提交 9b1b31d5 编写于 作者: D David S. Miller

Merge branch 'sfc-remove-nic_data-usage-in-common-code'

Edward Cree says:

====================
sfc: remove nic_data usage in common code

efx->nic_data should only be used from NIC-specific code (i.e. nic_type
 functions and things they call), in files like ef10[_sriov].c and
 siena.c.  This series refactors several nic_data usages from common
 code (mainly in mcdi_filters.c) into nic_type functions, in preparation
 for the upcoming ef100 driver which will use those functions but have
 its own struct layout for efx->nic_data distinct from ef10's.
After this series, one nic_data usage (in ptp.c) remains; it wasn't
 clear to me how to fix it, and ef100 devices don't yet have PTP support
 (so the initial ef100 driver will not call that code).
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -553,7 +553,7 @@ static int efx_ef10_probe(struct efx_nic *efx) ...@@ -553,7 +553,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;
nic_data->vport_id = EVB_PORT_ID_ASSIGNED; efx->vport_id = EVB_PORT_ID_ASSIGNED;
/* In case we're recovering from a crash (kexec), we want to /* In case we're recovering from a crash (kexec), we want to
* cancel any outstanding request by the previous user of this * cancel any outstanding request by the previous user of this
...@@ -1281,13 +1281,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx) ...@@ -1281,13 +1281,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
nic_data->must_check_datapath_caps = false; nic_data->must_check_datapath_caps = false;
} }
if (nic_data->must_realloc_vis) { if (efx->must_realloc_vis) {
/* We cannot let the number of VIs change now */ /* We cannot let the number of VIs change now */
rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis, rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis,
nic_data->n_allocated_vis); nic_data->n_allocated_vis);
if (rc) if (rc)
return rc; return rc;
nic_data->must_realloc_vis = false; efx->must_realloc_vis = false;
} }
if (nic_data->must_restore_piobufs && nic_data->n_piobufs) { if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
...@@ -1326,16 +1326,15 @@ static void efx_ef10_table_reset_mc_allocations(struct efx_nic *efx) ...@@ -1326,16 +1326,15 @@ static void efx_ef10_table_reset_mc_allocations(struct efx_nic *efx)
#endif #endif
/* All our allocations have been reset */ /* All our allocations have been reset */
nic_data->must_realloc_vis = true; efx->must_realloc_vis = true;
nic_data->must_restore_rss_contexts = true; efx_mcdi_filter_table_reset_mc_allocations(efx);
nic_data->must_restore_filters = true;
nic_data->must_restore_piobufs = true; nic_data->must_restore_piobufs = true;
efx_ef10_forget_old_piobufs(efx); efx_ef10_forget_old_piobufs(efx);
efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;
/* Driver-created vswitches and vports must be re-created */ /* Driver-created vswitches and vports must be re-created */
nic_data->must_probe_vswitching = true; nic_data->must_probe_vswitching = true;
nic_data->vport_id = EVB_PORT_ID_ASSIGNED; efx->vport_id = EVB_PORT_ID_ASSIGNED;
#ifdef CONFIG_SFC_SRIOV #ifdef CONFIG_SFC_SRIOV
if (nic_data->vf) if (nic_data->vf)
for (i = 0; i < efx->vf_count; i++) for (i = 0; i < efx->vf_count; i++)
...@@ -2389,6 +2388,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue) ...@@ -2389,6 +2388,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
} }
} }
static int efx_ef10_probe_multicast_chaining(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
unsigned int enabled, implemented;
bool want_workaround_26807;
int rc;
rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
if (rc == -ENOSYS) {
/* GET_WORKAROUNDS was implemented before this workaround,
* thus it must be unavailable in this firmware.
*/
nic_data->workaround_26807 = false;
return 0;
}
if (rc)
return rc;
want_workaround_26807 =
implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807;
nic_data->workaround_26807 =
!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);
if (want_workaround_26807 && !nic_data->workaround_26807) {
unsigned int flags;
rc = efx_mcdi_set_workaround(efx,
MC_CMD_WORKAROUND_BUG26807,
true, &flags);
if (!rc) {
if (flags &
1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
netif_info(efx, drv, efx->net_dev,
"other functions on NIC have been reset\n");
/* With MCFW v4.6.x and earlier, the
* boot count will have incremented,
* so re-read the warm_boot_count
* value now to ensure this function
* doesn't think it has changed next
* time it checks.
*/
rc = efx_ef10_get_warm_boot_count(efx);
if (rc >= 0) {
nic_data->warm_boot_count = rc;
rc = 0;
}
}
nic_data->workaround_26807 = true;
} else if (rc == -EPERM) {
rc = 0;
}
}
return rc;
}
static int efx_ef10_filter_table_probe(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
int rc = efx_ef10_probe_multicast_chaining(efx);
struct efx_mcdi_filter_vlan *vlan;
if (rc)
return rc;
rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807);
if (rc)
return rc;
list_for_each_entry(vlan, &nic_data->vlan_list, list) {
rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
if (rc)
goto fail_add_vlan;
}
return 0;
fail_add_vlan:
efx_mcdi_filter_table_remove(efx);
return rc;
}
/* This creates an entry in the RX descriptor queue */ /* This creates an entry in the RX descriptor queue */
static inline void static inline void
efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index) efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
...@@ -2464,75 +2543,14 @@ static int efx_ef10_ev_init(struct efx_channel *channel) ...@@ -2464,75 +2543,14 @@ static int efx_ef10_ev_init(struct efx_channel *channel)
{ {
struct efx_nic *efx = channel->efx; struct efx_nic *efx = channel->efx;
struct efx_ef10_nic_data *nic_data; struct efx_ef10_nic_data *nic_data;
unsigned int enabled, implemented;
bool use_v2, cut_thru; bool use_v2, cut_thru;
int rc;
nic_data = efx->nic_data; nic_data = efx->nic_data;
use_v2 = nic_data->datapath_caps2 & use_v2 = nic_data->datapath_caps2 &
1 << MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN; 1 << MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN;
cut_thru = !(nic_data->datapath_caps & cut_thru = !(nic_data->datapath_caps &
1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN); 1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN);
rc = efx_mcdi_ev_init(channel, cut_thru, use_v2); return efx_mcdi_ev_init(channel, cut_thru, use_v2);
/* IRQ return is ignored */
if (channel->channel || rc)
return rc;
/* Successfully created event queue on channel 0 */
rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
if (rc == -ENOSYS) {
/* GET_WORKAROUNDS was implemented before this workaround,
* thus it must be unavailable in this firmware.
*/
nic_data->workaround_26807 = false;
rc = 0;
} else if (rc) {
goto fail;
} else {
nic_data->workaround_26807 =
!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);
if (implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807 &&
!nic_data->workaround_26807) {
unsigned int flags;
rc = efx_mcdi_set_workaround(efx,
MC_CMD_WORKAROUND_BUG26807,
true, &flags);
if (!rc) {
if (flags &
1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
netif_info(efx, drv, efx->net_dev,
"other functions on NIC have been reset\n");
/* With MCFW v4.6.x and earlier, the
* boot count will have incremented,
* so re-read the warm_boot_count
* value now to ensure this function
* doesn't think it has changed next
* time it checks.
*/
rc = efx_ef10_get_warm_boot_count(efx);
if (rc >= 0) {
nic_data->warm_boot_count = rc;
rc = 0;
}
}
nic_data->workaround_26807 = true;
} else if (rc == -EPERM) {
rc = 0;
}
}
}
if (!rc)
return 0;
fail:
efx_mcdi_ev_fini(channel);
return rc;
} }
static void efx_ef10_handle_rx_wrong_queue(struct efx_rx_queue *rx_queue, static void efx_ef10_handle_rx_wrong_queue(struct efx_rx_queue *rx_queue,
...@@ -3100,16 +3118,15 @@ void efx_ef10_handle_drain_event(struct efx_nic *efx) ...@@ -3100,16 +3118,15 @@ void efx_ef10_handle_drain_event(struct efx_nic *efx)
static int efx_ef10_fini_dmaq(struct efx_nic *efx) static int efx_ef10_fini_dmaq(struct efx_nic *efx)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data;
struct efx_channel *channel;
struct efx_tx_queue *tx_queue; struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue; struct efx_rx_queue *rx_queue;
struct efx_channel *channel;
int pending; int pending;
/* If the MC has just rebooted, the TX/RX queues will have already been /* If the MC has just rebooted, the TX/RX queues will have already been
* torn down, but efx->active_queues needs to be set to zero. * torn down, but efx->active_queues needs to be set to zero.
*/ */
if (nic_data->must_realloc_vis) { if (efx->must_realloc_vis) {
atomic_set(&efx->active_queues, 0); atomic_set(&efx->active_queues, 0);
return 0; return 0;
} }
...@@ -3158,22 +3175,22 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) ...@@ -3158,22 +3175,22 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
efx_mcdi_filter_table_remove(efx); efx_mcdi_filter_table_remove(efx);
up_write(&efx->filter_sem); up_write(&efx->filter_sem);
rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id); rc = efx_ef10_vadaptor_free(efx, efx->vport_id);
if (rc) if (rc)
goto restore_filters; goto restore_filters;
ether_addr_copy(mac_old, nic_data->vport_mac); ether_addr_copy(mac_old, nic_data->vport_mac);
rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id, rc = efx_ef10_vport_del_mac(efx, efx->vport_id,
nic_data->vport_mac); nic_data->vport_mac);
if (rc) if (rc)
goto restore_vadaptor; goto restore_vadaptor;
rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, rc = efx_ef10_vport_add_mac(efx, efx->vport_id,
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
if (!rc) { if (!rc) {
ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr); ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
} else { } else {
rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old); rc2 = efx_ef10_vport_add_mac(efx, efx->vport_id, mac_old);
if (rc2) { if (rc2) {
/* Failed to add original MAC, so clear vport_mac */ /* Failed to add original MAC, so clear vport_mac */
eth_zero_addr(nic_data->vport_mac); eth_zero_addr(nic_data->vport_mac);
...@@ -3182,12 +3199,12 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) ...@@ -3182,12 +3199,12 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
} }
restore_vadaptor: restore_vadaptor:
rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); rc2 = efx_ef10_vadaptor_alloc(efx, efx->vport_id);
if (rc2) if (rc2)
goto reset_nic; goto reset_nic;
restore_filters: restore_filters:
down_write(&efx->filter_sem); down_write(&efx->filter_sem);
rc2 = efx_mcdi_filter_table_probe(efx); rc2 = efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem); up_write(&efx->filter_sem);
if (rc2) if (rc2)
goto reset_nic; goto reset_nic;
...@@ -3225,11 +3242,11 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) ...@@ -3225,11 +3242,11 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR), ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID, MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
nic_data->vport_id); efx->vport_id);
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf, rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
sizeof(inbuf), NULL, 0, NULL); sizeof(inbuf), NULL, 0, NULL);
efx_mcdi_filter_table_probe(efx); efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem); up_write(&efx->filter_sem);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
...@@ -3961,6 +3978,35 @@ static int efx_ef10_udp_tnl_del_port(struct efx_nic *efx, ...@@ -3961,6 +3978,35 @@ static int efx_ef10_udp_tnl_del_port(struct efx_nic *efx,
return rc; return rc;
} }
/* EF10 may have multiple datapath firmware variants within a
* single version. Report which variants are running.
*/
static size_t efx_ef10_print_additional_fwver(struct efx_nic *efx, char *buf,
size_t len)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
return scnprintf(buf, len, " rx%x tx%x",
nic_data->rx_dpcpu_fw_id,
nic_data->tx_dpcpu_fw_id);
}
static unsigned int ef10_check_caps(const struct efx_nic *efx,
u8 flag,
u32 offset)
{
const struct efx_ef10_nic_data *nic_data = efx->nic_data;
switch (offset) {
case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS1_OFST):
return nic_data->datapath_caps & BIT_ULL(flag);
case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS2_OFST):
return nic_data->datapath_caps2 & BIT_ULL(flag);
default:
return 0;
}
}
#define EF10_OFFLOAD_FEATURES \ #define EF10_OFFLOAD_FEATURES \
(NETIF_F_IP_CSUM | \ (NETIF_F_IP_CSUM | \
NETIF_F_HW_VLAN_CTAG_FILTER | \ NETIF_F_HW_VLAN_CTAG_FILTER | \
...@@ -4027,7 +4073,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { ...@@ -4027,7 +4073,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.ev_process = efx_ef10_ev_process, .ev_process = efx_ef10_ev_process,
.ev_read_ack = efx_ef10_ev_read_ack, .ev_read_ack = efx_ef10_ev_read_ack,
.ev_test_generate = efx_ef10_ev_test_generate, .ev_test_generate = efx_ef10_ev_test_generate,
.filter_table_probe = efx_mcdi_filter_table_probe, .filter_table_probe = efx_ef10_filter_table_probe,
.filter_table_restore = efx_mcdi_filter_table_restore, .filter_table_restore = efx_mcdi_filter_table_restore,
.filter_table_remove = efx_mcdi_filter_table_remove, .filter_table_remove = efx_mcdi_filter_table_remove,
.filter_update_rx_scatter = efx_mcdi_update_rx_scatter, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
...@@ -4073,6 +4119,8 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { ...@@ -4073,6 +4119,8 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
1 << HWTSTAMP_FILTER_ALL, 1 << HWTSTAMP_FILTER_ALL,
.rx_hash_key_size = 40, .rx_hash_key_size = 40,
.check_caps = ef10_check_caps,
.print_additional_fwver = efx_ef10_print_additional_fwver,
}; };
const struct efx_nic_type efx_hunt_a0_nic_type = { const struct efx_nic_type efx_hunt_a0_nic_type = {
...@@ -4139,7 +4187,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { ...@@ -4139,7 +4187,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.ev_process = efx_ef10_ev_process, .ev_process = efx_ef10_ev_process,
.ev_read_ack = efx_ef10_ev_read_ack, .ev_read_ack = efx_ef10_ev_read_ack,
.ev_test_generate = efx_ef10_ev_test_generate, .ev_test_generate = efx_ef10_ev_test_generate,
.filter_table_probe = efx_mcdi_filter_table_probe, .filter_table_probe = efx_ef10_filter_table_probe,
.filter_table_restore = efx_mcdi_filter_table_restore, .filter_table_restore = efx_mcdi_filter_table_restore,
.filter_table_remove = efx_mcdi_filter_table_remove, .filter_table_remove = efx_mcdi_filter_table_remove,
.filter_update_rx_scatter = efx_mcdi_update_rx_scatter, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
...@@ -4208,4 +4256,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { ...@@ -4208,4 +4256,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
1 << HWTSTAMP_FILTER_ALL, 1 << HWTSTAMP_FILTER_ALL,
.rx_hash_key_size = 40, .rx_hash_key_size = 40,
.check_caps = ef10_check_caps,
.print_additional_fwver = efx_ef10_print_additional_fwver,
}; };
...@@ -232,15 +232,14 @@ static int efx_ef10_sriov_restore_vf_vswitching(struct efx_nic *efx) ...@@ -232,15 +232,14 @@ static int efx_ef10_sriov_restore_vf_vswitching(struct efx_nic *efx)
static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx) static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data;
u32 port_flags; u32 port_flags;
int rc; int rc;
rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); rc = efx_ef10_vadaptor_alloc(efx, efx->vport_id);
if (rc) if (rc)
goto fail_vadaptor_alloc; goto fail_vadaptor_alloc;
rc = efx_ef10_vadaptor_query(efx, nic_data->vport_id, rc = efx_ef10_vadaptor_query(efx, efx->vport_id,
&port_flags, NULL, NULL); &port_flags, NULL, NULL);
if (rc) if (rc)
goto fail_vadaptor_query; goto fail_vadaptor_query;
...@@ -281,11 +280,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx) ...@@ -281,11 +280,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)
rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED, rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL, MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
EFX_EF10_NO_VLAN, &nic_data->vport_id); EFX_EF10_NO_VLAN, &efx->vport_id);
if (rc) if (rc)
goto fail2; goto fail2;
rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, net_dev->dev_addr); rc = efx_ef10_vport_add_mac(efx, efx->vport_id, net_dev->dev_addr);
if (rc) if (rc)
goto fail3; goto fail3;
ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr); ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr);
...@@ -296,11 +295,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx) ...@@ -296,11 +295,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)
return 0; return 0;
fail4: fail4:
efx_ef10_vport_del_mac(efx, nic_data->vport_id, nic_data->vport_mac); efx_ef10_vport_del_mac(efx, efx->vport_id, nic_data->vport_mac);
eth_zero_addr(nic_data->vport_mac); eth_zero_addr(nic_data->vport_mac);
fail3: fail3:
efx_ef10_vport_free(efx, nic_data->vport_id); efx_ef10_vport_free(efx, efx->vport_id);
nic_data->vport_id = EVB_PORT_ID_ASSIGNED; efx->vport_id = EVB_PORT_ID_ASSIGNED;
fail2: fail2:
efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED); efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED);
fail1: fail1:
...@@ -355,22 +354,22 @@ void efx_ef10_vswitching_remove_pf(struct efx_nic *efx) ...@@ -355,22 +354,22 @@ void efx_ef10_vswitching_remove_pf(struct efx_nic *efx)
efx_ef10_sriov_free_vf_vswitching(efx); efx_ef10_sriov_free_vf_vswitching(efx);
efx_ef10_vadaptor_free(efx, nic_data->vport_id); efx_ef10_vadaptor_free(efx, efx->vport_id);
if (nic_data->vport_id == EVB_PORT_ID_ASSIGNED) if (efx->vport_id == EVB_PORT_ID_ASSIGNED)
return; /* No vswitch was ever created */ return; /* No vswitch was ever created */
if (!is_zero_ether_addr(nic_data->vport_mac)) { if (!is_zero_ether_addr(nic_data->vport_mac)) {
efx_ef10_vport_del_mac(efx, nic_data->vport_id, efx_ef10_vport_del_mac(efx, efx->vport_id,
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
eth_zero_addr(nic_data->vport_mac); eth_zero_addr(nic_data->vport_mac);
} }
efx_ef10_vport_free(efx, nic_data->vport_id); efx_ef10_vport_free(efx, efx->vport_id);
nic_data->vport_id = EVB_PORT_ID_ASSIGNED; efx->vport_id = EVB_PORT_ID_ASSIGNED;
/* Only free the vswitch if no VFs are assigned */ /* Only free the vswitch if no VFs are assigned */
if (!pci_vfs_assigned(efx->pci_dev)) if (!pci_vfs_assigned(efx->pci_dev))
efx_ef10_vswitch_free(efx, nic_data->vport_id); efx_ef10_vswitch_free(efx, efx->vport_id);
} }
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx) void efx_ef10_vswitching_remove_vf(struct efx_nic *efx)
......
...@@ -1425,15 +1425,9 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) ...@@ -1425,15 +1425,9 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[2]),
le16_to_cpu(ver_words[3])); le16_to_cpu(ver_words[3]));
/* EF10 may have multiple datapath firmware variants within a if (efx->type->print_additional_fwver)
* single version. Report which variants are running. offset += efx->type->print_additional_fwver(efx, buf + offset,
*/ len - offset);
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
struct efx_ef10_nic_data *nic_data = efx->nic_data;
offset += scnprintf(buf + offset, len - offset, " rx%x tx%x",
nic_data->rx_dpcpu_fw_id,
nic_data->tx_dpcpu_fw_id);
/* It's theoretically possible for the string to exceed 31 /* It's theoretically possible for the string to exceed 31
* characters, though in practice the first three version * characters, though in practice the first three version
...@@ -1441,7 +1435,6 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) ...@@ -1441,7 +1435,6 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
*/ */
if (WARN_ON(offset >= len)) if (WARN_ON(offset >= len))
buf[0] = 0; buf[0] = 0;
}
return; return;
......
...@@ -326,6 +326,18 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); ...@@ -326,6 +326,18 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define MCDI_EVENT_FIELD(_ev, _field) \ #define MCDI_EVENT_FIELD(_ev, _field) \
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field) EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
#define MCDI_CAPABILITY(field) \
MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _LBN
#define MCDI_CAPABILITY_OFST(field) \
MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _OFST
/* field is FLAGS1 or FLAGS2 */
#define efx_has_cap(efx, flag, field) \
efx->type->check_caps(efx, \
MCDI_CAPABILITY(flag), \
MCDI_CAPABILITY_OFST(field))
void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len); void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
u16 *fw_subtype_list, u32 *capabilities); u16 *fw_subtype_list, u32 *capabilities);
......
...@@ -186,7 +186,6 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx, ...@@ -186,7 +186,6 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
struct efx_rss_context *ctx, struct efx_rss_context *ctx,
bool replacing) bool replacing)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data;
u32 flags = spec->flags; u32 flags = spec->flags;
memset(inbuf, 0, MC_CMD_FILTER_OP_EXT_IN_LEN); memset(inbuf, 0, MC_CMD_FILTER_OP_EXT_IN_LEN);
...@@ -211,7 +210,7 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx, ...@@ -211,7 +210,7 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
efx_mcdi_filter_push_prep_set_match_fields(efx, spec, inbuf); efx_mcdi_filter_push_prep_set_match_fields(efx, spec, inbuf);
} }
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, nic_data->vport_id); MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, efx->vport_id);
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST, MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST,
spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ? spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ?
MC_CMD_FILTER_OP_IN_RX_DEST_DROP : MC_CMD_FILTER_OP_IN_RX_DEST_DROP :
...@@ -332,7 +331,6 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx, ...@@ -332,7 +331,6 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
bool replace_equal) bool replace_equal)
{ {
DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT); DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
struct efx_ef10_nic_data *nic_data = efx->nic_data;
struct efx_mcdi_filter_table *table; struct efx_mcdi_filter_table *table;
struct efx_filter_spec *saved_spec; struct efx_filter_spec *saved_spec;
struct efx_rss_context *ctx = NULL; struct efx_rss_context *ctx = NULL;
...@@ -461,7 +459,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx, ...@@ -461,7 +459,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
rc = efx_mcdi_filter_push(efx, spec, &table->entry[ins_index].handle, rc = efx_mcdi_filter_push(efx, spec, &table->entry[ins_index].handle,
ctx, replacing); ctx, replacing);
if (rc == -EINVAL && nic_data->must_realloc_vis) if (rc == -EINVAL && efx->must_realloc_vis)
/* The MC rebooted under us, causing it to reject our filter /* The MC rebooted under us, causing it to reject our filter
* insertion as pointing to an invalid VI (spec->dmaq_id). * insertion as pointing to an invalid VI (spec->dmaq_id).
*/ */
...@@ -813,7 +811,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx, ...@@ -813,7 +811,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,
enum efx_encap_type encap_type, enum efx_encap_type encap_type,
bool multicast, bool rollback) bool multicast, bool rollback)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data; struct efx_mcdi_filter_table *table = efx->filter_state;
enum efx_filter_flags filter_flags; enum efx_filter_flags filter_flags;
struct efx_filter_spec spec; struct efx_filter_spec spec;
u8 baddr[ETH_ALEN]; u8 baddr[ETH_ALEN];
...@@ -830,8 +828,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx, ...@@ -830,8 +828,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,
efx_filter_set_uc_def(&spec); efx_filter_set_uc_def(&spec);
if (encap_type) { if (encap_type) {
if (nic_data->datapath_caps & if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1))
(1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))
efx_filter_set_encap_type(&spec, encap_type); efx_filter_set_encap_type(&spec, encap_type);
else else
/* /*
...@@ -899,7 +896,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx, ...@@ -899,7 +896,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx,
EFX_WARN_ON_PARANOID(*id != EFX_EF10_FILTER_ID_INVALID); EFX_WARN_ON_PARANOID(*id != EFX_EF10_FILTER_ID_INVALID);
*id = efx_mcdi_filter_get_unsafe_id(rc); *id = efx_mcdi_filter_get_unsafe_id(rc);
if (!nic_data->workaround_26807 && !encap_type) { if (!table->mc_chaining && !encap_type) {
/* Also need an Ethernet broadcast filter */ /* Also need an Ethernet broadcast filter */
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
filter_flags, 0); filter_flags, 0);
...@@ -965,7 +962,6 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx, ...@@ -965,7 +962,6 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
struct efx_mcdi_filter_vlan *vlan) struct efx_mcdi_filter_vlan *vlan)
{ {
struct efx_mcdi_filter_table *table = efx->filter_state; struct efx_mcdi_filter_table *table = efx->filter_state;
struct efx_ef10_nic_data *nic_data = efx->nic_data;
/* /*
* Do not install unspecified VID if VLAN filtering is enabled. * Do not install unspecified VID if VLAN filtering is enabled.
...@@ -1012,11 +1008,10 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx, ...@@ -1012,11 +1008,10 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
* If changing promiscuous state with cascaded multicast filters, remove * If changing promiscuous state with cascaded multicast filters, remove
* old filters first, so that packets are dropped rather than duplicated * old filters first, so that packets are dropped rather than duplicated
*/ */
if (nic_data->workaround_26807 && if (table->mc_chaining && table->mc_promisc_last != table->mc_promisc)
table->mc_promisc_last != table->mc_promisc)
efx_mcdi_filter_remove_old(efx); efx_mcdi_filter_remove_old(efx);
if (table->mc_promisc) { if (table->mc_promisc) {
if (nic_data->workaround_26807) { if (table->mc_chaining) {
/* /*
* If we failed to insert promiscuous filters, rollback * If we failed to insert promiscuous filters, rollback
* and fall back to individual multicast filters * and fall back to individual multicast filters
...@@ -1051,7 +1046,7 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx, ...@@ -1051,7 +1046,7 @@ static void efx_mcdi_filter_vlan_sync_rx_mode(struct efx_nic *efx,
*/ */
if (efx_mcdi_filter_insert_addr_list(efx, vlan, true, true)) { if (efx_mcdi_filter_insert_addr_list(efx, vlan, true, true)) {
/* Changing promisc state, so remove old filters */ /* Changing promisc state, so remove old filters */
if (nic_data->workaround_26807) if (table->mc_chaining)
efx_mcdi_filter_remove_old(efx); efx_mcdi_filter_remove_old(efx);
if (efx_mcdi_filter_insert_def(efx, vlan, if (efx_mcdi_filter_insert_def(efx, vlan,
EFX_ENCAP_TYPE_NONE, EFX_ENCAP_TYPE_NONE,
...@@ -1288,12 +1283,10 @@ efx_mcdi_filter_table_probe_matches(struct efx_nic *efx, ...@@ -1288,12 +1283,10 @@ efx_mcdi_filter_table_probe_matches(struct efx_nic *efx,
return 0; return 0;
} }
int efx_mcdi_filter_table_probe(struct efx_nic *efx) int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data;
struct net_device *net_dev = efx->net_dev; struct net_device *net_dev = efx->net_dev;
struct efx_mcdi_filter_table *table; struct efx_mcdi_filter_table *table;
struct efx_mcdi_filter_vlan *vlan;
int rc; int rc;
if (!efx_rwsem_assert_write_locked(&efx->filter_sem)) if (!efx_rwsem_assert_write_locked(&efx->filter_sem))
...@@ -1306,12 +1299,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx) ...@@ -1306,12 +1299,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx)
if (!table) if (!table)
return -ENOMEM; return -ENOMEM;
table->mc_chaining = multicast_chaining;
table->rx_match_count = 0; table->rx_match_count = 0;
rc = efx_mcdi_filter_table_probe_matches(efx, table, false); rc = efx_mcdi_filter_table_probe_matches(efx, table, false);
if (rc) if (rc)
goto fail; goto fail;
if (nic_data->datapath_caps & if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1))
(1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))
rc = efx_mcdi_filter_table_probe_matches(efx, table, true); rc = efx_mcdi_filter_table_probe_matches(efx, table, true);
if (rc) if (rc)
goto fail; goto fail;
...@@ -1342,22 +1335,22 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx) ...@@ -1342,22 +1335,22 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx)
efx->filter_state = table; efx->filter_state = table;
list_for_each_entry(vlan, &nic_data->vlan_list, list) {
rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
if (rc)
goto fail_add_vlan;
}
return 0; return 0;
fail_add_vlan:
efx_mcdi_filter_cleanup_vlans(efx);
efx->filter_state = NULL;
fail: fail:
kfree(table); kfree(table);
return rc; return rc;
} }
void efx_mcdi_filter_table_reset_mc_allocations(struct efx_nic *efx)
{
struct efx_mcdi_filter_table *table = efx->filter_state;
if (table) {
table->must_restore_filters = true;
table->must_restore_rss_contexts = true;
}
}
/* /*
* Caller must hold efx->filter_sem for read if race against * Caller must hold efx->filter_sem for read if race against
* efx_mcdi_filter_table_remove() is possible * efx_mcdi_filter_table_remove() is possible
...@@ -1365,7 +1358,6 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx) ...@@ -1365,7 +1358,6 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx)
void efx_mcdi_filter_table_restore(struct efx_nic *efx) void efx_mcdi_filter_table_restore(struct efx_nic *efx)
{ {
struct efx_mcdi_filter_table *table = efx->filter_state; struct efx_mcdi_filter_table *table = efx->filter_state;
struct efx_ef10_nic_data *nic_data = efx->nic_data;
unsigned int invalid_filters = 0, failed = 0; unsigned int invalid_filters = 0, failed = 0;
struct efx_mcdi_filter_vlan *vlan; struct efx_mcdi_filter_vlan *vlan;
struct efx_filter_spec *spec; struct efx_filter_spec *spec;
...@@ -1377,7 +1369,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx) ...@@ -1377,7 +1369,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx)
WARN_ON(!rwsem_is_locked(&efx->filter_sem)); WARN_ON(!rwsem_is_locked(&efx->filter_sem));
if (!nic_data->must_restore_filters) if (!table->must_restore_filters)
return; return;
if (!table) if (!table)
...@@ -1456,7 +1448,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx) ...@@ -1456,7 +1448,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx)
netif_err(efx, hw, efx->net_dev, netif_err(efx, hw, efx->net_dev,
"unable to restore %u filters\n", failed); "unable to restore %u filters\n", failed);
else else
nic_data->must_restore_filters = false; table->must_restore_filters = false;
} }
void efx_mcdi_filter_table_remove(struct efx_nic *efx) void efx_mcdi_filter_table_remove(struct efx_nic *efx)
...@@ -1921,7 +1913,6 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive ...@@ -1921,7 +1913,6 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
{ {
MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN); MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
struct efx_ef10_nic_data *nic_data = efx->nic_data;
size_t outlen; size_t outlen;
int rc; int rc;
u32 alloc_type = exclusive ? u32 alloc_type = exclusive ?
...@@ -1939,12 +1930,11 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive ...@@ -1939,12 +1930,11 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
return 0; return 0;
} }
if (nic_data->datapath_caps & if (efx_has_cap(efx, RX_RSS_LIMITED, FLAGS1))
1 << MC_CMD_GET_CAPABILITIES_OUT_RX_RSS_LIMITED_LBN)
return -EOPNOTSUPP; return -EOPNOTSUPP;
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID, MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
nic_data->vport_id); efx->vport_id);
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_TYPE, alloc_type); MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_TYPE, alloc_type);
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, rss_spread); MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, rss_spread);
...@@ -1961,8 +1951,7 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive ...@@ -1961,8 +1951,7 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive
if (context_size) if (context_size)
*context_size = rss_spread; *context_size = rss_spread;
if (nic_data->datapath_caps & if (efx_has_cap(efx, ADDITIONAL_RSS_MODES, FLAGS1))
1 << MC_CMD_GET_CAPABILITIES_OUT_ADDITIONAL_RSS_MODES_LBN)
efx_mcdi_set_rss_context_flags(efx, ctx); efx_mcdi_set_rss_context_flags(efx, ctx);
return 0; return 0;
...@@ -2030,14 +2019,14 @@ void efx_mcdi_rx_free_indir_table(struct efx_nic *efx) ...@@ -2030,14 +2019,14 @@ void efx_mcdi_rx_free_indir_table(struct efx_nic *efx)
static int efx_mcdi_filter_rx_push_shared_rss_config(struct efx_nic *efx, static int efx_mcdi_filter_rx_push_shared_rss_config(struct efx_nic *efx,
unsigned *context_size) unsigned *context_size)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data; struct efx_mcdi_filter_table *table = efx->filter_state;
int rc = efx_mcdi_filter_alloc_rss_context(efx, false, &efx->rss_context, int rc = efx_mcdi_filter_alloc_rss_context(efx, false, &efx->rss_context,
context_size); context_size);
if (rc != 0) if (rc != 0)
return rc; return rc;
nic_data->rx_rss_context_exclusive = false; table->rx_rss_context_exclusive = false;
efx_set_default_rx_indir_table(efx, &efx->rss_context); efx_set_default_rx_indir_table(efx, &efx->rss_context);
return 0; return 0;
} }
...@@ -2046,12 +2035,12 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx, ...@@ -2046,12 +2035,12 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx,
const u32 *rx_indir_table, const u32 *rx_indir_table,
const u8 *key) const u8 *key)
{ {
struct efx_mcdi_filter_table *table = efx->filter_state;
u32 old_rx_rss_context = efx->rss_context.context_id; u32 old_rx_rss_context = efx->rss_context.context_id;
struct efx_ef10_nic_data *nic_data = efx->nic_data;
int rc; int rc;
if (efx->rss_context.context_id == EFX_MCDI_RSS_CONTEXT_INVALID || if (efx->rss_context.context_id == EFX_MCDI_RSS_CONTEXT_INVALID ||
!nic_data->rx_rss_context_exclusive) { !table->rx_rss_context_exclusive) {
rc = efx_mcdi_filter_alloc_rss_context(efx, true, &efx->rss_context, rc = efx_mcdi_filter_alloc_rss_context(efx, true, &efx->rss_context,
NULL); NULL);
if (rc == -EOPNOTSUPP) if (rc == -EOPNOTSUPP)
...@@ -2068,7 +2057,7 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx, ...@@ -2068,7 +2057,7 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx,
if (efx->rss_context.context_id != old_rx_rss_context && if (efx->rss_context.context_id != old_rx_rss_context &&
old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID) old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID)
WARN_ON(efx_mcdi_filter_free_rss_context(efx, old_rx_rss_context) != 0); WARN_ON(efx_mcdi_filter_free_rss_context(efx, old_rx_rss_context) != 0);
nic_data->rx_rss_context_exclusive = true; table->rx_rss_context_exclusive = true;
if (rx_indir_table != efx->rss_context.rx_indir_table) if (rx_indir_table != efx->rss_context.rx_indir_table)
memcpy(efx->rss_context.rx_indir_table, rx_indir_table, memcpy(efx->rss_context.rx_indir_table, rx_indir_table,
sizeof(efx->rss_context.rx_indir_table)); sizeof(efx->rss_context.rx_indir_table));
...@@ -2182,13 +2171,13 @@ int efx_mcdi_rx_pull_rss_config(struct efx_nic *efx) ...@@ -2182,13 +2171,13 @@ int efx_mcdi_rx_pull_rss_config(struct efx_nic *efx)
void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx) void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data; struct efx_mcdi_filter_table *table = efx->filter_state;
struct efx_rss_context *ctx; struct efx_rss_context *ctx;
int rc; int rc;
WARN_ON(!mutex_is_locked(&efx->rss_lock)); WARN_ON(!mutex_is_locked(&efx->rss_lock));
if (!nic_data->must_restore_rss_contexts) if (!table->must_restore_rss_contexts)
return; return;
list_for_each_entry(ctx, &efx->rss_context.list, list) { list_for_each_entry(ctx, &efx->rss_context.list, list) {
...@@ -2204,7 +2193,7 @@ void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx) ...@@ -2204,7 +2193,7 @@ void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx)
"; RSS filters may fail to be applied\n", "; RSS filters may fail to be applied\n",
ctx->user_id, rc); ctx->user_id, rc);
} }
nic_data->must_restore_rss_contexts = false; table->must_restore_rss_contexts = false;
} }
int efx_mcdi_pf_rx_push_rss_config(struct efx_nic *efx, bool user, int efx_mcdi_pf_rx_push_rss_config(struct efx_nic *efx, bool user,
......
...@@ -55,6 +55,8 @@ struct efx_mcdi_filter_table { ...@@ -55,6 +55,8 @@ struct efx_mcdi_filter_table {
u32 rx_match_mcdi_flags[ u32 rx_match_mcdi_flags[
MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2]; MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2];
unsigned int rx_match_count; unsigned int rx_match_count;
/* Our RSS context is exclusive (as opposed to shared) */
bool rx_rss_context_exclusive;
struct rw_semaphore lock; /* Protects entries */ struct rw_semaphore lock; /* Protects entries */
struct { struct {
...@@ -75,14 +77,27 @@ struct efx_mcdi_filter_table { ...@@ -75,14 +77,27 @@ struct efx_mcdi_filter_table {
/* Whether in multicast promiscuous mode when last changed */ /* Whether in multicast promiscuous mode when last changed */
bool mc_promisc_last; bool mc_promisc_last;
bool mc_overflow; /* Too many MC addrs; should always imply mc_promisc */ bool mc_overflow; /* Too many MC addrs; should always imply mc_promisc */
/* RSS contexts have yet to be restored after MC reboot */
bool must_restore_rss_contexts;
/* filters have yet to be restored after MC reboot */
bool must_restore_filters;
/* Multicast filter chaining allows less-specific filters to receive
* multicast packets that matched more-specific filters. Early EF10
* firmware didn't support this (SF bug 26807); if mc_chaining == false
* then we still subscribe the dev_mc_list even when mc_promisc to
* prevent another VI stealing the traffic.
*/
bool mc_chaining;
bool vlan_filter; bool vlan_filter;
struct list_head vlan_list; struct list_head vlan_list;
}; };
int efx_mcdi_filter_table_probe(struct efx_nic *efx); int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining);
void efx_mcdi_filter_table_remove(struct efx_nic *efx); void efx_mcdi_filter_table_remove(struct efx_nic *efx);
void efx_mcdi_filter_table_restore(struct efx_nic *efx); void efx_mcdi_filter_table_restore(struct efx_nic *efx);
void efx_mcdi_filter_table_reset_mc_allocations(struct efx_nic *efx);
/* /*
* The filter table(s) are managed by firmware and we have write-only * The filter table(s) are managed by firmware and we have write-only
* access. When removing filters we must identify them to the * access. When removing filters we must identify them to the
......
...@@ -168,21 +168,18 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2) ...@@ -168,21 +168,18 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2)
size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE; size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE;
struct efx_channel *channel = tx_queue->channel; struct efx_channel *channel = tx_queue->channel;
struct efx_nic *efx = tx_queue->efx; struct efx_nic *efx = tx_queue->efx;
struct efx_ef10_nic_data *nic_data;
dma_addr_t dma_addr; dma_addr_t dma_addr;
size_t inlen; size_t inlen;
int rc, i; int rc, i;
BUILD_BUG_ON(MC_CMD_INIT_TXQ_OUT_LEN != 0); BUILD_BUG_ON(MC_CMD_INIT_TXQ_OUT_LEN != 0);
nic_data = efx->nic_data;
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_SIZE, tx_queue->ptr_mask + 1); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_SIZE, tx_queue->ptr_mask + 1);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_TARGET_EVQ, channel->channel); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_TARGET_EVQ, channel->channel);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_LABEL, tx_queue->queue); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_LABEL, tx_queue->queue);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_INSTANCE, tx_queue->queue); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_INSTANCE, tx_queue->queue);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_OWNER_ID, 0); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_OWNER_ID, 0);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_PORT_ID, nic_data->vport_id); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_PORT_ID, efx->vport_id);
dma_addr = tx_queue->txd.buf.dma_addr; dma_addr = tx_queue->txd.buf.dma_addr;
...@@ -276,7 +273,6 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue) ...@@ -276,7 +273,6 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue)
struct efx_channel *channel = efx_rx_queue_channel(rx_queue); struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE; size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE;
struct efx_nic *efx = rx_queue->efx; struct efx_nic *efx = rx_queue->efx;
struct efx_ef10_nic_data *nic_data = efx->nic_data;
dma_addr_t dma_addr; dma_addr_t dma_addr;
size_t inlen; size_t inlen;
int rc; int rc;
...@@ -295,7 +291,7 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue) ...@@ -295,7 +291,7 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue)
INIT_RXQ_IN_FLAG_PREFIX, 1, INIT_RXQ_IN_FLAG_PREFIX, 1,
INIT_RXQ_IN_FLAG_TIMESTAMP, 1); INIT_RXQ_IN_FLAG_TIMESTAMP, 1);
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0); MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0);
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, nic_data->vport_id); MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, efx->vport_id);
dma_addr = rx_queue->rxd.buf.dma_addr; dma_addr = rx_queue->rxd.buf.dma_addr;
......
...@@ -722,11 +722,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, ...@@ -722,11 +722,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx,
MAC_STATS_IN_PERIOD_MS, period); MAC_STATS_IN_PERIOD_MS, period);
MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) { if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
struct efx_ef10_nic_data *nic_data = efx->nic_data; MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, efx->vport_id);
MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, nic_data->vport_id);
}
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
NULL, 0, NULL); NULL, 0, NULL);
......
...@@ -887,8 +887,10 @@ struct efx_async_filter_insertion { ...@@ -887,8 +887,10 @@ struct efx_async_filter_insertion {
* @rss_context: Main RSS context. Its @list member is the head of the list of * @rss_context: Main RSS context. Its @list member is the head of the list of
* RSS contexts created by user requests * RSS contexts created by user requests
* @rss_lock: Protects custom RSS context software state in @rss_context.list * @rss_lock: Protects custom RSS context software state in @rss_context.list
* @vport_id: The function's vport ID, only relevant for PFs
* @int_error_count: Number of internal errors seen recently * @int_error_count: Number of internal errors seen recently
* @int_error_expire: Time at which error count will be expired * @int_error_expire: Time at which error count will be expired
* @must_realloc_vis: Flag: VIs have yet to be reallocated after MC reboot
* @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will * @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will
* acknowledge but do nothing else. * acknowledge but do nothing else.
* @irq_status: Interrupt status buffer * @irq_status: Interrupt status buffer
...@@ -1044,10 +1046,12 @@ struct efx_nic { ...@@ -1044,10 +1046,12 @@ struct efx_nic {
bool rx_scatter; bool rx_scatter;
struct efx_rss_context rss_context; struct efx_rss_context rss_context;
struct mutex rss_lock; struct mutex rss_lock;
u32 vport_id;
unsigned int_error_count; unsigned int_error_count;
unsigned long int_error_expire; unsigned long int_error_expire;
bool must_realloc_vis;
bool irq_soft_enabled; bool irq_soft_enabled;
struct efx_buffer irq_status; struct efx_buffer irq_status;
unsigned irq_zero_count; unsigned irq_zero_count;
...@@ -1292,6 +1296,7 @@ struct efx_udp_tunnel { ...@@ -1292,6 +1296,7 @@ struct efx_udp_tunnel {
* @udp_tnl_add_port: Add a UDP tunnel port * @udp_tnl_add_port: Add a UDP tunnel port
* @udp_tnl_has_port: Check if a port has been added as UDP tunnel * @udp_tnl_has_port: Check if a port has been added as UDP tunnel
* @udp_tnl_del_port: Remove a UDP tunnel port * @udp_tnl_del_port: Remove a UDP tunnel port
* @print_additional_fwver: Dump NIC-specific additional FW version info
* @revision: Hardware architecture revision * @revision: Hardware architecture revision
* @txd_ptr_tbl_base: TX descriptor ring base address * @txd_ptr_tbl_base: TX descriptor ring base address
* @rxd_ptr_tbl_base: RX descriptor ring base address * @rxd_ptr_tbl_base: RX descriptor ring base address
...@@ -1352,6 +1357,9 @@ struct efx_nic_type { ...@@ -1352,6 +1357,9 @@ struct efx_nic_type {
void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol);
int (*set_wol)(struct efx_nic *efx, u32 type); int (*set_wol)(struct efx_nic *efx, u32 type);
void (*resume_wol)(struct efx_nic *efx); void (*resume_wol)(struct efx_nic *efx);
unsigned int (*check_caps)(const struct efx_nic *efx,
u8 flag,
u32 offset);
int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests); int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests);
int (*test_nvram)(struct efx_nic *efx); int (*test_nvram)(struct efx_nic *efx);
void (*mcdi_request)(struct efx_nic *efx, void (*mcdi_request)(struct efx_nic *efx,
...@@ -1462,6 +1470,8 @@ struct efx_nic_type { ...@@ -1462,6 +1470,8 @@ struct efx_nic_type {
int (*udp_tnl_add_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl); int (*udp_tnl_add_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl);
bool (*udp_tnl_has_port)(struct efx_nic *efx, __be16 port); bool (*udp_tnl_has_port)(struct efx_nic *efx, __be16 port);
int (*udp_tnl_del_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl); int (*udp_tnl_del_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl);
size_t (*print_additional_fwver)(struct efx_nic *efx, char *buf,
size_t len);
int revision; int revision;
unsigned int txd_ptr_tbl_base; unsigned int txd_ptr_tbl_base;
......
...@@ -360,10 +360,6 @@ enum { ...@@ -360,10 +360,6 @@ enum {
* @warm_boot_count: Last seen MC warm boot count * @warm_boot_count: Last seen MC warm boot count
* @vi_base: Absolute index of first VI in this function * @vi_base: Absolute index of first VI in this function
* @n_allocated_vis: Number of VIs allocated to this function * @n_allocated_vis: Number of VIs allocated to this function
* @must_realloc_vis: Flag: VIs have yet to be reallocated after MC reboot
* @must_restore_rss_contexts: Flag: RSS contexts have yet to be restored after
* MC reboot
* @must_restore_filters: Flag: filters have yet to be restored after MC reboot
* @n_piobufs: Number of PIO buffers allocated to this function * @n_piobufs: Number of PIO buffers allocated to this function
* @wc_membase: Base address of write-combining mapping of the memory BAR * @wc_membase: Base address of write-combining mapping of the memory BAR
* @pio_write_base: Base address for writing PIO buffers * @pio_write_base: Base address for writing PIO buffers
...@@ -372,7 +368,6 @@ enum { ...@@ -372,7 +368,6 @@ enum {
* @piobuf_size: size of a single PIO buffer * @piobuf_size: size of a single PIO buffer
* @must_restore_piobufs: Flag: PIO buffers have yet to be restored after MC * @must_restore_piobufs: Flag: PIO buffers have yet to be restored after MC
* reboot * reboot
* @rx_rss_context_exclusive: Whether our RSS context is exclusive or shared
* @stats: Hardware statistics * @stats: Hardware statistics
* @workaround_35388: Flag: firmware supports workaround for bug 35388 * @workaround_35388: Flag: firmware supports workaround for bug 35388
* @workaround_26807: Flag: firmware supports workaround for bug 26807 * @workaround_26807: Flag: firmware supports workaround for bug 26807
...@@ -385,7 +380,6 @@ enum { ...@@ -385,7 +380,6 @@ enum {
* %MC_CMD_GET_CAPABILITIES response) * %MC_CMD_GET_CAPABILITIES response)
* @rx_dpcpu_fw_id: Firmware ID of the RxDPCPU * @rx_dpcpu_fw_id: Firmware ID of the RxDPCPU
* @tx_dpcpu_fw_id: Firmware ID of the TxDPCPU * @tx_dpcpu_fw_id: Firmware ID of the TxDPCPU
* @vport_id: The function's vport ID, only relevant for PFs
* @must_probe_vswitching: Flag: vswitching has yet to be setup after MC reboot * @must_probe_vswitching: Flag: vswitching has yet to be setup after MC reboot
* @pf_index: The number for this PF, or the parent PF if this is a VF * @pf_index: The number for this PF, or the parent PF if this is a VF
#ifdef CONFIG_SFC_SRIOV #ifdef CONFIG_SFC_SRIOV
...@@ -404,16 +398,12 @@ struct efx_ef10_nic_data { ...@@ -404,16 +398,12 @@ struct efx_ef10_nic_data {
u16 warm_boot_count; u16 warm_boot_count;
unsigned int vi_base; unsigned int vi_base;
unsigned int n_allocated_vis; unsigned int n_allocated_vis;
bool must_realloc_vis;
bool must_restore_rss_contexts;
bool must_restore_filters;
unsigned int n_piobufs; unsigned int n_piobufs;
void __iomem *wc_membase, *pio_write_base; void __iomem *wc_membase, *pio_write_base;
unsigned int pio_write_vi_base; unsigned int pio_write_vi_base;
unsigned int piobuf_handle[EF10_TX_PIOBUF_COUNT]; unsigned int piobuf_handle[EF10_TX_PIOBUF_COUNT];
u16 piobuf_size; u16 piobuf_size;
bool must_restore_piobufs; bool must_restore_piobufs;
bool rx_rss_context_exclusive;
u64 stats[EF10_STAT_COUNT]; u64 stats[EF10_STAT_COUNT];
bool workaround_35388; bool workaround_35388;
bool workaround_26807; bool workaround_26807;
...@@ -423,7 +413,6 @@ struct efx_ef10_nic_data { ...@@ -423,7 +413,6 @@ struct efx_ef10_nic_data {
u32 datapath_caps2; u32 datapath_caps2;
unsigned int rx_dpcpu_fw_id; unsigned int rx_dpcpu_fw_id;
unsigned int tx_dpcpu_fw_id; unsigned int tx_dpcpu_fw_id;
unsigned int vport_id;
bool must_probe_vswitching; bool must_probe_vswitching;
unsigned int pf_index; unsigned int pf_index;
u8 port_id[ETH_ALEN]; u8 port_id[ETH_ALEN];
......
...@@ -352,12 +352,7 @@ static int efx_phc_enable(struct ptp_clock_info *ptp, ...@@ -352,12 +352,7 @@ static int efx_phc_enable(struct ptp_clock_info *ptp,
bool efx_ptp_use_mac_tx_timestamps(struct efx_nic *efx) bool efx_ptp_use_mac_tx_timestamps(struct efx_nic *efx)
{ {
struct efx_ef10_nic_data *nic_data = efx->nic_data; return efx_has_cap(efx, TX_MAC_TIMESTAMPING, FLAGS2);
return ((efx_nic_rev(efx) >= EFX_REV_HUNT_A0) &&
(nic_data->datapath_caps2 &
(1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_MAC_TIMESTAMPING_LBN)
));
} }
/* PTP 'extra' channel is still a traffic channel, but we only create TX queues /* PTP 'extra' channel is still a traffic channel, but we only create TX queues
......
...@@ -948,6 +948,13 @@ static int siena_mtd_probe(struct efx_nic *efx) ...@@ -948,6 +948,13 @@ static int siena_mtd_probe(struct efx_nic *efx)
#endif /* CONFIG_SFC_MTD */ #endif /* CONFIG_SFC_MTD */
unsigned int siena_check_caps(const struct efx_nic *efx,
u8 flag, u32 offset)
{
/* Siena did not support MC_CMD_GET_CAPABILITIES */
return 0;
}
/************************************************************************** /**************************************************************************
* *
* Revision-dependent attributes used by efx.c and nic.c * Revision-dependent attributes used by efx.c and nic.c
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册