Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: fsl: dpio: add Net DIM integration

Use the generic dynamic interrupt moderation (dim) framework to
implement adaptive interrupt coalescing on Rx. With the per-packet
interrupt scheme, a high interrupt rate has been noted for moderate
traffic flows leading to high CPU utilization.

The dpio driver exports new functions to enable/disable adaptive IRQ
coalescing on a DPIO object, to query the state or to update Net DIM
with a new set of bytes and frames dequeued.

Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ioana Ciornei and committed by
David S. Miller
69651bd8 a64b4421

+85 -1
+1
drivers/soc/fsl/Kconfig
··· 24 24 tristate "QorIQ DPAA2 DPIO driver" 25 25 depends on FSL_MC_BUS 26 26 select SOC_BUS 27 + select DIMLIB 27 28 help 28 29 Driver for the DPAA2 DPIO object. A DPIO provides queue and 29 30 buffer management facilities for software to interact with
+79
drivers/soc/fsl/dpio/dpio-service.c
··· 12 12 #include <linux/platform_device.h> 13 13 #include <linux/interrupt.h> 14 14 #include <linux/dma-mapping.h> 15 + #include <linux/dim.h> 15 16 #include <linux/slab.h> 16 17 17 18 #include "dpio.h" ··· 29 28 spinlock_t lock_notifications; 30 29 struct list_head notifications; 31 30 struct device *dev; 31 + 32 + /* Net DIM */ 33 + struct dim rx_dim; 34 + /* protect against concurrent Net DIM updates */ 35 + spinlock_t dim_lock; 36 + u16 event_ctr; 37 + u64 bytes; 38 + u64 frames; 32 39 }; 33 40 34 41 struct dpaa2_io_store { ··· 109 100 } 110 101 EXPORT_SYMBOL_GPL(dpaa2_io_service_select); 111 102 103 + static void dpaa2_io_dim_work(struct work_struct *w) 104 + { 105 + struct dim *dim = container_of(w, struct dim, work); 106 + struct dim_cq_moder moder = 107 + net_dim_get_rx_moderation(dim->mode, dim->profile_ix); 108 + struct dpaa2_io *d = container_of(dim, struct dpaa2_io, rx_dim); 109 + 110 + dpaa2_io_set_irq_coalescing(d, moder.usec); 111 + dim->state = DIM_START_MEASURE; 112 + } 113 + 112 114 /** 113 115 * dpaa2_io_create() - create a dpaa2_io object. 114 116 * @desc: the dpaa2_io descriptor ··· 167 147 INIT_LIST_HEAD(&obj->node); 168 148 spin_lock_init(&obj->lock_mgmt_cmd); 169 149 spin_lock_init(&obj->lock_notifications); 150 + spin_lock_init(&obj->dim_lock); 170 151 INIT_LIST_HEAD(&obj->notifications); 171 152 172 153 /* For now only enable DQRR interrupts */ ··· 184 163 spin_unlock(&dpio_list_lock); 185 164 186 165 obj->dev = dev; 166 + 167 + memset(&obj->rx_dim, 0, sizeof(obj->rx_dim)); 168 + INIT_WORK(&obj->rx_dim.work, dpaa2_io_dim_work); 169 + obj->event_ctr = 0; 170 + obj->bytes = 0; 171 + obj->frames = 0; 187 172 188 173 return obj; 189 174 } ··· 229 202 int max = 0; 230 203 struct qbman_swp *swp; 231 204 u32 status; 205 + 206 + obj->event_ctr++; 232 207 233 208 swp = obj->swp; 234 209 status = qbman_swp_interrupt_read_status(swp); ··· 846 817 qbman_swp_get_irq_coalescing(swp, NULL, irq_holdoff); 847 818 } 848 819 EXPORT_SYMBOL(dpaa2_io_get_irq_coalescing); 820 + 821 + /** 822 + * dpaa2_io_set_adaptive_coalescing() - Enable/disable adaptive coalescing 823 + * @d: the given DPIO object 824 + * @use_adaptive_rx_coalesce: adaptive coalescing state 825 + */ 826 + void dpaa2_io_set_adaptive_coalescing(struct dpaa2_io *d, 827 + int use_adaptive_rx_coalesce) 828 + { 829 + d->swp->use_adaptive_rx_coalesce = use_adaptive_rx_coalesce; 830 + } 831 + EXPORT_SYMBOL(dpaa2_io_set_adaptive_coalescing); 832 + 833 + /** 834 + * dpaa2_io_get_adaptive_coalescing() - Query adaptive coalescing state 835 + * @d: the given DPIO object 836 + * 837 + * Return 1 when adaptive coalescing is enabled on the DPIO object and 0 838 + * otherwise. 839 + */ 840 + int dpaa2_io_get_adaptive_coalescing(struct dpaa2_io *d) 841 + { 842 + return d->swp->use_adaptive_rx_coalesce; 843 + } 844 + EXPORT_SYMBOL(dpaa2_io_get_adaptive_coalescing); 845 + 846 + /** 847 + * dpaa2_io_update_net_dim() - Update Net DIM 848 + * @d: the given DPIO object 849 + * @frames: how many frames have been dequeued by the user since the last call 850 + * @bytes: how many bytes have been dequeued by the user since the last call 851 + */ 852 + void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes) 853 + { 854 + struct dim_sample dim_sample = {}; 855 + 856 + if (!d->swp->use_adaptive_rx_coalesce) 857 + return; 858 + 859 + spin_lock(&d->dim_lock); 860 + 861 + d->bytes += bytes; 862 + d->frames += frames; 863 + 864 + dim_update_sample(d->event_ctr, d->frames, d->bytes, &dim_sample); 865 + net_dim(&d->rx_dim, dim_sample); 866 + 867 + spin_unlock(&d->dim_lock); 868 + } 869 + EXPORT_SYMBOL(dpaa2_io_update_net_dim);
+1
drivers/soc/fsl/dpio/qbman-portal.h
··· 162 162 /* Interrupt coalescing */ 163 163 u32 irq_threshold; 164 164 u32 irq_holdoff; 165 + int use_adaptive_rx_coalesce; 165 166 }; 166 167 167 168 /* Function pointers */
+4 -1
include/soc/fsl/dpaa2-io.h
··· 134 134 135 135 int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff); 136 136 void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff); 137 - 137 + void dpaa2_io_set_adaptive_coalescing(struct dpaa2_io *d, 138 + int use_adaptive_rx_coalesce); 139 + int dpaa2_io_get_adaptive_coalescing(struct dpaa2_io *d); 140 + void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes); 138 141 #endif /* __FSL_DPAA2_IO_H */