diff options
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 217 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ef10_sriov.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_filters.c | 82 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_filters.h | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_functions.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_port.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/rx.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena.c | 8 |
13 files changed, 243 insertions, 191 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 3f16bd807c6e..4b0e3695a71a 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -553,7 +553,7 @@ static int efx_ef10_probe(struct efx_nic *efx) 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 * cancel any outstanding request by the previous user of this @@ -1281,13 +1281,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx) 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 */ rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis, nic_data->n_allocated_vis); if (rc) return rc; - nic_data->must_realloc_vis = false; + efx->must_realloc_vis = false; } 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) #endif /* All our allocations have been reset */ - nic_data->must_realloc_vis = true; - nic_data->must_restore_rss_contexts = true; - nic_data->must_restore_filters = true; + efx->must_realloc_vis = true; + efx_mcdi_filter_table_reset_mc_allocations(efx); nic_data->must_restore_piobufs = true; efx_ef10_forget_old_piobufs(efx); 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; - nic_data->vport_id = EVB_PORT_ID_ASSIGNED; + efx->vport_id = EVB_PORT_ID_ASSIGNED; #ifdef CONFIG_SFC_SRIOV if (nic_data->vf) for (i = 0; i < efx->vf_count; i++) @@ -1820,6 +1819,7 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats, } static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx) + __must_hold(&efx->stats_lock) { MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN); struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -2389,6 +2389,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 */ static inline void efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index) @@ -2464,75 +2544,14 @@ static int efx_ef10_ev_init(struct efx_channel *channel) { struct efx_nic *efx = channel->efx; struct efx_ef10_nic_data *nic_data; - unsigned int enabled, implemented; bool use_v2, cut_thru; - int rc; nic_data = efx->nic_data; use_v2 = nic_data->datapath_caps2 & 1 << MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN; cut_thru = !(nic_data->datapath_caps & 1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN); - rc = 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; + return efx_mcdi_ev_init(channel, cut_thru, use_v2); } static void efx_ef10_handle_rx_wrong_queue(struct efx_rx_queue *rx_queue, @@ -3100,16 +3119,15 @@ void efx_ef10_handle_drain_event(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_rx_queue *rx_queue; + struct efx_channel *channel; int pending; /* 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. */ - if (nic_data->must_realloc_vis) { + if (efx->must_realloc_vis) { atomic_set(&efx->active_queues, 0); return 0; } @@ -3158,22 +3176,22 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) efx_mcdi_filter_table_remove(efx); 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) goto restore_filters; 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); if (rc) 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); if (!rc) { ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr); } 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) { /* Failed to add original MAC, so clear vport_mac */ eth_zero_addr(nic_data->vport_mac); @@ -3182,12 +3200,12 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) } restore_vadaptor: - rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); + rc2 = efx_ef10_vadaptor_alloc(efx, efx->vport_id); if (rc2) goto reset_nic; restore_filters: down_write(&efx->filter_sem); - rc2 = efx_mcdi_filter_table_probe(efx); + rc2 = efx_ef10_filter_table_probe(efx); up_write(&efx->filter_sem); if (rc2) goto reset_nic; @@ -3211,7 +3229,6 @@ reset_nic: static int efx_ef10_set_mac_address(struct efx_nic *efx) { MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN); - struct efx_ef10_nic_data *nic_data = efx->nic_data; bool was_enabled = efx->port_enabled; int rc; @@ -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), efx->net_dev->dev_addr); 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, sizeof(inbuf), NULL, 0, NULL); - efx_mcdi_filter_table_probe(efx); + efx_ef10_filter_table_probe(efx); up_write(&efx->filter_sem); mutex_unlock(&efx->mac_lock); @@ -3239,6 +3256,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) #ifdef CONFIG_SFC_SRIOV if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) { + struct efx_ef10_nic_data *nic_data = efx->nic_data; struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; if (rc == -EPERM) { @@ -3961,6 +3979,35 @@ out_unlock: 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 \ (NETIF_F_IP_CSUM | \ NETIF_F_HW_VLAN_CTAG_FILTER | \ @@ -4027,7 +4074,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .ev_process = efx_ef10_ev_process, .ev_read_ack = efx_ef10_ev_read_ack, .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_remove = efx_mcdi_filter_table_remove, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter, @@ -4073,6 +4120,8 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL, .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 = { @@ -4139,7 +4188,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .ev_process = efx_ef10_ev_process, .ev_read_ack = efx_ef10_ev_read_ack, .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_remove = efx_mcdi_filter_table_remove, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter, @@ -4208,4 +4257,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL, .rx_hash_key_size = 40, + .check_caps = ef10_check_caps, + .print_additional_fwver = efx_ef10_print_additional_fwver, }; diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 4580b30caae1..21fa6c0e8873 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -232,15 +232,14 @@ fail: 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; int rc; - rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); + rc = efx_ef10_vadaptor_alloc(efx, efx->vport_id); if (rc) 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); if (rc) goto fail_vadaptor_query; @@ -281,11 +280,11 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx) rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED, 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) 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) goto fail3; 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) return 0; 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); fail3: - efx_ef10_vport_free(efx, nic_data->vport_id); - nic_data->vport_id = EVB_PORT_ID_ASSIGNED; + efx_ef10_vport_free(efx, efx->vport_id); + efx->vport_id = EVB_PORT_ID_ASSIGNED; fail2: efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED); fail1: @@ -355,22 +354,22 @@ void efx_ef10_vswitching_remove_pf(struct efx_nic *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 */ 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); eth_zero_addr(nic_data->vport_mac); } - efx_ef10_vport_free(efx, nic_data->vport_id); - nic_data->vport_id = EVB_PORT_ID_ASSIGNED; + efx_ef10_vport_free(efx, efx->vport_id); + efx->vport_id = EVB_PORT_ID_ASSIGNED; /* Only free the vswitch if no VFs are assigned */ 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) diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 15c731d04065..a8cc3881edce 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1425,23 +1425,16 @@ 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[3])); - /* EF10 may have multiple datapath firmware variants within a - * single version. Report which variants are running. - */ - 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); + if (efx->type->print_additional_fwver) + offset += efx->type->print_additional_fwver(efx, buf + offset, + len - offset); - /* It's theoretically possible for the string to exceed 31 - * characters, though in practice the first three version - * components are short enough that this doesn't happen. - */ - if (WARN_ON(offset >= len)) - buf[0] = 0; - } + /* It's theoretically possible for the string to exceed 31 + * characters, though in practice the first three version + * components are short enough that this doesn't happen. + */ + if (WARN_ON(offset >= len)) + buf[0] = 0; return; diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 54a45010b576..b107e4c00285 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -326,6 +326,18 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_EVENT_FIELD(_ev, _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); int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, u16 *fw_subtype_list, u32 *capabilities); diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 4310ae5bd898..455a62814fb9 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -186,7 +186,6 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx, struct efx_rss_context *ctx, bool replacing) { - struct efx_ef10_nic_data *nic_data = efx->nic_data; u32 flags = spec->flags; 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, 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, spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ? MC_CMD_FILTER_OP_IN_RX_DEST_DROP : @@ -332,7 +331,6 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx, bool replace_equal) { 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_filter_spec *saved_spec; struct efx_rss_context *ctx = NULL; @@ -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, 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 * 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, enum efx_encap_type encap_type, 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; struct efx_filter_spec spec; u8 baddr[ETH_ALEN]; @@ -830,8 +828,7 @@ static int efx_mcdi_filter_insert_def(struct efx_nic *efx, efx_filter_set_uc_def(&spec); if (encap_type) { - if (nic_data->datapath_caps & - (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN)) + if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1)) efx_filter_set_encap_type(&spec, encap_type); else /* @@ -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); *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 */ efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0); @@ -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_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. @@ -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 * old filters first, so that packets are dropped rather than duplicated */ - if (nic_data->workaround_26807 && - table->mc_promisc_last != table->mc_promisc) + if (table->mc_chaining && table->mc_promisc_last != table->mc_promisc) efx_mcdi_filter_remove_old(efx); if (table->mc_promisc) { - if (nic_data->workaround_26807) { + if (table->mc_chaining) { /* * If we failed to insert promiscuous filters, rollback * and fall back to individual multicast filters @@ -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)) { /* Changing promisc state, so remove old filters */ - if (nic_data->workaround_26807) + if (table->mc_chaining) efx_mcdi_filter_remove_old(efx); if (efx_mcdi_filter_insert_def(efx, vlan, EFX_ENCAP_TYPE_NONE, @@ -1288,12 +1283,10 @@ efx_mcdi_filter_table_probe_matches(struct efx_nic *efx, 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 efx_mcdi_filter_table *table; - struct efx_mcdi_filter_vlan *vlan; int rc; if (!efx_rwsem_assert_write_locked(&efx->filter_sem)) @@ -1306,12 +1299,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx) if (!table) return -ENOMEM; + table->mc_chaining = multicast_chaining; table->rx_match_count = 0; rc = efx_mcdi_filter_table_probe_matches(efx, table, false); if (rc) goto fail; - if (nic_data->datapath_caps & - (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN)) + if (efx_has_cap(efx, VXLAN_NVGRE, FLAGS1)) rc = efx_mcdi_filter_table_probe_matches(efx, table, true); if (rc) goto fail; @@ -1342,22 +1335,22 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx) 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; - -fail_add_vlan: - efx_mcdi_filter_cleanup_vlans(efx); - efx->filter_state = NULL; fail: kfree(table); 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 * efx_mcdi_filter_table_remove() is possible @@ -1365,7 +1358,6 @@ fail: void efx_mcdi_filter_table_restore(struct efx_nic *efx) { 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; struct efx_mcdi_filter_vlan *vlan; struct efx_filter_spec *spec; @@ -1377,10 +1369,7 @@ void efx_mcdi_filter_table_restore(struct efx_nic *efx) WARN_ON(!rwsem_is_locked(&efx->filter_sem)); - if (!nic_data->must_restore_filters) - return; - - if (!table) + if (!table || !table->must_restore_filters) return; down_write(&table->lock); @@ -1456,7 +1445,7 @@ not_restored: netif_err(efx, hw, efx->net_dev, "unable to restore %u filters\n", failed); else - nic_data->must_restore_filters = false; + table->must_restore_filters = false; } void efx_mcdi_filter_table_remove(struct efx_nic *efx) @@ -1921,7 +1910,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(outbuf, MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN); - struct efx_ef10_nic_data *nic_data = efx->nic_data; size_t outlen; int rc; u32 alloc_type = exclusive ? @@ -1939,12 +1927,11 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive return 0; } - if (nic_data->datapath_caps & - 1 << MC_CMD_GET_CAPABILITIES_OUT_RX_RSS_LIMITED_LBN) + if (efx_has_cap(efx, RX_RSS_LIMITED, FLAGS1)) return -EOPNOTSUPP; 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_NUM_QUEUES, rss_spread); @@ -1961,8 +1948,7 @@ static int efx_mcdi_filter_alloc_rss_context(struct efx_nic *efx, bool exclusive if (context_size) *context_size = rss_spread; - if (nic_data->datapath_caps & - 1 << MC_CMD_GET_CAPABILITIES_OUT_ADDITIONAL_RSS_MODES_LBN) + if (efx_has_cap(efx, ADDITIONAL_RSS_MODES, FLAGS1)) efx_mcdi_set_rss_context_flags(efx, ctx); return 0; @@ -2030,14 +2016,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, 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, context_size); if (rc != 0) 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); return 0; } @@ -2046,12 +2032,12 @@ static int efx_mcdi_filter_rx_push_exclusive_rss_config(struct efx_nic *efx, const u32 *rx_indir_table, const u8 *key) { + struct efx_mcdi_filter_table *table = efx->filter_state; u32 old_rx_rss_context = efx->rss_context.context_id; - struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; 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, NULL); if (rc == -EOPNOTSUPP) @@ -2068,7 +2054,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 && old_rx_rss_context != EFX_MCDI_RSS_CONTEXT_INVALID) 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) memcpy(efx->rss_context.rx_indir_table, rx_indir_table, sizeof(efx->rss_context.rx_indir_table)); @@ -2182,13 +2168,13 @@ int efx_mcdi_rx_pull_rss_config(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; int rc; WARN_ON(!mutex_is_locked(&efx->rss_lock)); - if (!nic_data->must_restore_rss_contexts) + if (!table->must_restore_rss_contexts) return; list_for_each_entry(ctx, &efx->rss_context.list, list) { @@ -2204,7 +2190,7 @@ void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx) "; RSS filters may fail to be applied\n", 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, diff --git a/drivers/net/ethernet/sfc/mcdi_filters.h b/drivers/net/ethernet/sfc/mcdi_filters.h index 1837f4f5d661..03a8bf74c733 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.h +++ b/drivers/net/ethernet/sfc/mcdi_filters.h @@ -55,6 +55,8 @@ struct efx_mcdi_filter_table { u32 rx_match_mcdi_flags[ MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2]; 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 { @@ -75,14 +77,27 @@ struct efx_mcdi_filter_table { /* Whether in multicast promiscuous mode when last changed */ bool mc_promisc_last; 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; 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_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 * access. When removing filters we must identify them to the diff --git a/drivers/net/ethernet/sfc/mcdi_functions.c b/drivers/net/ethernet/sfc/mcdi_functions.c index dcfe78b0fa5a..962d8395d958 100644 --- a/drivers/net/ethernet/sfc/mcdi_functions.c +++ b/drivers/net/ethernet/sfc/mcdi_functions.c @@ -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; struct efx_channel *channel = tx_queue->channel; struct efx_nic *efx = tx_queue->efx; - struct efx_ef10_nic_data *nic_data; dma_addr_t dma_addr; size_t inlen; int rc, i; 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_TARGET_EVQ, channel->channel); 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_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; @@ -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); size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE; struct efx_nic *efx = rx_queue->efx; - struct efx_ef10_nic_data *nic_data = efx->nic_data; dma_addr_t dma_addr; size_t inlen; int rc; @@ -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_TIMESTAMP, 1); 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; diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index ab5227b13ae6..b807871d8f69 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -722,11 +722,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, MAC_STATS_IN_PERIOD_MS, period); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); - 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, nic_data->vport_id); - } + if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) + MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, efx->vport_id); rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), NULL, 0, NULL); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index b084e623b5f4..1afb58feb9ab 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -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 contexts created by user requests * @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_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 * acknowledge but do nothing else. * @irq_status: Interrupt status buffer @@ -1044,10 +1046,12 @@ struct efx_nic { bool rx_scatter; struct efx_rss_context rss_context; struct mutex rss_lock; + u32 vport_id; unsigned int_error_count; unsigned long int_error_expire; + bool must_realloc_vis; bool irq_soft_enabled; struct efx_buffer irq_status; unsigned irq_zero_count; @@ -1292,6 +1296,7 @@ struct efx_udp_tunnel { * @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_del_port: Remove a UDP tunnel port + * @print_additional_fwver: Dump NIC-specific additional FW version info * @revision: Hardware architecture revision * @txd_ptr_tbl_base: TX descriptor ring base address * @rxd_ptr_tbl_base: RX descriptor ring base address @@ -1352,6 +1357,9 @@ struct efx_nic_type { void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); int (*set_wol)(struct efx_nic *efx, u32 type); 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_nvram)(struct efx_nic *efx); void (*mcdi_request)(struct efx_nic *efx, @@ -1462,6 +1470,8 @@ struct efx_nic_type { 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); 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; unsigned int txd_ptr_tbl_base; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 6670fda8f35a..8f73c5d996eb 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -360,10 +360,6 @@ enum { * @warm_boot_count: Last seen MC warm boot count * @vi_base: Absolute index of first VI in 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 * @wc_membase: Base address of write-combining mapping of the memory BAR * @pio_write_base: Base address for writing PIO buffers @@ -372,7 +368,6 @@ enum { * @piobuf_size: size of a single PIO buffer * @must_restore_piobufs: Flag: PIO buffers have yet to be restored after MC * reboot - * @rx_rss_context_exclusive: Whether our RSS context is exclusive or shared * @stats: Hardware statistics * @workaround_35388: Flag: firmware supports workaround for bug 35388 * @workaround_26807: Flag: firmware supports workaround for bug 26807 @@ -385,7 +380,6 @@ enum { * %MC_CMD_GET_CAPABILITIES response) * @rx_dpcpu_fw_id: Firmware ID of the RxDPCPU * @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 * @pf_index: The number for this PF, or the parent PF if this is a VF #ifdef CONFIG_SFC_SRIOV @@ -404,16 +398,12 @@ struct efx_ef10_nic_data { u16 warm_boot_count; unsigned int vi_base; unsigned int n_allocated_vis; - bool must_realloc_vis; - bool must_restore_rss_contexts; - bool must_restore_filters; unsigned int n_piobufs; void __iomem *wc_membase, *pio_write_base; unsigned int pio_write_vi_base; unsigned int piobuf_handle[EF10_TX_PIOBUF_COUNT]; u16 piobuf_size; bool must_restore_piobufs; - bool rx_rss_context_exclusive; u64 stats[EF10_STAT_COUNT]; bool workaround_35388; bool workaround_26807; @@ -423,7 +413,6 @@ struct efx_ef10_nic_data { u32 datapath_caps2; unsigned int rx_dpcpu_fw_id; unsigned int tx_dpcpu_fw_id; - unsigned int vport_id; bool must_probe_vswitching; unsigned int pf_index; u8 port_id[ETH_ALEN]; diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 59b4f16896a8..04c7283d205e 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -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) { - struct efx_ef10_nic_data *nic_data = efx->nic_data; - - return ((efx_nic_rev(efx) >= EFX_REV_HUNT_A0) && - (nic_data->datapath_caps2 & - (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_MAC_TIMESTAMPING_LBN) - )); + return efx_has_cap(efx, TX_MAC_TIMESTAMPING, FLAGS2); } /* PTP 'extra' channel is still a traffic channel, but we only create TX queues diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 260352d97d9d..c01916cff507 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -308,6 +308,7 @@ static bool efx_do_xdp(struct efx_nic *efx, struct efx_channel *channel, xdp_set_data_meta_invalid(&xdp); xdp.data_end = xdp.data + rx_buf->len; xdp.rxq = &rx_queue->xdp_rxq_info; + xdp.frame_sz = efx->rx_page_buf_step; xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp); rcu_read_unlock(); @@ -328,7 +329,7 @@ static bool efx_do_xdp(struct efx_nic *efx, struct efx_channel *channel, case XDP_TX: /* Buffer ownership passes to tx on success. */ - xdpf = convert_to_xdp_frame(&xdp); + xdpf = xdp_convert_buff_to_frame(&xdp); err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); if (unlikely(err != 1)) { efx_free_rx_buffers(rx_queue, rx_buf, 1); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index baa464161626..891e9fb6abec 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -948,6 +948,13 @@ fail: #endif /* CONFIG_SFC_MTD */ +static 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 @@ -1086,4 +1093,5 @@ const struct efx_nic_type siena_a0_nic_type = { 1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT | 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT), .rx_hash_key_size = 16, + .check_caps = siena_check_caps, }; |