aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEdward Cree <ecree@solarflare.com>2018-04-24 12:09:30 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-24 13:48:22 -0400
commitf8d6203780b73c07dc49ee421fedae8edb76b6e4 (patch)
treeed28e63c7b6e5b9a6a8a0f791ffa1cfc3c86ee08 /drivers
parentd805c5209350ae725e3a1ee0204ba27d9e75ce3e (diff)
sfc: ARFS filter IDs
Associate an arbitrary ID with each ARFS filter, allowing to properly query for expiry. The association is maintained in a hash table, which is protected by a spinlock. v3: fix build warnings when CONFIG_RFS_ACCEL is disabled (thanks lkp-robot). v2: fixed uninitialised variable (thanks davem and lkp-robot). Fixes: 3af0f34290f6 ("sfc: replace asynchronous filter operations") Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/sfc/ef10.c80
-rw-r--r--drivers/net/ethernet/sfc/efx.c143
-rw-r--r--drivers/net/ethernet/sfc/efx.h21
-rw-r--r--drivers/net/ethernet/sfc/farch.c41
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h36
-rw-r--r--drivers/net/ethernet/sfc/rx.c62
6 files changed, 337 insertions, 46 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 83ce229f4eb7..63036d9bf3e6 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -3999,29 +3999,6 @@ static void efx_ef10_prepare_flr(struct efx_nic *efx)
3999 atomic_set(&efx->active_queues, 0); 3999 atomic_set(&efx->active_queues, 0);
4000} 4000}
4001 4001
4002static bool efx_ef10_filter_equal(const struct efx_filter_spec *left,
4003 const struct efx_filter_spec *right)
4004{
4005 if ((left->match_flags ^ right->match_flags) |
4006 ((left->flags ^ right->flags) &
4007 (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)))
4008 return false;
4009
4010 return memcmp(&left->outer_vid, &right->outer_vid,
4011 sizeof(struct efx_filter_spec) -
4012 offsetof(struct efx_filter_spec, outer_vid)) == 0;
4013}
4014
4015static unsigned int efx_ef10_filter_hash(const struct efx_filter_spec *spec)
4016{
4017 BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3);
4018 return jhash2((const u32 *)&spec->outer_vid,
4019 (sizeof(struct efx_filter_spec) -
4020 offsetof(struct efx_filter_spec, outer_vid)) / 4,
4021 0);
4022 /* XXX should we randomise the initval? */
4023}
4024
4025/* Decide whether a filter should be exclusive or else should allow 4002/* Decide whether a filter should be exclusive or else should allow
4026 * delivery to additional recipients. Currently we decide that 4003 * delivery to additional recipients. Currently we decide that
4027 * filters for specific local unicast MAC and IP addresses are 4004 * filters for specific local unicast MAC and IP addresses are
@@ -4346,7 +4323,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
4346 goto out_unlock; 4323 goto out_unlock;
4347 match_pri = rc; 4324 match_pri = rc;
4348 4325
4349 hash = efx_ef10_filter_hash(spec); 4326 hash = efx_filter_spec_hash(spec);
4350 is_mc_recip = efx_filter_is_mc_recipient(spec); 4327 is_mc_recip = efx_filter_is_mc_recipient(spec);
4351 if (is_mc_recip) 4328 if (is_mc_recip)
4352 bitmap_zero(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT); 4329 bitmap_zero(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
@@ -4378,7 +4355,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
4378 if (!saved_spec) { 4355 if (!saved_spec) {
4379 if (ins_index < 0) 4356 if (ins_index < 0)
4380 ins_index = i; 4357 ins_index = i;
4381 } else if (efx_ef10_filter_equal(spec, saved_spec)) { 4358 } else if (efx_filter_spec_equal(spec, saved_spec)) {
4382 if (spec->priority < saved_spec->priority && 4359 if (spec->priority < saved_spec->priority &&
4383 spec->priority != EFX_FILTER_PRI_AUTO) { 4360 spec->priority != EFX_FILTER_PRI_AUTO) {
4384 rc = -EPERM; 4361 rc = -EPERM;
@@ -4762,27 +4739,62 @@ static s32 efx_ef10_filter_get_rx_ids(struct efx_nic *efx,
4762static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id, 4739static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
4763 unsigned int filter_idx) 4740 unsigned int filter_idx)
4764{ 4741{
4742 struct efx_filter_spec *spec, saved_spec;
4765 struct efx_ef10_filter_table *table; 4743 struct efx_ef10_filter_table *table;
4766 struct efx_filter_spec *spec; 4744 struct efx_arfs_rule *rule = NULL;
4767 bool ret; 4745 bool ret = true, force = false;
4746 u16 arfs_id;
4768 4747
4769 down_read(&efx->filter_sem); 4748 down_read(&efx->filter_sem);
4770 table = efx->filter_state; 4749 table = efx->filter_state;
4771 down_write(&table->lock); 4750 down_write(&table->lock);
4772 spec = efx_ef10_filter_entry_spec(table, filter_idx); 4751 spec = efx_ef10_filter_entry_spec(table, filter_idx);
4773 4752
4774 if (!spec || spec->priority != EFX_FILTER_PRI_HINT) { 4753 if (!spec || spec->priority != EFX_FILTER_PRI_HINT)
4775 ret = true;
4776 goto out_unlock; 4754 goto out_unlock;
4777 }
4778 4755
4779 if (!rps_may_expire_flow(efx->net_dev, spec->dmaq_id, flow_id, 0)) { 4756 spin_lock_bh(&efx->rps_hash_lock);
4780 ret = false; 4757 if (!efx->rps_hash_table) {
4781 goto out_unlock; 4758 /* In the absence of the table, we always return 0 to ARFS. */
4759 arfs_id = 0;
4760 } else {
4761 rule = efx_rps_hash_find(efx, spec);
4762 if (!rule)
4763 /* ARFS table doesn't know of this filter, so remove it */
4764 goto expire;
4765 arfs_id = rule->arfs_id;
4766 ret = efx_rps_check_rule(rule, filter_idx, &force);
4767 if (force)
4768 goto expire;
4769 if (!ret) {
4770 spin_unlock_bh(&efx->rps_hash_lock);
4771 goto out_unlock;
4772 }
4782 } 4773 }
4783 4774 if (!rps_may_expire_flow(efx->net_dev, spec->dmaq_id, flow_id, arfs_id))
4775 ret = false;
4776 else if (rule)
4777 rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
4778expire:
4779 saved_spec = *spec; /* remove operation will kfree spec */
4780 spin_unlock_bh(&efx->rps_hash_lock);
4781 /* At this point (since we dropped the lock), another thread might queue
4782 * up a fresh insertion request (but the actual insertion will be held
4783 * up by our possession of the filter table lock). In that case, it
4784 * will set rule->filter_id to EFX_ARFS_FILTER_ID_PENDING, meaning that
4785 * the rule is not removed by efx_rps_hash_del() below.
4786 */
4784 ret = efx_ef10_filter_remove_internal(efx, 1U << spec->priority, 4787 ret = efx_ef10_filter_remove_internal(efx, 1U << spec->priority,
4785 filter_idx, true) == 0; 4788 filter_idx, true) == 0;
4789 /* While we can't safely dereference rule (we dropped the lock), we can
4790 * still test it for NULL.
4791 */
4792 if (ret && rule) {
4793 /* Expiring, so remove entry from ARFS table */
4794 spin_lock_bh(&efx->rps_hash_lock);
4795 efx_rps_hash_del(efx, &saved_spec);
4796 spin_unlock_bh(&efx->rps_hash_lock);
4797 }
4786out_unlock: 4798out_unlock:
4787 up_write(&table->lock); 4799 up_write(&table->lock);
4788 up_read(&efx->filter_sem); 4800 up_read(&efx->filter_sem);
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 692dd729ee2a..a4ebd8715494 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -3027,6 +3027,10 @@ static int efx_init_struct(struct efx_nic *efx,
3027 mutex_init(&efx->mac_lock); 3027 mutex_init(&efx->mac_lock);
3028#ifdef CONFIG_RFS_ACCEL 3028#ifdef CONFIG_RFS_ACCEL
3029 mutex_init(&efx->rps_mutex); 3029 mutex_init(&efx->rps_mutex);
3030 spin_lock_init(&efx->rps_hash_lock);
3031 /* Failure to allocate is not fatal, but may degrade ARFS performance */
3032 efx->rps_hash_table = kcalloc(EFX_ARFS_HASH_TABLE_SIZE,
3033 sizeof(*efx->rps_hash_table), GFP_KERNEL);
3030#endif 3034#endif
3031 efx->phy_op = &efx_dummy_phy_operations; 3035 efx->phy_op = &efx_dummy_phy_operations;
3032 efx->mdio.dev = net_dev; 3036 efx->mdio.dev = net_dev;
@@ -3070,6 +3074,10 @@ static void efx_fini_struct(struct efx_nic *efx)
3070{ 3074{
3071 int i; 3075 int i;
3072 3076
3077#ifdef CONFIG_RFS_ACCEL
3078 kfree(efx->rps_hash_table);
3079#endif
3080
3073 for (i = 0; i < EFX_MAX_CHANNELS; i++) 3081 for (i = 0; i < EFX_MAX_CHANNELS; i++)
3074 kfree(efx->channel[i]); 3082 kfree(efx->channel[i]);
3075 3083
@@ -3092,6 +3100,141 @@ void efx_update_sw_stats(struct efx_nic *efx, u64 *stats)
3092 stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops); 3100 stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops);
3093} 3101}
3094 3102
3103bool efx_filter_spec_equal(const struct efx_filter_spec *left,
3104 const struct efx_filter_spec *right)
3105{
3106 if ((left->match_flags ^ right->match_flags) |
3107 ((left->flags ^ right->flags) &
3108 (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)))
3109 return false;
3110
3111 return memcmp(&left->outer_vid, &right->outer_vid,
3112 sizeof(struct efx_filter_spec) -
3113 offsetof(struct efx_filter_spec, outer_vid)) == 0;
3114}
3115
3116u32 efx_filter_spec_hash(const struct efx_filter_spec *spec)
3117{
3118 BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3);
3119 return jhash2((const u32 *)&spec->outer_vid,
3120 (sizeof(struct efx_filter_spec) -
3121 offsetof(struct efx_filter_spec, outer_vid)) / 4,
3122 0);
3123}
3124
3125#ifdef CONFIG_RFS_ACCEL
3126bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx,
3127 bool *force)
3128{
3129 if (rule->filter_id == EFX_ARFS_FILTER_ID_PENDING) {
3130 /* ARFS is currently updating this entry, leave it */
3131 return false;
3132 }
3133 if (rule->filter_id == EFX_ARFS_FILTER_ID_ERROR) {
3134 /* ARFS tried and failed to update this, so it's probably out
3135 * of date. Remove the filter and the ARFS rule entry.
3136 */
3137 rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
3138 *force = true;
3139 return true;
3140 } else if (WARN_ON(rule->filter_id != filter_idx)) { /* can't happen */
3141 /* ARFS has moved on, so old filter is not needed. Since we did
3142 * not mark the rule with EFX_ARFS_FILTER_ID_REMOVING, it will
3143 * not be removed by efx_rps_hash_del() subsequently.
3144 */
3145 *force = true;
3146 return true;
3147 }
3148 /* Remove it iff ARFS wants to. */
3149 return true;
3150}
3151
3152struct hlist_head *efx_rps_hash_bucket(struct efx_nic *efx,
3153 const struct efx_filter_spec *spec)
3154{
3155 u32 hash = efx_filter_spec_hash(spec);
3156
3157 WARN_ON(!spin_is_locked(&efx->rps_hash_lock));
3158 if (!efx->rps_hash_table)
3159 return NULL;
3160 return &efx->rps_hash_table[hash % EFX_ARFS_HASH_TABLE_SIZE];
3161}
3162
3163struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx,
3164 const struct efx_filter_spec *spec)
3165{
3166 struct efx_arfs_rule *rule;
3167 struct hlist_head *head;
3168 struct hlist_node *node;
3169
3170 head = efx_rps_hash_bucket(efx, spec);
3171 if (!head)
3172 return NULL;
3173 hlist_for_each(node, head) {
3174 rule = container_of(node, struct efx_arfs_rule, node);
3175 if (efx_filter_spec_equal(spec, &rule->spec))
3176 return rule;
3177 }
3178 return NULL;
3179}
3180
3181struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx,
3182 const struct efx_filter_spec *spec,
3183 bool *new)
3184{
3185 struct efx_arfs_rule *rule;
3186 struct hlist_head *head;
3187 struct hlist_node *node;
3188
3189 head = efx_rps_hash_bucket(efx, spec);
3190 if (!head)
3191 return NULL;
3192 hlist_for_each(node, head) {
3193 rule = container_of(node, struct efx_arfs_rule, node);
3194 if (efx_filter_spec_equal(spec, &rule->spec)) {
3195 *new = false;
3196 return rule;
3197 }
3198 }
3199 rule = kmalloc(sizeof(*rule), GFP_ATOMIC);
3200 *new = true;
3201 if (rule) {
3202 memcpy(&rule->spec, spec, sizeof(rule->spec));
3203 hlist_add_head(&rule->node, head);
3204 }
3205 return rule;
3206}
3207
3208void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec)
3209{
3210 struct efx_arfs_rule *rule;
3211 struct hlist_head *head;
3212 struct hlist_node *node;
3213
3214 head = efx_rps_hash_bucket(efx, spec);
3215 if (WARN_ON(!head))
3216 return;
3217 hlist_for_each(node, head) {
3218 rule = container_of(node, struct efx_arfs_rule, node);
3219 if (efx_filter_spec_equal(spec, &rule->spec)) {
3220 /* Someone already reused the entry. We know that if
3221 * this check doesn't fire (i.e. filter_id == REMOVING)
3222 * then the REMOVING mark was put there by our caller,
3223 * because caller is holding a lock on filter table and
3224 * only holders of that lock set REMOVING.
3225 */
3226 if (rule->filter_id != EFX_ARFS_FILTER_ID_REMOVING)
3227 return;
3228 hlist_del(node);
3229 kfree(rule);
3230 return;
3231 }
3232 }
3233 /* We didn't find it. */
3234 WARN_ON(1);
3235}
3236#endif
3237
3095/* RSS contexts. We're using linked lists and crappy O(n) algorithms, because 3238/* RSS contexts. We're using linked lists and crappy O(n) algorithms, because
3096 * (a) this is an infrequent control-plane operation and (b) n is small (max 64) 3239 * (a) this is an infrequent control-plane operation and (b) n is small (max 64)
3097 */ 3240 */
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index a3140e16fcef..3f759ebdcf10 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -186,6 +186,27 @@ static inline void efx_filter_rfs_expire(struct work_struct *data) {}
186#endif 186#endif
187bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec); 187bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);
188 188
189bool efx_filter_spec_equal(const struct efx_filter_spec *left,
190 const struct efx_filter_spec *right);
191u32 efx_filter_spec_hash(const struct efx_filter_spec *spec);
192
193#ifdef CONFIG_RFS_ACCEL
194bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx,
195 bool *force);
196
197struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx,
198 const struct efx_filter_spec *spec);
199
200/* @new is written to indicate if entry was newly added (true) or if an old
201 * entry was found and returned (false).
202 */
203struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx,
204 const struct efx_filter_spec *spec,
205 bool *new);
206
207void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec);
208#endif
209
189/* RSS contexts */ 210/* RSS contexts */
190struct efx_rss_context *efx_alloc_rss_context_entry(struct efx_nic *efx); 211struct efx_rss_context *efx_alloc_rss_context_entry(struct efx_nic *efx);
191struct efx_rss_context *efx_find_rss_context_entry(struct efx_nic *efx, u32 id); 212struct efx_rss_context *efx_find_rss_context_entry(struct efx_nic *efx, u32 id);
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index 7174ef5e5c5e..c72adf8b52ea 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -2905,18 +2905,45 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
2905{ 2905{
2906 struct efx_farch_filter_state *state = efx->filter_state; 2906 struct efx_farch_filter_state *state = efx->filter_state;
2907 struct efx_farch_filter_table *table; 2907 struct efx_farch_filter_table *table;
2908 bool ret = false; 2908 bool ret = false, force = false;
2909 u16 arfs_id;
2909 2910
2910 down_write(&state->lock); 2911 down_write(&state->lock);
2912 spin_lock_bh(&efx->rps_hash_lock);
2911 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP]; 2913 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
2912 if (test_bit(index, table->used_bitmap) && 2914 if (test_bit(index, table->used_bitmap) &&
2913 table->spec[index].priority == EFX_FILTER_PRI_HINT && 2915 table->spec[index].priority == EFX_FILTER_PRI_HINT) {
2914 rps_may_expire_flow(efx->net_dev, table->spec[index].dmaq_id, 2916 struct efx_arfs_rule *rule = NULL;
2915 flow_id, 0)) { 2917 struct efx_filter_spec spec;
2916 efx_farch_filter_table_clear_entry(efx, table, index); 2918
2917 ret = true; 2919 efx_farch_filter_to_gen_spec(&spec, &table->spec[index]);
2920 if (!efx->rps_hash_table) {
2921 /* In the absence of the table, we always returned 0 to
2922 * ARFS, so use the same to query it.
2923 */
2924 arfs_id = 0;
2925 } else {
2926 rule = efx_rps_hash_find(efx, &spec);
2927 if (!rule) {
2928 /* ARFS table doesn't know of this filter, remove it */
2929 force = true;
2930 } else {
2931 arfs_id = rule->arfs_id;
2932 if (!efx_rps_check_rule(rule, index, &force))
2933 goto out_unlock;
2934 }
2935 }
2936 if (force || rps_may_expire_flow(efx->net_dev, spec.dmaq_id,
2937 flow_id, arfs_id)) {
2938 if (rule)
2939 rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
2940 efx_rps_hash_del(efx, &spec);
2941 efx_farch_filter_table_clear_entry(efx, table, index);
2942 ret = true;
2943 }
2918 } 2944 }
2919 2945out_unlock:
2946 spin_unlock_bh(&efx->rps_hash_lock);
2920 up_write(&state->lock); 2947 up_write(&state->lock);
2921 return ret; 2948 return ret;
2922} 2949}
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index eea3808b3f25..65568925c3ef 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -734,6 +734,35 @@ struct efx_rss_context {
734}; 734};
735 735
736#ifdef CONFIG_RFS_ACCEL 736#ifdef CONFIG_RFS_ACCEL
737/* Order of these is important, since filter_id >= %EFX_ARFS_FILTER_ID_PENDING
738 * is used to test if filter does or will exist.
739 */
740#define EFX_ARFS_FILTER_ID_PENDING -1
741#define EFX_ARFS_FILTER_ID_ERROR -2
742#define EFX_ARFS_FILTER_ID_REMOVING -3
743/**
744 * struct efx_arfs_rule - record of an ARFS filter and its IDs
745 * @node: linkage into hash table
746 * @spec: details of the filter (used as key for hash table). Use efx->type to
747 * determine which member to use.
748 * @rxq_index: channel to which the filter will steer traffic.
749 * @arfs_id: filter ID which was returned to ARFS
750 * @filter_id: index in software filter table. May be
751 * %EFX_ARFS_FILTER_ID_PENDING if filter was not inserted yet,
752 * %EFX_ARFS_FILTER_ID_ERROR if filter insertion failed, or
753 * %EFX_ARFS_FILTER_ID_REMOVING if expiry is currently removing the filter.
754 */
755struct efx_arfs_rule {
756 struct hlist_node node;
757 struct efx_filter_spec spec;
758 u16 rxq_index;
759 u16 arfs_id;
760 s32 filter_id;
761};
762
763/* Size chosen so that the table is one page (4kB) */
764#define EFX_ARFS_HASH_TABLE_SIZE 512
765
737/** 766/**
738 * struct efx_async_filter_insertion - Request to asynchronously insert a filter 767 * struct efx_async_filter_insertion - Request to asynchronously insert a filter
739 * @net_dev: Reference to the netdevice 768 * @net_dev: Reference to the netdevice
@@ -873,6 +902,10 @@ struct efx_async_filter_insertion {
873 * @rps_expire_channel's @rps_flow_id 902 * @rps_expire_channel's @rps_flow_id
874 * @rps_slot_map: bitmap of in-flight entries in @rps_slot 903 * @rps_slot_map: bitmap of in-flight entries in @rps_slot
875 * @rps_slot: array of ARFS insertion requests for efx_filter_rfs_work() 904 * @rps_slot: array of ARFS insertion requests for efx_filter_rfs_work()
905 * @rps_hash_lock: Protects ARFS filter mapping state (@rps_hash_table and
906 * @rps_next_id).
907 * @rps_hash_table: Mapping between ARFS filters and their various IDs
908 * @rps_next_id: next arfs_id for an ARFS filter
876 * @active_queues: Count of RX and TX queues that haven't been flushed and drained. 909 * @active_queues: Count of RX and TX queues that haven't been flushed and drained.
877 * @rxq_flush_pending: Count of number of receive queues that need to be flushed. 910 * @rxq_flush_pending: Count of number of receive queues that need to be flushed.
878 * Decremented when the efx_flush_rx_queue() is called. 911 * Decremented when the efx_flush_rx_queue() is called.
@@ -1029,6 +1062,9 @@ struct efx_nic {
1029 unsigned int rps_expire_index; 1062 unsigned int rps_expire_index;
1030 unsigned long rps_slot_map; 1063 unsigned long rps_slot_map;
1031 struct efx_async_filter_insertion rps_slot[EFX_RPS_MAX_IN_FLIGHT]; 1064 struct efx_async_filter_insertion rps_slot[EFX_RPS_MAX_IN_FLIGHT];
1065 spinlock_t rps_hash_lock;
1066 struct hlist_head *rps_hash_table;
1067 u32 rps_next_id;
1032#endif 1068#endif
1033 1069
1034 atomic_t active_queues; 1070 atomic_t active_queues;
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 9c593c661cbf..64a94f242027 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -834,9 +834,29 @@ static void efx_filter_rfs_work(struct work_struct *data)
834 struct efx_nic *efx = netdev_priv(req->net_dev); 834 struct efx_nic *efx = netdev_priv(req->net_dev);
835 struct efx_channel *channel = efx_get_channel(efx, req->rxq_index); 835 struct efx_channel *channel = efx_get_channel(efx, req->rxq_index);
836 int slot_idx = req - efx->rps_slot; 836 int slot_idx = req - efx->rps_slot;
837 struct efx_arfs_rule *rule;
838 u16 arfs_id = 0;
837 int rc; 839 int rc;
838 840
839 rc = efx->type->filter_insert(efx, &req->spec, true); 841 rc = efx->type->filter_insert(efx, &req->spec, true);
842 if (efx->rps_hash_table) {
843 spin_lock_bh(&efx->rps_hash_lock);
844 rule = efx_rps_hash_find(efx, &req->spec);
845 /* The rule might have already gone, if someone else's request
846 * for the same spec was already worked and then expired before
847 * we got around to our work. In that case we have nothing
848 * tying us to an arfs_id, meaning that as soon as the filter
849 * is considered for expiry it will be removed.
850 */
851 if (rule) {
852 if (rc < 0)
853 rule->filter_id = EFX_ARFS_FILTER_ID_ERROR;
854 else
855 rule->filter_id = rc;
856 arfs_id = rule->arfs_id;
857 }
858 spin_unlock_bh(&efx->rps_hash_lock);
859 }
840 if (rc >= 0) { 860 if (rc >= 0) {
841 /* Remember this so we can check whether to expire the filter 861 /* Remember this so we can check whether to expire the filter
842 * later. 862 * later.
@@ -848,18 +868,18 @@ static void efx_filter_rfs_work(struct work_struct *data)
848 868
849 if (req->spec.ether_type == htons(ETH_P_IP)) 869 if (req->spec.ether_type == htons(ETH_P_IP))
850 netif_info(efx, rx_status, efx->net_dev, 870 netif_info(efx, rx_status, efx->net_dev,
851 "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n", 871 "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d id %u]\n",
852 (req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", 872 (req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
853 req->spec.rem_host, ntohs(req->spec.rem_port), 873 req->spec.rem_host, ntohs(req->spec.rem_port),
854 req->spec.loc_host, ntohs(req->spec.loc_port), 874 req->spec.loc_host, ntohs(req->spec.loc_port),
855 req->rxq_index, req->flow_id, rc); 875 req->rxq_index, req->flow_id, rc, arfs_id);
856 else 876 else
857 netif_info(efx, rx_status, efx->net_dev, 877 netif_info(efx, rx_status, efx->net_dev,
858 "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n", 878 "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d id %u]\n",
859 (req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", 879 (req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
860 req->spec.rem_host, ntohs(req->spec.rem_port), 880 req->spec.rem_host, ntohs(req->spec.rem_port),
861 req->spec.loc_host, ntohs(req->spec.loc_port), 881 req->spec.loc_host, ntohs(req->spec.loc_port),
862 req->rxq_index, req->flow_id, rc); 882 req->rxq_index, req->flow_id, rc, arfs_id);
863 } 883 }
864 884
865 /* Release references */ 885 /* Release references */
@@ -872,8 +892,10 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
872{ 892{
873 struct efx_nic *efx = netdev_priv(net_dev); 893 struct efx_nic *efx = netdev_priv(net_dev);
874 struct efx_async_filter_insertion *req; 894 struct efx_async_filter_insertion *req;
895 struct efx_arfs_rule *rule;
875 struct flow_keys fk; 896 struct flow_keys fk;
876 int slot_idx; 897 int slot_idx;
898 bool new;
877 int rc; 899 int rc;
878 900
879 /* find a free slot */ 901 /* find a free slot */
@@ -926,12 +948,42 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
926 req->spec.rem_port = fk.ports.src; 948 req->spec.rem_port = fk.ports.src;
927 req->spec.loc_port = fk.ports.dst; 949 req->spec.loc_port = fk.ports.dst;
928 950
951 if (efx->rps_hash_table) {
952 /* Add it to ARFS hash table */
953 spin_lock(&efx->rps_hash_lock);
954 rule = efx_rps_hash_add(efx, &req->spec, &new);
955 if (!rule) {
956 rc = -ENOMEM;
957 goto out_unlock;
958 }
959 if (new)
960 rule->arfs_id = efx->rps_next_id++ % RPS_NO_FILTER;
961 rc = rule->arfs_id;
962 /* Skip if existing or pending filter already does the right thing */
963 if (!new && rule->rxq_index == rxq_index &&
964 rule->filter_id >= EFX_ARFS_FILTER_ID_PENDING)
965 goto out_unlock;
966 rule->rxq_index = rxq_index;
967 rule->filter_id = EFX_ARFS_FILTER_ID_PENDING;
968 spin_unlock(&efx->rps_hash_lock);
969 } else {
970 /* Without an ARFS hash table, we just use arfs_id 0 for all
971 * filters. This means if multiple flows hash to the same
972 * flow_id, all but the most recently touched will be eligible
973 * for expiry.
974 */
975 rc = 0;
976 }
977
978 /* Queue the request */
929 dev_hold(req->net_dev = net_dev); 979 dev_hold(req->net_dev = net_dev);
930 INIT_WORK(&req->work, efx_filter_rfs_work); 980 INIT_WORK(&req->work, efx_filter_rfs_work);
931 req->rxq_index = rxq_index; 981 req->rxq_index = rxq_index;
932 req->flow_id = flow_id; 982 req->flow_id = flow_id;
933 schedule_work(&req->work); 983 schedule_work(&req->work);
934 return 0; 984 return rc;
985out_unlock:
986 spin_unlock(&efx->rps_hash_lock);
935out_clear: 987out_clear:
936 clear_bit(slot_idx, &efx->rps_slot_map); 988 clear_bit(slot_idx, &efx->rps_slot_map);
937 return rc; 989 return rc;