Skip to content

Commit 295711f

Browse files
committed
Merge branch 'dpaa2-irq-coalescing'
Ioana Ciornei says: ==================== dpaa2-eth: add support for IRQ coalescing This patch set adds support for interrupts coalescing in dpaa2-eth. The first patches add support for the hardware level configuration of the IRQ coalescing in the dpio driver, while the ones that touch the dpaa2-eth driver are responsible for the ethtool user interraction. With the adaptive IRQ coalescing in place and enabled we have observed the following changes in interrupt rates on one A72 core @2.2GHz (LX2160A) while running a Rx TCP flow. The TCP stream is sent on a 10Gbit link and the only cpu that does Rx is fully utilized. IRQ rate (irqs / sec) before: 4.59 Gbits/sec 24k after: 5.67 Gbits/sec 1.3k ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents f3fafbc + fc398be commit 295711f

File tree

12 files changed

+276
-1
lines changed

12 files changed

+276
-1
lines changed

drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
533533

534534
percpu_stats->rx_packets++;
535535
percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
536+
ch->stats.bytes_per_cdan += dpaa2_fd_get_len(fd);
536537

537538
list_add_tail(&skb->list, ch->rx_list);
538539

@@ -641,6 +642,7 @@ static int dpaa2_eth_consume_frames(struct dpaa2_eth_channel *ch,
641642

642643
fq->stats.frames += cleaned;
643644
ch->stats.frames += cleaned;
645+
ch->stats.frames_per_cdan += cleaned;
644646

645647
/* A dequeue operation only pulls frames from a single queue
646648
* into the store. Return the frame queue as an out param.
@@ -1264,7 +1266,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
12641266

12651267
/* Tx confirmation frame processing routine */
12661268
static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
1267-
struct dpaa2_eth_channel *ch __always_unused,
1269+
struct dpaa2_eth_channel *ch,
12681270
const struct dpaa2_fd *fd,
12691271
struct dpaa2_eth_fq *fq)
12701272
{
@@ -1279,6 +1281,7 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
12791281
percpu_extras = this_cpu_ptr(priv->percpu_extras);
12801282
percpu_extras->tx_conf_frames++;
12811283
percpu_extras->tx_conf_bytes += fd_len;
1284+
ch->stats.bytes_per_cdan += fd_len;
12821285

12831286
/* Check frame errors in the FD field */
12841287
fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
@@ -1601,6 +1604,12 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
16011604
}
16021605
} while (store_cleaned);
16031606

1607+
/* Update NET DIM with the values for this CDAN */
1608+
dpaa2_io_update_net_dim(ch->dpio, ch->stats.frames_per_cdan,
1609+
ch->stats.bytes_per_cdan);
1610+
ch->stats.frames_per_cdan = 0;
1611+
ch->stats.bytes_per_cdan = 0;
1612+
16041613
/* We didn't consume the entire budget, so finish napi and
16051614
* re-enable data availability notifications
16061615
*/

drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,8 @@ struct dpaa2_eth_ch_stats {
384384
__u64 xdp_redirect;
385385
/* Must be last, does not show up in ethtool stats */
386386
__u64 frames;
387+
__u64 frames_per_cdan;
388+
__u64 bytes_per_cdan;
387389
};
388390

389391
/* Maximum number of queues associated with a DPNI */

drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,63 @@ static int dpaa2_eth_set_tunable(struct net_device *net_dev,
820820
return err;
821821
}
822822

823+
static int dpaa2_eth_get_coalesce(struct net_device *dev,
824+
struct ethtool_coalesce *ic,
825+
struct kernel_ethtool_coalesce *kernel_coal,
826+
struct netlink_ext_ack *extack)
827+
{
828+
struct dpaa2_eth_priv *priv = netdev_priv(dev);
829+
struct dpaa2_io *dpio = priv->channel[0]->dpio;
830+
831+
dpaa2_io_get_irq_coalescing(dpio, &ic->rx_coalesce_usecs);
832+
ic->use_adaptive_rx_coalesce = dpaa2_io_get_adaptive_coalescing(dpio);
833+
834+
return 0;
835+
}
836+
837+
static int dpaa2_eth_set_coalesce(struct net_device *dev,
838+
struct ethtool_coalesce *ic,
839+
struct kernel_ethtool_coalesce *kernel_coal,
840+
struct netlink_ext_ack *extack)
841+
{
842+
struct dpaa2_eth_priv *priv = netdev_priv(dev);
843+
struct dpaa2_io *dpio;
844+
int prev_adaptive;
845+
u32 prev_rx_usecs;
846+
int i, j, err;
847+
848+
/* Keep track of the previous value, just in case we fail */
849+
dpio = priv->channel[0]->dpio;
850+
dpaa2_io_get_irq_coalescing(dpio, &prev_rx_usecs);
851+
prev_adaptive = dpaa2_io_get_adaptive_coalescing(dpio);
852+
853+
/* Setup new value for rx coalescing */
854+
for (i = 0; i < priv->num_channels; i++) {
855+
dpio = priv->channel[i]->dpio;
856+
857+
dpaa2_io_set_adaptive_coalescing(dpio,
858+
ic->use_adaptive_rx_coalesce);
859+
err = dpaa2_io_set_irq_coalescing(dpio, ic->rx_coalesce_usecs);
860+
if (err)
861+
goto restore_rx_usecs;
862+
}
863+
864+
return 0;
865+
866+
restore_rx_usecs:
867+
for (j = 0; j < i; j++) {
868+
dpio = priv->channel[j]->dpio;
869+
870+
dpaa2_io_set_irq_coalescing(dpio, prev_rx_usecs);
871+
dpaa2_io_set_adaptive_coalescing(dpio, prev_adaptive);
872+
}
873+
874+
return err;
875+
}
876+
823877
const struct ethtool_ops dpaa2_ethtool_ops = {
878+
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
879+
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
824880
.get_drvinfo = dpaa2_eth_get_drvinfo,
825881
.nway_reset = dpaa2_eth_nway_reset,
826882
.get_link = ethtool_op_get_link,
@@ -836,4 +892,6 @@ const struct ethtool_ops dpaa2_ethtool_ops = {
836892
.get_ts_info = dpaa2_eth_get_ts_info,
837893
.get_tunable = dpaa2_eth_get_tunable,
838894
.set_tunable = dpaa2_eth_set_tunable,
895+
.get_coalesce = dpaa2_eth_get_coalesce,
896+
.set_coalesce = dpaa2_eth_set_coalesce,
839897
};

drivers/soc/fsl/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ config FSL_MC_DPIO
2424
tristate "QorIQ DPAA2 DPIO driver"
2525
depends on FSL_MC_BUS
2626
select SOC_BUS
27+
select DIMLIB
2728
help
2829
Driver for the DPAA2 DPIO object. A DPIO provides queue and
2930
buffer management facilities for software to interact with

drivers/soc/fsl/dpio/dpio-cmd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct dpio_rsp_get_attr {
4646
__le64 qbman_portal_ci_addr;
4747
/* cmd word 3 */
4848
__le32 qbman_version;
49+
__le32 pad1;
50+
/* cmd word 4 */
51+
__le32 clk;
4952
};
5053

5154
struct dpio_stashing_dest {

drivers/soc/fsl/dpio/dpio-driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
162162
goto err_get_attr;
163163
}
164164
desc.qman_version = dpio_attrs.qbman_version;
165+
desc.qman_clk = dpio_attrs.clk;
165166

166167
err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
167168
if (err) {

drivers/soc/fsl/dpio/dpio-service.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/platform_device.h>
1313
#include <linux/interrupt.h>
1414
#include <linux/dma-mapping.h>
15+
#include <linux/dim.h>
1516
#include <linux/slab.h>
1617

1718
#include "dpio.h"
@@ -28,6 +29,14 @@ struct dpaa2_io {
2829
spinlock_t lock_notifications;
2930
struct list_head notifications;
3031
struct device *dev;
32+
33+
/* Net DIM */
34+
struct dim rx_dim;
35+
/* protect against concurrent Net DIM updates */
36+
spinlock_t dim_lock;
37+
u16 event_ctr;
38+
u64 bytes;
39+
u64 frames;
3140
};
3241

3342
struct dpaa2_io_store {
@@ -100,6 +109,17 @@ struct dpaa2_io *dpaa2_io_service_select(int cpu)
100109
}
101110
EXPORT_SYMBOL_GPL(dpaa2_io_service_select);
102111

112+
static void dpaa2_io_dim_work(struct work_struct *w)
113+
{
114+
struct dim *dim = container_of(w, struct dim, work);
115+
struct dim_cq_moder moder =
116+
net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
117+
struct dpaa2_io *d = container_of(dim, struct dpaa2_io, rx_dim);
118+
119+
dpaa2_io_set_irq_coalescing(d, moder.usec);
120+
dim->state = DIM_START_MEASURE;
121+
}
122+
103123
/**
104124
* dpaa2_io_create() - create a dpaa2_io object.
105125
* @desc: the dpaa2_io descriptor
@@ -114,6 +134,7 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
114134
struct device *dev)
115135
{
116136
struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
137+
u32 qman_256_cycles_per_ns;
117138

118139
if (!obj)
119140
return NULL;
@@ -127,7 +148,15 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
127148
obj->dpio_desc = *desc;
128149
obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena;
129150
obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
151+
obj->swp_desc.qman_clk = obj->dpio_desc.qman_clk;
130152
obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
153+
154+
/* Compute how many 256 QBMAN cycles fit into one ns. This is because
155+
* the interrupt timeout period register needs to be specified in QBMAN
156+
* clock cycles in increments of 256.
157+
*/
158+
qman_256_cycles_per_ns = 256000 / (obj->swp_desc.qman_clk / 1000000);
159+
obj->swp_desc.qman_256_cycles_per_ns = qman_256_cycles_per_ns;
131160
obj->swp = qbman_swp_init(&obj->swp_desc);
132161

133162
if (!obj->swp) {
@@ -138,6 +167,7 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
138167
INIT_LIST_HEAD(&obj->node);
139168
spin_lock_init(&obj->lock_mgmt_cmd);
140169
spin_lock_init(&obj->lock_notifications);
170+
spin_lock_init(&obj->dim_lock);
141171
INIT_LIST_HEAD(&obj->notifications);
142172

143173
/* For now only enable DQRR interrupts */
@@ -155,6 +185,12 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
155185

156186
obj->dev = dev;
157187

188+
memset(&obj->rx_dim, 0, sizeof(obj->rx_dim));
189+
INIT_WORK(&obj->rx_dim.work, dpaa2_io_dim_work);
190+
obj->event_ctr = 0;
191+
obj->bytes = 0;
192+
obj->frames = 0;
193+
158194
return obj;
159195
}
160196

@@ -194,6 +230,8 @@ irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj)
194230
struct qbman_swp *swp;
195231
u32 status;
196232

233+
obj->event_ctr++;
234+
197235
swp = obj->swp;
198236
status = qbman_swp_interrupt_read_status(swp);
199237
if (!status)
@@ -779,3 +817,82 @@ int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, u32 *num)
779817
return 0;
780818
}
781819
EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count);
820+
821+
/**
822+
* dpaa2_io_set_irq_coalescing() - Set new IRQ coalescing values
823+
* @d: the given DPIO object
824+
* @irq_holdoff: interrupt holdoff (timeout) period in us
825+
*
826+
* Return 0 for success, or negative error code on error.
827+
*/
828+
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff)
829+
{
830+
struct qbman_swp *swp = d->swp;
831+
832+
return qbman_swp_set_irq_coalescing(swp, swp->dqrr.dqrr_size - 1,
833+
irq_holdoff);
834+
}
835+
EXPORT_SYMBOL(dpaa2_io_set_irq_coalescing);
836+
837+
/**
838+
* dpaa2_io_get_irq_coalescing() - Get the current IRQ coalescing parameters
839+
* @d: the given DPIO object
840+
* @irq_holdoff: interrupt holdoff (timeout) period in us
841+
*/
842+
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff)
843+
{
844+
struct qbman_swp *swp = d->swp;
845+
846+
qbman_swp_get_irq_coalescing(swp, NULL, irq_holdoff);
847+
}
848+
EXPORT_SYMBOL(dpaa2_io_get_irq_coalescing);
849+
850+
/**
851+
* dpaa2_io_set_adaptive_coalescing() - Enable/disable adaptive coalescing
852+
* @d: the given DPIO object
853+
* @use_adaptive_rx_coalesce: adaptive coalescing state
854+
*/
855+
void dpaa2_io_set_adaptive_coalescing(struct dpaa2_io *d,
856+
int use_adaptive_rx_coalesce)
857+
{
858+
d->swp->use_adaptive_rx_coalesce = use_adaptive_rx_coalesce;
859+
}
860+
EXPORT_SYMBOL(dpaa2_io_set_adaptive_coalescing);
861+
862+
/**
863+
* dpaa2_io_get_adaptive_coalescing() - Query adaptive coalescing state
864+
* @d: the given DPIO object
865+
*
866+
* Return 1 when adaptive coalescing is enabled on the DPIO object and 0
867+
* otherwise.
868+
*/
869+
int dpaa2_io_get_adaptive_coalescing(struct dpaa2_io *d)
870+
{
871+
return d->swp->use_adaptive_rx_coalesce;
872+
}
873+
EXPORT_SYMBOL(dpaa2_io_get_adaptive_coalescing);
874+
875+
/**
876+
* dpaa2_io_update_net_dim() - Update Net DIM
877+
* @d: the given DPIO object
878+
* @frames: how many frames have been dequeued by the user since the last call
879+
* @bytes: how many bytes have been dequeued by the user since the last call
880+
*/
881+
void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes)
882+
{
883+
struct dim_sample dim_sample = {};
884+
885+
if (!d->swp->use_adaptive_rx_coalesce)
886+
return;
887+
888+
spin_lock(&d->dim_lock);
889+
890+
d->bytes += bytes;
891+
d->frames += frames;
892+
893+
dim_update_sample(d->event_ctr, d->frames, d->bytes, &dim_sample);
894+
net_dim(&d->rx_dim, dim_sample);
895+
896+
spin_unlock(&d->dim_lock);
897+
}
898+
EXPORT_SYMBOL(dpaa2_io_update_net_dim);

drivers/soc/fsl/dpio/dpio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
162162
attr->qbman_portal_ci_offset =
163163
le64_to_cpu(dpio_rsp->qbman_portal_ci_addr);
164164
attr->qbman_version = le32_to_cpu(dpio_rsp->qbman_version);
165+
attr->clk = le32_to_cpu(dpio_rsp->clk);
165166

166167
return 0;
167168
}

drivers/soc/fsl/dpio/dpio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ int dpio_disable(struct fsl_mc_io *mc_io,
5959
* @num_priorities: Number of priorities for the notification channel (1-8);
6060
* relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL'
6161
* @qbman_version: QBMAN version
62+
* @clk: QBMAN clock frequency value in Hz
6263
*/
6364
struct dpio_attr {
6465
int id;
@@ -68,6 +69,7 @@ struct dpio_attr {
6869
enum dpio_channel_mode channel_mode;
6970
u8 num_priorities;
7071
u32 qbman_version;
72+
u32 clk;
7173
};
7274

7375
int dpio_get_attributes(struct fsl_mc_io *mc_io,

0 commit comments

Comments
 (0)