Skip to content

Commit

Permalink
soc: fsl: dpio: add Net DIM integration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
IoanaCiornei authored and davem330 committed Oct 15, 2021
1 parent a64b442 commit 69651bd
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/soc/fsl/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
79 changes: 79 additions & 0 deletions drivers/soc/fsl/dpio/dpio-service.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
1 change: 1 addition & 0 deletions drivers/soc/fsl/dpio/qbman-portal.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ struct qbman_swp {
/* Interrupt coalescing */
u32 irq_threshold;
u32 irq_holdoff;
int use_adaptive_rx_coalesce;
};

/* Function pointers */
Expand Down
5 changes: 4 additions & 1 deletion include/soc/fsl/dpaa2-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit 69651bd

Please sign in to comment.