sfc: VF representors for EF100 - RX side
Subsystems (3)
cover sfc: VF representors for EF100 - RX side
From: Edward Cree <[email protected]>
This series adds the receive path for EF100 VF representors, plus other
minor features such as statistics and MAC address setting.
Edward Cree (14):
sfc: plumb ef100 representor stats
sfc: ef100 representor RX NAPI poll
sfc: ef100 representor RX top half
sfc: determine wire m-port at EF100 PF probe time
sfc: check ef100 RX packets are from the wire
sfc: receive packets from EF100 VFs into representors
sfc: insert default MAE rules to connect VFs to representors
sfc: move table locking into filter_table_{probe,remove} methods
sfc: use a dynamic m-port for representor RX and set it promisc
sfc: look up VF's client ID when creating representor
sfc: fetch existing assigned MAC address from FW when creating VF rep
sfc: set EF100 VF MAC address through representor
sfc: get provisioned MAC address on EF100 VF probe
sfc: implement ethtool get/set RX ring size for EF100 reps
drivers/net/ethernet/sfc/Makefile | 3 +- drivers/net/ethernet/sfc/ef10.c | 26 +- drivers/net/ethernet/sfc/ef100.c | 1 + drivers/net/ethernet/sfc/ef100_netdev.c | 12 + drivers/net/ethernet/sfc/ef100_nic.c | 142 ++++++++-- drivers/net/ethernet/sfc/ef100_nic.h | 5 + drivers/net/ethernet/sfc/ef100_rep.c | 250 +++++++++++++++++- drivers/net/ethernet/sfc/ef100_rep.h | 22 ++ drivers/net/ethernet/sfc/ef100_rx.c | 45 +++- drivers/net/ethernet/sfc/ef10_sriov.c | 16 +- drivers/net/ethernet/sfc/ethtool_common.c | 1 + drivers/net/ethernet/sfc/filter.h | 18 ++ drivers/net/ethernet/sfc/mae.c | 304 +++++++++++++++++++++- drivers/net/ethernet/sfc/mae.h | 20 ++ drivers/net/ethernet/sfc/mcdi.h | 4 + drivers/net/ethernet/sfc/mcdi_filters.c | 6 +- drivers/net/ethernet/sfc/mcdi_filters.h | 1 + drivers/net/ethernet/sfc/mcdi_pcol_mae.h | 24 ++ drivers/net/ethernet/sfc/net_driver.h | 5 + drivers/net/ethernet/sfc/rx_common.c | 4 - drivers/net/ethernet/sfc/tc.c | 252 ++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 85 ++++++ 22 files changed, 1180 insertions(+), 66 deletions(-) create mode 100644 drivers/net/ethernet/sfc/mcdi_pcol_mae.h create mode 100644 drivers/net/ethernet/sfc/tc.c create mode 100644 drivers/net/ethernet/sfc/tc.h
PATCH 1/14 sfc: plumb ef100 representor stats
From: Edward Cree <[email protected]>
Implement .ndo_get_stats64() method to read values out of struct
efx_rep_sw_stats.
--- drivers/net/ethernet/sfc/ef100_rep.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +14 -0
@@ -79,10 +79,24 @@ static int efx_ef100_rep_get_phys_port_name(struct net_device *dev,return 0 ; } +static void efx_ef100_rep_get_stats64 (struct net_device *dev, +struct rtnl_link_stats64 *stats) +{ +struct efx_rep *efv =netdev_priv (dev); + + stats->rx_packets =atomic64_read (&efv->stats.rx_packets); + stats->tx_packets =atomic64_read (&efv->stats.tx_packets); + stats->rx_bytes =atomic64_read (&efv->stats.rx_bytes); + stats->tx_bytes =atomic64_read (&efv->stats.tx_bytes); + stats->rx_dropped =atomic64_read (&efv->stats.rx_dropped); + stats->tx_errors =atomic64_read (&efv->stats.tx_errors); +} +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, + .ndo_get_stats64 = efx_ef100_rep_get_stats64, }; static void efx_ef100_rep_get_drvinfo(struct net_device *dev,
PATCH 2/14 sfc: ef100 representor RX NAPI poll
In reply to [email protected]From: Edward Cree <[email protected]>
This patch adds the 'bottom half' napi->poll routine for representor RX. See the next patch (with the top half) for an explanation of the 'fake
interrupt' scheme used to drive this NAPI context.
--- drivers/net/ethernet/sfc/ef100_rep.c | 64 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 11 +++++ 2 files changed, 75 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +64 -0
@@ -16,12 +16,16 @@#define EFX_EF100_REP_DRIVER "efx_ef100_rep" +static int efx_ef100_rep_poll (struct napi_struct *napi,int weight); +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); +INIT_LIST_HEAD (&efv->rx_list); +spin_lock_init (&efv->rx_lock); efv->msg_enable =NETIF_MSG_DRV |NETIF_MSG_PROBE |NETIF_MSG_LINK |NETIF_MSG_IFDOWN | NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
@@ -29,6 +33,25 @@ static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv,return 0 ; } +static int efx_ef100_rep_open (struct net_device *net_dev) +{ +struct efx_rep *efv =netdev_priv (net_dev); + +netif_napi_add (net_dev, &efv->napi, efx_ef100_rep_poll, +NAPI_POLL_WEIGHT ); +napi_enable (&efv->napi); +return 0 ; +} + +static int efx_ef100_rep_close (struct net_device *net_dev) +{ +struct efx_rep *efv =netdev_priv (net_dev); + +napi_disable (&efv->napi); +netif_napi_del (&efv->napi); +return 0 ; +} +static netdev_tx_t efx_ef100_rep_xmit (struct sk_buff *skb,struct net_device *dev) {
@@ -93,6 +116,8 @@ static void efx_ef100_rep_get_stats64(struct net_device *dev, }static const struct net_device_ops efx_ef100_rep_netdev_ops = { + .ndo_open = efx_ef100_rep_open, + .ndo_stop = efx_ef100_rep_close, .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,
@@ -256,3 +281,42 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)list_for_each_entry_safe (efv, next, &efx->vf_reps, list)efx_ef100_vfrep_destroy (efx, efv); } + +static int efx_ef100_rep_poll (struct napi_struct *napi,int weight) +{ + struct efx_rep *efv = container_of(napi, struct efx_rep, napi); +unsigned int read_index; +struct list_head head; +struct sk_buff *skb; +bool need_resched; +int spent =0 ; + +INIT_LIST_HEAD (&head); +/* Grab up to 'weight' pending SKBs */ +spin_lock_bh (&efv->rx_lock); + read_index = efv->write_index; +while (spent < weight && !list_empty (&efv->rx_list)) { + skb = list_first_entry(&efv->rx_list, struct sk_buff, list); +list_del (&skb->list); +list_add_tail (&skb->list, &head); + spent++; + } +spin_unlock_bh (&efv->rx_lock); +/* Receive them */ +netif_receive_skb_list (&head); +if (spent < weight) +if (napi_complete_done (napi, spent)) { +spin_lock_bh (&efv->rx_lock); + efv->read_index = read_index; +/* If write_index advanced while we were doing the +* RX, then storing our read_index won't re-prime the +* fake-interrupt. In that case, we need to schedule +* NAPI again to consume the additional packet(s). +*/ + need_resched = efv->write_index != read_index; +spin_unlock_bh (&efv->rx_lock); +if (need_resched) +napi_schedule (&efv->napi); + } +return spent; +}
drivers/net/ethernet/sfc/ef100_rep.h +11 -0
@@ -29,7 +29,13 @@ struct efx_rep_sw_stats {* @msg_enable: log message enable flags * @mport: m-port ID of corresponding VF * @idx: VF index +* @write_index: number of packets enqueued to @rx_list +* @read_index: number of packets consumed from @rx_list +* @rx_pring_size: max length of RX list * @list: entry on efx->vf_reps +* @rx_list: list of SKBs queued for receive in NAPI poll +* @rx_lock: protects @rx_list +* @napi: NAPI control structure * @stats: software traffic counters for netdev stats */ struct efx_rep {
@@ -38,7 +44,12 @@ struct efx_rep {u32 msg_enable;u32 mport;unsigned int idx; +unsigned int write_index, read_index; +unsigned int rx_pring_size;struct list_head list; +struct list_head rx_list; +spinlock_t rx_lock; +struct napi_struct napi;struct efx_rep_sw_stats stats; };
PATCH 3/14 sfc: ef100 representor RX top half
In reply to [email protected]From: Edward Cree <[email protected]>
Representor RX uses a NAPI context driven by a 'fake interrupt': when
the parent PF receives a packet destined for the representor, it adds it to an SKB list (efv->rx_list), and schedules NAPI if the 'fake interrupt' is primed. The NAPI poll then pulls packets off this list and feeds them to the stack with netif_receive_skb_list().
This scheme allows us to decouple representor RX from the parent PF's
RX fast-path.
This patch implements the 'top half', which builds an SKB, copies data
into it from the RX buffer (which can then be released), adds it to the queue and fires the 'fake interrupt' if necessary.
--- drivers/net/ethernet/sfc/ef100_rep.c | 55 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 1 + 2 files changed, 56 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +55 -0
@@ -13,9 +13,12 @@#include "ef100_netdev.h" #include "ef100_nic.h" #include "mae.h" +#include "rx_common.h" #define EFX_EF100_REP_DRIVER "efx_ef100_rep" +#define EFX_REP_DEFAULT_PSEUDO_RING_SIZE 64 +static int efx_ef100_rep_poll (struct napi_struct *napi,int weight); static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv,
@@ -198,6 +201,7 @@ static int efx_ef100_configure_rep(struct efx_rep *efv)u32 selector;int rc; + efv->rx_pring_size =EFX_REP_DEFAULT_PSEUDO_RING_SIZE ;/* Construct mport selector for corresponding VF */ efx_mae_mport_vf (efx, efv->idx, &selector);/* Look up actual mport ID */
@@ -320,3 +324,54 @@ static int efx_ef100_rep_poll(struct napi_struct *napi, int weight) }return spent; } + +void efx_ef100_rep_rx_packet (struct efx_rep *efv,struct efx_rx_buffer *rx_buf) +{ +u8 *eh =efx_rx_buf_va (rx_buf); +struct sk_buff *skb; +bool primed; + +/* Don't allow too many queued SKBs to build up, as they consume +* GFP_ATOMIC memory. If we overrun, just start dropping. +*/ +if (efv->write_index -READ_ONCE (efv->read_index) > efv->rx_pring_size) { +atomic64_inc (&efv->stats.rx_dropped); +if (net_ratelimit ()) +netif_dbg (efv->parent, rx_err, efv->net_dev, +"nodesc-dropped packet of length %u\n" , + rx_buf->len); +return ; + } + + skb =netdev_alloc_skb (efv->net_dev, rx_buf->len); +if (!skb) { +atomic64_inc (&efv->stats.rx_dropped); +if (net_ratelimit ()) +netif_dbg (efv->parent, rx_err, efv->net_dev, +"noskb-dropped packet of length %u\n" , + rx_buf->len); +return ; + } +memcpy (skb->data, eh, rx_buf->len); +__skb_put (skb, rx_buf->len); + +skb_record_rx_queue (skb,0 );/* rep is single-queue */ + +/* Move past the ethernet header */ + skb->protocol =eth_type_trans (skb, efv->net_dev); + +skb_checksum_none_assert (skb); + +atomic64_inc (&efv->stats.rx_packets); +atomic64_add (rx_buf->len, &efv->stats.rx_bytes); + +/* Add it to the rx list */ +spin_lock_bh (&efv->rx_lock); + primed = efv->read_index == efv->write_index; +list_add_tail (&skb->list, &efv->rx_list); + efv->write_index++; +spin_unlock_bh (&efv->rx_lock); +/* Trigger rx work */ +if (primed) +napi_schedule (&efv->napi); +}
drivers/net/ethernet/sfc/ef100_rep.h +1 -0
@@ -57,4 +57,5 @@ 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); +void efx_ef100_rep_rx_packet (struct efx_rep *efv,struct efx_rx_buffer *rx_buf);#endif /* EF100_REP_H */
PATCH 4/14 sfc: determine wire m-port at EF100 PF probe time
In reply to [email protected]From: Edward Cree <[email protected]>
Traffic delivered to the (MAE admin) PF could be from either the wire
or a VF. The INGRESS_MPORT field of the RX prefix distinguishes these; base_mport is the value this field will have for traffic from the wire (which should be delivered to the PF's netdevice, not a representor).
--- drivers/net/ethernet/sfc/ef100_nic.c | 34 ++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_nic.h | 2 ++ drivers/net/ethernet/sfc/mae.c | 10 ++++++++ drivers/net/ethernet/sfc/mae.h | 1 + 4 files changed, 47 insertions(+)
drivers/net/ethernet/sfc/ef100_nic.c +34 -0
@@ -24,6 +24,7 @@#include "ef100_tx.h" #include "ef100_sriov.h" #include "ef100_netdev.h" +#include "mae.h" #include "rx_common.h" #define EF100_MAX_VIS 4096
@@ -704,6 +705,29 @@ static unsigned int efx_ef100_recycle_ring_size(const struct efx_nic *efx)return 10 *EFX_RECYCLE_RING_SIZE_10G ; } +static int efx_ef100_get_base_mport (struct efx_nic *efx) +{ +struct ef100_nic_data *nic_data = efx->nic_data; +u32 selector, id; +int rc; + +/* Construct mport selector for "physical network port" */ +efx_mae_mport_wire (efx, &selector); +/* Look up actual mport ID */ + rc =efx_mae_lookup_mport (efx, selector, &id); +if (rc) +return rc; +/* The ID should always fit in 16 bits, because that's how wide the +* corresponding fields in the RX prefix & TX override descriptor are +*/ +if (id >>16 ) +netif_warn (efx, probe, efx->net_dev,"Bad base m-port id %#x\n" , + id); + nic_data->base_mport = id; + nic_data->have_mport = true; +return 0 ; +} +static int compare_versions (const char *a,const char *b) {int a_major, a_minor, a_point, a_patch;
@@ -1064,6 +1088,16 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)eth_hw_addr_set (net_dev, net_dev->perm_addr);memcpy (nic_data->port_id, net_dev->perm_addr,ETH_ALEN ); +if (!nic_data->grp_mae) +return 0 ; + + rc =efx_ef100_get_base_mport (efx); +if (rc) { +netif_warn (efx, probe, net_dev, +"Failed to probe base mport rc %d; representors will not function\n" , + rc); + } +return 0 ; fail:
drivers/net/ethernet/sfc/ef100_nic.h +2 -0
@@ -72,6 +72,8 @@ struct ef100_nic_data {u8 port_id[ETH_ALEN ];DECLARE_BITMAP (evq_phases,EFX_MAX_CHANNELS );u64 stats[EF100_STAT_COUNT ]; +u32 base_mport; +bool have_mport;/* base_mport was populated successfully */ bool grp_mae;/* MAE Privilege */ u16 tso_max_hdr_len;u16 tso_max_payload_num_segs;
drivers/net/ethernet/sfc/mae.c +10 -0
@@ -13,6 +13,16 @@#include "mcdi.h" #include "mcdi_pcol.h" +void efx_mae_mport_wire (struct efx_nic *efx,u32 *out) +{ +efx_dword_t mport; + +EFX_POPULATE_DWORD_2 (mport, +MAE_MPORT_SELECTOR_TYPE ,MAE_MPORT_SELECTOR_TYPE_PPORT , +MAE_MPORT_SELECTOR_PPORT_ID , efx->port_num); + *out =EFX_DWORD_VAL (mport); +} +void efx_mae_mport_vf (struct efx_nic *efx__always_unused ,u32 vf_id,u32 *out) {efx_dword_t mport;
drivers/net/ethernet/sfc/mae.h +1 -0
@@ -15,6 +15,7 @@#include "net_driver.h" +void efx_mae_mport_wire (struct efx_nic *efx,u32 *out);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);
kernel test robot
build botRe: [PATCH net-next 04/14] sfc: determine wire m-port at EF100 PF probe time
I love your patch! Yet something to improve:
Hi,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 949d6b405e6160ae44baea39192d67b39cb7eeac config: mips-randconfig-s041-20220721 (https://download.01.org/0day-ci/archive/20220723/[email protected]/config) compiler: mips-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/f00d0e9f57792091c90518b98e8b722a4018f062
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059
git checkout f00d0e9f57792091c90518b98e8b722a4018f062
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=mips SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable
All errors (new ones prefixed by >>):
mips-linux-ld: drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_probe_netdev_pf':
ef100_nic.c:(.text+0x2904): undefined reference to `efx_mae_mport_wire'
>> mips-linux-ld: ef100_nic.c:(.text+0x2914): undefined reference to `efx_mae_lookup_mport'
Signature · 2 lines
0-DAY CI Kernel Test Service https://01.org/lkp
kernel test robot
build botRe: [PATCH net-next 04/14] sfc: determine wire m-port at EF100 PF probe time
In reply to [email protected]I love your patch! Yet something to improve:
Hi,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 949d6b405e6160ae44baea39192d67b39cb7eeac config: s390-randconfig-r003-20220721 (https://download.01.org/0day-ci/archive/20220723/[email protected]/config) compiler: s390-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/f00d0e9f57792091c90518b98e8b722a4018f062
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059 git checkout f00d0e9f57792091c90518b98e8b722a4018f062
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable
All errors (new ones prefixed by >>):
s390-linux-ld: s390-linux-ld: DWARF error: could not find abbrev number 5931 drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_probe_netdev_pf':
ef100_nic.c:(.text+0x2520): undefined reference to `efx_mae_mport_wire'
>> s390-linux-ld: ef100_nic.c:(.text+0x2534): undefined reference to `efx_mae_lookup_mport'
Signature · 2 lines
0-DAY CI Kernel Test Service https://01.org/lkp
Re: [PATCH net-next 04/14] sfc: determine wire m-port at EF100 PF probe time
Quoted 6 lines · kernel test robot
All errors (new ones prefixed by >>):
s390-linux-ld: s390-linux-ld: DWARF error: could not find abbrev number 5931 drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_probe_netdev_pf': ef100_nic.c:(.text+0x2520): undefined reference to `efx_mae_mport_wire'Quoted 1 line
Quoted 1 line
s390-linux-ld: ef100_nic.c:(.text+0x2534): undefined reference to `efx_mae_lookup_mport'
Oh, I see what's wrong here.
mae.o is under CONFIG_SFC_SRIOV in the Makefile, but these calls into it
are made unconditionally. And I hadn't thought to test with CONFIG_SFC_SRIOV=n. (D'oh!)
I'm able to reproduce on x86_64 with that config change, will fix in v2.
-ed
PATCH 5/14 sfc: check ef100 RX packets are from the wire
In reply to [email protected]From: Edward Cree <[email protected]>
If not, for now drop them and warn. A subsequent patch will look up
the source m-port to try and find a representor to deliver them to.
--- drivers/net/ethernet/sfc/ef100_rx.c | 28 ++++++++++++++++++----- drivers/net/ethernet/sfc/ethtool_common.c | 1 + drivers/net/ethernet/sfc/net_driver.h | 3 +++ 3 files changed, 26 insertions(+), 6 deletions(-)
drivers/net/ethernet/sfc/ef100_rx.c +22 -6
@@ -55,10 +55,14 @@ static bool ef100_has_fcs_error(struct efx_channel *channel, u32 *prefix)void __ef100_rx_packet (struct efx_channel *channel) { -struct efx_rx_buffer *rx_buf =efx_rx_buffer (&channel->rx_queue, channel->rx_pkt_index); +struct efx_rx_queue *rx_queue =efx_channel_get_rx_queue (channel); +struct efx_rx_buffer *rx_buf =efx_rx_buffer (rx_queue, + channel->rx_pkt_index);struct efx_nic *efx = channel->efx; +struct ef100_nic_data *nic_data;u8 *eh =efx_rx_buf_va (rx_buf);__wsum csum =0 ; +u16 ing_port;u32 *prefix; prefix = (u32 *)(eh -ESE_GZ_RX_PKT_PREFIX_LEN );
@@ -76,6 +80,19 @@ void __ef100_rx_packet(struct efx_channel *channel) goto out; } + ing_port =le16_to_cpu ((__force __le16 )PREFIX_FIELD (prefix,INGRESS_MPORT )); + + nic_data = efx->nic_data; + +if (nic_data->have_mport && ing_port != nic_data->base_mport) { +if (net_ratelimit ()) +netif_warn (efx, drv, efx->net_dev, +"Unrecognised ing_port %04x (base %04x), dropping\n" , + ing_port, nic_data->base_mport); + channel->n_rx_mport_bad++; + goto free_rx_buffer; + } +if (likely (efx->net_dev->features &NETIF_F_RXCSUM )) {if (PREFIX_FIELD (prefix,NT_OR_INNER_L3_CLASS ) ==1 ) { ++channel->n_rx_ip_hdr_chksum_err;
@@ -87,17 +104,16 @@ void __ef100_rx_packet(struct efx_channel *channel) }if (channel->type->receive_skb) { -struct efx_rx_queue *rx_queue = -efx_channel_get_rx_queue (channel); -/* no support for special channels yet, so just discard */ WARN_ON_ONCE (1 ); -efx_free_rx_buffers (rx_queue, rx_buf,1 ); - goto out; + goto free_rx_buffer; }efx_rx_packet_gro (channel, rx_buf, channel->rx_pkt_n_frags, eh, csum); + goto out; +free_rx_buffer: +efx_free_rx_buffers (rx_queue, rx_buf,1 ); out: channel->rx_pkt_n_frags =0 ; }
drivers/net/ethernet/sfc/ethtool_common.c +1 -0
@@ -91,6 +91,7 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {EFX_ETHTOOL_UINT_CHANNEL_STAT (rx_xdp_bad_drops),EFX_ETHTOOL_UINT_CHANNEL_STAT (rx_xdp_tx),EFX_ETHTOOL_UINT_CHANNEL_STAT (rx_xdp_redirect), +EFX_ETHTOOL_UINT_CHANNEL_STAT (rx_mport_bad), #ifdef CONFIG_RFS_ACCELEFX_ETHTOOL_UINT_CHANNEL_STAT_NO_N (rfs_filter_count), EFX_ETHTOOL_UINT_CHANNEL_STAT(rfs_succeeded),
drivers/net/ethernet/sfc/net_driver.h +3 -0
@@ -478,6 +478,8 @@ enum efx_sync_events_state {* @n_rx_xdp_bad_drops: Count of RX packets dropped due to XDP errors * @n_rx_xdp_tx: Count of RX packets retransmitted due to XDP * @n_rx_xdp_redirect: Count of RX packets redirected to a different NIC by XDP +* @n_rx_mport_bad: Count of RX packets dropped because their ingress mport was +* not recognised * @rx_pkt_n_frags: Number of fragments in next packet to be delivered by * __efx_rx_packet(), or zero if there is none * @rx_pkt_index: Ring index of first buffer for next packet to be delivered
@@ -540,6 +542,7 @@ struct efx_channel {unsigned int n_rx_xdp_bad_drops;unsigned int n_rx_xdp_tx;unsigned int n_rx_xdp_redirect; +unsigned int n_rx_mport_bad;unsigned int rx_pkt_n_frags;unsigned int rx_pkt_index;
PATCH 6/14 sfc: receive packets from EF100 VFs into representors
In reply to [email protected]From: Edward Cree <[email protected]>
If the source m-port of a packet in __ef100_rx_packet() is a VF,
hand off the packet to the corresponding representor with efx_ef100_rep_rx_packet().
--- drivers/net/ethernet/sfc/ef100_rep.c | 19 +++++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 5 +++++ drivers/net/ethernet/sfc/ef100_rx.c | 17 +++++++++++++++++ 3 files changed, 41 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +19 -0
@@ -224,6 +224,7 @@ static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)list_del (&efv->list);spin_unlock_bh (&efx->vf_reps_lock);rtnl_unlock (); +synchronize_rcu ();free_netdev (efv->net_dev); }
@@ -375,3 +376,21 @@ void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf)if (primed)napi_schedule (&efv->napi); } + +struct efx_rep *efx_ef100_find_rep_by_mport (struct efx_nic *efx,u16 mport) +{ +struct efx_rep *efv, *out =NULL ; + +/* spinlock guards against list mutation while we're walking it; +* but caller must also hold rcu_read_lock() to ensure the netdev +* isn't freed after we drop the spinlock. +*/ +spin_lock_bh (&efx->vf_reps_lock); +list_for_each_entry (efv, &efx->vf_reps, list) +if (efv->mport == mport) { + out = efv; +break ; + } +spin_unlock_bh (&efx->vf_reps_lock); +return out; +}
drivers/net/ethernet/sfc/ef100_rep.h +5 -0
@@ -58,4 +58,9 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv);void efx_ef100_fini_vfreps (struct efx_nic *efx);void efx_ef100_rep_rx_packet (struct efx_rep *efv,struct efx_rx_buffer *rx_buf); +/* Returns the representor corresponding to a VF m-port, or NULL +* @mport is an m-port label, *not* an m-port ID! +* Caller must hold rcu_read_lock(). +*/ +struct efx_rep *efx_ef100_find_rep_by_mport (struct efx_nic *efx,u16 mport);#endif /* EF100_REP_H */
drivers/net/ethernet/sfc/ef100_rx.c +17 -0
@@ -85,6 +85,23 @@ void __ef100_rx_packet(struct efx_channel *channel) nic_data = efx->nic_data;if (nic_data->have_mport && ing_port != nic_data->base_mport) { +struct efx_rep *efv; + +rcu_read_lock (); + efv =efx_ef100_find_rep_by_mport (efx, ing_port); +if (efv) { +if (efv->net_dev->flags &IFF_UP ) +efx_ef100_rep_rx_packet (efv, rx_buf); +rcu_read_unlock (); +/* Representor Rx doesn't care about PF Rx buffer +* ownership, it just makes a copy. So, we are done +* with the Rx buffer from PF point of view and should +* free it. +*/ + goto free_rx_buffer; + } +rcu_read_unlock (); +if (net_ratelimit ()) netif_warn(efx, drv, efx->net_dev, "Unrecognised ing_port %04x (base %04x), dropping\n",
kernel test robot
build botRe: [PATCH net-next 06/14] sfc: receive packets from EF100 VFs into representors
I love your patch! Yet something to improve:
Hi,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 949d6b405e6160ae44baea39192d67b39cb7eeac config: s390-randconfig-r003-20220721 (https://download.01.org/0day-ci/archive/20220723/[email protected]/config) compiler: s390-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/9c27ea557e7daaf1ef637c760e2ea4b29e5141b0
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review ecree-xilinx-com/sfc-VF-representors-for-EF100-RX-side/20220723-001059 git checkout 9c27ea557e7daaf1ef637c760e2ea4b29e5141b0
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable
All errors (new ones prefixed by >>):
s390-linux-ld: s390-linux-ld: DWARF error: could not find abbrev number 119 drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_probe_netdev_pf':
ef100_nic.c:(.text+0x2520): undefined reference to `efx_mae_mport_wire'
s390-linux-ld: ef100_nic.c:(.text+0x2534): undefined reference to `efx_mae_lookup_mport'
s390-linux-ld: s390-linux-ld: DWARF error: could not find abbrev number 13089 drivers/net/ethernet/sfc/ef100_rx.o: in function `__ef100_rx_packet':
ef100_rx.c:(.text+0x1f8): undefined reference to `efx_ef100_find_rep_by_mport'
>> s390-linux-ld: ef100_rx.c:(.text+0x240): undefined reference to `efx_ef100_rep_rx_packet'
Signature · 2 lines
0-DAY CI Kernel Test Service https://01.org/lkp
PATCH 7/14 sfc: insert default MAE rules to connect VFs to representors
In reply to [email protected]From: Edward Cree <[email protected]>
Default rules are low-priority switching rules which the hardware uses
in the absence of higher-priority rules. Each representor requires a corresponding rule matching traffic from its representee VF and delivering to the PF (where a check on INGRESS_MPORT in __ef100_rx_packet() will direct it to the representor). No rule is required in the reverse direction, because representor TX uses a TX override descriptor to bypass the MAE and deliver directly to the VF.
Since inserting any rule into the MAE disables the firmware's own
default rules, also insert a pair of rules to connect the PF to the physical network port and vice-versa.
--- drivers/net/ethernet/sfc/Makefile | 3 +- drivers/net/ethernet/sfc/ef100.c | 1 + drivers/net/ethernet/sfc/ef100_netdev.c | 2 + drivers/net/ethernet/sfc/ef100_nic.c | 17 ++ drivers/net/ethernet/sfc/ef100_rep.c | 20 +- drivers/net/ethernet/sfc/ef100_rep.h | 3 + drivers/net/ethernet/sfc/mae.c | 257 ++++++++++++++++++++++- drivers/net/ethernet/sfc/mae.h | 16 ++ drivers/net/ethernet/sfc/mcdi.h | 4 + drivers/net/ethernet/sfc/mcdi_pcol_mae.h | 24 +++ drivers/net/ethernet/sfc/net_driver.h | 2 + drivers/net/ethernet/sfc/tc.c | 183 ++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 76 +++++++ 13 files changed, 602 insertions(+), 6 deletions(-) create mode 100644 drivers/net/ethernet/sfc/mcdi_pcol_mae.h create mode 100644 drivers/net/ethernet/sfc/tc.c create mode 100644 drivers/net/ethernet/sfc/tc.h
drivers/net/ethernet/sfc/Makefile +2 -1
@@ -8,7 +8,8 @@ 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 mae.o +sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \ + mae.o tc.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/ethernet/sfc/ef100.c +1 -0
@@ -431,6 +431,7 @@ static void ef100_pci_remove(struct pci_dev *pci_dev) probe_data = container_of(efx, struct efx_probe_data, efx);ef100_remove_netdev (probe_data); +efx_fini_struct_tc (efx);ef100_remove (efx);efx_fini_io (efx);
drivers/net/ethernet/sfc/ef100_netdev.c +2 -0
@@ -329,6 +329,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)ef100_unregister_netdev (efx); +efx_fini_tc (efx); +down_write (&efx->filter_sem);efx_mcdi_filter_table_remove (efx);up_write (&efx->filter_sem);
drivers/net/ethernet/sfc/ef100_nic.c +17 -0
@@ -1091,6 +1091,10 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)if (!nic_data->grp_mae)return 0 ; + rc =efx_init_struct_tc (efx); +if (rc) +return rc; + rc =efx_ef100_get_base_mport (efx);if (rc) { netif_warn(efx, probe, net_dev,
@@ -1098,6 +1102,19 @@ int ef100_probe_netdev_pf(struct efx_nic *efx) rc); } + rc =efx_init_tc (efx); +if (rc) { +/* Either we don't have an MAE at all (i.e. legacy v-switching), +* or we do but we failed to probe it. In the latter case, we +* may not have set up default rules, in which case we won't be +* able to pass any traffic. However, we don't fail the probe, +* because the user might need to use the netdevice to apply +* configuration changes to fix whatever's wrong with the MAE. +*/ +netif_warn (efx, probe, net_dev,"Failed to probe MAE rc %d\n" , + rc); + } +return 0 ; fail:
drivers/net/ethernet/sfc/ef100_rep.c +16 -4
@@ -27,6 +27,8 @@ static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, efv->parent = efx; efv->idx = i;INIT_LIST_HEAD (&efv->list); + efv->dflt.fw_id =MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL ; +INIT_LIST_HEAD (&efv->dflt.acts.list);INIT_LIST_HEAD (&efv->rx_list);spin_lock_init (&efv->rx_lock); efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE |
@@ -212,7 +214,14 @@ static int efx_ef100_configure_rep(struct efx_rep *efv)/* mport label should fit in 16 bits */ WARN_ON (efv->mport >>16 ); -return 0 ; +return efx_tc_configure_default_rule_rep (efv); +} + +static void efx_ef100_deconfigure_rep (struct efx_rep *efv) +{ +struct efx_nic *efx = efv->parent; + +efx_tc_deconfigure_default_rule (efx, &efv->dflt); }static void efx_ef100_rep_destroy_netdev (struct efx_rep *efv)
@@ -246,19 +255,21 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)pci_err (efx->pci_dev,"Failed to configure representor for VF %d, rc %d\n" , i, rc); - goto fail; + goto fail1; } rc =register_netdev (efv->net_dev);if (rc) {pci_err (efx->pci_dev,"Failed to register representor for VF %d, rc %d\n" , i, rc); - goto fail; + goto fail2; }pci_dbg (efx->pci_dev,"Representor for VF %d is %s\n" , i, efv->net_dev->name);return 0 ; -fail: +fail2: +efx_ef100_deconfigure_rep (efv); +fail1:efx_ef100_rep_destroy_netdev (efv);return rc; }
@@ -272,6 +283,7 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)return ;netif_dbg (efx, drv, rep_dev,"Removing VF representor\n" );unregister_netdev (rep_dev); +efx_ef100_deconfigure_rep (efv);efx_ef100_rep_destroy_netdev (efv); }
drivers/net/ethernet/sfc/ef100_rep.h +3 -0
@@ -14,6 +14,7 @@#define EF100_REP_H #include "net_driver.h" +#include "tc.h" struct efx_rep_sw_stats {atomic64_t rx_packets, tx_packets;
@@ -32,6 +33,7 @@ struct efx_rep_sw_stats {* @write_index: number of packets enqueued to @rx_list * @read_index: number of packets consumed from @rx_list * @rx_pring_size: max length of RX list +* @dflt: default-rule for MAE switching * @list: entry on efx->vf_reps * @rx_list: list of SKBs queued for receive in NAPI poll * @rx_lock: protects @rx_list
@@ -46,6 +48,7 @@ struct efx_rep {unsigned int idx;unsigned int write_index, read_index;unsigned int rx_pring_size; +struct efx_tc_flow_rule dflt;struct list_head list;struct list_head rx_list;spinlock_t rx_lock;
drivers/net/ethernet/sfc/mae.c +256 -1
278 lines not on this page · raw message
drivers/net/ethernet/sfc/mae.h +16 -0
@@ -14,10 +14,26 @@/* MCDI interface for the ef100 Match-Action Engine */ #include "net_driver.h" +#include "tc.h" +#include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */ void efx_mae_mport_wire (struct efx_nic *efx,u32 *out); +void efx_mae_mport_uplink (struct efx_nic *efx,u32 *out);void efx_mae_mport_vf (struct efx_nic *efx,u32 vf_id,u32 *out); +void efx_mae_mport_mport (struct efx_nic *efx,u32 mport_id,u32 *out);int efx_mae_lookup_mport (struct efx_nic *efx,u32 selector,u32 *id); +int efx_mae_alloc_action_set (struct efx_nic *efx,struct efx_tc_action_set *act); +int efx_mae_free_action_set (struct efx_nic *efx,u32 fw_id); + +int efx_mae_alloc_action_set_list (struct efx_nic *efx, +struct efx_tc_action_set_list *acts); +int efx_mae_free_action_set_list (struct efx_nic *efx, +struct efx_tc_action_set_list *acts); + +int efx_mae_insert_rule (struct efx_nic *efx,const struct efx_tc_match *match, +u32 prio,u32 acts_id,u32 *id); +int efx_mae_delete_rule (struct efx_nic *efx,u32 id); +#endif /* EF100_MAE_H */
drivers/net/ethernet/sfc/mcdi.h +4 -0
@@ -205,6 +205,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); ((_ofst) + BUILD_BUG_ON_ZERO((_ofst) & (_align - 1)))#define _MCDI_DWORD (_buf, _field) \ ((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2)) +#define _MCDI_STRUCT_DWORD (_buf, _field) \ + ((_buf) + (_MCDI_CHECK_ALIGN(_field ## _OFST, 4) >> 2))#define MCDI_BYTE (_buf, _field) \ ((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \
@@ -214,6 +216,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))#define MCDI_SET_DWORD (_buf, _field, _value) \ EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value) +#define MCDI_STRUCT_SET_DWORD (_buf, _field, _value) \ + EFX_POPULATE_DWORD_1(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0, _value)#define MCDI_DWORD (_buf, _field) \ EFX_DWORD_FIELD(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0)#define MCDI_POPULATE_DWORD_1 (_buf, _field, _name1, _value1) \
drivers/net/ethernet/sfc/mcdi_pcol_mae.h new file +24 -0
@@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** +* Driver for Solarflare network controllers and boards +* Copyright 2019 Solarflare Communications 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 +* by the Free Software Foundation, incorporated herein by reference. +*/ + +#ifndef MCDI_PCOL_MAE_H +#define MCDI_PCOL_MAE_H +/* MCDI definitions for Match-Action Engine functionality, that are +* missing from the main mcdi_pcol.h +*/ + +/* MC_CMD_MAE_COUNTER_LIST_ALLOC is not (yet) a released API, but the +* following value is needed as an argument to MC_CMD_MAE_ACTION_SET_ALLOC. +*/ +/* enum: A counter ID that is guaranteed never to represent a real counter */ +#define MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL 0xffffffff + +#endif /* MCDI_PCOL_MAE_H */
drivers/net/ethernet/sfc/net_driver.h +2 -0
@@ -978,6 +978,7 @@ enum efx_xdp_tx_queues_mode {* @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their * xdp_rxq_info structures? * @netdev_notifier: Netdevice notifier. +* @tc: state for TC offload (EF100). * @mem_bar: The BAR that is mapped into membase. * @reg_base: Offset from the start of the bar to the function control window. * @monitor_work: Hardware monitor workitem
@@ -1161,6 +1162,7 @@ struct efx_nic {bool xdp_rxq_info_failed;struct notifier_block netdev_notifier; +struct efx_tc_state *tc;unsigned int mem_bar;u32 reg_base;
drivers/net/ethernet/sfc/tc.c new file +183 -0
183 lines not on this page · raw message
drivers/net/ethernet/sfc/tc.h new file +76 -0
76 lines not on this page · raw message
PATCH 8/14 sfc: move table locking into filter_table_{probe,remove} methods
In reply to [email protected]From: Edward Cree <[email protected]>
We need to be able to drop the efx->filter_sem in ef100_filter_table_up()
so that we can call functions that insert filters (and thus take that rwsem for read), which means the efx->type->filter_table_probe method needs to be responsible for taking the lock in the first place.
--- drivers/net/ethernet/sfc/ef10.c | 26 ++++++++++++++----------- drivers/net/ethernet/sfc/ef100_nic.c | 22 +++++++++++++-------- drivers/net/ethernet/sfc/ef10_sriov.c | 16 +++------------ drivers/net/ethernet/sfc/mcdi_filters.h | 1 + drivers/net/ethernet/sfc/rx_common.c | 4 ---- 5 files changed, 33 insertions(+), 36 deletions(-)
drivers/net/ethernet/sfc/ef10.c +15 -11
@@ -2538,23 +2538,33 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)if (rc)return rc; +down_write (&efx->filter_sem); rc =efx_mcdi_filter_table_probe (efx, nic_data->workaround_26807);if (rc) -return rc; + goto out_unlock;list_for_each_entry (vlan, &nic_data->vlan_list, list) { rc =efx_mcdi_filter_add_vlan (efx, vlan->vid);if (rc) goto fail_add_vlan; } -return 0 ; + goto out_unlock; fail_add_vlan:efx_mcdi_filter_table_remove (efx); +out_unlock: +up_write (&efx->filter_sem);return rc; } +static void efx_ef10_filter_table_remove (struct efx_nic *efx) +{ +down_write (&efx->filter_sem); +efx_mcdi_filter_table_remove (efx); +up_write (&efx->filter_sem); +} +/* This creates an entry in the RX descriptor queue */ static inline void efx_ef10_build_rx_desc (struct efx_rx_queue *rx_queue,unsigned int index)
@@ -3211,9 +3221,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)efx_device_detach_sync (efx);efx_net_stop (efx->net_dev); -down_write (&efx->filter_sem); -efx_mcdi_filter_table_remove (efx); -up_write (&efx->filter_sem); +efx_ef10_filter_table_remove (efx); rc =efx_ef10_vadaptor_free (efx, efx->vport_id);if (rc)
@@ -3243,9 +3251,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)if (rc2) goto reset_nic; restore_filters: -down_write (&efx->filter_sem); rc2 =efx_ef10_filter_table_probe (efx); -up_write (&efx->filter_sem);if (rc2) goto reset_nic;
@@ -3275,8 +3281,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)efx_net_stop (efx->net_dev);mutex_lock (&efx->mac_lock); -down_write (&efx->filter_sem); -efx_mcdi_filter_table_remove (efx); +efx_ef10_filter_table_remove (efx);ether_addr_copy (MCDI_PTR (inbuf,VADAPTOR_SET_MAC_IN_MACADDR ), efx->net_dev->dev_addr);
@@ -3286,7 +3291,6 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) sizeof(inbuf), NULL, 0, NULL);efx_ef10_filter_table_probe (efx); -up_write (&efx->filter_sem);mutex_unlock (&efx->mac_lock);if (was_enabled)
@@ -4092,7 +4096,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .ev_test_generate = efx_ef10_ev_test_generate, .filter_table_probe = efx_ef10_filter_table_probe, .filter_table_restore = efx_mcdi_filter_table_restore, - .filter_table_remove = efx_mcdi_filter_table_remove, + .filter_table_remove = efx_ef10_filter_table_remove, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter, .filter_insert = efx_mcdi_filter_insert, .filter_remove_safe = efx_mcdi_filter_remove_safe,
drivers/net/ethernet/sfc/ef100_nic.c +14 -8
@@ -375,26 +375,32 @@ static int ef100_filter_table_up(struct efx_nic *efx) {int rc; +down_write (&efx->filter_sem); rc =efx_mcdi_filter_add_vlan (efx,EFX_FILTER_VID_UNSPEC ); -if (rc) { -efx_mcdi_filter_table_down (efx); -return rc; - } +if (rc) + goto fail_unspec; rc =efx_mcdi_filter_add_vlan (efx,0 ); -if (rc) { -efx_mcdi_filter_del_vlan (efx,EFX_FILTER_VID_UNSPEC ); -efx_mcdi_filter_table_down (efx); - } +if (rc) + goto fail_vlan0; +up_write (&efx->filter_sem); +return 0 ; +fail_vlan0: +efx_mcdi_filter_del_vlan (efx,EFX_FILTER_VID_UNSPEC ); +fail_unspec: +efx_mcdi_filter_table_down (efx); +up_write (&efx->filter_sem);return rc; }static void ef100_filter_table_down (struct efx_nic *efx) { +down_write (&efx->filter_sem);efx_mcdi_filter_del_vlan (efx,0 );efx_mcdi_filter_del_vlan (efx,EFX_FILTER_VID_UNSPEC );efx_mcdi_filter_table_down (efx); +up_write (&efx->filter_sem); }/* Other
drivers/net/ethernet/sfc/ef10_sriov.c +3 -13
@@ -501,14 +501,11 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac)efx_device_detach_sync (vf->efx);efx_net_stop (vf->efx->net_dev); -down_write (&vf->efx->filter_sem); vf->efx->type->filter_table_remove (vf->efx); rc =efx_ef10_vadaptor_free (vf->efx,EVB_PORT_ID_ASSIGNED ); -if (rc) { -up_write (&vf->efx->filter_sem); +if (rc)return rc; - } } rc =efx_ef10_evb_port_assign (efx,EVB_PORT_ID_NULL , vf_i);
@@ -539,12 +536,9 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac)if (vf->efx) {/* VF cannot use the vport_id that the PF created */ rc =efx_ef10_vadaptor_alloc (vf->efx,EVB_PORT_ID_ASSIGNED ); -if (rc) { -up_write (&vf->efx->filter_sem); +if (rc)return rc; - } vf->efx->type->filter_table_probe (vf->efx); -up_write (&vf->efx->filter_sem);efx_net_open (vf->efx->net_dev);efx_device_attach_if_not_resetting (vf->efx); }
@@ -580,7 +574,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,efx_net_stop (vf->efx->net_dev);mutex_lock (&vf->efx->mac_lock); -down_write (&vf->efx->filter_sem); vf->efx->type->filter_table_remove (vf->efx); rc =efx_ef10_vadaptor_free (vf->efx,EVB_PORT_ID_ASSIGNED );
@@ -654,7 +647,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,if (rc2) goto reset_nic_up_write; -up_write (&vf->efx->filter_sem);mutex_unlock (&vf->efx->mac_lock); rc2 =efx_net_open (vf->efx->net_dev);
@@ -666,10 +658,8 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,return rc; reset_nic_up_write: -if (vf->efx) { -up_write (&vf->efx->filter_sem); +if (vf->efx)mutex_unlock (&vf->efx->mac_lock); - } reset_nic:if (vf->efx) { netif_err(efx, drv, efx->net_dev,
drivers/net/ethernet/sfc/mcdi_filters.h +1 -0
@@ -89,6 +89,7 @@ struct efx_mcdi_filter_table {*/ bool mc_chaining;bool vlan_filter; +/* Entries on the vlan_list are added/removed under filter_sem */ struct list_head vlan_list; };
drivers/net/ethernet/sfc/rx_common.c +0 -4
@@ -793,7 +793,6 @@ int efx_probe_filters(struct efx_nic *efx)int rc;mutex_lock (&efx->mac_lock); -down_write (&efx->filter_sem); rc = efx->type->filter_table_probe (efx);if (rc) goto out_unlock;
@@ -830,7 +829,6 @@ int efx_probe_filters(struct efx_nic *efx) }#endif out_unlock: -up_write (&efx->filter_sem);mutex_unlock (&efx->mac_lock);return rc; }
@@ -846,9 +844,7 @@ void efx_remove_filters(struct efx_nic *efx) channel->rps_flow_id = NULL; }#endif -down_write (&efx->filter_sem); efx->type->filter_table_remove (efx); -up_write (&efx->filter_sem); }#ifdef CONFIG_RFS_ACCEL
PATCH 9/14 sfc: use a dynamic m-port for representor RX and set it promisc
In reply to [email protected]From: Edward Cree <[email protected]>
Representors do not want to be subject to the PF's Ethernet address
filters, since traffic from VFs will typically have a destination either elsewhere on the link segment or on an overlay network.
So, create a dynamic m-port with promiscuous and all-multicast
filters, and set it as the egress port of representor default rules. Since the m-port is an alias of the calling PF's own m-port, traffic will still be delivered to the PF's RXQs, but it will be subject to the VNRX filter rules installed on the dynamic m-port (specified by the v-port ID field of the filter spec).
--- drivers/net/ethernet/sfc/ef100_nic.c | 11 ++++ drivers/net/ethernet/sfc/filter.h | 18 ++++++ drivers/net/ethernet/sfc/mae.c | 37 +++++++++++++ drivers/net/ethernet/sfc/mae.h | 3 + drivers/net/ethernet/sfc/mcdi_filters.c | 6 +- drivers/net/ethernet/sfc/tc.c | 73 ++++++++++++++++++++++++- drivers/net/ethernet/sfc/tc.h | 9 +++ 7 files changed, 154 insertions(+), 3 deletions(-)
drivers/net/ethernet/sfc/ef100_nic.c +11 -0
@@ -24,6 +24,7 @@#include "ef100_tx.h" #include "ef100_sriov.h" #include "ef100_netdev.h" +#include "tc.h" #include "mae.h" #include "rx_common.h"
@@ -383,7 +384,16 @@ static int ef100_filter_table_up(struct efx_nic *efx) rc =efx_mcdi_filter_add_vlan (efx,0 );if (rc) goto fail_vlan0; +/* Drop the lock: we've finished altering table existence, and +* filter insertion will need to take the lock for read. +*/ up_write (&efx->filter_sem); + rc =efx_tc_insert_rep_filters (efx); +/* Rep filter failure is nonfatal */ +if (rc) +netif_warn (efx, drv, efx->net_dev, +"Failed to insert representor filters, rc %d\n" , + rc);return 0 ; fail_vlan0:
@@ -396,6 +406,7 @@ static int ef100_filter_table_up(struct efx_nic *efx)static void ef100_filter_table_down (struct efx_nic *efx) { +efx_tc_remove_rep_filters (efx);down_write (&efx->filter_sem);efx_mcdi_filter_del_vlan (efx,0 );efx_mcdi_filter_del_vlan (efx,EFX_FILTER_VID_UNSPEC );
drivers/net/ethernet/sfc/filter.h +18 -0
@@ -88,6 +88,7 @@ enum efx_filter_priority {* the automatic filter in its place. * @EFX_FILTER_FLAG_RX: Filter is for RX * @EFX_FILTER_FLAG_TX: Filter is for TX +* @EFX_FILTER_FLAG_VPORT_ID: Virtual port ID for adapter switching. */ enum efx_filter_flags {EFX_FILTER_FLAG_RX_RSS =0x01 ,
@@ -95,6 +96,7 @@ enum efx_filter_flags {EFX_FILTER_FLAG_RX_OVER_AUTO =0x04 ,EFX_FILTER_FLAG_RX =0x08 ,EFX_FILTER_FLAG_TX =0x10 , + EFX_FILTER_FLAG_VPORT_ID = 0x20, };/** enum efx_encap_type - types of encapsulation
@@ -127,6 +129,9 @@ enum efx_encap_type {* MCFW context_id. * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for * an RX drop filter +* @vport_id: Virtual port ID associated with RX queue, for adapter switching, +* if %EFX_FILTER_FLAG_VPORT_ID is set. This is an MCFW vport_id, or on +* EF100 an mport selector. * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set * @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set * @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or
@@ -156,6 +161,7 @@ struct efx_filter_spec { u32 priority:2; u32 flags:6; u32 dmaq_id:12; +u32 vport_id;u32 rss_context;__be16 outer_vid__aligned(4) ;/* allow jhash2() of match values */ __be16 inner_vid;
@@ -292,6 +298,18 @@ static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec)return 0 ; } +/** +* efx_filter_set_vport_id - override virtual port id relating to filter +* @spec: Specification to initialise +* @vport_id: firmware ID of the virtual port +*/ +static inline void efx_filter_set_vport_id (struct efx_filter_spec *spec, +u32 vport_id) +{ + spec->flags |=EFX_FILTER_FLAG_VPORT_ID ; + spec->vport_id = vport_id; +} +static inline void efx_filter_set_encap_type (struct efx_filter_spec *spec,enum efx_encap_type encap_type) {
drivers/net/ethernet/sfc/mae.c +37 -0
@@ -13,6 +13,43 @@#include "mcdi.h" #include "mcdi_pcol_mae.h" +int efx_mae_allocate_mport (struct efx_nic *efx,u32 *id,u32 *label) +{ +MCDI_DECLARE_BUF (outbuf,MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN ); +MCDI_DECLARE_BUF (inbuf,MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN ); +size_t outlen; +int rc; + +if (WARN_ON_ONCE (!id)) +return -EINVAL ; +if (WARN_ON_ONCE (!label)) +return -EINVAL ; + +MCDI_SET_DWORD (inbuf,MAE_MPORT_ALLOC_ALIAS_IN_TYPE , +MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS ); +MCDI_SET_DWORD (inbuf,MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT , +MAE_MPORT_SELECTOR_ASSIGNED ); + rc =efx_mcdi_rpc (efx,MC_CMD_MAE_MPORT_ALLOC , inbuf,sizeof (inbuf), + outbuf,sizeof (outbuf), &outlen); +if (rc) +return rc; +if (outlen <sizeof (outbuf)) +return -EIO ; + *id =MCDI_DWORD (outbuf,MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID ); + *label =MCDI_DWORD (outbuf,MAE_MPORT_ALLOC_ALIAS_OUT_LABEL ); +return 0 ; +} + +int efx_mae_free_mport (struct efx_nic *efx,u32 id) +{ +MCDI_DECLARE_BUF (inbuf,MC_CMD_MAE_MPORT_FREE_IN_LEN ); + +BUILD_BUG_ON (MC_CMD_MAE_MPORT_FREE_OUT_LEN ); +MCDI_SET_DWORD (inbuf,MAE_MPORT_FREE_IN_MPORT_ID , id); +return efx_mcdi_rpc (efx,MC_CMD_MAE_MPORT_FREE , inbuf,sizeof (inbuf), +NULL ,0 ,NULL ); +} +void efx_mae_mport_wire (struct efx_nic *efx,u32 *out) {efx_dword_t mport;
drivers/net/ethernet/sfc/mae.h +3 -0
@@ -17,6 +17,9 @@#include "tc.h" #include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */ +int efx_mae_allocate_mport (struct efx_nic *efx,u32 *id,u32 *label); +int efx_mae_free_mport (struct efx_nic *efx,u32 id); +void efx_mae_mport_wire (struct efx_nic *efx,u32 *out);void efx_mae_mport_uplink (struct efx_nic *efx,u32 *out);void efx_mae_mport_vf (struct efx_nic *efx,u32 vf_id,u32 *out);
drivers/net/ethernet/sfc/mcdi_filters.c +5 -1
@@ -221,7 +221,10 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,efx_mcdi_filter_push_prep_set_match_fields (efx, spec, inbuf); } -MCDI_SET_DWORD (inbuf,FILTER_OP_IN_PORT_ID , efx->vport_id); +if (flags &EFX_FILTER_FLAG_VPORT_ID ) +MCDI_SET_DWORD (inbuf,FILTER_OP_IN_PORT_ID , spec->vport_id); +else +MCDI_SET_DWORD (inbuf,FILTER_OP_IN_PORT_ID , efx->vport_id); MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST, spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ? MC_CMD_FILTER_OP_IN_RX_DEST_DROP :
@@ -488,6 +491,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx, saved_spec->flags |= spec->flags; saved_spec->rss_context = spec->rss_context; saved_spec->dmaq_id = spec->dmaq_id; + saved_spec->vport_id = spec->vport_id; } }else if (!replacing) {kfree (saved_spec);
drivers/net/ethernet/sfc/tc.c +71 -2
109 lines not on this page · raw message
drivers/net/ethernet/sfc/tc.h +9 -0
@@ -49,12 +49,18 @@ enum efx_tc_rule_prios {/** * struct efx_tc_state - control plane data for TC offload * +* @reps_mport_id: MAE port allocated for representor RX +* @reps_filter_uc: VNIC filter for representor unicast RX (promisc) +* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) +* @reps_mport_vport_id: vport_id for representor RX filters * @dflt: Match-action rules for default switching; at priority * %EFX_TC_PRIO_DFLT. Named by *ingress* port * @dflt.pf: rule for traffic ingressing from PF (egresses to wire) * @dflt.wire: rule for traffic ingressing from wire (egresses to PF) */ struct efx_tc_state { +u32 reps_mport_id, reps_mport_vport_id; +s32 reps_filter_uc, reps_filter_mc;struct {struct efx_tc_flow_rule pf;struct efx_tc_flow_rule wire;
@@ -67,6 +73,9 @@ int efx_tc_configure_default_rule_rep(struct efx_rep *efv);void efx_tc_deconfigure_default_rule (struct efx_nic *efx,struct efx_tc_flow_rule *rule); +int efx_tc_insert_rep_filters (struct efx_nic *efx); +void efx_tc_remove_rep_filters (struct efx_nic *efx); +int efx_init_tc (struct efx_nic *efx);void efx_fini_tc (struct efx_nic *efx);
PATCH 10/14 sfc: look up VF's client ID when creating representor
In reply to [email protected]From: Edward Cree <[email protected]>
Firmware gives us a handle which we will later use to administrate the
VF's virtual MAC configuration.
--- drivers/net/ethernet/sfc/ef100_nic.c | 23 +++++++++++++++++++++++ drivers/net/ethernet/sfc/ef100_nic.h | 1 + drivers/net/ethernet/sfc/ef100_rep.c | 17 +++++++++++++++++ drivers/net/ethernet/sfc/ef100_rep.h | 2 ++ 4 files changed, 43 insertions(+)
drivers/net/ethernet/sfc/ef100_nic.c +23 -0
@@ -1092,6 +1092,29 @@ static int ef100_probe_main(struct efx_nic *efx)return rc; } +int efx_ef100_lookup_client_id (struct efx_nic *efx,efx_qword_t pciefn,u32 *id) +{ +MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_CLIENT_HANDLE_OUT_LEN ); +MCDI_DECLARE_BUF (inbuf,MC_CMD_GET_CLIENT_HANDLE_IN_LEN ); +u64 pciefn_flat =le64_to_cpu (pciefn.u64[0 ]); +size_t outlen; +int rc; + +MCDI_SET_DWORD (inbuf,GET_CLIENT_HANDLE_IN_TYPE , +MC_CMD_GET_CLIENT_HANDLE_IN_TYPE_FUNC ); +MCDI_SET_QWORD (inbuf,GET_CLIENT_HANDLE_IN_FUNC , + pciefn_flat); + + rc =efx_mcdi_rpc (efx,MC_CMD_GET_CLIENT_HANDLE , inbuf, +sizeof (inbuf), outbuf,sizeof (outbuf), &outlen); +if (rc) +return rc; +if (outlen <sizeof (outbuf)) +return -EIO ; + *id =MCDI_DWORD (outbuf,GET_CLIENT_HANDLE_OUT_HANDLE ); +return 0 ; +} +int ef100_probe_netdev_pf (struct efx_nic *efx) {struct ef100_nic_data *nic_data = efx->nic_data;
drivers/net/ethernet/sfc/ef100_nic.h +1 -0
@@ -17,6 +17,7 @@extern const struct efx_nic_type ef100_pf_nic_type;extern const struct efx_nic_type ef100_vf_nic_type; +int efx_ef100_lookup_client_id (struct efx_nic *efx,efx_qword_t pciefn,u32 *id);int ef100_probe_netdev_pf (struct efx_nic *efx);int ef100_probe_vf (struct efx_nic *efx);void ef100_remove (struct efx_nic *efx);
drivers/net/ethernet/sfc/ef100_rep.c +17 -0
@@ -200,6 +200,7 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,static int efx_ef100_configure_rep (struct efx_rep *efv) {struct efx_nic *efx = efv->parent; +efx_qword_t pciefn;u32 selector;int rc;
@@ -214,6 +215,22 @@ static int efx_ef100_configure_rep(struct efx_rep *efv)/* mport label should fit in 16 bits */ WARN_ON (efv->mport >>16 ); +/* Construct PCIE_FUNCTION structure for the representee */ +EFX_POPULATE_QWORD_3 (pciefn, +PCIE_FUNCTION_PF ,PCIE_FUNCTION_PF_NULL , +PCIE_FUNCTION_VF , efv->idx, +PCIE_FUNCTION_INTF ,PCIE_INTERFACE_CALLER ); +/* look up representee's client ID */ + rc =efx_ef100_lookup_client_id (efx, pciefn, &efv->clid); +if (rc) { + efv->clid =CLIENT_HANDLE_NULL ; +pci_dbg (efx->pci_dev,"Failed to get VF %u client ID, rc %d\n" , + efv->idx, rc); + }else { +pci_dbg (efx->pci_dev,"VF %u client ID %#x\n" , + efv->idx, efv->clid); + } +return efx_tc_configure_default_rule_rep (efv); }
drivers/net/ethernet/sfc/ef100_rep.h +2 -0
@@ -29,6 +29,7 @@ struct efx_rep_sw_stats {* @net_dev: representor netdevice * @msg_enable: log message enable flags * @mport: m-port ID of corresponding VF +* @clid: client ID of corresponding VF * @idx: VF index * @write_index: number of packets enqueued to @rx_list * @read_index: number of packets consumed from @rx_list
@@ -45,6 +46,7 @@ struct efx_rep {struct net_device *net_dev;u32 msg_enable;u32 mport; +u32 clid;unsigned int idx;unsigned int write_index, read_index;unsigned int rx_pring_size;
PATCH 11/14 sfc: fetch existing assigned MAC address from FW when creating VF rep
In reply to [email protected]From: Edward Cree <[email protected]>
For the sake of code commonality, this changes the PF probe path to also
use MC_CMD_GET_CLIENT_MAC_ADDRESSES instead of the old MC_CMD_GET_MAC_ADDRESSES.
--- drivers/net/ethernet/sfc/ef100_nic.c | 32 +++++++++++++++++++--------- drivers/net/ethernet/sfc/ef100_nic.h | 2 ++ drivers/net/ethernet/sfc/ef100_rep.c | 6 ++++++ 3 files changed, 30 insertions(+), 10 deletions(-)
drivers/net/ethernet/sfc/ef100_nic.c +22 -10
@@ -130,23 +130,34 @@ static void ef100_mcdi_reboot_detected(struct efx_nic *efx)/* MCDI calls */ -static int ef100_get_mac_address (struct efx_nic *efx,u8 *mac_address) +int ef100_get_mac_address (struct efx_nic *efx,u8 *mac_address, +int client_handle,bool empty_ok) { -MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_MAC_ADDRESSES_OUT_LEN ); +MCDI_DECLARE_BUF (outbuf,MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN (1 )); +MCDI_DECLARE_BUF (inbuf,MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN );size_t outlen;int rc; -BUILD_BUG_ON (MC_CMD_GET_MAC_ADDRESSES_IN_LEN !=0 ); +MCDI_SET_DWORD (inbuf,GET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE , + client_handle); - rc =efx_mcdi_rpc (efx,MC_CMD_GET_MAC_ADDRESSES ,NULL ,0 , - outbuf,sizeof (outbuf), &outlen); + rc =efx_mcdi_rpc (efx,MC_CMD_GET_CLIENT_MAC_ADDRESSES , inbuf, +sizeof (inbuf), outbuf,sizeof (outbuf), &outlen);if (rc)return rc; -if (outlen <MC_CMD_GET_MAC_ADDRESSES_OUT_LEN ) -return -EIO ; -ether_addr_copy (mac_address, -MCDI_PTR (outbuf,GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE )); +if (outlen >=MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN (1 )) { +ether_addr_copy (mac_address, +MCDI_PTR (outbuf, +GET_CLIENT_MAC_ADDRESSES_OUT_MAC_ADDRS )); + }else if (empty_ok) { +pci_warn (efx->pci_dev, +"No MAC address provisioned for client ID %#x.\n" , + client_handle); +eth_zero_addr (mac_address); + }else { +return -ENOENT ; + }return 0 ; }
@@ -1121,7 +1132,8 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)struct net_device *net_dev = efx->net_dev;int rc; - rc =ef100_get_mac_address (efx, net_dev->perm_addr); + rc =ef100_get_mac_address (efx, net_dev->perm_addr,CLIENT_HANDLE_SELF , + false);if (rc) goto fail;/* Assign MAC address */
drivers/net/ethernet/sfc/ef100_nic.h +2 -0
@@ -17,6 +17,8 @@extern const struct efx_nic_type ef100_pf_nic_type;extern const struct efx_nic_type ef100_vf_nic_type; +int ef100_get_mac_address (struct efx_nic *efx,u8 *mac_address, +int client_handle,bool empty_ok);int efx_ef100_lookup_client_id (struct efx_nic *efx,efx_qword_t pciefn,u32 *id);int ef100_probe_netdev_pf (struct efx_nic *efx);int ef100_probe_vf (struct efx_nic *efx);
drivers/net/ethernet/sfc/ef100_rep.c +6 -0
@@ -199,6 +199,7 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,static int efx_ef100_configure_rep (struct efx_rep *efv) { +struct net_device *net_dev = efv->net_dev;struct efx_nic *efx = efv->parent;efx_qword_t pciefn;u32 selector;
@@ -229,6 +230,11 @@ static int efx_ef100_configure_rep(struct efx_rep *efv) }else {pci_dbg (efx->pci_dev,"VF %u client ID %#x\n" , efv->idx, efv->clid); + +/* Get the assigned MAC address */ + (void )ef100_get_mac_address (efx, net_dev->perm_addr, efv->clid, + true); +eth_hw_addr_set (net_dev, net_dev->perm_addr); }return efx_tc_configure_default_rule_rep (efv);
PATCH 12/14 sfc: set EF100 VF MAC address through representor
In reply to [email protected]From: Edward Cree <[email protected]>
When setting the VF rep's MAC address, set the provisioned MAC address
for the VF through MC_CMD_SET_CLIENT_MAC_ADDRESSES.
--- drivers/net/ethernet/sfc/ef100_rep.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +28 -0
@@ -107,6 +107,33 @@ static int efx_ef100_rep_get_phys_port_name(struct net_device *dev,return 0 ; } +static int efx_ef100_rep_set_mac_address (struct net_device *net_dev,void *data) +{ +MCDI_DECLARE_BUF (inbuf,MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN (1 )); +struct efx_rep *efv =netdev_priv (net_dev); +struct efx_nic *efx = efv->parent; +struct sockaddr *addr = data; +const u8 *new_addr = addr->sa_data; +int rc; + +if (efv->clid ==CLIENT_HANDLE_NULL ) { +netif_info (efx, drv, net_dev,"Unable to set representee MAC address (client ID is null)\n" ); + }else { +BUILD_BUG_ON (MC_CMD_SET_CLIENT_MAC_ADDRESSES_OUT_LEN ); +MCDI_SET_DWORD (inbuf,SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE , + efv->clid); +ether_addr_copy (MCDI_PTR (inbuf,SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS ), + new_addr); + rc =efx_mcdi_rpc (efx,MC_CMD_SET_CLIENT_MAC_ADDRESSES , inbuf, +sizeof (inbuf),NULL ,0 ,NULL ); +if (rc) +return rc; + } + +eth_hw_addr_set (net_dev, new_addr); +return 0 ; +} +static void efx_ef100_rep_get_stats64 (struct net_device *dev,struct rtnl_link_stats64 *stats) {
@@ -126,6 +153,7 @@ 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, + .ndo_set_mac_address = efx_ef100_rep_set_mac_address, .ndo_get_stats64 = efx_ef100_rep_get_stats64, };
PATCH 13/14 sfc: get provisioned MAC address on EF100 VF probe
In reply to [email protected]From: Edward Cree <[email protected]>
Move the implementation from the PF-specific probe path to that part
which is common to both PFs and VFs.
--- drivers/net/ethernet/sfc/ef100_netdev.c | 10 ++++++++++ drivers/net/ethernet/sfc/ef100_nic.c | 11 ----------- 2 files changed, 10 insertions(+), 11 deletions(-)
drivers/net/ethernet/sfc/ef100_netdev.c +10 -0
@@ -347,6 +347,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) {struct efx_nic *efx = &probe_data->efx;struct efx_probe_data **probe_ptr; +struct ef100_nic_data *nic_data;struct net_device *net_dev;int rc;
@@ -398,6 +399,15 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)/* Don't fail init if RSS setup doesn't work. */ efx_mcdi_push_default_indir_table (efx, efx->n_rx_channels); + rc =ef100_get_mac_address (efx, net_dev->perm_addr,CLIENT_HANDLE_SELF , + efx->type->is_vf); +if (rc) + goto fail; +/* Assign MAC address */ +eth_hw_addr_set (net_dev, net_dev->perm_addr); + nic_data = efx->nic_data; +memcpy (nic_data->port_id, net_dev->perm_addr,ETH_ALEN ); + rc =ef100_register_netdev (efx);if (rc) goto fail;
drivers/net/ethernet/sfc/ef100_nic.c +0 -11
@@ -1132,14 +1132,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)struct net_device *net_dev = efx->net_dev;int rc; - rc =ef100_get_mac_address (efx, net_dev->perm_addr,CLIENT_HANDLE_SELF , - false); -if (rc) - goto fail; -/* Assign MAC address */ -eth_hw_addr_set (net_dev, net_dev->perm_addr); -memcpy (nic_data->port_id, net_dev->perm_addr,ETH_ALEN ); -if (!nic_data->grp_mae)return 0 ;
@@ -1168,9 +1160,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx) }return 0 ; - -fail: -return rc; }int ef100_probe_vf (struct efx_nic *efx)
PATCH 14/14 sfc: implement ethtool get/set RX ring size for EF100 reps
In reply to [email protected]From: Edward Cree <[email protected]>
It's not truly a ring, but the maximum length of the list of queued RX
SKBs is analogous to an RX ring size, so use that API to configure it.
--- drivers/net/ethernet/sfc/ef100_rep.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
drivers/net/ethernet/sfc/ef100_rep.c +27 -0
@@ -178,10 +178,37 @@ static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, efv->msg_enable = msg_enable; } +static void efx_ef100_rep_ethtool_get_ringparam (struct net_device *net_dev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kring, +struct netlink_ext_ack *ext_ack) +{ +struct efx_rep *efv =netdev_priv (net_dev); + + ring->rx_max_pending =U32_MAX ; + ring->rx_pending = efv->rx_pring_size; +} + +static int efx_ef100_rep_ethtool_set_ringparam (struct net_device *net_dev, +struct ethtool_ringparam *ring, +struct kernel_ethtool_ringparam *kring, +struct netlink_ext_ack *ext_ack) +{ +struct efx_rep *efv =netdev_priv (net_dev); + +if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->tx_pending) +return -EINVAL ; + + efv->rx_pring_size = ring->rx_pending; +return 0 ; +} +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, + .get_ringparam = efx_ef100_rep_ethtool_get_ringparam, + .set_ringparam = efx_ef100_rep_ethtool_set_ringparam, }; static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,