Loading drivers/net/ethernet/sfc/ef10.c +14 −14 Original line number Diff line number Diff line Loading @@ -660,7 +660,7 @@ static int efx_ef10_probe(struct efx_nic *efx) } nic_data->warm_boot_count = rc; efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; nic_data->vport_id = EVB_PORT_ID_ASSIGNED; Loading Loading @@ -1440,7 +1440,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx) nic_data->must_restore_filters = true; nic_data->must_restore_piobufs = true; efx_ef10_forget_old_piobufs(efx); efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* Driver-created vswitches and vports must be re-created */ nic_data->must_probe_vswitching = true; Loading Loading @@ -2598,7 +2598,7 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, bool exclusive, EFX_EF10_MAX_SHARED_RSS_CONTEXT_SIZE); if (!exclusive && rss_spread == 1) { ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; if (context_size) *context_size = 1; return 0; Loading Loading @@ -2685,11 +2685,11 @@ static void efx_ef10_rx_free_indir_table(struct efx_nic *efx) { int rc; if (efx->rss_context.context_id != EFX_EF10_RSS_CONTEXT_INVALID) { if (efx->rss_context.context_id != EFX_MCDI_RSS_CONTEXT_INVALID) { rc = efx_ef10_free_rss_context(efx, efx->rss_context.context_id); WARN_ON(rc != 0); } efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; } static int efx_ef10_rx_push_shared_rss_config(struct efx_nic *efx, Loading @@ -2715,7 +2715,7 @@ static int efx_ef10_rx_push_exclusive_rss_config(struct efx_nic *efx, struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; if (efx->rss_context.context_id == EFX_EF10_RSS_CONTEXT_INVALID || if (efx->rss_context.context_id == EFX_MCDI_RSS_CONTEXT_INVALID || !nic_data->rx_rss_context_exclusive) { rc = efx_ef10_alloc_rss_context(efx, true, &efx->rss_context, NULL); Loading @@ -2731,7 +2731,7 @@ static int efx_ef10_rx_push_exclusive_rss_config(struct efx_nic *efx, goto fail2; if (efx->rss_context.context_id != old_rx_rss_context && old_rx_rss_context != EFX_EF10_RSS_CONTEXT_INVALID) old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID) WARN_ON(efx_ef10_free_rss_context(efx, old_rx_rss_context) != 0); nic_data->rx_rss_context_exclusive = true; if (rx_indir_table != efx->rss_context.rx_indir_table) Loading Loading @@ -2762,7 +2762,7 @@ static int efx_ef10_rx_push_rss_context_config(struct efx_nic *efx, WARN_ON(!mutex_is_locked(&efx->rss_lock)); if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { rc = efx_ef10_alloc_rss_context(efx, true, ctx, NULL); if (rc) return rc; Loading Loading @@ -2797,7 +2797,7 @@ static int efx_ef10_rx_pull_rss_context_config(struct efx_nic *efx, BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_GET_TABLE_IN_LEN != MC_CMD_RSS_CONTEXT_GET_KEY_IN_LEN); if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) return -ENOENT; MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_TABLE_IN_RSS_CONTEXT_ID, Loading Loading @@ -2858,7 +2858,7 @@ static void efx_ef10_rx_restore_rss_contexts(struct efx_nic *efx) list_for_each_entry(ctx, &efx->rss_context.list, list) { /* previous NIC RSS context is gone */ ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* so try to allocate a new one */ rc = efx_ef10_rx_push_rss_context_config(efx, ctx, ctx->rx_indir_table, Loading Loading @@ -2929,7 +2929,7 @@ static int efx_ef10_vf_rx_push_rss_config(struct efx_nic *efx, bool user, { if (user) return -EOPNOTSUPP; if (efx->rss_context.context_id != EFX_EF10_RSS_CONTEXT_INVALID) if (efx->rss_context.context_id != EFX_MCDI_RSS_CONTEXT_INVALID) return 0; return efx_ef10_rx_push_shared_rss_config(efx, NULL); } Loading Loading @@ -3850,7 +3850,7 @@ static void efx_ef10_filter_push_prep(struct efx_nic *efx, */ if (WARN_ON_ONCE(!ctx)) flags &= ~EFX_FILTER_FLAG_RX_RSS; else if (WARN_ON_ONCE(ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID)) else if (WARN_ON_ONCE(ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID)) flags &= ~EFX_FILTER_FLAG_RX_RSS; } Loading Loading @@ -4029,7 +4029,7 @@ static s32 efx_ef10_filter_insert_locked(struct efx_nic *efx, rc = -ENOENT; goto out_unlock; } if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { rc = -EOPNOTSUPP; goto out_unlock; } Loading Loading @@ -4770,7 +4770,7 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx) invalid_filters++; goto not_restored; } if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { netif_warn(efx, drv, efx->net_dev, "Warning: unable to restore a filter with RSS context %u as it was not created.\n", spec->rss_context); Loading drivers/net/ethernet/sfc/efx.c +0 −200 Original line number Diff line number Diff line Loading @@ -384,70 +384,6 @@ static void efx_remove_nic(struct efx_nic *efx) efx->type->remove(efx); } static int efx_probe_filters(struct efx_nic *efx) { int rc; init_rwsem(&efx->filter_sem); mutex_lock(&efx->mac_lock); down_write(&efx->filter_sem); rc = efx->type->filter_table_probe(efx); if (rc) goto out_unlock; #ifdef CONFIG_RFS_ACCEL if (efx->type->offload_features & NETIF_F_NTUPLE) { struct efx_channel *channel; int i, success = 1; efx_for_each_channel(channel, efx) { channel->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters, sizeof(*channel->rps_flow_id), GFP_KERNEL); if (!channel->rps_flow_id) success = 0; else for (i = 0; i < efx->type->max_rx_ip_filters; ++i) channel->rps_flow_id[i] = RPS_FLOW_ID_INVALID; channel->rfs_expire_index = 0; channel->rfs_filter_count = 0; } if (!success) { efx_for_each_channel(channel, efx) kfree(channel->rps_flow_id); efx->type->filter_table_remove(efx); rc = -ENOMEM; goto out_unlock; } } #endif out_unlock: up_write(&efx->filter_sem); mutex_unlock(&efx->mac_lock); return rc; } static void efx_remove_filters(struct efx_nic *efx) { #ifdef CONFIG_RFS_ACCEL struct efx_channel *channel; efx_for_each_channel(channel, efx) { cancel_delayed_work_sync(&channel->filter_work); kfree(channel->rps_flow_id); } #endif down_write(&efx->filter_sem); efx->type->filter_table_remove(efx); up_write(&efx->filter_sem); } /************************************************************************** * * NIC startup/shutdown Loading Loading @@ -1109,142 +1045,6 @@ void efx_update_sw_stats(struct efx_nic *efx, u64 *stats) stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops); } bool efx_filter_spec_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right) { if ((left->match_flags ^ right->match_flags) | ((left->flags ^ right->flags) & (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX))) return false; return memcmp(&left->outer_vid, &right->outer_vid, sizeof(struct efx_filter_spec) - offsetof(struct efx_filter_spec, outer_vid)) == 0; } u32 efx_filter_spec_hash(const struct efx_filter_spec *spec) { BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3); return jhash2((const u32 *)&spec->outer_vid, (sizeof(struct efx_filter_spec) - offsetof(struct efx_filter_spec, outer_vid)) / 4, 0); } #ifdef CONFIG_RFS_ACCEL bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx, bool *force) { if (rule->filter_id == EFX_ARFS_FILTER_ID_PENDING) { /* ARFS is currently updating this entry, leave it */ return false; } if (rule->filter_id == EFX_ARFS_FILTER_ID_ERROR) { /* ARFS tried and failed to update this, so it's probably out * of date. Remove the filter and the ARFS rule entry. */ rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING; *force = true; return true; } else if (WARN_ON(rule->filter_id != filter_idx)) { /* can't happen */ /* ARFS has moved on, so old filter is not needed. Since we did * not mark the rule with EFX_ARFS_FILTER_ID_REMOVING, it will * not be removed by efx_rps_hash_del() subsequently. */ *force = true; return true; } /* Remove it iff ARFS wants to. */ return true; } static struct hlist_head *efx_rps_hash_bucket(struct efx_nic *efx, const struct efx_filter_spec *spec) { u32 hash = efx_filter_spec_hash(spec); lockdep_assert_held(&efx->rps_hash_lock); if (!efx->rps_hash_table) return NULL; return &efx->rps_hash_table[hash % EFX_ARFS_HASH_TABLE_SIZE]; } struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx, const struct efx_filter_spec *spec) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (!head) return NULL; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) return rule; } return NULL; } struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx, const struct efx_filter_spec *spec, bool *new) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (!head) return NULL; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) { *new = false; return rule; } } rule = kmalloc(sizeof(*rule), GFP_ATOMIC); *new = true; if (rule) { memcpy(&rule->spec, spec, sizeof(rule->spec)); hlist_add_head(&rule->node, head); } return rule; } void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (WARN_ON(!head)) return; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) { /* Someone already reused the entry. We know that if * this check doesn't fire (i.e. filter_id == REMOVING) * then the REMOVING mark was put there by our caller, * because caller is holding a lock on filter table and * only holders of that lock set REMOVING. */ if (rule->filter_id != EFX_ARFS_FILTER_ID_REMOVING) return; hlist_del(node); kfree(rule); return; } } /* We didn't find it. */ WARN_ON(1); } #endif /************************************************************************** * * PCI interface Loading drivers/net/ethernet/sfc/efx.h +1 −23 Original line number Diff line number Diff line Loading @@ -169,33 +169,11 @@ static inline void efx_filter_rfs_expire(struct work_struct *data) static inline void efx_filter_rfs_expire(struct work_struct *data) {} #define efx_filter_rfs_enabled() 0 #endif bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec); bool efx_filter_spec_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right); u32 efx_filter_spec_hash(const struct efx_filter_spec *spec); #ifdef CONFIG_RFS_ACCEL bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx, bool *force); struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx, const struct efx_filter_spec *spec); /* @new is written to indicate if entry was newly added (true) or if an old * entry was found and returned (false). */ struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx, const struct efx_filter_spec *spec, bool *new); void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec); #endif /* RSS contexts */ static inline bool efx_rss_active(struct efx_rss_context *ctx) { return ctx->context_id != EFX_EF10_RSS_CONTEXT_INVALID; return ctx->context_id != EFX_MCDI_RSS_CONTEXT_INVALID; } /* Ethtool support */ Loading drivers/net/ethernet/sfc/ethtool.c +1 −1 Original line number Diff line number Diff line Loading @@ -1020,7 +1020,7 @@ static int efx_ethtool_set_rxfh_context(struct net_device *net_dev, rc = -ENOMEM; goto out_unlock; } ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* Initialise indir table and key to defaults */ efx_set_default_rx_indir_table(efx, ctx); netdev_rss_key_fill(ctx->rx_hash_key, sizeof(ctx->rx_hash_key)); Loading drivers/net/ethernet/sfc/net_driver.h +3 −3 Original line number Diff line number Diff line Loading @@ -744,13 +744,13 @@ union efx_multicast_hash { struct vfdi_status; /* The reserved RSS context value */ #define EFX_EF10_RSS_CONTEXT_INVALID 0xffffffff #define EFX_MCDI_RSS_CONTEXT_INVALID 0xffffffff /** * struct efx_rss_context - A user-defined RSS context for filtering * @list: node of linked list on which this struct is stored * @context_id: the RSS_CONTEXT_ID returned by MC firmware, or * %EFX_EF10_RSS_CONTEXT_INVALID if this context is not present on the NIC. * For Siena, 0 if RSS is active, else %EFX_EF10_RSS_CONTEXT_INVALID. * %EFX_MCDI_RSS_CONTEXT_INVALID if this context is not present on the NIC. * For Siena, 0 if RSS is active, else %EFX_MCDI_RSS_CONTEXT_INVALID. * @user_id: the rss_context ID exposed to userspace over ethtool. * @rx_hash_udp_4tuple: UDP 4-tuple hashing enabled * @rx_hash_key: Toeplitz hash key for this RSS context Loading Loading
drivers/net/ethernet/sfc/ef10.c +14 −14 Original line number Diff line number Diff line Loading @@ -660,7 +660,7 @@ static int efx_ef10_probe(struct efx_nic *efx) } nic_data->warm_boot_count = rc; efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; nic_data->vport_id = EVB_PORT_ID_ASSIGNED; Loading Loading @@ -1440,7 +1440,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx) nic_data->must_restore_filters = true; nic_data->must_restore_piobufs = true; efx_ef10_forget_old_piobufs(efx); efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* Driver-created vswitches and vports must be re-created */ nic_data->must_probe_vswitching = true; Loading Loading @@ -2598,7 +2598,7 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, bool exclusive, EFX_EF10_MAX_SHARED_RSS_CONTEXT_SIZE); if (!exclusive && rss_spread == 1) { ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; if (context_size) *context_size = 1; return 0; Loading Loading @@ -2685,11 +2685,11 @@ static void efx_ef10_rx_free_indir_table(struct efx_nic *efx) { int rc; if (efx->rss_context.context_id != EFX_EF10_RSS_CONTEXT_INVALID) { if (efx->rss_context.context_id != EFX_MCDI_RSS_CONTEXT_INVALID) { rc = efx_ef10_free_rss_context(efx, efx->rss_context.context_id); WARN_ON(rc != 0); } efx->rss_context.context_id = EFX_EF10_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; } static int efx_ef10_rx_push_shared_rss_config(struct efx_nic *efx, Loading @@ -2715,7 +2715,7 @@ static int efx_ef10_rx_push_exclusive_rss_config(struct efx_nic *efx, struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; if (efx->rss_context.context_id == EFX_EF10_RSS_CONTEXT_INVALID || if (efx->rss_context.context_id == EFX_MCDI_RSS_CONTEXT_INVALID || !nic_data->rx_rss_context_exclusive) { rc = efx_ef10_alloc_rss_context(efx, true, &efx->rss_context, NULL); Loading @@ -2731,7 +2731,7 @@ static int efx_ef10_rx_push_exclusive_rss_config(struct efx_nic *efx, goto fail2; if (efx->rss_context.context_id != old_rx_rss_context && old_rx_rss_context != EFX_EF10_RSS_CONTEXT_INVALID) old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID) WARN_ON(efx_ef10_free_rss_context(efx, old_rx_rss_context) != 0); nic_data->rx_rss_context_exclusive = true; if (rx_indir_table != efx->rss_context.rx_indir_table) Loading Loading @@ -2762,7 +2762,7 @@ static int efx_ef10_rx_push_rss_context_config(struct efx_nic *efx, WARN_ON(!mutex_is_locked(&efx->rss_lock)); if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { rc = efx_ef10_alloc_rss_context(efx, true, ctx, NULL); if (rc) return rc; Loading Loading @@ -2797,7 +2797,7 @@ static int efx_ef10_rx_pull_rss_context_config(struct efx_nic *efx, BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_GET_TABLE_IN_LEN != MC_CMD_RSS_CONTEXT_GET_KEY_IN_LEN); if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) return -ENOENT; MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_TABLE_IN_RSS_CONTEXT_ID, Loading Loading @@ -2858,7 +2858,7 @@ static void efx_ef10_rx_restore_rss_contexts(struct efx_nic *efx) list_for_each_entry(ctx, &efx->rss_context.list, list) { /* previous NIC RSS context is gone */ ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* so try to allocate a new one */ rc = efx_ef10_rx_push_rss_context_config(efx, ctx, ctx->rx_indir_table, Loading Loading @@ -2929,7 +2929,7 @@ static int efx_ef10_vf_rx_push_rss_config(struct efx_nic *efx, bool user, { if (user) return -EOPNOTSUPP; if (efx->rss_context.context_id != EFX_EF10_RSS_CONTEXT_INVALID) if (efx->rss_context.context_id != EFX_MCDI_RSS_CONTEXT_INVALID) return 0; return efx_ef10_rx_push_shared_rss_config(efx, NULL); } Loading Loading @@ -3850,7 +3850,7 @@ static void efx_ef10_filter_push_prep(struct efx_nic *efx, */ if (WARN_ON_ONCE(!ctx)) flags &= ~EFX_FILTER_FLAG_RX_RSS; else if (WARN_ON_ONCE(ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID)) else if (WARN_ON_ONCE(ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID)) flags &= ~EFX_FILTER_FLAG_RX_RSS; } Loading Loading @@ -4029,7 +4029,7 @@ static s32 efx_ef10_filter_insert_locked(struct efx_nic *efx, rc = -ENOENT; goto out_unlock; } if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { rc = -EOPNOTSUPP; goto out_unlock; } Loading Loading @@ -4770,7 +4770,7 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx) invalid_filters++; goto not_restored; } if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) { if (ctx->context_id == EFX_MCDI_RSS_CONTEXT_INVALID) { netif_warn(efx, drv, efx->net_dev, "Warning: unable to restore a filter with RSS context %u as it was not created.\n", spec->rss_context); Loading
drivers/net/ethernet/sfc/efx.c +0 −200 Original line number Diff line number Diff line Loading @@ -384,70 +384,6 @@ static void efx_remove_nic(struct efx_nic *efx) efx->type->remove(efx); } static int efx_probe_filters(struct efx_nic *efx) { int rc; init_rwsem(&efx->filter_sem); mutex_lock(&efx->mac_lock); down_write(&efx->filter_sem); rc = efx->type->filter_table_probe(efx); if (rc) goto out_unlock; #ifdef CONFIG_RFS_ACCEL if (efx->type->offload_features & NETIF_F_NTUPLE) { struct efx_channel *channel; int i, success = 1; efx_for_each_channel(channel, efx) { channel->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters, sizeof(*channel->rps_flow_id), GFP_KERNEL); if (!channel->rps_flow_id) success = 0; else for (i = 0; i < efx->type->max_rx_ip_filters; ++i) channel->rps_flow_id[i] = RPS_FLOW_ID_INVALID; channel->rfs_expire_index = 0; channel->rfs_filter_count = 0; } if (!success) { efx_for_each_channel(channel, efx) kfree(channel->rps_flow_id); efx->type->filter_table_remove(efx); rc = -ENOMEM; goto out_unlock; } } #endif out_unlock: up_write(&efx->filter_sem); mutex_unlock(&efx->mac_lock); return rc; } static void efx_remove_filters(struct efx_nic *efx) { #ifdef CONFIG_RFS_ACCEL struct efx_channel *channel; efx_for_each_channel(channel, efx) { cancel_delayed_work_sync(&channel->filter_work); kfree(channel->rps_flow_id); } #endif down_write(&efx->filter_sem); efx->type->filter_table_remove(efx); up_write(&efx->filter_sem); } /************************************************************************** * * NIC startup/shutdown Loading Loading @@ -1109,142 +1045,6 @@ void efx_update_sw_stats(struct efx_nic *efx, u64 *stats) stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops); } bool efx_filter_spec_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right) { if ((left->match_flags ^ right->match_flags) | ((left->flags ^ right->flags) & (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX))) return false; return memcmp(&left->outer_vid, &right->outer_vid, sizeof(struct efx_filter_spec) - offsetof(struct efx_filter_spec, outer_vid)) == 0; } u32 efx_filter_spec_hash(const struct efx_filter_spec *spec) { BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3); return jhash2((const u32 *)&spec->outer_vid, (sizeof(struct efx_filter_spec) - offsetof(struct efx_filter_spec, outer_vid)) / 4, 0); } #ifdef CONFIG_RFS_ACCEL bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx, bool *force) { if (rule->filter_id == EFX_ARFS_FILTER_ID_PENDING) { /* ARFS is currently updating this entry, leave it */ return false; } if (rule->filter_id == EFX_ARFS_FILTER_ID_ERROR) { /* ARFS tried and failed to update this, so it's probably out * of date. Remove the filter and the ARFS rule entry. */ rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING; *force = true; return true; } else if (WARN_ON(rule->filter_id != filter_idx)) { /* can't happen */ /* ARFS has moved on, so old filter is not needed. Since we did * not mark the rule with EFX_ARFS_FILTER_ID_REMOVING, it will * not be removed by efx_rps_hash_del() subsequently. */ *force = true; return true; } /* Remove it iff ARFS wants to. */ return true; } static struct hlist_head *efx_rps_hash_bucket(struct efx_nic *efx, const struct efx_filter_spec *spec) { u32 hash = efx_filter_spec_hash(spec); lockdep_assert_held(&efx->rps_hash_lock); if (!efx->rps_hash_table) return NULL; return &efx->rps_hash_table[hash % EFX_ARFS_HASH_TABLE_SIZE]; } struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx, const struct efx_filter_spec *spec) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (!head) return NULL; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) return rule; } return NULL; } struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx, const struct efx_filter_spec *spec, bool *new) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (!head) return NULL; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) { *new = false; return rule; } } rule = kmalloc(sizeof(*rule), GFP_ATOMIC); *new = true; if (rule) { memcpy(&rule->spec, spec, sizeof(rule->spec)); hlist_add_head(&rule->node, head); } return rule; } void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec) { struct efx_arfs_rule *rule; struct hlist_head *head; struct hlist_node *node; head = efx_rps_hash_bucket(efx, spec); if (WARN_ON(!head)) return; hlist_for_each(node, head) { rule = container_of(node, struct efx_arfs_rule, node); if (efx_filter_spec_equal(spec, &rule->spec)) { /* Someone already reused the entry. We know that if * this check doesn't fire (i.e. filter_id == REMOVING) * then the REMOVING mark was put there by our caller, * because caller is holding a lock on filter table and * only holders of that lock set REMOVING. */ if (rule->filter_id != EFX_ARFS_FILTER_ID_REMOVING) return; hlist_del(node); kfree(rule); return; } } /* We didn't find it. */ WARN_ON(1); } #endif /************************************************************************** * * PCI interface Loading
drivers/net/ethernet/sfc/efx.h +1 −23 Original line number Diff line number Diff line Loading @@ -169,33 +169,11 @@ static inline void efx_filter_rfs_expire(struct work_struct *data) static inline void efx_filter_rfs_expire(struct work_struct *data) {} #define efx_filter_rfs_enabled() 0 #endif bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec); bool efx_filter_spec_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right); u32 efx_filter_spec_hash(const struct efx_filter_spec *spec); #ifdef CONFIG_RFS_ACCEL bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx, bool *force); struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx, const struct efx_filter_spec *spec); /* @new is written to indicate if entry was newly added (true) or if an old * entry was found and returned (false). */ struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx, const struct efx_filter_spec *spec, bool *new); void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec); #endif /* RSS contexts */ static inline bool efx_rss_active(struct efx_rss_context *ctx) { return ctx->context_id != EFX_EF10_RSS_CONTEXT_INVALID; return ctx->context_id != EFX_MCDI_RSS_CONTEXT_INVALID; } /* Ethtool support */ Loading
drivers/net/ethernet/sfc/ethtool.c +1 −1 Original line number Diff line number Diff line Loading @@ -1020,7 +1020,7 @@ static int efx_ethtool_set_rxfh_context(struct net_device *net_dev, rc = -ENOMEM; goto out_unlock; } ctx->context_id = EFX_EF10_RSS_CONTEXT_INVALID; ctx->context_id = EFX_MCDI_RSS_CONTEXT_INVALID; /* Initialise indir table and key to defaults */ efx_set_default_rx_indir_table(efx, ctx); netdev_rss_key_fill(ctx->rx_hash_key, sizeof(ctx->rx_hash_key)); Loading
drivers/net/ethernet/sfc/net_driver.h +3 −3 Original line number Diff line number Diff line Loading @@ -744,13 +744,13 @@ union efx_multicast_hash { struct vfdi_status; /* The reserved RSS context value */ #define EFX_EF10_RSS_CONTEXT_INVALID 0xffffffff #define EFX_MCDI_RSS_CONTEXT_INVALID 0xffffffff /** * struct efx_rss_context - A user-defined RSS context for filtering * @list: node of linked list on which this struct is stored * @context_id: the RSS_CONTEXT_ID returned by MC firmware, or * %EFX_EF10_RSS_CONTEXT_INVALID if this context is not present on the NIC. * For Siena, 0 if RSS is active, else %EFX_EF10_RSS_CONTEXT_INVALID. * %EFX_MCDI_RSS_CONTEXT_INVALID if this context is not present on the NIC. * For Siena, 0 if RSS is active, else %EFX_MCDI_RSS_CONTEXT_INVALID. * @user_id: the rss_context ID exposed to userspace over ethtool. * @rx_hash_udp_4tuple: UDP 4-tuple hashing enabled * @rx_hash_key: Toeplitz hash key for this RSS context Loading