sfc: VF representors for EF100
Subsystems (3)
v3 cover sfc: VF representors for EF100
From: Edward Cree <[email protected]>
This series adds representor netdevices for EF100 VFs, as a step towards
supporting TC offload and vDPA usecases in future patches.
In this first series is basic netdevice creation and packet TX; the
following series will add the RX path.
v3: dropped massive mcdi_pcol.h patch which was applied separately.
v2: converted comments on struct efx_nic members added in patch #4 to
kernel-doc (Jakub). While at it, also gave struct efx_rep its own kdoc since several members had comments on them.
Edward Cree (9):
sfc: update EF100 register descriptions
sfc: detect ef100 MAE admin privilege/capability at probe time
sfc: add skeleton ef100 VF representors
sfc: add basic ethtool ops to ef100 reps
sfc: phys port/switch identification for ef100 reps
sfc: determine representee m-port for EF100 representors
sfc: support passing a representor to the EF100 TX path
sfc: hook up ef100 representor TX
sfc: attach/detach EF100 representors along with their owning PF
drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef100_netdev.c | 16 +- drivers/net/ethernet/sfc/ef100_netdev.h | 5 + drivers/net/ethernet/sfc/ef100_nic.c | 7 + drivers/net/ethernet/sfc/ef100_nic.h | 1 + drivers/net/ethernet/sfc/ef100_regs.h | 83 +++++--- drivers/net/ethernet/sfc/ef100_rep.c | 244 ++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 49 +++++ drivers/net/ethernet/sfc/ef100_sriov.c | 32 +++- drivers/net/ethernet/sfc/ef100_sriov.h | 2 +- drivers/net/ethernet/sfc/ef100_tx.c | 84 +++++++- drivers/net/ethernet/sfc/ef100_tx.h | 3 + drivers/net/ethernet/sfc/efx.h | 9 +- drivers/net/ethernet/sfc/efx_common.c | 38 ++++ drivers/net/ethernet/sfc/efx_common.h | 3 + drivers/net/ethernet/sfc/mae.c | 44 +++++ drivers/net/ethernet/sfc/mae.h | 22 +++ drivers/net/ethernet/sfc/mcdi.c | 46 +++++ drivers/net/ethernet/sfc/mcdi.h | 1 + drivers/net/ethernet/sfc/net_driver.h | 5 + drivers/net/ethernet/sfc/tx.c | 6 +- drivers/net/ethernet/sfc/tx_common.c | 35 +++- drivers/net/ethernet/sfc/tx_common.h | 3 +- 23 files changed, 687 insertions(+), 53 deletions(-) create mode 100644 drivers/net/ethernet/sfc/ef100_rep.c create mode 100644 drivers/net/ethernet/sfc/ef100_rep.h create mode 100644 drivers/net/ethernet/sfc/mae.c create mode 100644 drivers/net/ethernet/sfc/mae.h
PATCH v3 1/9 sfc: update EF100 register descriptions
From: Edward Cree <[email protected]>
--- drivers/net/ethernet/sfc/ef100_regs.h | 83 +++++++++++++++++++-------- 1 file changed, 60 insertions(+), 23 deletions(-)
drivers/net/ethernet/sfc/ef100_regs.h +60 -23
@@ -2,7 +2,7 @@/**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2018 Solarflare Communications Inc. -* Copyright 2019-2020 Xilinx Inc. +* Copyright 2019-2022 Xilinx 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
@@ -181,12 +181,6 @@/* RHEAD_BASE_EVENT */ #define ESF_GZ_E_TYPE_LBN 60#define ESF_GZ_E_TYPE_WIDTH 4 -#define ESE_GZ_EF100_EV_DRIVER 5 -#define ESE_GZ_EF100_EV_MCDI 4 -#define ESE_GZ_EF100_EV_CONTROL 3 -#define ESE_GZ_EF100_EV_TX_TIMESTAMP 2 -#define ESE_GZ_EF100_EV_TX_COMPLETION 1 -#define ESE_GZ_EF100_EV_RX_PKTS 0#define ESF_GZ_EV_EVQ_PHASE_LBN 59#define ESF_GZ_EV_EVQ_PHASE_WIDTH 1#define ESE_GZ_RHEAD_BASE_EVENT_STRUCT_SIZE 64
@@ -369,14 +363,18 @@#define ESF_GZ_RX_PREFIX_VLAN_STRIP_TCI_WIDTH 16#define ESF_GZ_RX_PREFIX_CSUM_FRAME_LBN 144#define ESF_GZ_RX_PREFIX_CSUM_FRAME_WIDTH 16 -#define ESF_GZ_RX_PREFIX_INGRESS_VPORT_LBN 128 -#define ESF_GZ_RX_PREFIX_INGRESS_VPORT_WIDTH 16 +#define ESF_GZ_RX_PREFIX_INGRESS_MPORT_LBN 128 +#define ESF_GZ_RX_PREFIX_INGRESS_MPORT_WIDTH 16#define ESF_GZ_RX_PREFIX_USER_MARK_LBN 96#define ESF_GZ_RX_PREFIX_USER_MARK_WIDTH 32#define ESF_GZ_RX_PREFIX_RSS_HASH_LBN 64#define ESF_GZ_RX_PREFIX_RSS_HASH_WIDTH 32 -#define ESF_GZ_RX_PREFIX_PARTIAL_TSTAMP_LBN 32 -#define ESF_GZ_RX_PREFIX_PARTIAL_TSTAMP_WIDTH 32 +#define ESF_GZ_RX_PREFIX_PARTIAL_TSTAMP_LBN 34 +#define ESF_GZ_RX_PREFIX_PARTIAL_TSTAMP_WIDTH 30 +#define ESF_GZ_RX_PREFIX_VSWITCH_STATUS_LBN 33 +#define ESF_GZ_RX_PREFIX_VSWITCH_STATUS_WIDTH 1 +#define ESF_GZ_RX_PREFIX_VLAN_STRIPPED_LBN 32 +#define ESF_GZ_RX_PREFIX_VLAN_STRIPPED_WIDTH 1#define ESF_GZ_RX_PREFIX_CLASS_LBN 16#define ESF_GZ_RX_PREFIX_CLASS_WIDTH 16#define ESF_GZ_RX_PREFIX_USER_FLAG_LBN 15
@@ -454,12 +452,8 @@#define ESF_GZ_M2M_TRANSLATE_ADDR_WIDTH 1#define ESF_GZ_M2M_RSVD_LBN 120#define ESF_GZ_M2M_RSVD_WIDTH 2 -#define ESF_GZ_M2M_ADDR_SPC_LBN 108 -#define ESF_GZ_M2M_ADDR_SPC_WIDTH 12 -#define ESF_GZ_M2M_ADDR_SPC_PASID_LBN 86 -#define ESF_GZ_M2M_ADDR_SPC_PASID_WIDTH 22 -#define ESF_GZ_M2M_ADDR_SPC_MODE_LBN 84 -#define ESF_GZ_M2M_ADDR_SPC_MODE_WIDTH 2 +#define ESF_GZ_M2M_ADDR_SPC_ID_LBN 84 +#define ESF_GZ_M2M_ADDR_SPC_ID_WIDTH 36#define ESF_GZ_M2M_LEN_MINUS_1_LBN 64#define ESF_GZ_M2M_LEN_MINUS_1_WIDTH 20#define ESF_GZ_M2M_ADDR_LBN 0
@@ -492,12 +486,8 @@#define ESF_GZ_TX_SEG_TRANSLATE_ADDR_WIDTH 1#define ESF_GZ_TX_SEG_RSVD2_LBN 120#define ESF_GZ_TX_SEG_RSVD2_WIDTH 2 -#define ESF_GZ_TX_SEG_ADDR_SPC_LBN 108 -#define ESF_GZ_TX_SEG_ADDR_SPC_WIDTH 12 -#define ESF_GZ_TX_SEG_ADDR_SPC_PASID_LBN 86 -#define ESF_GZ_TX_SEG_ADDR_SPC_PASID_WIDTH 22 -#define ESF_GZ_TX_SEG_ADDR_SPC_MODE_LBN 84 -#define ESF_GZ_TX_SEG_ADDR_SPC_MODE_WIDTH 2 +#define ESF_GZ_TX_SEG_ADDR_SPC_ID_LBN 84 +#define ESF_GZ_TX_SEG_ADDR_SPC_ID_WIDTH 36#define ESF_GZ_TX_SEG_RSVD_LBN 80#define ESF_GZ_TX_SEG_RSVD_WIDTH 4#define ESF_GZ_TX_SEG_LEN_LBN 64
@@ -583,6 +573,12 @@#define ESE_GZ_SF_TX_TSO_DSC_FMT_STRUCT_SIZE 124 +/* Enum D2VIO_MSG_OP */ +#define ESE_GZ_QUE_JBDNE 3 +#define ESE_GZ_QUE_EVICT 2 +#define ESE_GZ_QUE_EMPTY 1 +#define ESE_GZ_NOP 0 +/* Enum DESIGN_PARAMS */ #define ESE_EF100_DP_GZ_RX_MAX_RUNT 17#define ESE_EF100_DP_GZ_VI_STRIDES 16
@@ -630,6 +626,19 @@#define ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE 256#define ESE_GZ_PCI_EXPRESS_XCAP_HDR_SIZE 4 +/* Enum RH_DSC_TYPE */ +#define ESE_GZ_TX_TOMB 0xF +#define ESE_GZ_TX_VIO 0xE +#define ESE_GZ_TX_TSO_OVRRD 0x8 +#define ESE_GZ_TX_D2CMP 0x7 +#define ESE_GZ_TX_DATA 0x6 +#define ESE_GZ_TX_D2M 0x5 +#define ESE_GZ_TX_M2M 0x4 +#define ESE_GZ_TX_SEG 0x3 +#define ESE_GZ_TX_TSO 0x2 +#define ESE_GZ_TX_OVRRD 0x1 +#define ESE_GZ_TX_SEND 0x0 +/* Enum RH_HCLASS_L2_CLASS */ #define ESE_GZ_RH_HCLASS_L2_CLASS_E2_0123VLAN 1#define ESE_GZ_RH_HCLASS_L2_CLASS_OTHER 0
@@ -666,6 +675,25 @@#define ESE_GZ_RH_HCLASS_TUNNEL_CLASS_VXLAN 1#define ESE_GZ_RH_HCLASS_TUNNEL_CLASS_NONE 0 +/* Enum SF_CTL_EVENT_SUBTYPE */ +#define ESE_GZ_EF100_CTL_EV_EVQ_TIMEOUT 0x3 +#define ESE_GZ_EF100_CTL_EV_FLUSH 0x2 +#define ESE_GZ_EF100_CTL_EV_TIME_SYNC 0x1 +#define ESE_GZ_EF100_CTL_EV_UNSOL_OVERFLOW 0x0 + +/* Enum SF_EVENT_TYPE */ +#define ESE_GZ_EF100_EV_DRIVER 0x5 +#define ESE_GZ_EF100_EV_MCDI 0x4 +#define ESE_GZ_EF100_EV_CONTROL 0x3 +#define ESE_GZ_EF100_EV_TX_TIMESTAMP 0x2 +#define ESE_GZ_EF100_EV_TX_COMPLETION 0x1 +#define ESE_GZ_EF100_EV_RX_PKTS 0x0 + +/* Enum SF_EW_EVENT_TYPE */ +#define ESE_GZ_EF100_EWEV_VIRTQ_DESC 0x2 +#define ESE_GZ_EF100_EWEV_TXQ_DESC 0x1 +#define ESE_GZ_EF100_EWEV_64BIT 0x0 +/* Enum TX_DESC_CSO_PARTIAL_EN */ #define ESE_GZ_TX_DESC_CSO_PARTIAL_EN_TCP 2#define ESE_GZ_TX_DESC_CSO_PARTIAL_EN_UDP 1
@@ -681,6 +709,15 @@#define ESE_GZ_TX_DESC_IP4_ID_INC_MOD16 2#define ESE_GZ_TX_DESC_IP4_ID_INC_MOD15 1#define ESE_GZ_TX_DESC_IP4_ID_NO_OP 0 + +/* Enum VIRTIO_NET_HDR_F */ +#define ESE_GZ_NEEDS_CSUM 0x1 + +/* Enum VIRTIO_NET_HDR_GSO */ +#define ESE_GZ_TCPV6 0x4 +#define ESE_GZ_UDP 0x3 +#define ESE_GZ_TCPV4 0x1 +#define ESE_GZ_NONE 0x0/**************************************************************************/ #define ESF_GZ_EV_DEBUG_EVENT_GEN_FLAGS_LBN 44
PATCH v3 2/9 sfc: detect ef100 MAE admin privilege/capability at probe time
In reply to [email protected]From: Edward Cree <[email protected]>
One PCIe function per network port (more precisely, per m-port group) is
responsible for configuring the Match-Action Engine which performs switching and packet modification in the slice to support flower/OVS offload. The GRP_MAE bit in the privilege mask indicates whether a given function has this capability.
At probe time, call MCDIs to read the calling function's privilege mask,
and store the GRP_MAE bit in a new ef100_nic_data member.
--- drivers/net/ethernet/sfc/ef100_nic.c | 7 +++++ drivers/net/ethernet/sfc/ef100_nic.h | 1 + drivers/net/ethernet/sfc/mcdi.c | 46 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mcdi.h | 1 + 4 files changed, 55 insertions(+)
drivers/net/ethernet/sfc/ef100_nic.c +7 -0
@@ -946,6 +946,7 @@ static int ef100_probe_main(struct efx_nic *efx)unsigned int bar_size =resource_size (&efx->pci_dev->resource[efx->mem_bar]);struct ef100_nic_data *nic_data;char fw_version[32 ]; +u32 priv_mask =0 ;int i, rc;if (WARN_ON (bar_size ==0 ))
@@ -1027,6 +1028,12 @@ static int ef100_probe_main(struct efx_nic *efx)efx_mcdi_print_fwver (efx, fw_version,sizeof (fw_version));pci_dbg (efx->pci_dev,"Firmware version %s\n" , fw_version); + rc =efx_mcdi_get_privilege_mask (efx, &priv_mask); +if (rc)/* non-fatal, and priv_mask will still be 0 */ +pci_info (efx->pci_dev, +"Failed to get privilege mask from FW, rc %d\n" , rc); + nic_data->grp_mae = !!(priv_mask &MC_CMD_PRIVILEGE_MASK_IN_GRP_MAE ); +if (compare_versions (fw_version,"1.1.0.1000" ) <0 ) {pci_info (efx->pci_dev,"Firmware uses old event descriptors\n" ); rc = -EINVAL ;
drivers/net/ethernet/sfc/ef100_nic.h +1 -0
@@ -72,6 +72,7 @@ struct ef100_nic_data {u8 port_id[ETH_ALEN ];DECLARE_BITMAP (evq_phases,EFX_MAX_CHANNELS );u64 stats[EF100_STAT_COUNT ]; +bool grp_mae;/* MAE Privilege */ u16 tso_max_hdr_len;u16 tso_max_payload_num_segs;u16 tso_max_frames;
drivers/net/ethernet/sfc/mcdi.c +46 -0
52 lines not on this page · raw message
drivers/net/ethernet/sfc/mcdi.h +1 -0
@@ -366,6 +366,7 @@ int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled, unsigned int *flags);int efx_mcdi_get_workarounds (struct efx_nic *efx,unsigned int *impl_out,unsigned int *enabled_out); +int efx_mcdi_get_privilege_mask (struct efx_nic *efx,u32 *mask);#ifdef CONFIG_SFC_MCDI_MON int efx_mcdi_mon_probe (struct efx_nic *efx);
PATCH v3 3/9 sfc: add skeleton ef100 VF representors
In reply to [email protected]From: Edward Cree <[email protected]>
No net_device_ops yet, just a placeholder netdev created per VF.
--- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef100_netdev.c | 2 +- drivers/net/ethernet/sfc/ef100_rep.c | 126 ++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 37 +++++++ drivers/net/ethernet/sfc/ef100_sriov.c | 32 ++++-- drivers/net/ethernet/sfc/ef100_sriov.h | 2 +- drivers/net/ethernet/sfc/efx_common.c | 2 + drivers/net/ethernet/sfc/net_driver.h | 4 + 8 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 drivers/net/ethernet/sfc/ef100_rep.c create mode 100644 drivers/net/ethernet/sfc/ef100_rep.h
drivers/net/ethernet/sfc/Makefile +1 -1
@@ -8,7 +8,7 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ ef100.o ef100_nic.o ef100_netdev.o \ ef100_ethtool.o ef100_rx.o ef100_tx.o sfc-$(CONFIG_SFC_MTD) += mtd.o -sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o +sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/ethernet/sfc/ef100_netdev.c +1 -1
@@ -312,7 +312,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)unregister_netdevice_notifier (&efx->netdev_notifier);#if defined(CONFIG_SFC_SRIOV )if (!efx->type->is_vf) -efx_ef100_pci_sriov_disable (efx); +efx_ef100_pci_sriov_disable (efx, true);#endif ef100_unregister_netdev (efx);
drivers/net/ethernet/sfc/ef100_rep.c new file +126 -0
126 lines not on this page · raw message
drivers/net/ethernet/sfc/ef100_rep.h new file +37 -0
@@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** +* Driver for Solarflare network controllers and boards +* Copyright 2019 Solarflare Communications Inc. +* Copyright 2020-2022 Xilinx 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. +*/ + +/* Handling for ef100 representor netdevs */ +#ifndef EF100_REP_H +#define EF100_REP_H + +#include "net_driver.h" + +/** +* struct efx_rep - Private data for an Efx representor +* +* @parent: the efx PF which manages this representor +* @net_dev: representor netdevice +* @msg_enable: log message enable flags +* @list: entry on efx->vf_reps +*/ +struct efx_rep { +struct efx_nic *parent; +struct net_device *net_dev; +u32 msg_enable; +struct list_head list; +}; + +int efx_ef100_vfrep_create (struct efx_nic *efx,unsigned int i); +void efx_ef100_vfrep_destroy (struct efx_nic *efx,struct efx_rep *efv); +void efx_ef100_fini_vfreps (struct efx_nic *efx); + +#endif /* EF100_REP_H */
drivers/net/ethernet/sfc/ef100_sriov.c +24 -8
@@ -11,46 +11,62 @@#include "ef100_sriov.h" #include "ef100_nic.h" +#include "ef100_rep.h" static int efx_ef100_pci_sriov_enable (struct efx_nic *efx,int num_vfs) { +struct ef100_nic_data *nic_data = efx->nic_data;struct pci_dev *dev = efx->pci_dev; -int rc; +struct efx_rep *efv, *next; +int rc, i; efx->vf_count = num_vfs; rc =pci_enable_sriov (dev, num_vfs);if (rc) - goto fail; + goto fail1; +if (!nic_data->grp_mae) +return 0 ; + +for (i =0 ; i < num_vfs; i++) { + rc =efx_ef100_vfrep_create (efx, i); +if (rc) + goto fail2; + }return 0 ; -fail: +fail2: +list_for_each_entry_safe (efv, next, &efx->vf_reps, list) +efx_ef100_vfrep_destroy (efx, efv); +pci_disable_sriov (dev); +fail1:netif_err (efx, probe, efx->net_dev,"Failed to enable SRIOV VFs\n" ); efx->vf_count =0 ;return rc; } -int efx_ef100_pci_sriov_disable (struct efx_nic *efx) +int efx_ef100_pci_sriov_disable (struct efx_nic *efx,bool force) {struct pci_dev *dev = efx->pci_dev;unsigned int vfs_assigned; vfs_assigned =pci_vfs_assigned (dev); -if (vfs_assigned) { +if (vfs_assigned && !force) {netif_info (efx, drv, efx->net_dev,"VFs are assigned to guests; " "please detach them before disabling SR-IOV\n" );return -EBUSY ; } -pci_disable_sriov (dev); - +efx_ef100_fini_vfreps (efx); +if (!vfs_assigned) +pci_disable_sriov (dev);return 0 ; }int efx_ef100_sriov_configure (struct efx_nic *efx,int num_vfs) {if (num_vfs ==0 ) -return efx_ef100_pci_sriov_disable (efx); +return efx_ef100_pci_sriov_disable (efx, false);else return efx_ef100_pci_sriov_enable (efx, num_vfs); }
drivers/net/ethernet/sfc/ef100_sriov.h +1 -1
@@ -11,4 +11,4 @@#include "net_driver.h" int efx_ef100_sriov_configure (struct efx_nic *efx,int num_vfs); -int efx_ef100_pci_sriov_disable (struct efx_nic *efx); +int efx_ef100_pci_sriov_disable (struct efx_nic *efx,bool force);
drivers/net/ethernet/sfc/efx_common.c +2 -0
@@ -1021,6 +1021,8 @@ int efx_init_struct(struct efx_nic *efx, struct pci_dev *pci_dev) efx->rps_hash_table =kcalloc (EFX_ARFS_HASH_TABLE_SIZE ,sizeof (*efx->rps_hash_table),GFP_KERNEL );#endif +spin_lock_init (&efx->vf_reps_lock); +INIT_LIST_HEAD (&efx->vf_reps);INIT_WORK (&efx->mac_work, efx_mac_work);init_waitqueue_head (&efx->flush_wq);
drivers/net/ethernet/sfc/net_driver.h +4 -0
@@ -966,6 +966,8 @@ enum efx_xdp_tx_queues_mode {* @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. +* @vf_reps_lock: Protects vf_reps list +* @vf_reps: local VF reps * @ptp_data: PTP state data * @ptp_warned: has this NIC seen and warned about unexpected PTP events? * @vpd_sn: Serial number read from VPD
@@ -1145,6 +1147,8 @@ struct efx_nic {unsigned vf_init_count;unsigned vi_scale;#endif +spinlock_t vf_reps_lock; +struct list_head vf_reps;struct efx_ptp_data *ptp_data;bool ptp_warned;
PATCH v3 4/9 sfc: add basic ethtool ops to ef100 reps
In reply to [email protected]From: Edward Cree <[email protected]>
--- drivers/net/ethernet/sfc/ef100_rep.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +26 -0
@@ -12,6 +12,8 @@#include "ef100_rep.h" #include "ef100_nic.h" +#define EFX_EF100_REP_DRIVER "efx_ef100_rep" +static int efx_ef100_rep_init_struct (struct efx_nic *efx,struct efx_rep *efv) { efv->parent = efx;
@@ -26,7 +28,31 @@ static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv)static const struct net_device_ops efx_ef100_rep_netdev_ops = { }; +static void efx_ef100_rep_get_drvinfo (struct net_device *dev, +struct ethtool_drvinfo *drvinfo) +{ +strscpy (drvinfo->driver,EFX_EF100_REP_DRIVER ,sizeof (drvinfo->driver)); +} + +static u32 efx_ef100_rep_ethtool_get_msglevel (struct net_device *net_dev) +{ +struct efx_rep *efv =netdev_priv (net_dev); + +return efv->msg_enable; +} + +static void efx_ef100_rep_ethtool_set_msglevel (struct net_device *net_dev, +u32 msg_enable) +{ +struct efx_rep *efv =netdev_priv (net_dev); + + efv->msg_enable = msg_enable; +} +static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { + .get_drvinfo = efx_ef100_rep_get_drvinfo, + .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, + .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, }; static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
PATCH v3 5/9 sfc: phys port/switch identification for ef100 reps
In reply to [email protected]From: Edward Cree <[email protected]>
Requires storing VF index in struct efx_rep.
--- drivers/net/ethernet/sfc/ef100_rep.c | 39 ++++++++++++++++++++++++++-- drivers/net/ethernet/sfc/ef100_rep.h | 2 ++ 2 files changed, 39 insertions(+), 2 deletions(-)
drivers/net/ethernet/sfc/ef100_rep.c +37 -2
@@ -14,9 +14,11 @@#define EFX_EF100_REP_DRIVER "efx_ef100_rep" -static int efx_ef100_rep_init_struct (struct efx_nic *efx,struct efx_rep *efv) +static int efx_ef100_rep_init_struct (struct efx_nic *efx,struct efx_rep *efv, +unsigned int i) { efv->parent = efx; + efv->idx = i;INIT_LIST_HEAD (&efv->list); efv->msg_enable =NETIF_MSG_DRV |NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
@@ -25,7 +27,40 @@ static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv)return 0 ; } +static int efx_ef100_rep_get_port_parent_id (struct net_device *dev, +struct netdev_phys_item_id *ppid) +{ +struct efx_rep *efv =netdev_priv (dev); +struct efx_nic *efx = efv->parent; +struct ef100_nic_data *nic_data; + + nic_data = efx->nic_data; +/* nic_data->port_id is a u8[] */ + ppid->id_len =sizeof (nic_data->port_id); +memcpy (ppid->id, nic_data->port_id,sizeof (nic_data->port_id)); +return 0 ; +} + +static int efx_ef100_rep_get_phys_port_name (struct net_device *dev, +char *buf,size_t len) +{ +struct efx_rep *efv =netdev_priv (dev); +struct efx_nic *efx = efv->parent; +struct ef100_nic_data *nic_data; +int ret; + + nic_data = efx->nic_data; + ret =snprintf (buf, len,"p%upf%uvf%u" , efx->port_num, + nic_data->pf_index, efv->idx); +if (ret >= len) +return -EOPNOTSUPP ; + +return 0 ; +} +static const struct net_device_ops efx_ef100_rep_netdev_ops = { + .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, + .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, }; static void efx_ef100_rep_get_drvinfo(struct net_device *dev,
@@ -67,7 +102,7 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,return ERR_PTR (-ENOMEM ); efv =netdev_priv (net_dev); - rc =efx_ef100_rep_init_struct (efx, efv); + rc =efx_ef100_rep_init_struct (efx, efv, i);if (rc) goto fail1; efv->net_dev = net_dev;
drivers/net/ethernet/sfc/ef100_rep.h +2 -0
@@ -21,12 +21,14 @@* @parent: the efx PF which manages this representor * @net_dev: representor netdevice * @msg_enable: log message enable flags +* @idx: VF index * @list: entry on efx->vf_reps */ struct efx_rep {struct efx_nic *parent;struct net_device *net_dev;u32 msg_enable; +unsigned int idx;struct list_head list; };
PATCH v3 6/9 sfc: determine representee m-port for EF100 representors
In reply to [email protected]From: Edward Cree <[email protected]>
An MAE port, or m-port, is a port (source/destination for traffic) on
the Match-Action Engine (the internal switch on EF100).
Representors will use their representee's m-port for two purposes: as
a destination override on TX from the representor, and as a source match in 'default rules' to steer representee traffic (when not matched by e.g. a TC flower rule) to representor RX via the parent PF's receive queue.
--- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/ef100_rep.c | 27 +++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 2 ++ drivers/net/ethernet/sfc/mae.c | 44 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 22 ++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/sfc/mae.c create mode 100644 drivers/net/ethernet/sfc/mae.h
drivers/net/ethernet/sfc/Makefile +1 -1
@@ -8,7 +8,7 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ ef100.o ef100_nic.o ef100_netdev.o \ ef100_ethtool.o ef100_rx.o ef100_tx.o sfc-$(CONFIG_SFC_MTD) += mtd.o -sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o +sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o mae.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/ethernet/sfc/ef100_rep.c +27 -0
@@ -11,6 +11,7 @@#include "ef100_rep.h" #include "ef100_nic.h" +#include "mae.h" #define EFX_EF100_REP_DRIVER "efx_ef100_rep"
@@ -124,6 +125,25 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,return ERR_PTR (rc); } +static int efx_ef100_configure_rep (struct efx_rep *efv) +{ +struct efx_nic *efx = efv->parent; +u32 selector; +int rc; + +/* Construct mport selector for corresponding VF */ +efx_mae_mport_vf (efx, efv->idx, &selector); +/* Look up actual mport ID */ + rc =efx_mae_lookup_mport (efx, selector, &efv->mport); +if (rc) +return rc; +pci_dbg (efx->pci_dev,"VF %u has mport ID %#x\n" , efv->idx, efv->mport); +/* mport label should fit in 16 bits */ +WARN_ON (efv->mport >>16 ); + +return 0 ; +} +static void efx_ef100_rep_destroy_netdev (struct efx_rep *efv) {struct efx_nic *efx = efv->parent;
@@ -147,6 +167,13 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) rc);return rc; } + rc =efx_ef100_configure_rep (efv); +if (rc) { +pci_err (efx->pci_dev, +"Failed to configure representor for VF %d, rc %d\n" , + i, rc); + goto fail; + } rc =register_netdev (efv->net_dev);if (rc) { pci_err(efx->pci_dev,
drivers/net/ethernet/sfc/ef100_rep.h +2 -0
@@ -21,6 +21,7 @@* @parent: the efx PF which manages this representor * @net_dev: representor netdevice * @msg_enable: log message enable flags +* @mport: m-port ID of corresponding VF * @idx: VF index * @list: entry on efx->vf_reps */
@@ -28,6 +29,7 @@ struct efx_rep {struct efx_nic *parent;struct net_device *net_dev;u32 msg_enable; +u32 mport;unsigned int idx;struct list_head list; };
drivers/net/ethernet/sfc/mae.c new file +44 -0
44 lines not on this page · raw message
drivers/net/ethernet/sfc/mae.h new file +22 -0
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** +* Driver for Solarflare network controllers and boards +* Copyright 2019 Solarflare Communications Inc. +* Copyright 2020-2022 Xilinx 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 EF100_MAE_H +#define EF100_MAE_H +/* MCDI interface for the ef100 Match-Action Engine */ + +#include "net_driver.h" + +void efx_mae_mport_vf (struct efx_nic *efx,u32 vf_id,u32 *out); + +int efx_mae_lookup_mport (struct efx_nic *efx,u32 selector,u32 *id); + +#endif /* EF100_MAE_H */
PATCH v3 7/9 sfc: support passing a representor to the EF100 TX path
In reply to [email protected]From: Edward Cree <[email protected]>
A non-null efv in __ef100_enqueue_skb() indicates that the packet is
from that representor, should be transmitted with a suitable option descriptor (to instruct the switch to deliver it to the representee), and should not be accounted to the parent PF's stats or BQL.
--- drivers/net/ethernet/sfc/ef100_rep.h | 8 +++ drivers/net/ethernet/sfc/ef100_tx.c | 84 +++++++++++++++++++++++++-- drivers/net/ethernet/sfc/ef100_tx.h | 3 + drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/tx.c | 6 +- drivers/net/ethernet/sfc/tx_common.c | 35 +++++++---- drivers/net/ethernet/sfc/tx_common.h | 3 +- 7 files changed, 123 insertions(+), 17 deletions(-)
drivers/net/ethernet/sfc/ef100_rep.h +8 -0
@@ -15,6 +15,12 @@#include "net_driver.h" +struct efx_rep_sw_stats { +atomic64_t rx_packets, tx_packets; +atomic64_t rx_bytes, tx_bytes; +atomic64_t rx_dropped, tx_errors; +}; +/** * struct efx_rep - Private data for an Efx representor *
@@ -24,6 +30,7 @@* @mport: m-port ID of corresponding VF * @idx: VF index * @list: entry on efx->vf_reps +* @stats: software traffic counters for netdev stats */ struct efx_rep {struct efx_nic *parent;
@@ -32,6 +39,7 @@ struct efx_rep {u32 mport;unsigned int idx;struct list_head list; +struct efx_rep_sw_stats stats; };int efx_ef100_vfrep_create (struct efx_nic *efx,unsigned int i);
drivers/net/ethernet/sfc/ef100_tx.c +80 -4
136 lines not on this page · raw message
drivers/net/ethernet/sfc/ef100_tx.h +3 -0
@@ -13,6 +13,7 @@#define EFX_EF100_TX_H #include "net_driver.h" +#include "ef100_rep.h" int ef100_tx_probe (struct efx_tx_queue *tx_queue);void ef100_tx_init (struct efx_tx_queue *tx_queue);
@@ -22,4 +23,6 @@ unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);void ef100_ev_tx (struct efx_channel *channel,const efx_qword_t *p_event);netdev_tx_t ef100_enqueue_skb (struct efx_tx_queue *tx_queue,struct sk_buff *skb); +int __ef100_enqueue_skb (struct efx_tx_queue *tx_queue,struct sk_buff *skb, +struct efx_rep *efv);#endif
drivers/net/ethernet/sfc/net_driver.h +1 -0
@@ -178,6 +178,7 @@ struct efx_tx_buffer {#define EFX_TX_BUF_OPTION 0x10/* empty buffer for option descriptor */ #define EFX_TX_BUF_XDP 0x20/* buffer was sent with XDP */ #define EFX_TX_BUF_TSO_V3 0x40/* empty buffer for a TSO_V3 descriptor */ +#define EFX_TX_BUF_EFV 0x100/* buffer was sent from representor */ /** * struct efx_tx_queue - An Efx TX queue
drivers/net/ethernet/sfc/tx.c +4 -2
@@ -559,6 +559,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,void efx_xmit_done_single (struct efx_tx_queue *tx_queue) {unsigned int pkts_compl =0 , bytes_compl =0 ; +unsigned int efv_pkts_compl =0 ;unsigned int read_ptr;bool finished = false;
@@ -580,7 +581,8 @@ void efx_xmit_done_single(struct efx_tx_queue *tx_queue)/* Need to check the flag before dequeueing. */ if (buffer->flags &EFX_TX_BUF_SKB ) finished = true; -efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl); +efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl, + &efv_pkts_compl); ++tx_queue->read_count; read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
@@ -589,7 +591,7 @@ void efx_xmit_done_single(struct efx_tx_queue *tx_queue) tx_queue->pkts_compl += pkts_compl; tx_queue->bytes_compl += bytes_compl; -EFX_WARN_ON_PARANOID (pkts_compl !=1 ); +EFX_WARN_ON_PARANOID (pkts_compl + efv_pkts_compl !=1 );efx_xmit_done_check_empty (tx_queue); }
drivers/net/ethernet/sfc/tx_common.c +25 -10
@@ -109,9 +109,11 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)/* Free any buffers left in the ring */ while (tx_queue->read_count != tx_queue->write_count) {unsigned int pkts_compl =0 , bytes_compl =0 ; +unsigned int efv_pkts_compl =0 ; buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask]; -efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl); +efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl, + &efv_pkts_compl); ++tx_queue->read_count; }
@@ -146,7 +148,8 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)void efx_dequeue_buffer (struct efx_tx_queue *tx_queue,struct efx_tx_buffer *buffer,unsigned int *pkts_compl, -unsigned int *bytes_compl) +unsigned int *bytes_compl, +unsigned int *efv_pkts_compl) {if (buffer->unmap_len) {struct device *dma_dev = &tx_queue->efx->pci_dev->dev;
@@ -164,9 +167,15 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,if (buffer->flags &EFX_TX_BUF_SKB ) {struct sk_buff *skb = (struct sk_buff *)buffer->skb; -EFX_WARN_ON_PARANOID (!pkts_compl || !bytes_compl); - (*pkts_compl)++; - (*bytes_compl) += skb->len; +if (unlikely (buffer->flags &EFX_TX_BUF_EFV )) { +EFX_WARN_ON_PARANOID (!efv_pkts_compl); + (*efv_pkts_compl)++; + }else { +EFX_WARN_ON_PARANOID (!pkts_compl || !bytes_compl); + (*pkts_compl)++; + (*bytes_compl) += skb->len; + } +if (tx_queue->timestamping && (tx_queue->completed_timestamp_major || tx_queue->completed_timestamp_minor)) {
@@ -199,7 +208,8 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,static void efx_dequeue_buffers (struct efx_tx_queue *tx_queue,unsigned int index,unsigned int *pkts_compl, -unsigned int *bytes_compl) +unsigned int *bytes_compl, +unsigned int *efv_pkts_compl) {struct efx_nic *efx = tx_queue->efx;unsigned int stop_index, read_ptr;
@@ -218,7 +228,8 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,return ; } -efx_dequeue_buffer (tx_queue, buffer, pkts_compl, bytes_compl); +efx_dequeue_buffer (tx_queue, buffer, pkts_compl, bytes_compl, + efv_pkts_compl); ++tx_queue->read_count; read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
@@ -241,15 +252,17 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)void efx_xmit_done (struct efx_tx_queue *tx_queue,unsigned int index) {unsigned int fill_level, pkts_compl =0 , bytes_compl =0 ; +unsigned int efv_pkts_compl =0 ;struct efx_nic *efx = tx_queue->efx;EFX_WARN_ON_ONCE_PARANOID (index > tx_queue->ptr_mask); -efx_dequeue_buffers (tx_queue, index, &pkts_compl, &bytes_compl); +efx_dequeue_buffers (tx_queue, index, &pkts_compl, &bytes_compl, + &efv_pkts_compl); tx_queue->pkts_compl += pkts_compl; tx_queue->bytes_compl += bytes_compl; -if (pkts_compl >1 ) +if (pkts_compl + efv_pkts_compl >1 ) ++tx_queue->merge_events;/* See if we need to restart the netif queue. This memory
@@ -274,6 +287,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)void efx_enqueue_unwind (struct efx_tx_queue *tx_queue,unsigned int insert_count) { +unsigned int efv_pkts_compl =0 ;struct efx_tx_buffer *buffer;unsigned int bytes_compl =0 ;unsigned int pkts_compl =0 ;
@@ -282,7 +296,8 @@ void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,while (tx_queue->insert_count != insert_count) { --tx_queue->insert_count; buffer =__efx_tx_queue_get_insert_buffer (tx_queue); -efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl); +efx_dequeue_buffer (tx_queue, buffer, &pkts_compl, &bytes_compl, + &efv_pkts_compl); } }
drivers/net/ethernet/sfc/tx_common.h +2 -1
@@ -19,7 +19,8 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);void efx_dequeue_buffer (struct efx_tx_queue *tx_queue,struct efx_tx_buffer *buffer,unsigned int *pkts_compl, -unsigned int *bytes_compl); +unsigned int *bytes_compl, +unsigned int *efv_pkts_compl);static inline bool efx_tx_buffer_in_use (struct efx_tx_buffer *buffer) {
PATCH v3 8/9 sfc: hook up ef100 representor TX
In reply to [email protected]From: Edward Cree <[email protected]>
Implement .ndo_start_xmit() by calling into the parent PF's TX path.
--- drivers/net/ethernet/sfc/ef100_netdev.c | 11 ++++++++++- drivers/net/ethernet/sfc/ef100_netdev.h | 5 +++++ drivers/net/ethernet/sfc/ef100_rep.c | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-)
drivers/net/ethernet/sfc/ef100_netdev.c +10 -1
@@ -195,6 +195,15 @@ static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) {struct efx_nic *efx =efx_netdev_priv (net_dev); + +return __ef100_hard_start_xmit (skb, efx, net_dev,NULL ); +} + +netdev_tx_t __ef100_hard_start_xmit (struct sk_buff *skb, +struct efx_nic *efx, +struct net_device *net_dev, +struct efx_rep *efv) +{struct efx_tx_queue *tx_queue;struct efx_channel *channel;int rc;
@@ -209,7 +218,7 @@ static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb, } tx_queue = &channel->tx_queue[0 ]; - rc =ef100_enqueue_skb (tx_queue, skb); + rc =__ef100_enqueue_skb (tx_queue, skb, efv);if (rc ==0 )return NETDEV_TX_OK ;
drivers/net/ethernet/sfc/ef100_netdev.h +5 -0
@@ -10,7 +10,12 @@*/ #include <linux/netdevice.h> +#include "ef100_rep.h" +netdev_tx_t __ef100_hard_start_xmit (struct sk_buff *skb, +struct efx_nic *efx, +struct net_device *net_dev, +struct efx_rep *efv);int ef100_netdev_event (struct notifier_block *this,unsigned long event,void *ptr);int ef100_probe_netdev (struct efx_probe_data *probe_data);
drivers/net/ethernet/sfc/ef100_rep.c +23 -0
@@ -10,6 +10,7 @@*/ #include "ef100_rep.h" +#include "ef100_netdev.h" #include "ef100_nic.h" #include "mae.h"
@@ -28,6 +29,25 @@ static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv,return 0 ; } +static netdev_tx_t efx_ef100_rep_xmit (struct sk_buff *skb, +struct net_device *dev) +{ +struct efx_rep *efv =netdev_priv (dev); +struct efx_nic *efx = efv->parent; +netdev_tx_t rc; + +/* __ef100_hard_start_xmit() will always return success even in the +* case of TX drops, where it will increment efx's tx_dropped. The +* efv stats really only count attempted TX, not success/failure. +*/ +atomic64_inc (&efv->stats.tx_packets); +atomic64_add (skb->len, &efv->stats.tx_bytes); +netif_tx_lock (efx->net_dev); + rc =__ef100_hard_start_xmit (skb, efx, dev, efv); +netif_tx_unlock (efx->net_dev); +return rc; +} +static int efx_ef100_rep_get_port_parent_id (struct net_device *dev,struct netdev_phys_item_id *ppid) {
@@ -60,6 +80,7 @@ static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, }static const struct net_device_ops efx_ef100_rep_netdev_ops = { + .ndo_start_xmit = efx_ef100_rep_xmit, .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, };
@@ -119,6 +140,8 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; net_dev->min_mtu =EFX_MIN_MTU ; net_dev->max_mtu =EFX_MAX_MTU ; + net_dev->features |=NETIF_F_LLTX ; + net_dev->hw_features |=NETIF_F_LLTX ;return efv; fail1:free_netdev (net_dev);
PATCH v3 9/9 sfc: attach/detach EF100 representors along with their owning PF
In reply to [email protected]From: Edward Cree <[email protected]>
Since representors piggy-back on the PF's queues for TX, they can
only accept new TXes while the PF is up. Thus, any operation which detaches the PF must first detach all its VFreps.
--- drivers/net/ethernet/sfc/ef100_netdev.c | 3 +++ drivers/net/ethernet/sfc/ef100_rep.c | 11 ++++++-- drivers/net/ethernet/sfc/efx.h | 9 ++++++- drivers/net/ethernet/sfc/efx_common.c | 36 +++++++++++++++++++++++++ drivers/net/ethernet/sfc/efx_common.h | 3 +++ 5 files changed, 59 insertions(+), 3 deletions(-)
drivers/net/ethernet/sfc/ef100_netdev.c +3 -0
@@ -85,6 +85,7 @@ static int ef100_net_stop(struct net_device *net_dev)netif_dbg (efx, ifdown, efx->net_dev,"closing on CPU %d\n" ,raw_smp_processor_id ()); +efx_detach_reps (efx);netif_stop_queue (net_dev);efx_stop_all (efx);efx_mcdi_mac_fini_stats (efx);
@@ -176,6 +177,8 @@ static int ef100_net_open(struct net_device *net_dev)mutex_unlock (&efx->mac_lock); efx->state =STATE_NET_UP ; +if (netif_running (efx->net_dev)) +efx_attach_reps (efx);return 0 ;
drivers/net/ethernet/sfc/ef100_rep.c +9 -2
@@ -132,8 +132,13 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,spin_lock_bh (&efx->vf_reps_lock);list_add_tail (&efv->list, &efx->vf_reps);spin_unlock_bh (&efx->vf_reps_lock); -netif_carrier_off (net_dev); -netif_tx_stop_all_queues (net_dev); +if (netif_running (efx->net_dev) && efx->state ==STATE_NET_UP ) { +netif_device_attach (net_dev); +netif_carrier_on (net_dev); + }else { +netif_carrier_off (net_dev); +netif_tx_stop_all_queues (net_dev); + }rtnl_unlock (); net_dev->netdev_ops = &efx_ef100_rep_netdev_ops;
@@ -171,9 +176,11 @@ static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) {struct efx_nic *efx = efv->parent; +rtnl_lock ();spin_lock_bh (&efx->vf_reps_lock);list_del (&efv->list);spin_unlock_bh (&efx->vf_reps_lock); +rtnl_unlock ();free_netdev (efv->net_dev); }
drivers/net/ethernet/sfc/efx.h +8 -1
@@ -12,6 +12,7 @@#include "net_driver.h" #include "ef100_rx.h" #include "ef100_tx.h" +#include "efx_common.h" #include "filter.h" int efx_net_open (struct net_device *net_dev);
@@ -206,6 +207,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx) {struct net_device *dev = efx->net_dev; +/* We must stop reps (which use our TX) before we stop ourselves. */ +efx_detach_reps (efx); +/* Lock/freeze all TX queues so that we can be sure the * TX scheduler is stopped when we're done and before * netif_device_present() becomes false.
@@ -217,8 +221,11 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)static inline void efx_device_attach_if_not_resetting (struct efx_nic *efx) { -if ((efx->state !=STATE_DISABLED ) && !efx->reset_pending) +if ((efx->state !=STATE_DISABLED ) && !efx->reset_pending) {netif_device_attach (efx->net_dev); +if (efx->state ==STATE_NET_UP ) +efx_attach_reps (efx); + } }static inline bool efx_rwsem_assert_write_locked (struct rw_semaphore *sem)
drivers/net/ethernet/sfc/efx_common.c +36 -0
@@ -24,6 +24,7 @@#include "mcdi_port_common.h" #include "io.h" #include "mcdi_pcol.h" +#include "ef100_rep.h" static unsigned int debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
@@ -1391,3 +1392,38 @@ int efx_get_phys_port_name(struct net_device *net_dev, char *name, size_t len)return -EINVAL ;return 0 ; } + +void efx_detach_reps (struct efx_nic *efx) +{ +struct net_device *rep_dev; +struct efx_rep *efv; + +ASSERT_RTNL (); +netif_dbg (efx, drv, efx->net_dev,"Detaching VF representors\n" ); +list_for_each_entry (efv, &efx->vf_reps, list) { + rep_dev = efv->net_dev; +if (!rep_dev) +continue ; +netif_carrier_off (rep_dev); +/* See efx_device_detach_sync() */ +netif_tx_lock_bh (rep_dev); +netif_tx_stop_all_queues (rep_dev); +netif_tx_unlock_bh (rep_dev); + } +} + +void efx_attach_reps (struct efx_nic *efx) +{ +struct net_device *rep_dev; +struct efx_rep *efv; + +ASSERT_RTNL (); +netif_dbg (efx, drv, efx->net_dev,"Attaching VF representors\n" ); +list_for_each_entry (efv, &efx->vf_reps, list) { + rep_dev = efv->net_dev; +if (!rep_dev) +continue ; +netif_tx_wake_all_queues (rep_dev); +netif_carrier_on (rep_dev); + } +}
drivers/net/ethernet/sfc/efx_common.h +3 -0
@@ -111,4 +111,7 @@ int efx_get_phys_port_id(struct net_device *net_dev,int efx_get_phys_port_name (struct net_device *net_dev,char *name,size_t len); + +void efx_detach_reps (struct efx_nic *efx); +void efx_attach_reps (struct efx_nic *efx);#endif
This series was applied to netdev/net-next.git (master) by David S. Miller <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (master) by David S. Miller <[email protected]>:
Quoted 8 lines · On Wed, 20 Jul 2022 19:29:23 +0100 you wrote:
From: Edward Cree <[email protected]>
This series adds representor netdevices for EF100 VFs, as a step towards
supporting TC offload and vDPA usecases in future patches.
In this first series is basic netdevice creation and packet TX; the
following series will add the RX path.[...]
Here is the summary with links:
- [v3,net-next,1/9] sfc: update EF100 register descriptions
https://git.kernel.org/netdev/net-next/c/8ca353da9c10 - [v3,net-next,2/9] sfc: detect ef100 MAE admin privilege/capability at probe time https://git.kernel.org/netdev/net-next/c/95287e1b4e5c - [v3,net-next,3/9] sfc: add skeleton ef100 VF representors https://git.kernel.org/netdev/net-next/c/08135eecd07f - [v3,net-next,4/9] sfc: add basic ethtool ops to ef100 reps https://git.kernel.org/netdev/net-next/c/5687eb3466a9 - [v3,net-next,5/9] sfc: phys port/switch identification for ef100 reps https://git.kernel.org/netdev/net-next/c/e1479556f808 - [v3,net-next,6/9] sfc: determine representee m-port for EF100 representors https://git.kernel.org/netdev/net-next/c/da56552d04c5 - [v3,net-next,7/9] sfc: support passing a representor to the EF100 TX path https://git.kernel.org/netdev/net-next/c/02443ab8c931 - [v3,net-next,8/9] sfc: hook up ef100 representor TX https://git.kernel.org/netdev/net-next/c/f72c38fad234 - [v3,net-next,9/9] sfc: attach/detach EF100 representors along with their owning PF https://git.kernel.org/netdev/net-next/c/84e7fc2591f7
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html