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>
This commit is contained in:
Родитель
a64b442137
Коммит
69651bd8d3
|
@ -24,6 +24,7 @@ config FSL_MC_DPIO
|
|||
tristate "QorIQ DPAA2 DPIO driver"
|
||||
depends on FSL_MC_BUS
|
||||
select SOC_BUS
|
||||
select DIMLIB
|
||||
help
|
||||
Driver for the DPAA2 DPIO object. A DPIO provides queue and
|
||||
buffer management facilities for software to interact with
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dim.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "dpio.h"
|
||||
|
@ -28,6 +29,14 @@ struct dpaa2_io {
|
|||
spinlock_t lock_notifications;
|
||||
struct list_head notifications;
|
||||
struct device *dev;
|
||||
|
||||
/* Net DIM */
|
||||
struct dim rx_dim;
|
||||
/* protect against concurrent Net DIM updates */
|
||||
spinlock_t dim_lock;
|
||||
u16 event_ctr;
|
||||
u64 bytes;
|
||||
u64 frames;
|
||||
};
|
||||
|
||||
struct dpaa2_io_store {
|
||||
|
@ -100,6 +109,17 @@ struct dpaa2_io *dpaa2_io_service_select(int cpu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dpaa2_io_service_select);
|
||||
|
||||
static void dpaa2_io_dim_work(struct work_struct *w)
|
||||
{
|
||||
struct dim *dim = container_of(w, struct dim, work);
|
||||
struct dim_cq_moder moder =
|
||||
net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
|
||||
struct dpaa2_io *d = container_of(dim, struct dpaa2_io, rx_dim);
|
||||
|
||||
dpaa2_io_set_irq_coalescing(d, moder.usec);
|
||||
dim->state = DIM_START_MEASURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* dpaa2_io_create() - create a dpaa2_io object.
|
||||
* @desc: the dpaa2_io descriptor
|
||||
|
@ -147,6 +167,7 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
|
|||
INIT_LIST_HEAD(&obj->node);
|
||||
spin_lock_init(&obj->lock_mgmt_cmd);
|
||||
spin_lock_init(&obj->lock_notifications);
|
||||
spin_lock_init(&obj->dim_lock);
|
||||
INIT_LIST_HEAD(&obj->notifications);
|
||||
|
||||
/* For now only enable DQRR interrupts */
|
||||
|
@ -164,6 +185,12 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
|
|||
|
||||
obj->dev = dev;
|
||||
|
||||
memset(&obj->rx_dim, 0, sizeof(obj->rx_dim));
|
||||
INIT_WORK(&obj->rx_dim.work, dpaa2_io_dim_work);
|
||||
obj->event_ctr = 0;
|
||||
obj->bytes = 0;
|
||||
obj->frames = 0;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -203,6 +230,8 @@ irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj)
|
|||
struct qbman_swp *swp;
|
||||
u32 status;
|
||||
|
||||
obj->event_ctr++;
|
||||
|
||||
swp = obj->swp;
|
||||
status = qbman_swp_interrupt_read_status(swp);
|
||||
if (!status)
|
||||
|
@ -817,3 +846,53 @@ void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff)
|
|||
qbman_swp_get_irq_coalescing(swp, NULL, irq_holdoff);
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_get_irq_coalescing);
|
||||
|
||||
/**
|
||||
* dpaa2_io_set_adaptive_coalescing() - Enable/disable adaptive coalescing
|
||||
* @d: the given DPIO object
|
||||
* @use_adaptive_rx_coalesce: adaptive coalescing state
|
||||
*/
|
||||
void dpaa2_io_set_adaptive_coalescing(struct dpaa2_io *d,
|
||||
int use_adaptive_rx_coalesce)
|
||||
{
|
||||
d->swp->use_adaptive_rx_coalesce = use_adaptive_rx_coalesce;
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_set_adaptive_coalescing);
|
||||
|
||||
/**
|
||||
* dpaa2_io_get_adaptive_coalescing() - Query adaptive coalescing state
|
||||
* @d: the given DPIO object
|
||||
*
|
||||
* Return 1 when adaptive coalescing is enabled on the DPIO object and 0
|
||||
* otherwise.
|
||||
*/
|
||||
int dpaa2_io_get_adaptive_coalescing(struct dpaa2_io *d)
|
||||
{
|
||||
return d->swp->use_adaptive_rx_coalesce;
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_get_adaptive_coalescing);
|
||||
|
||||
/**
|
||||
* dpaa2_io_update_net_dim() - Update Net DIM
|
||||
* @d: the given DPIO object
|
||||
* @frames: how many frames have been dequeued by the user since the last call
|
||||
* @bytes: how many bytes have been dequeued by the user since the last call
|
||||
*/
|
||||
void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes)
|
||||
{
|
||||
struct dim_sample dim_sample = {};
|
||||
|
||||
if (!d->swp->use_adaptive_rx_coalesce)
|
||||
return;
|
||||
|
||||
spin_lock(&d->dim_lock);
|
||||
|
||||
d->bytes += bytes;
|
||||
d->frames += frames;
|
||||
|
||||
dim_update_sample(d->event_ctr, d->frames, d->bytes, &dim_sample);
|
||||
net_dim(&d->rx_dim, dim_sample);
|
||||
|
||||
spin_unlock(&d->dim_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_update_net_dim);
|
||||
|
|
|
@ -162,6 +162,7 @@ struct qbman_swp {
|
|||
/* Interrupt coalescing */
|
||||
u32 irq_threshold;
|
||||
u32 irq_holdoff;
|
||||
int use_adaptive_rx_coalesce;
|
||||
};
|
||||
|
||||
/* Function pointers */
|
||||
|
|
|
@ -134,5 +134,8 @@ int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid,
|
|||
|
||||
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff);
|
||||
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff);
|
||||
|
||||
void dpaa2_io_set_adaptive_coalescing(struct dpaa2_io *d,
|
||||
int use_adaptive_rx_coalesce);
|
||||
int dpaa2_io_get_adaptive_coalescing(struct dpaa2_io *d);
|
||||
void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes);
|
||||
#endif /* __FSL_DPAA2_IO_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче