sfc: Add support for busy polling
Subsystems (3)
PATCH 1/1 sfc: Add support for busy polling
From: Alexandre Rames <[email protected]>
This patch adds the sfc driver code for implementing busy polling. It adds ndo_busy_poll method and locking between it and napi poll. It also adds each napi to the napi_hash right after netif_napi_add().
Uses efx_start_eventq and efx_stop_eventq in the self tests.
--- drivers/net/ethernet/sfc/efx.c | 54 ++++++++++++- drivers/net/ethernet/sfc/efx.h | 2 + drivers/net/ethernet/sfc/net_driver.h | 148 ++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/rx.c | 6 +- drivers/net/ethernet/sfc/selftest.c | 5 +- 5 files changed, 208 insertions(+), 7 deletions(-)
drivers/net/ethernet/sfc/efx.c +51 -3
@@ -272,6 +272,9 @@ static int efx_poll(struct napi_struct *napi, int budget)struct efx_nic *efx = channel->efx;int spent; +if (!efx_channel_lock_napi (channel)) +return budget; +netif_vdbg (efx, intr, efx->net_dev,"channel %d NAPI poll executing on CPU %d\n" , channel->channel,raw_smp_processor_id ());
@@ -311,6 +314,7 @@ static int efx_poll(struct napi_struct *napi, int budget)efx_nic_eventq_read_ack (channel); } +efx_channel_unlock_napi (channel);return spent; }
@@ -357,7 +361,7 @@ static int efx_init_eventq(struct efx_channel *channel) }/* Enable event queue processing and NAPI */ -static void efx_start_eventq (struct efx_channel *channel) +void efx_start_eventq (struct efx_channel *channel) {netif_dbg (channel->efx, ifup, channel->efx->net_dev,"chan %d start event queue\n" , channel->channel);
@@ -366,17 +370,20 @@ static void efx_start_eventq(struct efx_channel *channel) channel->enabled = true;smp_wmb (); +efx_channel_enable (channel);napi_enable (&channel->napi_str);efx_nic_eventq_read_ack (channel); }/* Disable event queue processing and NAPI */ -static void efx_stop_eventq (struct efx_channel *channel) +void efx_stop_eventq (struct efx_channel *channel) {if (!channel->enabled)return ;napi_disable (&channel->napi_str); +while (!efx_channel_disable (channel)) +usleep_range (1000 ,20000 ); channel->enabled = false; }
@@ -1960,6 +1967,8 @@ static void efx_init_napi_channel(struct efx_channel *channel) channel->napi_dev = efx->net_dev;netif_napi_add (channel->napi_dev, &channel->napi_str, efx_poll, napi_weight); +napi_hash_add (&channel->napi_str); +efx_channel_init_lock (channel); }static void efx_init_napi (struct efx_nic *efx)
@@ -1972,8 +1981,10 @@ static void efx_init_napi(struct efx_nic *efx)static void efx_fini_napi_channel (struct efx_channel *channel) { -if (channel->napi_dev) +if (channel->napi_dev) {netif_napi_del (&channel->napi_str); +napi_hash_del (&channel->napi_str); + } channel->napi_dev =NULL ; }
@@ -2008,6 +2019,37 @@ static void efx_netpoll(struct net_device *net_dev)#endif +#ifdef CONFIG_NET_RX_BUSY_POLL +static int efx_busy_poll (struct napi_struct *napi) +{ +struct efx_channel *channel = + container_of(napi, struct efx_channel, napi_str); +struct efx_nic *efx = channel->efx; +int budget =4 ; +int old_rx_packets, rx_packets; + +if (!netif_running (efx->net_dev)) +return LL_FLUSH_FAILED ; + +if (!efx_channel_lock_poll (channel)) +return LL_FLUSH_BUSY ; + + old_rx_packets = channel->rx_queue.rx_packets; +efx_process_channel (channel, budget); + + rx_packets = channel->rx_queue.rx_packets - old_rx_packets; + +/* There is no race condition with NAPI here. +* NAPI will automatically be rescheduled if it yielded during busy +* polling, because it was not able to take the lock and thus returned +* the full budget. +*/ +efx_channel_unlock_poll (channel); + +return rx_packets; +} +#endif +/************************************************************************** * * Kernel net device interface
@@ -2177,6 +2219,9 @@ static const struct net_device_ops efx_farch_netdev_ops = { .ndo_poll_controller = efx_netpoll, #endif .ndo_setup_tc = efx_setup_tc, +#ifdef CONFIG_NET_RX_BUSY_POLL + .ndo_busy_poll = efx_busy_poll, +#endif #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = efx_filter_rfs,#endif
@@ -2197,6 +2242,9 @@ static const struct net_device_ops efx_ef10_netdev_ops = {#ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = efx_netpoll,#endif +#ifdef CONFIG_NET_RX_BUSY_POLL + .ndo_busy_poll = efx_busy_poll, +#endif #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = efx_filter_rfs,#endif
drivers/net/ethernet/sfc/efx.h +2 -0
@@ -194,6 +194,8 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, bool rx_may_override_tx);void efx_get_irq_moderation (struct efx_nic *efx,unsigned int *tx_usecs,unsigned int *rx_usecs,bool *rx_adaptive); +void efx_stop_eventq (struct efx_channel *channel); +void efx_start_eventq (struct efx_channel *channel);/* Dummy PHY ops for PHY drivers */ int efx_port_dummy_op_int (struct efx_nic *efx);
drivers/net/ethernet/sfc/net_driver.h +148 -0
172 lines not on this page · raw message
drivers/net/ethernet/sfc/rx.c +5 -1
@@ -462,6 +462,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,skb_record_rx_queue (skb, channel->rx_queue.core_index); +skb_mark_napi_id (skb, &channel->napi_str); gro_result =napi_gro_frags (napi);if (gro_result !=GRO_DROP ) channel->irq_mod_score +=2 ;
@@ -520,6 +521,8 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,/* Move past the ethernet header */ skb->protocol =eth_type_trans (skb, efx->net_dev); +skb_mark_napi_id (skb, &channel->napi_str); +return skb; }
@@ -666,7 +669,8 @@ void __efx_rx_packet(struct efx_channel *channel)if (unlikely (!(efx->net_dev->features &NETIF_F_RXCSUM ))) rx_buf->flags &= ~EFX_RX_PKT_CSUMMED ; -if ((rx_buf->flags &EFX_RX_PKT_TCP ) && !channel->type->receive_skb) +if ((rx_buf->flags &EFX_RX_PKT_TCP ) && !channel->type->receive_skb && + !efx_channel_busy_polling (channel))efx_rx_packet_gro (channel, rx_buf, channel->rx_pkt_n_frags, eh);else efx_rx_deliver (channel, eh, rx_buf, channel->rx_pkt_n_frags);
drivers/net/ethernet/sfc/selftest.c +2 -3
@@ -188,7 +188,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,schedule_timeout_uninterruptible (wait);efx_for_each_channel (channel, efx) { -napi_disable (&channel->napi_str); +efx_stop_eventq (channel);if (channel->eventq_read_ptr != read_ptr[channel->channel]) {set_bit (channel->channel, &napi_ran);
@@ -200,8 +200,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,if (efx_nic_event_test_irq_cpu (channel) >=0 )clear_bit (channel->channel, &int_pend); } -napi_enable (&channel->napi_str); -efx_nic_eventq_read_ack (channel); +efx_start_eventq (channel); } wait *=2 ;
From: Shradha Shah <[email protected]>
Date: Tue, 22 Jul 2014 14:03:25 +0100
Quoted 9 lines
From: Alexandre Rames <[email protected]>
This patch adds the sfc driver code for implementing busy polling. It adds
ndo_busy_pollmethod and locking between it and napi poll. It also adds each napi to thenapi_hashright afternetif_napi_add().Uses
efx_start_eventqandefx_stop_eventqin the self tests.Signed-off-by Shradha Shah <[email protected]>
Applied, thanks.