Skip to content

Commit

Permalink
Merge branch 'net-generic-busy-polling'
Browse files Browse the repository at this point in the history
Eric Dumazet says:

====================
net: extend busy polling support

This patch series extends busy polling range to tunnels devices,
and adds busy polling generic support to all NAPI drivers.

No need to provide ndo_busy_poll() method and extra synchronization
between ndo_busy_poll() and normal napi->poll() method.
This was proven very difficult and bug prone.

mlx5 driver is changed to support busy polling using this new method,
and a second mlx5 patch adds napi_complete_done() support and proper
SNMP accounting.

bnx2x and mlx4 drivers are converted to new infrastructure,
reducing kernel bloat and improving performance.

Latest patch, adding generic support, adds a new requirement :

 -free_netdev() and netif_napi_del() must be called from process context.

Since this might not be the case in some drivers, we might have to
either : fix the non conformant drivers (by disabling busy polling on them)
or revert this last patch.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 18, 2015
2 parents d37b4c0 + 93d05d4 commit 85c72ba
Show file tree
Hide file tree
Showing 41 changed files with 171 additions and 507 deletions.
1 change: 0 additions & 1 deletion drivers/net/ethernet/amd/xgbe/xgbe-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,6 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
skb->dev = netdev;
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, channel->queue_index);
skb_mark_napi_id(skb, napi);

napi_gro_receive(napi, skb);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bcmsysport.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
/* Initialize SW view of the ring */
spin_lock_init(&ring->lock);
ring->priv = priv;
netif_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64);
netif_tx_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64);
ring->index = index;
ring->size = size;
ring->alloc_size = ring->size;
Expand Down
113 changes: 0 additions & 113 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,6 @@ struct bnx2x_fastpath {

struct napi_struct napi;

#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned long busy_poll_state;
#endif

union host_hc_status_block status_blk;
/* chip independent shortcuts into sb structure */
__le16 *sb_index_values;
Expand Down Expand Up @@ -617,115 +613,6 @@ struct bnx2x_fastpath {
#define bnx2x_fp_stats(bp, fp) (&((bp)->fp_stats[(fp)->index]))
#define bnx2x_fp_qstats(bp, fp) (&((bp)->fp_stats[(fp)->index].eth_q_stats))

#ifdef CONFIG_NET_RX_BUSY_POLL

enum bnx2x_fp_state {
BNX2X_STATE_FP_NAPI = BIT(0), /* NAPI handler owns the queue */

BNX2X_STATE_FP_NAPI_REQ_BIT = 1, /* NAPI would like to own the queue */
BNX2X_STATE_FP_NAPI_REQ = BIT(1),

BNX2X_STATE_FP_POLL_BIT = 2,
BNX2X_STATE_FP_POLL = BIT(2), /* busy_poll owns the queue */

BNX2X_STATE_FP_DISABLE_BIT = 3, /* queue is dismantled */
};

static inline void bnx2x_fp_busy_poll_init(struct bnx2x_fastpath *fp)
{
WRITE_ONCE(fp->busy_poll_state, 0);
}

/* called from the device poll routine to get ownership of a FP */
static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
{
unsigned long prev, old = READ_ONCE(fp->busy_poll_state);

while (1) {
switch (old) {
case BNX2X_STATE_FP_POLL:
/* make sure bnx2x_fp_lock_poll() wont starve us */
set_bit(BNX2X_STATE_FP_NAPI_REQ_BIT,
&fp->busy_poll_state);
/* fallthrough */
case BNX2X_STATE_FP_POLL | BNX2X_STATE_FP_NAPI_REQ:
return false;
default:
break;
}
prev = cmpxchg(&fp->busy_poll_state, old, BNX2X_STATE_FP_NAPI);
if (unlikely(prev != old)) {
old = prev;
continue;
}
return true;
}
}

static inline void bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
{
smp_wmb();
fp->busy_poll_state = 0;
}

/* called from bnx2x_low_latency_poll() */
static inline bool bnx2x_fp_lock_poll(struct bnx2x_fastpath *fp)
{
return cmpxchg(&fp->busy_poll_state, 0, BNX2X_STATE_FP_POLL) == 0;
}

static inline void bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
{
smp_mb__before_atomic();
clear_bit(BNX2X_STATE_FP_POLL_BIT, &fp->busy_poll_state);
}

/* true if a socket is polling */
static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
{
return READ_ONCE(fp->busy_poll_state) & BNX2X_STATE_FP_POLL;
}

/* false if fp is currently owned */
static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
{
set_bit(BNX2X_STATE_FP_DISABLE_BIT, &fp->busy_poll_state);
return !bnx2x_fp_ll_polling(fp);

}
#else
static inline void bnx2x_fp_busy_poll_init(struct bnx2x_fastpath *fp)
{
}

static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
{
return true;
}

static inline void bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
{
}

static inline bool bnx2x_fp_lock_poll(struct bnx2x_fastpath *fp)
{
return false;
}

static inline void bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
{
}

static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
{
return false;
}
static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
{
return true;
}
#endif /* CONFIG_NET_RX_BUSY_POLL */

/* Use 2500 as a mini-jumbo MTU for FCoE */
#define BNX2X_FCOE_MINI_JUMBO_MTU 2500

Expand Down
50 changes: 2 additions & 48 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ static void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
for_each_rx_queue_cnic(bp, i) {
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, NAPI_POLL_WEIGHT);
napi_hash_add(&bnx2x_fp(bp, i, napi));
}
}

Expand All @@ -58,7 +57,6 @@ static void bnx2x_add_all_napi(struct bnx2x *bp)
for_each_eth_queue(bp, i) {
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, NAPI_POLL_WEIGHT);
napi_hash_add(&bnx2x_fp(bp, i, napi));
}
}

Expand Down Expand Up @@ -1094,12 +1092,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
le16_to_cpu(cqe_fp->vlan_tag));

skb_mark_napi_id(skb, &fp->napi);

if (bnx2x_fp_ll_polling(fp))
netif_receive_skb(skb);
else
napi_gro_receive(&fp->napi, skb);
napi_gro_receive(&fp->napi, skb);
next_rx:
rx_buf->data = NULL;

Expand Down Expand Up @@ -1869,7 +1862,6 @@ static void bnx2x_napi_enable_cnic(struct bnx2x *bp)
int i;

for_each_rx_queue_cnic(bp, i) {
bnx2x_fp_busy_poll_init(&bp->fp[i]);
napi_enable(&bnx2x_fp(bp, i, napi));
}
}
Expand All @@ -1879,7 +1871,6 @@ static void bnx2x_napi_enable(struct bnx2x *bp)
int i;

for_each_eth_queue(bp, i) {
bnx2x_fp_busy_poll_init(&bp->fp[i]);
napi_enable(&bnx2x_fp(bp, i, napi));
}
}
Expand All @@ -1890,8 +1881,6 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp)

for_each_rx_queue_cnic(bp, i) {
napi_disable(&bnx2x_fp(bp, i, napi));
while (!bnx2x_fp_ll_disable(&bp->fp[i]))
usleep_range(1000, 2000);
}
}

Expand All @@ -1901,8 +1890,6 @@ static void bnx2x_napi_disable(struct bnx2x *bp)

for_each_eth_queue(bp, i) {
napi_disable(&bnx2x_fp(bp, i, napi));
while (!bnx2x_fp_ll_disable(&bp->fp[i]))
usleep_range(1000, 2000);
}
}

Expand Down Expand Up @@ -3232,9 +3219,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
return 0;
}
#endif
if (!bnx2x_fp_lock_napi(fp))
return budget;

for_each_cos_in_tx_queue(fp, cos)
if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos]))
bnx2x_tx_int(bp, fp->txdata_ptr[cos]);
Expand All @@ -3243,14 +3227,10 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
work_done += bnx2x_rx_int(fp, budget - work_done);

/* must not complete if we consumed full budget */
if (work_done >= budget) {
bnx2x_fp_unlock_napi(fp);
if (work_done >= budget)
break;
}
}

bnx2x_fp_unlock_napi(fp);

/* Fall out from the NAPI loop if needed */
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {

Expand Down Expand Up @@ -3294,32 +3274,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
return work_done;
}

#ifdef CONFIG_NET_RX_BUSY_POLL
/* must be called with local_bh_disable()d */
int bnx2x_low_latency_recv(struct napi_struct *napi)
{
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
napi);
struct bnx2x *bp = fp->bp;
int found = 0;

if ((bp->state == BNX2X_STATE_CLOSED) ||
(bp->state == BNX2X_STATE_ERROR) ||
(bp->dev->features & (NETIF_F_LRO | NETIF_F_GRO)))
return LL_FLUSH_FAILED;

if (!bnx2x_fp_lock_poll(fp))
return LL_FLUSH_BUSY;

if (bnx2x_has_rx_work(fp))
found = bnx2x_rx_int(fp, 4);

bnx2x_fp_unlock_poll(fp);

return found;
}
#endif

/* we split the first BD into headers and data BDs
* to ease the pain of our fellow microcode engineers
* we use one mapping for both BDs
Expand Down
7 changes: 0 additions & 7 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,13 +569,6 @@ int bnx2x_enable_msix(struct bnx2x *bp);
*/
int bnx2x_enable_msi(struct bnx2x *bp);

/**
* bnx2x_low_latency_recv - LL callback
*
* @napi: napi structure
*/
int bnx2x_low_latency_recv(struct napi_struct *napi);

/**
* bnx2x_alloc_mem_bp - allocate memories outsize main driver structure
*
Expand Down
3 changes: 0 additions & 3 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13004,9 +13004,6 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn,
#endif

#ifdef CONFIG_NET_RX_BUSY_POLL
.ndo_busy_poll = bnx2x_low_latency_recv,
#endif
.ndo_get_phys_port_id = bnx2x_get_phys_port_id,
.ndo_set_vf_link_state = bnx2x_set_vf_link_state,
.ndo_features_check = bnx2x_features_check,
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4227,12 +4227,10 @@ static void bnxt_init_napi(struct bnxt *bp)
bnapi = bp->bnapi[i];
netif_napi_add(bp->dev, &bnapi->napi,
bnxt_poll, 64);
napi_hash_add(&bnapi->napi);
}
} else {
bnapi = bp->bnapi[0];
netif_napi_add(bp->dev, &bnapi->napi, bnxt_poll, 64);
napi_hash_add(&bnapi->napi);
}
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/broadcom/genet/bcmgenet.c
Original file line number Diff line number Diff line change
Expand Up @@ -2041,11 +2041,11 @@ static void bcmgenet_init_tx_napi(struct bcmgenet_priv *priv)

for (i = 0; i < priv->hw_params->tx_queues; ++i) {
ring = &priv->tx_rings[i];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
netif_tx_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
}

ring = &priv->tx_rings[DESC_INDEX];
netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
netif_tx_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64);
}

static void bcmgenet_enable_tx_napi(struct bcmgenet_priv *priv)
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/chelsio/cxgb4/sge.c
Original file line number Diff line number Diff line change
Expand Up @@ -1864,7 +1864,6 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
skb->truesize += skb->data_len;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(skb, rxq->rspq.idx);
skb_mark_napi_id(skb, &rxq->rspq.napi);
pi = netdev_priv(skb->dev);
if (pi->rxtstamp)
cxgb4_sgetim_to_hwtstamp(adapter, skb_hwtstamps(skb),
Expand Down Expand Up @@ -2528,7 +2527,6 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
goto err;

netif_napi_add(dev, &iq->napi, napi_rx_handler, 64);
napi_hash_add(&iq->napi);
iq->cur_desc = iq->desc;
iq->cidx = 0;
iq->gen = 1;
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/cisco/enic/enic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2458,13 +2458,11 @@ static int enic_dev_init(struct enic *enic)
switch (vnic_dev_get_intr_mode(enic->vdev)) {
default:
netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
napi_hash_add(&enic->napi[0]);
break;
case VNIC_DEV_INTR_MODE_MSIX:
for (i = 0; i < enic->rq_count; i++) {
netif_napi_add(netdev, &enic->napi[i],
enic_poll_msix_rq, NAPI_POLL_WEIGHT);
napi_hash_add(&enic->napi[i]);
}
for (i = 0; i < enic->wq_count; i++)
netif_napi_add(netdev, &enic->napi[enic_cq_wq(enic, i)],
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2184,7 +2184,6 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);

skb->csum_level = rxcp->tunneled;
skb_mark_napi_id(skb, napi);

if (rxcp->vlanf)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rxcp->vlan_tag);
Expand Down Expand Up @@ -2631,7 +2630,6 @@ static int be_evt_queues_create(struct be_adapter *adapter)
eqo->affinity_mask);
netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
BE_NAPI_WEIGHT);
napi_hash_add(&eqo->napi);
}
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
ndev->netdev_ops = &fs_enet_netdev_ops;
ndev->watchdog_timeo = 2 * HZ;
netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight);
netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2);
netif_tx_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2);

ndev->ethtool_ops = &fs_ethtool_ops;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/freescale/gianfar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1347,12 +1347,12 @@ static int gfar_probe(struct platform_device *ofdev)
if (priv->poll_mode == GFAR_SQ_POLLING) {
netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
gfar_poll_rx_sq, GFAR_DEV_WEIGHT);
netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
netif_tx_napi_add(dev, &priv->gfargrp[i].napi_tx,
gfar_poll_tx_sq, 2);
} else {
netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
gfar_poll_rx, GFAR_DEV_WEIGHT);
netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
netif_tx_napi_add(dev, &priv->gfargrp[i].napi_tx,
gfar_poll_tx, 2);
}
}
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,6 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
continue;
}
#endif
skb_mark_napi_id(skb, &rx_ring->q_vector->napi);
i40e_receive_skb(rx_ring, skb, vlan_tag);

rx_desc->wb.qword1.status_error_len = 0;
Expand Down
Loading

0 comments on commit 85c72ba

Please sign in to comment.