sfc: Enabling EF10 Vf's, set up vswitching and bind the SFC driver to the VF's
Subsystems (3)
cover sfc: Enabling EF10 Vf's, set up vswitching and bind the SFC driver to the VF's
This set of patches makes way for the implementation of EF10 SR-IOV driver starting with some cleanup code.
NIC specific SR-IOV functions are moved to their own header and netdev_ops are made generic instead of being NIC specific
Next in line comes the patch to enable VF's using sriov_configure. VEB vswitching hierarchy is set up next followed by patches to prepare sfc driver to bind to enabled VF's
This is followed by patch to support use of shared RSS contexts which makes VF's use shared RSS contexts in all cases.
Patch series ends with a patch to bind the sfc driver to the enabled VF's which creates network interfaces corresponding to the VF's.
Coming up soon are the patches to set_vf_mac, set_vf_config, set_vf_vlan, vf_spoofcheck, etc.
These patches have been tested with and without CONFIG_SFC_SRIOV. In the case of CONFIG_SFC_SRIOV=y enabling of VF's using sriov_configure is also tested. The enabled VF's bind to the installed sfc driver succesfully to create network interfaces. In the case of CONFIG_SFC_SRIOV=n enabling of VF's using sriov_configure returns the correct error message:
"Function not implemented".
Daniel Pieczko (5):
sfc: Move and rename efx_vf struct to siena_vf
sfc: Record [rt]x_dpcpu_fw_id in EF10 nic_data
sfc: record the PF's vport ID in nic_data
sfc: create VEB vswitch and vport above default firmware setup
sfc: get the PF number and record in nic_data
Edward Cree (1):
sfc: Cope with permissions enforcement added to firmware for SR-IOV
Jon Cooper (1):
sfc: Add use of shared RSS contexts.
Shradha Shah (7):
sfc: Own header for nic-specific sriov functions, single instance of
netdev_ops and sriov removed from Falcon code
sfc: Enable VF's via a write to the sysfs file sriov_numvfs
sfc: Use MCDI to set FILTER_OP_IN_TX_DOMAIN
sfc: Prepare to bind the sfc driver to the VF.
sfc: create vports for VFs and assign random MAC addresses
sfc: manually allocate and free vadaptors
sfc: Bind the sfc driver to any available VF's
drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef10.c | 373 +++++++++++++++++++++++++--- drivers/net/ethernet/sfc/ef10_sriov.c | 430 +++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef10_sriov.h | 70 ++++++ drivers/net/ethernet/sfc/efx.c | 198 +++++++++------ drivers/net/ethernet/sfc/efx.h | 10 + drivers/net/ethernet/sfc/ethtool.c | 5 +- drivers/net/ethernet/sfc/falcon.c | 33 ++- drivers/net/ethernet/sfc/farch.c | 64 +++-- drivers/net/ethernet/sfc/mcdi.c | 118 ++++++--- drivers/net/ethernet/sfc/mcdi.h | 2 + drivers/net/ethernet/sfc/mcdi_pcol.h | 23 ++ drivers/net/ethernet/sfc/net_driver.h | 21 +- drivers/net/ethernet/sfc/nic.h | 133 ++-------- drivers/net/ethernet/sfc/siena.c | 25 +- drivers/net/ethernet/sfc/siena_sriov.c | 142 ++++++----- drivers/net/ethernet/sfc/siena_sriov.h | 79 ++++++ drivers/net/ethernet/sfc/sriov.c | 60 +++++ drivers/net/ethernet/sfc/sriov.h | 27 +++ 19 files changed, 1455 insertions(+), 360 deletions(-) create mode 100644 drivers/net/ethernet/sfc/ef10_sriov.c create mode 100644 drivers/net/ethernet/sfc/ef10_sriov.h create mode 100644 drivers/net/ethernet/sfc/siena_sriov.h create mode 100644 drivers/net/ethernet/sfc/sriov.c create mode 100644 drivers/net/ethernet/sfc/sriov.h
PATCH 1/14 sfc: Own header for nic-specific sriov functions, single instance of netdev_ops and sriov removed from Falcon code
By putting all the efx_{siena,ef10}_sriov_* declarations in {siena,ef10}_sriov.h, ensure they cannot be called from nic-generic code. Also fixes up an instance of this, where mcdi.c was calling efx_siena_sriov_flr.
The single instance of netdev_ops should call general high level functions that can then call something adapter specific in efx_nic_type. We should only do adapter specialisation via efx_nic_type.
Removal of sriov functionality from the Falcon code means that tests are needed for the presence of some callbacks.
--- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef10.c | 8 +++ drivers/net/ethernet/sfc/ef10_sriov.h | 54 ++++++++++++++++ drivers/net/ethernet/sfc/efx.c | 104 +++++++++++++++--------------- drivers/net/ethernet/sfc/efx.h | 7 +++ drivers/net/ethernet/sfc/falcon.c | 10 --- drivers/net/ethernet/sfc/farch.c | 64 ++++++++++++------- drivers/net/ethernet/sfc/mcdi.c | 4 +- drivers/net/ethernet/sfc/net_driver.h | 8 +++ drivers/net/ethernet/sfc/nic.h | 111 --------------------------------- drivers/net/ethernet/sfc/siena.c | 10 +++ drivers/net/ethernet/sfc/siena_sriov.c | 18 +++--- drivers/net/ethernet/sfc/siena_sriov.h | 78 +++++++++++++++++++++++ drivers/net/ethernet/sfc/sriov.c | 60 ++++++++++++++++++ drivers/net/ethernet/sfc/sriov.h | 27 ++++++++ 15 files changed, 355 insertions(+), 210 deletions(-) create mode 100644 drivers/net/ethernet/sfc/ef10_sriov.h create mode 100644 drivers/net/ethernet/sfc/siena_sriov.h create mode 100644 drivers/net/ethernet/sfc/sriov.c create mode 100644 drivers/net/ethernet/sfc/sriov.h
drivers/net/ethernet/sfc/Makefile +1 -1
@@ -3,6 +3,6 @@ sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \ tenxpress.o txc43128_phy.o falcon_boards.o \ mcdi.o mcdi_port.o mcdi_mon.o ptp.o sfc-$(CONFIG_SFC_MTD) += mtd.o -sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o +sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/ethernet/sfc/ef10.c +8 -0
@@ -15,6 +15,7 @@#include "nic.h" #include "workarounds.h" #include "selftest.h" +#include "ef10_sriov.h" #include <linux/in.h> #include <linux/jhash.h> #include <linux/wait.h>
@@ -3689,11 +3690,18 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .ptp_write_host_time = efx_ef10_ptp_write_host_time, .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events, .ptp_set_ts_config = efx_ef10_ptp_set_ts_config, +#ifdef CONFIG_SFC_SRIOV .sriov_init = efx_ef10_sriov_init, .sriov_fini = efx_ef10_sriov_fini, .sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed, .sriov_wanted = efx_ef10_sriov_wanted, .sriov_reset = efx_ef10_sriov_reset, + .sriov_flr = efx_ef10_sriov_flr, + .sriov_set_vf_mac = efx_ef10_sriov_set_vf_mac, + .sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan, + .sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk, + .sriov_get_vf_config = efx_ef10_sriov_get_vf_config, +#endif .revision =EFX_REV_HUNT_A0 , .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
drivers/net/ethernet/sfc/ef10_sriov.h new file +54 -0
54 lines not on this page · raw message
drivers/net/ethernet/sfc/efx.c +49 -55
202 lines not on this page · raw message
drivers/net/ethernet/sfc/efx.h +7 -0
@@ -220,6 +220,13 @@ static inline void efx_mtd_rename(struct efx_nic *efx) {}static inline void efx_mtd_remove (struct efx_nic *efx) {}#endif +#ifdef CONFIG_SFC_SRIOV +static inline unsigned int efx_vf_size (struct efx_nic *efx) +{ +return 1 << efx->vi_scale; +} +#endif +static inline void efx_schedule_channel (struct efx_channel *channel) { netif_vdbg(channel->efx, intr, channel->efx->net_dev,
drivers/net/ethernet/sfc/falcon.c +0 -10
@@ -2766,11 +2766,6 @@ const struct efx_nic_type falcon_a1_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif - .sriov_init = efx_falcon_sriov_init, - .sriov_fini = efx_falcon_sriov_fini, - .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, - .sriov_wanted = efx_falcon_sriov_wanted, - .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_A1, .txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER,
@@ -2867,11 +2862,6 @@ const struct efx_nic_type falcon_b0_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif - .sriov_init = efx_falcon_sriov_init, - .sriov_fini = efx_falcon_sriov_fini, - .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, - .sriov_wanted = efx_falcon_sriov_wanted, - .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_B0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
drivers/net/ethernet/sfc/farch.c +41 -23
113 lines not on this page · raw message
drivers/net/ethernet/sfc/mcdi.c +3 -1
@@ -1035,7 +1035,9 @@ void efx_mcdi_process_event(struct efx_channel *channel,/* MAC stats are gather lazily. We can ignore this. */ break ;case MCDI_EVENT_CODE_FLR : -efx_siena_sriov_flr (efx,MCDI_EVENT_FIELD (*event,FLR_VF )); +if (efx->type->sriov_flr) + efx->type->sriov_flr (efx, +MCDI_EVENT_FIELD (*event,FLR_VF ));break ;case MCDI_EVENT_CODE_PTP_RX :case MCDI_EVENT_CODE_PTP_FAULT :
drivers/net/ethernet/sfc/net_driver.h +8 -0
@@ -1335,6 +1335,14 @@ struct efx_nic_type {void (*sriov_mac_address_changed)(struct efx_nic *efx);bool (*sriov_wanted)(struct efx_nic *efx);void (*sriov_reset)(struct efx_nic *efx); +void (*sriov_flr)(struct efx_nic *efx,unsigned vf_i); +int (*sriov_set_vf_mac)(struct efx_nic *efx,int vf_i,u8 *mac); +int (*sriov_set_vf_vlan)(struct efx_nic *efx,int vf_i,u16 vlan, +u8 qos); +int (*sriov_set_vf_spoofchk)(struct efx_nic *efx,int vf_i, +bool spoofchk); +int (*sriov_get_vf_config)(struct efx_nic *efx,int vf_i, +struct ifla_vf_info *ivi);int revision;unsigned int txd_ptr_tbl_base;
drivers/net/ethernet/sfc/nic.h +0 -111
120 lines not on this page · raw message
drivers/net/ethernet/sfc/siena.c +10 -0
@@ -25,6 +25,7 @@#include "mcdi.h" #include "mcdi_pcol.h" #include "selftest.h" +#include "siena_sriov.h" /* Hardware control for SFC9000 family including SFL9021 (aka Siena). */
@@ -306,7 +307,9 @@ static int siena_probe_nic(struct efx_nic *efx)if (rc) goto fail5; +#ifdef CONFIG_SFC_SRIOV efx_siena_sriov_probe (efx); +#endif efx_ptp_defer_probe_with_channel (efx);return 0 ;
@@ -996,11 +999,18 @@ const struct efx_nic_type siena_a0_nic_type = {#endif .ptp_write_host_time = siena_ptp_write_host_time, .ptp_set_ts_config = siena_ptp_set_ts_config, +#ifdef CONFIG_SFC_SRIOV .sriov_init = efx_siena_sriov_init, .sriov_fini = efx_siena_sriov_fini, .sriov_mac_address_changed = efx_siena_sriov_mac_address_changed, .sriov_wanted = efx_siena_sriov_wanted, .sriov_reset = efx_siena_sriov_reset, + .sriov_flr = efx_siena_sriov_flr, + .sriov_set_vf_mac = efx_siena_sriov_set_vf_mac, + .sriov_set_vf_vlan = efx_siena_sriov_set_vf_vlan, + .sriov_set_vf_spoofchk = efx_siena_sriov_set_vf_spoofchk, + .sriov_get_vf_config = efx_siena_sriov_get_vf_config, +#endif .revision =EFX_REV_SIENA_A0 , .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
drivers/net/ethernet/sfc/siena_sriov.c +9 -9
@@ -16,6 +16,7 @@#include "filter.h" #include "mcdi_pcol.h" #include "farch_regs.h" +#include "siena_sriov.h" #include "vfdi.h" /* Number of longs required to track all the VIs in a VF */
@@ -1573,7 +1574,6 @@ int efx_init_sriov(void) vfdi_workqueue =create_singlethread_workqueue ("sfc_vfdi" );if (!vfdi_workqueue)return -ENOMEM ; -return 0 ; }
@@ -1582,9 +1582,8 @@ void efx_fini_sriov(void)destroy_workqueue (vfdi_workqueue); } -int efx_siena_sriov_set_vf_mac (struct net_device *net_dev,int vf_i,u8 *mac) +int efx_siena_sriov_set_vf_mac (struct efx_nic *efx,int vf_i,u8 *mac) { -struct efx_nic *efx =netdev_priv (net_dev);struct efx_vf *vf;if (vf_i >= efx->vf_init_count)
@@ -1599,10 +1598,9 @@ int efx_siena_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac)return 0 ; } -int efx_siena_sriov_set_vf_vlan (struct net_device *net_dev,int vf_i, +int efx_siena_sriov_set_vf_vlan (struct efx_nic *efx,int vf_i,u16 vlan,u8 qos) { -struct efx_nic *efx =netdev_priv (net_dev);struct efx_vf *vf;u16 tci;
@@ -1619,10 +1617,9 @@ int efx_siena_sriov_set_vf_vlan(struct net_device *net_dev, int vf_i,return 0 ; } -int efx_siena_sriov_set_vf_spoofchk (struct net_device *net_dev,int vf_i, +int efx_siena_sriov_set_vf_spoofchk (struct efx_nic *efx,int vf_i,bool spoofchk) { -struct efx_nic *efx =netdev_priv (net_dev);struct efx_vf *vf;int rc;
@@ -1643,10 +1640,9 @@ int efx_siena_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i,return rc; } -int efx_siena_sriov_get_vf_config (struct net_device *net_dev,int vf_i, +int efx_siena_sriov_get_vf_config (struct efx_nic *efx,int vf_i,struct ifla_vf_info *ivi) { -struct efx_nic *efx =netdev_priv (net_dev);struct efx_vf *vf;u16 tci;
@@ -1666,3 +1662,7 @@ int efx_siena_sriov_get_vf_config(struct net_device *net_dev, int vf_i,return 0 ; } +bool efx_siena_sriov_wanted (struct efx_nic *efx) +{ +return efx->vf_count !=0 ; +}
drivers/net/ethernet/sfc/siena_sriov.h new file +78 -0
78 lines not on this page · raw message
drivers/net/ethernet/sfc/sriov.c new file +60 -0
60 lines not on this page · raw message
drivers/net/ethernet/sfc/sriov.h new file +27 -0
@@ -0,0 +1,27 @@ +/**************************************************************************** +* Driver for Solarflare network controllers and boards +* Copyright 2014-2015 Solarflare Communications Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published +* by the Free Software Foundation, incorporated herein by reference. +*/ + +#ifndef EFX_SRIOV_H +#define EFX_SRIOV_H + +#include "net_driver.h" + +#ifdef CONFIG_SFC_SRIOV + +int efx_sriov_set_vf_mac (struct net_device *net_dev,int vf_i,u8 *mac); +int efx_sriov_set_vf_vlan (struct net_device *net_dev,int vf_i,u16 vlan, +u8 qos); +int efx_sriov_set_vf_spoofchk (struct net_device *net_dev,int vf_i, +bool spoofchk); +int efx_sriov_get_vf_config (struct net_device *net_dev,int vf_i, +struct ifla_vf_info *ivi); + +#endif /* CONFIG_SFC_SRIOV */ + +#endif /* EFX_SRIOV_H */
PATCH 2/14 sfc: Move and rename efx_vf struct to siena_vf
In reply to Shradha ShahFrom: Daniel Pieczko <[email protected]>
The efx_vf struct contains Siena-specific fields for VFs, so rename to siena_vf.
Also move it into the siena_nic_data struct, as EF10 will track its VFs in its own ef10_nic_data, storing much less information about them since VFDI is no longer used.
--- drivers/net/ethernet/sfc/net_driver.h | 3 - drivers/net/ethernet/sfc/nic.h | 2 + drivers/net/ethernet/sfc/siena_sriov.c | 119 ++++++++++++++++++--------------- 3 files changed, 67 insertions(+), 57 deletions(-)
drivers/net/ethernet/sfc/net_driver.h +0 -3
@@ -793,7 +793,6 @@ union efx_multicast_hash {efx_oword_t oword[EFX_MCAST_HASH_ENTRIES /sizeof (efx_oword_t) /8 ]; }; -struct efx_vf ;struct vfdi_status ;/**
@@ -909,7 +908,6 @@ struct vfdi_status;* completed (either success or failure). Not used when MCDI is used to * flush receive queues. * @flush_wq: wait queue used by efx_nic_flush_queues() to wait for flush completions. -* @vf: Array of &struct efx_vf objects. * @vf_count: Number of VFs intended to be enabled. * @vf_init_count: Number of VFs that have been fully initialised. * @vi_scale: log2 number of vnics per VF.
@@ -1053,7 +1051,6 @@ struct efx_nic {wait_queue_head_t flush_wq;#ifdef CONFIG_SFC_SRIOV -struct efx_vf *vf;unsigned vf_count;unsigned vf_init_count;unsigned vi_scale;
drivers/net/ethernet/sfc/nic.h +2 -0
@@ -381,6 +381,7 @@ enum {* @efx: Pointer back to main interface structure * @wol_filter_id: Wake-on-LAN packet filter id * @stats: Hardware statistics +* @vf: Array of &struct siena_vf objects * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. * @vfdi_status: Common VFDI status page to be dmad to VF address space. * @local_addr_list: List of local addresses. Protected by %local_lock.
@@ -394,6 +395,7 @@ struct siena_nic_data {int wol_filter_id;u64 stats[SIENA_STAT_COUNT ];#ifdef CONFIG_SFC_SRIOV +struct siena_vf *vf;struct efx_channel *vfdi_channel;unsigned vf_buftbl_base;struct efx_buffer vfdi_status;
drivers/net/ethernet/sfc/siena_sriov.c +65 -54
416 lines not on this page · raw message
PATCH 3/14 sfc: Enable VF's via a write to the sysfs file sriov_numvfs
In reply to Shradha ShahThis patch adds support for the use of sriov_configure on EF10 to enable Virtual Functions while the driver is loaded.
--- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef10.c | 1 + drivers/net/ethernet/sfc/ef10_sriov.c | 47 ++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef10_sriov.h | 2 ++ drivers/net/ethernet/sfc/efx.c | 23 +++++++++++++++++ drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/siena.c | 1 + drivers/net/ethernet/sfc/siena_sriov.c | 5 ++++ drivers/net/ethernet/sfc/siena_sriov.h | 1 + 9 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/sfc/ef10_sriov.c
drivers/net/ethernet/sfc/Makefile +1 -1
@@ -3,6 +3,6 @@ sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \ tenxpress.o txc43128_phy.o falcon_boards.o \ mcdi.o mcdi_port.o mcdi_mon.o ptp.o sfc-$(CONFIG_SFC_MTD) += mtd.o -sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o +sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o ef10_sriov.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/ethernet/sfc/ef10.c +1 -0
@@ -3691,6 +3691,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events, .ptp_set_ts_config = efx_ef10_ptp_set_ts_config, #ifdef CONFIG_SFC_SRIOV + .sriov_configure = efx_ef10_sriov_configure, .sriov_init = efx_ef10_sriov_init, .sriov_fini = efx_ef10_sriov_fini, .sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed,
drivers/net/ethernet/sfc/ef10_sriov.c new file +47 -0
47 lines not on this page · raw message
drivers/net/ethernet/sfc/ef10_sriov.h +2 -0
@@ -17,6 +17,8 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx)return false; } +int efx_ef10_sriov_configure (struct efx_nic *efx,int num_vfs); +static inline int efx_ef10_sriov_init (struct efx_nic *efx) {return -EOPNOTSUPP ;
drivers/net/ethernet/sfc/efx.c +23 -0
@@ -3046,6 +3046,26 @@ static int efx_pci_probe(struct pci_dev *pci_dev,return rc; } +/* efx_pci_sriov_configure returns the actual number of Virtual Functions +* enabled on success +*/ +#ifdef CONFIG_SFC_SRIOV +static int efx_pci_sriov_configure (struct pci_dev *dev,int num_vfs) +{ +int rc; +struct efx_nic *efx =pci_get_drvdata (dev); + +if (efx->type->sriov_configure) { + rc = efx->type->sriov_configure (efx, num_vfs); +if (rc) +return rc; +else +return num_vfs; + }else +return -EOPNOTSUPP ; +} +#endif +static int efx_pm_freeze (struct device *dev) {struct efx_nic *efx =pci_get_drvdata (to_pci_dev (dev));
@@ -3268,6 +3288,9 @@ static struct pci_driver efx_pci_driver = { .remove = efx_pci_remove, .driver.pm = &efx_pm_ops, .err_handler = &efx_err_handlers, +#ifdef CONFIG_SFC_SRIOV + .sriov_configure = efx_pci_sriov_configure, +#endif };/**************************************************************************
drivers/net/ethernet/sfc/net_driver.h +1 -0
@@ -1327,6 +1327,7 @@ struct efx_nic_type {int (*ptp_set_ts_sync_events)(struct efx_nic *efx,bool en,bool temp);int (*ptp_set_ts_config)(struct efx_nic *efx,struct hwtstamp_config *init); +int (*sriov_configure)(struct efx_nic *efx,int num_vfs);int (*sriov_init)(struct efx_nic *efx);void (*sriov_fini)(struct efx_nic *efx);void (*sriov_mac_address_changed)(struct efx_nic *efx);
drivers/net/ethernet/sfc/siena.c +1 -0
@@ -1000,6 +1000,7 @@ const struct efx_nic_type siena_a0_nic_type = { .ptp_write_host_time = siena_ptp_write_host_time, .ptp_set_ts_config = siena_ptp_set_ts_config, #ifdef CONFIG_SFC_SRIOV + .sriov_configure = efx_siena_sriov_configure, .sriov_init = efx_siena_sriov_init, .sriov_fini = efx_siena_sriov_fini, .sriov_mac_address_changed = efx_siena_sriov_mac_address_changed,
drivers/net/ethernet/sfc/siena_sriov.c +5 -0
@@ -1677,3 +1677,8 @@ bool efx_siena_sriov_wanted(struct efx_nic *efx) {return efx->vf_count !=0 ; } + +int efx_siena_sriov_configure (struct efx_nic *efx,int num_vfs) +{ +return 0 ; +}
drivers/net/ethernet/sfc/siena_sriov.h +1 -0
@@ -41,6 +41,7 @@ ((EFX_MAX_VF_EVQ_SIZE +2 *EFX_MAX_DMAQ_SIZE ) * \ sizeof(efx_qword_t) / EFX_BUF_SIZE) +int efx_siena_sriov_configure (struct efx_nic *efx,int num_vfs);int efx_siena_sriov_init (struct efx_nic *efx);void efx_siena_sriov_fini (struct efx_nic *efx);void efx_siena_sriov_mac_address_changed (struct efx_nic *efx);
PATCH 4/14 sfc: Use MCDI to set FILTER_OP_IN_TX_DOMAIN
In reply to Shradha ShahThe TX_DOMAIN field is currently reserved but its safer to set it to 0 for future compatibility.
--- drivers/net/ethernet/sfc/ef10.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/sfc/ef10.c +1 -0
@@ -2292,6 +2292,7 @@ static void efx_ef10_filter_push_prep(struct efx_nic *efx, spec->dmaq_id ==EFX_FILTER_RX_DMAQ_ID_DROP ?MC_CMD_FILTER_OP_IN_RX_DEST_DROP : MC_CMD_FILTER_OP_IN_RX_DEST_HOST); +MCDI_SET_DWORD (inbuf,FILTER_OP_IN_TX_DOMAIN ,0 );MCDI_SET_DWORD (inbuf,FILTER_OP_IN_TX_DEST ,MC_CMD_FILTER_OP_IN_TX_DEST_DEFAULT ); MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_QUEUE,
PATCH 5/14 sfc: Record [rt]x_dpcpu_fw_id in EF10 nic_data
In reply to Shradha ShahFrom: Daniel Pieczko <[email protected]>
The (future) code to add/remove vswitches and vports will be dependent on the firmware variant.
To simplify the checking of the firmware variant, record values for rx_dpcpu_fw_id and tx_dpcpu_fw_id in EF10 nic_data.
There was only one place where this was previously used:efx_mcdi_print_fwver() in ethtool.c.
The MC_CMD_GET_CAPABILITIES can be replaced and the values from nic_data used instead.
Note that the printing of "?" if the MC command fails or if the outlength is incorrect no longer apply, because errors are returned in efx_ef10_init_datapath_caps() in both of these cases.
--- drivers/net/ethernet/sfc/ef10.c | 7 +++++++ drivers/net/ethernet/sfc/mcdi.c | 22 ++++++---------------- drivers/net/ethernet/sfc/nic.h | 4 ++++ 3 files changed, 17 insertions(+), 16 deletions(-)
drivers/net/ethernet/sfc/ef10.c +7 -0
@@ -118,6 +118,13 @@ static int efx_ef10_init_datapath_caps(struct efx_nic *efx) nic_data->datapath_caps =MCDI_DWORD (outbuf,GET_CAPABILITIES_OUT_FLAGS1 ); +/* record the DPCPU firmware IDs to determine VEB vswitching support. +*/ + nic_data->rx_dpcpu_fw_id = +MCDI_WORD (outbuf,GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID ); + nic_data->tx_dpcpu_fw_id = +MCDI_WORD (outbuf,GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID ); +if (!(nic_data->datapath_caps & (1 <<MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN ))) { netif_err(efx, drv, efx->net_dev,
drivers/net/ethernet/sfc/mcdi.c +6 -16
@@ -1083,9 +1083,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,void efx_mcdi_print_fwver (struct efx_nic *efx,char *buf,size_t len) { -MCDI_DECLARE_BUF (outbuf, -max (MC_CMD_GET_VERSION_OUT_LEN , -MC_CMD_GET_CAPABILITIES_OUT_LEN )); +MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_VERSION_OUT_LEN );size_t outlength;const __le16 *ver_words;size_t offset;
@@ -1110,19 +1108,11 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)* single version. Report which variants are running. */ if (efx_nic_rev (efx) >=EFX_REV_HUNT_A0 ) { -BUILD_BUG_ON (MC_CMD_GET_CAPABILITIES_IN_LEN !=0 ); - rc =efx_mcdi_rpc (efx,MC_CMD_GET_CAPABILITIES ,NULL ,0 , - outbuf,sizeof (outbuf), &outlength); -if (rc || outlength <MC_CMD_GET_CAPABILITIES_OUT_LEN ) - offset +=snprintf ( - buf + offset, len - offset," rx? tx?" ); -else - offset +=snprintf ( - buf + offset, len - offset," rx%x tx%x" , -MCDI_WORD (outbuf, -GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID ), -MCDI_WORD (outbuf, -GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID )); +struct efx_ef10_nic_data *nic_data = efx->nic_data; + + offset +=snprintf (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 * characters, though in practice the first three version
drivers/net/ethernet/sfc/nic.h +4 -0
@@ -491,6 +491,8 @@ enum {* after MC reboot * @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of * %MC_CMD_GET_CAPABILITIES response) +* @rx_dpcpu_fw_id: Firmware ID of the RxDPCPU +* @tx_dpcpu_fw_id: Firmware ID of the TxDPCPU */ struct efx_ef10_nic_data {struct efx_buffer mcdi_buf;
@@ -509,6 +511,8 @@ struct efx_ef10_nic_data {bool workaround_35388;bool must_check_datapath_caps;u32 datapath_caps; +unsigned int rx_dpcpu_fw_id; +unsigned int tx_dpcpu_fw_id; };int efx_init_sriov (void );
PATCH 6/14 sfc: record the PF's vport ID in nic_data
In reply to Shradha ShahFrom: Daniel Pieczko <[email protected]>
The default port ID of EVB_PORT_ID_ASSIGNED is a "magic" number for the MCFW to select the physical port of the PF. If other vswitches and vports are created on top of the default firmware configuration, the ID of the newly created vport is then required when passed to MCDI commands. Currently, this doesn't happen so the vport_id is never changed, but a subsequent patch will change this behaviour so that other vswitches and vports are created.
The vport_id recorded in nic_data is only relevant for PFs. VFs will have their vports created by their parent PF, and in that case the parent PF will record the vport ID of each VF. For a VF, nic_data->vport_id is expected to remain at the default value.
--- drivers/net/ethernet/sfc/ef10.c | 13 +++++++++---- drivers/net/ethernet/sfc/nic.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-)
drivers/net/ethernet/sfc/ef10.c +9 -4
@@ -217,6 +217,8 @@ static int efx_ef10_probe(struct efx_nic *efx) nic_data->rx_rss_context =EFX_EF10_RSS_CONTEXT_INVALID ; + nic_data->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 * function. We send a special message using the least
@@ -1245,6 +1247,7 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)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 = efx->nic_data;size_t inlen, outlen;dma_addr_t dma_addr;efx_qword_t *txd;
@@ -1259,7 +1262,7 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)INIT_TXQ_IN_FLAG_IP_CSUM_DIS , !csum_offload, INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload);MCDI_SET_DWORD (inbuf,INIT_TXQ_IN_OWNER_ID ,0 ); -MCDI_SET_DWORD (inbuf,INIT_TXQ_IN_PORT_ID ,EVB_PORT_ID_ASSIGNED ); +MCDI_SET_DWORD (inbuf,INIT_TXQ_IN_PORT_ID , nic_data->vport_id); dma_addr = tx_queue->txd.buf.dma_addr;
@@ -1390,11 +1393,12 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context) {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;MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID , -EVB_PORT_ID_ASSIGNED ); + nic_data->vport_id);MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_TYPE ,MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE ); MCDI_SET_DWORD(inbuf, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES,
@@ -1508,6 +1512,7 @@ static void efx_ef10_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;size_t inlen, outlen;dma_addr_t dma_addr;int rc;
@@ -1525,7 +1530,7 @@ static void efx_ef10_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 ,EVB_PORT_ID_ASSIGNED ); +MCDI_SET_DWORD (inbuf,INIT_RXQ_IN_PORT_ID , nic_data->vport_id); dma_addr = rx_queue->rxd.buf.dma_addr;
@@ -2294,7 +2299,7 @@ static void efx_ef10_filter_push_prep(struct efx_nic *efx, match_fields); } -MCDI_SET_DWORD (inbuf,FILTER_OP_IN_PORT_ID ,EVB_PORT_ID_ASSIGNED ); +MCDI_SET_DWORD (inbuf,FILTER_OP_IN_PORT_ID , nic_data->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 :
drivers/net/ethernet/sfc/nic.h +2 -0
@@ -493,6 +493,7 @@ 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 */ struct efx_ef10_nic_data {struct efx_buffer mcdi_buf;
@@ -513,6 +514,7 @@ struct efx_ef10_nic_data {u32 datapath_caps;unsigned int rx_dpcpu_fw_id;unsigned int tx_dpcpu_fw_id; +unsigned int vport_id; };int efx_init_sriov (void );
PATCH 7/14 sfc: create VEB vswitch and vport above default firmware setup
In reply to Shradha ShahFrom: Daniel Pieczko <[email protected]>
Adds functions to allocate and free vswitches and vports; vadaptors are automatically allocated and freed when TX/RX queues are initialised and finalised. This vswitching structure is only created if the firmware supports it, so a check that full-featured firmware is running is performed first.
If the MC resets, the vswitching infrastructure will need to be recreated, so mark the "must_probe_vswitching" flag when an MC reboot is detected.
Don't try to create a vswitch if vf-count=0
This allocation of vswitches and vports does not currently support configuring VLAN tags, but that can be added in a future change.
--- drivers/net/ethernet/sfc/ef10.c | 7 ++ drivers/net/ethernet/sfc/ef10_sriov.c | 121 ++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef10_sriov.h | 4 ++ drivers/net/ethernet/sfc/efx.c | 30 ++++++++- drivers/net/ethernet/sfc/net_driver.h | 3 + drivers/net/ethernet/sfc/nic.h | 2 + drivers/net/ethernet/sfc/siena.c | 3 + 7 files changed, 167 insertions(+), 3 deletions(-)
drivers/net/ethernet/sfc/ef10.c +7 -0
@@ -1133,6 +1133,10 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)/* All our allocations have been reset */ efx_ef10_reset_mc_allocations (efx); +/* Driver-created vswitches and vports must be re-created */ + nic_data->must_probe_vswitching = true; + nic_data->vport_id =EVB_PORT_ID_ASSIGNED ; +/* The datapath firmware might have been changed */ nic_data->must_check_datapath_caps = true;
@@ -3715,6 +3719,9 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan, .sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk, .sriov_get_vf_config = efx_ef10_sriov_get_vf_config, + .vswitching_probe = efx_ef10_vswitching_probe, + .vswitching_restore = efx_ef10_vswitching_restore, + .vswitching_remove = efx_ef10_vswitching_remove, #endif .revision = EFX_REV_HUNT_A0,
drivers/net/ethernet/sfc/ef10_sriov.c +121 -0
124 lines not on this page · raw message
drivers/net/ethernet/sfc/ef10_sriov.h +4 -0
@@ -53,4 +53,8 @@ static inline int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf, return -EOPNOTSUPP; } +int efx_ef10_vswitching_probe (struct efx_nic *efx); +int efx_ef10_vswitching_restore (struct efx_nic *efx); +void efx_ef10_vswitching_remove (struct efx_nic *efx); +#endif /* EF10_SRIOV_H */
drivers/net/ethernet/sfc/efx.c +27 -3
@@ -1721,21 +1721,33 @@ static int efx_probe_all(struct efx_nic *efx) } efx->rxq_entries = efx->txq_entries =EFX_DEFAULT_DMAQ_SIZE ; +#ifdef CONFIG_SFC_SRIOV + rc = efx->type->vswitching_probe (efx); +if (rc)/* not fatal; the PF will still work fine */ +netif_warn (efx, probe, efx->net_dev, +"failed to setup vswitching rc=%d;" +" VFs may not function\n" , rc); +#endif + rc =efx_probe_filters (efx);if (rc) {netif_err (efx, probe, efx->net_dev,"failed to create filter tables\n" ); - goto fail3; + goto fail4; } rc =efx_probe_channels (efx);if (rc) - goto fail4; + goto fail5;return 0 ; - fail4: + fail5:efx_remove_filters (efx); + fail4: +#ifdef CONFIG_SFC_SRIOV + efx->type->vswitching_remove (efx); +#endif fail3:efx_remove_port (efx); fail2:
@@ -1825,6 +1837,9 @@ static void efx_remove_all(struct efx_nic *efx) {efx_remove_channels (efx);efx_remove_filters (efx); +#ifdef CONFIG_SFC_SRIOV + efx->type->vswitching_remove (efx); +#endif efx_remove_port (efx);efx_remove_nic (efx); }
@@ -2417,6 +2432,15 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) rc =efx_enable_interrupts (efx);if (rc) goto fail; + +#ifdef CONFIG_SFC_SRIOV + rc = efx->type->vswitching_restore (efx); +if (rc)/* not fatal; the PF will still work fine */ +netif_warn (efx, probe, efx->net_dev, +"failed to restore vswitching rc=%d;" +" VFs may not function\n" , rc); +#endif +efx_restore_filters (efx);if (efx->type->sriov_reset) efx->type->sriov_reset (efx);
drivers/net/ethernet/sfc/net_driver.h +3 -0
@@ -1341,6 +1341,9 @@ struct efx_nic_type { bool spoofchk);int (*sriov_get_vf_config)(struct efx_nic *efx,int vf_i,struct ifla_vf_info *ivi); +int (*vswitching_probe)(struct efx_nic *efx); +int (*vswitching_restore)(struct efx_nic *efx); +void (*vswitching_remove)(struct efx_nic *efx);int revision;unsigned int txd_ptr_tbl_base;
drivers/net/ethernet/sfc/nic.h +2 -0
@@ -494,6 +494,7 @@ enum {* @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 */ struct efx_ef10_nic_data {struct efx_buffer mcdi_buf;
@@ -515,6 +516,7 @@ struct efx_ef10_nic_data {unsigned int rx_dpcpu_fw_id;unsigned int tx_dpcpu_fw_id;unsigned int vport_id; +bool must_probe_vswitching; };int efx_init_sriov (void );
drivers/net/ethernet/sfc/siena.c +3 -0
@@ -1011,6 +1011,9 @@ const struct efx_nic_type siena_a0_nic_type = { .sriov_set_vf_vlan = efx_siena_sriov_set_vf_vlan, .sriov_set_vf_spoofchk = efx_siena_sriov_set_vf_spoofchk, .sriov_get_vf_config = efx_siena_sriov_get_vf_config, + .vswitching_probe = efx_port_dummy_op_int, + .vswitching_restore = efx_port_dummy_op_int, + .vswitching_remove = efx_port_dummy_op_void, #endif .revision = EFX_REV_SIENA_A0,
PATCH 8/14 sfc: get the PF number and record in nic_data
In reply to Shradha ShahFrom: Daniel Pieczko <[email protected]>
Use MC_CMD_GET_FUNCTION_INFO to record the PF number in nic_data. This will be needed when assigned vports to VFs.
--- drivers/net/ethernet/sfc/ef10.c | 22 ++++++++++++++++++++++ drivers/net/ethernet/sfc/nic.h | 2 ++ 2 files changed, 24 insertions(+)
drivers/net/ethernet/sfc/ef10.c +22 -0
@@ -96,6 +96,24 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)return resource_size (&efx->pci_dev->resource[EFX_MEM_BAR ]); } +static int efx_ef10_get_pf_index (struct efx_nic *efx) +{ +MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_FUNCTION_INFO_OUT_LEN ); +struct efx_ef10_nic_data *nic_data = efx->nic_data; +size_t outlen; +int rc; + + rc =efx_mcdi_rpc (efx,MC_CMD_GET_FUNCTION_INFO ,NULL ,0 , outbuf, +sizeof (outbuf), &outlen); +if (rc) +return rc; +if (outlen <sizeof (outbuf)) +return -EIO ; + + nic_data->pf_index =MCDI_DWORD (outbuf,GET_FUNCTION_INFO_OUT_PF ); +return 0 ; +} +static int efx_ef10_init_datapath_caps (struct efx_nic *efx) {MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_CAPABILITIES_OUT_LEN );
@@ -240,6 +258,10 @@ static int efx_ef10_probe(struct efx_nic *efx)if (rc) goto fail3; + rc =efx_ef10_get_pf_index (efx); +if (rc) + goto fail3; + rc =efx_ef10_init_datapath_caps (efx);if (rc <0 ) goto fail3;
drivers/net/ethernet/sfc/nic.h +2 -0
@@ -495,6 +495,7 @@ enum {* @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 */ struct efx_ef10_nic_data {struct efx_buffer mcdi_buf;
@@ -517,6 +518,7 @@ struct efx_ef10_nic_data {unsigned int tx_dpcpu_fw_id;unsigned int vport_id;bool must_probe_vswitching; +unsigned int pf_index; };int efx_init_sriov (void );
PATCH 9/14 sfc: Prepare to bind the sfc driver to the VF.
In reply to Shradha ShahAdded efx_nic_type structure for VF.
Mapped a different BAR for VF as it uses BAR 0 for memory. Added functions sriov_init and sriov_fini.
--- drivers/net/ethernet/sfc/ef10.c | 141 +++++++++++++++++++++++++++++++++- drivers/net/ethernet/sfc/ef10_sriov.c | 17 ++++ drivers/net/ethernet/sfc/ef10_sriov.h | 9 +-- drivers/net/ethernet/sfc/efx.c | 15 ++-- drivers/net/ethernet/sfc/efx.h | 2 + drivers/net/ethernet/sfc/falcon.c | 2 + drivers/net/ethernet/sfc/net_driver.h | 2 + drivers/net/ethernet/sfc/nic.h | 1 + drivers/net/ethernet/sfc/siena.c | 1 + 9 files changed, 175 insertions(+), 15 deletions(-)
drivers/net/ethernet/sfc/ef10.c +138 -3
@@ -93,7 +93,10 @@ static int efx_ef10_get_warm_boot_count(struct efx_nic *efx)static unsigned int efx_ef10_mem_map_size (struct efx_nic *efx) { -return resource_size (&efx->pci_dev->resource[EFX_MEM_BAR ]); +int bar; + + bar = efx->type->mem_bar; +return resource_size (&efx->pci_dev->resource[bar]); }static int efx_ef10_get_pf_index (struct efx_nic *efx)
@@ -204,7 +207,7 @@ static int efx_ef10_probe(struct efx_nic *efx) efx->max_channels = min_t(unsigned int,EFX_MAX_CHANNELS , -resource_size (&efx->pci_dev->resource[EFX_MEM_BAR ]) / +efx_ef10_mem_map_size (efx) / (EFX_VI_PAGE_SIZE *EFX_TXQ_TYPES ));if (WARN_ON (efx->max_channels ==0 ))return -EIO ;
@@ -311,6 +314,23 @@ fail1:return rc; } +static int efx_ef10_probe_pf (struct efx_nic *efx) +{ +return efx_ef10_probe (efx); +} + +#ifdef CONFIG_SFC_SRIOV +static int efx_ef10_probe_vf (struct efx_nic *efx) +{ +return efx_ef10_probe (efx); +} +#else +static int efx_ef10_probe_vf (struct efx_nic *efx __attribute__ ((unused))) +{ +return 0 ; +} +#endif +static int efx_ef10_free_vis (struct efx_nic *efx) {MCDI_DECLARE_BUF_OUT_OR_ERR (outbuf,0 );
@@ -1076,6 +1096,14 @@ static void efx_ef10_push_irq_moderation(struct efx_channel *channel) } } +static void efx_ef10_get_wol_vf (struct efx_nic *efx, +struct ethtool_wolinfo *wol) {} + +static int efx_ef10_set_wol_vf (struct efx_nic *efx,u32 type) +{ +return -EOPNOTSUPP ; +} +static void efx_ef10_get_wol (struct efx_nic *efx,struct ethtool_wolinfo *wol) { wol->supported =0 ;
@@ -3534,6 +3562,9 @@ static void efx_ef10_ptp_write_host_time(struct efx_nic *efx, u32 host_time)_efx_writed (efx,cpu_to_le32 (host_time),ER_DZ_MC_DB_LWRD ); } +static void efx_ef10_ptp_write_host_time_vf (struct efx_nic *efx, +u32 host_time) {} +static int efx_ef10_rx_enable_timestamping (struct efx_channel *channel,bool temp) {
@@ -3611,6 +3642,12 @@ static int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en,return 0 ; } +static int efx_ef10_ptp_set_ts_config_vf (struct efx_nic *efx, +struct hwtstamp_config *init) +{ +return -EOPNOTSUPP ; +} +static int efx_ef10_ptp_set_ts_config (struct efx_nic *efx,struct hwtstamp_config *init) {
@@ -3647,9 +3684,107 @@ static int efx_ef10_ptp_set_ts_config(struct efx_nic *efx, } } +const struct efx_nic_type efx_hunt_a0_vf_nic_type = { + .mem_bar =EFX_MEM_VF_BAR , + .mem_map_size = efx_ef10_mem_map_size, + .probe = efx_ef10_probe_vf, + .remove = efx_ef10_remove, + .dimension_resources = efx_ef10_dimension_resources, + .init = efx_ef10_init_nic, + .fini = efx_port_dummy_op_void, + .map_reset_reason = efx_mcdi_map_reset_reason, + .map_reset_flags = efx_ef10_map_reset_flags, + .reset = efx_ef10_reset, + .probe_port = efx_mcdi_port_probe, + .remove_port = efx_mcdi_port_remove, + .fini_dmaq = efx_ef10_fini_dmaq, + .prepare_flr = efx_ef10_prepare_flr, + .finish_flr = efx_port_dummy_op_void, + .describe_stats = efx_ef10_describe_stats, + .update_stats = efx_ef10_update_stats, + .start_stats = efx_port_dummy_op_void, + .pull_stats = efx_port_dummy_op_void, + .stop_stats = efx_port_dummy_op_void, + .set_id_led = efx_mcdi_set_id_led, + .push_irq_moderation = efx_ef10_push_irq_moderation, + .reconfigure_mac = efx_ef10_mac_reconfigure, + .check_mac_fault = efx_mcdi_mac_check_fault, + .reconfigure_port = efx_mcdi_port_reconfigure, + .get_wol = efx_ef10_get_wol_vf, + .set_wol = efx_ef10_set_wol_vf, + .resume_wol = efx_port_dummy_op_void, + .mcdi_request = efx_ef10_mcdi_request, + .mcdi_poll_response = efx_ef10_mcdi_poll_response, + .mcdi_read_response = efx_ef10_mcdi_read_response, + .mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot, + .irq_enable_master = efx_port_dummy_op_void, + .irq_test_generate = efx_ef10_irq_test_generate, + .irq_disable_non_ev = efx_port_dummy_op_void, + .irq_handle_msi = efx_ef10_msi_interrupt, + .irq_handle_legacy = efx_ef10_legacy_interrupt, + .tx_probe = efx_ef10_tx_probe, + .tx_init = efx_ef10_tx_init, + .tx_remove = efx_ef10_tx_remove, + .tx_write = efx_ef10_tx_write, + .rx_push_rss_config = efx_ef10_rx_push_rss_config, + .rx_probe = efx_ef10_rx_probe, + .rx_init = efx_ef10_rx_init, + .rx_remove = efx_ef10_rx_remove, + .rx_write = efx_ef10_rx_write, + .rx_defer_refill = efx_ef10_rx_defer_refill, + .ev_probe = efx_ef10_ev_probe, + .ev_init = efx_ef10_ev_init, + .ev_fini = efx_ef10_ev_fini, + .ev_remove = efx_ef10_ev_remove, + .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_ef10_filter_table_probe, + .filter_table_restore = efx_ef10_filter_table_restore, + .filter_table_remove = efx_ef10_filter_table_remove, + .filter_update_rx_scatter = efx_ef10_filter_update_rx_scatter, + .filter_insert = efx_ef10_filter_insert, + .filter_remove_safe = efx_ef10_filter_remove_safe, + .filter_get_safe = efx_ef10_filter_get_safe, + .filter_clear_rx = efx_ef10_filter_clear_rx, + .filter_count_rx_used = efx_ef10_filter_count_rx_used, + .filter_get_rx_id_limit = efx_ef10_filter_get_rx_id_limit, + .filter_get_rx_ids = efx_ef10_filter_get_rx_ids, +#ifdef CONFIG_RFS_ACCEL + .filter_rfs_insert = efx_ef10_filter_rfs_insert, + .filter_rfs_expire_one = efx_ef10_filter_rfs_expire_one, +#endif +#ifdef CONFIG_SFC_MTD + .mtd_probe = efx_port_dummy_op_int, +#endif + .ptp_write_host_time = efx_ef10_ptp_write_host_time_vf, + .ptp_set_ts_config = efx_ef10_ptp_set_ts_config_vf, +#ifdef CONFIG_SFC_SRIOV + .vswitching_probe = efx_port_dummy_op_int, + .vswitching_restore = efx_port_dummy_op_int, + .vswitching_remove = efx_port_dummy_op_void, +#endif + .revision =EFX_REV_HUNT_A0 , + .max_dma_mask =DMA_BIT_MASK (ESF_DZ_TX_KER_BUF_ADDR_WIDTH ), + .rx_prefix_size =ES_DZ_RX_PREFIX_SIZE , + .rx_hash_offset =ES_DZ_RX_PREFIX_HASH_OFST , + .rx_ts_offset =ES_DZ_RX_PREFIX_TSTAMP_OFST , + .can_rx_scatter = true, + .always_rx_scatter = true, + .max_interrupt_mode =EFX_INT_MODE_MSIX , + .timer_period_max =1 <<ERF_DD_EVQ_IND_TIMER_VAL_WIDTH , + .offload_features = (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM | +NETIF_F_RXHASH |NETIF_F_NTUPLE ), + .mcdi_max_ver =2 , + .max_rx_ip_filters =HUNT_FILTER_TBL_ROWS , + .hwtstamp_filters =1 <<HWTSTAMP_FILTER_NONE | +1 <<HWTSTAMP_FILTER_ALL , +}; +const struct efx_nic_type efx_hunt_a0_nic_type = { + .mem_bar =EFX_MEM_BAR , .mem_map_size = efx_ef10_mem_map_size, - .probe = efx_ef10_probe, + .probe = efx_ef10_probe_pf, .remove = efx_ef10_remove, .dimension_resources = efx_ef10_dimension_resources, .init = efx_ef10_init_nic,
drivers/net/ethernet/sfc/ef10_sriov.c +17 -0
@@ -46,6 +46,23 @@ int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs)return efx_ef10_pci_sriov_enable (efx, num_vfs); } +int efx_ef10_sriov_init (struct efx_nic *efx) +{ +return 0 ; +} + +void efx_ef10_sriov_fini (struct efx_nic *efx) +{ +int rc; + + rc =efx_ef10_pci_sriov_disable (efx); +if (rc) +netif_dbg (efx, drv, efx->net_dev, +"Disabling SRIOV was not successful rc=%d\n" , rc); +else +netif_dbg (efx, drv, efx->net_dev,"SRIOV disabled\n" ); +} +static int efx_ef10_vswitch_alloc (struct efx_nic *efx,unsigned int port_id,unsigned int vswitch_type) {
drivers/net/ethernet/sfc/ef10_sriov.h +2 -7
@@ -18,15 +18,10 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) }int efx_ef10_sriov_configure (struct efx_nic *efx,int num_vfs); - -static inline int efx_ef10_sriov_init (struct efx_nic *efx) -{ -return -EOPNOTSUPP ; -} - +int efx_ef10_sriov_init (struct efx_nic *efx);static inline void efx_ef10_sriov_mac_address_changed (struct efx_nic *efx) {}static inline void efx_ef10_sriov_reset (struct efx_nic *efx) {} -static inline void efx_ef10_sriov_fini (struct efx_nic *efx) {} +void efx_ef10_sriov_fini (struct efx_nic *efx);static inline void efx_ef10_sriov_flr (struct efx_nic *efx,unsigned vf_i) {} static inline int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf,
drivers/net/ethernet/sfc/efx.c +10 -5
@@ -1201,10 +1201,12 @@ static int efx_init_io(struct efx_nic *efx)struct pci_dev *pci_dev = efx->pci_dev;dma_addr_t dma_mask = efx->type->max_dma_mask;unsigned int mem_map_size = efx->type->mem_map_size (efx); -int rc; +int rc, bar;netif_dbg (efx, probe, efx->net_dev,"initialising I/O\n" ); + bar = efx->type->mem_bar; + rc =pci_enable_device (pci_dev);if (rc) { netif_err(efx, probe, efx->net_dev,
@@ -1235,8 +1237,8 @@ static int efx_init_io(struct efx_nic *efx)netif_dbg (efx, probe, efx->net_dev,"using DMA mask %llx\n" , (unsigned long long ) dma_mask); - efx->membase_phys =pci_resource_start (efx->pci_dev,EFX_MEM_BAR ); - rc =pci_request_region (pci_dev,EFX_MEM_BAR ,"sfc" ); + efx->membase_phys =pci_resource_start (efx->pci_dev, bar); + rc =pci_request_region (pci_dev, bar,"sfc" );if (rc) {netif_err (efx, probe, efx->net_dev,"request for memory BAR failed\n" );
@@ -1259,7 +1261,7 @@ static int efx_init_io(struct efx_nic *efx)return 0 ; fail4: -pci_release_region (efx->pci_dev,EFX_MEM_BAR ); +pci_release_region (efx->pci_dev, bar); fail3: efx->membase_phys =0 ; fail2:
@@ -1270,6 +1272,8 @@ static int efx_init_io(struct efx_nic *efx)static void efx_fini_io (struct efx_nic *efx) { +int bar; +netif_dbg (efx, drv, efx->net_dev,"shutting down I/O\n" );if (efx->membase) {
@@ -1278,7 +1282,8 @@ static void efx_fini_io(struct efx_nic *efx) }if (efx->membase_phys) { -pci_release_region (efx->pci_dev,EFX_MEM_BAR ); + bar = efx->type->mem_bar; +pci_release_region (efx->pci_dev, bar); efx->membase_phys =0 ; }
drivers/net/ethernet/sfc/efx.h +2 -0
@@ -15,7 +15,9 @@#include "filter.h" /* All controllers use BAR 0 for I/O space and BAR 2(&3) for memory */ +/* All VFs use BAR 0/1 for memory */ #define EFX_MEM_BAR 2 +#define EFX_MEM_VF_BAR 0/* TX */ int efx_probe_tx_queue (struct efx_tx_queue *tx_queue);
drivers/net/ethernet/sfc/falcon.c +2 -0
@@ -2687,6 +2687,7 @@ static int falcon_set_wol(struct efx_nic *efx, u32 type)*/ const struct efx_nic_type falcon_a1_nic_type = { + .mem_bar =EFX_MEM_BAR , .mem_map_size = falcon_a1_mem_map_size, .probe = falcon_probe_nic, .remove = falcon_remove_nic,
@@ -2783,6 +2784,7 @@ const struct efx_nic_type falcon_a1_nic_type = { };const struct efx_nic_type falcon_b0_nic_type = { + .mem_bar =EFX_MEM_BAR , .mem_map_size = falcon_b0_mem_map_size, .probe = falcon_probe_nic, .remove = falcon_remove_nic,
drivers/net/ethernet/sfc/net_driver.h +2 -0
@@ -1089,6 +1089,7 @@ struct efx_mtd_partition {/** * struct efx_nic_type - Efx device type definition +* @mem_bar: Get the memory BAR * @mem_map_size: Get memory BAR mapped size * @probe: Probe the controller * @remove: Free resources allocated by probe()
@@ -1223,6 +1224,7 @@ struct efx_mtd_partition {* @hwtstamp_filters: Mask of hardware timestamp filter types supported */ struct efx_nic_type { +unsigned int mem_bar;unsigned int (*mem_map_size)(struct efx_nic *efx);int (*probe)(struct efx_nic *efx);void (*remove)(struct efx_nic *efx);
drivers/net/ethernet/sfc/nic.h +1 -0
@@ -555,6 +555,7 @@ extern const struct efx_nic_type falcon_a1_nic_type;extern const struct efx_nic_type falcon_b0_nic_type;extern const struct efx_nic_type siena_a0_nic_type;extern const struct efx_nic_type efx_hunt_a0_nic_type; +extern const struct efx_nic_type efx_hunt_a0_vf_nic_type;/************************************************************************** *
drivers/net/ethernet/sfc/siena.c +1 -0
@@ -912,6 +912,7 @@ fail:*/ const struct efx_nic_type siena_a0_nic_type = { + .mem_bar =EFX_MEM_BAR , .mem_map_size = siena_mem_map_size, .probe = siena_probe_nic, .remove = siena_remove_nic,
PATCH 10/14 sfc: create vports for VFs and assign random MAC addresses
In reply to Shradha ShahThe parent PF creates vports for all its child VFs and adds MAC addresses to these. When the VF driver loads, it can make an MCDI call to get the MAC address that the parent PF assigned it.
The parent PF also assigns a mac address to its own vport because implicit creation of a vAdaptor will only work on evb ports with MAC addresses assigned.
The vport MAC address needs to be stored in the PF's nic_data struct as it can later be changed on the vadaptor (and its net_dev struct). When removing a vport the original MAC address must be deleted.
A new flag is needed in the VF data structure to identify whether a vport has been assigned to the VF. This is to determine whether it needs to be un-assigned before freeing the vport. Also, attempting to un-assign a vport which is not assigned will result in an EALREADY error.
--- drivers/net/ethernet/sfc/ef10_sriov.c | 262 +++++++++++++++++++++++++++++----- drivers/net/ethernet/sfc/ef10_sriov.h | 12 ++ drivers/net/ethernet/sfc/nic.h | 7 + 3 files changed, 244 insertions(+), 37 deletions(-)
drivers/net/ethernet/sfc/ef10_sriov.c +225 -37
@@ -14,53 +14,43 @@#include "nic.h" #include "mcdi_pcol.h" -static int efx_ef10_pci_sriov_enable (struct efx_nic *efx,int num_vfs) +static int efx_ef10_evb_port_assign (struct efx_nic *efx,unsigned int port_id, +unsigned int vf_fn) { -int rc =0 ; -struct pci_dev *dev = efx->pci_dev; +MCDI_DECLARE_BUF (inbuf,MC_CMD_EVB_PORT_ASSIGN_IN_LEN ); +struct efx_ef10_nic_data *nic_data = efx->nic_data; - efx->vf_count = num_vfs; - rc =pci_enable_sriov (dev, num_vfs); -if (rc) { - efx->vf_count =0 ; -netif_err (efx, probe, efx->net_dev, -"Failed to enable SRIOV VFs\n" ); - } -return rc; +MCDI_SET_DWORD (inbuf,EVB_PORT_ASSIGN_IN_PORT_ID , port_id); +MCDI_POPULATE_DWORD_2 (inbuf,EVB_PORT_ASSIGN_IN_FUNCTION , +EVB_PORT_ASSIGN_IN_PF , nic_data->pf_index, +EVB_PORT_ASSIGN_IN_VF , vf_fn); + +return efx_mcdi_rpc (efx,MC_CMD_EVB_PORT_ASSIGN , inbuf,sizeof (inbuf), +NULL ,0 ,NULL ); } -static int efx_ef10_pci_sriov_disable (struct efx_nic *efx) +static int efx_ef10_vport_add_mac (struct efx_nic *efx, +unsigned int port_id,u8 *mac) { -struct pci_dev *dev = efx->pci_dev; +MCDI_DECLARE_BUF (inbuf,MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN ); - efx->vf_count =0 ; -pci_disable_sriov (dev); -return 0 ; -} +MCDI_SET_DWORD (inbuf,VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID , port_id); +ether_addr_copy (MCDI_PTR (inbuf,VPORT_ADD_MAC_ADDRESS_IN_MACADDR ), mac); -int efx_ef10_sriov_configure (struct efx_nic *efx,int num_vfs) -{ -if (num_vfs ==0 ) -return efx_ef10_pci_sriov_disable (efx); -else -return efx_ef10_pci_sriov_enable (efx, num_vfs); +return efx_mcdi_rpc (efx,MC_CMD_VPORT_ADD_MAC_ADDRESS , inbuf, +sizeof (inbuf),NULL ,0 ,NULL ); } -int efx_ef10_sriov_init (struct efx_nic *efx) +static int efx_ef10_vport_del_mac (struct efx_nic *efx, +unsigned int port_id,u8 *mac) { -return 0 ; -} +MCDI_DECLARE_BUF (inbuf,MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN ); -void efx_ef10_sriov_fini (struct efx_nic *efx) -{ -int rc; +MCDI_SET_DWORD (inbuf,VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID , port_id); +ether_addr_copy (MCDI_PTR (inbuf,VPORT_DEL_MAC_ADDRESS_IN_MACADDR ), mac); - rc =efx_ef10_pci_sriov_disable (efx); -if (rc) -netif_dbg (efx, drv, efx->net_dev, -"Disabling SRIOV was not successful rc=%d\n" , rc); -else -netif_dbg (efx, drv, efx->net_dev,"SRIOV disabled\n" ); +return efx_mcdi_rpc (efx,MC_CMD_VPORT_DEL_MAC_ADDRESS , inbuf, +sizeof (inbuf),NULL ,0 ,NULL ); } static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
@@ -127,12 +117,124 @@ static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id) NULL, 0, NULL); } +static void efx_ef10_sriov_free_vf_vports (struct efx_nic *efx) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; +int i; + +if (!nic_data->vf) +return ; + +for (i =0 ; i < efx->vf_count; i++) { +struct ef10_vf *vf = nic_data->vf + i; + +if (vf->vport_assigned) { +efx_ef10_evb_port_assign (efx,EVB_PORT_ID_NULL , i); + vf->vport_assigned =0 ; + } + +if (!is_zero_ether_addr (vf->mac)) { +efx_ef10_vport_del_mac (efx, vf->vport_id, vf->mac); +eth_zero_addr (vf->mac); + } + +if (vf->vport_id) { +efx_ef10_vport_free (efx, vf->vport_id); + vf->vport_id =0 ; + } + } +} + +static void efx_ef10_sriov_free_vf_vswitching (struct efx_nic *efx) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; + +efx_ef10_sriov_free_vf_vports (efx); +kfree (nic_data->vf); + nic_data->vf =NULL ; +} + +static int efx_ef10_sriov_assign_vf_vport (struct efx_nic *efx, +unsigned int vf_i) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; +struct ef10_vf *vf = nic_data->vf + vf_i; +int rc; + +if (WARN_ON_ONCE (!nic_data->vf)) +return -EOPNOTSUPP ; + + rc =efx_ef10_vport_alloc (efx,EVB_PORT_ID_ASSIGNED , +MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL , + &vf->vport_id); +if (rc) +return rc; + + rc =efx_ef10_vport_add_mac (efx, vf->vport_id, vf->mac); +if (rc) { +eth_zero_addr (vf->mac); +return rc; + } + + rc =efx_ef10_evb_port_assign (efx, vf->vport_id, vf_i); +if (rc) +return rc; + + vf->vport_assigned =1 ; +return 0 ; +} + +static int efx_ef10_sriov_alloc_vf_vswitching (struct efx_nic *efx) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; +unsigned int i; +int rc; + + nic_data->vf =kcalloc (efx->vf_count,sizeof (struct ef10_vf ), +GFP_KERNEL ); +if (!nic_data->vf) +return -ENOMEM ; + +for (i =0 ; i < efx->vf_count; i++) { +random_ether_addr (nic_data->vf[i].mac); + + rc =efx_ef10_sriov_assign_vf_vport (efx, i); +if (rc) + goto fail; + } + +return 0 ; +fail: +efx_ef10_sriov_free_vf_vports (efx); +kfree (nic_data->vf); + nic_data->vf =NULL ; +return rc; +} + +static int efx_ef10_sriov_restore_vf_vswitching (struct efx_nic *efx) +{ +unsigned int i; +int rc; + +for (i =0 ; i < efx->vf_count; i++) { + rc =efx_ef10_sriov_assign_vf_vport (efx, i); +if (rc) + goto fail; + } + +return 0 ; +fail: +efx_ef10_sriov_free_vf_vswitching (efx); +return rc; +} +/* On top of the default firmware vswitch setup, create a VEB vswitch and * expansion vport for use by this function. */ int efx_ef10_vswitching_probe (struct efx_nic *efx) {struct efx_ef10_nic_data *nic_data = efx->nic_data; +struct net_device *net_dev = efx->net_dev;int rc;if (pci_sriov_get_totalvfs (efx->pci_dev) <=0 )
@@ -149,7 +251,16 @@ int efx_ef10_vswitching_probe(struct efx_nic *efx)if (rc) goto fail2; + rc =efx_ef10_vport_add_mac (efx, nic_data->vport_id, net_dev->dev_addr); +if (rc) + goto fail3; + +ether_addr_copy (nic_data->vport_mac, net_dev->dev_addr); +return 0 ; +fail3: +efx_ef10_vport_free (efx, nic_data->vport_id); + nic_data->vport_id =EVB_PORT_ID_ASSIGNED ; fail2:efx_ef10_vswitch_free (efx,EVB_PORT_ID_ASSIGNED ); fail1:
@@ -165,9 +276,15 @@ int efx_ef10_vswitching_restore(struct efx_nic *efx)return 0 ; rc =efx_ef10_vswitching_probe (efx); +if (rc) + goto fail; + + rc =efx_ef10_sriov_restore_vf_vswitching (efx); +if (rc) + goto fail; -if (!rc) - nic_data->must_probe_vswitching = false; + nic_data->must_probe_vswitching = false; +fail:return rc; }
@@ -175,11 +292,82 @@ void efx_ef10_vswitching_remove(struct efx_nic *efx) {struct efx_ef10_nic_data *nic_data = efx->nic_data; +efx_ef10_sriov_free_vf_vswitching (efx); +if (nic_data->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->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_vswitch_free (efx, nic_data->vport_id); } + +static int efx_ef10_pci_sriov_enable (struct efx_nic *efx,int num_vfs) +{ +int rc =0 ; +struct pci_dev *dev = efx->pci_dev; + + efx->vf_count = num_vfs; + + rc =efx_ef10_sriov_alloc_vf_vswitching (efx); +if (rc) + goto fail1; + + rc =pci_enable_sriov (dev, num_vfs); +if (rc) + goto fail2; + +return 0 ; +fail2: +efx_ef10_sriov_free_vf_vswitching (efx); +fail1: + efx->vf_count =0 ; +netif_err (efx, probe, efx->net_dev, +"Failed to enable SRIOV VFs\n" ); +return rc; +} + +static int efx_ef10_pci_sriov_disable (struct efx_nic *efx) +{ +struct pci_dev *dev = efx->pci_dev; + +pci_disable_sriov (dev); +efx_ef10_sriov_free_vf_vswitching (efx); + efx->vf_count =0 ; +return 0 ; +} + +int efx_ef10_sriov_configure (struct efx_nic *efx,int num_vfs) +{ +if (num_vfs ==0 ) +return efx_ef10_pci_sriov_disable (efx); +else +return efx_ef10_pci_sriov_enable (efx, num_vfs); +} + +int efx_ef10_sriov_init (struct efx_nic *efx) +{ +return 0 ; +} + +void efx_ef10_sriov_fini (struct efx_nic *efx) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; +int rc; + +if (!nic_data->vf) +return ; + + rc =efx_ef10_pci_sriov_disable (efx); +if (rc) +netif_dbg (efx, drv, efx->net_dev, +"Disabling SRIOV was not successful rc=%d\n" , rc); +else +netif_dbg (efx, drv, efx->net_dev,"SRIOV disabled\n" ); +}
drivers/net/ethernet/sfc/ef10_sriov.h +12 -0
@@ -12,6 +12,18 @@#include "net_driver.h" +/** +* struct ef10_vf - PF's store of VF data +* @vport_id: vport ID for the VF +* @vport_assigned: record whether the vport is currently assigned to the VF +* @mac: MAC address for the VF, zero when address is removed from the vport +*/ +struct ef10_vf { +unsigned int vport_id; +unsigned int vport_assigned; +u8 mac[ETH_ALEN ]; +}; +static inline bool efx_ef10_sriov_wanted (struct efx_nic *efx) {return false;
drivers/net/ethernet/sfc/nic.h +7 -0
@@ -496,6 +496,9 @@ enum {* @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 +* @vf: Pointer to VF data structure +#endif */ struct efx_ef10_nic_data {struct efx_buffer mcdi_buf;
@@ -519,6 +522,10 @@ struct efx_ef10_nic_data {unsigned int vport_id;bool must_probe_vswitching;unsigned int pf_index; +#ifdef CONFIG_SFC_SRIOV +struct ef10_vf *vf; +#endif +u8 vport_mac[ETH_ALEN ]; };int efx_init_sriov (void );
PATCH 11/14 sfc: manually allocate and free vadaptors
In reply to Shradha ShahTo be able to use MC_CMD_VADAPTOR_SET_MAC, vadaptors must be manually allocated and freed as automatic vadaptors will disappear when their reference_count reaches zero, which must happen before the MAC address is changed.
Vadaptors are allocated and freed in the vswitching_probe/remove functions for PFs and VFs, and this means that vadaptors are restored correctly following an MC reboot or other reset when required.
--- drivers/net/ethernet/sfc/ef10.c | 12 +++--- drivers/net/ethernet/sfc/ef10_sriov.c | 71 +++++++++++++++++++++++++++++++---- drivers/net/ethernet/sfc/ef10_sriov.h | 9 +++-- 3 files changed, 76 insertions(+), 16 deletions(-)
drivers/net/ethernet/sfc/ef10.c +6 -6
@@ -3760,9 +3760,9 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .ptp_write_host_time = efx_ef10_ptp_write_host_time_vf, .ptp_set_ts_config = efx_ef10_ptp_set_ts_config_vf, #ifdef CONFIG_SFC_SRIOV - .vswitching_probe = efx_port_dummy_op_int, - .vswitching_restore = efx_port_dummy_op_int, - .vswitching_remove = efx_port_dummy_op_void, + .vswitching_probe = efx_ef10_vswitching_probe_vf, + .vswitching_restore = efx_ef10_vswitching_restore_vf, + .vswitching_remove = efx_ef10_vswitching_remove_vf, #endif .revision =EFX_REV_HUNT_A0 , .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
@@ -3876,9 +3876,9 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan, .sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk, .sriov_get_vf_config = efx_ef10_sriov_get_vf_config, - .vswitching_probe = efx_ef10_vswitching_probe, - .vswitching_restore = efx_ef10_vswitching_restore, - .vswitching_remove = efx_ef10_vswitching_remove, + .vswitching_probe = efx_ef10_vswitching_probe_pf, + .vswitching_restore = efx_ef10_vswitching_restore_pf, + .vswitching_remove = efx_ef10_vswitching_remove_pf, #endif .revision = EFX_REV_HUNT_A0,
drivers/net/ethernet/sfc/ef10_sriov.c +64 -7
126 lines not on this page · raw message
drivers/net/ethernet/sfc/ef10_sriov.h +6 -3
@@ -60,8 +60,11 @@ static inline int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf, return -EOPNOTSUPP; } -int efx_ef10_vswitching_probe (struct efx_nic *efx); -int efx_ef10_vswitching_restore (struct efx_nic *efx); -void efx_ef10_vswitching_remove (struct efx_nic *efx); +int efx_ef10_vswitching_probe_pf (struct efx_nic *efx); +int efx_ef10_vswitching_probe_vf (struct efx_nic *efx); +int efx_ef10_vswitching_restore_pf (struct efx_nic *efx); +int efx_ef10_vswitching_restore_vf (struct efx_nic *efx); +void efx_ef10_vswitching_remove_pf (struct efx_nic *efx); +void efx_ef10_vswitching_remove_vf (struct efx_nic *efx);#endif /* EF10_SRIOV_H */
PATCH 12/14 sfc: Cope with permissions enforcement added to firmware for SR-IOV
In reply to Shradha ShahFrom: Edward Cree <[email protected]>
* Accept EPERM in some simple cases, the following cases are handled:
1) efx_mcdi_read_assertion()
Unprivileged PCI functions aren't allowed to GET_ASSERTS.
We return success as it's up to the primary PF to deal with asserts.
2) efx_mcdi_mon_probe() in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to read sensor info, and worrying about sensor data is the primary PF's job.
3) phy_op->reconfigure() in efx_init_port() and efx_reset_up() Unprivileged functions aren't allowed to MC_CMD_SET_LINK, they just have to accept the settings (including flow-control, which is what efx_init_port() is worried about) they've been given.
4) Fallback to GET_WORKAROUNDS in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to set workarounds. So if efx_mcdi_set_workaround() fails EPERM, use efx_mcdi_get_workarounds() to find out if workaround_35388 is enabled.
5) If DRV_ATTACH gets EPERM, try without specifying fw-variant Unprivileged PCI functions have to use a FIRMWARE_ID of 0xffffffff (MC_CMD_FW_DONT_CARE).
6) Don't try to exit_assertion unless one had fired
Previously we called efx_mcdi_exit_assertion even if efx_mcdi_read_assertion had received MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS. This is unnecessary, and the resulting MC_CMD_REBOOT, even if the AFTER_ASSERTION flag made it a no-op, would fail EPERM for unprivileged PCI functions.
So make efx_mcdi_read_assertion return whether an assert happened, and only call efx_mcdi_exit_assertion if it has.
--- drivers/net/ethernet/sfc/ef10.c | 16 ++++++- drivers/net/ethernet/sfc/efx.c | 5 ++- drivers/net/ethernet/sfc/mcdi.c | 82 ++++++++++++++++++++++++++++++------ drivers/net/ethernet/sfc/mcdi.h | 2 + drivers/net/ethernet/sfc/mcdi_pcol.h | 23 ++++++++++ 5 files changed, 111 insertions(+), 17 deletions(-)
drivers/net/ethernet/sfc/ef10.c +14 -2
@@ -286,10 +286,22 @@ static int efx_ef10_probe(struct efx_nic *efx) goto fail3; efx->timer_quantum_ns =1536000 / rc;/* 1536 cycles */ -/* Check whether firmware supports bug 35388 workaround */ +/* Check whether firmware supports bug 35388 workaround. +* First try to enable it, then if we get EPERM, just +* ask if it's already enabled +*/ rc =efx_mcdi_set_workaround (efx,MC_CMD_WORKAROUND_BUG35388 , true);if (rc ==0 ) nic_data->workaround_35388 = true; +else if (rc == -EPERM ) { +unsigned int enabled; + + rc =efx_mcdi_get_workarounds (efx,NULL , &enabled); +if (rc) + goto fail3; + nic_data->workaround_35388 = enabled & +MC_CMD_GET_WORKAROUNDS_OUT_BUG35388 ; + }else if (rc != -ENOSYS && rc != -ENOENT ) goto fail3; netif_dbg(efx, probe, efx->net_dev,
@@ -297,7 +309,7 @@ static int efx_ef10_probe(struct efx_nic *efx) nic_data->workaround_35388 ? "en" : "dis"); rc =efx_mcdi_mon_probe (efx); -if (rc) +if (rc && rc != -EPERM ) goto fail3;efx_ptp_probe (efx,NULL );
drivers/net/ethernet/sfc/efx.c +3 -2
@@ -1046,7 +1046,7 @@ static int efx_init_port(struct efx_nic *efx)/* Ensure the PHY advertises the correct flow control settings */ rc = efx->phy_op->reconfigure (efx); -if (rc) +if (rc && rc != -EPERM ) goto fail2;mutex_unlock (&efx->mac_lock);
@@ -2429,7 +2429,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) rc = efx->phy_op->init (efx);if (rc) goto fail; -if (efx->phy_op->reconfigure (efx)) + rc = efx->phy_op->reconfigure (efx); +if (rc && rc != -EPERM )netif_err (efx, drv, efx->net_dev,"could not restore PHY settings\n" ); }
drivers/net/ethernet/sfc/mcdi.c +69 -13
133 lines not on this page · raw message
drivers/net/ethernet/sfc/mcdi.h +2 -0
@@ -339,6 +339,8 @@ bool efx_mcdi_mac_check_fault(struct efx_nic *efx);enum reset_type efx_mcdi_map_reset_reason (enum reset_type reason);int efx_mcdi_reset (struct efx_nic *efx,enum reset_type method);int efx_mcdi_set_workaround (struct efx_nic *efx,u32 type,bool enabled); +int efx_mcdi_get_workarounds (struct efx_nic *efx,unsigned int *impl_out, +unsigned int *enabled_out);#ifdef CONFIG_SFC_MCDI_MON int efx_mcdi_mon_probe (struct efx_nic *efx);
drivers/net/ethernet/sfc/mcdi_pcol.h +23 -0
@@ -1875,6 +1875,8 @@#define MC_CMD_FW_FULL_FEATURED 0x0/* enum: Prefer to use firmware with fewer features but lower latency */ #define MC_CMD_FW_LOW_LATENCY 0x1 +/* enum: Only this option is allowed for non-admin functions */ +#define MC_CMD_FW_DONT_CARE 0xffffffff/* MC_CMD_DRV_ATTACH_OUT msgresponse */ #define MC_CMD_DRV_ATTACH_OUT_LEN 4
@@ -4087,6 +4089,27 @@/***********************************/ +/* MC_CMD_GET_WORKAROUNDS +* Read the list of all implemented and all currently enabled workarounds. The +* enums here must correspond with those in MC_CMD_WORKAROUND. +*/ +#define MC_CMD_GET_WORKAROUNDS 0x59 + +/* MC_CMD_GET_WORKAROUNDS_OUT msgresponse */ +#define MC_CMD_GET_WORKAROUNDS_OUT_LEN 8 +/* Each workaround is represented by a single bit according to the enums below. +*/ +#define MC_CMD_GET_WORKAROUNDS_OUT_IMPLEMENTED_OFST 0 +#define MC_CMD_GET_WORKAROUNDS_OUT_ENABLED_OFST 4 +/* enum: Bug 17230 work around. */ +#define MC_CMD_GET_WORKAROUNDS_OUT_BUG17230 0x2 +/* enum: Bug 35388 work around (unsafe EVQ writes). */ +#define MC_CMD_GET_WORKAROUNDS_OUT_BUG35388 0x4 +/* enum: Bug35017 workaround (A64 tables must be identity map) */ +#define MC_CMD_GET_WORKAROUNDS_OUT_BUG35017 0x8 + + +/***********************************/ /* MC_CMD_READ_REGS * Get a dump of the MCPU registers */
PATCH 13/14 sfc: Add use of shared RSS contexts.
In reply to Shradha ShahFrom: Jon Cooper <[email protected]>
Allow PFs to allocate shared RSS contexts if we exhaust our exclusive RSS contexts. Make VFs use shared RSS contexts in all cases.
Spruce up error handling so that the shadow copy of the RSS table is updated after successful update, rather than in all cases, so that we report the actual contents of the RSS table after a failure to set it, rather than what we'd like it to be.
Populate context_size parameter when vacuously allocating RSS context of size 1.
--- drivers/net/ethernet/sfc/ef10.c | 157 +++++++++++++++++++++++++++++----- drivers/net/ethernet/sfc/efx.c | 17 ++-- drivers/net/ethernet/sfc/efx.h | 1 + drivers/net/ethernet/sfc/ethtool.c | 5 +- drivers/net/ethernet/sfc/falcon.c | 19 +++- drivers/net/ethernet/sfc/net_driver.h | 3 +- drivers/net/ethernet/sfc/nic.h | 2 + drivers/net/ethernet/sfc/siena.c | 9 +- 8 files changed, 177 insertions(+), 36 deletions(-)
drivers/net/ethernet/sfc/ef10.c +135 -22
@@ -31,6 +31,9 @@ enum {/* The reserved RSS context value */ #define EFX_EF10_RSS_CONTEXT_INVALID 0xffffffff +/* The maximum size of a shared RSS context */ +/* TODO: this should really be from the mcdi protocol export */ +#define EFX_EF10_MAX_SHARED_RSS_CONTEXT_SIZE 64UL/* The filter table(s) are managed by firmware and we have write-only * access. When removing filters we must identify them to the
@@ -78,7 +81,6 @@ struct efx_ef10_filter_table {/* An arbitrary search limit for the software hash table */ #define EFX_EF10_FILTER_SEARCH_LIMIT 200 -static void efx_ef10_rx_push_rss_config (struct efx_nic *efx);static void efx_ef10_rx_free_indir_table (struct efx_nic *efx);static void efx_ef10_filter_table_remove (struct efx_nic *efx);
@@ -751,7 +753,9 @@ static int efx_ef10_init_nic(struct efx_nic *efx) nic_data->must_restore_piobufs = false; } -efx_ef10_rx_push_rss_config (efx); +/* don't fail init if RSS setup doesn't work */ + efx->type->rx_push_rss_config (efx, false, efx->rx_indir_table); +return 0 ; }
@@ -1455,20 +1459,33 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue) } } -static int efx_ef10_alloc_rss_context (struct efx_nic *efx,u32 *context) +static int efx_ef10_alloc_rss_context (struct efx_nic *efx,u32 *context, +bool exclusive,unsigned *context_size) {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 ? +MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE : +MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED ; +unsigned rss_spread = exclusive ? + efx->rss_spread : +min (rounddown_pow_of_two (efx->rss_spread), +EFX_EF10_MAX_SHARED_RSS_CONTEXT_SIZE ); + +if (!exclusive && rss_spread ==1 ) { + *context =EFX_EF10_RSS_CONTEXT_INVALID ; +if (context_size) + *context_size =1 ; +return 0 ; + }MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID , nic_data->vport_id); -MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_TYPE , -MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE ); -MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_NUM_QUEUES , -EFX_MAX_CHANNELS ); +MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_TYPE , alloc_type); +MCDI_SET_DWORD (inbuf,RSS_CONTEXT_ALLOC_IN_NUM_QUEUES , rss_spread); rc =efx_mcdi_rpc (efx,MC_CMD_RSS_CONTEXT_ALLOC , inbuf,sizeof (inbuf), outbuf,sizeof (outbuf), &outlen);
@@ -1480,6 +1497,9 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context) *context =MCDI_DWORD (outbuf,RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID ); +if (context_size) + *context_size = rss_spread; +return 0 ; }
@@ -1496,7 +1516,8 @@ static void efx_ef10_free_rss_context(struct efx_nic *efx, u32 context)WARN_ON (rc !=0 ); } -static int efx_ef10_populate_rss_table (struct efx_nic *efx,u32 context) +static int efx_ef10_populate_rss_table (struct efx_nic *efx,u32 context, +const u32 *rx_indir_table) {MCDI_DECLARE_BUF (tablebuf,MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN );MCDI_DECLARE_BUF (keybuf,MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN );
@@ -1510,7 +1531,7 @@ static int efx_ef10_populate_rss_table(struct efx_nic *efx, u32 context)for (i =0 ; i <ARRAY_SIZE (efx->rx_indir_table); ++i)MCDI_PTR (tablebuf,RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE )[i] = - (u8 ) efx->rx_indir_table[i]; + (u8 ) rx_indir_table[i]; rc =efx_mcdi_rpc (efx,MC_CMD_RSS_CONTEXT_SET_TABLE , tablebuf,sizeof (tablebuf),NULL ,0 ,NULL );
@@ -1538,27 +1559,119 @@ static void efx_ef10_rx_free_indir_table(struct efx_nic *efx) nic_data->rx_rss_context =EFX_EF10_RSS_CONTEXT_INVALID ; } -static void efx_ef10_rx_push_rss_config (struct efx_nic *efx) +static int efx_ef10_rx_push_shared_rss_config (struct efx_nic *efx, +unsigned *context_size) { +u32 new_rx_rss_context;struct efx_ef10_nic_data *nic_data = efx->nic_data; -int rc; +int rc =efx_ef10_alloc_rss_context (efx, &new_rx_rss_context, + false, context_size); + +if (rc !=0 ) +return rc; -netif_dbg (efx, drv, efx->net_dev,"pushing RSS config\n" ); + nic_data->rx_rss_context = new_rx_rss_context; + nic_data->rx_rss_context_exclusive = false; +efx_set_default_rx_indir_table (efx); +return 0 ; +} -if (nic_data->rx_rss_context ==EFX_EF10_RSS_CONTEXT_INVALID ) { - rc =efx_ef10_alloc_rss_context (efx, &nic_data->rx_rss_context); -if (rc !=0 ) - goto fail; +static int efx_ef10_rx_push_exclusive_rss_config (struct efx_nic *efx, +const u32 *rx_indir_table) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; +int rc; +u32 new_rx_rss_context; + +if (nic_data->rx_rss_context ==EFX_EF10_RSS_CONTEXT_INVALID || + !nic_data->rx_rss_context_exclusive) { + rc =efx_ef10_alloc_rss_context (efx, &new_rx_rss_context, + true,NULL ); +if (rc == -EOPNOTSUPP ) +return rc; +else if (rc !=0 ) + goto fail1; + }else { + new_rx_rss_context = nic_data->rx_rss_context; } - rc =efx_ef10_populate_rss_table (efx, nic_data->rx_rss_context); + rc =efx_ef10_populate_rss_table (efx, new_rx_rss_context, + rx_indir_table);if (rc !=0 ) - goto fail; + goto fail2; -return ; +if (nic_data->rx_rss_context != new_rx_rss_context) +efx_ef10_rx_free_indir_table (efx); + nic_data->rx_rss_context = new_rx_rss_context; + nic_data->rx_rss_context_exclusive = true; +if (rx_indir_table != efx->rx_indir_table) +memcpy (efx->rx_indir_table, rx_indir_table, +sizeof (efx->rx_indir_table)); +return 0 ; -fail: +fail2: +if (new_rx_rss_context != nic_data->rx_rss_context) +efx_ef10_free_rss_context (efx, new_rx_rss_context); +fail1:netif_err (efx, hw, efx->net_dev,"%s: failed rc=%d\n" , __func__, rc); +return rc; +} + +static int efx_ef10_pf_rx_push_rss_config (struct efx_nic *efx,bool user, +const u32 *rx_indir_table) +{ +int rc; + +if (efx->rss_spread ==1 ) +return 0 ; + + rc =efx_ef10_rx_push_exclusive_rss_config (efx, rx_indir_table); + +if (rc == -ENOBUFS && !user) { +unsigned context_size; +bool mismatch = false; +size_t i; + +for (i =0 ; i <ARRAY_SIZE (efx->rx_indir_table) && !mismatch; + i++) + mismatch = rx_indir_table[i] != +ethtool_rxfh_indir_default (i, efx->rss_spread); + + rc =efx_ef10_rx_push_shared_rss_config (efx, &context_size); +if (rc ==0 ) { +if (context_size != efx->rss_spread) +netif_warn (efx, probe, efx->net_dev, +"Could not allocate an exclusive RSS" +" context; allocated a shared one of" +" different size." +" Wanted %u, got %u.\n" , + efx->rss_spread, context_size); +else if (mismatch) +netif_warn (efx, probe, efx->net_dev, +"Could not allocate an exclusive RSS" +" context; allocated a shared one but" +" could not apply custom" +" indirection.\n" ); +else +netif_info (efx, probe, efx->net_dev, +"Could not allocate an exclusive RSS" +" context; allocated a shared one.\n" ); + } + } +return rc; +} + +static int efx_ef10_vf_rx_push_rss_config (struct efx_nic *efx,bool user, +const u32 *rx_indir_table + __attribute__ ((unused))) +{ +struct efx_ef10_nic_data *nic_data = efx->nic_data; + +if (user) +return -EOPNOTSUPP ; +if (nic_data->rx_rss_context !=EFX_EF10_RSS_CONTEXT_INVALID ) +return 0 ; +return efx_ef10_rx_push_shared_rss_config (efx,NULL ); }static int efx_ef10_rx_probe (struct efx_rx_queue *rx_queue)
@@ -3738,7 +3851,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .tx_init = efx_ef10_tx_init, .tx_remove = efx_ef10_tx_remove, .tx_write = efx_ef10_tx_write, - .rx_push_rss_config = efx_ef10_rx_push_rss_config, + .rx_push_rss_config = efx_ef10_vf_rx_push_rss_config, .rx_probe = efx_ef10_rx_probe, .rx_init = efx_ef10_rx_init, .rx_remove = efx_ef10_rx_remove,
@@ -3837,7 +3950,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .tx_init = efx_ef10_tx_init, .tx_remove = efx_ef10_tx_remove, .tx_write = efx_ef10_tx_write, - .rx_push_rss_config = efx_ef10_rx_push_rss_config, + .rx_push_rss_config = efx_ef10_pf_rx_push_rss_config, .rx_probe = efx_ef10_rx_probe, .rx_init = efx_ef10_rx_init, .rx_remove = efx_ef10_rx_remove,
drivers/net/ethernet/sfc/efx.c +12 -5
@@ -1290,6 +1290,15 @@ static void efx_fini_io(struct efx_nic *efx)pci_disable_device (efx->pci_dev); } +void efx_set_default_rx_indir_table (struct efx_nic *efx) +{ +size_t i; + +for (i =0 ; i <ARRAY_SIZE (efx->rx_indir_table); i++) + efx->rx_indir_table[i] = +ethtool_rxfh_indir_default (i, efx->rss_spread); +} +static unsigned int efx_wanted_parallelism (struct efx_nic *efx) {cpumask_var_t thread_mask;
@@ -1607,7 +1616,6 @@ static void efx_set_channels(struct efx_nic *efx)static int efx_probe_nic (struct efx_nic *efx) { -size_t i;int rc;netif_dbg (efx, probe, efx->net_dev,"creating NIC\n" );
@@ -1630,10 +1638,9 @@ static int efx_probe_nic(struct efx_nic *efx) goto fail2;if (efx->n_channels >1 ) -netdev_rss_key_fill (&efx->rx_hash_key,sizeof (efx->rx_hash_key)); -for (i =0 ; i <ARRAY_SIZE (efx->rx_indir_table); i++) - efx->rx_indir_table[i] = -ethtool_rxfh_indir_default (i, efx->rss_spread); +netdev_rss_key_fill (&efx->rx_hash_key, +sizeof (efx->rx_hash_key)); +efx_set_default_rx_indir_table (efx);netif_set_real_num_tx_queues (efx->net_dev, efx->n_tx_channels);netif_set_real_num_rx_queues (efx->net_dev, efx->n_rx_channels);
drivers/net/ethernet/sfc/efx.h +1 -0
@@ -34,6 +34,7 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);extern unsigned int efx_piobuf_size;/* RX */ +void efx_set_default_rx_indir_table (struct efx_nic *efx);void efx_rx_config_page_split (struct efx_nic *efx);int efx_probe_rx_queue (struct efx_rx_queue *rx_queue);void efx_remove_rx_queue (struct efx_rx_queue *rx_queue);
drivers/net/ethernet/sfc/ethtool.c +2 -3
@@ -1109,9 +1109,8 @@ static int efx_ethtool_set_rxfh(struct net_device *net_dev, const u32 *indir,return -EOPNOTSUPP ;if (!indir)return 0 ; -memcpy (efx->rx_indir_table, indir,sizeof (efx->rx_indir_table)); - efx->type->rx_push_rss_config (efx); -return 0 ; + +return efx->type->rx_push_rss_config (efx, true, indir); } static int efx_ethtool_get_ts_info(struct net_device *net_dev,
drivers/net/ethernet/sfc/falcon.c +16 -3
@@ -477,16 +477,29 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)* ************************************************************************** */ +static int dummy_rx_push_rss_config (struct efx_nic *efx,bool user, +const u32 *rx_indir_table) +{ + (void ) efx; + (void ) user; + (void ) rx_indir_table; +return -ENOSYS ; +} -static void falcon_b0_rx_push_rss_config (struct efx_nic *efx) +static int falcon_b0_rx_push_rss_config (struct efx_nic *efx,bool user, +const u32 *rx_indir_table) {efx_oword_t temp; + (void ) user;/* Set hash key for IPv4 */ memcpy (&temp, efx->rx_hash_key,sizeof (temp));efx_writeo (efx, &temp,FR_BZ_RX_RSS_TKEY ); +memcpy (efx->rx_indir_table, rx_indir_table, +sizeof (efx->rx_indir_table));efx_farch_rx_push_indir_table (efx); +return 0 ; }/**************************************************************************
@@ -2507,7 +2520,7 @@ static int falcon_init_nic(struct efx_nic *efx)falcon_init_rx_cfg (efx);if (efx_nic_rev (efx) >=EFX_REV_FALCON_B0 ) { -falcon_b0_rx_push_rss_config (efx); +falcon_b0_rx_push_rss_config (efx, false, efx->rx_indir_table);/* Set destination of both TX and RX Flush events */ EFX_POPULATE_OWORD_1 (temp,FRF_BZ_FLS_EVQ_ID ,0 );
@@ -2730,7 +2743,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .tx_init = efx_farch_tx_init, .tx_remove = efx_farch_tx_remove, .tx_write = efx_farch_tx_write, - .rx_push_rss_config = efx_port_dummy_op_void, + .rx_push_rss_config = dummy_rx_push_rss_config, .rx_probe = efx_farch_rx_probe, .rx_init = efx_farch_rx_init, .rx_remove = efx_farch_rx_remove,
drivers/net/ethernet/sfc/net_driver.h +2 -1
@@ -1276,7 +1276,8 @@ struct efx_nic_type {void (*tx_init)(struct efx_tx_queue *tx_queue);void (*tx_remove)(struct efx_tx_queue *tx_queue);void (*tx_write)(struct efx_tx_queue *tx_queue); -void (*rx_push_rss_config)(struct efx_nic *efx); +int (*rx_push_rss_config)(struct efx_nic *efx,bool user, +const u32 *rx_indir_table);int (*rx_probe)(struct efx_rx_queue *rx_queue);void (*rx_init)(struct efx_rx_queue *rx_queue);void (*rx_remove)(struct efx_rx_queue *rx_queue);
drivers/net/ethernet/sfc/nic.h +2 -0
@@ -485,6 +485,7 @@ enum {* @must_restore_piobufs: Flag: PIO buffers have yet to be restored after MC * reboot * @rx_rss_context: Firmware handle for our RSS context +* @rx_rss_context_exclusive: Whether our RSS context is exclusive or shared * @stats: Hardware statistics * @workaround_35388: Flag: firmware supports workaround for bug 35388 * @must_check_datapath_caps: Flag: @datapath_caps needs to be revalidated
@@ -513,6 +514,7 @@ struct efx_ef10_nic_data {unsigned int piobuf_handle[EF10_TX_PIOBUF_COUNT ];bool must_restore_piobufs;u32 rx_rss_context; +bool rx_rss_context_exclusive;u64 stats[EF10_STAT_COUNT ];bool workaround_35388;bool must_check_datapath_caps;
drivers/net/ethernet/sfc/siena.c +7 -2
@@ -324,7 +324,8 @@ fail1:return rc; } -static void siena_rx_push_rss_config (struct efx_nic *efx) +static int siena_rx_push_rss_config (struct efx_nic *efx,bool user, +const u32 *rx_indir_table) {efx_oword_t temp;
@@ -346,7 +347,11 @@ static void siena_rx_push_rss_config(struct efx_nic *efx) FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);efx_writeo (efx, &temp,FR_CZ_RX_RSS_IPV6_REG3 ); +memcpy (efx->rx_indir_table, rx_indir_table, +sizeof (efx->rx_indir_table));efx_farch_rx_push_indir_table (efx); + +return 0 ; }/* This call performs hardware-specific global initialisation, such as
@@ -389,7 +394,7 @@ static int siena_init_nic(struct efx_nic *efx) EFX_RX_USR_BUF_SIZE >> 5);efx_writeo (efx, &temp,FR_AZ_RX_CFG ); -siena_rx_push_rss_config (efx); +siena_rx_push_rss_config (efx, false, efx->rx_indir_table);/* Enable event logging */ rc =efx_mcdi_log_ctrl (efx, true, false,0 );
PATCH 14/14 sfc: Bind the sfc driver to any available VF's
In reply to Shradha ShahAdd the device ID of the VF to the PCI device ID table.
Added a boolean flag is_vf in efx_nic_type to differentiate between a VF and PF at probe time. This flag is useful in later patches while setting MAC address specially in the PCI-passthrough case.
--- drivers/net/ethernet/sfc/ef10.c | 2 ++ drivers/net/ethernet/sfc/efx.c | 6 +++++- drivers/net/ethernet/sfc/falcon.c | 2 ++ drivers/net/ethernet/sfc/mcdi.c | 10 ---------- drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/siena.c | 1 + 6 files changed, 11 insertions(+), 11 deletions(-)
drivers/net/ethernet/sfc/ef10.c +2 -0
@@ -3810,6 +3810,7 @@ static int efx_ef10_ptp_set_ts_config(struct efx_nic *efx, }const struct efx_nic_type efx_hunt_a0_vf_nic_type = { + .is_vf = true, .mem_bar =EFX_MEM_VF_BAR , .mem_map_size = efx_ef10_mem_map_size, .probe = efx_ef10_probe_vf,
@@ -3907,6 +3908,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { };const struct efx_nic_type efx_hunt_a0_nic_type = { + .is_vf = false, .mem_bar =EFX_MEM_BAR , .mem_map_size = efx_ef10_mem_map_size, .probe = efx_ef10_probe_pf,
drivers/net/ethernet/sfc/efx.c +5 -1
@@ -1454,6 +1454,7 @@ static int efx_probe_interrupts(struct efx_nic *efx) }#endif efx->rss_spread = efx->n_rx_channels; +return 0 ; }
@@ -2676,6 +2677,8 @@ static const struct pci_device_id efx_pci_table[] = { .driver_data = (unsigned long) &siena_a0_nic_type}, {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903), /* SFC9120 PF */ .driver_data = (unsigned long) &efx_hunt_a0_nic_type}, + {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x1903), /* SFC9120 VF */ + .driver_data = (unsigned long) &efx_hunt_a0_vf_nic_type}, {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0923), /* SFC9140 PF */ .driver_data = (unsigned long) &efx_hunt_a0_nic_type}, {0} /* end of list */
@@ -3031,7 +3034,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,netif_info (efx, probe, efx->net_dev,"Solarflare NIC detected\n" ); -efx_probe_vpd_strings (efx); +if (!efx->type->is_vf) +efx_probe_vpd_strings (efx);/* Set up basic I/O (BAR mappings etc) */ rc =efx_init_io (efx);
drivers/net/ethernet/sfc/falcon.c +2 -0
@@ -2700,6 +2700,7 @@ static int falcon_set_wol(struct efx_nic *efx, u32 type)*/ const struct efx_nic_type falcon_a1_nic_type = { + .is_vf = false, .mem_bar =EFX_MEM_BAR , .mem_map_size = falcon_a1_mem_map_size, .probe = falcon_probe_nic,
@@ -2797,6 +2798,7 @@ const struct efx_nic_type falcon_a1_nic_type = { };const struct efx_nic_type falcon_b0_nic_type = { + .is_vf = false, .mem_bar =EFX_MEM_BAR , .mem_map_size = falcon_b0_mem_map_size, .probe = falcon_probe_nic,
drivers/net/ethernet/sfc/mcdi.c +0 -10
@@ -1186,16 +1186,6 @@ static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,* and are completely trusted by firmware. Abort probing * if that's not true for this function. */ -if (driver_operating && - (efx->mcdi->fn_flags & - (1 <<MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | -1 <<MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED )) != - (1 <<MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | -1 <<MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED )) { -netif_err (efx, probe, efx->net_dev, -"This driver version only supports one function per port\n" ); -return -ENODEV ; - }if (was_attached !=NULL ) *was_attached =MCDI_DWORD (outbuf,DRV_ATTACH_OUT_OLD_STATE );
drivers/net/ethernet/sfc/net_driver.h +1 -0
@@ -1224,6 +1224,7 @@ struct efx_mtd_partition {* @hwtstamp_filters: Mask of hardware timestamp filter types supported */ struct efx_nic_type { +bool is_vf;unsigned int mem_bar;unsigned int (*mem_map_size)(struct efx_nic *efx);int (*probe)(struct efx_nic *efx);
drivers/net/ethernet/sfc/siena.c +1 -0
@@ -917,6 +917,7 @@ fail:*/ const struct efx_nic_type siena_a0_nic_type = { + .is_vf = false, .mem_bar =EFX_MEM_BAR , .mem_map_size = siena_mem_map_size, .probe = siena_probe_nic,
David Miller
maintainerFrom: Shradha Shah <[email protected]>
Date: Wed, 6 May 2015 00:53:03 +0100
Quoted 19 lines
This set of patches makes way for the implementation of EF10 SR-IOV driver starting with some cleanup code.
NIC specific SR-IOV functions are moved to their own header andnetdev_opsare made generic instead of being NIC specificNext in line comes the patch to enable VF's using
sriov_configure. VEB vswitching hierarchy is set up next followed by patches to prepare sfc driver to bind to enabled VF'sThis is followed by patch to support use of shared RSS contexts which makes VF's use shared RSS contexts in all cases.
Patch series ends with a patch to bind the sfc driver to the enabled VF's which creates network interfaces corresponding to the VF's.
Coming up soon are the patches to
set_vf_mac,set_vf_config,set_vf_vlan,vf_spoofcheck, etc.
Quoted 7 lines
These patches have been tested with and without
CONFIG_SFC_SRIOV. In the case ofCONFIG_SFC_SRIOV=yenabling of VF's usingsriov_configureis also tested. The enabled VF's bind to the installed sfc driver succesfully to create network interfaces. In the case ofCONFIG_SFC_SRIOV=nenabling of VF's usingsriov_configurereturns the correct error message:
"Function not implemented".
Series applied, thanks.