pull request: sfc-next-2.6 2011-02-18
Subsystems (2)
The following changes since commit f878b995b0f746f5726af9e66940f3bf373dae91:
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6 (2011-02-15 12:25:19 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6.git for-davem
Add support for RFS acceleration in the sfc driver, and allow it to be enabled and disabled dynamically using ethtool.
Ben.
Ben Hutchings (3):
net: RPS: Make hardware-accelerated RFS conditional on NETIF_F_NTUPLE
sfc: Limit filter search depth further for performance hints (i.e. RFS)
sfc: Implement hardware acceleration of RFS
drivers/net/sfc/efx.c | 49 +++++++++++++++++- drivers/net/sfc/efx.h | 15 +++++ drivers/net/sfc/filter.c | 117 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/sfc/net_driver.h | 3 + net/core/dev.c | 3 +- 5 files changed, 180 insertions(+), 7 deletions(-)
Signature · 3 lines
Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
PATCH 1/3 net: RPS: Make hardware-accelerated RFS conditional on NETIF_F_NTUPLE
For testing and debugging purposes it is useful to be able to disable hardware acceleration of RFS without disabling RFS altogether. Since this is a similar feature to 'n-tuple' flow steering through the ethtool API, test the same feature flag that controls that.
--- net/core/dev.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
net/core/dev.c +2 -1
@@ -2607,7 +2607,8 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb,int rc;/* Should we steer this flow to a different hardware queue? */ -if (!skb_rx_queue_recorded (skb) || !dev->rx_cpu_rmap) +if (!skb_rx_queue_recorded (skb) || !dev->rx_cpu_rmap || + !(dev->features &NETIF_F_NTUPLE )) goto out; rxq_index =cpu_rmap_lookup_index (dev->rx_cpu_rmap, next_cpu);if (rxq_index ==skb_get_rx_queue (skb))
Signature · 8 lines
1.7.3.4 -- Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
PATCH 2/3 sfc: Limit filter search depth further for performance hints (i.e. RFS)
In reply to Ben Hutchings--- drivers/net/sfc/filter.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/sfc/filter.c +9 -4
@@ -27,6 +27,10 @@*/ #define FILTER_CTL_SRCH_MAX 200 +/* Don't try very hard to find space for performance hints, as this is +* counter-productive. */ +#define FILTER_CTL_SRCH_HINT_MAX 5 +enum efx_filter_table_id {EFX_FILTER_TABLE_RX_IP =0 ,EFX_FILTER_TABLE_RX_MAC ,
@@ -325,15 +329,16 @@ static int efx_filter_search(struct efx_filter_table *table, struct efx_filter_spec *spec, u32 key, bool for_insert, int *depth_required) { - unsigned hash, incr, filter_idx, depth; + unsigned hash, incr, filter_idx, depth, depth_max;struct efx_filter_spec *cmp; hash =efx_filter_hash (key); incr =efx_filter_increment (key); + depth_max = (spec->priority <=EFX_FILTER_PRI_HINT ? +FILTER_CTL_SRCH_HINT_MAX :FILTER_CTL_SRCH_MAX );for (depth =1 , filter_idx = hash & (table->size -1 ); - depth <=FILTER_CTL_SRCH_MAX && -test_bit (filter_idx, table->used_bitmap); + depth <= depth_max &&test_bit (filter_idx, table->used_bitmap); ++depth) { cmp = &table->spec[filter_idx];if (efx_filter_equal (spec, cmp))
@@ -342,7 +347,7 @@ static int efx_filter_search(struct efx_filter_table *table, }if (!for_insert)return -ENOENT ; -if (depth >FILTER_CTL_SRCH_MAX ) +if (depth > depth_max)return -EBUSY ; found: *depth_required = depth;
Signature · 8 lines
1.7.3.4 -- Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
PATCH 3/3 sfc: Implement hardware acceleration of RFS
In reply to Ben HutchingsUse the existing filter management functions to insert TCP/IPv4 and UDP/IPv4 4-tuple filters for Receive Flow Steering.
For each channel, track how many RFS filters are being added during processing of received packets and scan the corresponding number of table entries for filters that may be reclaimed. Do this in batches to reduce lock overhead.
--- drivers/net/sfc/efx.c | 49 +++++++++++++++++++- drivers/net/sfc/efx.h | 15 ++++++ drivers/net/sfc/filter.c | 104 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/sfc/net_driver.h | 3 + 4 files changed, 169 insertions(+), 2 deletions(-)
drivers/net/sfc/efx.c +47 -2
@@ -21,6 +21,7 @@#include <linux/ethtool.h> #include <linux/topology.h> #include <linux/gfp.h> +#include <linux/cpu_rmap.h> #include "net_driver.h" #include "efx.h" #include "nic.h"
@@ -307,6 +308,8 @@ static int efx_poll(struct napi_struct *napi, int budget) channel->irq_mod_score =0 ; } +efx_filter_rfs_expire (channel); +/* There is no race here; although napi_disable() will * only wait for napi_complete(), this isn't a problem * since efx_channel_processed() will have no effect if
@@ -1175,10 +1178,32 @@ static int efx_wanted_channels(void)return count; } +static int +efx_init_rx_cpu_rmap (struct efx_nic *efx,struct msix_entry *xentries) +{ +#ifdef CONFIG_RFS_ACCEL +int i, rc; + + efx->net_dev->rx_cpu_rmap =alloc_irq_cpu_rmap (efx->n_rx_channels); +if (!efx->net_dev->rx_cpu_rmap) +return -ENOMEM ; +for (i =0 ; i < efx->n_rx_channels; i++) { + rc =irq_cpu_rmap_add (efx->net_dev->rx_cpu_rmap, + xentries[i].vector); +if (rc) { +free_irq_cpu_rmap (efx->net_dev->rx_cpu_rmap); + efx->net_dev->rx_cpu_rmap =NULL ; +return rc; + } + } +#endif +return 0 ; +} +/* Probe the number and type of interrupts we are able to obtain, and * the resulting numbers of channels and RX queues. */ -static void efx_probe_interrupts (struct efx_nic *efx) +static int efx_probe_interrupts (struct efx_nic *efx) {int max_channels =min_t (int, efx->type->phys_addr_channels,EFX_MAX_CHANNELS );
@@ -1220,6 +1245,11 @@ static void efx_probe_interrupts(struct efx_nic *efx) efx->n_tx_channels = efx->n_channels; efx->n_rx_channels = efx->n_channels; } + rc =efx_init_rx_cpu_rmap (efx, xentries); +if (rc) { +pci_disable_msix (efx->pci_dev); +return rc; + }for (i =0 ; i < n_channels; i++)efx_get_channel (efx, i)->irq = xentries[i].vector;
@@ -1253,6 +1283,8 @@ static void efx_probe_interrupts(struct efx_nic *efx) efx->n_tx_channels =1 ; efx->legacy_irq = efx->pci_dev->irq; } + +return 0 ; }static void efx_remove_interrupts (struct efx_nic *efx)
@@ -1289,7 +1321,9 @@ static int efx_probe_nic(struct efx_nic *efx)/* Determine the number of channels and queues by trying to hook * in MSI-X interrupts. */ -efx_probe_interrupts (efx); + rc =efx_probe_interrupts (efx); +if (rc) + goto fail;if (efx->n_channels >1 )get_random_bytes (&efx->rx_hash_key,sizeof (efx->rx_hash_key));
@@ -1304,6 +1338,10 @@ static int efx_probe_nic(struct efx_nic *efx)efx_init_irq_moderation (efx, tx_irq_mod_usec, rx_irq_mod_usec, true);return 0 ; + +fail: + efx->type->remove (efx); +return rc; }static void efx_remove_nic (struct efx_nic *efx)
@@ -1837,6 +1875,9 @@ static const struct net_device_ops efx_netdev_ops = { .ndo_poll_controller = efx_netpoll, #endif .ndo_setup_tc = efx_setup_tc, +#ifdef CONFIG_RFS_ACCEL + .ndo_rx_flow_steer = efx_filter_rfs, +#endif };static void efx_update_name (struct efx_nic *efx)
@@ -2274,6 +2315,10 @@ static void efx_fini_struct(struct efx_nic *efx)*/ static void efx_pci_remove_main (struct efx_nic *efx) { +#ifdef CONFIG_RFS_ACCEL +free_irq_cpu_rmap (efx->net_dev->rx_cpu_rmap); + efx->net_dev->rx_cpu_rmap =NULL ; +#endif efx_nic_fini_interrupt (efx);efx_fini_channels (efx);efx_fini_port (efx);
drivers/net/sfc/efx.h +15 -0
@@ -76,6 +76,21 @@ extern int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec);extern void efx_filter_clear_rx (struct efx_nic *efx,enum efx_filter_priority priority); +#ifdef CONFIG_RFS_ACCEL +extern int efx_filter_rfs (struct net_device *net_dev,const struct sk_buff *skb, +u16 rxq_index,u32 flow_id); +extern bool __efx_filter_rfs_expire (struct efx_nic *efx,unsigned quota); +static inline void efx_filter_rfs_expire (struct efx_channel *channel) +{ +if (channel->rfs_filters_added >=60 && +__efx_filter_rfs_expire (channel->efx,100 )) + channel->rfs_filters_added -=60 ; +} +#define efx_filter_rfs_enabled () 1 +#else +static inline void efx_filter_rfs_expire (struct efx_channel *channel) {} +#define efx_filter_rfs_enabled () 0 +#endif /* Channels */ extern void efx_process_channel_now (struct efx_channel *channel);
drivers/net/sfc/filter.c +104 -0
127 lines not on this page · raw message
drivers/net/sfc/net_driver.h +3 -0
@@ -362,6 +362,9 @@ struct efx_channel {unsigned int irq_count;unsigned int irq_mod_score; +#ifdef CONFIG_RFS_ACCEL +unsigned int rfs_filters_added; +#endif int rx_alloc_level;int rx_alloc_push_pages;
Signature · 7 lines
1.7.3.4 -- Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
David Miller
maintainerFrom: Ben Hutchings <[email protected]>
Date: Fri, 18 Feb 2011 16:00:39 +0000
Quoted 10 lines
The following changes since commit
f878b995b0f746f5726af9e66940f3bf373dae91:Merge branch 'for-davem' of
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6(2011-02-15 12:25:19 -0800)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6.gitfor-davemAdd support for RFS acceleration in the sfc driver, and allow it to be enabled and disabled dynamically using ethtool.
Pulled, thanks Ben.