Skip to content

Commit 3421257

Browse files
Jiawen WuNipaLocal
authored andcommitted
net: wangxun: support to use adaptive RX coalescing
Support to turn on/off adaptive RX coalesce. When adaptive RX coalesce is on, use DIM algorithm for a dynamic interrupt moderation. Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com> Signed-off-by: NipaLocal <nipa@local>
1 parent e644504 commit 3421257

File tree

8 files changed

+119
-5
lines changed

8 files changed

+119
-5
lines changed

drivers/net/ethernet/wangxun/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ config LIBWX
2020
tristate
2121
depends on PTP_1588_CLOCK_OPTIONAL
2222
select PAGE_POOL
23+
select DIMLIB
2324
help
2425
Common library for Wangxun(R) Ethernet drivers.
2526

drivers/net/ethernet/wangxun/libwx/wx_ethtool.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ int wx_get_coalesce(struct net_device *netdev,
303303
else
304304
ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2;
305305

306+
if (wx->rx_itr_setting == 1)
307+
ec->use_adaptive_rx_coalesce = 1;
308+
306309
/* if in mixed tx/rx queues per vector mode, report only rx settings */
307310
if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
308311
return 0;
@@ -363,10 +366,15 @@ int wx_set_coalesce(struct net_device *netdev,
363366
(ec->tx_coalesce_usecs > (max_eitr >> 2)))
364367
return -EINVAL;
365368

369+
if (ec->use_adaptive_rx_coalesce) {
370+
wx->rx_itr_setting = 1;
371+
return 0;
372+
}
373+
366374
if (ec->rx_coalesce_usecs > 1)
367375
wx->rx_itr_setting = ec->rx_coalesce_usecs << 2;
368376
else
369-
wx->rx_itr_setting = ec->rx_coalesce_usecs;
377+
wx->rx_itr_setting = rx_itr_param;
370378

371379
if (wx->rx_itr_setting != 1)
372380
rx_itr_param = wx->rx_itr_setting;

drivers/net/ethernet/wangxun/libwx/wx_lib.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "wx_lib.h"
1717
#include "wx_ptp.h"
1818
#include "wx_hw.h"
19+
#include "wx_vf_lib.h"
1920

2021
/* Lookup table mapping the HW PTYPE to the bit field for decoding */
2122
static struct wx_dec_ptype wx_ptype_lookup[256] = {
@@ -832,6 +833,36 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector,
832833
return !!budget;
833834
}
834835

836+
static void wx_update_rx_dim_sample(struct wx_q_vector *q_vector)
837+
{
838+
struct dim_sample sample = {};
839+
840+
dim_update_sample(q_vector->total_events,
841+
q_vector->rx.total_packets,
842+
q_vector->rx.total_bytes,
843+
&sample);
844+
845+
net_dim(&q_vector->rx.dim, &sample);
846+
}
847+
848+
static void wx_update_tx_dim_sample(struct wx_q_vector *q_vector)
849+
{
850+
struct dim_sample sample = {};
851+
852+
dim_update_sample(q_vector->total_events,
853+
q_vector->tx.total_packets,
854+
q_vector->tx.total_bytes,
855+
&sample);
856+
857+
net_dim(&q_vector->tx.dim, &sample);
858+
}
859+
860+
static void wx_update_dim_sample(struct wx_q_vector *q_vector)
861+
{
862+
wx_update_rx_dim_sample(q_vector);
863+
wx_update_tx_dim_sample(q_vector);
864+
}
865+
835866
/**
836867
* wx_poll - NAPI polling RX/TX cleanup routine
837868
* @napi: napi struct with our devices info in it
@@ -878,6 +909,8 @@ static int wx_poll(struct napi_struct *napi, int budget)
878909

879910
/* all work done, exit the polling mode */
880911
if (likely(napi_complete_done(napi, work_done))) {
912+
if (wx->rx_itr_setting == 1)
913+
wx_update_dim_sample(q_vector);
881914
if (netif_running(wx->netdev))
882915
wx_intr_enable(wx, WX_INTR_Q(q_vector->v_idx));
883916
}
@@ -1591,13 +1624,74 @@ netdev_tx_t wx_xmit_frame(struct sk_buff *skb,
15911624
}
15921625
EXPORT_SYMBOL(wx_xmit_frame);
15931626

1627+
static void wx_set_itr(struct wx_q_vector *q_vector)
1628+
{
1629+
struct wx *wx = q_vector->wx;
1630+
u32 new_itr;
1631+
1632+
/* use the smallest value of new ITR delay calculations */
1633+
new_itr = min(q_vector->rx.itr, q_vector->tx.itr);
1634+
new_itr <<= 2;
1635+
1636+
if (new_itr != q_vector->itr) {
1637+
/* save the algorithm value here */
1638+
q_vector->itr = new_itr;
1639+
1640+
if (wx->pdev->is_virtfn)
1641+
wx_write_eitr_vf(q_vector);
1642+
else
1643+
wx_write_eitr(q_vector);
1644+
}
1645+
}
1646+
1647+
static void wx_rx_dim_work(struct work_struct *work)
1648+
{
1649+
struct dim *dim = container_of(work, struct dim, work);
1650+
struct dim_cq_moder rx_moder;
1651+
struct wx_ring_container *rx;
1652+
struct wx_q_vector *q_vector;
1653+
1654+
rx = container_of(dim, struct wx_ring_container, dim);
1655+
1656+
rx_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
1657+
rx->itr = rx_moder.usec;
1658+
1659+
q_vector = container_of(rx, struct wx_q_vector, rx);
1660+
wx_set_itr(q_vector);
1661+
1662+
dim->state = DIM_START_MEASURE;
1663+
}
1664+
1665+
static void wx_tx_dim_work(struct work_struct *work)
1666+
{
1667+
struct dim *dim = container_of(work, struct dim, work);
1668+
struct dim_cq_moder tx_moder;
1669+
struct wx_ring_container *tx;
1670+
struct wx_q_vector *q_vector;
1671+
1672+
tx = container_of(dim, struct wx_ring_container, dim);
1673+
1674+
tx_moder = net_dim_get_tx_moderation(dim->mode, dim->profile_ix);
1675+
tx->itr = tx_moder.usec;
1676+
1677+
q_vector = container_of(tx, struct wx_q_vector, tx);
1678+
wx_set_itr(q_vector);
1679+
1680+
dim->state = DIM_START_MEASURE;
1681+
}
1682+
15941683
void wx_napi_enable_all(struct wx *wx)
15951684
{
15961685
struct wx_q_vector *q_vector;
15971686
int q_idx;
15981687

15991688
for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) {
16001689
q_vector = wx->q_vector[q_idx];
1690+
1691+
INIT_WORK(&q_vector->rx.dim.work, wx_rx_dim_work);
1692+
INIT_WORK(&q_vector->tx.dim.work, wx_tx_dim_work);
1693+
q_vector->rx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
1694+
q_vector->tx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
16011695
napi_enable(&q_vector->napi);
16021696
}
16031697
}
@@ -1611,6 +1705,8 @@ void wx_napi_disable_all(struct wx *wx)
16111705
for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) {
16121706
q_vector = wx->q_vector[q_idx];
16131707
napi_disable(&q_vector->napi);
1708+
cancel_work_sync(&q_vector->rx.dim.work);
1709+
cancel_work_sync(&q_vector->tx.dim.work);
16141710
}
16151711
}
16161712
EXPORT_SYMBOL(wx_napi_disable_all);
@@ -2197,8 +2293,10 @@ irqreturn_t wx_msix_clean_rings(int __always_unused irq, void *data)
21972293
struct wx_q_vector *q_vector = data;
21982294

21992295
/* EIAM disabled interrupts (on this vector) for us */
2200-
if (q_vector->rx.ring || q_vector->tx.ring)
2296+
if (q_vector->rx.ring || q_vector->tx.ring) {
22012297
napi_schedule_irqoff(&q_vector->napi);
2298+
q_vector->total_events++;
2299+
}
22022300

22032301
return IRQ_HANDLED;
22042302
}

drivers/net/ethernet/wangxun/libwx/wx_type.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/netdevice.h>
1111
#include <linux/if_vlan.h>
1212
#include <linux/phylink.h>
13+
#include <linux/dim.h>
1314
#include <net/ip.h>
1415

1516
#define WX_NCSI_SUP 0x8000
@@ -1034,6 +1035,7 @@ struct wx_ring_container {
10341035
unsigned int total_packets; /* total packets processed this int */
10351036
u8 count; /* total number of rings in vector */
10361037
u8 itr; /* current ITR setting for ring */
1038+
struct dim dim; /* data for net_dim algorithm */
10371039
};
10381040
struct wx_ring {
10391041
struct wx_ring *next; /* pointer to next ring in q_vector */
@@ -1090,6 +1092,8 @@ struct wx_q_vector {
10901092
struct napi_struct napi;
10911093
struct rcu_head rcu; /* to avoid race with update stats on free */
10921094

1095+
u16 total_events; /* number of interrupts processed */
1096+
10931097
char name[IFNAMSIZ + 17];
10941098

10951099
/* for dynamic allocation of rings associated with this q_vector */

drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "wx_vf.h"
1111
#include "wx_vf_lib.h"
1212

13-
static void wx_write_eitr_vf(struct wx_q_vector *q_vector)
13+
void wx_write_eitr_vf(struct wx_q_vector *q_vector)
1414
{
1515
struct wx *wx = q_vector->wx;
1616
int v_idx = q_vector->v_idx;

drivers/net/ethernet/wangxun/libwx/wx_vf_lib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef _WX_VF_LIB_H_
55
#define _WX_VF_LIB_H_
66

7+
void wx_write_eitr_vf(struct wx_q_vector *q_vector);
78
void wx_configure_msix_vf(struct wx *wx);
89
int wx_write_uc_addr_list_vf(struct net_device *netdev);
910
void wx_setup_psrtype_vf(struct wx *wx);

drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ static int ngbe_set_channels(struct net_device *dev,
115115

116116
static const struct ethtool_ops ngbe_ethtool_ops = {
117117
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
118-
ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
118+
ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
119+
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
119120
.get_drvinfo = wx_get_drvinfo,
120121
.get_link = ethtool_op_get_link,
121122
.get_link_ksettings = wx_get_link_ksettings,

drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,8 @@ static int txgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
538538

539539
static const struct ethtool_ops txgbe_ethtool_ops = {
540540
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
541-
ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
541+
ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
542+
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
542543
.get_drvinfo = wx_get_drvinfo,
543544
.nway_reset = wx_nway_reset,
544545
.get_link = ethtool_op_get_link,

0 commit comments

Comments
 (0)