From: Saeed Mahameed <saeedm@nvidia.com>
Hi Dave, Jakub, Jason,
This series form Parav was the theme of this mlx5 release cycle,
we've been waiting anxiously for the auxbus infrastructure to make it into
the kernel, and now as the auxbus is in and all the stars are aligned, I
can finally submit this patchset of the devlink and mlx5 subfunction support.
For more detailed information about subfunctions please see detailed tag
log below.
Please pull and let me know if there's any problem.
Thanks,
Saeed.
---
Changelog:
v9->v10:
- Remove redundant statement from patch #4 commit message
- Minor grammar improvement in SF documentation patch
v8->v9:
- Use proper functions doc in patches #3,#4
v7->v8:
- Address documentation related comments missed on v5, Jakub.
v6-v7:
- Resolve new kdoc warning
v5->v6:
- update docs and corrected spellings and typos according to previous
review
- use of shorted macro names
- using updated callback to return port index
- updated commit message example for add command return fields
- driver name suffix corrected from 'mlx5_core' to 'sf'
- using MLX5_ADEV_NAME prefix to match with other mlx5 auxiliary devices
- fixed sf allocated condition
- using 80 characters alignment
- shorten the enum type names and enum values from
PORT_FUNCTION to PORT_FN
- return port attributes of newly created port
- moved port add and delete callbacks pointer check before preparing
attributes for driver
- added comment to clarify that about desired port index during add
callback
- place SF number attribute only when port flavour is SF
- packed the sf attribute structure
- removed external flag for sf for initial patchset
v4->v5:
- Fix some typos in the documentation
v3->v4:
- Fix 32bit compilation issue
v2->v3:
- added header file sf/priv.h to cmd.c to avoid missing prototype warning
- made mlx5_sf_table_disable as static function as its used only in one file
v1->v2:
- added documentation for subfunction and its mlx5 implementation
- add MLX5_SF config option documentation
- rebased
- dropped devlink global lock improvement patch as mlx5 doesn't support
reload while SFs are allocated
- dropped devlink reload lock patch as mlx5 doesn't support reload
when SFs are allocated
- using updated vhca event from device to add remove auxiliary device
- split sf devlink port allocation and sf hardware context allocation
Thanks,
Saeed.
---
The following changes since commit 7b8fc0103bb51d1d3e1fb5fd67958612e709f883:
bonding: add a vlan+srcmac tx hashing option (2021-01-19 19:30:32 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-updates-2021-01-13
for you to fetch changes up to 142d93d12dc187f6a32aae2048da0c8230636b86:
net/mlx5: Add devlink subfunction port documentation (2021-01-22 11:32:12 -0800)
----------------------------------------------------------------
mlx5 subfunction support
Parav Pandit Says:
=================
This patchset introduces support for mlx5 subfunction (SF).
A subfunction is a lightweight function that has a parent PCI function on
which it is deployed. mlx5 subfunction has its own function capabilities
and its own resources. This means a subfunction has its own dedicated
queues(txq, rxq, cq, eq). These queues are neither shared nor stolen from
the parent PCI function.
When subfunction is RDMA capable, it has its own QP1, GID table and rdma
resources neither shared nor stolen from the parent PCI function.
A subfunction has dedicated window in PCI BAR space that is not shared
with the other subfunctions or parent PCI function. This ensures that all
class devices of the subfunction accesses only assigned PCI BAR space.
A Subfunction supports eswitch representation through which it supports tc
offloads. User must configure eswitch to send/receive packets from/to
subfunction port.
Subfunctions share PCI level resources such as PCI MSI-X IRQs with
their other subfunctions and/or with its parent PCI function.
Patch summary:
--------------
Patch 1 to 4 prepares devlink
patch 5 to 7 mlx5 adds SF device support
Patch 8 to 11 mlx5 adds SF devlink port support
Patch 12 and 14 adds documentation
Patch-1 prepares code to handle multiple port function attributes
Patch-2 introduces devlink pcisf port flavour similar to pcipf and pcivf
Patch-3 adds port add and delete driver callbacks
Patch-4 adds port function state get and set callbacks
Patch-5 mlx5 vhca event notifier support to distribute subfunction
state change notification
Patch-6 adds SF auxiliary device
Patch-7 adds SF auxiliary driver
Patch-8 prepares eswitch to handler SF vport
Patch-9 adds eswitch helpers to add/remove SF vport
Patch-10 implements devlink port add/del callbacks
Patch-11 implements devlink port function get/set callbacks
Patch-12 to 14 adds documentation
Patch-12 added mlx5 port function documentation
Patch-13 adds subfunction documentation
Patch-14 adds mlx5 subfunction documentation
Subfunction support is discussed in detail in RFC [1] and [2].
RFC [1] and extension [2] describes requirements, design and proposed
plumbing using devlink, auxiliary bus and sysfs for systemd/udev
support. Functionality of this patchset is best explained using real
examples further below.
overview:
--------
A subfunction can be created and deleted by a user using devlink port
add/delete interface.
A subfunction can be configured using devlink port function attribute
before its activated.
When a subfunction is activated, it results in an auxiliary device on
the host PCI device where it is deployed. A driver binds to the
auxiliary device that further creates supported class devices.
example subfunction usage sequence:
-----------------------------------
Change device to switchdev mode:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
Add a devlink port of subfunction flavour:
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
Configure mac address of the port function:
$ devlink port function set ens2f0npf0sf88 hw_addr 00:00:00:00:88:88
Now activate the function:
$ devlink port function set ens2f0npf0sf88 state active
Now use the auxiliary device and class devices:
$ devlink dev show
pci/0000:06:00.0
auxiliary/mlx5_core.sf.4
$ ip link show
127: ens2f0np0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 24:8a:07:b3:d1:12 brd ff:ff:ff:ff:ff:ff
altname enp6s0f0np0
129: p0sf88: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:88:88 brd ff:ff:ff:ff:ff:ff
$ rdma dev show
43: rdmap6s0f0: node_type ca fw 16.29.0550 node_guid 248a:0703:00b3:d112 sys_image_guid 248a:0703:00b3:d112
44: mlx5_0: node_type ca fw 16.29.0550 node_guid 0000:00ff:fe00:8888 sys_image_guid 248a:0703:00b3:d112
After use inactivate the function:
$ devlink port function set ens2f0npf0sf88 state inactive
Now delete the subfunction port:
$ devlink port del ens2f0npf0sf88
[1] https://lore.kernel.org/netdev/20200519092258.GF4655@nanopsycho/
[2] https://marc.info/?l=linux-netdev&m=158555928517777&w=2
=================
----------------------------------------------------------------
Parav Pandit (13):
devlink: Prepare code to fill multiple port function attributes
devlink: Introduce PCI SF port flavour and port attribute
devlink: Support add and delete devlink port
devlink: Support get and set state of port function
net/mlx5: Introduce vhca state event notifier
net/mlx5: SF, Add auxiliary device support
net/mlx5: SF, Add auxiliary device driver
net/mlx5: E-switch, Add eswitch helpers for SF vport
net/mlx5: SF, Add port add delete functionality
net/mlx5: SF, Port function state change support
devlink: Add devlink port documentation
devlink: Extend devlink port documentation for subfunctions
net/mlx5: Add devlink subfunction port documentation
Vu Pham (1):
net/mlx5: E-switch, Prepare eswitch to handle SF vport
Documentation/driver-api/auxiliary_bus.rst | 2 +
.../device_drivers/ethernet/mellanox/mlx5.rst | 215 ++++++++
Documentation/networking/devlink/devlink-port.rst | 199 ++++++++
Documentation/networking/devlink/index.rst | 1 +
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 19 +
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 9 +
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 8 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 19 +
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 5 +-
.../mellanox/mlx5/core/esw/acl/egress_ofld.c | 2 +-
.../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 41 ++
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 48 +-
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 78 +++
.../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 47 +-
drivers/net/ethernet/mellanox/mlx5/core/events.c | 7 +
drivers/net/ethernet/mellanox/mlx5/core/main.c | 60 ++-
.../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 12 +
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 20 +
drivers/net/ethernet/mellanox/mlx5/core/sf/cmd.c | 49 ++
.../net/ethernet/mellanox/mlx5/core/sf/dev/dev.c | 275 ++++++++++
.../net/ethernet/mellanox/mlx5/core/sf/dev/dev.h | 55 ++
.../ethernet/mellanox/mlx5/core/sf/dev/driver.c | 101 ++++
.../net/ethernet/mellanox/mlx5/core/sf/devlink.c | 556 +++++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/sf/hw_table.c | 233 +++++++++
.../mellanox/mlx5/core/sf/mlx5_ifc_vhca_event.h | 82 +++
drivers/net/ethernet/mellanox/mlx5/core/sf/priv.h | 21 +
drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h | 100 ++++
.../ethernet/mellanox/mlx5/core/sf/vhca_event.c | 189 +++++++
.../ethernet/mellanox/mlx5/core/sf/vhca_event.h | 57 +++
drivers/net/ethernet/mellanox/mlx5/core/vport.c | 3 +-
include/linux/mlx5/driver.h | 16 +-
include/net/devlink.h | 100 ++++
include/uapi/linux/devlink.h | 25 +
net/core/devlink.c | 310 ++++++++++--
34 files changed, 2917 insertions(+), 47 deletions(-)
create mode 100644 Documentation/networking/devlink/devlink-port.rst
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/cmd.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/mlx5_ifc_vhca_event.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/priv.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.h
@@ -34,6 +34,9 @@ Devlink port flavours are described below.* - ``DEVLINK_PORT_FLAVOUR_PCI_VF``- This indicates an eswitch port representing a port of PCI virtual function (VF).+* - ``DEVLINK_PORT_FLAVOUR_PCI_SF``+- This indicates an eswitch port representing a port of PCI+ subfunction (SF).* - ``DEVLINK_PORT_FLAVOUR_VIRTUAL``- This indicates a virtual port for the PCI virtual function.
@@ -57,8 +60,9 @@ Devlink port can have a different type based on the link layer described below. PCI controllers --------------- In most cases a PCI device has only one controller. A controller consists of-potentially multiple physical and virtual functions. A function consists-of one or more ports. This port is represented by the devlink eswitch port.+potentially multiple physical, virtual functions and subfunctions. A function+consists of one or more ports. This port is represented by the devlink eswitch+port. A PCI device connected to multiple CPUs or multiple PCI root complexes or a SmartNIC, however, may have multiple controllers. For a device with multiple
@@ -111,8 +115,85 @@ function. Usually it means, user should configure function attribute before a bus specific device for the function is created. However, when SRIOV is enabled, virtual function devices are created on the PCI bus. Hence, function attribute should be configured before binding virtual-function device to the driver.+function device to the driver. For subfunctions, this means user should+configure port function attribute before activating the port function. A user may set the hardware address of the function using 'devlink port function set hw_addr' command. For Ethernet port function this means a MAC address.++Subfunction+============++Subfunction is a lightweight function that has a parent PCI function on which+it is deployed. Subfunction is created and deployed in unit of 1. Unlike+SRIOV VFs, a subfunction doesn't require its own PCI virtual function.+A subfunction communicates with the hardware through the parent PCI function.++To use a subfunction, 3 steps setup sequence is followed.+(1) create - create a subfunction;+(2) configure - configure subfunction attributes;+(3) deploy - deploy the subfunction;++Subfunction management is done using devlink port user interface.+User performs setup on the subfunction management device.++(1) Create+----------+A subfunction is created using a devlink port interface. A user adds the+subfunction by adding a devlink port of subfunction flavour. The devlink+kernel code calls down to subfunction management driver (devlink ops) and asks+it to create a subfunction devlink port. Driver then instantiates the+subfunction port and any associated objects such as health reporters and+representor netdevice.++(2) Configure+-------------+A subfunction devlink port is created but it is not active yet. That means the+entities are created on devlink side, the e-switch port representor is created,+but the subfunction device itself it not created. A user might use e-switch port+representor to do settings, putting it into bridge, adding TC rules, etc. A user+might as well configure the hardware address (such as MAC address) of the+subfunction while subfunction is inactive.++(3) Deploy+----------+Once a subfunction is configured, user must activate it to use it. Upon+activation, subfunction management driver asks the subfunction management+device to instantiate the subfunction device on particular PCI function.+A subfunction device is created on the :ref:`Documentation/driver-api/auxiliary_bus.rst <auxiliary_bus>`.+At this point a matching subfunction driver binds to the subfunction's auxiliary device.++Terms and Definitions+=====================++..list-table:: Terms and Definitions+:widths: 22 90++* - Term+- Definitions+* - ``PCI device``+- A physical PCI device having one or more PCI bus consists of one or+ more PCI controllers.+* - ``PCI controller``+- A controller consists of potentially multiple physical functions,+ virtual functions and subfunctions.+* - ``Port function``+- An object to manage the function of a port.+* - ``Subfunction``+- A lightweight function that has parent PCI function on which it is+ deployed.+* - ``Subfunction device``+- A bus device of the subfunction, usually on a auxiliary bus.+* - ``Subfunction driver``+- A device driver for the subfunction auxiliary device.+* - ``Subfunction management device``+- A PCI physical function that supports subfunction management.+* - ``Subfunction management driver``+- A device driver for PCI physical function that supports+ subfunction management using devlink port interface.+* - ``Subfunction host driver``+- A device driver for PCI physical function that hosts subfunction+ devices. In most cases it is same as subfunction management driver. When+ subfunction is used on external controller, subfunction management and+ host drivers are different.
From: Parav Pandit <redacted>
Add auxiliary device driver for mlx5 subfunction auxiliary device.
A mlx5 subfunction is similar to PCI PF and VF. For a subfunction
an auxiliary device is created.
As a result, when mlx5 SF auxiliary device binds to the driver,
its netdev and rdma device are created, they appear as
$ ls -l /sys/bus/auxiliary/devices/
mlx5_core.sf.4 -> ../../../devices/pci0000:00/0000:00:03.0/0000:06:00.0/mlx5_core.sf.4
$ ls -l /sys/class/net/eth1/device
/sys/class/net/eth1/device -> ../../../mlx5_core.sf.4
$ cat /sys/bus/auxiliary/devices/mlx5_core.sf.4/sfnum
88
$ devlink dev show
pci/0000:06:00.0
auxiliary/mlx5_core.sf.4
$ devlink port show auxiliary/mlx5_core.sf.4/1
auxiliary/mlx5_core.sf.4/1: type eth netdev p0sf88 flavour virtual port 0 splittable false
$ rdma link show mlx5_0/1
link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev p0sf88
$ rdma dev show
8: rocep6s0f1: node_type ca fw 16.29.0550 node_guid 248a:0703:00b3:d113 sys_image_guid 248a:0703:00b3:d112
13: mlx5_0: node_type ca fw 16.29.0550 node_guid 0000:00ff:fe00:8888 sys_image_guid 248a:0703:00b3:d112
In future, devlink device instance name will adapt to have sfnum
annotation using either an alias or as devlink instance name described
in RFC [1].
[1] https://lore.kernel.org/netdev/20200519092258.GF4655@nanopsycho/
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
.../net/ethernet/mellanox/mlx5/core/devlink.c | 12 +++
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/main.c | 12 ++-
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 10 ++
.../net/ethernet/mellanox/mlx5/core/pci_irq.c | 20 ++++
.../ethernet/mellanox/mlx5/core/sf/dev/dev.c | 10 ++
.../ethernet/mellanox/mlx5/core/sf/dev/dev.h | 20 ++++
.../mellanox/mlx5/core/sf/dev/driver.c | 101 ++++++++++++++++++
include/linux/mlx5/driver.h | 4 +-
10 files changed, 187 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
@@ -127,6 +128,17 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,structnetlink_ext_ack*extack){structmlx5_core_dev*dev=devlink_priv(devlink);+boolsf_dev_allocated;++sf_dev_allocated=mlx5_sf_dev_allocated(dev);+if(sf_dev_allocated){+/* Reload results in deleting SF device which further results in+*unregisteringdevlinkinstancewhileholdingdevlink_mutext.+*Hence,donotsupportreload.+*/+NL_SET_ERR_MSG_MOD(extack,"reload is unsupported when SFs are allocated\n");+return-EOPNOTSUPP;+}switch(action){caseDEVLINK_RELOAD_ACTION_DRIVER_REINIT:
@@ -30,6 +30,9 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev){structmlx5_irq_table*irq_table;+if(mlx5_core_is_sf(dev))+return0;+irq_table=kvzalloc(sizeof(*irq_table),GFP_KERNEL);if(!irq_table)return-ENOMEM;
@@ -40,6 +43,9 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev)voidmlx5_irq_table_cleanup(structmlx5_core_dev*dev){+if(mlx5_core_is_sf(dev))+return;+kvfree(dev->priv.irq_table);}
@@ -268,6 +274,9 @@ int mlx5_irq_table_create(struct mlx5_core_dev *dev)intnvec;interr;+if(mlx5_core_is_sf(dev))+return0;+nvec=MLX5_CAP_GEN(dev,num_ports)*num_online_cpus()+MLX5_IRQ_VEC_COMP_BASE;nvec=min_t(int,nvec,num_eqs);
@@ -319,6 +328,9 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev)structmlx5_irq_table*table=dev->priv.irq_table;inti;+if(mlx5_core_is_sf(dev))+return;+/* free_irq requires that affinity and rmap will be cleared*beforecallingit.Thisiswhythereisasymmetrywithset_rmap*whichshouldbecalledafteralloc_irqbutbeforerequest_irq.
From: Parav Pandit <redacted>
Support changing the state of the SF port's function through devlink.
When activating the SF port's function, enable the hca in the device
followed by adding its auxiliary device.
When deactivating the SF port's function, delete its auxiliary device
followed by disabling the vHCA.
Port function attributes get/set callbacks are invoked with devlink
instance lock held. Such callbacks need to synchronize with sf port
table getting disabled either via sriov sysfs callback. Such callbacks
synchronize with table disable context holding table refcount.
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show ens2f0npf0sf88
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:88:88 state inactive opstate detached
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active
$ devlink port show ens2f0npf0sf88 -jp
{
"port": {
"pci/0000:06:00.0/32768": {
"type": "eth",
"netdev": "ens2f0npf0sf88",
"flavour": "pcisf",
"controller": 0,
"pfnum": 0,
"sfnum": 88,
"external": false,
"splittable": false,
"function": {
"hw_addr": "00:00:00:00:88:88",
"state": "active",
"opstate": "attached"
}
}
}
}
On port function activation, an auxiliary device is created in below
example.
$ devlink dev show
devlink dev show auxiliary/mlx5_core.sf.4
$ devlink port show auxiliary/mlx5_core.sf.4/1
auxiliary/mlx5_core.sf.4/1: type eth netdev p0sf88 flavour virtual port 0 splittable false
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/devlink.c | 2 +
.../net/ethernet/mellanox/mlx5/core/main.c | 10 +
.../net/ethernet/mellanox/mlx5/core/sf/cmd.c | 22 ++
.../ethernet/mellanox/mlx5/core/sf/devlink.c | 284 ++++++++++++++++--
.../ethernet/mellanox/mlx5/core/sf/hw_table.c | 116 ++++++-
.../net/ethernet/mellanox/mlx5/core/sf/priv.h | 4 +
.../net/ethernet/mellanox/mlx5/core/sf/sf.h | 20 +-
7 files changed, 431 insertions(+), 27 deletions(-)
@@ -16,7 +22,10 @@ struct mlx5_sf_table {structxarrayport_indices;/* port index based lookup. */refcount_trefcount;structcompletiondisable_complete;+structmutexsf_state_lock;/* Serializes sf state among user cmds & vhca event handler. */structnotifier_blockesw_nb;+structnotifier_blockvhca_nb;+u8ecpu:1;};staticstructmlx5_sf*
@@ -25,6 +34,19 @@ mlx5_sf_lookup_by_index(struct mlx5_sf_table *table, unsigned int port_index)returnxa_load(&table->port_indices,port_index);}+staticstructmlx5_sf*+mlx5_sf_lookup_by_function_id(structmlx5_sf_table*table,unsignedintfn_id)+{+unsignedlongindex;+structmlx5_sf*sf;++xa_for_each(&table->port_indices,index,sf){+if(sf->hw_fn_id==fn_id)+returnsf;+}+returnNULL;+}+staticintmlx5_sf_id_insert(structmlx5_sf_table*table,structmlx5_sf*sf){returnxa_insert(&table->port_indices,sf->port_index,sf,GFP_KERNEL);
@@ -99,6 +123,146 @@ static void mlx5_sf_table_put(struct mlx5_sf_table *table)complete(&table->disable_complete);}+staticenumdevlink_port_fn_statemlx5_sf_to_devlink_state(u8hw_state)+{+switch(hw_state){+caseMLX5_VHCA_STATE_ACTIVE:+caseMLX5_VHCA_STATE_IN_USE:+caseMLX5_VHCA_STATE_TEARDOWN_REQUEST:+returnDEVLINK_PORT_FN_STATE_ACTIVE;+caseMLX5_VHCA_STATE_INVALID:+caseMLX5_VHCA_STATE_ALLOCATED:+default:+returnDEVLINK_PORT_FN_STATE_INACTIVE;+}+}++staticenumdevlink_port_fn_opstatemlx5_sf_to_devlink_opstate(u8hw_state)+{+switch(hw_state){+caseMLX5_VHCA_STATE_IN_USE:+caseMLX5_VHCA_STATE_TEARDOWN_REQUEST:+returnDEVLINK_PORT_FN_OPSTATE_ATTACHED;+caseMLX5_VHCA_STATE_INVALID:+caseMLX5_VHCA_STATE_ALLOCATED:+caseMLX5_VHCA_STATE_ACTIVE:+default:+returnDEVLINK_PORT_FN_OPSTATE_DETACHED;+}+}++staticboolmlx5_sf_is_active(conststructmlx5_sf*sf)+{+returnsf->hw_state==MLX5_VHCA_STATE_ACTIVE||sf->hw_state==MLX5_VHCA_STATE_IN_USE;+}++intmlx5_devlink_sf_port_fn_state_get(structdevlink*devlink,structdevlink_port*dl_port,+enumdevlink_port_fn_state*state,+enumdevlink_port_fn_opstate*opstate,+structnetlink_ext_ack*extack)+{+structmlx5_core_dev*dev=devlink_priv(devlink);+structmlx5_sf_table*table;+structmlx5_sf*sf;+interr=0;++table=mlx5_sf_table_try_get(dev);+if(!table)+return-EOPNOTSUPP;++sf=mlx5_sf_lookup_by_index(table,dl_port->index);+if(!sf){+err=-EOPNOTSUPP;+gotosf_err;+}+mutex_lock(&table->sf_state_lock);+*state=mlx5_sf_to_devlink_state(sf->hw_state);+*opstate=mlx5_sf_to_devlink_opstate(sf->hw_state);+mutex_unlock(&table->sf_state_lock);+sf_err:+mlx5_sf_table_put(table);+returnerr;+}++staticintmlx5_sf_activate(structmlx5_core_dev*dev,structmlx5_sf*sf)+{+interr;++if(mlx5_sf_is_active(sf))+return0;+if(sf->hw_state!=MLX5_VHCA_STATE_ALLOCATED)+return-EINVAL;++err=mlx5_cmd_sf_enable_hca(dev,sf->hw_fn_id);+if(err)+returnerr;++sf->hw_state=MLX5_VHCA_STATE_ACTIVE;+return0;+}++staticintmlx5_sf_deactivate(structmlx5_core_dev*dev,structmlx5_sf*sf)+{+interr;++if(!mlx5_sf_is_active(sf))+return0;++err=mlx5_cmd_sf_disable_hca(dev,sf->hw_fn_id);+if(err)+returnerr;++sf->hw_state=MLX5_VHCA_STATE_TEARDOWN_REQUEST;+return0;+}++staticintmlx5_sf_state_set(structmlx5_core_dev*dev,structmlx5_sf_table*table,+structmlx5_sf*sf,+enumdevlink_port_fn_statestate)+{+interr=0;++mutex_lock(&table->sf_state_lock);+if(state==mlx5_sf_to_devlink_state(sf->hw_state))+gotoout;+if(state==DEVLINK_PORT_FN_STATE_ACTIVE)+err=mlx5_sf_activate(dev,sf);+elseif(state==DEVLINK_PORT_FN_STATE_INACTIVE)+err=mlx5_sf_deactivate(dev,sf);+else+err=-EINVAL;+out:+mutex_unlock(&table->sf_state_lock);+returnerr;+}++intmlx5_devlink_sf_port_fn_state_set(structdevlink*devlink,structdevlink_port*dl_port,+enumdevlink_port_fn_statestate,+structnetlink_ext_ack*extack)+{+structmlx5_core_dev*dev=devlink_priv(devlink);+structmlx5_sf_table*table;+structmlx5_sf*sf;+interr;++table=mlx5_sf_table_try_get(dev);+if(!table){+NL_SET_ERR_MSG_MOD(extack,+"Port state set is only supported in eswitch switchdev mode or SF ports are disabled.");+return-EOPNOTSUPP;+}+sf=mlx5_sf_lookup_by_index(table,dl_port->index);+if(!sf){+err=-ENODEV;+gotoout;+}++err=mlx5_sf_state_set(dev,table,sf,state);+out:+mlx5_sf_table_put(table);+returnerr;+}+staticintmlx5_sf_add(structmlx5_core_dev*dev,structmlx5_sf_table*table,conststructdevlink_port_new_attrs*new_attr,structnetlink_ext_ack*extack,
@@ -188,10 +342,30 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink,returnerr;}+staticvoidmlx5_sf_dealloc(structmlx5_sf_table*table,structmlx5_sf*sf)+{+if(sf->hw_state==MLX5_VHCA_STATE_ALLOCATED){+mlx5_sf_free(table,sf);+}elseif(mlx5_sf_is_active(sf)){+/* Even if its active, it is treated as in_use because by the time,+*itisdisabledhere,itmaygettingused.Soitissafeto+*alwayslookfortheeventtoensurethatitisrecycledonlyafter+*firmwaregivesconfirmationthatitisdetachedbythedriver.+*/+mlx5_cmd_sf_disable_hca(table->dev,sf->hw_fn_id);+mlx5_sf_hw_table_sf_deferred_free(table->dev,sf->id);+kfree(sf);+}else{+mlx5_sf_hw_table_sf_deferred_free(table->dev,sf->id);+kfree(sf);+}+}+intmlx5_devlink_sf_port_del(structdevlink*devlink,unsignedintport_index,structnetlink_ext_ack*extack){structmlx5_core_dev*dev=devlink_priv(devlink);+structmlx5_eswitch*esw=dev->priv.eswitch;structmlx5_sf_table*table;structmlx5_sf*sf;interr=0;
@@ -208,20 +382,58 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,gotosf_err;}-mlx5_sf_del(dev,table,sf);+mlx5_esw_offloads_sf_vport_disable(esw,sf->hw_fn_id);+mlx5_sf_id_erase(table,sf);++mutex_lock(&table->sf_state_lock);+mlx5_sf_dealloc(table,sf);+mutex_unlock(&table->sf_state_lock);sf_err:mlx5_sf_table_put(table);returnerr;}-staticvoidmlx5_sf_destroy_all(structmlx5_sf_table*table)+staticboolmlx5_sf_state_update_check(conststructmlx5_sf*sf,u8new_state){-structmlx5_core_dev*dev=table->dev;-unsignedlongindex;+if(sf->hw_state==MLX5_VHCA_STATE_ACTIVE&&new_state==MLX5_VHCA_STATE_IN_USE)+returntrue;++if(sf->hw_state==MLX5_VHCA_STATE_IN_USE&&new_state==MLX5_VHCA_STATE_ACTIVE)+returntrue;++if(sf->hw_state==MLX5_VHCA_STATE_TEARDOWN_REQUEST&&+new_state==MLX5_VHCA_STATE_ALLOCATED)+returntrue;++returnfalse;+}++staticintmlx5_sf_vhca_event(structnotifier_block*nb,unsignedlongopcode,void*data)+{+structmlx5_sf_table*table=container_of(nb,structmlx5_sf_table,vhca_nb);+conststructmlx5_vhca_state_event*event=data;+boolupdate=false;structmlx5_sf*sf;-xa_for_each(&table->port_indices,index,sf)-mlx5_sf_del(dev,table,sf);+table=mlx5_sf_table_try_get(table->dev);+if(!table)+return0;++mutex_lock(&table->sf_state_lock);+sf=mlx5_sf_lookup_by_function_id(table,event->function_id);+if(!sf)+gotosf_err;++/* When driver is attached or detached to a function, an event+*notifiessuchstatechange.+*/+update=mlx5_sf_state_update_check(sf,event->new_vhca_state);+if(update)+sf->hw_state=event->new_vhca_state;+sf_err:+mutex_unlock(&table->sf_state_lock);+mlx5_sf_table_put(table);+return0;}staticvoidmlx5_sf_table_enable(structmlx5_sf_table*table)
@@ -233,6 +445,22 @@ static void mlx5_sf_table_enable(struct mlx5_sf_table *table)refcount_set(&table->refcount,1);}+staticvoidmlx5_sf_deactivate_all(structmlx5_sf_table*table)+{+structmlx5_eswitch*esw=table->dev->priv.eswitch;+unsignedlongindex;+structmlx5_sf*sf;++/* At this point, no new user commands can start and no vhca event can+*arrive.ItissafetodestroyallusercreatedSFs.+*/+xa_for_each(&table->port_indices,index,sf){+mlx5_esw_offloads_sf_vport_disable(esw,sf->hw_fn_id);+mlx5_sf_id_erase(table,sf);+mlx5_sf_dealloc(table,sf);+}+}+staticvoidmlx5_sf_table_disable(structmlx5_sf_table*table){if(!mlx5_sf_max_functions(table->dev))
@@ -241,14 +469,13 @@ static void mlx5_sf_table_disable(struct mlx5_sf_table *table)if(!refcount_read(&table->refcount))return;-/* Balances with refcount_set; drop the reference so that new user cmd cannot start. */+/* Balances with refcount_set; drop the reference so that new user cmd cannot start+*andnewvhcaeventhandlercannnotrun.+*/mlx5_sf_table_put(table);wait_for_completion(&table->disable_complete);-/* At this point, no new user commands can start.-*ItissafetodestroyallusercreatedSFs.-*/-mlx5_sf_destroy_all(table);+mlx5_sf_deactivate_all(table);}staticintmlx5_sf_esw_event(structnotifier_block*nb,unsignedlongevent,void*data)
@@ -280,23 +507,34 @@ int mlx5_sf_table_init(struct mlx5_core_dev *dev)structmlx5_sf_table*table;interr;-if(!mlx5_sf_table_supported(dev))+if(!mlx5_sf_table_supported(dev)||!mlx5_vhca_event_supported(dev))return0;table=kzalloc(sizeof(*table),GFP_KERNEL);if(!table)return-ENOMEM;+mutex_init(&table->sf_state_lock);table->dev=dev;xa_init(&table->port_indices);dev->priv.sf_table=table;+refcount_set(&table->refcount,0);table->esw_nb.notifier_call=mlx5_sf_esw_event;err=mlx5_esw_event_notifier_register(dev->priv.eswitch,&table->esw_nb);if(err)gotoreg_err;++table->vhca_nb.notifier_call=mlx5_sf_vhca_event;+err=mlx5_vhca_event_notifier_register(table->dev,&table->vhca_nb);+if(err)+gotovhca_err;+return0;+vhca_err:+mlx5_esw_event_notifier_unregister(dev->priv.eswitch,&table->esw_nb);reg_err:+mutex_destroy(&table->sf_state_lock);kfree(table);dev->priv.sf_table=NULL;returnerr;
@@ -34,10 +44,13 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)if(!table->max_local_functions)return-EOPNOTSUPP;+mutex_lock(&table->table_lock);/* Check if sf with same sfnum already exists or not. */for(i=0;i<table->max_local_functions;i++){-if(table->sfs[i].allocated&&table->sfs[i].usr_sfnum==usr_sfnum)-return-EEXIST;+if(table->sfs[i].allocated&&table->sfs[i].usr_sfnum==usr_sfnum){+err=-EEXIST;+gotoexist_err;+}}/* Find the free entry and allocate the entry from the array */
@@ -63,16 +76,19 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)if(err)gotovhca_err;+mutex_unlock(&table->table_lock);returnsw_id;vhca_err:mlx5_cmd_dealloc_sf(table->dev,hw_fn_id);err:table->sfs[i].allocated=false;+exist_err:+mutex_unlock(&table->table_lock);returnerr;}-voidmlx5_sf_hw_table_sf_free(structmlx5_core_dev*dev,u16id)+staticvoid_mlx5_sf_hw_id_free(structmlx5_core_dev*dev,u16id){structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;u16hw_fn_id;
@@ -88,7 +148,7 @@ int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev)structmlx5_sf_hw*sfs;intmax_functions;-if(!mlx5_sf_supported(dev))+if(!mlx5_sf_supported(dev)||!mlx5_vhca_event_supported(dev))return0;max_functions=mlx5_sf_max_functions(dev);
@@ -100,6 +160,7 @@ int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev)if(!sfs)gototable_err;+mutex_init(&table->table_lock);table->dev=dev;table->sfs=sfs;table->max_local_functions=max_functions;
@@ -120,6 +181,53 @@ void mlx5_sf_hw_table_cleanup(struct mlx5_core_dev *dev)if(!table)return;+mutex_destroy(&table->table_lock);kfree(table->sfs);kfree(table);}++staticintmlx5_sf_hw_vhca_event(structnotifier_block*nb,unsignedlongopcode,void*data)+{+structmlx5_sf_hw_table*table=container_of(nb,structmlx5_sf_hw_table,vhca_nb);+conststructmlx5_vhca_state_event*event=data;+structmlx5_sf_hw*sf_hw;+u16sw_id;++if(event->new_vhca_state!=MLX5_VHCA_STATE_ALLOCATED)+return0;++sw_id=mlx5_sf_hw_to_sw_id(table->dev,event->function_id);+sf_hw=&table->sfs[sw_id];++mutex_lock(&table->table_lock);+/* SF driver notified through firmware that SF is finally detached.+*Hencerecyclethesfhardwareidforreuse.+*/+if(sf_hw->allocated&&sf_hw->pending_delete)+_mlx5_sf_hw_id_free(table->dev,sw_id);+mutex_unlock(&table->table_lock);+return0;+}++intmlx5_sf_hw_table_create(structmlx5_core_dev*dev)+{+structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;++if(!table)+return0;++table->vhca_nb.notifier_call=mlx5_sf_hw_vhca_event;+returnmlx5_vhca_event_notifier_register(table->dev,&table->vhca_nb);+}++voidmlx5_sf_hw_table_destroy(structmlx5_core_dev*dev)+{+structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;++if(!table)+return;++mlx5_vhca_event_notifier_unregister(table->dev,&table->vhca_nb);+/* Dealloc SFs whose firmware event has been missed. */+mlx5_sf_hw_dealloc_all(table);+}
From: Parav Pandit <redacted>
To handle SF port management outside of the eswitch as independent
software layer, introduce eswitch notifier APIs so that mlx5 upper
layer who wish to support sf port management in switchdev mode can
perform its task whenever eswitch mode is set to switchdev or before
eswitch is disabled.
Initialize sf port table on such eswitch event.
Add SF port add and delete functionality in switchdev mode.
Destroy all SF ports when eswitch is disabled.
Expose SF port add and delete to user via devlink commands.
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show ens2f0npf0sf88
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
or by its unique port index:
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show ens2f0npf0sf88 -jp
{
"port": {
"pci/0000:06:00.0/32768": {
"type": "eth",
"netdev": "ens2f0npf0sf88",
"flavour": "pcisf",
"controller": 0,
"pfnum": 0,
"sfnum": 88,
"external": false,
"splittable": false,
"function": {
"hw_addr": "00:00:00:00:00:00",
"state": "inactive",
"opstate": "detached"
}
}
}
}
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/Kconfig | 10 +
.../net/ethernet/mellanox/mlx5/core/Makefile | 5 +
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 4 +
.../net/ethernet/mellanox/mlx5/core/devlink.c | 5 +
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 25 ++
.../net/ethernet/mellanox/mlx5/core/eswitch.h | 12 +
.../net/ethernet/mellanox/mlx5/core/main.c | 18 +
.../net/ethernet/mellanox/mlx5/core/sf/cmd.c | 27 ++
.../ethernet/mellanox/mlx5/core/sf/devlink.c | 316 ++++++++++++++++++
.../ethernet/mellanox/mlx5/core/sf/hw_table.c | 125 +++++++
.../net/ethernet/mellanox/mlx5/core/sf/priv.h | 17 +
.../net/ethernet/mellanox/mlx5/core/sf/sf.h | 37 ++
include/linux/mlx5/driver.h | 6 +
13 files changed, 607 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/cmd.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/priv.h
@@ -1599,6 +1599,15 @@ mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)kvfree(out);}+staticvoidmlx5_esw_mode_change_notify(structmlx5_eswitch*esw,u16mode)+{+structmlx5_esw_event_infoinfo={};++info.new_mode=mode;++blocking_notifier_call_chain(&esw->n_head,0,&info);+}+/***mlx5_eswitch_enable_locked-Enableeswitch*@esw:Pointertoeswitch
@@ -1659,6 +1668,8 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)mode==MLX5_ESWITCH_LEGACY?"LEGACY":"OFFLOADS",esw->esw_funcs.num_vfs,esw->enabled_vports);+mlx5_esw_mode_change_notify(esw,mode);+return0;abort:
@@ -1715,6 +1726,11 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)esw->mode==MLX5_ESWITCH_LEGACY?"LEGACY":"OFFLOADS",esw->esw_funcs.num_vfs,esw->enabled_vports);+/* Notify eswitch users that it is exiting from current mode.+*Sothatitcandonecessarycleanupbeforetheeswitchisdisabled.+*/+mlx5_esw_mode_change_notify(esw,MLX5_ESWITCH_NONE);+mlx5_eswitch_event_handlers_unregister(esw);if(esw->mode==MLX5_ESWITCH_LEGACY)
@@ -1815,6 +1831,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)esw->offloads.inline_mode=MLX5_INLINE_MODE_NONE;dev->priv.eswitch=esw;+BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head);return0;abort:if(esw->work_queue)
@@ -893,6 +893,18 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)gotoerr_fpga_cleanup;}+err=mlx5_sf_hw_table_init(dev);+if(err){+mlx5_core_err(dev,"Failed to init SF HW table %d\n",err);+gotoerr_sf_hw_table_cleanup;+}++err=mlx5_sf_table_init(dev);+if(err){+mlx5_core_err(dev,"Failed to init SF table %d\n",err);+gotoerr_sf_table_cleanup;+}+dev->dm=mlx5_dm_create(dev);if(IS_ERR(dev->dm))mlx5_core_warn(dev,"Failed to init device memory%d\n",err);
@@ -903,6 +915,10 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)return0;+err_sf_table_cleanup:+mlx5_sf_hw_table_cleanup(dev);+err_sf_hw_table_cleanup:+mlx5_vhca_event_cleanup(dev);err_fpga_cleanup:mlx5_fpga_cleanup(dev);err_eswitch_cleanup:
@@ -0,0 +1,316 @@+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB+/* Copyright (c) 2020 Mellanox Technologies Ltd */++#include<linux/mlx5/driver.h>+#include"eswitch.h"+#include"priv.h"++structmlx5_sf{+structdevlink_portdl_port;+unsignedintport_index;+u16id;+};++structmlx5_sf_table{+structmlx5_core_dev*dev;/* To refer from notifier context. */+structxarrayport_indices;/* port index based lookup. */+refcount_trefcount;+structcompletiondisable_complete;+structnotifier_blockesw_nb;+};++staticstructmlx5_sf*+mlx5_sf_lookup_by_index(structmlx5_sf_table*table,unsignedintport_index)+{+returnxa_load(&table->port_indices,port_index);+}++staticintmlx5_sf_id_insert(structmlx5_sf_table*table,structmlx5_sf*sf)+{+returnxa_insert(&table->port_indices,sf->port_index,sf,GFP_KERNEL);+}++staticvoidmlx5_sf_id_erase(structmlx5_sf_table*table,structmlx5_sf*sf)+{+xa_erase(&table->port_indices,sf->port_index);+}++staticstructmlx5_sf*+mlx5_sf_alloc(structmlx5_sf_table*table,u32sfnum,structnetlink_ext_ack*extack)+{+unsignedintdl_port_index;+structmlx5_sf*sf;+u16hw_fn_id;+intid_err;+interr;++id_err=mlx5_sf_hw_table_sf_alloc(table->dev,sfnum);+if(id_err<0){+err=id_err;+gotoid_err;+}++sf=kzalloc(sizeof(*sf),GFP_KERNEL);+if(!sf){+err=-ENOMEM;+gotoalloc_err;+}+sf->id=id_err;+hw_fn_id=mlx5_sf_sw_to_hw_id(table->dev,sf->id);+dl_port_index=mlx5_esw_vport_to_devlink_port_index(table->dev,hw_fn_id);+sf->port_index=dl_port_index;++err=mlx5_sf_id_insert(table,sf);+if(err)+gotoinsert_err;++returnsf;++insert_err:+kfree(sf);+alloc_err:+mlx5_sf_hw_table_sf_free(table->dev,id_err);+id_err:+if(err==-EEXIST)+NL_SET_ERR_MSG_MOD(extack,"SF already exist. Choose different sfnum");+returnERR_PTR(err);+}++staticvoidmlx5_sf_free(structmlx5_sf_table*table,structmlx5_sf*sf)+{+mlx5_sf_id_erase(table,sf);+mlx5_sf_hw_table_sf_free(table->dev,sf->id);+kfree(sf);+}++staticstructmlx5_sf_table*mlx5_sf_table_try_get(structmlx5_core_dev*dev)+{+structmlx5_sf_table*table=dev->priv.sf_table;++if(!table)+returnNULL;++returnrefcount_inc_not_zero(&table->refcount)?table:NULL;+}++staticvoidmlx5_sf_table_put(structmlx5_sf_table*table)+{+if(refcount_dec_and_test(&table->refcount))+complete(&table->disable_complete);+}++staticintmlx5_sf_add(structmlx5_core_dev*dev,structmlx5_sf_table*table,+conststructdevlink_port_new_attrs*new_attr,+structnetlink_ext_ack*extack,+unsignedint*new_port_index)+{+structmlx5_eswitch*esw=dev->priv.eswitch;+structmlx5_sf*sf;+u16hw_fn_id;+interr;++sf=mlx5_sf_alloc(table,new_attr->sfnum,extack);+if(IS_ERR(sf))+returnPTR_ERR(sf);++hw_fn_id=mlx5_sf_sw_to_hw_id(dev,sf->id);+err=mlx5_esw_offloads_sf_vport_enable(esw,&sf->dl_port,hw_fn_id,new_attr->sfnum);+if(err)+gotoesw_err;+*new_port_index=sf->port_index;+return0;++esw_err:+mlx5_sf_free(table,sf);+returnerr;+}++staticvoidmlx5_sf_del(structmlx5_core_dev*dev,structmlx5_sf_table*table,structmlx5_sf*sf)+{+structmlx5_eswitch*esw=dev->priv.eswitch;+u16hw_fn_id;++hw_fn_id=mlx5_sf_sw_to_hw_id(dev,sf->id);+mlx5_esw_offloads_sf_vport_disable(esw,hw_fn_id);+mlx5_sf_free(table,sf);+}++staticint+mlx5_sf_new_check_attr(structmlx5_core_dev*dev,conststructdevlink_port_new_attrs*new_attr,+structnetlink_ext_ack*extack)+{+if(new_attr->flavour!=DEVLINK_PORT_FLAVOUR_PCI_SF){+NL_SET_ERR_MSG_MOD(extack,"Driver supports only SF port addition");+return-EOPNOTSUPP;+}+if(new_attr->port_index_valid){+NL_SET_ERR_MSG_MOD(extack,+"Driver does not support user defined port index assignment");+return-EOPNOTSUPP;+}+if(!new_attr->sfnum_valid){+NL_SET_ERR_MSG_MOD(extack,+"User must provide unique sfnum. Driver does not support auto assignment");+return-EOPNOTSUPP;+}+if(new_attr->controller_valid&&new_attr->controller){+NL_SET_ERR_MSG_MOD(extack,"External controller is unsupported");+return-EOPNOTSUPP;+}+if(new_attr->pfnum!=PCI_FUNC(dev->pdev->devfn)){+NL_SET_ERR_MSG_MOD(extack,"Invalid pfnum supplied");+return-EOPNOTSUPP;+}+return0;+}++intmlx5_devlink_sf_port_new(structdevlink*devlink,+conststructdevlink_port_new_attrs*new_attr,+structnetlink_ext_ack*extack,+unsignedint*new_port_index)+{+structmlx5_core_dev*dev=devlink_priv(devlink);+structmlx5_sf_table*table;+interr;++err=mlx5_sf_new_check_attr(dev,new_attr,extack);+if(err)+returnerr;++table=mlx5_sf_table_try_get(dev);+if(!table){+NL_SET_ERR_MSG_MOD(extack,+"Port add is only supported in eswitch switchdev mode or SF ports are disabled.");+return-EOPNOTSUPP;+}+err=mlx5_sf_add(dev,table,new_attr,extack,new_port_index);+mlx5_sf_table_put(table);+returnerr;+}++intmlx5_devlink_sf_port_del(structdevlink*devlink,unsignedintport_index,+structnetlink_ext_ack*extack)+{+structmlx5_core_dev*dev=devlink_priv(devlink);+structmlx5_sf_table*table;+structmlx5_sf*sf;+interr=0;++table=mlx5_sf_table_try_get(dev);+if(!table){+NL_SET_ERR_MSG_MOD(extack,+"Port del is only supported in eswitch switchdev mode or SF ports are disabled.");+return-EOPNOTSUPP;+}+sf=mlx5_sf_lookup_by_index(table,port_index);+if(!sf){+err=-ENODEV;+gotosf_err;+}++mlx5_sf_del(dev,table,sf);+sf_err:+mlx5_sf_table_put(table);+returnerr;+}++staticvoidmlx5_sf_destroy_all(structmlx5_sf_table*table)+{+structmlx5_core_dev*dev=table->dev;+unsignedlongindex;+structmlx5_sf*sf;++xa_for_each(&table->port_indices,index,sf)+mlx5_sf_del(dev,table,sf);+}++staticvoidmlx5_sf_table_enable(structmlx5_sf_table*table)+{+if(!mlx5_sf_max_functions(table->dev))+return;++init_completion(&table->disable_complete);+refcount_set(&table->refcount,1);+}++staticvoidmlx5_sf_table_disable(structmlx5_sf_table*table)+{+if(!mlx5_sf_max_functions(table->dev))+return;++if(!refcount_read(&table->refcount))+return;++/* Balances with refcount_set; drop the reference so that new user cmd cannot start. */+mlx5_sf_table_put(table);+wait_for_completion(&table->disable_complete);++/* At this point, no new user commands can start.+*ItissafetodestroyallusercreatedSFs.+*/+mlx5_sf_destroy_all(table);+}++staticintmlx5_sf_esw_event(structnotifier_block*nb,unsignedlongevent,void*data)+{+structmlx5_sf_table*table=container_of(nb,structmlx5_sf_table,esw_nb);+conststructmlx5_esw_event_info*mode=data;++switch(mode->new_mode){+caseMLX5_ESWITCH_OFFLOADS:+mlx5_sf_table_enable(table);+break;+caseMLX5_ESWITCH_NONE:+mlx5_sf_table_disable(table);+break;+default:+break;+};++return0;+}++staticboolmlx5_sf_table_supported(conststructmlx5_core_dev*dev)+{+returndev->priv.eswitch&&MLX5_ESWITCH_MANAGER(dev)&&mlx5_sf_supported(dev);+}++intmlx5_sf_table_init(structmlx5_core_dev*dev)+{+structmlx5_sf_table*table;+interr;++if(!mlx5_sf_table_supported(dev))+return0;++table=kzalloc(sizeof(*table),GFP_KERNEL);+if(!table)+return-ENOMEM;++table->dev=dev;+xa_init(&table->port_indices);+dev->priv.sf_table=table;+table->esw_nb.notifier_call=mlx5_sf_esw_event;+err=mlx5_esw_event_notifier_register(dev->priv.eswitch,&table->esw_nb);+if(err)+gotoreg_err;+return0;++reg_err:+kfree(table);+dev->priv.sf_table=NULL;+returnerr;+}++voidmlx5_sf_table_cleanup(structmlx5_core_dev*dev)+{+structmlx5_sf_table*table=dev->priv.sf_table;++if(!table)+return;++mlx5_esw_event_notifier_unregister(dev->priv.eswitch,&table->esw_nb);+WARN_ON(refcount_read(&table->refcount));+WARN_ON(!xa_empty(&table->port_indices));+kfree(table);+}
@@ -0,0 +1,125 @@+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB+/* Copyright (c) 2020 Mellanox Technologies Ltd */+#include<linux/mlx5/driver.h>+#include"vhca_event.h"+#include"priv.h"+#include"sf.h"+#include"ecpf.h"++structmlx5_sf_hw{+u32usr_sfnum;+u8allocated:1;+};++structmlx5_sf_hw_table{+structmlx5_core_dev*dev;+structmlx5_sf_hw*sfs;+intmax_local_functions;+u8ecpu:1;+};++u16mlx5_sf_sw_to_hw_id(conststructmlx5_core_dev*dev,u16sw_id)+{+returnsw_id+mlx5_sf_start_function_id(dev);+}++intmlx5_sf_hw_table_sf_alloc(structmlx5_core_dev*dev,u32usr_sfnum)+{+structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;+intsw_id=-ENOSPC;+u16hw_fn_id;+interr;+inti;++if(!table->max_local_functions)+return-EOPNOTSUPP;++/* Check if sf with same sfnum already exists or not. */+for(i=0;i<table->max_local_functions;i++){+if(table->sfs[i].allocated&&table->sfs[i].usr_sfnum==usr_sfnum)+return-EEXIST;+}++/* Find the free entry and allocate the entry from the array */+for(i=0;i<table->max_local_functions;i++){+if(!table->sfs[i].allocated){+table->sfs[i].usr_sfnum=usr_sfnum;+table->sfs[i].allocated=true;+sw_id=i;+break;+}+}+if(sw_id==-ENOSPC){+err=-ENOSPC;+gotoerr;+}++hw_fn_id=mlx5_sf_sw_to_hw_id(table->dev,sw_id);+err=mlx5_cmd_alloc_sf(table->dev,hw_fn_id);+if(err)+gotoerr;++err=mlx5_modify_vhca_sw_id(dev,hw_fn_id,table->ecpu,usr_sfnum);+if(err)+gotovhca_err;++returnsw_id;++vhca_err:+mlx5_cmd_dealloc_sf(table->dev,hw_fn_id);+err:+table->sfs[i].allocated=false;+returnerr;+}++voidmlx5_sf_hw_table_sf_free(structmlx5_core_dev*dev,u16id)+{+structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;+u16hw_fn_id;++hw_fn_id=mlx5_sf_sw_to_hw_id(table->dev,id);+mlx5_cmd_dealloc_sf(table->dev,hw_fn_id);+table->sfs[id].allocated=false;+}++intmlx5_sf_hw_table_init(structmlx5_core_dev*dev)+{+structmlx5_sf_hw_table*table;+structmlx5_sf_hw*sfs;+intmax_functions;++if(!mlx5_sf_supported(dev))+return0;++max_functions=mlx5_sf_max_functions(dev);+table=kzalloc(sizeof(*table),GFP_KERNEL);+if(!table)+return-ENOMEM;++sfs=kcalloc(max_functions,sizeof(*sfs),GFP_KERNEL);+if(!sfs)+gototable_err;++table->dev=dev;+table->sfs=sfs;+table->max_local_functions=max_functions;+table->ecpu=mlx5_read_embedded_cpu(dev);+dev->priv.sf_hw_table=table;+mlx5_core_dbg(dev,"SF HW table: max sfs = %d\n",max_functions);+return0;++table_err:+kfree(table);+return-ENOMEM;+}++voidmlx5_sf_hw_table_cleanup(structmlx5_core_dev*dev)+{+structmlx5_sf_hw_table*table=dev->priv.sf_hw_table;++if(!table)+return;++kfree(table->sfs);+kfree(table);+}
@@ -0,0 +1,118 @@+.. SPDX-License-Identifier: GPL-2.0++.._devlink_port:++============+Devlink Port+============++``devlink-port`` is a port that exists on the device. It has a logically+separate ingress/egress point of the device. A devlink port can be any one+of many flavours. A devlink port flavour along with port attributes+describe what a port represents.++A device driver that intends to publish a devlink port sets the+devlink port attributes and registers the devlink port.++Devlink port flavours are described below.++..list-table:: List of devlink port flavours+:widths: 33 90++* - Flavour+- Description+* - ``DEVLINK_PORT_FLAVOUR_PHYSICAL``+- Any kind of physical port. This can be an eswitch physical port or any+ other physical port on the device.+* - ``DEVLINK_PORT_FLAVOUR_DSA``+- This indicates a DSA interconnect port.+* - ``DEVLINK_PORT_FLAVOUR_CPU``+- This indicates a CPU port applicable only to DSA.+* - ``DEVLINK_PORT_FLAVOUR_PCI_PF``+- This indicates an eswitch port representing a port of PCI+ physical function (PF).+* - ``DEVLINK_PORT_FLAVOUR_PCI_VF``+- This indicates an eswitch port representing a port of PCI+ virtual function (VF).+* - ``DEVLINK_PORT_FLAVOUR_VIRTUAL``+- This indicates a virtual port for the PCI virtual function.++Devlink port can have a different type based on the link layer described below.++..list-table:: List of devlink port types+:widths: 23 90++* - Type+- Description+* - ``DEVLINK_PORT_TYPE_ETH``+- Driver should set this port type when a link layer of the port is+ Ethernet.+* - ``DEVLINK_PORT_TYPE_IB``+- Driver should set this port type when a link layer of the port is+ InfiniBand.+* - ``DEVLINK_PORT_TYPE_AUTO``+- This type is indicated by the user when driver should detect the port+ type automatically.++PCI controllers+---------------+In most cases a PCI device has only one controller. A controller consists of+potentially multiple physical and virtual functions. A function consists+of one or more ports. This port is represented by the devlink eswitch port.++A PCI device connected to multiple CPUs or multiple PCI root complexes or a+SmartNIC, however, may have multiple controllers. For a device with multiple+controllers, each controller is distinguished by a unique controller number.+An eswitch is on the PCI device which supports ports of multiple controllers.++An example view of a system with two controllers::++ ---------------------------------------------------------+| |+| --------- --------- ------- ------- |+ ----------- | | vf(s) | | sf(s) | |vf(s)| |sf(s)| |+| server | | ------- ----/---- ---/----- ------- ---/--- ---/--- |+| pci rc |=== | pf0 |______/________/ | pf1 |___/_______/ |+| connect | | ------- ------- |+ ----------- | | controller_num=1 (no eswitch) |+ ------|--------------------------------------------------+ (internal wire)+ |+ ---------------------------------------------------------+| devlink eswitch ports and reps |+| ----------------------------------------------------- |+| |ctrl-0 | ctrl-0 | ctrl-0 | ctrl-0 | ctrl-0 |ctrl-0 | |+| |pf0 | pf0vfN | pf0sfN | pf1 | pf1vfN |pf1sfN | |+| ----------------------------------------------------- |+| |ctrl-1 | ctrl-1 | ctrl-1 | ctrl-1 | ctrl-1 |ctrl-1 | |+| |pf0 | pf0vfN | pf0sfN | pf1 | pf1vfN |pf1sfN | |+| ----------------------------------------------------- |+| |+| |+ ----------- | --------- --------- ------- ------- |+| smartNIC| | | vf(s) | | sf(s) | |vf(s)| |sf(s)| |+| pci rc |==| ------- ----/---- ---/----- ------- ---/--- ---/--- |+| connect | | | pf0 |______/________/ | pf1 |___/_______/ |+ ----------- | ------- ------- |+| |+| local controller_num=0 (eswitch) |+ ---------------------------------------------------------++In the above example, the external controller (identified by controller number = 1)+doesn't have the eswitch. Local controller (identified by controller number = 0)+has the eswitch. The Devlink instance on the local controller has eswitch+devlink ports for both the controllers.++Function configuration+======================++A user can configure the function attribute before enumerating the PCI+function. Usually it means, user should configure function attribute+before a bus specific device for the function is created. However, when+SRIOV is enabled, virtual function devices are created on the PCI bus.+Hence, function attribute should be configured before binding virtual+function device to the driver.++A user may set the hardware address of the function using+'devlink port function set hw_addr' command. For Ethernet port function+this means a MAC address.
From: Parav Pandit <redacted>
Introduce API to add and delete an auxiliary device for an SF.
Each SF has its own dedicated window in the PCI BAR 2.
SF device is similar to PCI PF and VF that supports multiple class of
devices such as net, rdma and vdpa.
SF device will be added or removed in subsequent patch during SF
devlink port function state change command.
A subfunction device exposes user supplied subfunction number which will
be further used by systemd/udev to have deterministic name for its
netdevice and rdma device.
An mlx5 subfunction auxiliary device example:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show ens2f0npf0sf88
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:88:88 state inactive opstate detached
$ devlink port function set ens2f0npf0sf88 hw_addr 00:00:00:00:88:88 state active
On activation,
$ ls -l /sys/bus/auxiliary/devices/
mlx5_core.sf.4 -> ../../../devices/pci0000:00/0000:00:03.0/0000:06:00.0/mlx5_core.sf.4
$ cat /sys/bus/auxiliary/devices/mlx5_core.sf.4/sfnum
88
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../device_drivers/ethernet/mellanox/mlx5.rst | 5 +
.../net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
.../net/ethernet/mellanox/mlx5/core/main.c | 4 +
.../ethernet/mellanox/mlx5/core/sf/dev/dev.c | 265 ++++++++++++++++++
.../ethernet/mellanox/mlx5/core/sf/dev/dev.h | 35 +++
include/linux/mlx5/driver.h | 2 +
6 files changed, 312 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h
@@ -97,6 +97,11 @@ Enabling the driver and kconfig options| Provides low-level InfiniBand/RDMA and `RoCE <https://community.mellanox.com/s/article/recommended-network-configuration-examples-for-roce-deployment>`_ support.+**CONFIG_MLX5_SF=(y/n)**++| Build support for subfunction.+| Subfunctons are more light weight than PCI SRIOV VFs. Choosing this option+| will enable support for creating subfunction devices.**External options** ( Choose if the corresponding mlx5 feature is required )
@@ -0,0 +1,265 @@+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB+/* Copyright (c) 2020 Mellanox Technologies Ltd */++#include<linux/mlx5/driver.h>+#include<linux/mlx5/device.h>+#include"mlx5_core.h"+#include"dev.h"+#include"sf/vhca_event.h"+#include"sf/sf.h"+#include"sf/mlx5_ifc_vhca_event.h"+#include"ecpf.h"++structmlx5_sf_dev_table{+structxarraydevices;+unsignedintmax_sfs;+phys_addr_tbase_address;+u64sf_bar_length;+structnotifier_blocknb;+structmlx5_core_dev*dev;+};++staticboolmlx5_sf_dev_supported(conststructmlx5_core_dev*dev)+{+returnMLX5_CAP_GEN(dev,sf)&&mlx5_vhca_event_supported(dev);+}++staticssize_tsfnum_show(structdevice*dev,structdevice_attribute*attr,char*buf)+{+structauxiliary_device*adev=container_of(dev,structauxiliary_device,dev);+structmlx5_sf_dev*sf_dev=container_of(adev,structmlx5_sf_dev,adev);++returnscnprintf(buf,PAGE_SIZE,"%u\n",sf_dev->sfnum);+}+staticDEVICE_ATTR_RO(sfnum);++staticstructattribute*sf_device_attrs[]={+&dev_attr_sfnum.attr,+NULL,+};++staticconststructattribute_groupsf_attr_group={+.attrs=sf_device_attrs,+};++staticconststructattribute_group*sf_attr_groups[2]={+&sf_attr_group,+NULL+};++staticvoidmlx5_sf_dev_release(structdevice*device)+{+structauxiliary_device*adev=container_of(device,structauxiliary_device,dev);+structmlx5_sf_dev*sf_dev=container_of(adev,structmlx5_sf_dev,adev);++mlx5_adev_idx_free(adev->id);+kfree(sf_dev);+}++staticvoidmlx5_sf_dev_remove(structmlx5_sf_dev*sf_dev)+{+auxiliary_device_delete(&sf_dev->adev);+auxiliary_device_uninit(&sf_dev->adev);+}++staticvoidmlx5_sf_dev_add(structmlx5_core_dev*dev,u16sf_index,u32sfnum)+{+structmlx5_sf_dev_table*table=dev->priv.sf_dev_table;+structmlx5_sf_dev*sf_dev;+structpci_dev*pdev;+interr;+intid;++id=mlx5_adev_idx_alloc();+if(id<0){+err=id;+gotoadd_err;+}++sf_dev=kzalloc(sizeof(*sf_dev),GFP_KERNEL);+if(!sf_dev){+mlx5_adev_idx_free(id);+err=-ENOMEM;+gotoadd_err;+}+pdev=dev->pdev;+sf_dev->adev.id=id;+sf_dev->adev.name=MLX5_SF_DEV_ID_NAME;+sf_dev->adev.dev.release=mlx5_sf_dev_release;+sf_dev->adev.dev.parent=&pdev->dev;+sf_dev->adev.dev.groups=sf_attr_groups;+sf_dev->sfnum=sfnum;+sf_dev->parent_mdev=dev;++if(!table->max_sfs){+mlx5_adev_idx_free(id);+kfree(sf_dev);+err=-EOPNOTSUPP;+gotoadd_err;+}+sf_dev->bar_base_addr=table->base_address+(sf_index*table->sf_bar_length);++err=auxiliary_device_init(&sf_dev->adev);+if(err){+mlx5_adev_idx_free(id);+kfree(sf_dev);+gotoadd_err;+}++err=auxiliary_device_add(&sf_dev->adev);+if(err){+put_device(&sf_dev->adev.dev);+gotoadd_err;+}++err=xa_insert(&table->devices,sf_index,sf_dev,GFP_KERNEL);+if(err)+gotoxa_err;+return;++xa_err:+mlx5_sf_dev_remove(sf_dev);+add_err:+mlx5_core_err(dev,"SF DEV: fail device add for index=%d sfnum=%d err=%d\n",+sf_index,sfnum,err);+}++staticvoidmlx5_sf_dev_del(structmlx5_core_dev*dev,structmlx5_sf_dev*sf_dev,u16sf_index)+{+structmlx5_sf_dev_table*table=dev->priv.sf_dev_table;++xa_erase(&table->devices,sf_index);+mlx5_sf_dev_remove(sf_dev);+}++staticint+mlx5_sf_dev_state_change_handler(structnotifier_block*nb,unsignedlongevent_code,void*data)+{+structmlx5_sf_dev_table*table=container_of(nb,structmlx5_sf_dev_table,nb);+conststructmlx5_vhca_state_event*event=data;+structmlx5_sf_dev*sf_dev;+u16sf_index;++sf_index=event->function_id-MLX5_CAP_GEN(table->dev,sf_base_id);+sf_dev=xa_load(&table->devices,sf_index);+switch(event->new_vhca_state){+caseMLX5_VHCA_STATE_ALLOCATED:+if(sf_dev)+mlx5_sf_dev_del(table->dev,sf_dev,sf_index);+break;+caseMLX5_VHCA_STATE_TEARDOWN_REQUEST:+if(sf_dev)+mlx5_sf_dev_del(table->dev,sf_dev,sf_index);+else+mlx5_core_err(table->dev,+"SF DEV: teardown state for invalid dev index=%d fn_id=0x%x\n",+sf_index,event->sw_function_id);+break;+caseMLX5_VHCA_STATE_ACTIVE:+if(!sf_dev)+mlx5_sf_dev_add(table->dev,sf_index,event->sw_function_id);+break;+default:+break;+}+return0;+}++staticintmlx5_sf_dev_vhca_arm_all(structmlx5_sf_dev_table*table)+{+structmlx5_core_dev*dev=table->dev;+u16max_functions;+u16function_id;+interr=0;+boolecpu;+inti;++max_functions=mlx5_sf_max_functions(dev);+function_id=MLX5_CAP_GEN(dev,sf_base_id);+ecpu=mlx5_read_embedded_cpu(dev);+/* Arm the vhca context as the vhca event notifier */+for(i=0;i<max_functions;i++){+err=mlx5_vhca_event_arm(dev,function_id,ecpu);+if(err)+returnerr;++function_id++;+}+return0;+}++voidmlx5_sf_dev_table_create(structmlx5_core_dev*dev)+{+structmlx5_sf_dev_table*table;+unsignedintmax_sfs;+interr;++if(!mlx5_sf_dev_supported(dev)||!mlx5_vhca_event_supported(dev))+return;++table=kzalloc(sizeof(*table),GFP_KERNEL);+if(!table){+err=-ENOMEM;+gototable_err;+}++table->nb.notifier_call=mlx5_sf_dev_state_change_handler;+table->dev=dev;+if(MLX5_CAP_GEN(dev,max_num_sf))+max_sfs=MLX5_CAP_GEN(dev,max_num_sf);+else+max_sfs=1<<MLX5_CAP_GEN(dev,log_max_sf);+table->sf_bar_length=1<<(MLX5_CAP_GEN(dev,log_min_sf_size)+12);+table->base_address=pci_resource_start(dev->pdev,2);+table->max_sfs=max_sfs;+xa_init(&table->devices);+dev->priv.sf_dev_table=table;++err=mlx5_vhca_event_notifier_register(dev,&table->nb);+if(err)+gotovhca_err;+err=mlx5_sf_dev_vhca_arm_all(table);+if(err)+gotoarm_err;+mlx5_core_dbg(dev,"SF DEV: max sf devices=%d\n",max_sfs);+return;++arm_err:+mlx5_vhca_event_notifier_unregister(dev,&table->nb);+vhca_err:+table->max_sfs=0;+kfree(table);+dev->priv.sf_dev_table=NULL;+table_err:+mlx5_core_err(dev,"SF DEV table create err = %d\n",err);+}++staticvoidmlx5_sf_dev_destroy_all(structmlx5_sf_dev_table*table)+{+structmlx5_sf_dev*sf_dev;+unsignedlongindex;++xa_for_each(&table->devices,index,sf_dev){+xa_erase(&table->devices,index);+mlx5_sf_dev_remove(sf_dev);+}+}++voidmlx5_sf_dev_table_destroy(structmlx5_core_dev*dev)+{+structmlx5_sf_dev_table*table=dev->priv.sf_dev_table;++if(!table)+return;++mlx5_vhca_event_notifier_unregister(dev,&table->nb);++/* Now that event handler is not running, it is safe to destroy+*thesfdevicewithoutrace.+*/+mlx5_sf_dev_destroy_all(table);++WARN_ON(!xa_empty(&table->devices));+kfree(table);+dev->priv.sf_dev_table=NULL;+}
From: Vu Pham <redacted>
Prepare eswitch to handle SF vport during
(a) querying eswitch functions
(b) egress ACL creation
(c) account for SF vports in total vports calculation
Assign a dedicated placeholder for SFs vports and their representors.
They are placed after VFs vports and before ECPF vports as below:
[PF,VF0,...,VFn,SF0,...SFm,ECPF,UPLINK].
Change functions to map SF's vport numbers to indices when
accessing the vports or representors arrays, and vice versa.
Signed-off-by: Vu Pham <redacted>
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Roi Dayan <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../mellanox/mlx5/core/esw/acl/egress_ofld.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 11 +++-
.../net/ethernet/mellanox/mlx5/core/eswitch.h | 50 +++++++++++++++++++
.../mellanox/mlx5/core/eswitch_offloads.c | 11 ++++
.../net/ethernet/mellanox/mlx5/core/vport.c | 3 +-
5 files changed, 73 insertions(+), 4 deletions(-)
@@ -499,6 +500,40 @@ static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev)MLX5_VPORT_PF:MLX5_VPORT_FIRST_VF;}+staticinlineintmlx5_esw_sf_start_idx(conststructmlx5_eswitch*esw)+{+/* PF and VF vports indices start from 0 to max_vfs */+returnMLX5_VPORT_PF_PLACEHOLDER+mlx5_core_max_vfs(esw->dev);+}++staticinlineintmlx5_esw_sf_end_idx(conststructmlx5_eswitch*esw)+{+returnmlx5_esw_sf_start_idx(esw)+mlx5_sf_max_functions(esw->dev);+}++staticinlineint+mlx5_esw_sf_vport_num_to_index(conststructmlx5_eswitch*esw,u16vport_num)+{+returnvport_num-mlx5_sf_start_function_id(esw->dev)++MLX5_VPORT_PF_PLACEHOLDER+mlx5_core_max_vfs(esw->dev);+}++staticinlineu16+mlx5_esw_sf_vport_index_to_num(conststructmlx5_eswitch*esw,intidx)+{+returnmlx5_sf_start_function_id(esw->dev)+idx-+(MLX5_VPORT_PF_PLACEHOLDER+mlx5_core_max_vfs(esw->dev));+}++staticinlinebool+mlx5_esw_is_sf_vport(conststructmlx5_eswitch*esw,u16vport_num)+{+returnmlx5_sf_supported(esw->dev)&&+vport_num>=mlx5_sf_start_function_id(esw->dev)&&+(vport_num<(mlx5_sf_start_function_id(esw->dev)++mlx5_sf_max_functions(esw->dev)));+}+staticinlineboolmlx5_eswitch_is_funcs_handler(conststructmlx5_core_dev*dev){returnmlx5_core_is_ecpf_esw_manager(dev);
@@ -527,6 +562,10 @@ static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw,if(vport_num==MLX5_VPORT_UPLINK)returnmlx5_eswitch_uplink_idx(esw);+if(mlx5_esw_is_sf_vport(esw,vport_num))+returnmlx5_esw_sf_vport_num_to_index(esw,vport_num);++/* PF and VF vports start from 0 to max_vfs */returnvport_num;}
@@ -540,6 +579,12 @@ static inline u16 mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw,if(index==mlx5_eswitch_uplink_idx(esw))returnMLX5_VPORT_UPLINK;+/* SF vports indices are after VFs and before ECPF */+if(mlx5_sf_supported(esw->dev)&&+index>mlx5_core_max_vfs(esw->dev))+returnmlx5_esw_sf_vport_index_to_num(esw,index);++/* PF and VF vports start from 0 to max_vfs */returnindex;}
@@ -36,6 +36,7 @@#include<linux/mlx5/vport.h>#include<linux/mlx5/eswitch.h>#include"mlx5_core.h"+#include"sf/sf.h"/* Mutex to hold while enabling or disabling RoCE */staticDEFINE_MUTEX(mlx5_roce_en_lock);
@@ -12,6 +12,8 @@ Contents-`Enabling the driver and kconfig options`_-`Devlink info`_-`Devlink parameters`_+-`mlx5 subfunction`_+-`mlx5 port function`_-`Devlink health reporters`_-`mlx5 tracepoints`_
@@ -181,6 +183,214 @@ User command examples: values: cmode driverinit value true+mlx5 subfunction+================+mlx5 supports subfunction management using devlink port (see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.++A Subfunction has its own function capabilities and its own resources. This+means a subfunction has its own dedicated queues (txq, rxq, cq, eq). These+queues are neither shared nor stolen from the parent PCI function.++When a subfunction is RDMA capable, it has its own QP1, GID table and rdma+resources neither shared nor stolen from the parent PCI function.++A subfunction has a dedicated window in PCI BAR space that is not shared+with ther other subfunctions or the parent PCI function. This ensures that all+devices (netdev, rdma, vdpa etc.) of the subfunction accesses only assigned+PCI BAR space.++A Subfunction supports eswitch representation through which it supports tc+offloads. The user configures eswitch to send/receive packets from/to+the subfunction port.++Subfunctions share PCI level resources such as PCI MSI-X IRQs with+other subfunctions and/or with its parent PCI function.++Example mlx5 software, system and device view::++ _______+| admin |+| user |----------+ |_______| |+| |+ ____|____ __|______ _________________+| | | | | |+| devlink | | tc tool | | user |+| tool | |_________| | applications |+ |_________| | |_________________|+| | | |+| | | | Userspace+ +---------|-------------|-------------------|----------|--------------------++| | +----------+ +----------+ Kernel+| | | netdev | | rdma dev |+| | +----------+ +----------++ (devlink port add/del | ^ ^+ port function set) | | |+| | +---------------|+ _____|___ | | _______|_______+| | | | | mlx5 class |+| devlink | +------------+ | | drivers |+| kernel | | rep netdev | | |(mlx5_core,ib) |+ |_________| +------------+ | |_______________|+| | | ^+ (devlink ops) | | (probe/remove)+ _________|________ | | ____|________+| subfunction | | +---------------+ | subfunction |+| management driver|----- | subfunction |---| driver |+| (mlx5_core) | | auxiliary dev | | (mlx5_core) |+ |__________________| +---------------+ |_____________|+| ^+ (sf add/del, vhca events) |+| (device add/del)+ _____|____ ____|________+| | | subfunction |+| PCI NIC |---- activate/deactive events---->| host driver |+ |__________| | (mlx5_core) |+ |_____________|++Subfunction is created using devlink port interface.++- Change device to switchdev mode::++ $ devlink dev eswitch set pci/0000:06:00.0 mode switchdev++- Add a devlink port of subfunction flaovur::++ $ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88+ pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false+ function:+ hw_addr 00:00:00:00:00:00 state inactive opstate detached++- Show a devlink port of the subfunction::++ $ devlink port show pci/0000:06:00.0/32768+ pci/0000:06:00.0/32768: type eth netdev enp6s0pf0sf88 flavour pcisf pfnum 0 sfnum 88+ function:+ hw_addr 00:00:00:00:00:00 state inactive opstate detached++- Delete a devlink port of subfunction after use::++ $ devlink port del pci/0000:06:00.0/32768++mlx5 function attributes+========================+The mlx5 driver provides a mechanism to setup PCI VF/SF function attributes in+a unified way for SmartNIC and non-SmartNIC.++This is supported only when the eswitch mode is set to switchdev. Port function+configuration of the PCI VF/SF is supported through devlink eswitch port.++Port function attributes should be set before PCI VF/SF is enumerated by the+driver.++MAC address setup+-----------------+mlx5 driver provides mechanism to setup the MAC address of the PCI VF/SF.++The configured MAC address of the PCI VF/SF will be used by netdevice and rdma+device created for the PCI VF/SF.++- Get the MAC address of the VF identified by its unique devlink port index::++ $ devlink port show pci/0000:06:00.0/2+ pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1+ function:+ hw_addr 00:00:00:00:00:00++- Set the MAC address of the VF identified by its unique devlink port index::++ $ devlink port function set pci/0000:06:00.0/2 hw_addr 00:11:22:33:44:55++ $ devlink port show pci/0000:06:00.0/2+ pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1+ function:+ hw_addr 00:11:22:33:44:55++- Get the MAC address of the SF identified by its unique devlink port index::++ $ devlink port show pci/0000:06:00.0/32768+ pci/0000:06:00.0/32768: type eth netdev enp6s0pf0sf88 flavour pcisf pfnum 0 sfnum 88+ function:+ hw_addr 00:00:00:00:00:00++- Set the MAC address of the VF identified by its unique devlink port index::++ $ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88++ $ devlink port show pci/0000:06:00.0/32768+ pci/0000:06:00.0/32768: type eth netdev enp6s0pf0sf88 flavour pcivf pfnum 0 sfnum 88+ function:+ hw_addr 00:00:00:00:88:88++SF state setup+--------------+To use the SF, the user must active the SF using the SF function state+attribute.++- Get the state of the SF identified by its unique devlink port index::++ $ devlink port show ens2f0npf0sf88+ pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false+ function:+ hw_addr 00:00:00:00:88:88 state inactive opstate detached++- Activate the function and verify its state is active::++ $ devlink port function set ens2f0npf0sf88 state active++ $ devlink port show ens2f0npf0sf88+ pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false+ function:+ hw_addr 00:00:00:00:88:88 state active opstate detached++Upon function activation, the PF driver instance gets the event from the device+that a particular SF was activated. It's the cue to put the device on bus, probe+it and instantiate the devlink instance and class specific auxiliary devices+for it.++- Show the auxiliary device and port of the subfunction::++ $ devlink dev show+ devlink dev show auxiliary/mlx5_core.sf.4++ $ devlink port show auxiliary/mlx5_core.sf.4/1+ auxiliary/mlx5_core.sf.4/1: type eth netdev p0sf88 flavour virtual port 0 splittable false++ $ rdma link show mlx5_0/1+ link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev p0sf88++ $ rdma dev show+ 8: rocep6s0f1: node_type ca fw 16.29.0550 node_guid 248a:0703:00b3:d113 sys_image_guid 248a:0703:00b3:d112+ 13: mlx5_0: node_type ca fw 16.29.0550 node_guid 0000:00ff:fe00:8888 sys_image_guid 248a:0703:00b3:d112++- Subfunction auxiliary device and class device hierarchy::++ mlx5_core.sf.4+ (subfunction auxiliary device)+ /\+ / \+ / \+ / \+ / \+ mlx5_core.eth.4 mlx5_core.rdma.4+ (sf eth aux dev) (sf rdma aux dev)+| |+| |+ p0sf88 mlx5_0+ (sf netdev) (sf rdma device)++Additionally, the SF port also gets the event when the driver attaches to the+auxiliary device of the subfunction. This results in changing the operational+state of the function. This provides visiblity to the user to decide when is it+safe to delete the SF port for graceful termination of the subfunction.++- Show the SF port operational state::++ $ devlink port show ens2f0npf0sf88+ pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false+ function:+ hw_addr 00:00:00:00:88:88 state active opstate attached+ Devlink health reporters ========================
From: Parav Pandit <redacted>
vhca state events indicates change in the state of the vhca that may
occur due to a SF allocation, deallocation or enabling/disabling the
SF HCA.
Introduce vhca state event handler which will be used by SF devlink
port manager and SF hardware id allocator in subsequent patches
to act on the event.
This enables single entity to subscribe, query and rearm the event
for a function.
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/Kconfig | 9 +
.../net/ethernet/mellanox/mlx5/core/Makefile | 4 +
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 4 +
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 3 +
.../net/ethernet/mellanox/mlx5/core/events.c | 7 +
.../net/ethernet/mellanox/mlx5/core/main.c | 16 ++
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +
.../mlx5/core/sf/mlx5_ifc_vhca_event.h | 82 ++++++++
.../net/ethernet/mellanox/mlx5/core/sf/sf.h | 45 +++++
.../mellanox/mlx5/core/sf/vhca_event.c | 189 ++++++++++++++++++
.../mellanox/mlx5/core/sf/vhca_event.h | 57 ++++++
include/linux/mlx5/driver.h | 4 +
12 files changed, 422 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/mlx5_ifc_vhca_event.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.h
From: Parav Pandit <redacted>
devlink port function can be in active or inactive state.
Allow users to get and set port function's state.
When the port function it activated, its operational state may change
after a while when the device is created and driver binds to it.
Similarly on deactivation flow.
To clearly describe the state of the port function and its device's
operational state in the host system, define state and opstate
attributes.
Example of a PCI SF port which supports a port function:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:88:88 state inactive opstate detached
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active
$ devlink port show pci/0000:06:00.0/32768 -jp
{
"port": {
"pci/0000:06:00.0/32768": {
"type": "eth",
"netdev": "ens2f0npf0sf88",
"flavour": "pcisf",
"controller": 0,
"pfnum": 0,
"sfnum": 88,
"external": false,
"splittable": false,
"function": {
"hw_addr": "00:00:00:00:88:88",
"state": "active",
"opstate": "attached"
}
}
}
}
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Jiri Pirko <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
include/net/devlink.h | 32 +++++++++++++
include/uapi/linux/devlink.h | 20 ++++++++
net/core/devlink.c | 90 +++++++++++++++++++++++++++++++++++-
3 files changed, 141 insertions(+), 1 deletion(-)
@@ -746,6 +749,58 @@ devlink_port_fn_hw_addr_fill(struct devlink *devlink, const struct devlink_ops *return0;}+staticbool+devlink_port_fn_state_valid(enumdevlink_port_fn_statestate)+{+returnstate==DEVLINK_PORT_FN_STATE_INACTIVE||+state==DEVLINK_PORT_FN_STATE_ACTIVE;+}++staticbool+devlink_port_fn_opstate_valid(enumdevlink_port_fn_opstateopstate)+{+returnopstate==DEVLINK_PORT_FN_OPSTATE_DETACHED||+opstate==DEVLINK_PORT_FN_OPSTATE_ATTACHED;+}++staticint+devlink_port_fn_state_fill(structdevlink*devlink,+conststructdevlink_ops*ops,+structdevlink_port*port,structsk_buff*msg,+structnetlink_ext_ack*extack,+bool*msg_updated)+{+enumdevlink_port_fn_opstateopstate;+enumdevlink_port_fn_statestate;+interr;++if(!ops->port_fn_state_get)+return0;++err=ops->port_fn_state_get(devlink,port,&state,&opstate,extack);+if(err){+if(err==-EOPNOTSUPP)+return0;+returnerr;+}+if(!devlink_port_fn_state_valid(state)){+WARN_ON_ONCE(1);+NL_SET_ERR_MSG_MOD(extack,"Invalid state read from driver");+return-EINVAL;+}+if(!devlink_port_fn_opstate_valid(opstate)){+WARN_ON_ONCE(1);+NL_SET_ERR_MSG_MOD(extack,+"Invalid operational state read from driver");+return-EINVAL;+}+if(nla_put_u8(msg,DEVLINK_PORT_FN_ATTR_STATE,state)||+nla_put_u8(msg,DEVLINK_PORT_FN_ATTR_OPSTATE,opstate))+return-EMSGSIZE;+*msg_updated=true;+return0;+}+staticintdevlink_nl_port_function_attrs_put(structsk_buff*msg,structdevlink_port*port,structnetlink_ext_ack*extack)
@@ -1028,6 +1088,24 @@ devlink_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port *returnops->port_function_hw_addr_set(devlink,port,hw_addr,hw_addr_len,extack);}+staticintdevlink_port_fn_state_set(structdevlink*devlink,+structdevlink_port*port,+conststructnlattr*attr,+structnetlink_ext_ack*extack)+{+enumdevlink_port_fn_statestate;+conststructdevlink_ops*ops;++state=nla_get_u8(attr);+ops=devlink->ops;+if(!ops->port_fn_state_set){+NL_SET_ERR_MSG_MOD(extack,+"Function does not support state setting");+return-EOPNOTSUPP;+}+returnops->port_fn_state_set(devlink,port,state,extack);+}+staticintdevlink_port_function_set(structdevlink*devlink,structdevlink_port*port,conststructnlattr*attr,structnetlink_ext_ack*extack)
@@ -1043,8 +1121,18 @@ devlink_port_function_set(struct devlink *devlink, struct devlink_port *port,}attr=tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR];-if(attr)+if(attr){err=devlink_port_function_hw_addr_set(devlink,port,attr,extack);+if(err)+returnerr;+}+/* Keep this as the last function attribute set, so that when+*multipleportfunctionattributesaresetalongwithstate,+*Thosecanbeappliedfirstbeforeactivatingthestate.+*/+attr=tb[DEVLINK_PORT_FN_ATTR_STATE];+if(attr)+err=devlink_port_fn_state_set(devlink,port,attr,extack);if(!err)devlink_port_notify(port,DEVLINK_CMD_PORT_NEW);
From: Parav Pandit <redacted>
Prepare code to fill zero or more port function optional attributes.
Subsequent patch makes use of this to fill more port function
attributes.
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Jiri Pirko <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
net/core/devlink.c | 64 ++++++++++++++++++++++++----------------------
1 file changed, 33 insertions(+), 31 deletions(-)
@@ -712,6 +712,31 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg,return0;}+staticint+devlink_port_fn_hw_addr_fill(structdevlink*devlink,conststructdevlink_ops*ops,+structdevlink_port*port,structsk_buff*msg,+structnetlink_ext_ack*extack,bool*msg_updated)+{+u8hw_addr[MAX_ADDR_LEN];+inthw_addr_len;+interr;++if(!ops->port_function_hw_addr_get)+return0;++err=ops->port_function_hw_addr_get(devlink,port,hw_addr,&hw_addr_len,extack);+if(err){+if(err==-EOPNOTSUPP)+return0;+returnerr;+}+err=nla_put(msg,DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,hw_addr_len,hw_addr);+if(err)+returnerr;+*msg_updated=true;+return0;+}+staticintdevlink_nl_port_function_attrs_put(structsk_buff*msg,structdevlink_port*port,structnetlink_ext_ack*extack)
@@ -719,36 +744,17 @@ devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *porstructdevlink*devlink=port->devlink;conststructdevlink_ops*ops;structnlattr*function_attr;-boolempty_nest=true;-interr=0;+boolmsg_updated=false;+interr;function_attr=nla_nest_start_noflag(msg,DEVLINK_ATTR_PORT_FUNCTION);if(!function_attr)return-EMSGSIZE;ops=devlink->ops;-if(ops->port_function_hw_addr_get){-inthw_addr_len;-u8hw_addr[MAX_ADDR_LEN];--err=ops->port_function_hw_addr_get(devlink,port,hw_addr,&hw_addr_len,extack);-if(err==-EOPNOTSUPP){-/* Port function attributes are optional for a port. If port doesn't-*supportfunctionattribute,returning-EOPNOTSUPPisnotanerror.-*/-err=0;-gotoout;-}elseif(err){-gotoout;-}-err=nla_put(msg,DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,hw_addr_len,hw_addr);-if(err)-gotoout;-empty_nest=false;-}--out:-if(err||empty_nest)+err=devlink_port_fn_hw_addr_fill(devlink,ops,port,msg,+extack,&msg_updated);+if(err||!msg_updated)nla_nest_cancel(msg,function_attr);elsenla_nest_end(msg,function_attr);
From: Parav Pandit <redacted>
A PCI sub-function (SF) represents a portion of the device similar
to PCI VF.
In an eswitch, PCI SF may have port which is normally represented
using a representor netdevice.
To have better visibility of eswitch port, its association with SF,
and its representor netdevice, introduce a PCI SF port flavour.
When devlink port flavour is PCI SF, fill up PCI SF attributes of the
port.
Extend port name creation using PCI PF and SF number scheme on best
effort basis, so that vendor drivers can skip defining their own
scheme.
This is done as cApfNSfM, where A, N and M are controller, PCI PF and
PCI SF number respectively.
This is similar to existing naming for PCI PF and PCI VF ports.
An example view of a PCI SF port:
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:88:88 state active opstate attached
$ devlink port show pci/0000:06:00.0/32768 -jp
{
"port": {
"pci/0000:06:00.0/32768": {
"type": "eth",
"netdev": "ens2f0npf0sf88",
"flavour": "pcisf",
"controller": 0,
"pfnum": 0,
"sfnum": 88,
"splittable": false,
"function": {
"hw_addr": "00:00:00:00:88:88",
"state": "active",
"opstate": "attached"
}
}
}
}
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Jiri Pirko <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
include/net/devlink.h | 16 +++++++++++++++
include/uapi/linux/devlink.h | 5 +++++
net/core/devlink.c | 39 ++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+)
@@ -200,6 +200,10 @@ enum devlink_port_flavour {DEVLINK_PORT_FLAVOUR_UNUSED,/* Port which exists in the switch, but*isnotusedinanyway.*/+DEVLINK_PORT_FLAVOUR_PCI_SF,/* Represents eswitch port+*forthePCISF.Itisaninternal+*portthatfacesthePCISF.+*/};enumdevlink_param_cmode{
@@ -529,6 +533,7 @@ enum devlink_attr {DEVLINK_ATTR_RELOAD_ACTION_INFO,/* nested */DEVLINK_ATTR_RELOAD_ACTION_STATS,/* nested */+DEVLINK_ATTR_PORT_PCI_SF_NUMBER,/* u32 *//* add new attributes above here, update the policy in devlink.c */__DEVLINK_ATTR_MAX,
From: Parav Pandit <redacted>
Extended devlink interface for the user to add and delete a port.
Extend devlink to connect user requests to driver to add/delete
a port in the device.
Driver routines are invoked without holding devlink instance lock.
This enables driver to perform several devlink objects registration,
unregistration such as (port, health reporter, resource etc) by using
existing devlink APIs.
This also helps to uniformly use the code for port unregistration
during driver unload and during port deletion initiated by user.
Examples of add, show and delete commands:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 external false splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
$ udevadm test-builtin net_id /sys/class/net/eth6
Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
Using default interface naming scheme 'v245'.
ID_NET_NAMING_SCHEME=v245
ID_NET_NAME_PATH=enp6s0f0npf0sf88
ID_NET_NAME_SLOT=ens2f0npf0sf88
Unload module index
Unloaded link configuration context.
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
include/net/devlink.h | 52 ++++++++++++++++++
net/core/devlink.c | 121 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 173 insertions(+)
@@ -1147,6 +1147,111 @@ static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,returndevlink_port_unsplit(devlink,port_index,info->extack);}+staticintdevlink_port_new_notifiy(structdevlink*devlink,+unsignedintport_index,+structgenl_info*info)+{+structdevlink_port*devlink_port;+structsk_buff*msg;+interr;++msg=nlmsg_new(NLMSG_DEFAULT_SIZE,GFP_KERNEL);+if(!msg)+return-ENOMEM;++mutex_lock(&devlink->lock);+devlink_port=devlink_port_get_by_index(devlink,port_index);+if(!devlink_port){+err=-ENODEV;+gotoout;+}++err=devlink_nl_port_fill(msg,devlink,devlink_port,+DEVLINK_CMD_NEW,info->snd_portid,+info->snd_seq,0,NULL);+if(err)+gotoout;++err=genlmsg_reply(msg,info);+mutex_unlock(&devlink->lock);+returnerr;++out:+mutex_unlock(&devlink->lock);+nlmsg_free(msg);+returnerr;+}++staticintdevlink_nl_cmd_port_new_doit(structsk_buff*skb,+structgenl_info*info)+{+structnetlink_ext_ack*extack=info->extack;+structdevlink_port_new_attrsnew_attrs={};+structdevlink*devlink=info->user_ptr[0];+unsignedintnew_port_index;+interr;++if(!devlink->ops->port_new||!devlink->ops->port_del)+return-EOPNOTSUPP;++if(!info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]||+!info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]){+NL_SET_ERR_MSG_MOD(extack,"Port flavour or PCI PF are not specified");+return-EINVAL;+}+new_attrs.flavour=nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]);+new_attrs.pfnum=+nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]);++if(info->attrs[DEVLINK_ATTR_PORT_INDEX]){+/* Port index of the new port being created by driver. */+new_attrs.port_index=+nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);+new_attrs.port_index_valid=true;+}+if(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]){+new_attrs.controller=+nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]);+new_attrs.controller_valid=true;+}+if(new_attrs.flavour==DEVLINK_PORT_FLAVOUR_PCI_SF&&+info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]){+new_attrs.sfnum=nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]);+new_attrs.sfnum_valid=true;+}++err=devlink->ops->port_new(devlink,&new_attrs,extack,+&new_port_index);+if(err)+returnerr;++err=devlink_port_new_notifiy(devlink,new_port_index,info);+if(err&&err!=-ENODEV){+/* Fail to send the response; destroy newly created port. */+devlink->ops->port_del(devlink,new_port_index,extack);+}+returnerr;+}++staticintdevlink_nl_cmd_port_del_doit(structsk_buff*skb,+structgenl_info*info)+{+structnetlink_ext_ack*extack=info->extack;+structdevlink*devlink=info->user_ptr[0];+unsignedintport_index;++if(!devlink->ops->port_del)+return-EOPNOTSUPP;++if(!info->attrs[DEVLINK_ATTR_PORT_INDEX]){+NL_SET_ERR_MSG_MOD(extack,"Port index is not specified");+return-EINVAL;+}+port_index=nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);++returndevlink->ops->port_del(devlink,port_index,extack);+}+staticintdevlink_nl_sb_fill(structsk_buff*msg,structdevlink*devlink,structdevlink_sb*devlink_sb,enumdevlink_commandcmd,u32portid,
On Fri, Jan 22, 2021 at 11:37 AM Saeed Mahameed [off-list ref] wrote:
This series form Parav was the theme of this mlx5 release cycle,
we've been waiting anxiously for the auxbus infrastructure to make it into
the kernel, and now as the auxbus is in and all the stars are aligned, I
can finally submit this patchset of the devlink and mlx5 subfunction support.
For more detailed information about subfunctions please see detailed tag
log below.
Apologies for the tardy question out of left field, but I've been
thinking about this some more. If I recall, the primary motivation for
this was a means to effectively address more VFs? But, why can't the
device simply expose more bus numbers?
From the PCI spec:
"SR-IOV Devices may consume more than one Bus Number. A VF can be
associated with any Bus Number within
the Device’s Bus Number range - the captured Bus Number plus any
additional Bus Numbers configured by
software. See Section 9.2.1.2 for details.
- Use of multiple Bus Numbers enables a device to support a very large
number of VFs - up to the size
of the Routing ID space minus the bits used to identify intervening busses"
Regards,
Edwin Peer
From: Edwin Peer <redacted>
Sent: Monday, January 25, 2021 2:17 AM
On Fri, Jan 22, 2021 at 11:37 AM Saeed Mahameed [off-list ref]
wrote:
quoted
For more detailed information about subfunctions please see detailed tag
log below.
Apologies for the tardy question out of left field, but I've been
thinking about this some more. If I recall, the primary motivation for
this was a means to effectively address more VFs? But, why can't the
device simply expose more bus numbers?
From: Jason Gunthorpe <jgg@nvidia.com> Date: 2021-01-25 13:25:23
On Mon, Jan 25, 2021 at 10:57:14AM +0000, Parav Pandit wrote:
Hi Edwin,
quoted
From: Edwin Peer <redacted>
Sent: Monday, January 25, 2021 2:17 AM
On Fri, Jan 22, 2021 at 11:37 AM Saeed Mahameed [off-list ref]
wrote:
quoted
For more detailed information about subfunctions please see detailed tag
log below.
Apologies for the tardy question out of left field, but I've been
thinking about this some more. If I recall, the primary motivation for
this was a means to effectively address more VFs? But, why can't the
device simply expose more bus numbers?
Several weeks back, Jason already answered this VF scaling question
from you at discussion [1].
To add a little more colour, the PCI spec design requires a CAM (ie
search) to figure out which function an incoming address is connected
to because there are no restrictions on how BAR's of each function
have to be layed out.
SRIOV and SF's require a simple linear lookup to learn the "function"
because the BAR space is required to be linear.
Scaling a CAM to high sizes is physicaly infeasible, so all approaches
to scaling PCI functions go this road of having a single large BAR
space.
Jason
On Mon, Jan 25, 2021 at 2:57 AM Parav Pandit [off-list ref] wrote:
quoted
Apologies for the tardy question out of left field, but I've been
thinking about this some more. If I recall, the primary motivation for
this was a means to effectively address more VFs? But, why can't the
device simply expose more bus numbers?
True, although I didn't really consider the full cost argument at the
time because the core answer was "They can't", however, the fact is,
PCI can.
Regards,
Edwin Peer
A lot of the trappings that PCI-SIG requires to be implemented in HW
for a VF, like PCI config space, MSI tables, BAR space, etc. is all
just dead weight when scaling up to 1000's of VFs.
What do these amount to in practice? Presumably config space is backed
by normal memory controlled by firmware. Do VF's need to expose ECAM?
Also, don't MSI tables come out of the BAR budget? Is the required BAR
space necessarily more than any other addressable unit that can be
delegated to a SF?
Whatever the costs, presumably they need to be weighed against the
complexity costs of the alternative?
Regards,
Edwin Peer
From: Jason Gunthorpe <jgg@nvidia.com> Date: 2021-01-25 20:02:16
On Mon, Jan 25, 2021 at 11:34:49AM -0800, Edwin Peer wrote:
What do these amount to in practice? Presumably config space is backed
by normal memory controlled by firmware. Do VF's need to expose ECAM?
Also, don't MSI tables come out of the BAR budget? Is the required BAR
space necessarily more than any other addressable unit that can be
delegated to a SF?
Every writable data mandated by the PCI spec requires very expensive
on-die SRAM to store it.
We've seen Intel drivers that show their SIOV ADIs don't even have a
register file and the only PCI presence is just a write-only doorbell
page in the BAR.
It is hard to argue a write-only register in a BAR page vs all the
SRIOV trappings when it comes to HW cost.
Jason
On Mon, Jan 25, 2021 at 11:49 AM Jason Gunthorpe [off-list ref] wrote:
I've never seen someone implement a NumVF > 256 by co-opting the bus
number.
Usually the VF offset already places the VF routing IDs into a
different bus number range from the PF. That much at least works
today.
Can Linux even assign more bus numbers to a port without firmware
help? Bus numbers are something that requires the root complex to be
aware of to setup routability.
I'm not sure, presumably something already infers this for the first
additional bus number based on the SR-IOV config capability?
Regards,
Edwin Peer
From: Michael Chan <michael.chan@broadcom.com> Date: 2021-01-25 20:25:10
On Mon, Jan 25, 2021 at 12:09 PM Edwin Peer [off-list ref] wrote:
On Mon, Jan 25, 2021 at 11:49 AM Jason Gunthorpe [off-list ref] wrote:
quoted
I've never seen someone implement a NumVF > 256 by co-opting the bus
number.
Usually the VF offset already places the VF routing IDs into a
different bus number range from the PF. That much at least works
today.
quoted
Can Linux even assign more bus numbers to a port without firmware
help? Bus numbers are something that requires the root complex to be
aware of to setup routability.
I'm not sure, presumably something already infers this for the first
additional bus number based on the SR-IOV config capability?
Yes, this should work. During enumeration, it sees that a device
capable of SRIOV needs more than one bus number and will assign the
proper primary and secondary bus numbers to the upstream bridge.
On Mon, Jan 25, 2021 at 11:59 AM Jason Gunthorpe [off-list ref] wrote:
Every writable data mandated by the PCI spec requires very expensive
on-die SRAM to store it.
That's an implementation decision. Nothing mandates that the state has
to physically exist in the same structure, only that reads and writes
are appropriately responded to. Parts that are read only could be
generated on the fly and writes can be stored more efficiently.
We've seen Intel drivers that show their SIOV ADIs don't even have a
register file and the only PCI presence is just a write-only doorbell
page in the BAR.
Right, but presumably it still needs to be at least a page. And,
nothing says your device's VF BAR protocol can't be equally simple.
It is hard to argue a write-only register in a BAR page vs all the
SRIOV trappings when it comes to HW cost.
Say it's double the cost? I don't know that it is, but does that
warrant the additional complexity of SFs? We should try to quantify.
Regards,
Edwin Peer
From: Edwin Peer <redacted>
Sent: Tuesday, January 26, 2021 1:36 AM
On Mon, Jan 25, 2021 at 11:49 AM Jason Gunthorpe [off-list ref]
wrote:
quoted
I've never seen someone implement a NumVF > 256 by co-opting the bus
number.
Usually the VF offset already places the VF routing IDs into a
different bus number range from the PF. That much at least works
today.
quoted
Can Linux even assign more bus numbers to a port without firmware
help? Bus numbers are something that requires the root complex to be
aware of to setup routability.
I'm not sure, presumably something already infers this for the first
additional bus number based on the SR-IOV config capability?
It is not inferred.
Linux pci core programs the additional registers for subordinate and secondary bus numbers.
Though, it comes with its own extra hw cost.
Keep in mind how 1000 Vfs are enabled and disabled in one go at pci spec level and so at OS level, as opposed to unit of one here.
PCI comes with heavy bus level reset requirement apart from AER and more.
From: Jason Gunthorpe <jgg@nvidia.com> Date: 2021-01-25 20:42:51
On Mon, Jan 25, 2021 at 12:22:13PM -0800, Edwin Peer wrote:
On Mon, Jan 25, 2021 at 11:59 AM Jason Gunthorpe [off-list ref] wrote:
quoted
Every writable data mandated by the PCI spec requires very expensive
on-die SRAM to store it.
That's an implementation decision. Nothing mandates that the state has
to physically exist in the same structure, only that reads and writes
are appropriately responded to.
Yes, PCI does mandate this, you can't store the data on the other side
of the PCI link, and if you can't cross the PCI link that only leaves
on die/package memory resources.
quoted
We've seen Intel drivers that show their SIOV ADIs don't even have a
register file and the only PCI presence is just a write-only doorbell
page in the BAR.
Right, but presumably it still needs to be at least a page. And,
nothing says your device's VF BAR protocol can't be equally simple.
Having VFs that are not self-contained would require significant
changing of current infrastructure, if we are going to change things
then let's fix everything instead of some half measure.
SRIOV really doesn't bring much benefits, it has lots of odd little
restrictions and strange lifecycle rules for what modern devices want
to do.
quoted
It is hard to argue a write-only register in a BAR page vs all the
SRIOV trappings when it comes to HW cost.
Say it's double the cost? I don't know that it is, but does that
warrant the additional complexity of SFs? We should try to quantify.
The actual complexity inside the kernel is small and the user
experience to manage them through devlink is dramatically better than
SRIOV. I think it is a win even if there isn't any HW savings.
Jason
From: Jason Gunthorpe <jgg@nvidia.com> Date: 2021-01-25 20:49:08
On Mon, Jan 25, 2021 at 11:23:56AM -0800, Edwin Peer wrote:
On Mon, Jan 25, 2021 at 5:22 AM Jason Gunthorpe [off-list ref] wrote:
quoted
SRIOV and SF's require a simple linear lookup to learn the "function"
because the BAR space is required to be linear.
Isn't this still true even for NumVF's > 256? Wouldn't there still be
a contiguous VF BAR space? Don't the routing IDs simply carry on
incrementing by stride, with each being assigned the next slice of the
shared BAR space?
I've never seen someone implement a NumVF > 256 by co-opting the bus
number.
Can Linux even assign more bus numbers to a port without firmware
help? Bus numbers are something that requires the root complex to be
aware of to setup routability.
Jason
On Mon, Jan 25, 2021 at 12:41 PM Jason Gunthorpe [off-list ref] wrote:
quoted
That's an implementation decision. Nothing mandates that the state has
to physically exist in the same structure, only that reads and writes
are appropriately responded to.
Yes, PCI does mandate this, you can't store the data on the other side
of the PCI link, and if you can't cross the PCI link that only leaves
on die/package memory resources.
Going off device was not what I was suggesting at all. I meant the
data doesn't necessarily need to be stored in the same physical
layout.
Take the config space for example. Many fields are read-only,
constant, always zero (for non-legacy) or reserved. These could be
generated by firmware in response to requests without ever being
backed by physical memory. Similarly, writes that imply a state change
can simply make that state change in whatever internal representation
is convenient for the device. One need only make sure the read back of
that state is appropriately reverse translated from your internal
representation. Similarly, if you're not exposing a bunch of optional
capabilities (the SFs don't), then you don't need the full config
space either, simply render the zeroes in response to the reads where
you have nothing to say.
That's not to say all implementations would be capable of this, only
that it is an implementation choice.
quoted
Right, but presumably it still needs to be at least a page. And,
nothing says your device's VF BAR protocol can't be equally simple.
Having VFs that are not self-contained would require significant
changing of current infrastructure, if we are going to change things
then let's fix everything instead of some half measure.
I don't understand what you mean by self-contained. If your device
only needs a doorbell write to trigger a DMA, no reason your VF BAR
needs to expose more. In practice, there will be some kind of
configuration channel too, but this doesn't necessarily need a lot of
room either (you don't have to represent configuration as a bulky
register file exposing every conceivable option, it could be a mailbox
with a command protocol).
The actual complexity inside the kernel is small and the user
experience to manage them through devlink is dramatically better than
SRIOV. I think it is a win even if there isn't any HW savings.
I'm not sure I agree with respect to user experience. Users are
familiar with SR-IOV. Now you impose a complementary model for
accomplishing the same goal (without solving all the problems, as per
the previous discussion, so we'll need to reinvent it again later).
Adds to confusion.
It's not easier for vendors either. Now we need to get users onto new
drivers to exploit it, with all the distribution lags that entails
(where existing drivers would work for SR-IOV). Some vendors will
support it, some won't, further adding to user confusion.
Regards,
Edwin Peer
From: Jason Gunthorpe <jgg@nvidia.com> Date: 2021-01-25 23:16:37
On Mon, Jan 25, 2021 at 01:23:04PM -0800, Edwin Peer wrote:
On Mon, Jan 25, 2021 at 12:41 PM Jason Gunthorpe [off-list ref] wrote:
quoted
quoted
That's an implementation decision. Nothing mandates that the state has
to physically exist in the same structure, only that reads and writes
are appropriately responded to.
Yes, PCI does mandate this, you can't store the data on the other side
of the PCI link, and if you can't cross the PCI link that only leaves
on die/package memory resources.
Going off device was not what I was suggesting at all. I meant the
data doesn't necessarily need to be stored in the same physical
layout.
It doesn't change anything, every writable bit must still be stored
on-die SRAM. You can compute the minimum by summing all writable and
read-reporting bits in the standard SRIOV config space.
Every bit used for SRIOV is a bit that couldn't be used to improve
device performance.
quoted
quoted
Right, but presumably it still needs to be at least a page. And,
nothing says your device's VF BAR protocol can't be equally simple.
Having VFs that are not self-contained would require significant
changing of current infrastructure, if we are going to change things
then let's fix everything instead of some half measure.
I don't understand what you mean by self-contained.
Self-contained means you can pass the VF to a VM with vfio and run a
driver on it. A VF that only has a write-only doorbell page probably
cannot be self contained.
In practice, there will be some kind of configuration channel too,
but this doesn't necessarily need a lot of room either
I don't know of any device that can run without configuration, even in
a VF case.
So this all costs SRAM too.
quoted
The actual complexity inside the kernel is small and the user
experience to manage them through devlink is dramatically better than
SRIOV. I think it is a win even if there isn't any HW savings.
I'm not sure I agree with respect to user experience. Users are
familiar with SR-IOV.
Sort of, SRIOV is a very bad fit for these sophisticated devices, and
no, users are not familiar with the weird intricate details of SR-IOV
in the context of very sophisticated reconfigurable HW like we are
seeing now.
Look at the other series about MSI-X reconfiguration for some colour
on where SRIOV runs into limits due to its specific design.
Now you impose a complementary model for accomplishing the same goal
(without solving all the problems, as per the previous discussion,
so we'll need to reinvent it again later).
I'm not sure what you are referring to.
It's not easier for vendors either. Now we need to get users onto new
drivers to exploit it, with all the distribution lags that entails
(where existing drivers would work for SR-IOV).
Compatability with existing drivers in a VM is a vendor
choice. Drivers can do a lot in a scalable way in hypervisor SW to
present whateve programming interface makes sense to the VM. Intel is
showing this approach in their IDXD SIOV ADI driver.
Some vendors will support it, some won't, further adding to user
confusion.
Such is the nature of all things, some vendors supported SRIOV and
other didn't too.
Jason
On Mon, Jan 25, 2021 at 5:22 AM Jason Gunthorpe [off-list ref] wrote:
SRIOV and SF's require a simple linear lookup to learn the "function"
because the BAR space is required to be linear.
Isn't this still true even for NumVF's > 256? Wouldn't there still be
a contiguous VF BAR space? Don't the routing IDs simply carry on
incrementing by stride, with each being assigned the next slice of the
shared BAR space?
Scaling a CAM to high sizes is physicaly infeasible, so all approaches
to scaling PCI functions go this road of having a single large BAR
space.
If the above is true, is there really a need to scale up CAM?
Regards,
Edwin Peer
From: Jakub Kicinski <kuba@kernel.org> Date: 2021-01-27 04:32:50
On Fri, 22 Jan 2021 11:36:44 -0800 Saeed Mahameed wrote:
This series form Parav was the theme of this mlx5 release cycle,
we've been waiting anxiously for the auxbus infrastructure to make it into
the kernel, and now as the auxbus is in and all the stars are aligned, I
can finally submit this patchset of the devlink and mlx5 subfunction support.
For more detailed information about subfunctions please see detailed tag
log below.
Are there any further comments, objections or actions that need to be
taken on this series, anyone?
Looks like the discussion has ended. Not knowing any users who would
need this I'd like to at least make sure we have reasonable consensus
among vendors.
On Tue, 2021-01-26 at 17:34 -0800, Jakub Kicinski wrote:
On Fri, 22 Jan 2021 11:36:44 -0800 Saeed Mahameed wrote:
quoted
This series form Parav was the theme of this mlx5 release cycle,
we've been waiting anxiously for the auxbus infrastructure to make
it into
the kernel, and now as the auxbus is in and all the stars are
aligned, I
can finally submit this patchset of the devlink and mlx5
subfunction support.
For more detailed information about subfunctions please see
detailed tag
log below.
Are there any further comments, objections or actions that need to be
taken on this series, anyone?
Looks like the discussion has ended. Not knowing any users who would
need this I'd like to at least make sure we have reasonable consensus
among vendors.
Hey Jakub, sorry to nag, but I need to make some progress, can we move
on please ? my submission queue is about to explode :) !
Thanks,
Saeed.
From: Jakub Kicinski <kuba@kernel.org> Date: 2021-01-29 00:12:14
On Thu, 28 Jan 2021 16:03:02 -0800 Saeed Mahameed wrote:
On Tue, 2021-01-26 at 17:34 -0800, Jakub Kicinski wrote:
quoted
On Fri, 22 Jan 2021 11:36:44 -0800 Saeed Mahameed wrote:
quoted
This series form Parav was the theme of this mlx5 release cycle,
we've been waiting anxiously for the auxbus infrastructure to make
it into
the kernel, and now as the auxbus is in and all the stars are
aligned, I
can finally submit this patchset of the devlink and mlx5
subfunction support.
For more detailed information about subfunctions please see
detailed tag
log below.
Are there any further comments, objections or actions that need to be
taken on this series, anyone?
Looks like the discussion has ended. Not knowing any users who would
need this I'd like to at least make sure we have reasonable consensus
among vendors.
Hey Jakub, sorry to nag, but I need to make some progress, can we move
on please ? my submission queue is about to explode :) !
I'll pull it in by the end of the day, just need to do some backports
and then it'll be on top of my list.
Hello:
This series was applied to netdev/net-next.git (refs/heads/master):
On Fri, 22 Jan 2021 11:36:45 -0800 you wrote:
From: Parav Pandit <redacted>
Prepare code to fill zero or more port function optional attributes.
Subsequent patch makes use of this to fill more port function
attributes.
Signed-off-by: Parav Pandit <redacted>
Reviewed-by: Jiri Pirko <redacted>
Reviewed-by: Vu Pham <redacted>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
[...]