* [iwl-next v1 00/15] ice: support devlink subfunctions
@ 2024-02-13 7:27 Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 01/15] ice: move devlink port code to a separate file Michal Swiatkowski
` (14 more replies)
0 siblings, 15 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Currently ice driver does not allow creating more than one networking
device per physical function. The only way to have more hardware backed
netdev is to use SR-IOV.
Following patchset adds support for devlink port API. For each new
pcisf type port, driver allocates new VSI, configures all resources
needed, including dynamically MSIX vectors, program rules and registers
new netdev.
This series supports only one Tx/Rx queue pair per subfunction.
Example commands:
devlink port add pci/0000:31:00.1 flavour pcisf pfnum 1 sfnum 1000
devlink port function set pci/0000:31:00.1/1 hw_addr 00:00:00:00:03:14
devlink port function set pci/0000:31:00.1/1 state active
devlink port function del pci/0000:31:00.1/1
Patch 1 -> Move devlink port related code to separate file
Patch 2-5 -> Add basic support for devlink subfunctions
Patch 6 -> Expose auxiliary bus devices for subfunctions
Patch 7 -> Expose auxiliary device sfnum attribute in sysfs
Patch 8-13 -> Add eswitch support for subfunctions
Michal Swiatkowski (8):
ice: store SF data in VSI struct
ice: store representor ID in bridge port
ice: create port representor for SF
ice: check if SF is ready in ethtool ops
ice: netdevice ops for SF representor
ice: support subfunction devlink Tx topology
ice: basic support for VLAN in subfunctions
ice: move ice_devlink.[ch] to devlink folder
Pawel Chmielewski (1):
ice: add subfunctions ethtool ops
Piotr Raczynski (6):
ice: move devlink port code to a separate file
ice: add new VSI type for subfunctions
ice: export ice ndo_ops functions
ice: add basic devlink subfunctions support
ice: add subfunction aux driver support
ice: add auxiliary device sfnum attribute
drivers/net/ethernet/intel/ice/Makefile | 6 +-
.../intel/ice/{ => devlink}/ice_devlink.c | 468 +--------
.../intel/ice/{ => devlink}/ice_devlink.h | 3 +
.../intel/ice/devlink/ice_devlink_port.c | 986 ++++++++++++++++++
.../intel/ice/devlink/ice_devlink_port.h | 49 +
drivers/net/ethernet/intel/ice/ice.h | 19 +-
drivers/net/ethernet/intel/ice/ice_base.c | 5 +-
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 3 +-
drivers/net/ethernet/intel/ice/ice_eswitch.c | 84 +-
drivers/net/ethernet/intel/ice/ice_eswitch.h | 22 +-
.../net/ethernet/intel/ice/ice_eswitch_br.c | 4 +-
.../net/ethernet/intel/ice/ice_eswitch_br.h | 1 +
drivers/net/ethernet/intel/ice/ice_ethtool.c | 43 +-
drivers/net/ethernet/intel/ice/ice_lib.c | 53 +-
drivers/net/ethernet/intel/ice/ice_lib.h | 3 +
drivers/net/ethernet/intel/ice/ice_main.c | 70 +-
drivers/net/ethernet/intel/ice/ice_repr.c | 197 ++--
drivers/net/ethernet/intel/ice/ice_repr.h | 23 +-
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 354 +++++++
drivers/net/ethernet/intel/ice/ice_sf_eth.h | 36 +
.../ethernet/intel/ice/ice_sf_vsi_vlan_ops.c | 21 +
.../ethernet/intel/ice/ice_sf_vsi_vlan_ops.h | 13 +
drivers/net/ethernet/intel/ice/ice_sriov.c | 4 +-
drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
drivers/net/ethernet/intel/ice/ice_type.h | 1 +
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +-
.../net/ethernet/intel/ice/ice_vsi_vlan_ops.c | 4 +
drivers/net/ethernet/intel/ice/ice_xsk.c | 2 +-
28 files changed, 1902 insertions(+), 578 deletions(-)
rename drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.c (80%)
rename drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.h (90%)
create mode 100644 drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
create mode 100644 drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.c
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.h
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.c
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.h
--
2.42.0
^ permalink raw reply [flat|nested] 36+ messages in thread
* [iwl-next v1 01/15] ice: move devlink port code to a separate file
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 02/15] ice: add new VSI type for subfunctions Michal Swiatkowski
` (13 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Keep devlink related code in a separate file. More devlink port code and
handlers will be added here for other port operations.
On this occasion, remove unnecessary ice_devlink.h include in ice_lib.c.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/Makefile | 2 +
.../intel/ice/devlink/ice_devlink_port.c | 434 ++++++++++++++++++
.../intel/ice/devlink/ice_devlink_port.h | 12 +
drivers/net/ethernet/intel/ice/ice_devlink.c | 423 -----------------
drivers/net/ethernet/intel/ice/ice_lib.c | 1 -
drivers/net/ethernet/intel/ice/ice_main.c | 1 +
drivers/net/ethernet/intel/ice/ice_repr.c | 1 +
7 files changed, 450 insertions(+), 424 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
create mode 100644 drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index cddd82d4ca0f..cd4ab46d72a7 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -5,6 +5,7 @@
# Makefile for the Intel(R) Ethernet Connection E800 Series Linux Driver
#
+subdir-ccflags-y += -I$(src)
obj-$(CONFIG_ICE) += ice.o
ice-y := ice_main.o \
@@ -29,6 +30,7 @@ ice-y := ice_main.o \
ice_flow.o \
ice_idc.o \
ice_devlink.o \
+ devlink/ice_devlink_port.o \
ice_ddp.o \
ice_fw_update.o \
ice_lag.o \
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
new file mode 100644
index 000000000000..c8c823467fcf
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020, Intel Corporation. */
+
+#include <linux/vmalloc.h>
+
+#include "ice.h"
+#include "ice_lib.h"
+#include "ice_devlink.h"
+#include "ice_devlink_port.h"
+#include "ice_eswitch.h"
+#include "ice_fw_update.h"
+#include "ice_dcb_lib.h"
+
+static int ice_active_port_option = -1;
+
+/**
+ * ice_devlink_port_opt_speed_str - convert speed to a string
+ * @speed: speed value
+ */
+static const char *ice_devlink_port_opt_speed_str(u8 speed)
+{
+ switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
+ case ICE_AQC_PORT_OPT_MAX_LANE_100M:
+ return "0.1";
+ case ICE_AQC_PORT_OPT_MAX_LANE_1G:
+ return "1";
+ case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
+ return "2.5";
+ case ICE_AQC_PORT_OPT_MAX_LANE_5G:
+ return "5";
+ case ICE_AQC_PORT_OPT_MAX_LANE_10G:
+ return "10";
+ case ICE_AQC_PORT_OPT_MAX_LANE_25G:
+ return "25";
+ case ICE_AQC_PORT_OPT_MAX_LANE_50G:
+ return "50";
+ case ICE_AQC_PORT_OPT_MAX_LANE_100G:
+ return "100";
+ }
+
+ return "-";
+}
+
+#define ICE_PORT_OPT_DESC_LEN 50
+/**
+ * ice_devlink_port_options_print - Print available port split options
+ * @pf: the PF to print split port options
+ *
+ * Prints a table with available port split options and max port speeds
+ */
+static void ice_devlink_port_options_print(struct ice_pf *pf)
+{
+ u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
+ struct ice_aqc_get_port_options_elem *options, *opt;
+ struct device *dev = ice_pf_to_dev(pf);
+ bool active_valid, pending_valid;
+ char desc[ICE_PORT_OPT_DESC_LEN];
+ const char *str;
+ int status;
+
+ options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
+ sizeof(*options), GFP_KERNEL);
+ if (!options)
+ return;
+
+ for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
+ opt = options + i * ICE_AQC_PORT_OPT_MAX;
+ options_count = ICE_AQC_PORT_OPT_MAX;
+ active_valid = 0;
+
+ status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
+ i, true, &active_idx,
+ &active_valid, &pending_idx,
+ &pending_valid);
+ if (status) {
+ dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
+ i, status);
+ goto err;
+ }
+ }
+
+ dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
+ dev_dbg(dev, "Status Split Quad 0 Quad 1\n");
+ dev_dbg(dev, " count L0 L1 L2 L3 L4 L5 L6 L7\n");
+
+ for (i = 0; i < options_count; i++) {
+ cnt = 0;
+
+ if (i == ice_active_port_option)
+ str = "Active";
+ else if ((i == pending_idx) && pending_valid)
+ str = "Pending";
+ else
+ str = "";
+
+ cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+ "%-8s", str);
+
+ cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+ "%-6u", options[i].pmd);
+
+ for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
+ speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
+ str = ice_devlink_port_opt_speed_str(speed);
+ cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+ "%3s ", str);
+ }
+
+ dev_dbg(dev, "%s\n", desc);
+ }
+
+err:
+ kfree(options);
+}
+
+/**
+ * ice_devlink_aq_set_port_option - Send set port option admin queue command
+ * @pf: the PF to print split port options
+ * @option_idx: selected port option
+ * @extack: extended netdev ack structure
+ *
+ * Sends set port option admin queue command with selected port option and
+ * calls NVM write activate.
+ */
+static int
+ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
+ struct netlink_ext_ack *extack)
+{
+ struct device *dev = ice_pf_to_dev(pf);
+ int status;
+
+ status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
+ if (status) {
+ dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
+ status, pf->hw.adminq.sq_last_status);
+ NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
+ return -EIO;
+ }
+
+ status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
+ if (status) {
+ dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
+ status, pf->hw.adminq.sq_last_status);
+ NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
+ return -EIO;
+ }
+
+ status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
+ if (status) {
+ dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
+ status, pf->hw.adminq.sq_last_status);
+ NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
+ ice_release_nvm(&pf->hw);
+ return -EIO;
+ }
+
+ ice_release_nvm(&pf->hw);
+
+ NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
+ return 0;
+}
+
+/**
+ * ice_devlink_port_split - .port_split devlink handler
+ * @devlink: devlink instance structure
+ * @port: devlink port structure
+ * @count: number of ports to split to
+ * @extack: extended netdev ack structure
+ *
+ * Callback for the devlink .port_split operation.
+ *
+ * Unfortunately, the devlink expression of available options is limited
+ * to just a number, so search for an FW port option which supports
+ * the specified number. As there could be multiple FW port options with
+ * the same port split count, allow switching between them. When the same
+ * port split count request is issued again, switch to the next FW port
+ * option with the same port split count.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
+ unsigned int count, struct netlink_ext_ack *extack)
+{
+ struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
+ u8 i, j, active_idx, pending_idx, new_option;
+ struct ice_pf *pf = devlink_priv(devlink);
+ u8 option_count = ICE_AQC_PORT_OPT_MAX;
+ struct device *dev = ice_pf_to_dev(pf);
+ bool active_valid, pending_valid;
+ int status;
+
+ status = ice_aq_get_port_options(&pf->hw, options, &option_count,
+ 0, true, &active_idx, &active_valid,
+ &pending_idx, &pending_valid);
+ if (status) {
+ dev_dbg(dev, "Couldn't read port split options, err = %d\n",
+ status);
+ NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
+ return -EIO;
+ }
+
+ new_option = ICE_AQC_PORT_OPT_MAX;
+ active_idx = pending_valid ? pending_idx : active_idx;
+ for (i = 1; i <= option_count; i++) {
+ /* In order to allow switching between FW port options with
+ * the same port split count, search for a new option starting
+ * from the active/pending option (with array wrap around).
+ */
+ j = (active_idx + i) % option_count;
+
+ if (count == options[j].pmd) {
+ new_option = j;
+ break;
+ }
+ }
+
+ if (new_option == active_idx) {
+ dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
+ count);
+ NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
+ ice_devlink_port_options_print(pf);
+ return -EINVAL;
+ }
+
+ if (new_option == ICE_AQC_PORT_OPT_MAX) {
+ dev_dbg(dev, "request to split: count: %u not found\n", count);
+ NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
+ ice_devlink_port_options_print(pf);
+ return -EINVAL;
+ }
+
+ status = ice_devlink_aq_set_port_option(pf, new_option, extack);
+ if (status)
+ return status;
+
+ ice_devlink_port_options_print(pf);
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_unsplit - .port_unsplit devlink handler
+ * @devlink: devlink instance structure
+ * @port: devlink port structure
+ * @extack: extended netdev ack structure
+ *
+ * Callback for the devlink .port_unsplit operation.
+ * Calls ice_devlink_port_split with split count set to 1.
+ * There could be no FW option available with split count 1.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+
+static int
+ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
+ struct netlink_ext_ack *extack)
+{
+ return ice_devlink_port_split(devlink, port, 1, extack);
+}
+
+/**
+ * ice_devlink_set_port_split_options - Set port split options
+ * @pf: the PF to set port split options
+ * @attrs: devlink attributes
+ *
+ * Sets devlink port split options based on available FW port options
+ */
+static void
+ice_devlink_set_port_split_options(struct ice_pf *pf,
+ struct devlink_port_attrs *attrs)
+{
+ struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
+ u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
+ bool active_valid, pending_valid;
+ int status;
+
+ status = ice_aq_get_port_options(&pf->hw, options, &option_count,
+ 0, true, &active_idx, &active_valid,
+ &pending_idx, &pending_valid);
+ if (status) {
+ dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
+ status);
+ return;
+ }
+
+ /* find the biggest available port split count */
+ for (i = 0; i < option_count; i++)
+ attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
+
+ attrs->splittable = attrs->lanes ? 1 : 0;
+ ice_active_port_option = active_idx;
+}
+
+static const struct devlink_port_ops ice_devlink_port_ops = {
+ .port_split = ice_devlink_port_split,
+ .port_unsplit = ice_devlink_port_unsplit,
+};
+
+/**
+ * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
+ * @pf: the PF to create a devlink port for
+ * @ppid: struct with switch id information
+ */
+static void
+ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
+{
+ struct pci_dev *pdev = pf->pdev;
+ u64 id;
+
+ id = pci_get_dsn(pdev);
+
+ ppid->id_len = sizeof(id);
+ put_unaligned_be64(id, &ppid->id);
+}
+
+/**
+ * ice_devlink_create_pf_port - Create a devlink port for this PF
+ * @pf: the PF to create a devlink port for
+ *
+ * Create and register a devlink_port for this PF.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int ice_devlink_create_pf_port(struct ice_pf *pf)
+{
+ struct devlink_port_attrs attrs = {};
+ struct devlink_port *devlink_port;
+ struct devlink *devlink;
+ struct ice_vsi *vsi;
+ struct device *dev;
+ int err;
+
+ dev = ice_pf_to_dev(pf);
+
+ devlink_port = &pf->devlink_port;
+
+ vsi = ice_get_main_vsi(pf);
+ if (!vsi)
+ return -EIO;
+
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+ attrs.phys.port_number = pf->hw.bus.func;
+
+ /* As FW supports only port split options for whole device,
+ * set port split options only for first PF.
+ */
+ if (pf->hw.pf_id == 0)
+ ice_devlink_set_port_split_options(pf, &attrs);
+
+ ice_devlink_set_switch_id(pf, &attrs.switch_id);
+
+ devlink_port_attrs_set(devlink_port, &attrs);
+ devlink = priv_to_devlink(pf);
+
+ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
+ &ice_devlink_port_ops);
+ if (err) {
+ dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
+ pf->hw.pf_id, err);
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
+ * @pf: the PF to cleanup
+ *
+ * Unregisters the devlink_port structure associated with this PF.
+ */
+void ice_devlink_destroy_pf_port(struct ice_pf *pf)
+{
+ devl_port_unregister(&pf->devlink_port);
+}
+
+/**
+ * ice_devlink_create_vf_port - Create a devlink port for this VF
+ * @vf: the VF to create a port for
+ *
+ * Create and register a devlink_port for this VF.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int ice_devlink_create_vf_port(struct ice_vf *vf)
+{
+ struct devlink_port_attrs attrs = {};
+ struct devlink_port *devlink_port;
+ struct devlink *devlink;
+ struct ice_vsi *vsi;
+ struct device *dev;
+ struct ice_pf *pf;
+ int err;
+
+ pf = vf->pf;
+ dev = ice_pf_to_dev(pf);
+ devlink_port = &vf->devlink_port;
+
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi)
+ return -EINVAL;
+
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
+ attrs.pci_vf.pf = pf->hw.bus.func;
+ attrs.pci_vf.vf = vf->vf_id;
+
+ ice_devlink_set_switch_id(pf, &attrs.switch_id);
+
+ devlink_port_attrs_set(devlink_port, &attrs);
+ devlink = priv_to_devlink(pf);
+
+ err = devlink_port_register(devlink, devlink_port, vsi->idx);
+ if (err) {
+ dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
+ vf->vf_id, err);
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
+ * @vf: the VF to cleanup
+ *
+ * Unregisters the devlink_port structure associated with this VF.
+ */
+void ice_devlink_destroy_vf_port(struct ice_vf *vf)
+{
+ devl_rate_leaf_destroy(&vf->devlink_port);
+ devlink_port_unregister(&vf->devlink_port);
+}
+
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
new file mode 100644
index 000000000000..983d136f5ddf
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2023, Intel Corporation. */
+
+#ifndef _ICE_DEVLINK_PORT_H_
+#define _ICE_DEVLINK_PORT_H_
+
+int ice_devlink_create_pf_port(struct ice_pf *pf);
+void ice_devlink_destroy_pf_port(struct ice_pf *pf);
+int ice_devlink_create_vf_port(struct ice_vf *vf);
+void ice_devlink_destroy_vf_port(struct ice_vf *vf);
+
+#endif /* _ICE_DEVLINK_PORT_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index cc717175178b..e5f275ca82e5 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -10,8 +10,6 @@
#include "ice_fw_update.h"
#include "ice_dcb_lib.h"
-static int ice_active_port_option = -1;
-
/* context for devlink info version reporting */
struct ice_info_ctx {
char buf[128];
@@ -525,251 +523,6 @@ ice_devlink_reload_empr_finish(struct ice_pf *pf,
return 0;
}
-/**
- * ice_devlink_port_opt_speed_str - convert speed to a string
- * @speed: speed value
- */
-static const char *ice_devlink_port_opt_speed_str(u8 speed)
-{
- switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
- case ICE_AQC_PORT_OPT_MAX_LANE_100M:
- return "0.1";
- case ICE_AQC_PORT_OPT_MAX_LANE_1G:
- return "1";
- case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
- return "2.5";
- case ICE_AQC_PORT_OPT_MAX_LANE_5G:
- return "5";
- case ICE_AQC_PORT_OPT_MAX_LANE_10G:
- return "10";
- case ICE_AQC_PORT_OPT_MAX_LANE_25G:
- return "25";
- case ICE_AQC_PORT_OPT_MAX_LANE_50G:
- return "50";
- case ICE_AQC_PORT_OPT_MAX_LANE_100G:
- return "100";
- }
-
- return "-";
-}
-
-#define ICE_PORT_OPT_DESC_LEN 50
-/**
- * ice_devlink_port_options_print - Print available port split options
- * @pf: the PF to print split port options
- *
- * Prints a table with available port split options and max port speeds
- */
-static void ice_devlink_port_options_print(struct ice_pf *pf)
-{
- u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
- struct ice_aqc_get_port_options_elem *options, *opt;
- struct device *dev = ice_pf_to_dev(pf);
- bool active_valid, pending_valid;
- char desc[ICE_PORT_OPT_DESC_LEN];
- const char *str;
- int status;
-
- options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
- sizeof(*options), GFP_KERNEL);
- if (!options)
- return;
-
- for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
- opt = options + i * ICE_AQC_PORT_OPT_MAX;
- options_count = ICE_AQC_PORT_OPT_MAX;
- active_valid = 0;
-
- status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
- i, true, &active_idx,
- &active_valid, &pending_idx,
- &pending_valid);
- if (status) {
- dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
- i, status);
- goto err;
- }
- }
-
- dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
- dev_dbg(dev, "Status Split Quad 0 Quad 1\n");
- dev_dbg(dev, " count L0 L1 L2 L3 L4 L5 L6 L7\n");
-
- for (i = 0; i < options_count; i++) {
- cnt = 0;
-
- if (i == ice_active_port_option)
- str = "Active";
- else if ((i == pending_idx) && pending_valid)
- str = "Pending";
- else
- str = "";
-
- cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
- "%-8s", str);
-
- cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
- "%-6u", options[i].pmd);
-
- for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
- speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
- str = ice_devlink_port_opt_speed_str(speed);
- cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
- "%3s ", str);
- }
-
- dev_dbg(dev, "%s\n", desc);
- }
-
-err:
- kfree(options);
-}
-
-/**
- * ice_devlink_aq_set_port_option - Send set port option admin queue command
- * @pf: the PF to print split port options
- * @option_idx: selected port option
- * @extack: extended netdev ack structure
- *
- * Sends set port option admin queue command with selected port option and
- * calls NVM write activate.
- */
-static int
-ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
- struct netlink_ext_ack *extack)
-{
- struct device *dev = ice_pf_to_dev(pf);
- int status;
-
- status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
- if (status) {
- dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
- status, pf->hw.adminq.sq_last_status);
- NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
- return -EIO;
- }
-
- status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
- if (status) {
- dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
- status, pf->hw.adminq.sq_last_status);
- NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
- return -EIO;
- }
-
- status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
- if (status) {
- dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
- status, pf->hw.adminq.sq_last_status);
- NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
- ice_release_nvm(&pf->hw);
- return -EIO;
- }
-
- ice_release_nvm(&pf->hw);
-
- NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
- return 0;
-}
-
-/**
- * ice_devlink_port_split - .port_split devlink handler
- * @devlink: devlink instance structure
- * @port: devlink port structure
- * @count: number of ports to split to
- * @extack: extended netdev ack structure
- *
- * Callback for the devlink .port_split operation.
- *
- * Unfortunately, the devlink expression of available options is limited
- * to just a number, so search for an FW port option which supports
- * the specified number. As there could be multiple FW port options with
- * the same port split count, allow switching between them. When the same
- * port split count request is issued again, switch to the next FW port
- * option with the same port split count.
- *
- * Return: zero on success or an error code on failure.
- */
-static int
-ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
- unsigned int count, struct netlink_ext_ack *extack)
-{
- struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
- u8 i, j, active_idx, pending_idx, new_option;
- struct ice_pf *pf = devlink_priv(devlink);
- u8 option_count = ICE_AQC_PORT_OPT_MAX;
- struct device *dev = ice_pf_to_dev(pf);
- bool active_valid, pending_valid;
- int status;
-
- status = ice_aq_get_port_options(&pf->hw, options, &option_count,
- 0, true, &active_idx, &active_valid,
- &pending_idx, &pending_valid);
- if (status) {
- dev_dbg(dev, "Couldn't read port split options, err = %d\n",
- status);
- NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
- return -EIO;
- }
-
- new_option = ICE_AQC_PORT_OPT_MAX;
- active_idx = pending_valid ? pending_idx : active_idx;
- for (i = 1; i <= option_count; i++) {
- /* In order to allow switching between FW port options with
- * the same port split count, search for a new option starting
- * from the active/pending option (with array wrap around).
- */
- j = (active_idx + i) % option_count;
-
- if (count == options[j].pmd) {
- new_option = j;
- break;
- }
- }
-
- if (new_option == active_idx) {
- dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
- count);
- NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
- ice_devlink_port_options_print(pf);
- return -EINVAL;
- }
-
- if (new_option == ICE_AQC_PORT_OPT_MAX) {
- dev_dbg(dev, "request to split: count: %u not found\n", count);
- NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
- ice_devlink_port_options_print(pf);
- return -EINVAL;
- }
-
- status = ice_devlink_aq_set_port_option(pf, new_option, extack);
- if (status)
- return status;
-
- ice_devlink_port_options_print(pf);
-
- return 0;
-}
-
-/**
- * ice_devlink_port_unsplit - .port_unsplit devlink handler
- * @devlink: devlink instance structure
- * @port: devlink port structure
- * @extack: extended netdev ack structure
- *
- * Callback for the devlink .port_unsplit operation.
- * Calls ice_devlink_port_split with split count set to 1.
- * There could be no FW option available with split count 1.
- *
- * Return: zero on success or an error code on failure.
- */
-static int
-ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
- struct netlink_ext_ack *extack)
-{
- return ice_devlink_port_split(devlink, port, 1, extack);
-}
-
/**
* ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree
* @pf: pf struct
@@ -1674,23 +1427,6 @@ void ice_devlink_unregister(struct ice_pf *pf)
devlink_unregister(priv_to_devlink(pf));
}
-/**
- * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
- * @pf: the PF to create a devlink port for
- * @ppid: struct with switch id information
- */
-static void
-ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
-{
- struct pci_dev *pdev = pf->pdev;
- u64 id;
-
- id = pci_get_dsn(pdev);
-
- ppid->id_len = sizeof(id);
- put_unaligned_be64(id, &ppid->id);
-}
-
int ice_devlink_register_params(struct ice_pf *pf)
{
struct devlink *devlink = priv_to_devlink(pf);
@@ -1705,165 +1441,6 @@ void ice_devlink_unregister_params(struct ice_pf *pf)
ARRAY_SIZE(ice_devlink_params));
}
-/**
- * ice_devlink_set_port_split_options - Set port split options
- * @pf: the PF to set port split options
- * @attrs: devlink attributes
- *
- * Sets devlink port split options based on available FW port options
- */
-static void
-ice_devlink_set_port_split_options(struct ice_pf *pf,
- struct devlink_port_attrs *attrs)
-{
- struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
- u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
- bool active_valid, pending_valid;
- int status;
-
- status = ice_aq_get_port_options(&pf->hw, options, &option_count,
- 0, true, &active_idx, &active_valid,
- &pending_idx, &pending_valid);
- if (status) {
- dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
- status);
- return;
- }
-
- /* find the biggest available port split count */
- for (i = 0; i < option_count; i++)
- attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
-
- attrs->splittable = attrs->lanes ? 1 : 0;
- ice_active_port_option = active_idx;
-}
-
-static const struct devlink_port_ops ice_devlink_port_ops = {
- .port_split = ice_devlink_port_split,
- .port_unsplit = ice_devlink_port_unsplit,
-};
-
-/**
- * ice_devlink_create_pf_port - Create a devlink port for this PF
- * @pf: the PF to create a devlink port for
- *
- * Create and register a devlink_port for this PF.
- * This function has to be called under devl_lock.
- *
- * Return: zero on success or an error code on failure.
- */
-int ice_devlink_create_pf_port(struct ice_pf *pf)
-{
- struct devlink_port_attrs attrs = {};
- struct devlink_port *devlink_port;
- struct devlink *devlink;
- struct ice_vsi *vsi;
- struct device *dev;
- int err;
-
- devlink = priv_to_devlink(pf);
-
- dev = ice_pf_to_dev(pf);
-
- devlink_port = &pf->devlink_port;
-
- vsi = ice_get_main_vsi(pf);
- if (!vsi)
- return -EIO;
-
- attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
- attrs.phys.port_number = pf->hw.bus.func;
-
- /* As FW supports only port split options for whole device,
- * set port split options only for first PF.
- */
- if (pf->hw.pf_id == 0)
- ice_devlink_set_port_split_options(pf, &attrs);
-
- ice_devlink_set_switch_id(pf, &attrs.switch_id);
-
- devlink_port_attrs_set(devlink_port, &attrs);
-
- err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
- &ice_devlink_port_ops);
- if (err) {
- dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
- pf->hw.pf_id, err);
- return err;
- }
-
- return 0;
-}
-
-/**
- * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
- * @pf: the PF to cleanup
- *
- * Unregisters the devlink_port structure associated with this PF.
- * This function has to be called under devl_lock.
- */
-void ice_devlink_destroy_pf_port(struct ice_pf *pf)
-{
- devl_port_unregister(&pf->devlink_port);
-}
-
-/**
- * ice_devlink_create_vf_port - Create a devlink port for this VF
- * @vf: the VF to create a port for
- *
- * Create and register a devlink_port for this VF.
- *
- * Return: zero on success or an error code on failure.
- */
-int ice_devlink_create_vf_port(struct ice_vf *vf)
-{
- struct devlink_port_attrs attrs = {};
- struct devlink_port *devlink_port;
- struct devlink *devlink;
- struct ice_vsi *vsi;
- struct device *dev;
- struct ice_pf *pf;
- int err;
-
- pf = vf->pf;
- dev = ice_pf_to_dev(pf);
- devlink_port = &vf->devlink_port;
-
- vsi = ice_get_vf_vsi(vf);
- if (!vsi)
- return -EINVAL;
-
- attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
- attrs.pci_vf.pf = pf->hw.bus.func;
- attrs.pci_vf.vf = vf->vf_id;
-
- ice_devlink_set_switch_id(pf, &attrs.switch_id);
-
- devlink_port_attrs_set(devlink_port, &attrs);
- devlink = priv_to_devlink(pf);
-
- err = devlink_port_register(devlink, devlink_port, vsi->idx);
- if (err) {
- dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
- vf->vf_id, err);
- return err;
- }
-
- return 0;
-}
-
-/**
- * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
- * @vf: the VF to cleanup
- *
- * Unregisters the devlink_port structure associated with this VF.
- */
-void ice_devlink_destroy_vf_port(struct ice_vf *vf)
-{
- devl_rate_leaf_destroy(&vf->devlink_port);
- devlink_port_unregister(&vf->devlink_port);
-}
-
#define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024)
static const struct devlink_region_ops ice_nvm_region_ops;
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 718cb8df7853..b2d7e3c0edcc 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -7,7 +7,6 @@
#include "ice_lib.h"
#include "ice_fltr.h"
#include "ice_dcb_lib.h"
-#include "ice_devlink.h"
#include "ice_vsi_vlan_ops.h"
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 824732f16112..fbf1d56c50e9 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -15,6 +15,7 @@
#include "ice_dcb_nl.h"
#include "ice_devlink.h"
#include "ice_hwmon.h"
+#include "devlink/ice_devlink_port.h"
/* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
* ice tracepoint functions. This must be done exactly once across the
* ice driver.
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 2429727d5562..7d066ea0caa0 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -4,6 +4,7 @@
#include "ice.h"
#include "ice_eswitch.h"
#include "ice_devlink.h"
+#include "devlink/ice_devlink_port.h"
#include "ice_sriov.h"
#include "ice_tc_lib.h"
#include "ice_dcb_lib.h"
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 02/15] ice: add new VSI type for subfunctions
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 01/15] ice: move devlink port code to a separate file Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 03/15] ice: export ice ndo_ops functions Michal Swiatkowski
` (12 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Add required plumbing for new VSI type dedicated to devlink subfunctions.
Make sure that the vsi is properly configured and destroyed. Also allow
loading XDP and AF_XDP sockets.
The first implementation of devlink subfunctions supports only one Tx/Rx
queue pair per given subfunction.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_base.c | 5 +++-
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 1 +
drivers/net/ethernet/intel/ice/ice_lib.c | 25 ++++++++++++++++++--
drivers/net/ethernet/intel/ice/ice_main.c | 7 ++++--
drivers/net/ethernet/intel/ice/ice_type.h | 1 +
drivers/net/ethernet/intel/ice/ice_xsk.c | 2 +-
6 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index 79485c944c9d..8ca944d0fa51 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -331,6 +331,9 @@ ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf
tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf->vf_id;
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF;
break;
+ case ICE_VSI_SF:
+ tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
+ break;
default:
return;
}
@@ -527,7 +530,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
ring->rx_buf_len = ring->vsi->rx_buf_len;
- if (ring->vsi->type == ICE_VSI_PF) {
+ if (ring->vsi->type == ICE_VSI_PF || ring->vsi->type == ICE_VSI_SF) {
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
ring->q_index,
diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
index ceb17c004d79..63ce4920de4e 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
@@ -187,6 +187,7 @@ void ice_vsi_set_dcb_tc_cfg(struct ice_vsi *vsi)
vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg);
break;
case ICE_VSI_CHNL:
+ case ICE_VSI_SF:
vsi->tc_cfg.ena_tc = BIT(ice_get_first_droptc(vsi));
vsi->tc_cfg.numtc = 1;
break;
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index b2d7e3c0edcc..572d9b345f66 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -20,6 +20,8 @@ const char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
return "ICE_VSI_PF";
case ICE_VSI_VF:
return "ICE_VSI_VF";
+ case ICE_VSI_SF:
+ return "ICE_VSI_SF";
case ICE_VSI_CTRL:
return "ICE_VSI_CTRL";
case ICE_VSI_CHNL:
@@ -141,6 +143,7 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
{
switch (vsi->type) {
case ICE_VSI_PF:
+ case ICE_VSI_SF:
case ICE_VSI_CTRL:
case ICE_VSI_LB:
/* a user could change the values of num_[tr]x_desc using
@@ -207,6 +210,12 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
max_t(int, vsi->alloc_rxq,
vsi->alloc_txq));
break;
+ case ICE_VSI_SF:
+ vsi->alloc_txq = 1;
+ vsi->alloc_rxq = 1;
+ vsi->num_q_vectors = 1;
+ vsi->irq_dyn_alloc = true;
+ break;
case ICE_VSI_VF:
if (vf->num_req_qs)
vf->num_vf_qs = vf->num_req_qs;
@@ -566,6 +575,7 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
switch (vsi->type) {
case ICE_VSI_PF:
+ case ICE_VSI_SF:
/* Setup default MSIX irq handler for VSI */
vsi->irq_handler = ice_msix_clean_rings;
break;
@@ -894,6 +904,11 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
max_rss_size);
vsi->rss_lut_type = ICE_LUT_PF;
break;
+ case ICE_VSI_SF:
+ vsi->rss_table_size = ICE_LUT_VSI_SIZE;
+ vsi->rss_size = min_t(u16, num_online_cpus(), max_rss_size);
+ vsi->rss_lut_type = ICE_LUT_VSI;
+ break;
case ICE_VSI_VF:
/* VF VSI will get a small RSS table.
* For VSI_LUT, LUT size should be set to 64 bytes.
@@ -1141,6 +1156,7 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
break;
case ICE_VSI_VF:
+ case ICE_VSI_SF:
/* VF VSI will gets a small RSS table which is a VSI LUT type */
lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
break;
@@ -1219,6 +1235,7 @@ static int ice_vsi_init(struct ice_vsi *vsi, u32 vsi_flags)
case ICE_VSI_PF:
ctxt->flags = ICE_AQ_VSI_TYPE_PF;
break;
+ case ICE_VSI_SF:
case ICE_VSI_CHNL:
ctxt->flags = ICE_AQ_VSI_TYPE_VMDQ2;
break;
@@ -2063,6 +2080,7 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
case ICE_VSI_CHNL:
case ICE_VSI_LB:
case ICE_VSI_PF:
+ case ICE_VSI_SF:
max_agg_nodes = ICE_MAX_PF_AGG_NODES;
agg_node_id_start = ICE_PF_AGG_NODE_ID_START;
agg_node_iter = &pf->pf_agg_node[0];
@@ -2234,6 +2252,7 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
switch (vsi->type) {
case ICE_VSI_CTRL:
+ case ICE_VSI_SF:
case ICE_VSI_PF:
ret = ice_vsi_alloc_q_vectors(vsi);
if (ret)
@@ -2625,7 +2644,8 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked)
clear_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
- if (vsi->netdev && vsi->type == ICE_VSI_PF) {
+ if (vsi->netdev && (vsi->type == ICE_VSI_PF ||
+ vsi->type == ICE_VSI_SF)) {
if (netif_running(vsi->netdev)) {
if (!locked)
rtnl_lock();
@@ -2654,7 +2674,8 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
set_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
- if (vsi->type == ICE_VSI_PF && vsi->netdev) {
+ if (vsi->netdev && (vsi->type == ICE_VSI_PF ||
+ vsi->type == ICE_VSI_SF)) {
if (netif_running(vsi->netdev)) {
if (!locked)
rtnl_lock();
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index fbf1d56c50e9..ebab03b16596 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -2911,6 +2911,9 @@ int ice_vsi_determine_xdp_res(struct ice_vsi *vsi)
if (avail < cpus / 2)
return -ENOMEM;
+ if (vsi->type == ICE_VSI_SF)
+ avail = vsi->alloc_txq;
+
vsi->num_xdp_txq = min_t(u16, avail, cpus);
if (vsi->num_xdp_txq < cpus)
@@ -3026,8 +3029,8 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)
struct ice_netdev_priv *np = netdev_priv(dev);
struct ice_vsi *vsi = np->vsi;
- if (vsi->type != ICE_VSI_PF) {
- NL_SET_ERR_MSG_MOD(xdp->extack, "XDP can be loaded only on PF VSI");
+ if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_SF) {
+ NL_SET_ERR_MSG_MOD(xdp->extack, "XDP can be loaded only on PF or SF VSI");
return -EINVAL;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 32386aecd6c5..636c30487cc8 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -150,6 +150,7 @@ enum ice_vsi_type {
ICE_VSI_CTRL = 3, /* equates to ICE_VSI_PF with 1 queue pair */
ICE_VSI_CHNL = 4,
ICE_VSI_LB = 6,
+ ICE_VSI_SF = 9,
};
struct ice_link_status {
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index 8a051420fa19..fe1726526e4f 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -287,7 +287,7 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
{
int err;
- if (vsi->type != ICE_VSI_PF)
+ if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_SF)
return -EINVAL;
if (qid >= vsi->netdev->real_num_rx_queues ||
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 03/15] ice: export ice ndo_ops functions
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 01/15] ice: move devlink port code to a separate file Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 02/15] ice: add new VSI type for subfunctions Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 04/15] ice: add basic devlink subfunctions support Michal Swiatkowski
` (11 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Make some of the netdevice_ops functions visible from outside for
another VSI type created netdev.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice.h | 8 +++++
drivers/net/ethernet/intel/ice/ice_lib.c | 22 ++++++++++++++
drivers/net/ethernet/intel/ice/ice_lib.h | 1 +
drivers/net/ethernet/intel/ice/ice_main.c | 37 ++++-------------------
4 files changed, 37 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index c4127d5f2be3..c40fc339a604 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -979,6 +979,14 @@ void ice_unload(struct ice_pf *pf);
void ice_adv_lnk_speed_maps_init(void);
int ice_init_dev(struct ice_pf *pf);
void ice_deinit_dev(struct ice_pf *pf);
+int ice_change_mtu(struct net_device *netdev, int new_mtu);
+void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue);
+int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp);
+void ice_set_netdev_features(struct net_device *netdev);
+int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
+int ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
+void ice_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats);
/**
* ice_set_rdma_cap - enable RDMA support
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 572d9b345f66..8706d0589caa 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -2812,6 +2812,28 @@ void ice_vsi_set_napi_queues(struct ice_vsi *vsi, bool locked)
ice_q_vector_set_napi_queues(vsi->q_vectors[i], locked);
}
+/**
+ * ice_napi_add - register NAPI handler for the VSI
+ * @vsi: VSI for which NAPI handler is to be registered
+ *
+ * This function is only called in the driver's load path. Registering the NAPI
+ * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume,
+ * reset/rebuild, etc.)
+ */
+void ice_napi_add(struct ice_vsi *vsi)
+{
+ int v_idx;
+
+ if (!vsi->netdev)
+ return;
+
+ ice_for_each_q_vector(vsi, v_idx) {
+ netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
+ ice_napi_poll);
+ ice_q_vector_set_napi_queues(vsi->q_vectors[v_idx], false);
+ }
+}
+
/**
* ice_vsi_release - Delete a VSI and free its resources
* @vsi: the VSI being removed
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 0c77d581416a..aa3a85d31f95 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -84,6 +84,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params);
void ice_q_vector_set_napi_queues(struct ice_q_vector *q_vector, bool locked);
void ice_vsi_set_napi_queues(struct ice_vsi *vsi, bool locked);
+void ice_napi_add(struct ice_vsi *vsi);
int ice_vsi_release(struct ice_vsi *vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index ebab03b16596..b0f6a11ae744 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3024,7 +3024,7 @@ static int ice_xdp_safe_mode(struct net_device __always_unused *dev,
* @dev: netdevice
* @xdp: XDP command
*/
-static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
struct ice_netdev_priv *np = netdev_priv(dev);
struct ice_vsi *vsi = np->vsi;
@@ -3483,28 +3483,6 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
return 0;
}
-/**
- * ice_napi_add - register NAPI handler for the VSI
- * @vsi: VSI for which NAPI handler is to be registered
- *
- * This function is only called in the driver's load path. Registering the NAPI
- * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume,
- * reset/rebuild, etc.)
- */
-static void ice_napi_add(struct ice_vsi *vsi)
-{
- int v_idx;
-
- if (!vsi->netdev)
- return;
-
- ice_for_each_q_vector(vsi, v_idx) {
- netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
- ice_napi_poll);
- ice_q_vector_set_napi_queues(vsi->q_vectors[v_idx], false);
- }
-}
-
/**
* ice_set_ops - set netdev and ethtools ops for the given netdev
* @vsi: the VSI associated with the new netdev
@@ -3538,7 +3516,7 @@ static void ice_set_ops(struct ice_vsi *vsi)
* ice_set_netdev_features - set features for the given netdev
* @netdev: netdev instance
*/
-static void ice_set_netdev_features(struct net_device *netdev)
+void ice_set_netdev_features(struct net_device *netdev)
{
struct ice_pf *pf = ice_netdev_to_pf(netdev);
bool is_dvm_ena = ice_is_dvm_ena(&pf->hw);
@@ -3720,8 +3698,7 @@ ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
*
* net_device_ops implementation for adding VLAN IDs
*/
-static int
-ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
+int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi_vlan_ops *vlan_ops;
@@ -3783,8 +3760,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
*
* net_device_ops implementation for removing VLAN IDs
*/
-static int
-ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
+int ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi_vlan_ops *vlan_ops;
@@ -6945,7 +6921,6 @@ void ice_update_pf_stats(struct ice_pf *pf)
* @netdev: network interface device structure
* @stats: main device statistics structure
*/
-static
void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -7574,7 +7549,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
*
* Returns 0 on success, negative on failure
*/
-static int ice_change_mtu(struct net_device *netdev, int new_mtu)
+int ice_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
@@ -7999,7 +7974,7 @@ ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
* @netdev: network interface device structure
* @txqueue: Tx queue
*/
-static void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)
+void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_tx_ring *tx_ring = NULL;
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (2 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 03/15] ice: export ice ndo_ops functions Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 8:55 ` Jiri Pirko
2024-02-13 7:27 ` [iwl-next v1 05/15] ice: add subfunctions ethtool ops Michal Swiatkowski
` (10 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Implement devlink port handlers responsible for ethernet type devlink
subfunctions. Create subfunction devlink port and setup all resources
needed for a subfunction netdev to operate. Configure new VSI for each
new subfunction, initialize and configure interrupts and Tx/Rx resources.
Set correct MAC filters and create new netdev.
For now, subfunction is limited to only one Tx/Rx queue pair.
Only allocate new subfunction VSI with devlink port new command.
This makes sure that real resources are configured only when a new
subfunction gets activated. Allocate and free subfunction MSIX
interrupt vectors using new API calls with pci_msix_alloc_irq_at
and pci_msix_free_irq.
Temporarily, before adding auxiliary bus driver for subfunctions,
configure subfunction netdev directly for the created devlink
port. This will be modified in the next patch to properly that handle
devlink port as the port representor.
Support both automatic and manual subfunction numbers. If no subfunction
number is provided, use xa_alloc to pick a number automatically. This
will find the first free index and use that as the number. This reduces
burden on users in the simple case where a specific number is not
required. It may also be slightly faster to check that a number exists
since xarray lookup should be faster than a linear scan of the dyn_ports
xarray.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Co-developed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/Makefile | 1 +
.../intel/ice/devlink/ice_devlink_port.c | 508 ++++++++++++++++++
.../intel/ice/devlink/ice_devlink_port.h | 30 ++
drivers/net/ethernet/intel/ice/ice.h | 4 +
drivers/net/ethernet/intel/ice/ice_devlink.c | 3 +
drivers/net/ethernet/intel/ice/ice_lib.c | 5 +-
drivers/net/ethernet/intel/ice/ice_lib.h | 2 +
drivers/net/ethernet/intel/ice/ice_main.c | 14 +-
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 138 +++++
drivers/net/ethernet/intel/ice/ice_sf_eth.h | 15 +
10 files changed, 716 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.c
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.h
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index cd4ab46d72a7..d56a7165df95 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -31,6 +31,7 @@ ice-y := ice_main.o \
ice_idc.o \
ice_devlink.o \
devlink/ice_devlink_port.o \
+ ice_sf_eth.o \
ice_ddp.o \
ice_fw_update.o \
ice_lag.o \
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
index c8c823467fcf..90efceaddb02 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
@@ -10,6 +10,8 @@
#include "ice_eswitch.h"
#include "ice_fw_update.h"
#include "ice_dcb_lib.h"
+#include "ice_sf_eth.h"
+#include "ice_fltr.h"
static int ice_active_port_option = -1;
@@ -432,3 +434,509 @@ void ice_devlink_destroy_vf_port(struct ice_vf *vf)
devlink_port_unregister(&vf->devlink_port);
}
+/**
+ * ice_activate_dynamic_port - Activate a dynamic port
+ * @dyn_port: dynamic port instance to activate
+ * @extack: extack for reporting error messages
+ *
+ * Activate the dynamic port based on its flavour.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,
+ struct netlink_ext_ack *extack)
+{
+ int err;
+
+ switch (dyn_port->devlink_port.attrs.flavour) {
+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
+ err = ice_sf_eth_activate(dyn_port, extack);
+ if (err)
+ return err;
+ break;
+ default:
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported port flavour");
+ return -EOPNOTSUPP;
+ }
+
+ dyn_port->active = 1;
+
+ return 0;
+}
+
+/**
+ * ice_deactivate_dynamic_port - Deactivate a dynamic port
+ * @dyn_port: dynamic port instance to deactivate
+ *
+ * Undo activation of a dynamic port.
+ */
+static void ice_deactivate_dynamic_port(struct ice_dynamic_port *dyn_port)
+{
+ switch (dyn_port->devlink_port.attrs.flavour) {
+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
+ ice_sf_eth_deactivate(dyn_port);
+ break;
+ default:
+ WARN(1, "Attempting to deactivate port with unexpected port flavour %d",
+ dyn_port->devlink_port.attrs.flavour);
+ }
+
+ dyn_port->active = 0;
+}
+
+/**
+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
+ * @dyn_port: dynamic port instance to deallocate
+ *
+ * Free resources associated with a dynamically added devlink port. Will
+ * deactivate the port if its currently active.
+ */
+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
+{
+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
+ struct ice_pf *pf = dyn_port->pf;
+
+ if (dyn_port->active)
+ ice_deactivate_dynamic_port(dyn_port);
+
+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
+
+ devl_port_unregister(devlink_port);
+ ice_vsi_free(dyn_port->vsi);
+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
+ kfree(dyn_port);
+}
+
+/**
+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
+ * @pf: pointer to the pf structure
+ */
+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
+{
+ struct devlink *devlink = priv_to_devlink(pf);
+ struct ice_dynamic_port *dyn_port;
+ unsigned long index;
+
+ devl_lock(devlink);
+ xa_for_each(&pf->dyn_ports, index, dyn_port)
+ ice_dealloc_dynamic_port(dyn_port);
+ devl_unlock(devlink);
+}
+
+/**
+ * ice_devlink_port_new_check_attr - Check that new port attributes are valid
+ * @pf: pointer to the PF structure
+ * @new_attr: the attributes for the new port
+ * @extack: extack for reporting error messages
+ *
+ * Check that the attributes for the new port are valid before continuing to
+ * allocate the devlink port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_new_check_attr(struct ice_pf *pf,
+ const struct devlink_port_new_attrs *new_attr,
+ struct netlink_ext_ack *extack)
+{
+ if (new_attr->flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
+ NL_SET_ERR_MSG_MOD(extack, "Flavour other than pcisf is not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (new_attr->controller_valid) {
+ NL_SET_ERR_MSG_MOD(extack, "Setting controller is not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (new_attr->port_index_valid) {
+ NL_SET_ERR_MSG_MOD(extack, "Port index is autogenerated by the driver");
+ return -EOPNOTSUPP;
+ }
+
+ if (new_attr->pfnum != pf->hw.bus.func) {
+ NL_SET_ERR_MSG_MOD(extack, "Incorrect pfnum supplied");
+ return -EINVAL;
+ }
+
+ if (!pci_msix_can_alloc_dyn(pf->pdev)) {
+ NL_SET_ERR_MSG_MOD(extack, "Dynamic MSIX-X interrupt allocation is not supported");
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_del - devlink handler for port delete
+ * @devlink: pointer to devlink
+ * @port: devlink port to be deleted
+ * @extack: pointer to extack
+ *
+ * Deletes devlink port and deallocates all resources associated with
+ * created subfunction.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_del(struct devlink *devlink, struct devlink_port *port,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_dynamic_port *dyn_port;
+
+ dyn_port = ice_devlink_port_to_dyn(port);
+ if (!dyn_port) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to find Subfunction port with a given index");
+ return -EINVAL;
+ }
+
+ ice_dealloc_dynamic_port(dyn_port);
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_fn_hw_addr_set - devlink handler for mac address set
+ * @port: pointer to devlink port
+ * @hw_addr: hw address to set
+ * @hw_addr_len: hw address length
+ * @extack: extack for reporting error messages
+ *
+ * Sets mac address for the port, verifies arguments and copies address
+ * to the subfunction structure.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr,
+ int hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_dynamic_port *dyn_port;
+
+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
+ return -EOPNOTSUPP;
+ }
+
+ dyn_port = ice_devlink_port_to_dyn(port);
+
+ if (hw_addr_len != ETH_ALEN || !is_valid_ether_addr(hw_addr)) {
+ NL_SET_ERR_MSG_MOD(extack, "Invalid ethernet address");
+ return -EADDRNOTAVAIL;
+ }
+
+ if (ether_addr_equal(dyn_port->hw_addr, hw_addr)) {
+ NL_SET_ERR_MSG_MOD(extack, "address already set");
+ return 0;
+ }
+
+ ether_addr_copy(dyn_port->hw_addr, hw_addr);
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_fn_hw_addr_get - devlink handler for mac address get
+ * @port: pointer to devlink port
+ * @hw_addr: hw address to set
+ * @hw_addr_len: hw address length
+ * @extack: extack for reporting error messages
+ *
+ * Returns mac address for the port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr,
+ int *hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_dynamic_port *dyn_port;
+
+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF)
+ return -EOPNOTSUPP;
+
+ dyn_port = ice_devlink_port_to_dyn(port);
+
+ ether_addr_copy(hw_addr, dyn_port->hw_addr);
+ *hw_addr_len = ETH_ALEN;
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_fn_state_set - devlink handler for port state set
+ * @port: pointer to devlink port
+ * @state: state to set
+ * @extack: extack for reporting error messages
+ *
+ * Activates or deactivates the port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_fn_state_set(struct devlink_port *port,
+ enum devlink_port_fn_state state,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_dynamic_port *dyn_port;
+
+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
+ return -EOPNOTSUPP;
+ }
+
+ dyn_port = ice_devlink_port_to_dyn(port);
+
+ switch (state) {
+ case DEVLINK_PORT_FN_STATE_ACTIVE:
+ if (!dyn_port->active)
+ return ice_activate_dynamic_port(dyn_port, extack);
+ break;
+ case DEVLINK_PORT_FN_STATE_INACTIVE:
+ if (dyn_port->active)
+ ice_deactivate_dynamic_port(dyn_port);
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_devlink_port_fn_state_get - devlink handler for port state get
+ * @port: pointer to devlink port
+ * @state: admin configured state of the port
+ * @opstate: current port operational state
+ * @extack: extack for reporting error messages
+ *
+ * Gets port state.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_fn_state_get(struct devlink_port *port,
+ enum devlink_port_fn_state *state,
+ enum devlink_port_fn_opstate *opstate,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_dynamic_port *dyn_port;
+
+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
+ return -EOPNOTSUPP;
+ }
+
+ dyn_port = ice_devlink_port_to_dyn(port);
+
+ if (dyn_port->active) {
+ *state = DEVLINK_PORT_FN_STATE_ACTIVE;
+ *opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
+ } else {
+ *state = DEVLINK_PORT_FN_STATE_INACTIVE;
+ *opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;
+ }
+
+ return 0;
+}
+
+static const struct devlink_port_ops ice_devlink_port_sf_ops = {
+ .port_del = ice_devlink_port_del,
+ .port_fn_hw_addr_get = ice_devlink_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = ice_devlink_port_fn_hw_addr_set,
+ .port_fn_state_get = ice_devlink_port_fn_state_get,
+ .port_fn_state_set = ice_devlink_port_fn_state_set,
+};
+
+/**
+ * ice_reserve_sf_num - Reserve a subfunction number for this port
+ * @pf: pointer to the pf structure
+ * @new_attr: devlink port attributes requested
+ * @extack: extack for reporting error messages
+ * @sfnum: on success, the sf number reserved
+ *
+ * Reserve a subfunction number for this port. Only called for
+ * DEVLINK_PORT_FLAVOUR_PCI_SF ports.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_reserve_sf_num(struct ice_pf *pf,
+ const struct devlink_port_new_attrs *new_attr,
+ struct netlink_ext_ack *extack, u32 *sfnum)
+{
+ int err;
+
+ /* If user didn't request an explicit number, pick one */
+ if (!new_attr->sfnum_valid)
+ return xa_alloc(&pf->sf_nums, sfnum, NULL, xa_limit_32b,
+ GFP_KERNEL);
+
+ /* Otherwise, check and use the number provided */
+ err = xa_insert(&pf->sf_nums, new_attr->sfnum, NULL, GFP_KERNEL);
+ if (err) {
+ if (err == -EBUSY)
+ NL_SET_ERR_MSG_MOD(extack, "Subfunction with given sfnum already exists");
+ return err;
+ }
+
+ *sfnum = new_attr->sfnum;
+
+ return 0;
+}
+
+/**
+ * ice_devlink_create_sf_port - Register PCI subfunction devlink port
+ * @dyn_port: the dynamic port instance structure for this subfunction
+ * @sfnum: the subfunction number to use for the port
+ *
+ * Register PCI subfunction flavour devlink port for a dynamically added
+ * subfunction port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_create_sf_port(struct ice_dynamic_port *dyn_port, u32 sfnum)
+{
+ struct devlink_port_attrs attrs = {};
+ struct devlink_port *devlink_port;
+ struct devlink *devlink;
+ struct ice_vsi *vsi;
+ struct device *dev;
+ struct ice_pf *pf;
+ int err;
+
+ vsi = dyn_port->vsi;
+ pf = dyn_port->pf;
+ dev = ice_pf_to_dev(pf);
+
+ devlink_port = &dyn_port->devlink_port;
+
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_SF;
+ attrs.pci_sf.pf = pf->hw.bus.func;
+ attrs.pci_sf.sf = sfnum;
+
+ devlink_port_attrs_set(devlink_port, &attrs);
+ devlink = priv_to_devlink(pf);
+
+ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
+ &ice_devlink_port_sf_ops);
+ if (err) {
+ dev_err(dev, "Failed to create devlink port for Subfunction %d",
+ vsi->idx);
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_alloc_dynamic_port - Allocate new dynamic port
+ * @pf: pointer to the pf structure
+ * @new_attr: devlink port attributes requested
+ * @extack: extack for reporting error messages
+ * @devlink_port: index of newly created devlink port
+ *
+ * Allocate a new dynamic port instance and prepare it for configuration
+ * with devlink.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_alloc_dynamic_port(struct ice_pf *pf,
+ const struct devlink_port_new_attrs *new_attr,
+ struct netlink_ext_ack *extack,
+ struct devlink_port **devlink_port)
+{
+ struct ice_dynamic_port *dyn_port;
+ struct ice_vsi *vsi;
+ u32 sfnum;
+ int err;
+
+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF) {
+ err = ice_reserve_sf_num(pf, new_attr, extack, &sfnum);
+ if (err)
+ return err;
+ }
+
+ dyn_port = kzalloc(sizeof(*dyn_port), GFP_KERNEL);
+ if (!dyn_port) {
+ err = -ENOMEM;
+ goto unroll_reserve_sf_num;
+ }
+
+ vsi = ice_vsi_alloc(pf);
+ if (!vsi) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate VSI");
+ err = -ENOMEM;
+ goto unroll_dyn_port_alloc;
+ }
+
+ dyn_port->vsi = vsi;
+ dyn_port->pf = pf;
+ dyn_port->active = 0;
+ eth_random_addr(dyn_port->hw_addr);
+
+ err = xa_insert(&pf->dyn_ports, vsi->idx, dyn_port, GFP_KERNEL);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Port index reservation failed");
+ goto unroll_vsi_alloc;
+ }
+
+ err = ice_devlink_create_sf_port(dyn_port, sfnum);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Port registration failed");
+ goto unroll_xa_insert;
+ }
+
+ *devlink_port = &dyn_port->devlink_port;
+
+ return 0;
+
+unroll_xa_insert:
+ xa_erase(&pf->dyn_ports, vsi->idx);
+unroll_vsi_alloc:
+ ice_vsi_free(vsi);
+unroll_dyn_port_alloc:
+ kfree(dyn_port);
+unroll_reserve_sf_num:
+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
+ xa_erase(&pf->sf_nums, sfnum);
+
+ return err;
+}
+
+/**
+ * ice_devlink_port_new - devlink handler for the new port
+ * @devlink: pointer to devlink
+ * @new_attr: pointer to the port new attributes
+ * @extack: extack for reporting error messages
+ * @devlink_port: pointer to a new port
+ *
+ * Creates new devlink port, checks new port attributes and reject
+ * any unsupported parameters, allocates new subfunction for that port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int
+ice_devlink_port_new(struct devlink *devlink,
+ const struct devlink_port_new_attrs *new_attr,
+ struct netlink_ext_ack *extack,
+ struct devlink_port **devlink_port)
+{
+ struct ice_pf *pf = (struct ice_pf *)devlink_priv(devlink);
+ struct device *dev = ice_pf_to_dev(pf);
+ int err;
+
+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
+
+ err = ice_devlink_port_new_check_attr(pf, new_attr, extack);
+ if (err)
+ return err;
+
+ return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port);
+}
+
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
index 983d136f5ddf..2bb203c1713f 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
@@ -4,9 +4,39 @@
#ifndef _ICE_DEVLINK_PORT_H_
#define _ICE_DEVLINK_PORT_H_
+#include "../ice.h"
+
+/**
+ * struct ice_dynamic_port - Track dynamically added devlink port instance
+ * @hw_addr: the HW address for this port
+ * @active: true if the port has been activated
+ * @devlink_port: the associated devlink port structure
+ * @pf: pointer to the PF private structure
+ * @vsi: the VSI associated with this port
+ *
+ * An instance of a dynamically added devlink port. Each port flavour
+ */
+struct ice_dynamic_port {
+ u8 hw_addr[ETH_ALEN];
+ u8 active : 1;
+ struct devlink_port devlink_port;
+ struct ice_pf *pf;
+ struct ice_vsi *vsi;
+};
+
+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf);
+
int ice_devlink_create_pf_port(struct ice_pf *pf);
void ice_devlink_destroy_pf_port(struct ice_pf *pf);
int ice_devlink_create_vf_port(struct ice_vf *vf);
void ice_devlink_destroy_vf_port(struct ice_vf *vf);
+#define ice_devlink_port_to_dyn(p) \
+ container_of(port, struct ice_dynamic_port, devlink_port)
+
+int
+ice_devlink_port_new(struct devlink *devlink,
+ const struct devlink_port_new_attrs *new_attr,
+ struct netlink_ext_ack *extack,
+ struct devlink_port **devlink_port);
#endif /* _ICE_DEVLINK_PORT_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index c40fc339a604..767ea80684e7 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -646,6 +646,9 @@ struct ice_pf {
struct ice_eswitch eswitch;
struct ice_esw_br_port *br_port;
+ struct xarray dyn_ports;
+ struct xarray sf_nums;
+
#define ICE_INVALID_AGG_NODE_ID 0
#define ICE_PF_AGG_NODE_ID_START 1
#define ICE_MAX_PF_AGG_NODES 32
@@ -902,6 +905,7 @@ int ice_vsi_open(struct ice_vsi *vsi);
void ice_set_ethtool_ops(struct net_device *netdev);
void ice_set_ethtool_repr_ops(struct net_device *netdev);
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
+void ice_set_ethtool_sf_ops(struct net_device *netdev);
u16 ice_get_avail_txq_count(struct ice_pf *pf);
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index e5f275ca82e5..c186e793153d 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -6,6 +6,7 @@
#include "ice.h"
#include "ice_lib.h"
#include "ice_devlink.h"
+#include "devlink/ice_devlink_port.h"
#include "ice_eswitch.h"
#include "ice_fw_update.h"
#include "ice_dcb_lib.h"
@@ -1131,6 +1132,8 @@ static const struct devlink_ops ice_devlink_ops = {
.rate_leaf_parent_set = ice_devlink_set_parent,
.rate_node_parent_set = ice_devlink_set_parent,
+
+ .port_new = ice_devlink_port_new,
};
static int
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 8706d0589caa..3472011922c1 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -7,6 +7,7 @@
#include "ice_lib.h"
#include "ice_fltr.h"
#include "ice_dcb_lib.h"
+#include "ice_type.h"
#include "ice_vsi_vlan_ops.h"
/**
@@ -440,7 +441,7 @@ static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
* This deallocates the VSI's queue resources, removes it from the PF's
* VSI array if necessary, and deallocates the VSI
*/
-static void ice_vsi_free(struct ice_vsi *vsi)
+void ice_vsi_free(struct ice_vsi *vsi)
{
struct ice_pf *pf = NULL;
struct device *dev;
@@ -612,7 +613,7 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
*
* returns a pointer to a VSI on success, NULL on failure.
*/
-static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_vsi *vsi = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index aa3a85d31f95..9cc7cc57e41a 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -97,6 +97,8 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf);
+void ice_vsi_free(struct ice_vsi *vsi);
bool ice_is_reset_in_progress(unsigned long *state);
int ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b0f6a11ae744..e4269a7df7d6 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -16,6 +16,7 @@
#include "ice_devlink.h"
#include "ice_hwmon.h"
#include "devlink/ice_devlink_port.h"
+#include "ice_sf_eth.h"
/* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
* ice tracepoint functions. This must be done exactly once across the
* ice driver.
@@ -3929,6 +3930,9 @@ static void ice_deinit_pf(struct ice_pf *pf)
if (pf->ptp.clock)
ptp_clock_unregister(pf->ptp.clock);
+
+ xa_destroy(&pf->dyn_ports);
+ xa_destroy(&pf->sf_nums);
}
/**
@@ -4022,6 +4026,9 @@ static int ice_init_pf(struct ice_pf *pf)
hash_init(pf->vfs.table);
ice_mbx_init_snapshot(&pf->hw);
+ xa_init(&pf->dyn_ports);
+ xa_init(&pf->sf_nums);
+
return 0;
}
@@ -5250,6 +5257,8 @@ static void ice_remove(struct pci_dev *pdev)
struct ice_pf *pf = pci_get_drvdata(pdev);
int i;
+ ice_dealloc_all_dynamic_ports(pf);
+
for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
if (!ice_is_reset_in_progress(pf->state))
break;
@@ -6561,7 +6570,8 @@ static int ice_up_complete(struct ice_vsi *vsi)
if (vsi->port_info &&
(vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
- vsi->netdev && vsi->type == ICE_VSI_PF) {
+ ((vsi->netdev && vsi->type == ICE_VSI_PF) ||
+ (vsi->netdev && vsi->type == ICE_VSI_SF))) {
ice_print_link_msg(vsi, true);
netif_tx_start_all_queues(vsi->netdev);
netif_carrier_on(vsi->netdev);
@@ -7217,7 +7227,7 @@ int ice_vsi_open(struct ice_vsi *vsi)
ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
- if (vsi->type == ICE_VSI_PF) {
+ if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_SF) {
/* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
if (err)
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
new file mode 100644
index 000000000000..f569f176f29f
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023, Intel Corporation. */
+
+#include "ice.h"
+#include "ice_lib.h"
+#include "ice_txrx.h"
+#include "ice_fltr.h"
+#include "ice_sf_eth.h"
+#include "devlink/ice_devlink_port.h"
+
+static const struct net_device_ops ice_sf_netdev_ops = {
+ .ndo_open = ice_open,
+ .ndo_stop = ice_stop,
+ .ndo_start_xmit = ice_start_xmit,
+ .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
+ .ndo_change_mtu = ice_change_mtu,
+ .ndo_get_stats64 = ice_get_stats64,
+ .ndo_tx_timeout = ice_tx_timeout,
+ .ndo_bpf = ice_xdp,
+ .ndo_xdp_xmit = ice_xdp_xmit,
+ .ndo_xsk_wakeup = ice_xsk_wakeup,
+};
+
+/**
+ * ice_sf_cfg_netdev - Allocate, configure and register a netdev
+ * @dyn_port: subfunction associated with configured netdev
+ *
+ * Returns 0 on success, negative value on failure
+ */
+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
+{
+ struct net_device *netdev;
+ struct ice_vsi *vsi = dyn_port->vsi;
+ struct ice_netdev_priv *np;
+ int err;
+
+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
+ vsi->alloc_rxq);
+ if (!netdev)
+ return -ENOMEM;
+
+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
+ vsi->netdev = netdev;
+ np = netdev_priv(netdev);
+ np->vsi = vsi;
+
+ ice_set_netdev_features(netdev);
+
+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
+ NETDEV_XDP_ACT_RX_SG;
+
+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
+ netdev->netdev_ops = &ice_sf_netdev_ops;
+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
+
+ err = register_netdev(netdev);
+ if (err) {
+ free_netdev(netdev);
+ vsi->netdev = NULL;
+ return -ENOMEM;
+ }
+ set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
+ netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
+
+ return 0;
+}
+
+/**
+ * ice_sf_eth_activate - Activate Ethernet subfunction port
+ * @dyn_port: the dynamic port instance for this subfunction
+ * @extack: extack for reporting error messages
+ *
+ * Setups netdev resources and filters for a subfunction.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int
+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_vsi_cfg_params params = {};
+ struct ice_vsi *vsi = dyn_port->vsi;
+ struct ice_pf *pf = dyn_port->pf;
+ int err;
+
+ params.type = ICE_VSI_SF;
+ params.pi = pf->hw.port_info;
+ params.flags = ICE_VSI_FLAG_INIT;
+
+ err = ice_vsi_cfg(vsi, ¶ms);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Subfunction vsi config failed");
+ return err;
+ }
+
+ err = ice_sf_cfg_netdev(dyn_port);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Subfunction netdev config failed");
+ goto err_vsi_decfg;
+ }
+
+ err = ice_fltr_add_mac_and_broadcast(vsi, vsi->netdev->dev_addr,
+ ICE_FWD_TO_VSI);
+ if (err)
+ NL_SET_ERR_MSG_MOD(extack, "can't add MAC filters for subfunction VSI");
+
+ ice_napi_add(vsi);
+
+ return err;
+
+err_vsi_decfg:
+ ice_vsi_decfg(vsi);
+ return err;
+}
+
+/**
+ * ice_sf_eth_deactivate - Deactivate subfunction
+ * @dyn_port: the dynamic port instance for this subfunction
+ *
+ * Free netdev resources and filters for a subfunction.
+ */
+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
+{
+ struct ice_vsi *vsi = dyn_port->vsi;
+
+ ice_vsi_close(vsi);
+ unregister_netdev(vsi->netdev);
+ clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
+ free_netdev(vsi->netdev);
+ clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
+ vsi->netdev = NULL;
+ ice_vsi_decfg(vsi);
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.h b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
new file mode 100644
index 000000000000..f4b8b36b1a67
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2023, Intel Corporation. */
+
+#ifndef _ICE_SF_ETH_H_
+#define _ICE_SF_ETH_H_
+
+#include "ice.h"
+#include "devlink/ice_devlink_port.h"
+
+int
+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
+ struct netlink_ext_ack *extack);
+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port);
+
+#endif /* _ICE_SF_ETH_H_ */
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 05/15] ice: add subfunctions ethtool ops
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (3 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 04/15] ice: add basic devlink subfunctions support Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 06/15] ice: add subfunction aux driver support Michal Swiatkowski
` (9 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Pawel Chmielewski, Michal Swiatkowski
From: Pawel Chmielewski <pawel.chmielewski@intel.com>
Add only limited number of ethtools ops. Also, stats set for a
subfunction is different than a regular netdev since there are
not port stats, show only related VSI statistics.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Pawel Chmielewski <pawel.chmielewski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_ethtool.c | 36 ++++++++++++++++++++
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 1 +
2 files changed, 37 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 3cc364a4d682..c862b21bad9f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -1564,6 +1564,22 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
return ret;
}
+/**
+ * ice_get_sf_sset_count - get number of stats to display for specified netdev
+ * of subfunction flavor
+ * @netdev: network interface device structure
+ * @sset: set of statistics to display
+ */
+static int ice_get_sf_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ICE_VSI_STATS_LEN + ice_q_stats_len(netdev);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int ice_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
@@ -4290,6 +4306,17 @@ static const struct ethtool_ops ice_ethtool_safe_mode_ops = {
.get_channels = ice_get_channels,
};
+static const struct ethtool_ops ice_sf_ethtool_ops = {
+ .get_drvinfo = ice_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_strings = ice_get_strings,
+ .get_ethtool_stats = ice_get_ethtool_stats,
+ .get_sset_count = ice_get_sf_sset_count,
+ .get_ringparam = ice_get_ringparam,
+ .set_ringparam = ice_set_ringparam,
+ .get_channels = ice_get_channels,
+};
+
/**
* ice_set_ethtool_safe_mode_ops - setup safe mode ethtool ops
* @netdev: network interface device structure
@@ -4326,3 +4353,12 @@ void ice_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &ice_ethtool_ops;
}
+
+/**
+ * ice_set_ethtool_sf_ops - setup subfunction ethtool ops
+ * @netdev: network interface device structure
+ */
+void ice_set_ethtool_sf_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &ice_sf_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index f569f176f29f..f45ac76f0f43 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -55,6 +55,7 @@ static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
eth_hw_addr_set(netdev, dyn_port->hw_addr);
ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
netdev->netdev_ops = &ice_sf_netdev_ops;
+ ice_set_ethtool_sf_ops(netdev);
SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
err = register_netdev(netdev);
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 06/15] ice: add subfunction aux driver support
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (4 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 05/15] ice: add subfunctions ethtool ops Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 8:57 ` Jiri Pirko
2024-02-13 7:27 ` [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute Michal Swiatkowski
` (8 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Instead of only registering devlink port by the ice driver itself,
let PF driver only register port representor for a given subfunction.
Then, aux driver is supposed to register its own devlink instance and
register virtual devlink port.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
.../intel/ice/devlink/ice_devlink_port.c | 52 ++++-
.../intel/ice/devlink/ice_devlink_port.h | 6 +
drivers/net/ethernet/intel/ice/ice_devlink.c | 28 ++-
drivers/net/ethernet/intel/ice/ice_devlink.h | 3 +
drivers/net/ethernet/intel/ice/ice_main.c | 9 +
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 214 ++++++++++++++++--
drivers/net/ethernet/intel/ice/ice_sf_eth.h | 21 ++
7 files changed, 302 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
index 90efceaddb02..33f290fed3d8 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
@@ -434,6 +434,48 @@ void ice_devlink_destroy_vf_port(struct ice_vf *vf)
devlink_port_unregister(&vf->devlink_port);
}
+/**
+ * ice_devlink_create_sf_dev_port - Register virtual port for a subfunction
+ * @sf_dev: the subfunction device to create a devlink port for
+ *
+ * Register virtual flavour devlink port for the subfunction auxiliary device
+ * created after activating a dynamically added devlink port.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int ice_devlink_create_sf_dev_port(struct ice_sf_dev *sf_dev)
+{
+ struct devlink_port_attrs attrs = {};
+ struct devlink_port *devlink_port;
+ struct ice_dynamic_port *dyn_port;
+ struct devlink *devlink;
+ struct ice_vsi *vsi;
+ struct device *dev;
+ struct ice_pf *pf;
+ int err;
+
+ dyn_port = sf_dev->dyn_port;
+ vsi = dyn_port->vsi;
+ pf = dyn_port->pf;
+ dev = ice_pf_to_dev(pf);
+
+ devlink_port = &sf_dev->priv->devlink_port;
+
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL;
+
+ devlink_port_attrs_set(devlink_port, &attrs);
+ devlink = priv_to_devlink(sf_dev->priv);
+
+ devl_lock(devlink);
+ err = devl_port_register(devlink, devlink_port, vsi->idx);
+ if (err)
+ dev_err(dev, "Failed to create virtual devlink port for auxiliary subfunction device %d",
+ vsi->idx);
+ devl_unlock(devlink);
+
+ return err;
+}
+
/**
* ice_activate_dynamic_port - Activate a dynamic port
* @dyn_port: dynamic port instance to activate
@@ -731,13 +773,15 @@ ice_devlink_port_fn_state_get(struct devlink_port *port,
dyn_port = ice_devlink_port_to_dyn(port);
- if (dyn_port->active) {
+ if (dyn_port->active)
*state = DEVLINK_PORT_FN_STATE_ACTIVE;
- *opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
- } else {
+ else
*state = DEVLINK_PORT_FN_STATE_INACTIVE;
+
+ if (dyn_port->sf_dev && dyn_port->sf_dev->adev.dev.driver)
+ *opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
+ else
*opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;
- }
return 0;
}
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
index 2bb203c1713f..96d57ed54d7f 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
@@ -13,6 +13,7 @@
* @devlink_port: the associated devlink port structure
* @pf: pointer to the PF private structure
* @vsi: the VSI associated with this port
+ * @sf_dev: dynamic port device private data
*
* An instance of a dynamically added devlink port. Each port flavour
*/
@@ -22,6 +23,10 @@ struct ice_dynamic_port {
struct devlink_port devlink_port;
struct ice_pf *pf;
struct ice_vsi *vsi;
+ /* Flavour-specific implementation data */
+ union {
+ struct ice_sf_dev *sf_dev;
+ };
};
void ice_dealloc_all_dynamic_ports(struct ice_pf *pf);
@@ -30,6 +35,7 @@ int ice_devlink_create_pf_port(struct ice_pf *pf);
void ice_devlink_destroy_pf_port(struct ice_pf *pf);
int ice_devlink_create_vf_port(struct ice_vf *vf);
void ice_devlink_destroy_vf_port(struct ice_vf *vf);
+int ice_devlink_create_sf_dev_port(struct ice_sf_dev *sf_dev);
#define ice_devlink_port_to_dyn(p) \
container_of(port, struct ice_dynamic_port, devlink_port)
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index c186e793153d..6278ff3eb7c9 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -1382,18 +1382,21 @@ static void ice_devlink_free(void *devlink_ptr)
}
/**
- * ice_allocate_pf - Allocate devlink and return PF structure pointer
+ * ice_devlink_alloc - Allocate devlink and return devlink priv pointer
* @dev: the device to allocate for
+ * @priv_size: size of the priv memory
+ * @ops: pointer to devlink ops for this device
*
- * Allocate a devlink instance for this device and return the private area as
- * the PF structure. The devlink memory is kept track of through devres by
- * adding an action to remove it when unwinding.
+ * Allocate a devlink instance for this device and return the private pointer
+ * The devlink memory is kept track of through devres by adding an action to
+ * remove it when unwinding.
*/
-struct ice_pf *ice_allocate_pf(struct device *dev)
+void *ice_devlink_alloc(struct device *dev, size_t priv_size,
+ const struct devlink_ops *ops)
{
struct devlink *devlink;
- devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev);
+ devlink = devlink_alloc(ops, priv_size, dev);
if (!devlink)
return NULL;
@@ -1404,6 +1407,19 @@ struct ice_pf *ice_allocate_pf(struct device *dev)
return devlink_priv(devlink);
}
+/**
+ * ice_allocate_pf - Allocate devlink and return PF structure pointer
+ * @dev: the device to allocate for
+ *
+ * Allocate a devlink instance for this device and return the private area as
+ * the PF structure. The devlink memory is kept track of through devres by
+ * adding an action to remove it when unwinding.
+ */
+struct ice_pf *ice_allocate_pf(struct device *dev)
+{
+ return ice_devlink_alloc(dev, sizeof(struct ice_pf), &ice_devlink_ops);
+}
+
/**
* ice_devlink_register - Register devlink interface for this PF
* @pf: the PF to register the devlink for.
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/ice_devlink.h
index d291c0e2e17b..4f4a7254bcc8 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.h
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.h
@@ -5,6 +5,9 @@
#define _ICE_DEVLINK_H_
struct ice_pf *ice_allocate_pf(struct device *dev);
+void *
+ice_devlink_alloc(struct device *dev, size_t priv_size,
+ const struct devlink_ops *ops);
void ice_devlink_register(struct ice_pf *pf);
void ice_devlink_unregister(struct ice_pf *pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index e4269a7df7d6..7ff96da33e8d 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5750,8 +5750,16 @@ static int __init ice_module_init(void)
goto err_dest_lag_wq;
}
+ status = ice_sf_driver_register();
+ if (status) {
+ pr_err("failed to register SF driver, err %d\n", status);
+ goto err_sf_driver;
+ }
+
return 0;
+err_sf_driver:
+ pci_unregister_driver(&ice_driver);
err_dest_lag_wq:
destroy_workqueue(ice_lag_wq);
ice_debugfs_exit();
@@ -5769,6 +5777,7 @@ module_init(ice_module_init);
*/
static void __exit ice_module_exit(void)
{
+ ice_sf_driver_unregister();
pci_unregister_driver(&ice_driver);
ice_debugfs_exit();
destroy_workqueue(ice_wq);
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index f45ac76f0f43..ab90db52a8fc 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -6,6 +6,7 @@
#include "ice_txrx.h"
#include "ice_fltr.h"
#include "ice_sf_eth.h"
+#include "ice_devlink.h"
#include "devlink/ice_devlink_port.h"
static const struct net_device_ops ice_sf_netdev_ops = {
@@ -24,15 +25,16 @@ static const struct net_device_ops ice_sf_netdev_ops = {
/**
* ice_sf_cfg_netdev - Allocate, configure and register a netdev
- * @dyn_port: subfunction associated with configured netdev
+ * @sf_dev: subfunction associated with configured netdev
*
* Returns 0 on success, negative value on failure
*/
-static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
+static int ice_sf_cfg_netdev(struct ice_sf_dev *sf_dev)
{
- struct net_device *netdev;
+ struct ice_dynamic_port *dyn_port = sf_dev->dyn_port;
struct ice_vsi *vsi = dyn_port->vsi;
struct ice_netdev_priv *np;
+ struct net_device *netdev;
int err;
netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
@@ -40,7 +42,7 @@ static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
if (!netdev)
return -ENOMEM;
- SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
+ SET_NETDEV_DEV(netdev, &sf_dev->adev.dev);
set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
vsi->netdev = netdev;
np = netdev_priv(netdev);
@@ -56,7 +58,7 @@ static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
netdev->netdev_ops = &ice_sf_netdev_ops;
ice_set_ethtool_sf_ops(netdev);
- SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
+ SET_NETDEV_DEVLINK_PORT(netdev, &sf_dev->priv->devlink_port);
err = register_netdev(netdev);
if (err) {
@@ -71,45 +73,70 @@ static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
return 0;
}
+static const struct devlink_ops ice_sf_devlink_ops;
+
/**
- * ice_sf_eth_activate - Activate Ethernet subfunction port
- * @dyn_port: the dynamic port instance for this subfunction
- * @extack: extack for reporting error messages
+ * ice_sf_dev_probe - subfunction driver probe function
+ * @adev: pointer to the auxiliary device
+ * @id: pointer to the auxiliary_device id
*
- * Setups netdev resources and filters for a subfunction.
+ * Configure VSI and netdev resources for the subfunction device.
*
* Return: zero on success or an error code on failure.
*/
-int
-ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
- struct netlink_ext_ack *extack)
+static int ice_sf_dev_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
{
+ struct ice_sf_dev *sf_dev = ice_adev_to_sf_dev(adev);
+ struct ice_dynamic_port *dyn_port = sf_dev->dyn_port;
struct ice_vsi_cfg_params params = {};
struct ice_vsi *vsi = dyn_port->vsi;
struct ice_pf *pf = dyn_port->pf;
+ struct device *dev = &adev->dev;
+ struct ice_sf_priv *priv;
int err;
params.type = ICE_VSI_SF;
params.pi = pf->hw.port_info;
params.flags = ICE_VSI_FLAG_INIT;
+ priv = ice_devlink_alloc(&adev->dev, sizeof(struct ice_sf_priv),
+ &ice_sf_devlink_ops);
+ if (!priv) {
+ dev_err(dev, "Subfunction devlink alloc failed");
+ return -ENOMEM;
+ }
+
+ priv->dev = sf_dev;
+ sf_dev->priv = priv;
+
+ devlink_register(priv_to_devlink(priv));
+
err = ice_vsi_cfg(vsi, ¶ms);
if (err) {
- NL_SET_ERR_MSG_MOD(extack, "Subfunction vsi config failed");
+ dev_err(dev, "Subfunction vsi config failed");
return err;
}
- err = ice_sf_cfg_netdev(dyn_port);
+ err = ice_devlink_create_sf_dev_port(sf_dev);
+ if (err)
+ dev_dbg(dev, "Cannot add ice virtual devlink port for subfunction");
+
+ err = ice_sf_cfg_netdev(sf_dev);
if (err) {
- NL_SET_ERR_MSG_MOD(extack, "Subfunction netdev config failed");
+ dev_err(dev, "subfunction netdev config failed");
goto err_vsi_decfg;
}
err = ice_fltr_add_mac_and_broadcast(vsi, vsi->netdev->dev_addr,
ICE_FWD_TO_VSI);
+
if (err)
- NL_SET_ERR_MSG_MOD(extack, "can't add MAC filters for subfunction VSI");
+ dev_dbg(dev, "can't add MAC filters %pM for VSI %d\n",
+ vsi->netdev->dev_addr, vsi->idx);
+ dev_dbg(dev, "MAC %pM filter added for vsi %d\n", vsi->netdev->dev_addr,
+ vsi->idx);
ice_napi_add(vsi);
return err;
@@ -120,20 +147,165 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
}
/**
- * ice_sf_eth_deactivate - Deactivate subfunction
- * @dyn_port: the dynamic port instance for this subfunction
+ * ice_sf_dev_remove - subfunction driver remove function
+ * @adev: pointer to the auxiliary device
*
- * Free netdev resources and filters for a subfunction.
+ * Deinitalize VSI and netdev resources for the subfunction device.
*/
-void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
+static void ice_sf_dev_remove(struct auxiliary_device *adev)
{
+ struct ice_sf_dev *sf_dev = ice_adev_to_sf_dev(adev);
+ struct devlink *devlink = priv_to_devlink(sf_dev->priv);
+ struct ice_dynamic_port *dyn_port = sf_dev->dyn_port;
struct ice_vsi *vsi = dyn_port->vsi;
ice_vsi_close(vsi);
+
unregister_netdev(vsi->netdev);
clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
+ devlink_port_unregister(&sf_dev->priv->devlink_port);
free_netdev(vsi->netdev);
- clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
vsi->netdev = NULL;
+ clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
+ devlink_unregister(devlink);
+ devlink_free(devlink);
ice_vsi_decfg(vsi);
}
+
+static const struct auxiliary_device_id ice_sf_dev_id_table[] = {
+ { .name = "ice.sf", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(auxiliary, ice_sf_dev_id_table);
+
+static struct auxiliary_driver ice_sf_driver = {
+ .name = "sf",
+ .probe = ice_sf_dev_probe,
+ .remove = ice_sf_dev_remove,
+ .id_table = ice_sf_dev_id_table
+};
+
+static DEFINE_XARRAY_ALLOC1(ice_sf_aux_id);
+
+/**
+ * ice_sf_driver_register - Register new auxiliary subfunction driver
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int ice_sf_driver_register(void)
+{
+ return auxiliary_driver_register(&ice_sf_driver);
+}
+
+/**
+ * ice_sf_driver_unregister - Unregister new auxiliary subfunction driver
+ *
+ * Return: zero on success or an error code on failure.
+ */
+void ice_sf_driver_unregister(void)
+{
+ auxiliary_driver_unregister(&ice_sf_driver);
+}
+
+/**
+ * ice_sf_dev_release - Release device associated with auxiliary device
+ * @device: pointer to the device
+ *
+ * Since most of the code for subfunction deactivation is handled in
+ * the remove handler, here just free tracking resources.
+ */
+static void ice_sf_dev_release(struct device *device)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(device);
+ struct ice_sf_dev *sf_dev = ice_adev_to_sf_dev(adev);
+
+ xa_erase(&ice_sf_aux_id, adev->id);
+ kfree(sf_dev);
+}
+
+/**
+ * ice_sf_eth_activate - Activate Ethernet subfunction port
+ * @dyn_port: the dynamic port instance for this subfunction
+ * @extack: extack for reporting error messages
+ *
+ * Activate the dynamic port as an Ethernet subfunction. Setup the netdev
+ * resources associated and initialize the auxiliary device.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+int
+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_pf *pf = dyn_port->pf;
+ struct ice_sf_dev *sf_dev;
+ struct pci_dev *pdev;
+ int err;
+ u32 id;
+
+ err = xa_alloc(&ice_sf_aux_id, &id, NULL, xa_limit_32b,
+ GFP_KERNEL);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Could not allocate subfunction ID");
+ return err;
+ }
+
+ sf_dev = kzalloc(sizeof(*sf_dev), GFP_KERNEL);
+ if (!sf_dev) {
+ err = -ENOMEM;
+ NL_SET_ERR_MSG_MOD(extack, "Could not allocate sf_dev memory");
+ goto xa_erase;
+ }
+ pdev = pf->pdev;
+
+ sf_dev->dyn_port = dyn_port;
+ sf_dev->adev.id = id;
+ sf_dev->adev.name = "sf";
+ sf_dev->adev.dev.release = ice_sf_dev_release;
+ sf_dev->adev.dev.parent = &pdev->dev;
+
+ err = auxiliary_device_init(&sf_dev->adev);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to initialize auxiliary device");
+ goto sf_dev_free;
+ }
+
+ err = auxiliary_device_add(&sf_dev->adev);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Auxiliary device failed to probe");
+ goto aux_dev_uninit;
+ }
+
+ dyn_port->sf_dev = sf_dev;
+
+ return 0;
+
+aux_dev_uninit:
+ auxiliary_device_uninit(&sf_dev->adev);
+sf_dev_free:
+ kfree(sf_dev);
+xa_erase:
+ xa_erase(&ice_sf_aux_id, id);
+
+ return err;
+}
+
+/**
+ * ice_sf_eth_deactivate - Deactivate Ethernet subfunction port
+ * @dyn_port: the dynamic port instance for this subfunction
+ *
+ * Deactivate the Ethernet subfunction, removing its auxiliary device and the
+ * associated resources.
+ */
+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
+{
+ struct ice_sf_dev *sf_dev = dyn_port->sf_dev;
+
+ if (sf_dev) {
+ auxiliary_device_delete(&sf_dev->adev);
+ auxiliary_device_uninit(&sf_dev->adev);
+ }
+
+ dyn_port->sf_dev = NULL;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.h b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
index f4b8b36b1a67..366344c3ff90 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.h
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
@@ -4,12 +4,33 @@
#ifndef _ICE_SF_ETH_H_
#define _ICE_SF_ETH_H_
+#include <linux/auxiliary_bus.h>
#include "ice.h"
#include "devlink/ice_devlink_port.h"
+struct ice_sf_dev {
+ struct auxiliary_device adev;
+ struct ice_dynamic_port *dyn_port;
+ struct ice_sf_priv *priv;
+};
+
+struct ice_sf_priv {
+ struct ice_sf_dev *dev;
+ struct devlink_port devlink_port;
+};
+
+static inline struct
+ice_sf_dev *ice_adev_to_sf_dev(struct auxiliary_device *adev)
+{
+ return container_of(adev, struct ice_sf_dev, adev);
+}
+
int
ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
struct netlink_ext_ack *extack);
void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port);
+int ice_sf_driver_register(void);
+void ice_sf_driver_unregister(void);
+
#endif /* _ICE_SF_ETH_H_ */
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (5 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 06/15] ice: add subfunction aux driver support Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 8:59 ` Jiri Pirko
2024-02-13 7:27 ` [iwl-next v1 08/15] ice: store SF data in VSI struct Michal Swiatkowski
` (7 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski, Michal Swiatkowski
From: Piotr Raczynski <piotr.raczynski@intel.com>
Add read only sysfs attribute for each auxiliary subfunction
device. This attribute is needed for orchestration layer
to distinguish SF devices from each other since there is no
native devlink mechanism to represent the connection between
devlink instance and the devlink port created for the port
representor.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index ab90db52a8fc..abee733710a5 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
kfree(sf_dev);
}
+static ssize_t
+sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct devlink_port_attrs *attrs;
+ struct auxiliary_device *adev;
+ struct ice_sf_dev *sf_dev;
+
+ adev = to_auxiliary_dev(dev);
+ sf_dev = ice_adev_to_sf_dev(adev);
+ attrs = &sf_dev->dyn_port->devlink_port.attrs;
+
+ return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
+}
+
+static DEVICE_ATTR_RO(sfnum);
+
+static struct attribute *ice_sf_device_attrs[] = {
+ &dev_attr_sfnum.attr,
+ NULL,
+};
+
+static const struct attribute_group ice_sf_attr_group = {
+ .attrs = ice_sf_device_attrs,
+};
+
+static const struct attribute_group *ice_sf_attr_groups[2] = {
+ &ice_sf_attr_group,
+ NULL
+};
+
/**
* ice_sf_eth_activate - Activate Ethernet subfunction port
* @dyn_port: the dynamic port instance for this subfunction
@@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
sf_dev->dyn_port = dyn_port;
sf_dev->adev.id = id;
sf_dev->adev.name = "sf";
+ sf_dev->adev.dev.groups = ice_sf_attr_groups;
sf_dev->adev.dev.release = ice_sf_dev_release;
sf_dev->adev.dev.parent = &pdev->dev;
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 08/15] ice: store SF data in VSI struct
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (6 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 09/15] ice: store representor ID in bridge port Michal Swiatkowski
` (6 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Store subfunction pointer in VSI struct. The same is done for VF
pointer. Make union of subfunction and VF pointer as only one of them
can be set with one VSI.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice.h | 7 ++++++-
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index 767ea80684e7..4d35480178bc 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -352,7 +352,12 @@ struct ice_vsi {
u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */
- struct ice_vf *vf; /* VF associated with this VSI */
+ union {
+ /* VF associated with this VSI */
+ struct ice_vf *vf;
+ /* SF associated with this VSI */
+ struct ice_dynamic_port *sf;
+ };
u16 num_gfltr;
u16 num_bfltr;
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index abee733710a5..55db2e4beb72 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -117,6 +117,7 @@ static int ice_sf_dev_probe(struct auxiliary_device *adev,
dev_err(dev, "Subfunction vsi config failed");
return err;
}
+ vsi->sf = dyn_port;
err = ice_devlink_create_sf_dev_port(sf_dev);
if (err)
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 09/15] ice: store representor ID in bridge port
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (7 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 08/15] ice: store SF data in VSI struct Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 10/15] ice: create port representor for SF Michal Swiatkowski
` (5 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
It is used to get representor structure during cleaning.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 4 +++-
drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 1 +
drivers/net/ethernet/intel/ice/ice_repr.c | 7 ++-----
drivers/net/ethernet/intel/ice/ice_repr.h | 1 +
4 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
index ac5beecd028b..f5aceb32bf4d 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
@@ -896,7 +896,8 @@ ice_eswitch_br_port_deinit(struct ice_esw_br *bridge,
if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back) {
vsi->back->br_port = NULL;
} else {
- struct ice_repr *repr = ice_repr_get_by_vsi(vsi);
+ struct ice_repr *repr =
+ ice_repr_get(vsi->back, br_port->repr_id);
if (repr)
repr->br_port = NULL;
@@ -937,6 +938,7 @@ ice_eswitch_br_vf_repr_port_init(struct ice_esw_br *bridge,
br_port->vsi = repr->src_vsi;
br_port->vsi_idx = br_port->vsi->idx;
br_port->type = ICE_ESWITCH_BR_VF_REPR_PORT;
+ br_port->repr_id = repr->id;
repr->br_port = br_port;
err = xa_insert(&bridge->ports, br_port->vsi_idx, br_port, GFP_KERNEL);
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
index 85a8fadb2928..c15c7344d7f8 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
@@ -46,6 +46,7 @@ struct ice_esw_br_port {
enum ice_esw_br_port_type type;
u16 vsi_idx;
u16 pvid;
+ u32 repr_id;
struct xarray vlans;
};
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 7d066ea0caa0..414760a872a9 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -449,12 +449,9 @@ struct ice_repr *ice_repr_add_vf(struct ice_vf *vf)
return ERR_PTR(err);
}
-struct ice_repr *ice_repr_get_by_vsi(struct ice_vsi *vsi)
+struct ice_repr *ice_repr_get(struct ice_pf *pf, u32 id)
{
- if (!vsi->vf)
- return NULL;
-
- return xa_load(&vsi->back->eswitch.reprs, vsi->vf->repr_id);
+ return xa_load(&pf->eswitch.reprs, id);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h
index cff730b15ca0..07842620d7a2 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.h
+++ b/drivers/net/ethernet/intel/ice/ice_repr.h
@@ -40,4 +40,5 @@ struct ice_repr *ice_repr_get_by_vsi(struct ice_vsi *vsi);
void ice_repr_inc_tx_stats(struct ice_repr *repr, unsigned int len,
int xmit_status);
void ice_repr_inc_rx_stats(struct net_device *netdev, unsigned int len);
+struct ice_repr *ice_repr_get(struct ice_pf *pf, u32 id);
#endif
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 10/15] ice: create port representor for SF
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (8 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 09/15] ice: store representor ID in bridge port Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 9:00 ` Jiri Pirko
2024-02-13 7:27 ` [iwl-next v1 11/15] ice: check if SF is ready in ethtool ops Michal Swiatkowski
` (4 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Store subfunction and VF pointer in port representor structure as an
union. Add port representor type to distinguish between each of them.
Keep the same flow of port representor creation, but instead of general
attach function create helpers for VF and subfunction attach function.
Type of port representor can be also known based on VSI type, but it
is more clean to have it directly saved in port representor structure.
Create port representor when subfunction port is activated.
Add devlink lock for whole VF port representor creationi and destruction.
It is done to be symmetric with what happens in case of SF port
representor. SF port representor is always added or removed with devlink
lock taken. Doing the same with VF port representor simplify logic.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
.../intel/ice/devlink/ice_devlink_port.c | 4 +-
.../intel/ice/devlink/ice_devlink_port.h | 1 +
drivers/net/ethernet/intel/ice/ice_eswitch.c | 82 ++++++++++---
drivers/net/ethernet/intel/ice/ice_eswitch.h | 22 +++-
drivers/net/ethernet/intel/ice/ice_repr.c | 110 +++++++++++-------
drivers/net/ethernet/intel/ice/ice_repr.h | 21 +++-
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 11 ++
drivers/net/ethernet/intel/ice/ice_sriov.c | 4 +-
drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +-
10 files changed, 184 insertions(+), 77 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
index 33f290fed3d8..33171020a612 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
@@ -412,7 +412,7 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)
devlink_port_attrs_set(devlink_port, &attrs);
devlink = priv_to_devlink(pf);
- err = devlink_port_register(devlink, devlink_port, vsi->idx);
+ err = devl_port_register(devlink, devlink_port, vsi->idx);
if (err) {
dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
vf->vf_id, err);
@@ -431,7 +431,7 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)
void ice_devlink_destroy_vf_port(struct ice_vf *vf)
{
devl_rate_leaf_destroy(&vf->devlink_port);
- devlink_port_unregister(&vf->devlink_port);
+ devl_port_unregister(&vf->devlink_port);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
index 96d57ed54d7f..cb46e1ab9ca8 100644
--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
@@ -23,6 +23,7 @@ struct ice_dynamic_port {
struct devlink_port devlink_port;
struct ice_pf *pf;
struct ice_vsi *vsi;
+ unsigned long repr_id;
/* Flavour-specific implementation data */
union {
struct ice_sf_dev *sf_dev;
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index af4e9530eb48..50985a3732c0 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -417,10 +417,9 @@ static void ice_eswitch_start_reprs(struct ice_pf *pf)
ice_eswitch_start_all_tx_queues(pf);
}
-int
-ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
+static int
+ice_eswitch_attach(struct ice_pf *pf, struct ice_repr *repr, unsigned long *id)
{
- struct ice_repr *repr;
int err;
if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY)
@@ -434,11 +433,9 @@ ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
ice_eswitch_stop_reprs(pf);
- repr = ice_repr_add_vf(vf);
- if (IS_ERR(repr)) {
- err = PTR_ERR(repr);
+ err = repr->ops.add(repr);
+ if (err)
goto err_create_repr;
- }
err = ice_eswitch_setup_repr(pf, repr);
if (err)
@@ -448,7 +445,7 @@ ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
if (err)
goto err_xa_alloc;
- vf->repr_id = repr->id;
+ *id = repr->id;
ice_eswitch_start_reprs(pf);
@@ -457,7 +454,7 @@ ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
err_xa_alloc:
ice_eswitch_release_repr(pf, repr);
err_setup_repr:
- ice_repr_rem_vf(repr);
+ repr->ops.rem(repr);
err_create_repr:
if (xa_empty(&pf->eswitch.reprs))
ice_eswitch_disable_switchdev(pf);
@@ -466,14 +463,41 @@ ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
return err;
}
-void ice_eswitch_detach(struct ice_pf *pf, struct ice_vf *vf)
+int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)
{
- struct ice_repr *repr = xa_load(&pf->eswitch.reprs, vf->repr_id);
+ struct ice_repr *repr = ice_repr_create_vf(vf);
struct devlink *devlink = priv_to_devlink(pf);
+ int err;
- if (!repr)
- return;
+ if (IS_ERR(repr))
+ return PTR_ERR(repr);
+
+ devl_lock(devlink);
+ err = ice_eswitch_attach(pf, repr, &vf->repr_id);
+ if (err)
+ ice_repr_destroy(repr);
+ devl_unlock(devlink);
+
+ return err;
+}
+
+int ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
+{
+ struct ice_repr *repr = ice_repr_create_sf(sf);
+ int err;
+
+ if (IS_ERR(repr))
+ return PTR_ERR(repr);
+
+ err = ice_eswitch_attach(pf, repr, &sf->repr_id);
+ if (err)
+ ice_repr_destroy(repr);
+
+ return err;
+}
+static void ice_eswitch_detach(struct ice_pf *pf, struct ice_repr *repr)
+{
ice_eswitch_stop_reprs(pf);
xa_erase(&pf->eswitch.reprs, repr->id);
@@ -481,21 +505,45 @@ void ice_eswitch_detach(struct ice_pf *pf, struct ice_vf *vf)
ice_eswitch_disable_switchdev(pf);
ice_eswitch_release_repr(pf, repr);
- ice_repr_rem_vf(repr);
+ repr->ops.rem(repr);
+ ice_repr_destroy(repr);
if (xa_empty(&pf->eswitch.reprs)) {
+ struct devlink *devlink = priv_to_devlink(pf);
+
/* since all port representors are destroyed, there is
* no point in keeping the nodes
*/
ice_devlink_rate_clear_tx_topology(ice_get_main_vsi(pf));
- devl_lock(devlink);
devl_rate_nodes_destroy(devlink);
- devl_unlock(devlink);
} else {
ice_eswitch_start_reprs(pf);
}
}
+void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf)
+{
+ struct ice_repr *repr = xa_load(&pf->eswitch.reprs, vf->repr_id);
+ struct devlink *devlink = priv_to_devlink(pf);
+
+ if (!repr)
+ return;
+
+ devl_lock(devlink);
+ ice_eswitch_detach(pf, repr);
+ devl_unlock(devlink);
+}
+
+void ice_eswitch_detach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
+{
+ struct ice_repr *repr = xa_load(&pf->eswitch.reprs, sf->repr_id);
+
+ if (!repr)
+ return;
+
+ ice_eswitch_detach(pf, repr);
+}
+
/**
* ice_eswitch_rebuild - rebuild eswitch
* @pf: pointer to PF structure
@@ -509,7 +557,7 @@ void ice_eswitch_rebuild(struct ice_pf *pf)
return;
xa_for_each(&pf->eswitch.reprs, id, repr)
- ice_eswitch_detach(pf, repr->vf);
+ ice_eswitch_detach(pf, repr);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h
index e2e5c0c75e7d..72349fe18f1b 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h
@@ -5,11 +5,13 @@
#define _ICE_ESWITCH_H_
#include <net/devlink.h>
+#include "devlink/ice_devlink_port.h"
#ifdef CONFIG_ICE_SWITCHDEV
-void ice_eswitch_detach(struct ice_pf *pf, struct ice_vf *vf);
-int
-ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf);
+void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf);
+void ice_eswitch_detach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf);
+int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf);
+int ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf);
void ice_eswitch_rebuild(struct ice_pf *pf);
int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode);
@@ -29,10 +31,20 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
struct net_device *ice_eswitch_get_target(struct ice_rx_ring *rx_ring,
union ice_32b_rx_flex_desc *rx_desc);
#else /* CONFIG_ICE_SWITCHDEV */
-static inline void ice_eswitch_detach(struct ice_pf *pf, struct ice_vf *vf) { }
+static inline void
+ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf) { }
+
+static inline void
+ice_eswitch_detach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf) { }
+
+static inline int
+ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)
+{
+ return -EOPNOTSUPP;
+}
static inline int
-ice_eswitch_attach(struct ice_pf *pf, struct ice_vf *vf)
+ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
{
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 414760a872a9..7047fea66f4f 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -317,35 +317,27 @@ ice_repr_reg_netdev(struct net_device *netdev)
return register_netdev(netdev);
}
-static void ice_repr_remove_node(struct devlink_port *devlink_port)
-{
- devl_lock(devlink_port->devlink);
- devl_rate_leaf_destroy(devlink_port);
- devl_unlock(devlink_port->devlink);
-}
-
/**
- * ice_repr_rem - remove representor from VF
+ * ice_repr_destroy - remove representor from VF
* @repr: pointer to representor structure
*/
-static void ice_repr_rem(struct ice_repr *repr)
+void ice_repr_destroy(struct ice_repr *repr)
{
free_percpu(repr->stats);
free_netdev(repr->netdev);
kfree(repr);
}
-/**
- * ice_repr_rem_vf - remove representor from VF
- * @repr: pointer to representor structure
- */
-void ice_repr_rem_vf(struct ice_repr *repr)
+static void ice_repr_rem_vf(struct ice_repr *repr)
{
- ice_repr_remove_node(&repr->vf->devlink_port);
unregister_netdev(repr->netdev);
ice_devlink_destroy_vf_port(repr->vf);
ice_virtchnl_set_dflt_ops(repr->vf);
- ice_repr_rem(repr);
+}
+
+static void ice_repr_rem_sf(struct ice_repr *repr)
+{
+ unregister_netdev(repr->netdev);
}
static void ice_repr_set_tx_topology(struct ice_pf *pf)
@@ -363,12 +355,9 @@ static void ice_repr_set_tx_topology(struct ice_pf *pf)
/**
* ice_repr_add - add representor for generic VSI
- * @pf: pointer to PF structure
* @src_vsi: pointer to VSI structure of device to represent
- * @parent_mac: device MAC address
*/
-static struct ice_repr *
-ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac)
+static struct ice_repr *ice_repr_create(struct ice_vsi *src_vsi)
{
struct ice_netdev_priv *np;
struct ice_repr *repr;
@@ -395,7 +384,10 @@ ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac)
np = netdev_priv(repr->netdev);
np->repr = repr;
- ether_addr_copy(repr->parent_mac, parent_mac);
+ repr->netdev->min_mtu = ETH_MIN_MTU;
+ repr->netdev->max_mtu = ICE_MAX_MTU;
+
+ SET_NETDEV_DEV(repr->netdev, ice_pf_to_dev(src_vsi->back));
return repr;
@@ -406,32 +398,15 @@ ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac)
return ERR_PTR(err);
}
-struct ice_repr *ice_repr_add_vf(struct ice_vf *vf)
+static int ice_repr_add_vf(struct ice_repr *repr)
{
- struct ice_repr *repr;
- struct ice_vsi *vsi;
+ struct ice_vf *vf = repr->vf;
int err;
- vsi = ice_get_vf_vsi(vf);
- if (!vsi)
- return ERR_PTR(-ENOENT);
-
err = ice_devlink_create_vf_port(vf);
if (err)
- return ERR_PTR(err);
-
- repr = ice_repr_add(vf->pf, vsi, vf->hw_lan_addr);
- if (IS_ERR(repr)) {
- err = PTR_ERR(repr);
- goto err_repr_add;
- }
-
- repr->vf = vf;
+ return err;
- repr->netdev->min_mtu = ETH_MIN_MTU;
- repr->netdev->max_mtu = ICE_MAX_MTU;
-
- SET_NETDEV_DEV(repr->netdev, ice_pf_to_dev(vf->pf));
SET_NETDEV_DEVLINK_PORT(repr->netdev, &vf->devlink_port);
err = ice_repr_reg_netdev(repr->netdev);
if (err)
@@ -440,13 +415,58 @@ struct ice_repr *ice_repr_add_vf(struct ice_vf *vf)
ice_virtchnl_set_repr_ops(vf);
ice_repr_set_tx_topology(vf->pf);
- return repr;
+ return 0;
err_netdev:
- ice_repr_rem(repr);
-err_repr_add:
ice_devlink_destroy_vf_port(vf);
- return ERR_PTR(err);
+ return err;
+}
+
+struct ice_repr *ice_repr_create_vf(struct ice_vf *vf)
+{
+ struct ice_vsi *vsi = ice_get_vf_vsi(vf);
+ struct ice_repr *repr;
+
+ if (!vsi)
+ return ERR_PTR(-EINVAL);
+
+ repr = ice_repr_create(vsi);
+ if (!repr)
+ return ERR_PTR(-ENOMEM);
+
+ repr->type = ICE_REPR_TYPE_VF;
+ repr->vf = vf;
+ repr->ops.add = ice_repr_add_vf;
+ repr->ops.rem = ice_repr_rem_vf;
+
+ ether_addr_copy(repr->parent_mac, vf->hw_lan_addr);
+
+ return repr;
+}
+
+static int ice_repr_add_sf(struct ice_repr *repr)
+{
+ struct ice_dynamic_port *sf = repr->sf;
+
+ SET_NETDEV_DEVLINK_PORT(repr->netdev, &sf->devlink_port);
+ return ice_repr_reg_netdev(repr->netdev);
+}
+
+struct ice_repr *ice_repr_create_sf(struct ice_dynamic_port *sf)
+{
+ struct ice_repr *repr = ice_repr_create(sf->vsi);
+
+ if (!repr)
+ return ERR_PTR(-ENOMEM);
+
+ repr->type = ICE_REPR_TYPE_SF;
+ repr->sf = sf;
+ repr->ops.add = ice_repr_add_sf;
+ repr->ops.rem = ice_repr_rem_sf;
+
+ ether_addr_copy(repr->parent_mac, sf->hw_addr);
+
+ return repr;
}
struct ice_repr *ice_repr_get(struct ice_pf *pf, u32 id)
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h
index 07842620d7a2..dcba07899877 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.h
+++ b/drivers/net/ethernet/intel/ice/ice_repr.h
@@ -15,19 +15,34 @@ struct ice_repr_pcpu_stats {
u64 tx_drops;
};
+enum ice_repr_type {
+ ICE_REPR_TYPE_VF,
+ ICE_REPR_TYPE_SF,
+};
+
struct ice_repr {
struct ice_vsi *src_vsi;
- struct ice_vf *vf;
struct net_device *netdev;
struct metadata_dst *dst;
struct ice_esw_br_port *br_port;
struct ice_repr_pcpu_stats __percpu *stats;
u32 id;
u8 parent_mac[ETH_ALEN];
+ enum ice_repr_type type;
+ union {
+ struct ice_vf *vf;
+ struct ice_dynamic_port *sf;
+ };
+ struct {
+ int (*add)(struct ice_repr *repr);
+ void (*rem)(struct ice_repr *repr);
+ } ops;
};
-struct ice_repr *ice_repr_add_vf(struct ice_vf *vf);
-void ice_repr_rem_vf(struct ice_repr *repr);
+struct ice_repr *ice_repr_create_vf(struct ice_vf *vf);
+struct ice_repr *ice_repr_create_sf(struct ice_dynamic_port *sf);
+
+void ice_repr_destroy(struct ice_repr *repr);
void ice_repr_start_tx_queues(struct ice_repr *repr);
void ice_repr_stop_tx_queues(struct ice_repr *repr);
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index 55db2e4beb72..3d30dfaed7d7 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -309,10 +309,19 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
goto aux_dev_uninit;
}
+ err = ice_eswitch_attach_sf(pf, dyn_port);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Failed to attach device to eswitch");
+ goto aux_dev_remove;
+ }
+
dyn_port->sf_dev = sf_dev;
return 0;
+aux_dev_remove:
+ auxiliary_device_delete(&sf_dev->adev);
aux_dev_uninit:
auxiliary_device_uninit(&sf_dev->adev);
sf_dev_free:
@@ -334,6 +343,8 @@ void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
{
struct ice_sf_dev *sf_dev = dyn_port->sf_dev;
+ ice_eswitch_detach_sf(dyn_port->pf, dyn_port);
+
if (sf_dev) {
auxiliary_device_delete(&sf_dev->adev);
auxiliary_device_uninit(&sf_dev->adev);
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 706b5ee8ec89..c2fffc179dc4 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -175,7 +175,7 @@ void ice_free_vfs(struct ice_pf *pf)
ice_for_each_vf(pf, bkt, vf) {
mutex_lock(&vf->cfg_lock);
- ice_eswitch_detach(pf, vf);
+ ice_eswitch_detach_vf(pf, vf);
ice_dis_vf_qs(vf);
if (test_bit(ICE_VF_STATE_INIT, vf->vf_states)) {
@@ -598,7 +598,7 @@ static int ice_start_vfs(struct ice_pf *pf)
goto teardown;
}
- retval = ice_eswitch_attach(pf, vf);
+ retval = ice_eswitch_attach_vf(pf, vf);
if (retval) {
dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d",
vf->vf_id, retval);
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 97d41d6ebf1f..4e4c5d480e2d 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -2406,7 +2406,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
ICE_TXD_CTX_QW1_CMD_S);
ice_tstamp(tx_ring, skb, first, &offload);
- if (ice_is_switchdev_running(vsi->back))
+ if (ice_is_switchdev_running(vsi->back) && vsi->type != ICE_VSI_SF)
ice_eswitch_set_target_vsi(skb, &offload);
if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) {
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index 2ffdae9a82df..1bd68d0c9823 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -775,7 +775,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
ice_for_each_vf(pf, bkt, vf) {
mutex_lock(&vf->cfg_lock);
- ice_eswitch_detach(pf, vf);
+ ice_eswitch_detach_vf(pf, vf);
vf->driver_caps = 0;
ice_vc_set_default_allowlist(vf);
@@ -791,7 +791,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
ice_vf_rebuild_vsi(vf);
ice_vf_post_vsi_rebuild(vf);
- ice_eswitch_attach(pf, vf);
+ ice_eswitch_attach_vf(pf, vf);
mutex_unlock(&vf->cfg_lock);
}
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 11/15] ice: check if SF is ready in ethtool ops
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (9 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 10/15] ice: create port representor for SF Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 12/15] ice: netdevice ops for SF representor Michal Swiatkowski
` (3 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Now there is another type of port representor. Correct checking if
parent device is ready to reflect also new PR type.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_ethtool.c | 7 +++----
drivers/net/ethernet/intel/ice/ice_repr.c | 12 ++++++++++++
drivers/net/ethernet/intel/ice/ice_repr.h | 1 +
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index c862b21bad9f..8a46550860e6 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -4018,7 +4018,7 @@ ice_repr_get_drvinfo(struct net_device *netdev,
{
struct ice_repr *repr = ice_netdev_to_repr(netdev);
- if (ice_check_vf_ready_for_cfg(repr->vf))
+ if (repr->ops.ready(repr))
return;
__ice_get_drvinfo(netdev, drvinfo, repr->src_vsi);
@@ -4030,8 +4030,7 @@ ice_repr_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
struct ice_repr *repr = ice_netdev_to_repr(netdev);
/* for port representors only ETH_SS_STATS is supported */
- if (ice_check_vf_ready_for_cfg(repr->vf) ||
- stringset != ETH_SS_STATS)
+ if (repr->ops.ready(repr) || stringset != ETH_SS_STATS)
return;
__ice_get_strings(netdev, stringset, data, repr->src_vsi);
@@ -4044,7 +4043,7 @@ ice_repr_get_ethtool_stats(struct net_device *netdev,
{
struct ice_repr *repr = ice_netdev_to_repr(netdev);
- if (ice_check_vf_ready_for_cfg(repr->vf))
+ if (repr->ops.ready(repr))
return;
__ice_get_ethtool_stats(netdev, stats, data, repr->src_vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 7047fea66f4f..f0ae7a9000b4 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -317,6 +317,16 @@ ice_repr_reg_netdev(struct net_device *netdev)
return register_netdev(netdev);
}
+static int ice_repr_ready_vf(struct ice_repr *repr)
+{
+ return !ice_check_vf_ready_for_cfg(repr->vf);
+}
+
+static int ice_repr_ready_sf(struct ice_repr *repr)
+{
+ return !repr->sf->active;
+}
+
/**
* ice_repr_destroy - remove representor from VF
* @repr: pointer to representor structure
@@ -438,6 +448,7 @@ struct ice_repr *ice_repr_create_vf(struct ice_vf *vf)
repr->vf = vf;
repr->ops.add = ice_repr_add_vf;
repr->ops.rem = ice_repr_rem_vf;
+ repr->ops.ready = ice_repr_ready_vf;
ether_addr_copy(repr->parent_mac, vf->hw_lan_addr);
@@ -463,6 +474,7 @@ struct ice_repr *ice_repr_create_sf(struct ice_dynamic_port *sf)
repr->sf = sf;
repr->ops.add = ice_repr_add_sf;
repr->ops.rem = ice_repr_rem_sf;
+ repr->ops.ready = ice_repr_ready_sf;
ether_addr_copy(repr->parent_mac, sf->hw_addr);
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h
index dcba07899877..27def65614f3 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.h
+++ b/drivers/net/ethernet/intel/ice/ice_repr.h
@@ -36,6 +36,7 @@ struct ice_repr {
struct {
int (*add)(struct ice_repr *repr);
void (*rem)(struct ice_repr *repr);
+ int (*ready)(struct ice_repr *repr);
} ops;
};
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 12/15] ice: netdevice ops for SF representor
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (10 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 11/15] ice: check if SF is ready in ethtool ops Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 13/15] ice: support subfunction devlink Tx topology Michal Swiatkowski
` (2 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Subfunction port representor needs the basic netdevice ops to work
correctly. Create them.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_repr.c | 63 +++++++++++++++++------
1 file changed, 48 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index f0ae7a9000b4..125bcf2e4c00 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -32,7 +32,10 @@ ice_repr_get_phys_port_name(struct net_device *netdev, char *buf, size_t len)
int res;
/* Devlink port is registered and devlink core is taking care of name formatting. */
- if (repr->vf->devlink_port.devlink)
+ if ((repr->type == ICE_REPR_TYPE_VF &&
+ repr->vf->devlink_port.devlink) ||
+ (repr->type == ICE_REPR_TYPE_SF &&
+ repr->sf->devlink_port.devlink))
return -EOPNOTSUPP;
res = snprintf(buf, len, "pf%dvfr%d", ice_repr_get_sw_port_id(repr),
@@ -92,12 +95,13 @@ static void
ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
+ struct ice_repr *repr = np->repr;
struct ice_eth_stats *eth_stats;
struct ice_vsi *vsi;
- if (ice_is_vf_disabled(np->repr->vf))
+ if (repr->ops.ready(repr))
return;
- vsi = np->repr->src_vsi;
+ vsi = repr->src_vsi;
ice_update_vsi_stats(vsi);
eth_stats = &vsi->eth_stats;
@@ -126,7 +130,7 @@ struct ice_repr *ice_netdev_to_repr(const struct net_device *netdev)
}
/**
- * ice_repr_open - Enable port representor's network interface
+ * ice_repr_vf_open - Enable port representor's network interface
* @netdev: network interface device structure
*
* The open entry point is called when a port representor's network
@@ -135,7 +139,7 @@ struct ice_repr *ice_netdev_to_repr(const struct net_device *netdev)
*
* Returns 0 on success
*/
-static int ice_repr_open(struct net_device *netdev)
+static int ice_repr_vf_open(struct net_device *netdev)
{
struct ice_repr *repr = ice_netdev_to_repr(netdev);
struct ice_vf *vf;
@@ -151,8 +155,16 @@ static int ice_repr_open(struct net_device *netdev)
return 0;
}
+static int ice_repr_sf_open(struct net_device *netdev)
+{
+ netif_carrier_on(netdev);
+ netif_tx_start_all_queues(netdev);
+
+ return 0;
+}
+
/**
- * ice_repr_stop - Disable port representor's network interface
+ * ice_repr_vf_stop - Disable port representor's network interface
* @netdev: network interface device structure
*
* The stop entry point is called when a port representor's network
@@ -161,7 +173,7 @@ static int ice_repr_open(struct net_device *netdev)
*
* Returns 0 on success
*/
-static int ice_repr_stop(struct net_device *netdev)
+static int ice_repr_vf_stop(struct net_device *netdev)
{
struct ice_repr *repr = ice_netdev_to_repr(netdev);
struct ice_vf *vf;
@@ -177,6 +189,14 @@ static int ice_repr_stop(struct net_device *netdev)
return 0;
}
+static int ice_repr_sf_stop(struct net_device *netdev)
+{
+ netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
+
+ return 0;
+}
+
/**
* ice_repr_sp_stats64 - get slow path stats for port representor
* @dev: network interface device structure
@@ -278,11 +298,22 @@ ice_repr_setup_tc(struct net_device *netdev, enum tc_setup_type type,
}
}
-static const struct net_device_ops ice_repr_netdev_ops = {
+static const struct net_device_ops ice_repr_vf_netdev_ops = {
+ .ndo_get_phys_port_name = ice_repr_get_phys_port_name,
+ .ndo_get_stats64 = ice_repr_get_stats64,
+ .ndo_open = ice_repr_vf_open,
+ .ndo_stop = ice_repr_vf_stop,
+ .ndo_start_xmit = ice_eswitch_port_start_xmit,
+ .ndo_setup_tc = ice_repr_setup_tc,
+ .ndo_has_offload_stats = ice_repr_ndo_has_offload_stats,
+ .ndo_get_offload_stats = ice_repr_ndo_get_offload_stats,
+};
+
+static const struct net_device_ops ice_repr_sf_netdev_ops = {
.ndo_get_phys_port_name = ice_repr_get_phys_port_name,
.ndo_get_stats64 = ice_repr_get_stats64,
- .ndo_open = ice_repr_open,
- .ndo_stop = ice_repr_stop,
+ .ndo_open = ice_repr_sf_open,
+ .ndo_stop = ice_repr_sf_stop,
.ndo_start_xmit = ice_eswitch_port_start_xmit,
.ndo_setup_tc = ice_repr_setup_tc,
.ndo_has_offload_stats = ice_repr_ndo_has_offload_stats,
@@ -295,18 +326,20 @@ static const struct net_device_ops ice_repr_netdev_ops = {
*/
bool ice_is_port_repr_netdev(const struct net_device *netdev)
{
- return netdev && (netdev->netdev_ops == &ice_repr_netdev_ops);
+ return netdev && (netdev->netdev_ops == &ice_repr_vf_netdev_ops ||
+ netdev->netdev_ops == &ice_repr_sf_netdev_ops);
}
/**
* ice_repr_reg_netdev - register port representor netdev
* @netdev: pointer to port representor netdev
+ * @ops: new ops for netdev
*/
static int
-ice_repr_reg_netdev(struct net_device *netdev)
+ice_repr_reg_netdev(struct net_device *netdev, const struct net_device_ops *ops)
{
eth_hw_addr_random(netdev);
- netdev->netdev_ops = &ice_repr_netdev_ops;
+ netdev->netdev_ops = ops;
ice_set_ethtool_repr_ops(netdev);
netdev->hw_features |= NETIF_F_HW_TC;
@@ -418,7 +451,7 @@ static int ice_repr_add_vf(struct ice_repr *repr)
return err;
SET_NETDEV_DEVLINK_PORT(repr->netdev, &vf->devlink_port);
- err = ice_repr_reg_netdev(repr->netdev);
+ err = ice_repr_reg_netdev(repr->netdev, &ice_repr_vf_netdev_ops);
if (err)
goto err_netdev;
@@ -460,7 +493,7 @@ static int ice_repr_add_sf(struct ice_repr *repr)
struct ice_dynamic_port *sf = repr->sf;
SET_NETDEV_DEVLINK_PORT(repr->netdev, &sf->devlink_port);
- return ice_repr_reg_netdev(repr->netdev);
+ return ice_repr_reg_netdev(repr->netdev, &ice_repr_sf_netdev_ops);
}
struct ice_repr *ice_repr_create_sf(struct ice_dynamic_port *sf)
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 13/15] ice: support subfunction devlink Tx topology
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (11 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 12/15] ice: netdevice ops for SF representor Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 14/15] ice: basic support for VLAN in subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 15/15] ice: move ice_devlink.[ch] to devlink folder Michal Swiatkowski
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Flow for creating Tx topology is the same as for VF port representors,
but the devlink port is stored in different place (sf->devlink_port).
When creating VF devlink lock isn't taken, when creating subfunction it
is. Setting Tx topology function needs to take this lock, check if it
was taken before to not do it twice.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/ice_devlink.c | 14 ++++++++++++--
drivers/net/ethernet/intel/ice/ice_repr.c | 14 +++++++++-----
2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index 6278ff3eb7c9..503e175140ad 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -595,6 +595,7 @@ static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node
struct ice_sched_node *tc_node, struct ice_pf *pf)
{
struct devlink_rate *rate_node = NULL;
+ struct ice_dynamic_port *sf;
struct ice_vf *vf;
int i;
@@ -606,6 +607,7 @@ static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node
/* create root node */
rate_node = devl_rate_node_create(devlink, node, node->name, NULL);
} else if (node->vsi_handle &&
+ pf->vsi[node->vsi_handle]->type == ICE_VSI_VF &&
pf->vsi[node->vsi_handle]->vf) {
vf = pf->vsi[node->vsi_handle]->vf;
if (!vf->devlink_port.devlink_rate)
@@ -614,6 +616,16 @@ static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node
*/
devl_rate_leaf_create(&vf->devlink_port, node,
node->parent->rate_node);
+ } else if (node->vsi_handle &&
+ pf->vsi[node->vsi_handle]->type == ICE_VSI_SF &&
+ pf->vsi[node->vsi_handle]->sf) {
+ sf = pf->vsi[node->vsi_handle]->sf;
+ if (!sf->devlink_port.devlink_rate)
+ /* leaf nodes doesn't have children
+ * so we don't set rate_node
+ */
+ devl_rate_leaf_create(&sf->devlink_port, node,
+ node->parent->rate_node);
} else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF &&
node->parent->rate_node) {
rate_node = devl_rate_node_create(devlink, node, node->name,
@@ -645,10 +657,8 @@ int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *v
tc_node = pi->root->children[0];
mutex_lock(&pi->sched_lock);
- devl_lock(devlink);
for (i = 0; i < tc_node->num_children; i++)
ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf);
- devl_unlock(devlink);
mutex_unlock(&pi->sched_lock);
return 0;
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 125bcf2e4c00..fb0171afa43e 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -380,19 +380,17 @@ static void ice_repr_rem_vf(struct ice_repr *repr)
static void ice_repr_rem_sf(struct ice_repr *repr)
{
+ devl_rate_leaf_destroy(&repr->sf->devlink_port);
unregister_netdev(repr->netdev);
}
-static void ice_repr_set_tx_topology(struct ice_pf *pf)
+static void ice_repr_set_tx_topology(struct ice_pf *pf, struct devlink *devlink)
{
- struct devlink *devlink;
-
/* only export if ADQ and DCB disabled and eswitch enabled*/
if (ice_is_adq_active(pf) || ice_is_dcb_active(pf) ||
!ice_is_switchdev_running(pf))
return;
- devlink = priv_to_devlink(pf);
ice_devlink_rate_init_tx_topology(devlink, ice_get_main_vsi(pf));
}
@@ -444,6 +442,7 @@ static struct ice_repr *ice_repr_create(struct ice_vsi *src_vsi)
static int ice_repr_add_vf(struct ice_repr *repr)
{
struct ice_vf *vf = repr->vf;
+ struct devlink *devlink;
int err;
err = ice_devlink_create_vf_port(vf);
@@ -456,7 +455,9 @@ static int ice_repr_add_vf(struct ice_repr *repr)
goto err_netdev;
ice_virtchnl_set_repr_ops(vf);
- ice_repr_set_tx_topology(vf->pf);
+
+ devlink = priv_to_devlink(vf->pf);
+ ice_repr_set_tx_topology(vf->pf, devlink);
return 0;
@@ -493,6 +494,9 @@ static int ice_repr_add_sf(struct ice_repr *repr)
struct ice_dynamic_port *sf = repr->sf;
SET_NETDEV_DEVLINK_PORT(repr->netdev, &sf->devlink_port);
+
+ ice_repr_set_tx_topology(sf->vsi->back, priv_to_devlink(sf->vsi->back));
+
return ice_repr_reg_netdev(repr->netdev, &ice_repr_sf_netdev_ops);
}
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 14/15] ice: basic support for VLAN in subfunctions
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (12 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 13/15] ice: support subfunction devlink Tx topology Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 15/15] ice: move ice_devlink.[ch] to devlink folder Michal Swiatkowski
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Implement add / delete vlan for subfunction type VSI.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/Makefile | 1 +
.../ethernet/intel/ice/ice_sf_vsi_vlan_ops.c | 21 +++++++++++++++++++
.../ethernet/intel/ice/ice_sf_vsi_vlan_ops.h | 13 ++++++++++++
.../net/ethernet/intel/ice/ice_vsi_vlan_ops.c | 4 ++++
4 files changed, 39 insertions(+)
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.c
create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.h
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index d56a7165df95..6f350d8624d7 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -32,6 +32,7 @@ ice-y := ice_main.o \
ice_devlink.o \
devlink/ice_devlink_port.o \
ice_sf_eth.o \
+ ice_sf_vsi_vlan_ops.o \
ice_ddp.o \
ice_fw_update.o \
ice_lag.o \
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.c b/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.c
new file mode 100644
index 000000000000..3d7e96721cf9
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023, Intel Corporation. */
+
+#include "ice_vsi_vlan_ops.h"
+#include "ice_vsi_vlan_lib.h"
+#include "ice_vlan_mode.h"
+#include "ice.h"
+#include "ice_sf_vsi_vlan_ops.h"
+
+void ice_sf_vsi_init_vlan_ops(struct ice_vsi *vsi)
+{
+ struct ice_vsi_vlan_ops *vlan_ops;
+
+ if (ice_is_dvm_ena(&vsi->back->hw))
+ vlan_ops = &vsi->outer_vlan_ops;
+ else
+ vlan_ops = &vsi->inner_vlan_ops;
+
+ vlan_ops->add_vlan = ice_vsi_add_vlan;
+ vlan_ops->del_vlan = ice_vsi_del_vlan;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.h b/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.h
new file mode 100644
index 000000000000..8c44eafceea0
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_sf_vsi_vlan_ops.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2023, Intel Corporation. */
+
+#ifndef _ICE_SF_VSI_VLAN_OPS_H_
+#define _ICE_SF_VSI_VLAN_OPS_H_
+
+#include "ice_vsi_vlan_ops.h"
+
+struct ice_vsi;
+
+void ice_sf_vsi_init_vlan_ops(struct ice_vsi *vsi);
+
+#endif /* _ICE_SF_VSI_VLAN_OPS_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.c b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.c
index 7aae7fdcfcdb..8c7a9b41fb63 100644
--- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.c
+++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.c
@@ -3,6 +3,7 @@
#include "ice_pf_vsi_vlan_ops.h"
#include "ice_vf_vsi_vlan_ops.h"
+#include "ice_sf_vsi_vlan_ops.h"
#include "ice_lib.h"
#include "ice.h"
@@ -77,6 +78,9 @@ void ice_vsi_init_vlan_ops(struct ice_vsi *vsi)
case ICE_VSI_VF:
ice_vf_vsi_init_vlan_ops(vsi);
break;
+ case ICE_VSI_SF:
+ ice_sf_vsi_init_vlan_ops(vsi);
+ break;
default:
dev_dbg(ice_pf_to_dev(vsi->back), "%s does not support VLAN operations\n",
ice_vsi_type_str(vsi->type));
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [iwl-next v1 15/15] ice: move ice_devlink.[ch] to devlink folder
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
` (13 preceding siblings ...)
2024-02-13 7:27 ` [iwl-next v1 14/15] ice: basic support for VLAN in subfunctions Michal Swiatkowski
@ 2024-02-13 7:27 ` Michal Swiatkowski
14 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 7:27 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, jacob.e.keller, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Michal Swiatkowski
Only moving whole files, fixing Makefile and bunch of includes.
Some changes to ice_devlink file was done even in representor part (Tx
topology), so keep it as final patch to not mess up with rebasing.
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ice/Makefile | 2 +-
drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.c | 0
drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.h | 0
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 2 +-
drivers/net/ethernet/intel/ice/ice_eswitch.c | 2 +-
drivers/net/ethernet/intel/ice/ice_main.c | 2 +-
drivers/net/ethernet/intel/ice/ice_repr.c | 2 +-
drivers/net/ethernet/intel/ice/ice_sf_eth.c | 2 +-
8 files changed, 6 insertions(+), 6 deletions(-)
rename drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.c (100%)
rename drivers/net/ethernet/intel/ice/{ => devlink}/ice_devlink.h (100%)
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index 6f350d8624d7..895cec763637 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -29,7 +29,7 @@ ice-y := ice_main.o \
ice_flex_pipe.o \
ice_flow.o \
ice_idc.o \
- ice_devlink.o \
+ devlink/ice_devlink.o \
devlink/ice_devlink_port.o \
ice_sf_eth.o \
ice_sf_vsi_vlan_ops.o \
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink.c
similarity index 100%
rename from drivers/net/ethernet/intel/ice/ice_devlink.c
rename to drivers/net/ethernet/intel/ice/devlink/ice_devlink.c
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink.h
similarity index 100%
rename from drivers/net/ethernet/intel/ice/ice_devlink.h
rename to drivers/net/ethernet/intel/ice/devlink/ice_devlink.h
diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
index 63ce4920de4e..3f6661390151 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
@@ -3,7 +3,7 @@
#include "ice_dcb_lib.h"
#include "ice_dcb_nl.h"
-#include "ice_devlink.h"
+#include "devlink/ice_devlink.h"
/**
* ice_dcb_get_ena_tc - return bitmap of enabled TCs
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index 50985a3732c0..416728d0674f 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -7,7 +7,7 @@
#include "ice_eswitch_br.h"
#include "ice_fltr.h"
#include "ice_repr.h"
-#include "ice_devlink.h"
+#include "devlink/ice_devlink.h"
#include "ice_tc_lib.h"
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 7ff96da33e8d..5129bce8538a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -13,7 +13,7 @@
#include "ice_fltr.h"
#include "ice_dcb_lib.h"
#include "ice_dcb_nl.h"
-#include "ice_devlink.h"
+#include "devlink/ice_devlink.h"
#include "ice_hwmon.h"
#include "devlink/ice_devlink_port.h"
#include "ice_sf_eth.h"
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index fb0171afa43e..11ead0a0365d 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -3,7 +3,7 @@
#include "ice.h"
#include "ice_eswitch.h"
-#include "ice_devlink.h"
+#include "devlink/ice_devlink.h"
#include "devlink/ice_devlink_port.h"
#include "ice_sriov.h"
#include "ice_tc_lib.h"
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index 3d30dfaed7d7..f00aabb68f0f 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -6,7 +6,7 @@
#include "ice_txrx.h"
#include "ice_fltr.h"
#include "ice_sf_eth.h"
-#include "ice_devlink.h"
+#include "devlink/ice_devlink.h"
#include "devlink/ice_devlink_port.h"
static const struct net_device_ops ice_sf_netdev_ops = {
--
2.42.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 7:27 ` [iwl-next v1 04/15] ice: add basic devlink subfunctions support Michal Swiatkowski
@ 2024-02-13 8:55 ` Jiri Pirko
2024-02-13 9:39 ` [Intel-wired-lan] " Michal Swiatkowski
2024-02-14 19:45 ` Jacob Keller
0 siblings, 2 replies; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 8:55 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
>From: Piotr Raczynski <piotr.raczynski@intel.com>
>
>Implement devlink port handlers responsible for ethernet type devlink
>subfunctions. Create subfunction devlink port and setup all resources
>needed for a subfunction netdev to operate. Configure new VSI for each
>new subfunction, initialize and configure interrupts and Tx/Rx resources.
>Set correct MAC filters and create new netdev.
>
>For now, subfunction is limited to only one Tx/Rx queue pair.
>
>Only allocate new subfunction VSI with devlink port new command.
>This makes sure that real resources are configured only when a new
>subfunction gets activated. Allocate and free subfunction MSIX
>interrupt vectors using new API calls with pci_msix_alloc_irq_at
>and pci_msix_free_irq.
>
>Temporarily, before adding auxiliary bus driver for subfunctions,
>configure subfunction netdev directly for the created devlink
>port. This will be modified in the next patch to properly that handle
>devlink port as the port representor.
>
>Support both automatic and manual subfunction numbers. If no subfunction
>number is provided, use xa_alloc to pick a number automatically. This
>will find the first free index and use that as the number. This reduces
>burden on users in the simple case where a specific number is not
>required. It may also be slightly faster to check that a number exists
>since xarray lookup should be faster than a linear scan of the dyn_ports
>xarray.
>
>Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>Co-developed-by: Jacob Keller <jacob.e.keller@intel.com>
>Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
>Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>---
> drivers/net/ethernet/intel/ice/Makefile | 1 +
> .../intel/ice/devlink/ice_devlink_port.c | 508 ++++++++++++++++++
> .../intel/ice/devlink/ice_devlink_port.h | 30 ++
> drivers/net/ethernet/intel/ice/ice.h | 4 +
> drivers/net/ethernet/intel/ice/ice_devlink.c | 3 +
> drivers/net/ethernet/intel/ice/ice_lib.c | 5 +-
> drivers/net/ethernet/intel/ice/ice_lib.h | 2 +
> drivers/net/ethernet/intel/ice/ice_main.c | 14 +-
> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 138 +++++
> drivers/net/ethernet/intel/ice/ice_sf_eth.h | 15 +
> 10 files changed, 716 insertions(+), 4 deletions(-)
> create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.c
> create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.h
>
>diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
>index cd4ab46d72a7..d56a7165df95 100644
>--- a/drivers/net/ethernet/intel/ice/Makefile
>+++ b/drivers/net/ethernet/intel/ice/Makefile
>@@ -31,6 +31,7 @@ ice-y := ice_main.o \
> ice_idc.o \
> ice_devlink.o \
> devlink/ice_devlink_port.o \
>+ ice_sf_eth.o \
> ice_ddp.o \
> ice_fw_update.o \
> ice_lag.o \
>diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>index c8c823467fcf..90efceaddb02 100644
>--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>@@ -10,6 +10,8 @@
> #include "ice_eswitch.h"
> #include "ice_fw_update.h"
> #include "ice_dcb_lib.h"
>+#include "ice_sf_eth.h"
>+#include "ice_fltr.h"
>
> static int ice_active_port_option = -1;
>
>@@ -432,3 +434,509 @@ void ice_devlink_destroy_vf_port(struct ice_vf *vf)
> devlink_port_unregister(&vf->devlink_port);
> }
>
>+/**
>+ * ice_activate_dynamic_port - Activate a dynamic port
>+ * @dyn_port: dynamic port instance to activate
>+ * @extack: extack for reporting error messages
>+ *
>+ * Activate the dynamic port based on its flavour.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,
>+ struct netlink_ext_ack *extack)
>+{
>+ int err;
>+
>+ switch (dyn_port->devlink_port.attrs.flavour) {
>+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
Pointless switch case.
It looks like you have odd habbit of checking things that cannot happen
all over this patch :) See more below...
>+ err = ice_sf_eth_activate(dyn_port, extack);
>+ if (err)
>+ return err;
>+ break;
>+ default:
>+ NL_SET_ERR_MSG_MOD(extack, "Unsupported port flavour");
>+ return -EOPNOTSUPP;
>+ }
>+
>+ dyn_port->active = 1;
true?
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_deactivate_dynamic_port - Deactivate a dynamic port
>+ * @dyn_port: dynamic port instance to deactivate
>+ *
>+ * Undo activation of a dynamic port.
>+ */
>+static void ice_deactivate_dynamic_port(struct ice_dynamic_port *dyn_port)
>+{
>+ switch (dyn_port->devlink_port.attrs.flavour) {
>+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
Pointless switch case. Not possible to be anything else then
DEVLINK_PORT_FLAVOUR_PCI_SF.
>+ ice_sf_eth_deactivate(dyn_port);
>+ break;
>+ default:
>+ WARN(1, "Attempting to deactivate port with unexpected port flavour %d",
>+ dyn_port->devlink_port.attrs.flavour);
>+ }
>+
>+ dyn_port->active = 0;
false?
>+}
>+
>+/**
>+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
>+ * @dyn_port: dynamic port instance to deallocate
>+ *
>+ * Free resources associated with a dynamically added devlink port. Will
>+ * deactivate the port if its currently active.
>+ */
>+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
>+{
>+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
>+ struct ice_pf *pf = dyn_port->pf;
>+
>+ if (dyn_port->active)
>+ ice_deactivate_dynamic_port(dyn_port);
>+
>+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
I don't understand how this check could be false. Remove it.
>+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
>+
>+ devl_port_unregister(devlink_port);
>+ ice_vsi_free(dyn_port->vsi);
>+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
>+ kfree(dyn_port);
>+}
>+
>+/**
>+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
>+ * @pf: pointer to the pf structure
>+ */
>+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
>+{
>+ struct devlink *devlink = priv_to_devlink(pf);
>+ struct ice_dynamic_port *dyn_port;
>+ unsigned long index;
>+
>+ devl_lock(devlink);
>+ xa_for_each(&pf->dyn_ports, index, dyn_port)
>+ ice_dealloc_dynamic_port(dyn_port);
>+ devl_unlock(devlink);
Hmm, I would assume that the called should already hold the devlink
instance lock when doing remove. What is stopping user from issuing
port_new command here, after devl_unlock()?
>+}
>+
>+/**
>+ * ice_devlink_port_new_check_attr - Check that new port attributes are valid
>+ * @pf: pointer to the PF structure
>+ * @new_attr: the attributes for the new port
>+ * @extack: extack for reporting error messages
>+ *
>+ * Check that the attributes for the new port are valid before continuing to
>+ * allocate the devlink port.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_new_check_attr(struct ice_pf *pf,
>+ const struct devlink_port_new_attrs *new_attr,
>+ struct netlink_ext_ack *extack)
>+{
>+ if (new_attr->flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
>+ NL_SET_ERR_MSG_MOD(extack, "Flavour other than pcisf is not supported");
>+ return -EOPNOTSUPP;
>+ }
>+
>+ if (new_attr->controller_valid) {
>+ NL_SET_ERR_MSG_MOD(extack, "Setting controller is not supported");
>+ return -EOPNOTSUPP;
>+ }
>+
>+ if (new_attr->port_index_valid) {
>+ NL_SET_ERR_MSG_MOD(extack, "Port index is autogenerated by the driver");
Does not look like an error message. Please re-phrase.
>+ return -EOPNOTSUPP;
>+ }
>+
>+ if (new_attr->pfnum != pf->hw.bus.func) {
>+ NL_SET_ERR_MSG_MOD(extack, "Incorrect pfnum supplied");
>+ return -EINVAL;
>+ }
>+
>+ if (!pci_msix_can_alloc_dyn(pf->pdev)) {
>+ NL_SET_ERR_MSG_MOD(extack, "Dynamic MSIX-X interrupt allocation is not supported");
>+ return -EOPNOTSUPP;
>+ }
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_del - devlink handler for port delete
>+ * @devlink: pointer to devlink
>+ * @port: devlink port to be deleted
>+ * @extack: pointer to extack
>+ *
>+ * Deletes devlink port and deallocates all resources associated with
>+ * created subfunction.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_del(struct devlink *devlink, struct devlink_port *port,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+
>+ dyn_port = ice_devlink_port_to_dyn(port);
>+ if (!dyn_port) {
Can't happen. Remove the check.
>+ NL_SET_ERR_MSG_MOD(extack, "Failed to find Subfunction port with a given index");
>+ return -EINVAL;
>+ }
>+
>+ ice_dealloc_dynamic_port(dyn_port);
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_fn_hw_addr_set - devlink handler for mac address set
>+ * @port: pointer to devlink port
>+ * @hw_addr: hw address to set
>+ * @hw_addr_len: hw address length
>+ * @extack: extack for reporting error messages
>+ *
>+ * Sets mac address for the port, verifies arguments and copies address
>+ * to the subfunction structure.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr,
>+ int hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+
>+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
How exactly this can happen? It could not. Remove the check. Remove it
from the rest of the ops too.
>+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
>+ return -EOPNOTSUPP;
>+ }
>+
>+ dyn_port = ice_devlink_port_to_dyn(port);
>+
>+ if (hw_addr_len != ETH_ALEN || !is_valid_ether_addr(hw_addr)) {
>+ NL_SET_ERR_MSG_MOD(extack, "Invalid ethernet address");
>+ return -EADDRNOTAVAIL;
>+ }
>+
>+ if (ether_addr_equal(dyn_port->hw_addr, hw_addr)) {
>+ NL_SET_ERR_MSG_MOD(extack, "address already set");
You start with capital letter in the rest of the messages.
>+ return 0;
>+ }
>+
>+ ether_addr_copy(dyn_port->hw_addr, hw_addr);
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_fn_hw_addr_get - devlink handler for mac address get
>+ * @port: pointer to devlink port
>+ * @hw_addr: hw address to set
>+ * @hw_addr_len: hw address length
>+ * @extack: extack for reporting error messages
>+ *
>+ * Returns mac address for the port.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr,
>+ int *hw_addr_len,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+
>+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF)
>+ return -EOPNOTSUPP;
Pointless check.
>+
>+ dyn_port = ice_devlink_port_to_dyn(port);
>+
>+ ether_addr_copy(hw_addr, dyn_port->hw_addr);
>+ *hw_addr_len = ETH_ALEN;
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_fn_state_set - devlink handler for port state set
>+ * @port: pointer to devlink port
>+ * @state: state to set
>+ * @extack: extack for reporting error messages
>+ *
>+ * Activates or deactivates the port.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_fn_state_set(struct devlink_port *port,
>+ enum devlink_port_fn_state state,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+
>+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
>+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
>+ return -EOPNOTSUPP;
>+ }
Pointless check.
>+
>+ dyn_port = ice_devlink_port_to_dyn(port);
>+
>+ switch (state) {
>+ case DEVLINK_PORT_FN_STATE_ACTIVE:
>+ if (!dyn_port->active)
>+ return ice_activate_dynamic_port(dyn_port, extack);
>+ break;
>+ case DEVLINK_PORT_FN_STATE_INACTIVE:
>+ if (dyn_port->active)
>+ ice_deactivate_dynamic_port(dyn_port);
>+ break;
>+ }
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_port_fn_state_get - devlink handler for port state get
>+ * @port: pointer to devlink port
>+ * @state: admin configured state of the port
>+ * @opstate: current port operational state
>+ * @extack: extack for reporting error messages
>+ *
>+ * Gets port state.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_port_fn_state_get(struct devlink_port *port,
>+ enum devlink_port_fn_state *state,
>+ enum devlink_port_fn_opstate *opstate,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+
>+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
>+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
>+ return -EOPNOTSUPP;
>+ }
Pointless check.
>+
>+ dyn_port = ice_devlink_port_to_dyn(port);
>+
>+ if (dyn_port->active) {
>+ *state = DEVLINK_PORT_FN_STATE_ACTIVE;
>+ *opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
>+ } else {
>+ *state = DEVLINK_PORT_FN_STATE_INACTIVE;
>+ *opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;
>+ }
>+
>+ return 0;
>+}
>+
>+static const struct devlink_port_ops ice_devlink_port_sf_ops = {
>+ .port_del = ice_devlink_port_del,
>+ .port_fn_hw_addr_get = ice_devlink_port_fn_hw_addr_get,
>+ .port_fn_hw_addr_set = ice_devlink_port_fn_hw_addr_set,
>+ .port_fn_state_get = ice_devlink_port_fn_state_get,
>+ .port_fn_state_set = ice_devlink_port_fn_state_set,
>+};
>+
>+/**
>+ * ice_reserve_sf_num - Reserve a subfunction number for this port
>+ * @pf: pointer to the pf structure
>+ * @new_attr: devlink port attributes requested
>+ * @extack: extack for reporting error messages
>+ * @sfnum: on success, the sf number reserved
>+ *
>+ * Reserve a subfunction number for this port. Only called for
>+ * DEVLINK_PORT_FLAVOUR_PCI_SF ports.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_reserve_sf_num(struct ice_pf *pf,
>+ const struct devlink_port_new_attrs *new_attr,
>+ struct netlink_ext_ack *extack, u32 *sfnum)
>+{
>+ int err;
>+
>+ /* If user didn't request an explicit number, pick one */
>+ if (!new_attr->sfnum_valid)
>+ return xa_alloc(&pf->sf_nums, sfnum, NULL, xa_limit_32b,
>+ GFP_KERNEL);
>+
>+ /* Otherwise, check and use the number provided */
>+ err = xa_insert(&pf->sf_nums, new_attr->sfnum, NULL, GFP_KERNEL);
>+ if (err) {
>+ if (err == -EBUSY)
>+ NL_SET_ERR_MSG_MOD(extack, "Subfunction with given sfnum already exists");
>+ return err;
>+ }
>+
>+ *sfnum = new_attr->sfnum;
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_devlink_create_sf_port - Register PCI subfunction devlink port
>+ * @dyn_port: the dynamic port instance structure for this subfunction
>+ * @sfnum: the subfunction number to use for the port
>+ *
>+ * Register PCI subfunction flavour devlink port for a dynamically added
>+ * subfunction port.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_devlink_create_sf_port(struct ice_dynamic_port *dyn_port, u32 sfnum)
>+{
>+ struct devlink_port_attrs attrs = {};
>+ struct devlink_port *devlink_port;
>+ struct devlink *devlink;
>+ struct ice_vsi *vsi;
>+ struct device *dev;
>+ struct ice_pf *pf;
>+ int err;
>+
>+ vsi = dyn_port->vsi;
>+ pf = dyn_port->pf;
>+ dev = ice_pf_to_dev(pf);
>+
>+ devlink_port = &dyn_port->devlink_port;
>+
>+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_SF;
>+ attrs.pci_sf.pf = pf->hw.bus.func;
>+ attrs.pci_sf.sf = sfnum;
>+
>+ devlink_port_attrs_set(devlink_port, &attrs);
>+ devlink = priv_to_devlink(pf);
>+
>+ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
>+ &ice_devlink_port_sf_ops);
>+ if (err) {
>+ dev_err(dev, "Failed to create devlink port for Subfunction %d",
>+ vsi->idx);
>+ return err;
>+ }
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_alloc_dynamic_port - Allocate new dynamic port
>+ * @pf: pointer to the pf structure
>+ * @new_attr: devlink port attributes requested
>+ * @extack: extack for reporting error messages
>+ * @devlink_port: index of newly created devlink port
>+ *
>+ * Allocate a new dynamic port instance and prepare it for configuration
>+ * with devlink.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+static int
>+ice_alloc_dynamic_port(struct ice_pf *pf,
>+ const struct devlink_port_new_attrs *new_attr,
>+ struct netlink_ext_ack *extack,
>+ struct devlink_port **devlink_port)
>+{
>+ struct ice_dynamic_port *dyn_port;
>+ struct ice_vsi *vsi;
>+ u32 sfnum;
>+ int err;
>+
>+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF) {
>+ err = ice_reserve_sf_num(pf, new_attr, extack, &sfnum);
>+ if (err)
>+ return err;
>+ }
>+
>+ dyn_port = kzalloc(sizeof(*dyn_port), GFP_KERNEL);
>+ if (!dyn_port) {
>+ err = -ENOMEM;
>+ goto unroll_reserve_sf_num;
>+ }
>+
>+ vsi = ice_vsi_alloc(pf);
>+ if (!vsi) {
>+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate VSI");
>+ err = -ENOMEM;
>+ goto unroll_dyn_port_alloc;
>+ }
>+
>+ dyn_port->vsi = vsi;
>+ dyn_port->pf = pf;
>+ dyn_port->active = 0;
Pointless init, the memory is already zeroed.
>+ eth_random_addr(dyn_port->hw_addr);
>+
>+ err = xa_insert(&pf->dyn_ports, vsi->idx, dyn_port, GFP_KERNEL);
>+ if (err) {
>+ NL_SET_ERR_MSG_MOD(extack, "Port index reservation failed");
>+ goto unroll_vsi_alloc;
>+ }
>+
>+ err = ice_devlink_create_sf_port(dyn_port, sfnum);
>+ if (err) {
>+ NL_SET_ERR_MSG_MOD(extack, "Port registration failed");
>+ goto unroll_xa_insert;
>+ }
>+
>+ *devlink_port = &dyn_port->devlink_port;
>+
>+ return 0;
>+
>+unroll_xa_insert:
>+ xa_erase(&pf->dyn_ports, vsi->idx);
>+unroll_vsi_alloc:
>+ ice_vsi_free(vsi);
>+unroll_dyn_port_alloc:
>+ kfree(dyn_port);
>+unroll_reserve_sf_num:
>+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
>+ xa_erase(&pf->sf_nums, sfnum);
>+
>+ return err;
>+}
>+
>+/**
>+ * ice_devlink_port_new - devlink handler for the new port
>+ * @devlink: pointer to devlink
>+ * @new_attr: pointer to the port new attributes
>+ * @extack: extack for reporting error messages
>+ * @devlink_port: pointer to a new port
>+ *
>+ * Creates new devlink port, checks new port attributes and reject
>+ * any unsupported parameters, allocates new subfunction for that port.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+int
>+ice_devlink_port_new(struct devlink *devlink,
>+ const struct devlink_port_new_attrs *new_attr,
>+ struct netlink_ext_ack *extack,
>+ struct devlink_port **devlink_port)
>+{
>+ struct ice_pf *pf = (struct ice_pf *)devlink_priv(devlink);
Pointless cast.
>+ struct device *dev = ice_pf_to_dev(pf);
>+ int err;
>+
>+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
>+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
How this message could ever help anyone?
>+
>+ err = ice_devlink_port_new_check_attr(pf, new_attr, extack);
>+ if (err)
>+ return err;
>+
>+ return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port);
>+}
>+
>diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
>index 983d136f5ddf..2bb203c1713f 100644
>--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
>+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
>@@ -4,9 +4,39 @@
> #ifndef _ICE_DEVLINK_PORT_H_
> #define _ICE_DEVLINK_PORT_H_
>
>+#include "../ice.h"
>+
>+/**
>+ * struct ice_dynamic_port - Track dynamically added devlink port instance
>+ * @hw_addr: the HW address for this port
>+ * @active: true if the port has been activated
>+ * @devlink_port: the associated devlink port structure
>+ * @pf: pointer to the PF private structure
>+ * @vsi: the VSI associated with this port
>+ *
>+ * An instance of a dynamically added devlink port. Each port flavour
>+ */
>+struct ice_dynamic_port {
>+ u8 hw_addr[ETH_ALEN];
>+ u8 active : 1;
>+ struct devlink_port devlink_port;
>+ struct ice_pf *pf;
>+ struct ice_vsi *vsi;
>+};
>+
>+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf);
>+
> int ice_devlink_create_pf_port(struct ice_pf *pf);
> void ice_devlink_destroy_pf_port(struct ice_pf *pf);
> int ice_devlink_create_vf_port(struct ice_vf *vf);
> void ice_devlink_destroy_vf_port(struct ice_vf *vf);
>
>+#define ice_devlink_port_to_dyn(p) \
>+ container_of(port, struct ice_dynamic_port, devlink_port)
>+
>+int
>+ice_devlink_port_new(struct devlink *devlink,
>+ const struct devlink_port_new_attrs *new_attr,
>+ struct netlink_ext_ack *extack,
>+ struct devlink_port **devlink_port);
> #endif /* _ICE_DEVLINK_PORT_H_ */
>diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
>index c40fc339a604..767ea80684e7 100644
>--- a/drivers/net/ethernet/intel/ice/ice.h
>+++ b/drivers/net/ethernet/intel/ice/ice.h
>@@ -646,6 +646,9 @@ struct ice_pf {
> struct ice_eswitch eswitch;
> struct ice_esw_br_port *br_port;
>
>+ struct xarray dyn_ports;
>+ struct xarray sf_nums;
>+
> #define ICE_INVALID_AGG_NODE_ID 0
> #define ICE_PF_AGG_NODE_ID_START 1
> #define ICE_MAX_PF_AGG_NODES 32
>@@ -902,6 +905,7 @@ int ice_vsi_open(struct ice_vsi *vsi);
> void ice_set_ethtool_ops(struct net_device *netdev);
> void ice_set_ethtool_repr_ops(struct net_device *netdev);
> void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
>+void ice_set_ethtool_sf_ops(struct net_device *netdev);
> u16 ice_get_avail_txq_count(struct ice_pf *pf);
> u16 ice_get_avail_rxq_count(struct ice_pf *pf);
> int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
>diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
>index e5f275ca82e5..c186e793153d 100644
>--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
>+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
>@@ -6,6 +6,7 @@
> #include "ice.h"
> #include "ice_lib.h"
> #include "ice_devlink.h"
>+#include "devlink/ice_devlink_port.h"
> #include "ice_eswitch.h"
> #include "ice_fw_update.h"
> #include "ice_dcb_lib.h"
>@@ -1131,6 +1132,8 @@ static const struct devlink_ops ice_devlink_ops = {
>
> .rate_leaf_parent_set = ice_devlink_set_parent,
> .rate_node_parent_set = ice_devlink_set_parent,
>+
>+ .port_new = ice_devlink_port_new,
> };
>
> static int
>diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
>index 8706d0589caa..3472011922c1 100644
>--- a/drivers/net/ethernet/intel/ice/ice_lib.c
>+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
>@@ -7,6 +7,7 @@
> #include "ice_lib.h"
> #include "ice_fltr.h"
> #include "ice_dcb_lib.h"
>+#include "ice_type.h"
> #include "ice_vsi_vlan_ops.h"
>
> /**
>@@ -440,7 +441,7 @@ static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
> * This deallocates the VSI's queue resources, removes it from the PF's
> * VSI array if necessary, and deallocates the VSI
> */
>-static void ice_vsi_free(struct ice_vsi *vsi)
>+void ice_vsi_free(struct ice_vsi *vsi)
> {
> struct ice_pf *pf = NULL;
> struct device *dev;
>@@ -612,7 +613,7 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
> *
> * returns a pointer to a VSI on success, NULL on failure.
> */
>-static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
>+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
> {
> struct device *dev = ice_pf_to_dev(pf);
> struct ice_vsi *vsi = NULL;
>diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
>index aa3a85d31f95..9cc7cc57e41a 100644
>--- a/drivers/net/ethernet/intel/ice/ice_lib.h
>+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
>@@ -97,6 +97,8 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
>
> int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
> int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
>+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf);
>+void ice_vsi_free(struct ice_vsi *vsi);
>
> bool ice_is_reset_in_progress(unsigned long *state);
> int ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout);
>diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
>index b0f6a11ae744..e4269a7df7d6 100644
>--- a/drivers/net/ethernet/intel/ice/ice_main.c
>+++ b/drivers/net/ethernet/intel/ice/ice_main.c
>@@ -16,6 +16,7 @@
> #include "ice_devlink.h"
> #include "ice_hwmon.h"
> #include "devlink/ice_devlink_port.h"
>+#include "ice_sf_eth.h"
> /* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
> * ice tracepoint functions. This must be done exactly once across the
> * ice driver.
>@@ -3929,6 +3930,9 @@ static void ice_deinit_pf(struct ice_pf *pf)
>
> if (pf->ptp.clock)
> ptp_clock_unregister(pf->ptp.clock);
>+
>+ xa_destroy(&pf->dyn_ports);
>+ xa_destroy(&pf->sf_nums);
> }
>
> /**
>@@ -4022,6 +4026,9 @@ static int ice_init_pf(struct ice_pf *pf)
> hash_init(pf->vfs.table);
> ice_mbx_init_snapshot(&pf->hw);
>
>+ xa_init(&pf->dyn_ports);
>+ xa_init(&pf->sf_nums);
>+
> return 0;
> }
>
>@@ -5250,6 +5257,8 @@ static void ice_remove(struct pci_dev *pdev)
> struct ice_pf *pf = pci_get_drvdata(pdev);
> int i;
>
>+ ice_dealloc_all_dynamic_ports(pf);
>+
> for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
> if (!ice_is_reset_in_progress(pf->state))
> break;
>@@ -6561,7 +6570,8 @@ static int ice_up_complete(struct ice_vsi *vsi)
>
> if (vsi->port_info &&
> (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
>- vsi->netdev && vsi->type == ICE_VSI_PF) {
>+ ((vsi->netdev && vsi->type == ICE_VSI_PF) ||
>+ (vsi->netdev && vsi->type == ICE_VSI_SF))) {
> ice_print_link_msg(vsi, true);
> netif_tx_start_all_queues(vsi->netdev);
> netif_carrier_on(vsi->netdev);
>@@ -7217,7 +7227,7 @@ int ice_vsi_open(struct ice_vsi *vsi)
>
> ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
>
>- if (vsi->type == ICE_VSI_PF) {
>+ if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_SF) {
> /* Notify the stack of the actual queue counts. */
> err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
> if (err)
>diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>new file mode 100644
>index 000000000000..f569f176f29f
>--- /dev/null
>+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>@@ -0,0 +1,138 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/* Copyright (c) 2023, Intel Corporation. */
It's 2024
>+
>+#include "ice.h"
>+#include "ice_lib.h"
>+#include "ice_txrx.h"
>+#include "ice_fltr.h"
>+#include "ice_sf_eth.h"
>+#include "devlink/ice_devlink_port.h"
>+
>+static const struct net_device_ops ice_sf_netdev_ops = {
>+ .ndo_open = ice_open,
>+ .ndo_stop = ice_stop,
>+ .ndo_start_xmit = ice_start_xmit,
>+ .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
>+ .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
>+ .ndo_change_mtu = ice_change_mtu,
>+ .ndo_get_stats64 = ice_get_stats64,
>+ .ndo_tx_timeout = ice_tx_timeout,
>+ .ndo_bpf = ice_xdp,
>+ .ndo_xdp_xmit = ice_xdp_xmit,
>+ .ndo_xsk_wakeup = ice_xsk_wakeup,
>+};
>+
>+/**
>+ * ice_sf_cfg_netdev - Allocate, configure and register a netdev
>+ * @dyn_port: subfunction associated with configured netdev
>+ *
>+ * Returns 0 on success, negative value on failure
>+ */
>+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
>+{
>+ struct net_device *netdev;
>+ struct ice_vsi *vsi = dyn_port->vsi;
>+ struct ice_netdev_priv *np;
>+ int err;
>+
>+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
>+ vsi->alloc_rxq);
>+ if (!netdev)
>+ return -ENOMEM;
>+
>+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
>+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
>+ vsi->netdev = netdev;
>+ np = netdev_priv(netdev);
>+ np->vsi = vsi;
>+
>+ ice_set_netdev_features(netdev);
>+
>+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
>+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
>+ NETDEV_XDP_ACT_RX_SG;
>+
>+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
>+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
>+ netdev->netdev_ops = &ice_sf_netdev_ops;
>+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
>+
>+ err = register_netdev(netdev);
It the the actual subfunction or eswitch port representor of the
subfunction. Looks like the port representor. In that case. It should be
created no matter if the subfunction is activated, when it it created.
If this is the actual subfunction netdev, you should not link it to
devlink port here.
>+ if (err) {
>+ free_netdev(netdev);
>+ vsi->netdev = NULL;
>+ return -ENOMEM;
>+ }
>+ set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
>+ netif_carrier_off(netdev);
>+ netif_tx_stop_all_queues(netdev);
>+
>+ return 0;
>+}
>+
>+/**
>+ * ice_sf_eth_activate - Activate Ethernet subfunction port
>+ * @dyn_port: the dynamic port instance for this subfunction
>+ * @extack: extack for reporting error messages
>+ *
>+ * Setups netdev resources and filters for a subfunction.
>+ *
>+ * Return: zero on success or an error code on failure.
>+ */
>+int
>+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
>+ struct netlink_ext_ack *extack)
>+{
>+ struct ice_vsi_cfg_params params = {};
>+ struct ice_vsi *vsi = dyn_port->vsi;
>+ struct ice_pf *pf = dyn_port->pf;
>+ int err;
>+
>+ params.type = ICE_VSI_SF;
>+ params.pi = pf->hw.port_info;
>+ params.flags = ICE_VSI_FLAG_INIT;
>+
>+ err = ice_vsi_cfg(vsi, ¶ms);
>+ if (err) {
>+ NL_SET_ERR_MSG_MOD(extack, "Subfunction vsi config failed");
>+ return err;
>+ }
>+
>+ err = ice_sf_cfg_netdev(dyn_port);
>+ if (err) {
>+ NL_SET_ERR_MSG_MOD(extack, "Subfunction netdev config failed");
>+ goto err_vsi_decfg;
>+ }
>+
>+ err = ice_fltr_add_mac_and_broadcast(vsi, vsi->netdev->dev_addr,
>+ ICE_FWD_TO_VSI);
>+ if (err)
>+ NL_SET_ERR_MSG_MOD(extack, "can't add MAC filters for subfunction VSI");
Start with capital letter here.
>+
>+ ice_napi_add(vsi);
>+
>+ return err;
>+
>+err_vsi_decfg:
>+ ice_vsi_decfg(vsi);
>+ return err;
>+}
>+
>+/**
>+ * ice_sf_eth_deactivate - Deactivate subfunction
>+ * @dyn_port: the dynamic port instance for this subfunction
>+ *
>+ * Free netdev resources and filters for a subfunction.
>+ */
>+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
>+{
>+ struct ice_vsi *vsi = dyn_port->vsi;
>+
>+ ice_vsi_close(vsi);
>+ unregister_netdev(vsi->netdev);
>+ clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
>+ free_netdev(vsi->netdev);
>+ clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
>+ vsi->netdev = NULL;
>+ ice_vsi_decfg(vsi);
>+}
>diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.h b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
>new file mode 100644
>index 000000000000..f4b8b36b1a67
>--- /dev/null
>+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
>@@ -0,0 +1,15 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/* Copyright (c) 2023, Intel Corporation. */
>+
>+#ifndef _ICE_SF_ETH_H_
>+#define _ICE_SF_ETH_H_
>+
>+#include "ice.h"
>+#include "devlink/ice_devlink_port.h"
>+
>+int
>+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
>+ struct netlink_ext_ack *extack);
>+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port);
>+
>+#endif /* _ICE_SF_ETH_H_ */
>--
>2.42.0
pw-bot: cr
>
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 06/15] ice: add subfunction aux driver support
2024-02-13 7:27 ` [iwl-next v1 06/15] ice: add subfunction aux driver support Michal Swiatkowski
@ 2024-02-13 8:57 ` Jiri Pirko
2024-02-13 9:43 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 8:57 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 08:27:15AM CET, michal.swiatkowski@linux.intel.com wrote:
>From: Piotr Raczynski <piotr.raczynski@intel.com>
>
>Instead of only registering devlink port by the ice driver itself,
>let PF driver only register port representor for a given subfunction.
>Then, aux driver is supposed to register its own devlink instance and
>register virtual devlink port.
>
>Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>---
> .../intel/ice/devlink/ice_devlink_port.c | 52 ++++-
> .../intel/ice/devlink/ice_devlink_port.h | 6 +
> drivers/net/ethernet/intel/ice/ice_devlink.c | 28 ++-
> drivers/net/ethernet/intel/ice/ice_devlink.h | 3 +
> drivers/net/ethernet/intel/ice/ice_main.c | 9 +
> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 214 ++++++++++++++++--
> drivers/net/ethernet/intel/ice/ice_sf_eth.h | 21 ++
> 7 files changed, 302 insertions(+), 31 deletions(-)
Could you please split this. I see that you can push out 1-3 patches as
preparation.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 7:27 ` [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute Michal Swiatkowski
@ 2024-02-13 8:59 ` Jiri Pirko
2024-02-13 9:53 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 8:59 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
>From: Piotr Raczynski <piotr.raczynski@intel.com>
>
>Add read only sysfs attribute for each auxiliary subfunction
>device. This attribute is needed for orchestration layer
>to distinguish SF devices from each other since there is no
>native devlink mechanism to represent the connection between
>devlink instance and the devlink port created for the port
>representor.
>
>Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>---
> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
>diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>index ab90db52a8fc..abee733710a5 100644
>--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>@@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
> kfree(sf_dev);
> }
>
>+static ssize_t
>+sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
>+{
>+ struct devlink_port_attrs *attrs;
>+ struct auxiliary_device *adev;
>+ struct ice_sf_dev *sf_dev;
>+
>+ adev = to_auxiliary_dev(dev);
>+ sf_dev = ice_adev_to_sf_dev(adev);
>+ attrs = &sf_dev->dyn_port->devlink_port.attrs;
>+
>+ return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
>+}
>+
>+static DEVICE_ATTR_RO(sfnum);
>+
>+static struct attribute *ice_sf_device_attrs[] = {
>+ &dev_attr_sfnum.attr,
>+ NULL,
>+};
>+
>+static const struct attribute_group ice_sf_attr_group = {
>+ .attrs = ice_sf_device_attrs,
>+};
>+
>+static const struct attribute_group *ice_sf_attr_groups[2] = {
>+ &ice_sf_attr_group,
>+ NULL
>+};
>+
> /**
> * ice_sf_eth_activate - Activate Ethernet subfunction port
> * @dyn_port: the dynamic port instance for this subfunction
>@@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
> sf_dev->dyn_port = dyn_port;
> sf_dev->adev.id = id;
> sf_dev->adev.name = "sf";
>+ sf_dev->adev.dev.groups = ice_sf_attr_groups;
Ugh. Custom driver sysfs files like this are always very questionable.
Don't do that please. If you need to expose sfnum, please think about
some common way. Why exactly you need to expose it?
pw-bot: cr
> sf_dev->adev.dev.release = ice_sf_dev_release;
> sf_dev->adev.dev.parent = &pdev->dev;
>
>--
>2.42.0
>
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 10/15] ice: create port representor for SF
2024-02-13 7:27 ` [iwl-next v1 10/15] ice: create port representor for SF Michal Swiatkowski
@ 2024-02-13 9:00 ` Jiri Pirko
2024-02-13 9:55 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 9:00 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski
Tue, Feb 13, 2024 at 08:27:19AM CET, michal.swiatkowski@linux.intel.com wrote:
>Store subfunction and VF pointer in port representor structure as an
>union. Add port representor type to distinguish between each of them.
>
>Keep the same flow of port representor creation, but instead of general
>attach function create helpers for VF and subfunction attach function.
>
>Type of port representor can be also known based on VSI type, but it
>is more clean to have it directly saved in port representor structure.
>
>Create port representor when subfunction port is activated.
>
>Add devlink lock for whole VF port representor creationi and destruction.
>It is done to be symmetric with what happens in case of SF port
>representor. SF port representor is always added or removed with devlink
>lock taken. Doing the same with VF port representor simplify logic.
>
>Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>---
> .../intel/ice/devlink/ice_devlink_port.c | 4 +-
> .../intel/ice/devlink/ice_devlink_port.h | 1 +
> drivers/net/ethernet/intel/ice/ice_eswitch.c | 82 ++++++++++---
> drivers/net/ethernet/intel/ice/ice_eswitch.h | 22 +++-
> drivers/net/ethernet/intel/ice/ice_repr.c | 110 +++++++++++-------
> drivers/net/ethernet/intel/ice/ice_repr.h | 21 +++-
> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 11 ++
> drivers/net/ethernet/intel/ice/ice_sriov.c | 4 +-
> drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
> drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +-
> 10 files changed, 184 insertions(+), 77 deletions(-)
Again, please split.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Intel-wired-lan] [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 8:55 ` Jiri Pirko
@ 2024-02-13 9:39 ` Michal Swiatkowski
2024-02-13 11:27 ` Jiri Pirko
2024-02-14 19:45 ` Jacob Keller
1 sibling, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 9:39 UTC (permalink / raw)
To: Jiri Pirko
Cc: maciej.fijalkowski, netdev, michal.kubiak, intel-wired-lan,
pio.raczynski, sridhar.samudrala, jacob.e.keller, wojciech.drewek,
Piotr Raczynski, przemyslaw.kitszel
On Tue, Feb 13, 2024 at 09:55:20AM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >
> >Implement devlink port handlers responsible for ethernet type devlink
> >subfunctions. Create subfunction devlink port and setup all resources
> >needed for a subfunction netdev to operate. Configure new VSI for each
> >new subfunction, initialize and configure interrupts and Tx/Rx resources.
> >Set correct MAC filters and create new netdev.
> >
> >For now, subfunction is limited to only one Tx/Rx queue pair.
> >
> >Only allocate new subfunction VSI with devlink port new command.
> >This makes sure that real resources are configured only when a new
> >subfunction gets activated. Allocate and free subfunction MSIX
> >interrupt vectors using new API calls with pci_msix_alloc_irq_at
> >and pci_msix_free_irq.
> >
> >Temporarily, before adding auxiliary bus driver for subfunctions,
> >configure subfunction netdev directly for the created devlink
> >port. This will be modified in the next patch to properly that handle
> >devlink port as the port representor.
> >
> >Support both automatic and manual subfunction numbers. If no subfunction
> >number is provided, use xa_alloc to pick a number automatically. This
> >will find the first free index and use that as the number. This reduces
> >burden on users in the simple case where a specific number is not
> >required. It may also be slightly faster to check that a number exists
> >since xarray lookup should be faster than a linear scan of the dyn_ports
> >xarray.
> >
> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >Co-developed-by: Jacob Keller <jacob.e.keller@intel.com>
> >Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >---
> > drivers/net/ethernet/intel/ice/Makefile | 1 +
> > .../intel/ice/devlink/ice_devlink_port.c | 508 ++++++++++++++++++
> > .../intel/ice/devlink/ice_devlink_port.h | 30 ++
> > drivers/net/ethernet/intel/ice/ice.h | 4 +
> > drivers/net/ethernet/intel/ice/ice_devlink.c | 3 +
> > drivers/net/ethernet/intel/ice/ice_lib.c | 5 +-
> > drivers/net/ethernet/intel/ice/ice_lib.h | 2 +
> > drivers/net/ethernet/intel/ice/ice_main.c | 14 +-
> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 138 +++++
> > drivers/net/ethernet/intel/ice/ice_sf_eth.h | 15 +
> > 10 files changed, 716 insertions(+), 4 deletions(-)
> > create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.c
> > create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.h
> >
> >diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
> >index cd4ab46d72a7..d56a7165df95 100644
> >--- a/drivers/net/ethernet/intel/ice/Makefile
> >+++ b/drivers/net/ethernet/intel/ice/Makefile
> >@@ -31,6 +31,7 @@ ice-y := ice_main.o \
> > ice_idc.o \
> > ice_devlink.o \
> > devlink/ice_devlink_port.o \
> >+ ice_sf_eth.o \
> > ice_ddp.o \
> > ice_fw_update.o \
> > ice_lag.o \
> >diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
> >index c8c823467fcf..90efceaddb02 100644
> >--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
> >+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
> >@@ -10,6 +10,8 @@
> > #include "ice_eswitch.h"
> > #include "ice_fw_update.h"
> > #include "ice_dcb_lib.h"
> >+#include "ice_sf_eth.h"
> >+#include "ice_fltr.h"
> >
> > static int ice_active_port_option = -1;
> >
> >@@ -432,3 +434,509 @@ void ice_devlink_destroy_vf_port(struct ice_vf *vf)
> > devlink_port_unregister(&vf->devlink_port);
> > }
> >
> >+/**
> >+ * ice_activate_dynamic_port - Activate a dynamic port
> >+ * @dyn_port: dynamic port instance to activate
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Activate the dynamic port based on its flavour.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ int err;
> >+
> >+ switch (dyn_port->devlink_port.attrs.flavour) {
> >+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
>
> Pointless switch case.
>
> It looks like you have odd habbit of checking things that cannot happen
> all over this patch :) See more below...
>
Right, I will remove it, thanks
>
> >+ err = ice_sf_eth_activate(dyn_port, extack);
> >+ if (err)
> >+ return err;
> >+ break;
> >+ default:
> >+ NL_SET_ERR_MSG_MOD(extack, "Unsupported port flavour");
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ dyn_port->active = 1;
>
> true?
>
Will change
>
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_deactivate_dynamic_port - Deactivate a dynamic port
> >+ * @dyn_port: dynamic port instance to deactivate
> >+ *
> >+ * Undo activation of a dynamic port.
> >+ */
> >+static void ice_deactivate_dynamic_port(struct ice_dynamic_port *dyn_port)
> >+{
> >+ switch (dyn_port->devlink_port.attrs.flavour) {
> >+ case DEVLINK_PORT_FLAVOUR_PCI_SF:
>
> Pointless switch case. Not possible to be anything else then
> DEVLINK_PORT_FLAVOUR_PCI_SF.
>
Ok, will fix it
>
> >+ ice_sf_eth_deactivate(dyn_port);
> >+ break;
> >+ default:
> >+ WARN(1, "Attempting to deactivate port with unexpected port flavour %d",
> >+ dyn_port->devlink_port.attrs.flavour);
> >+ }
> >+
> >+ dyn_port->active = 0;
>
> false?
>
Will change
>
> >+}
> >+
> >+/**
> >+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
> >+ * @dyn_port: dynamic port instance to deallocate
> >+ *
> >+ * Free resources associated with a dynamically added devlink port. Will
> >+ * deactivate the port if its currently active.
> >+ */
> >+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
> >+{
> >+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
> >+ struct ice_pf *pf = dyn_port->pf;
> >+
> >+ if (dyn_port->active)
> >+ ice_deactivate_dynamic_port(dyn_port);
> >+
> >+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
>
> I don't understand how this check could be false. Remove it.
>
Yeah, will remove
>
> >+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
> >+
> >+ devl_port_unregister(devlink_port);
> >+ ice_vsi_free(dyn_port->vsi);
> >+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
> >+ kfree(dyn_port);
> >+}
> >+
> >+/**
> >+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
> >+ * @pf: pointer to the pf structure
> >+ */
> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
> >+{
> >+ struct devlink *devlink = priv_to_devlink(pf);
> >+ struct ice_dynamic_port *dyn_port;
> >+ unsigned long index;
> >+
> >+ devl_lock(devlink);
> >+ xa_for_each(&pf->dyn_ports, index, dyn_port)
> >+ ice_dealloc_dynamic_port(dyn_port);
> >+ devl_unlock(devlink);
>
> Hmm, I would assume that the called should already hold the devlink
> instance lock when doing remove. What is stopping user from issuing
> port_new command here, after devl_unlock()?
>
It is only called from remove path, but I can move it upper.
>
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_new_check_attr - Check that new port attributes are valid
> >+ * @pf: pointer to the PF structure
> >+ * @new_attr: the attributes for the new port
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Check that the attributes for the new port are valid before continuing to
> >+ * allocate the devlink port.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_new_check_attr(struct ice_pf *pf,
> >+ const struct devlink_port_new_attrs *new_attr,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ if (new_attr->flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Flavour other than pcisf is not supported");
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ if (new_attr->controller_valid) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Setting controller is not supported");
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ if (new_attr->port_index_valid) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Port index is autogenerated by the driver");
>
> Does not look like an error message. Please re-phrase.
>
Ok, I will
>
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ if (new_attr->pfnum != pf->hw.bus.func) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Incorrect pfnum supplied");
> >+ return -EINVAL;
> >+ }
> >+
> >+ if (!pci_msix_can_alloc_dyn(pf->pdev)) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Dynamic MSIX-X interrupt allocation is not supported");
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_del - devlink handler for port delete
> >+ * @devlink: pointer to devlink
> >+ * @port: devlink port to be deleted
> >+ * @extack: pointer to extack
> >+ *
> >+ * Deletes devlink port and deallocates all resources associated with
> >+ * created subfunction.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_del(struct devlink *devlink, struct devlink_port *port,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+
> >+ dyn_port = ice_devlink_port_to_dyn(port);
> >+ if (!dyn_port) {
>
> Can't happen. Remove the check.
>
Will remove
>
> >+ NL_SET_ERR_MSG_MOD(extack, "Failed to find Subfunction port with a given index");
> >+ return -EINVAL;
> >+ }
> >+
> >+ ice_dealloc_dynamic_port(dyn_port);
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_fn_hw_addr_set - devlink handler for mac address set
> >+ * @port: pointer to devlink port
> >+ * @hw_addr: hw address to set
> >+ * @hw_addr_len: hw address length
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Sets mac address for the port, verifies arguments and copies address
> >+ * to the subfunction structure.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr,
> >+ int hw_addr_len,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+
> >+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
>
> How exactly this can happen? It could not. Remove the check. Remove it
> from the rest of the ops too.
>
I will, thanks
>
> >+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
> >+ return -EOPNOTSUPP;
> >+ }
> >+
> >+ dyn_port = ice_devlink_port_to_dyn(port);
> >+
> >+ if (hw_addr_len != ETH_ALEN || !is_valid_ether_addr(hw_addr)) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Invalid ethernet address");
> >+ return -EADDRNOTAVAIL;
> >+ }
> >+
> >+ if (ether_addr_equal(dyn_port->hw_addr, hw_addr)) {
> >+ NL_SET_ERR_MSG_MOD(extack, "address already set");
>
> You start with capital letter in the rest of the messages.
>
Will fix
>
> >+ return 0;
> >+ }
> >+
> >+ ether_addr_copy(dyn_port->hw_addr, hw_addr);
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_fn_hw_addr_get - devlink handler for mac address get
> >+ * @port: pointer to devlink port
> >+ * @hw_addr: hw address to set
> >+ * @hw_addr_len: hw address length
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Returns mac address for the port.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr,
> >+ int *hw_addr_len,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+
> >+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF)
> >+ return -EOPNOTSUPP;
>
> Pointless check.
>
Will remove
>
> >+
> >+ dyn_port = ice_devlink_port_to_dyn(port);
> >+
> >+ ether_addr_copy(hw_addr, dyn_port->hw_addr);
> >+ *hw_addr_len = ETH_ALEN;
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_fn_state_set - devlink handler for port state set
> >+ * @port: pointer to devlink port
> >+ * @state: state to set
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Activates or deactivates the port.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_fn_state_set(struct devlink_port *port,
> >+ enum devlink_port_fn_state state,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+
> >+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
> >+ return -EOPNOTSUPP;
> >+ }
>
> Pointless check.
>
Will remove
>
> >+
> >+ dyn_port = ice_devlink_port_to_dyn(port);
> >+
> >+ switch (state) {
> >+ case DEVLINK_PORT_FN_STATE_ACTIVE:
> >+ if (!dyn_port->active)
> >+ return ice_activate_dynamic_port(dyn_port, extack);
> >+ break;
> >+ case DEVLINK_PORT_FN_STATE_INACTIVE:
> >+ if (dyn_port->active)
> >+ ice_deactivate_dynamic_port(dyn_port);
> >+ break;
> >+ }
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_fn_state_get - devlink handler for port state get
> >+ * @port: pointer to devlink port
> >+ * @state: admin configured state of the port
> >+ * @opstate: current port operational state
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Gets port state.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_port_fn_state_get(struct devlink_port *port,
> >+ enum devlink_port_fn_state *state,
> >+ enum devlink_port_fn_opstate *opstate,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+
> >+ if (port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Port is not a Subfunction");
> >+ return -EOPNOTSUPP;
> >+ }
>
> Pointless check.
>
Will remove
>
> >+
> >+ dyn_port = ice_devlink_port_to_dyn(port);
> >+
> >+ if (dyn_port->active) {
> >+ *state = DEVLINK_PORT_FN_STATE_ACTIVE;
> >+ *opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
> >+ } else {
> >+ *state = DEVLINK_PORT_FN_STATE_INACTIVE;
> >+ *opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;
> >+ }
> >+
> >+ return 0;
> >+}
> >+
> >+static const struct devlink_port_ops ice_devlink_port_sf_ops = {
> >+ .port_del = ice_devlink_port_del,
> >+ .port_fn_hw_addr_get = ice_devlink_port_fn_hw_addr_get,
> >+ .port_fn_hw_addr_set = ice_devlink_port_fn_hw_addr_set,
> >+ .port_fn_state_get = ice_devlink_port_fn_state_get,
> >+ .port_fn_state_set = ice_devlink_port_fn_state_set,
> >+};
> >+
> >+/**
> >+ * ice_reserve_sf_num - Reserve a subfunction number for this port
> >+ * @pf: pointer to the pf structure
> >+ * @new_attr: devlink port attributes requested
> >+ * @extack: extack for reporting error messages
> >+ * @sfnum: on success, the sf number reserved
> >+ *
> >+ * Reserve a subfunction number for this port. Only called for
> >+ * DEVLINK_PORT_FLAVOUR_PCI_SF ports.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_reserve_sf_num(struct ice_pf *pf,
> >+ const struct devlink_port_new_attrs *new_attr,
> >+ struct netlink_ext_ack *extack, u32 *sfnum)
> >+{
> >+ int err;
> >+
> >+ /* If user didn't request an explicit number, pick one */
> >+ if (!new_attr->sfnum_valid)
> >+ return xa_alloc(&pf->sf_nums, sfnum, NULL, xa_limit_32b,
> >+ GFP_KERNEL);
> >+
> >+ /* Otherwise, check and use the number provided */
> >+ err = xa_insert(&pf->sf_nums, new_attr->sfnum, NULL, GFP_KERNEL);
> >+ if (err) {
> >+ if (err == -EBUSY)
> >+ NL_SET_ERR_MSG_MOD(extack, "Subfunction with given sfnum already exists");
> >+ return err;
> >+ }
> >+
> >+ *sfnum = new_attr->sfnum;
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_devlink_create_sf_port - Register PCI subfunction devlink port
> >+ * @dyn_port: the dynamic port instance structure for this subfunction
> >+ * @sfnum: the subfunction number to use for the port
> >+ *
> >+ * Register PCI subfunction flavour devlink port for a dynamically added
> >+ * subfunction port.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_devlink_create_sf_port(struct ice_dynamic_port *dyn_port, u32 sfnum)
> >+{
> >+ struct devlink_port_attrs attrs = {};
> >+ struct devlink_port *devlink_port;
> >+ struct devlink *devlink;
> >+ struct ice_vsi *vsi;
> >+ struct device *dev;
> >+ struct ice_pf *pf;
> >+ int err;
> >+
> >+ vsi = dyn_port->vsi;
> >+ pf = dyn_port->pf;
> >+ dev = ice_pf_to_dev(pf);
> >+
> >+ devlink_port = &dyn_port->devlink_port;
> >+
> >+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_SF;
> >+ attrs.pci_sf.pf = pf->hw.bus.func;
> >+ attrs.pci_sf.sf = sfnum;
> >+
> >+ devlink_port_attrs_set(devlink_port, &attrs);
> >+ devlink = priv_to_devlink(pf);
> >+
> >+ err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
> >+ &ice_devlink_port_sf_ops);
> >+ if (err) {
> >+ dev_err(dev, "Failed to create devlink port for Subfunction %d",
> >+ vsi->idx);
> >+ return err;
> >+ }
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_alloc_dynamic_port - Allocate new dynamic port
> >+ * @pf: pointer to the pf structure
> >+ * @new_attr: devlink port attributes requested
> >+ * @extack: extack for reporting error messages
> >+ * @devlink_port: index of newly created devlink port
> >+ *
> >+ * Allocate a new dynamic port instance and prepare it for configuration
> >+ * with devlink.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+static int
> >+ice_alloc_dynamic_port(struct ice_pf *pf,
> >+ const struct devlink_port_new_attrs *new_attr,
> >+ struct netlink_ext_ack *extack,
> >+ struct devlink_port **devlink_port)
> >+{
> >+ struct ice_dynamic_port *dyn_port;
> >+ struct ice_vsi *vsi;
> >+ u32 sfnum;
> >+ int err;
> >+
> >+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF) {
> >+ err = ice_reserve_sf_num(pf, new_attr, extack, &sfnum);
> >+ if (err)
> >+ return err;
> >+ }
> >+
> >+ dyn_port = kzalloc(sizeof(*dyn_port), GFP_KERNEL);
> >+ if (!dyn_port) {
> >+ err = -ENOMEM;
> >+ goto unroll_reserve_sf_num;
> >+ }
> >+
> >+ vsi = ice_vsi_alloc(pf);
> >+ if (!vsi) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate VSI");
> >+ err = -ENOMEM;
> >+ goto unroll_dyn_port_alloc;
> >+ }
> >+
> >+ dyn_port->vsi = vsi;
> >+ dyn_port->pf = pf;
> >+ dyn_port->active = 0;
>
> Pointless init, the memory is already zeroed.
>
Right, I will remove it
>
> >+ eth_random_addr(dyn_port->hw_addr);
> >+
> >+ err = xa_insert(&pf->dyn_ports, vsi->idx, dyn_port, GFP_KERNEL);
> >+ if (err) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Port index reservation failed");
> >+ goto unroll_vsi_alloc;
> >+ }
> >+
> >+ err = ice_devlink_create_sf_port(dyn_port, sfnum);
> >+ if (err) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Port registration failed");
> >+ goto unroll_xa_insert;
> >+ }
> >+
> >+ *devlink_port = &dyn_port->devlink_port;
> >+
> >+ return 0;
> >+
> >+unroll_xa_insert:
> >+ xa_erase(&pf->dyn_ports, vsi->idx);
> >+unroll_vsi_alloc:
> >+ ice_vsi_free(vsi);
> >+unroll_dyn_port_alloc:
> >+ kfree(dyn_port);
> >+unroll_reserve_sf_num:
> >+ if (new_attr->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
> >+ xa_erase(&pf->sf_nums, sfnum);
> >+
> >+ return err;
> >+}
> >+
> >+/**
> >+ * ice_devlink_port_new - devlink handler for the new port
> >+ * @devlink: pointer to devlink
> >+ * @new_attr: pointer to the port new attributes
> >+ * @extack: extack for reporting error messages
> >+ * @devlink_port: pointer to a new port
> >+ *
> >+ * Creates new devlink port, checks new port attributes and reject
> >+ * any unsupported parameters, allocates new subfunction for that port.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+int
> >+ice_devlink_port_new(struct devlink *devlink,
> >+ const struct devlink_port_new_attrs *new_attr,
> >+ struct netlink_ext_ack *extack,
> >+ struct devlink_port **devlink_port)
> >+{
> >+ struct ice_pf *pf = (struct ice_pf *)devlink_priv(devlink);
>
> Pointless cast.
>
Ok, will remove
>
> >+ struct device *dev = ice_pf_to_dev(pf);
> >+ int err;
> >+
> >+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
> >+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
>
> How this message could ever help anyone?
>
Probably only developer of the code :p, will remove it
>
> >+
> >+ err = ice_devlink_port_new_check_attr(pf, new_attr, extack);
> >+ if (err)
> >+ return err;
> >+
> >+ return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port);
> >+}
> >+
> >diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
> >index 983d136f5ddf..2bb203c1713f 100644
> >--- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
> >+++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.h
> >@@ -4,9 +4,39 @@
> > #ifndef _ICE_DEVLINK_PORT_H_
> > #define _ICE_DEVLINK_PORT_H_
> >
> >+#include "../ice.h"
> >+
> >+/**
> >+ * struct ice_dynamic_port - Track dynamically added devlink port instance
> >+ * @hw_addr: the HW address for this port
> >+ * @active: true if the port has been activated
> >+ * @devlink_port: the associated devlink port structure
> >+ * @pf: pointer to the PF private structure
> >+ * @vsi: the VSI associated with this port
> >+ *
> >+ * An instance of a dynamically added devlink port. Each port flavour
> >+ */
> >+struct ice_dynamic_port {
> >+ u8 hw_addr[ETH_ALEN];
> >+ u8 active : 1;
> >+ struct devlink_port devlink_port;
> >+ struct ice_pf *pf;
> >+ struct ice_vsi *vsi;
> >+};
> >+
> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf);
> >+
> > int ice_devlink_create_pf_port(struct ice_pf *pf);
> > void ice_devlink_destroy_pf_port(struct ice_pf *pf);
> > int ice_devlink_create_vf_port(struct ice_vf *vf);
> > void ice_devlink_destroy_vf_port(struct ice_vf *vf);
> >
> >+#define ice_devlink_port_to_dyn(p) \
> >+ container_of(port, struct ice_dynamic_port, devlink_port)
> >+
> >+int
> >+ice_devlink_port_new(struct devlink *devlink,
> >+ const struct devlink_port_new_attrs *new_attr,
> >+ struct netlink_ext_ack *extack,
> >+ struct devlink_port **devlink_port);
> > #endif /* _ICE_DEVLINK_PORT_H_ */
> >diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
> >index c40fc339a604..767ea80684e7 100644
> >--- a/drivers/net/ethernet/intel/ice/ice.h
> >+++ b/drivers/net/ethernet/intel/ice/ice.h
> >@@ -646,6 +646,9 @@ struct ice_pf {
> > struct ice_eswitch eswitch;
> > struct ice_esw_br_port *br_port;
> >
> >+ struct xarray dyn_ports;
> >+ struct xarray sf_nums;
> >+
> > #define ICE_INVALID_AGG_NODE_ID 0
> > #define ICE_PF_AGG_NODE_ID_START 1
> > #define ICE_MAX_PF_AGG_NODES 32
> >@@ -902,6 +905,7 @@ int ice_vsi_open(struct ice_vsi *vsi);
> > void ice_set_ethtool_ops(struct net_device *netdev);
> > void ice_set_ethtool_repr_ops(struct net_device *netdev);
> > void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
> >+void ice_set_ethtool_sf_ops(struct net_device *netdev);
> > u16 ice_get_avail_txq_count(struct ice_pf *pf);
> > u16 ice_get_avail_rxq_count(struct ice_pf *pf);
> > int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
> >diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
> >index e5f275ca82e5..c186e793153d 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
> >@@ -6,6 +6,7 @@
> > #include "ice.h"
> > #include "ice_lib.h"
> > #include "ice_devlink.h"
> >+#include "devlink/ice_devlink_port.h"
> > #include "ice_eswitch.h"
> > #include "ice_fw_update.h"
> > #include "ice_dcb_lib.h"
> >@@ -1131,6 +1132,8 @@ static const struct devlink_ops ice_devlink_ops = {
> >
> > .rate_leaf_parent_set = ice_devlink_set_parent,
> > .rate_node_parent_set = ice_devlink_set_parent,
> >+
> >+ .port_new = ice_devlink_port_new,
> > };
> >
> > static int
> >diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
> >index 8706d0589caa..3472011922c1 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_lib.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
> >@@ -7,6 +7,7 @@
> > #include "ice_lib.h"
> > #include "ice_fltr.h"
> > #include "ice_dcb_lib.h"
> >+#include "ice_type.h"
> > #include "ice_vsi_vlan_ops.h"
> >
> > /**
> >@@ -440,7 +441,7 @@ static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
> > * This deallocates the VSI's queue resources, removes it from the PF's
> > * VSI array if necessary, and deallocates the VSI
> > */
> >-static void ice_vsi_free(struct ice_vsi *vsi)
> >+void ice_vsi_free(struct ice_vsi *vsi)
> > {
> > struct ice_pf *pf = NULL;
> > struct device *dev;
> >@@ -612,7 +613,7 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
> > *
> > * returns a pointer to a VSI on success, NULL on failure.
> > */
> >-static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
> >+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
> > {
> > struct device *dev = ice_pf_to_dev(pf);
> > struct ice_vsi *vsi = NULL;
> >diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
> >index aa3a85d31f95..9cc7cc57e41a 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_lib.h
> >+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
> >@@ -97,6 +97,8 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
> >
> > int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
> > int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
> >+struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf);
> >+void ice_vsi_free(struct ice_vsi *vsi);
> >
> > bool ice_is_reset_in_progress(unsigned long *state);
> > int ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout);
> >diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
> >index b0f6a11ae744..e4269a7df7d6 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_main.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_main.c
> >@@ -16,6 +16,7 @@
> > #include "ice_devlink.h"
> > #include "ice_hwmon.h"
> > #include "devlink/ice_devlink_port.h"
> >+#include "ice_sf_eth.h"
> > /* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
> > * ice tracepoint functions. This must be done exactly once across the
> > * ice driver.
> >@@ -3929,6 +3930,9 @@ static void ice_deinit_pf(struct ice_pf *pf)
> >
> > if (pf->ptp.clock)
> > ptp_clock_unregister(pf->ptp.clock);
> >+
> >+ xa_destroy(&pf->dyn_ports);
> >+ xa_destroy(&pf->sf_nums);
> > }
> >
> > /**
> >@@ -4022,6 +4026,9 @@ static int ice_init_pf(struct ice_pf *pf)
> > hash_init(pf->vfs.table);
> > ice_mbx_init_snapshot(&pf->hw);
> >
> >+ xa_init(&pf->dyn_ports);
> >+ xa_init(&pf->sf_nums);
> >+
> > return 0;
> > }
> >
> >@@ -5250,6 +5257,8 @@ static void ice_remove(struct pci_dev *pdev)
> > struct ice_pf *pf = pci_get_drvdata(pdev);
> > int i;
> >
> >+ ice_dealloc_all_dynamic_ports(pf);
> >+
> > for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
> > if (!ice_is_reset_in_progress(pf->state))
> > break;
> >@@ -6561,7 +6570,8 @@ static int ice_up_complete(struct ice_vsi *vsi)
> >
> > if (vsi->port_info &&
> > (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
> >- vsi->netdev && vsi->type == ICE_VSI_PF) {
> >+ ((vsi->netdev && vsi->type == ICE_VSI_PF) ||
> >+ (vsi->netdev && vsi->type == ICE_VSI_SF))) {
> > ice_print_link_msg(vsi, true);
> > netif_tx_start_all_queues(vsi->netdev);
> > netif_carrier_on(vsi->netdev);
> >@@ -7217,7 +7227,7 @@ int ice_vsi_open(struct ice_vsi *vsi)
> >
> > ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
> >
> >- if (vsi->type == ICE_VSI_PF) {
> >+ if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_SF) {
> > /* Notify the stack of the actual queue counts. */
> > err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
> > if (err)
> >diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >new file mode 100644
> >index 000000000000..f569f176f29f
> >--- /dev/null
> >+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >@@ -0,0 +1,138 @@
> >+// SPDX-License-Identifier: GPL-2.0
> >+/* Copyright (c) 2023, Intel Corporation. */
>
> It's 2024
>
Time is passing quickly, I will change
>
> >+
> >+#include "ice.h"
> >+#include "ice_lib.h"
> >+#include "ice_txrx.h"
> >+#include "ice_fltr.h"
> >+#include "ice_sf_eth.h"
> >+#include "devlink/ice_devlink_port.h"
> >+
> >+static const struct net_device_ops ice_sf_netdev_ops = {
> >+ .ndo_open = ice_open,
> >+ .ndo_stop = ice_stop,
> >+ .ndo_start_xmit = ice_start_xmit,
> >+ .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
> >+ .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
> >+ .ndo_change_mtu = ice_change_mtu,
> >+ .ndo_get_stats64 = ice_get_stats64,
> >+ .ndo_tx_timeout = ice_tx_timeout,
> >+ .ndo_bpf = ice_xdp,
> >+ .ndo_xdp_xmit = ice_xdp_xmit,
> >+ .ndo_xsk_wakeup = ice_xsk_wakeup,
> >+};
> >+
> >+/**
> >+ * ice_sf_cfg_netdev - Allocate, configure and register a netdev
> >+ * @dyn_port: subfunction associated with configured netdev
> >+ *
> >+ * Returns 0 on success, negative value on failure
> >+ */
> >+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
> >+{
> >+ struct net_device *netdev;
> >+ struct ice_vsi *vsi = dyn_port->vsi;
> >+ struct ice_netdev_priv *np;
> >+ int err;
> >+
> >+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
> >+ vsi->alloc_rxq);
> >+ if (!netdev)
> >+ return -ENOMEM;
> >+
> >+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
> >+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
> >+ vsi->netdev = netdev;
> >+ np = netdev_priv(netdev);
> >+ np->vsi = vsi;
> >+
> >+ ice_set_netdev_features(netdev);
> >+
> >+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
> >+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
> >+ NETDEV_XDP_ACT_RX_SG;
> >+
> >+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
> >+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
> >+ netdev->netdev_ops = &ice_sf_netdev_ops;
> >+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
> >+
> >+ err = register_netdev(netdev);
>
> It the the actual subfunction or eswitch port representor of the
> subfunction. Looks like the port representor. In that case. It should be
> created no matter if the subfunction is activated, when it it created.
>
> If this is the actual subfunction netdev, you should not link it to
> devlink port here.
>
This is the actual subfunction netdev. Where in this case it should be
linked?
>
>
> >+ if (err) {
> >+ free_netdev(netdev);
> >+ vsi->netdev = NULL;
> >+ return -ENOMEM;
> >+ }
> >+ set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
> >+ netif_carrier_off(netdev);
> >+ netif_tx_stop_all_queues(netdev);
> >+
> >+ return 0;
> >+}
> >+
> >+/**
> >+ * ice_sf_eth_activate - Activate Ethernet subfunction port
> >+ * @dyn_port: the dynamic port instance for this subfunction
> >+ * @extack: extack for reporting error messages
> >+ *
> >+ * Setups netdev resources and filters for a subfunction.
> >+ *
> >+ * Return: zero on success or an error code on failure.
> >+ */
> >+int
> >+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
> >+ struct netlink_ext_ack *extack)
> >+{
> >+ struct ice_vsi_cfg_params params = {};
> >+ struct ice_vsi *vsi = dyn_port->vsi;
> >+ struct ice_pf *pf = dyn_port->pf;
> >+ int err;
> >+
> >+ params.type = ICE_VSI_SF;
> >+ params.pi = pf->hw.port_info;
> >+ params.flags = ICE_VSI_FLAG_INIT;
> >+
> >+ err = ice_vsi_cfg(vsi, ¶ms);
> >+ if (err) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Subfunction vsi config failed");
> >+ return err;
> >+ }
> >+
> >+ err = ice_sf_cfg_netdev(dyn_port);
> >+ if (err) {
> >+ NL_SET_ERR_MSG_MOD(extack, "Subfunction netdev config failed");
> >+ goto err_vsi_decfg;
> >+ }
> >+
> >+ err = ice_fltr_add_mac_and_broadcast(vsi, vsi->netdev->dev_addr,
> >+ ICE_FWD_TO_VSI);
> >+ if (err)
> >+ NL_SET_ERR_MSG_MOD(extack, "can't add MAC filters for subfunction VSI");
>
> Start with capital letter here.
>
Ok, will fix
>
> >+
> >+ ice_napi_add(vsi);
> >+
> >+ return err;
> >+
> >+err_vsi_decfg:
> >+ ice_vsi_decfg(vsi);
> >+ return err;
> >+}
> >+
> >+/**
> >+ * ice_sf_eth_deactivate - Deactivate subfunction
> >+ * @dyn_port: the dynamic port instance for this subfunction
> >+ *
> >+ * Free netdev resources and filters for a subfunction.
> >+ */
> >+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port)
> >+{
> >+ struct ice_vsi *vsi = dyn_port->vsi;
> >+
> >+ ice_vsi_close(vsi);
> >+ unregister_netdev(vsi->netdev);
> >+ clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
> >+ free_netdev(vsi->netdev);
> >+ clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
> >+ vsi->netdev = NULL;
> >+ ice_vsi_decfg(vsi);
> >+}
> >diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.h b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
> >new file mode 100644
> >index 000000000000..f4b8b36b1a67
> >--- /dev/null
> >+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.h
> >@@ -0,0 +1,15 @@
> >+/* SPDX-License-Identifier: GPL-2.0 */
> >+/* Copyright (c) 2023, Intel Corporation. */
> >+
> >+#ifndef _ICE_SF_ETH_H_
> >+#define _ICE_SF_ETH_H_
> >+
> >+#include "ice.h"
> >+#include "devlink/ice_devlink_port.h"
> >+
> >+int
> >+ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
> >+ struct netlink_ext_ack *extack);
> >+void ice_sf_eth_deactivate(struct ice_dynamic_port *dyn_port);
> >+
> >+#endif /* _ICE_SF_ETH_H_ */
> >--
> >2.42.0
>
> pw-bot: cr
>
> >
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 06/15] ice: add subfunction aux driver support
2024-02-13 8:57 ` Jiri Pirko
@ 2024-02-13 9:43 ` Michal Swiatkowski
2024-02-13 11:28 ` Jiri Pirko
0 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 9:43 UTC (permalink / raw)
To: Jiri Pirko
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
On Tue, Feb 13, 2024 at 09:57:12AM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 08:27:15AM CET, michal.swiatkowski@linux.intel.com wrote:
> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >
> >Instead of only registering devlink port by the ice driver itself,
> >let PF driver only register port representor for a given subfunction.
> >Then, aux driver is supposed to register its own devlink instance and
> >register virtual devlink port.
> >
> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >---
> > .../intel/ice/devlink/ice_devlink_port.c | 52 ++++-
> > .../intel/ice/devlink/ice_devlink_port.h | 6 +
> > drivers/net/ethernet/intel/ice/ice_devlink.c | 28 ++-
> > drivers/net/ethernet/intel/ice/ice_devlink.h | 3 +
> > drivers/net/ethernet/intel/ice/ice_main.c | 9 +
> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 214 ++++++++++++++++--
> > drivers/net/ethernet/intel/ice/ice_sf_eth.h | 21 ++
> > 7 files changed, 302 insertions(+), 31 deletions(-)
>
> Could you please split this. I see that you can push out 1-3 patches as
> preparation.
Do you mean 1-3 patchses from this patch, or from whole patchset? I mean,
do you want to split the patchset to two patchsets? (by splitting patch
from the patchset I will have more than netdev maximum; 15 I think).
Thanks,
Michal
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 8:59 ` Jiri Pirko
@ 2024-02-13 9:53 ` Michal Swiatkowski
2024-02-13 11:29 ` Jiri Pirko
0 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 9:53 UTC (permalink / raw)
To: Jiri Pirko
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >
> >Add read only sysfs attribute for each auxiliary subfunction
> >device. This attribute is needed for orchestration layer
> >to distinguish SF devices from each other since there is no
> >native devlink mechanism to represent the connection between
> >devlink instance and the devlink port created for the port
> >representor.
> >
> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >---
> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
> > 1 file changed, 31 insertions(+)
> >
> >diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >index ab90db52a8fc..abee733710a5 100644
> >--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >@@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
> > kfree(sf_dev);
> > }
> >
> >+static ssize_t
> >+sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
> >+{
> >+ struct devlink_port_attrs *attrs;
> >+ struct auxiliary_device *adev;
> >+ struct ice_sf_dev *sf_dev;
> >+
> >+ adev = to_auxiliary_dev(dev);
> >+ sf_dev = ice_adev_to_sf_dev(adev);
> >+ attrs = &sf_dev->dyn_port->devlink_port.attrs;
> >+
> >+ return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
> >+}
> >+
> >+static DEVICE_ATTR_RO(sfnum);
> >+
> >+static struct attribute *ice_sf_device_attrs[] = {
> >+ &dev_attr_sfnum.attr,
> >+ NULL,
> >+};
> >+
> >+static const struct attribute_group ice_sf_attr_group = {
> >+ .attrs = ice_sf_device_attrs,
> >+};
> >+
> >+static const struct attribute_group *ice_sf_attr_groups[2] = {
> >+ &ice_sf_attr_group,
> >+ NULL
> >+};
> >+
> > /**
> > * ice_sf_eth_activate - Activate Ethernet subfunction port
> > * @dyn_port: the dynamic port instance for this subfunction
> >@@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
> > sf_dev->dyn_port = dyn_port;
> > sf_dev->adev.id = id;
> > sf_dev->adev.name = "sf";
> >+ sf_dev->adev.dev.groups = ice_sf_attr_groups;
>
> Ugh. Custom driver sysfs files like this are always very questionable.
> Don't do that please. If you need to expose sfnum, please think about
> some common way. Why exactly you need to expose it?
Uh, hard question. I will drop it and check if it still needed to expose
the sfnum, probably no, as I have never used this sysfs during testing.
Should devlink be used for it?
Thanks
>
> pw-bot: cr
>
>
> > sf_dev->adev.dev.release = ice_sf_dev_release;
> > sf_dev->adev.dev.parent = &pdev->dev;
> >
> >--
> >2.42.0
> >
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 10/15] ice: create port representor for SF
2024-02-13 9:00 ` Jiri Pirko
@ 2024-02-13 9:55 ` Michal Swiatkowski
0 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 9:55 UTC (permalink / raw)
To: Jiri Pirko
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski
On Tue, Feb 13, 2024 at 10:00:20AM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 08:27:19AM CET, michal.swiatkowski@linux.intel.com wrote:
> >Store subfunction and VF pointer in port representor structure as an
> >union. Add port representor type to distinguish between each of them.
> >
> >Keep the same flow of port representor creation, but instead of general
> >attach function create helpers for VF and subfunction attach function.
> >
> >Type of port representor can be also known based on VSI type, but it
> >is more clean to have it directly saved in port representor structure.
> >
> >Create port representor when subfunction port is activated.
> >
> >Add devlink lock for whole VF port representor creationi and destruction.
> >It is done to be symmetric with what happens in case of SF port
> >representor. SF port representor is always added or removed with devlink
> >lock taken. Doing the same with VF port representor simplify logic.
> >
> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >---
> > .../intel/ice/devlink/ice_devlink_port.c | 4 +-
> > .../intel/ice/devlink/ice_devlink_port.h | 1 +
> > drivers/net/ethernet/intel/ice/ice_eswitch.c | 82 ++++++++++---
> > drivers/net/ethernet/intel/ice/ice_eswitch.h | 22 +++-
> > drivers/net/ethernet/intel/ice/ice_repr.c | 110 +++++++++++-------
> > drivers/net/ethernet/intel/ice/ice_repr.h | 21 +++-
> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 11 ++
> > drivers/net/ethernet/intel/ice/ice_sriov.c | 4 +-
> > drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
> > drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +-
> > 10 files changed, 184 insertions(+), 77 deletions(-)
>
> Again, please split.
Ok
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Intel-wired-lan] [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 9:39 ` [Intel-wired-lan] " Michal Swiatkowski
@ 2024-02-13 11:27 ` Jiri Pirko
2024-02-13 12:02 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 11:27 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: maciej.fijalkowski, netdev, michal.kubiak, intel-wired-lan,
pio.raczynski, sridhar.samudrala, jacob.e.keller, wojciech.drewek,
Piotr Raczynski, przemyslaw.kitszel
Tue, Feb 13, 2024 at 10:39:47AM CET, michal.swiatkowski@linux.intel.com wrote:
>On Tue, Feb 13, 2024 at 09:55:20AM +0100, Jiri Pirko wrote:
>> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
>> >From: Piotr Raczynski <piotr.raczynski@intel.com>
[...]
>
>>
>> >+}
>> >+
>> >+/**
>> >+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
>> >+ * @dyn_port: dynamic port instance to deallocate
>> >+ *
>> >+ * Free resources associated with a dynamically added devlink port. Will
>> >+ * deactivate the port if its currently active.
>> >+ */
>> >+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
>> >+{
>> >+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
>> >+ struct ice_pf *pf = dyn_port->pf;
>> >+
>> >+ if (dyn_port->active)
>> >+ ice_deactivate_dynamic_port(dyn_port);
>> >+
>> >+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
>>
>> I don't understand how this check could be false. Remove it.
>>
>Yeah, will remove
>
>>
>> >+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
>> >+
>> >+ devl_port_unregister(devlink_port);
>> >+ ice_vsi_free(dyn_port->vsi);
>> >+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
>> >+ kfree(dyn_port);
>> >+}
>> >+
>> >+/**
>> >+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
>> >+ * @pf: pointer to the pf structure
>> >+ */
>> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
>> >+{
>> >+ struct devlink *devlink = priv_to_devlink(pf);
>> >+ struct ice_dynamic_port *dyn_port;
>> >+ unsigned long index;
>> >+
>> >+ devl_lock(devlink);
>> >+ xa_for_each(&pf->dyn_ports, index, dyn_port)
>> >+ ice_dealloc_dynamic_port(dyn_port);
>> >+ devl_unlock(devlink);
>>
>> Hmm, I would assume that the called should already hold the devlink
>> instance lock when doing remove. What is stopping user from issuing
>> port_new command here, after devl_unlock()?
>>
>It is only called from remove path, but I can move it upper.
I know it is called on remove path. Again, what is stopping user from
issuing port_new after ice_dealloc_all_dynamic_ports() is called?
[...]
>>
>> >+ struct device *dev = ice_pf_to_dev(pf);
>> >+ int err;
>> >+
>> >+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
>> >+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
>>
>> How this message could ever help anyone?
>>
>Probably only developer of the code :p, will remove it
How exactly?
[...]
>> >+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
>> >+{
>> >+ struct net_device *netdev;
>> >+ struct ice_vsi *vsi = dyn_port->vsi;
>> >+ struct ice_netdev_priv *np;
>> >+ int err;
>> >+
>> >+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
>> >+ vsi->alloc_rxq);
>> >+ if (!netdev)
>> >+ return -ENOMEM;
>> >+
>> >+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
>> >+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
>> >+ vsi->netdev = netdev;
>> >+ np = netdev_priv(netdev);
>> >+ np->vsi = vsi;
>> >+
>> >+ ice_set_netdev_features(netdev);
>> >+
>> >+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
>> >+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
>> >+ NETDEV_XDP_ACT_RX_SG;
>> >+
>> >+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
>> >+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
>> >+ netdev->netdev_ops = &ice_sf_netdev_ops;
>> >+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
>> >+
>> >+ err = register_netdev(netdev);
>>
>> It the the actual subfunction or eswitch port representor of the
>> subfunction. Looks like the port representor. In that case. It should be
>> created no matter if the subfunction is activated, when it it created.
>>
>> If this is the actual subfunction netdev, you should not link it to
>> devlink port here.
>>
>This is the actual subfunction netdev. Where in this case it should be
>linked?
To the SF auxdev, obviously.
Here, you should have eswitch port representor netdev.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 06/15] ice: add subfunction aux driver support
2024-02-13 9:43 ` Michal Swiatkowski
@ 2024-02-13 11:28 ` Jiri Pirko
2024-02-13 12:03 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 11:28 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 10:43:00AM CET, michal.swiatkowski@linux.intel.com wrote:
>On Tue, Feb 13, 2024 at 09:57:12AM +0100, Jiri Pirko wrote:
>> Tue, Feb 13, 2024 at 08:27:15AM CET, michal.swiatkowski@linux.intel.com wrote:
>> >From: Piotr Raczynski <piotr.raczynski@intel.com>
>> >
>> >Instead of only registering devlink port by the ice driver itself,
>> >let PF driver only register port representor for a given subfunction.
>> >Then, aux driver is supposed to register its own devlink instance and
>> >register virtual devlink port.
>> >
>> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>> >---
>> > .../intel/ice/devlink/ice_devlink_port.c | 52 ++++-
>> > .../intel/ice/devlink/ice_devlink_port.h | 6 +
>> > drivers/net/ethernet/intel/ice/ice_devlink.c | 28 ++-
>> > drivers/net/ethernet/intel/ice/ice_devlink.h | 3 +
>> > drivers/net/ethernet/intel/ice/ice_main.c | 9 +
>> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 214 ++++++++++++++++--
>> > drivers/net/ethernet/intel/ice/ice_sf_eth.h | 21 ++
>> > 7 files changed, 302 insertions(+), 31 deletions(-)
>>
>> Could you please split this. I see that you can push out 1-3 patches as
>> preparation.
>
>Do you mean 1-3 patchses from this patch, or from whole patchset? I mean,
This patch.
>do you want to split the patchset to two patchsets? (by splitting patch
Yes, 2 patchsets. If convenient 3. Just do one change per patch so it is
reviewable.
>from the patchset I will have more than netdev maximum; 15 I think).
>
>Thanks,
>Michal
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 9:53 ` Michal Swiatkowski
@ 2024-02-13 11:29 ` Jiri Pirko
2024-02-13 11:55 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 11:29 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 10:53:50AM CET, michal.swiatkowski@linux.intel.com wrote:
>On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
>> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
>> >From: Piotr Raczynski <piotr.raczynski@intel.com>
>> >
>> >Add read only sysfs attribute for each auxiliary subfunction
>> >device. This attribute is needed for orchestration layer
>> >to distinguish SF devices from each other since there is no
>> >native devlink mechanism to represent the connection between
>> >devlink instance and the devlink port created for the port
>> >representor.
>> >
>> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>> >---
>> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
>> > 1 file changed, 31 insertions(+)
>> >
>> >diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>> >index ab90db52a8fc..abee733710a5 100644
>> >--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>> >+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>> >@@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
>> > kfree(sf_dev);
>> > }
>> >
>> >+static ssize_t
>> >+sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
>> >+{
>> >+ struct devlink_port_attrs *attrs;
>> >+ struct auxiliary_device *adev;
>> >+ struct ice_sf_dev *sf_dev;
>> >+
>> >+ adev = to_auxiliary_dev(dev);
>> >+ sf_dev = ice_adev_to_sf_dev(adev);
>> >+ attrs = &sf_dev->dyn_port->devlink_port.attrs;
>> >+
>> >+ return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
>> >+}
>> >+
>> >+static DEVICE_ATTR_RO(sfnum);
>> >+
>> >+static struct attribute *ice_sf_device_attrs[] = {
>> >+ &dev_attr_sfnum.attr,
>> >+ NULL,
>> >+};
>> >+
>> >+static const struct attribute_group ice_sf_attr_group = {
>> >+ .attrs = ice_sf_device_attrs,
>> >+};
>> >+
>> >+static const struct attribute_group *ice_sf_attr_groups[2] = {
>> >+ &ice_sf_attr_group,
>> >+ NULL
>> >+};
>> >+
>> > /**
>> > * ice_sf_eth_activate - Activate Ethernet subfunction port
>> > * @dyn_port: the dynamic port instance for this subfunction
>> >@@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
>> > sf_dev->dyn_port = dyn_port;
>> > sf_dev->adev.id = id;
>> > sf_dev->adev.name = "sf";
>> >+ sf_dev->adev.dev.groups = ice_sf_attr_groups;
>>
>> Ugh. Custom driver sysfs files like this are always very questionable.
>> Don't do that please. If you need to expose sfnum, please think about
>> some common way. Why exactly you need to expose it?
>
>Uh, hard question. I will drop it and check if it still needed to expose
>the sfnum, probably no, as I have never used this sysfs during testing.
>
>Should devlink be used for it?
sfnum is exposed over devlink on the port representor. If you need to
expose it on the actual SF, we have to figure it out. But again, why?
>
>Thanks
>
>>
>> pw-bot: cr
>>
>>
>> > sf_dev->adev.dev.release = ice_sf_dev_release;
>> > sf_dev->adev.dev.parent = &pdev->dev;
>> >
>> >--
>> >2.42.0
>> >
>> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 11:29 ` Jiri Pirko
@ 2024-02-13 11:55 ` Michal Swiatkowski
2024-02-13 22:04 ` Jacob Keller
0 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 11:55 UTC (permalink / raw)
To: Jiri Pirko
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
On Tue, Feb 13, 2024 at 12:29:40PM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 10:53:50AM CET, michal.swiatkowski@linux.intel.com wrote:
> >On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
> >> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
> >> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >> >
> >> >Add read only sysfs attribute for each auxiliary subfunction
> >> >device. This attribute is needed for orchestration layer
> >> >to distinguish SF devices from each other since there is no
> >> >native devlink mechanism to represent the connection between
> >> >devlink instance and the devlink port created for the port
> >> >representor.
> >> >
> >> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >> >---
> >> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
> >> > 1 file changed, 31 insertions(+)
> >> >
> >> >diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >> >index ab90db52a8fc..abee733710a5 100644
> >> >--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >> >+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >> >@@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
> >> > kfree(sf_dev);
> >> > }
> >> >
> >> >+static ssize_t
> >> >+sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
> >> >+{
> >> >+ struct devlink_port_attrs *attrs;
> >> >+ struct auxiliary_device *adev;
> >> >+ struct ice_sf_dev *sf_dev;
> >> >+
> >> >+ adev = to_auxiliary_dev(dev);
> >> >+ sf_dev = ice_adev_to_sf_dev(adev);
> >> >+ attrs = &sf_dev->dyn_port->devlink_port.attrs;
> >> >+
> >> >+ return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
> >> >+}
> >> >+
> >> >+static DEVICE_ATTR_RO(sfnum);
> >> >+
> >> >+static struct attribute *ice_sf_device_attrs[] = {
> >> >+ &dev_attr_sfnum.attr,
> >> >+ NULL,
> >> >+};
> >> >+
> >> >+static const struct attribute_group ice_sf_attr_group = {
> >> >+ .attrs = ice_sf_device_attrs,
> >> >+};
> >> >+
> >> >+static const struct attribute_group *ice_sf_attr_groups[2] = {
> >> >+ &ice_sf_attr_group,
> >> >+ NULL
> >> >+};
> >> >+
> >> > /**
> >> > * ice_sf_eth_activate - Activate Ethernet subfunction port
> >> > * @dyn_port: the dynamic port instance for this subfunction
> >> >@@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
> >> > sf_dev->dyn_port = dyn_port;
> >> > sf_dev->adev.id = id;
> >> > sf_dev->adev.name = "sf";
> >> >+ sf_dev->adev.dev.groups = ice_sf_attr_groups;
> >>
> >> Ugh. Custom driver sysfs files like this are always very questionable.
> >> Don't do that please. If you need to expose sfnum, please think about
> >> some common way. Why exactly you need to expose it?
> >
> >Uh, hard question. I will drop it and check if it still needed to expose
> >the sfnum, probably no, as I have never used this sysfs during testing.
> >
> >Should devlink be used for it?
>
> sfnum is exposed over devlink on the port representor. If you need to
> expose it on the actual SF, we have to figure it out. But again, why?
>
>
Only one argument why which I have in my mind is to support it in the legacy
mode. But probably subfunctions shouldn't be supported in legacy mode.
Thanks, I will remove it and use sfnum expose from representor.
> >
> >Thanks
> >
> >>
> >> pw-bot: cr
> >>
> >>
> >> > sf_dev->adev.dev.release = ice_sf_dev_release;
> >> > sf_dev->adev.dev.parent = &pdev->dev;
> >> >
> >> >--
> >> >2.42.0
> >> >
> >> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Intel-wired-lan] [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 11:27 ` Jiri Pirko
@ 2024-02-13 12:02 ` Michal Swiatkowski
2024-02-13 14:57 ` Jiri Pirko
0 siblings, 1 reply; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 12:02 UTC (permalink / raw)
To: Jiri Pirko
Cc: maciej.fijalkowski, netdev, michal.kubiak, intel-wired-lan,
pio.raczynski, sridhar.samudrala, jacob.e.keller, wojciech.drewek,
Piotr Raczynski, przemyslaw.kitszel
On Tue, Feb 13, 2024 at 12:27:20PM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 10:39:47AM CET, michal.swiatkowski@linux.intel.com wrote:
> >On Tue, Feb 13, 2024 at 09:55:20AM +0100, Jiri Pirko wrote:
> >> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
> >> >From: Piotr Raczynski <piotr.raczynski@intel.com>
>
> [...]
>
>
> >
> >>
> >> >+}
> >> >+
> >> >+/**
> >> >+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
> >> >+ * @dyn_port: dynamic port instance to deallocate
> >> >+ *
> >> >+ * Free resources associated with a dynamically added devlink port. Will
> >> >+ * deactivate the port if its currently active.
> >> >+ */
> >> >+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
> >> >+{
> >> >+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
> >> >+ struct ice_pf *pf = dyn_port->pf;
> >> >+
> >> >+ if (dyn_port->active)
> >> >+ ice_deactivate_dynamic_port(dyn_port);
> >> >+
> >> >+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
> >>
> >> I don't understand how this check could be false. Remove it.
> >>
> >Yeah, will remove
> >
> >>
> >> >+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
> >> >+
> >> >+ devl_port_unregister(devlink_port);
> >> >+ ice_vsi_free(dyn_port->vsi);
> >> >+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
> >> >+ kfree(dyn_port);
> >> >+}
> >> >+
> >> >+/**
> >> >+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
> >> >+ * @pf: pointer to the pf structure
> >> >+ */
> >> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
> >> >+{
> >> >+ struct devlink *devlink = priv_to_devlink(pf);
> >> >+ struct ice_dynamic_port *dyn_port;
> >> >+ unsigned long index;
> >> >+
> >> >+ devl_lock(devlink);
> >> >+ xa_for_each(&pf->dyn_ports, index, dyn_port)
> >> >+ ice_dealloc_dynamic_port(dyn_port);
> >> >+ devl_unlock(devlink);
> >>
> >> Hmm, I would assume that the called should already hold the devlink
> >> instance lock when doing remove. What is stopping user from issuing
> >> port_new command here, after devl_unlock()?
> >>
> >It is only called from remove path, but I can move it upper.
>
> I know it is called on remove path. Again, what is stopping user from
> issuing port_new after ice_dealloc_all_dynamic_ports() is called?
>
> [...]
>
What is a problem here? Calling port_new from user perspective will have
devlink lock, right? Do you mean that devlink lock should be taken for
whole cleanup, so from the start to the moment when devlink is
unregister? I wrote that, I will do that in next version (moving it
upper).
>
> >>
> >> >+ struct device *dev = ice_pf_to_dev(pf);
> >> >+ int err;
> >> >+
> >> >+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
> >> >+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
> >>
> >> How this message could ever help anyone?
> >>
> >Probably only developer of the code :p, will remove it
>
> How exactly?
>
I meant this code developer, it probably was used to check if number and
indexes are correct, but now it should be removed. Like, leftover after
developing, sorry.
> [...]
>
>
> >> >+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
> >> >+{
> >> >+ struct net_device *netdev;
> >> >+ struct ice_vsi *vsi = dyn_port->vsi;
> >> >+ struct ice_netdev_priv *np;
> >> >+ int err;
> >> >+
> >> >+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
> >> >+ vsi->alloc_rxq);
> >> >+ if (!netdev)
> >> >+ return -ENOMEM;
> >> >+
> >> >+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
> >> >+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
> >> >+ vsi->netdev = netdev;
> >> >+ np = netdev_priv(netdev);
> >> >+ np->vsi = vsi;
> >> >+
> >> >+ ice_set_netdev_features(netdev);
> >> >+
> >> >+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
> >> >+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
> >> >+ NETDEV_XDP_ACT_RX_SG;
> >> >+
> >> >+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
> >> >+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
> >> >+ netdev->netdev_ops = &ice_sf_netdev_ops;
> >> >+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
> >> >+
> >> >+ err = register_netdev(netdev);
> >>
> >> It the the actual subfunction or eswitch port representor of the
> >> subfunction. Looks like the port representor. In that case. It should be
> >> created no matter if the subfunction is activated, when it it created.
> >>
> >> If this is the actual subfunction netdev, you should not link it to
> >> devlink port here.
> >>
> >This is the actual subfunction netdev. Where in this case it should be
> >linked?
>
> To the SF auxdev, obviously.
>
> Here, you should have eswitch port representor netdev.
>
Oh, ok, thanks, will link it correctly in next version.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 06/15] ice: add subfunction aux driver support
2024-02-13 11:28 ` Jiri Pirko
@ 2024-02-13 12:03 ` Michal Swiatkowski
0 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-13 12:03 UTC (permalink / raw)
To: Jiri Pirko
Cc: intel-wired-lan, netdev, jacob.e.keller, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
On Tue, Feb 13, 2024 at 12:28:19PM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 10:43:00AM CET, michal.swiatkowski@linux.intel.com wrote:
> >On Tue, Feb 13, 2024 at 09:57:12AM +0100, Jiri Pirko wrote:
> >> Tue, Feb 13, 2024 at 08:27:15AM CET, michal.swiatkowski@linux.intel.com wrote:
> >> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >> >
> >> >Instead of only registering devlink port by the ice driver itself,
> >> >let PF driver only register port representor for a given subfunction.
> >> >Then, aux driver is supposed to register its own devlink instance and
> >> >register virtual devlink port.
> >> >
> >> >Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >> >Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >> >Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >> >---
> >> > .../intel/ice/devlink/ice_devlink_port.c | 52 ++++-
> >> > .../intel/ice/devlink/ice_devlink_port.h | 6 +
> >> > drivers/net/ethernet/intel/ice/ice_devlink.c | 28 ++-
> >> > drivers/net/ethernet/intel/ice/ice_devlink.h | 3 +
> >> > drivers/net/ethernet/intel/ice/ice_main.c | 9 +
> >> > drivers/net/ethernet/intel/ice/ice_sf_eth.c | 214 ++++++++++++++++--
> >> > drivers/net/ethernet/intel/ice/ice_sf_eth.h | 21 ++
> >> > 7 files changed, 302 insertions(+), 31 deletions(-)
> >>
> >> Could you please split this. I see that you can push out 1-3 patches as
> >> preparation.
> >
> >Do you mean 1-3 patchses from this patch, or from whole patchset? I mean,
>
> This patch.
>
> >do you want to split the patchset to two patchsets? (by splitting patch
>
> Yes, 2 patchsets. If convenient 3. Just do one change per patch so it is
> reviewable.
>
>
Ok, will do that.
> >from the patchset I will have more than netdev maximum; 15 I think).
> >
> >Thanks,
> >Michal
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Intel-wired-lan] [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 12:02 ` Michal Swiatkowski
@ 2024-02-13 14:57 ` Jiri Pirko
2024-02-14 6:26 ` Michal Swiatkowski
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-13 14:57 UTC (permalink / raw)
To: Michal Swiatkowski
Cc: maciej.fijalkowski, netdev, michal.kubiak, intel-wired-lan,
pio.raczynski, sridhar.samudrala, jacob.e.keller, wojciech.drewek,
Piotr Raczynski, przemyslaw.kitszel
Tue, Feb 13, 2024 at 01:02:43PM CET, michal.swiatkowski@linux.intel.com wrote:
>On Tue, Feb 13, 2024 at 12:27:20PM +0100, Jiri Pirko wrote:
>> Tue, Feb 13, 2024 at 10:39:47AM CET, michal.swiatkowski@linux.intel.com wrote:
>> >On Tue, Feb 13, 2024 at 09:55:20AM +0100, Jiri Pirko wrote:
>> >> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
>> >> >From: Piotr Raczynski <piotr.raczynski@intel.com>
>>
>> [...]
>>
>>
>> >
>> >>
>> >> >+}
>> >> >+
>> >> >+/**
>> >> >+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
>> >> >+ * @dyn_port: dynamic port instance to deallocate
>> >> >+ *
>> >> >+ * Free resources associated with a dynamically added devlink port. Will
>> >> >+ * deactivate the port if its currently active.
>> >> >+ */
>> >> >+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
>> >> >+{
>> >> >+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
>> >> >+ struct ice_pf *pf = dyn_port->pf;
>> >> >+
>> >> >+ if (dyn_port->active)
>> >> >+ ice_deactivate_dynamic_port(dyn_port);
>> >> >+
>> >> >+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
>> >>
>> >> I don't understand how this check could be false. Remove it.
>> >>
>> >Yeah, will remove
>> >
>> >>
>> >> >+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
>> >> >+
>> >> >+ devl_port_unregister(devlink_port);
>> >> >+ ice_vsi_free(dyn_port->vsi);
>> >> >+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
>> >> >+ kfree(dyn_port);
>> >> >+}
>> >> >+
>> >> >+/**
>> >> >+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
>> >> >+ * @pf: pointer to the pf structure
>> >> >+ */
>> >> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
>> >> >+{
>> >> >+ struct devlink *devlink = priv_to_devlink(pf);
>> >> >+ struct ice_dynamic_port *dyn_port;
>> >> >+ unsigned long index;
>> >> >+
>> >> >+ devl_lock(devlink);
>> >> >+ xa_for_each(&pf->dyn_ports, index, dyn_port)
>> >> >+ ice_dealloc_dynamic_port(dyn_port);
>> >> >+ devl_unlock(devlink);
>> >>
>> >> Hmm, I would assume that the called should already hold the devlink
>> >> instance lock when doing remove. What is stopping user from issuing
>> >> port_new command here, after devl_unlock()?
>> >>
>> >It is only called from remove path, but I can move it upper.
>>
>> I know it is called on remove path. Again, what is stopping user from
>> issuing port_new after ice_dealloc_all_dynamic_ports() is called?
>>
>> [...]
>>
>What is a problem here? Calling port_new from user perspective will have
>devlink lock, right? Do you mean that devlink lock should be taken for
>whole cleanup, so from the start to the moment when devlink is
>unregister? I wrote that, I will do that in next version (moving it
Yep, otherwise you can ice_dealloc_all_dynamic_ports() and end up with
another port created after that which nobody cleans-up.
>upper).
>
>>
>> >>
>> >> >+ struct device *dev = ice_pf_to_dev(pf);
>> >> >+ int err;
>> >> >+
>> >> >+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
>> >> >+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
>> >>
>> >> How this message could ever help anyone?
>> >>
>> >Probably only developer of the code :p, will remove it
>>
>> How exactly?
>>
>I meant this code developer, it probably was used to check if number and
>indexes are correct, but now it should be removed. Like, leftover after
>developing, sorry.
>
>> [...]
>>
>>
>> >> >+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
>> >> >+{
>> >> >+ struct net_device *netdev;
>> >> >+ struct ice_vsi *vsi = dyn_port->vsi;
>> >> >+ struct ice_netdev_priv *np;
>> >> >+ int err;
>> >> >+
>> >> >+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
>> >> >+ vsi->alloc_rxq);
>> >> >+ if (!netdev)
>> >> >+ return -ENOMEM;
>> >> >+
>> >> >+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
>> >> >+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
>> >> >+ vsi->netdev = netdev;
>> >> >+ np = netdev_priv(netdev);
>> >> >+ np->vsi = vsi;
>> >> >+
>> >> >+ ice_set_netdev_features(netdev);
>> >> >+
>> >> >+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
>> >> >+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
>> >> >+ NETDEV_XDP_ACT_RX_SG;
>> >> >+
>> >> >+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
>> >> >+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
>> >> >+ netdev->netdev_ops = &ice_sf_netdev_ops;
>> >> >+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
>> >> >+
>> >> >+ err = register_netdev(netdev);
>> >>
>> >> It the the actual subfunction or eswitch port representor of the
>> >> subfunction. Looks like the port representor. In that case. It should be
>> >> created no matter if the subfunction is activated, when it it created.
>> >>
>> >> If this is the actual subfunction netdev, you should not link it to
>> >> devlink port here.
>> >>
>> >This is the actual subfunction netdev. Where in this case it should be
>> >linked?
>>
>> To the SF auxdev, obviously.
>>
>> Here, you should have eswitch port representor netdev.
>>
>Oh, ok, thanks, will link it correctly in next version.
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 11:55 ` Michal Swiatkowski
@ 2024-02-13 22:04 ` Jacob Keller
2024-02-14 8:45 ` Jiri Pirko
0 siblings, 1 reply; 36+ messages in thread
From: Jacob Keller @ 2024-02-13 22:04 UTC (permalink / raw)
To: Michal Swiatkowski, Jiri Pirko
Cc: intel-wired-lan, netdev, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski
On 2/13/2024 3:55 AM, Michal Swiatkowski wrote:
> On Tue, Feb 13, 2024 at 12:29:40PM +0100, Jiri Pirko wrote:
>> Tue, Feb 13, 2024 at 10:53:50AM CET, michal.swiatkowski@linux.intel.com wrote:
>>> On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
>>>> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
>>>>> From: Piotr Raczynski <piotr.raczynski@intel.com>
>>>>>
>>>>> Add read only sysfs attribute for each auxiliary subfunction
>>>>> device. This attribute is needed for orchestration layer
>>>>> to distinguish SF devices from each other since there is no
>>>>> native devlink mechanism to represent the connection between
>>>>> devlink instance and the devlink port created for the port
>>>>> representor.
>>>>>
>>>>> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>>>>> Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>>>>> Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>>>>> ---
>>>>> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
>>>>> 1 file changed, 31 insertions(+)
>>>>>
>>>>> diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>> index ab90db52a8fc..abee733710a5 100644
>>>>> --- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>> +++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>> @@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
>>>>> kfree(sf_dev);
>>>>> }
>>>>>
>>>>> +static ssize_t
>>>>> +sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
>>>>> +{
>>>>> + struct devlink_port_attrs *attrs;
>>>>> + struct auxiliary_device *adev;
>>>>> + struct ice_sf_dev *sf_dev;
>>>>> +
>>>>> + adev = to_auxiliary_dev(dev);
>>>>> + sf_dev = ice_adev_to_sf_dev(adev);
>>>>> + attrs = &sf_dev->dyn_port->devlink_port.attrs;
>>>>> +
>>>>> + return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
>>>>> +}
>>>>> +
>>>>> +static DEVICE_ATTR_RO(sfnum);
>>>>> +
>>>>> +static struct attribute *ice_sf_device_attrs[] = {
>>>>> + &dev_attr_sfnum.attr,
>>>>> + NULL,
>>>>> +};
>>>>> +
>>>>> +static const struct attribute_group ice_sf_attr_group = {
>>>>> + .attrs = ice_sf_device_attrs,
>>>>> +};
>>>>> +
>>>>> +static const struct attribute_group *ice_sf_attr_groups[2] = {
>>>>> + &ice_sf_attr_group,
>>>>> + NULL
>>>>> +};
>>>>> +
>>>>> /**
>>>>> * ice_sf_eth_activate - Activate Ethernet subfunction port
>>>>> * @dyn_port: the dynamic port instance for this subfunction
>>>>> @@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
>>>>> sf_dev->dyn_port = dyn_port;
>>>>> sf_dev->adev.id = id;
>>>>> sf_dev->adev.name = "sf";
>>>>> + sf_dev->adev.dev.groups = ice_sf_attr_groups;
>>>>
>>>> Ugh. Custom driver sysfs files like this are always very questionable.
>>>> Don't do that please. If you need to expose sfnum, please think about
>>>> some common way. Why exactly you need to expose it?
>>>
>>> Uh, hard question. I will drop it and check if it still needed to expose
>>> the sfnum, probably no, as I have never used this sysfs during testing.
>>>
>>> Should devlink be used for it?
>>
>> sfnum is exposed over devlink on the port representor. If you need to
>> expose it on the actual SF, we have to figure it out. But again, why?
>>
>>
I vaguely remember some internal discussion about orchestration software
wanting to know which subfunction was associated with which auxiliary
device. However, I think a much better solution would be to expose the
auxiliary device ID out of devlink_port instead, through devlink port.
I can't find any notes on this and it was quite some time ago so maybe
things have changed.
If we enable support for user-space configurable sfnum, then we can just
have the orchestration software pick its sfnum (or check the netlink
return value from the port add), so probably this is not that useful.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [Intel-wired-lan] [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 14:57 ` Jiri Pirko
@ 2024-02-14 6:26 ` Michal Swiatkowski
0 siblings, 0 replies; 36+ messages in thread
From: Michal Swiatkowski @ 2024-02-14 6:26 UTC (permalink / raw)
To: Jiri Pirko
Cc: maciej.fijalkowski, netdev, michal.kubiak, intel-wired-lan,
pio.raczynski, sridhar.samudrala, jacob.e.keller, wojciech.drewek,
Piotr Raczynski, przemyslaw.kitszel
On Tue, Feb 13, 2024 at 03:57:59PM +0100, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 01:02:43PM CET, michal.swiatkowski@linux.intel.com wrote:
> >On Tue, Feb 13, 2024 at 12:27:20PM +0100, Jiri Pirko wrote:
> >> Tue, Feb 13, 2024 at 10:39:47AM CET, michal.swiatkowski@linux.intel.com wrote:
> >> >On Tue, Feb 13, 2024 at 09:55:20AM +0100, Jiri Pirko wrote:
> >> >> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
> >> >> >From: Piotr Raczynski <piotr.raczynski@intel.com>
> >>
> >> [...]
> >>
> >>
> >> >
> >> >>
> >> >> >+}
> >> >> >+
> >> >> >+/**
> >> >> >+ * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
> >> >> >+ * @dyn_port: dynamic port instance to deallocate
> >> >> >+ *
> >> >> >+ * Free resources associated with a dynamically added devlink port. Will
> >> >> >+ * deactivate the port if its currently active.
> >> >> >+ */
> >> >> >+static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
> >> >> >+{
> >> >> >+ struct devlink_port *devlink_port = &dyn_port->devlink_port;
> >> >> >+ struct ice_pf *pf = dyn_port->pf;
> >> >> >+
> >> >> >+ if (dyn_port->active)
> >> >> >+ ice_deactivate_dynamic_port(dyn_port);
> >> >> >+
> >> >> >+ if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF)
> >> >>
> >> >> I don't understand how this check could be false. Remove it.
> >> >>
> >> >Yeah, will remove
> >> >
> >> >>
> >> >> >+ xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
> >> >> >+
> >> >> >+ devl_port_unregister(devlink_port);
> >> >> >+ ice_vsi_free(dyn_port->vsi);
> >> >> >+ xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
> >> >> >+ kfree(dyn_port);
> >> >> >+}
> >> >> >+
> >> >> >+/**
> >> >> >+ * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
> >> >> >+ * @pf: pointer to the pf structure
> >> >> >+ */
> >> >> >+void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
> >> >> >+{
> >> >> >+ struct devlink *devlink = priv_to_devlink(pf);
> >> >> >+ struct ice_dynamic_port *dyn_port;
> >> >> >+ unsigned long index;
> >> >> >+
> >> >> >+ devl_lock(devlink);
> >> >> >+ xa_for_each(&pf->dyn_ports, index, dyn_port)
> >> >> >+ ice_dealloc_dynamic_port(dyn_port);
> >> >> >+ devl_unlock(devlink);
> >> >>
> >> >> Hmm, I would assume that the called should already hold the devlink
> >> >> instance lock when doing remove. What is stopping user from issuing
> >> >> port_new command here, after devl_unlock()?
> >> >>
> >> >It is only called from remove path, but I can move it upper.
> >>
> >> I know it is called on remove path. Again, what is stopping user from
> >> issuing port_new after ice_dealloc_all_dynamic_ports() is called?
> >>
> >> [...]
> >>
> >What is a problem here? Calling port_new from user perspective will have
> >devlink lock, right? Do you mean that devlink lock should be taken for
> >whole cleanup, so from the start to the moment when devlink is
> >unregister? I wrote that, I will do that in next version (moving it
>
> Yep, otherwise you can ice_dealloc_all_dynamic_ports() and end up with
> another port created after that which nobody cleans-up.
>
Thanks for pointing it, as you mentioned in other patch, I will take a
lock for whole init/cleanup.
> >upper).
> >
> >>
> >> >>
> >> >> >+ struct device *dev = ice_pf_to_dev(pf);
> >> >> >+ int err;
> >> >> >+
> >> >> >+ dev_dbg(dev, "%s flavour:%d index:%d pfnum:%d\n", __func__,
> >> >> >+ new_attr->flavour, new_attr->port_index, new_attr->pfnum);
> >> >>
> >> >> How this message could ever help anyone?
> >> >>
> >> >Probably only developer of the code :p, will remove it
> >>
> >> How exactly?
> >>
> >I meant this code developer, it probably was used to check if number and
> >indexes are correct, but now it should be removed. Like, leftover after
> >developing, sorry.
> >
> >> [...]
> >>
> >>
> >> >> >+static int ice_sf_cfg_netdev(struct ice_dynamic_port *dyn_port)
> >> >> >+{
> >> >> >+ struct net_device *netdev;
> >> >> >+ struct ice_vsi *vsi = dyn_port->vsi;
> >> >> >+ struct ice_netdev_priv *np;
> >> >> >+ int err;
> >> >> >+
> >> >> >+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
> >> >> >+ vsi->alloc_rxq);
> >> >> >+ if (!netdev)
> >> >> >+ return -ENOMEM;
> >> >> >+
> >> >> >+ SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev);
> >> >> >+ set_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
> >> >> >+ vsi->netdev = netdev;
> >> >> >+ np = netdev_priv(netdev);
> >> >> >+ np->vsi = vsi;
> >> >> >+
> >> >> >+ ice_set_netdev_features(netdev);
> >> >> >+
> >> >> >+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
> >> >> >+ NETDEV_XDP_ACT_XSK_ZEROCOPY |
> >> >> >+ NETDEV_XDP_ACT_RX_SG;
> >> >> >+
> >> >> >+ eth_hw_addr_set(netdev, dyn_port->hw_addr);
> >> >> >+ ether_addr_copy(netdev->perm_addr, dyn_port->hw_addr);
> >> >> >+ netdev->netdev_ops = &ice_sf_netdev_ops;
> >> >> >+ SET_NETDEV_DEVLINK_PORT(netdev, &dyn_port->devlink_port);
> >> >> >+
> >> >> >+ err = register_netdev(netdev);
> >> >>
> >> >> It the the actual subfunction or eswitch port representor of the
> >> >> subfunction. Looks like the port representor. In that case. It should be
> >> >> created no matter if the subfunction is activated, when it it created.
> >> >>
> >> >> If this is the actual subfunction netdev, you should not link it to
> >> >> devlink port here.
> >> >>
> >> >This is the actual subfunction netdev. Where in this case it should be
> >> >linked?
> >>
> >> To the SF auxdev, obviously.
> >>
> >> Here, you should have eswitch port representor netdev.
> >>
> >Oh, ok, thanks, will link it correctly in next version.
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-13 22:04 ` Jacob Keller
@ 2024-02-14 8:45 ` Jiri Pirko
2024-02-14 19:41 ` Keller, Jacob E
0 siblings, 1 reply; 36+ messages in thread
From: Jiri Pirko @ 2024-02-14 8:45 UTC (permalink / raw)
To: Jacob Keller
Cc: Michal Swiatkowski, intel-wired-lan, netdev, michal.kubiak,
maciej.fijalkowski, sridhar.samudrala, przemyslaw.kitszel,
wojciech.drewek, pio.raczynski, Piotr Raczynski
Tue, Feb 13, 2024 at 11:04:00PM CET, jacob.e.keller@intel.com wrote:
>
>
>On 2/13/2024 3:55 AM, Michal Swiatkowski wrote:
>> On Tue, Feb 13, 2024 at 12:29:40PM +0100, Jiri Pirko wrote:
>>> Tue, Feb 13, 2024 at 10:53:50AM CET, michal.swiatkowski@linux.intel.com wrote:
>>>> On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
>>>>> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com wrote:
>>>>>> From: Piotr Raczynski <piotr.raczynski@intel.com>
>>>>>>
>>>>>> Add read only sysfs attribute for each auxiliary subfunction
>>>>>> device. This attribute is needed for orchestration layer
>>>>>> to distinguish SF devices from each other since there is no
>>>>>> native devlink mechanism to represent the connection between
>>>>>> devlink instance and the devlink port created for the port
>>>>>> representor.
>>>>>>
>>>>>> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>>>>>> Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>>>>>> Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>>>>>> ---
>>>>>> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31 +++++++++++++++++++++
>>>>>> 1 file changed, 31 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>>> index ab90db52a8fc..abee733710a5 100644
>>>>>> --- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>>> +++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
>>>>>> @@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device *device)
>>>>>> kfree(sf_dev);
>>>>>> }
>>>>>>
>>>>>> +static ssize_t
>>>>>> +sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
>>>>>> +{
>>>>>> + struct devlink_port_attrs *attrs;
>>>>>> + struct auxiliary_device *adev;
>>>>>> + struct ice_sf_dev *sf_dev;
>>>>>> +
>>>>>> + adev = to_auxiliary_dev(dev);
>>>>>> + sf_dev = ice_adev_to_sf_dev(adev);
>>>>>> + attrs = &sf_dev->dyn_port->devlink_port.attrs;
>>>>>> +
>>>>>> + return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
>>>>>> +}
>>>>>> +
>>>>>> +static DEVICE_ATTR_RO(sfnum);
>>>>>> +
>>>>>> +static struct attribute *ice_sf_device_attrs[] = {
>>>>>> + &dev_attr_sfnum.attr,
>>>>>> + NULL,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group ice_sf_attr_group = {
>>>>>> + .attrs = ice_sf_device_attrs,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group *ice_sf_attr_groups[2] = {
>>>>>> + &ice_sf_attr_group,
>>>>>> + NULL
>>>>>> +};
>>>>>> +
>>>>>> /**
>>>>>> * ice_sf_eth_activate - Activate Ethernet subfunction port
>>>>>> * @dyn_port: the dynamic port instance for this subfunction
>>>>>> @@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port *dyn_port,
>>>>>> sf_dev->dyn_port = dyn_port;
>>>>>> sf_dev->adev.id = id;
>>>>>> sf_dev->adev.name = "sf";
>>>>>> + sf_dev->adev.dev.groups = ice_sf_attr_groups;
>>>>>
>>>>> Ugh. Custom driver sysfs files like this are always very questionable.
>>>>> Don't do that please. If you need to expose sfnum, please think about
>>>>> some common way. Why exactly you need to expose it?
>>>>
>>>> Uh, hard question. I will drop it and check if it still needed to expose
>>>> the sfnum, probably no, as I have never used this sysfs during testing.
>>>>
>>>> Should devlink be used for it?
>>>
>>> sfnum is exposed over devlink on the port representor. If you need to
>>> expose it on the actual SF, we have to figure it out. But again, why?
>>>
>>>
>
>I vaguely remember some internal discussion about orchestration software
>wanting to know which subfunction was associated with which auxiliary
>device. However, I think a much better solution would be to expose the
>auxiliary device ID out of devlink_port instead, through devlink port.
>
>I can't find any notes on this and it was quite some time ago so maybe
>things have changed.
>
>If we enable support for user-space configurable sfnum, then we can just
>have the orchestration software pick its sfnum (or check the netlink
>return value from the port add), so probably this is not that useful.
This is already solved by nested devlink. When you properly call
devl_port_fn_devlink_set(), you link the SF devlink instance with the
eswitch port representor. Then the user sees:
$ devlink port
pci/0000:08:00.1/98304: type eth netdev eth4 flavour pcisf controller 0 pfnum 1 sfnum 109 splittable false
function:
hw_addr 00:00:00:00:00:00 state active opstate attached roce enable
nested_devlink:
auxiliary/mlx5_core.sf.2
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
2024-02-14 8:45 ` Jiri Pirko
@ 2024-02-14 19:41 ` Keller, Jacob E
0 siblings, 0 replies; 36+ messages in thread
From: Keller, Jacob E @ 2024-02-14 19:41 UTC (permalink / raw)
To: Jiri Pirko
Cc: Michal Swiatkowski, intel-wired-lan@lists.osuosl.org,
netdev@vger.kernel.org, Kubiak, Michal, Fijalkowski, Maciej,
Samudrala, Sridhar, Kitszel, Przemyslaw, Drewek, Wojciech,
pio.raczynski@gmail.com, Piotr Raczynski
> -----Original Message-----
> From: Jiri Pirko <jiri@resnulli.us>
> Sent: Wednesday, February 14, 2024 12:45 AM
> To: Keller, Jacob E <jacob.e.keller@intel.com>
> Cc: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>; intel-wired-
> lan@lists.osuosl.org; netdev@vger.kernel.org; Kubiak, Michal
> <michal.kubiak@intel.com>; Fijalkowski, Maciej <maciej.fijalkowski@intel.com>;
> Samudrala, Sridhar <sridhar.samudrala@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; Drewek, Wojciech
> <wojciech.drewek@intel.com>; pio.raczynski@gmail.com; Piotr Raczynski
> <piotr.raczynski@intel.com>
> Subject: Re: [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute
>
> Tue, Feb 13, 2024 at 11:04:00PM CET, jacob.e.keller@intel.com wrote:
> >
> >
> >On 2/13/2024 3:55 AM, Michal Swiatkowski wrote:
> >> On Tue, Feb 13, 2024 at 12:29:40PM +0100, Jiri Pirko wrote:
> >>> Tue, Feb 13, 2024 at 10:53:50AM CET, michal.swiatkowski@linux.intel.com
> wrote:
> >>>> On Tue, Feb 13, 2024 at 09:59:14AM +0100, Jiri Pirko wrote:
> >>>>> Tue, Feb 13, 2024 at 08:27:16AM CET, michal.swiatkowski@linux.intel.com
> wrote:
> >>>>>> From: Piotr Raczynski <piotr.raczynski@intel.com>
> >>>>>>
> >>>>>> Add read only sysfs attribute for each auxiliary subfunction
> >>>>>> device. This attribute is needed for orchestration layer
> >>>>>> to distinguish SF devices from each other since there is no
> >>>>>> native devlink mechanism to represent the connection between
> >>>>>> devlink instance and the devlink port created for the port
> >>>>>> representor.
> >>>>>>
> >>>>>> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
> >>>>>> Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
> >>>>>> Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> >>>>>> ---
> >>>>>> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 31
> +++++++++++++++++++++
> >>>>>> 1 file changed, 31 insertions(+)
> >>>>>>
> >>>>>> diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >>>>>> index ab90db52a8fc..abee733710a5 100644
> >>>>>> --- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >>>>>> +++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
> >>>>>> @@ -224,6 +224,36 @@ static void ice_sf_dev_release(struct device
> *device)
> >>>>>> kfree(sf_dev);
> >>>>>> }
> >>>>>>
> >>>>>> +static ssize_t
> >>>>>> +sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
> >>>>>> +{
> >>>>>> + struct devlink_port_attrs *attrs;
> >>>>>> + struct auxiliary_device *adev;
> >>>>>> + struct ice_sf_dev *sf_dev;
> >>>>>> +
> >>>>>> + adev = to_auxiliary_dev(dev);
> >>>>>> + sf_dev = ice_adev_to_sf_dev(adev);
> >>>>>> + attrs = &sf_dev->dyn_port->devlink_port.attrs;
> >>>>>> +
> >>>>>> + return sysfs_emit(buf, "%u\n", attrs->pci_sf.sf);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static DEVICE_ATTR_RO(sfnum);
> >>>>>> +
> >>>>>> +static struct attribute *ice_sf_device_attrs[] = {
> >>>>>> + &dev_attr_sfnum.attr,
> >>>>>> + NULL,
> >>>>>> +};
> >>>>>> +
> >>>>>> +static const struct attribute_group ice_sf_attr_group = {
> >>>>>> + .attrs = ice_sf_device_attrs,
> >>>>>> +};
> >>>>>> +
> >>>>>> +static const struct attribute_group *ice_sf_attr_groups[2] = {
> >>>>>> + &ice_sf_attr_group,
> >>>>>> + NULL
> >>>>>> +};
> >>>>>> +
> >>>>>> /**
> >>>>>> * ice_sf_eth_activate - Activate Ethernet subfunction port
> >>>>>> * @dyn_port: the dynamic port instance for this subfunction
> >>>>>> @@ -262,6 +292,7 @@ ice_sf_eth_activate(struct ice_dynamic_port
> *dyn_port,
> >>>>>> sf_dev->dyn_port = dyn_port;
> >>>>>> sf_dev->adev.id = id;
> >>>>>> sf_dev->adev.name = "sf";
> >>>>>> + sf_dev->adev.dev.groups = ice_sf_attr_groups;
> >>>>>
> >>>>> Ugh. Custom driver sysfs files like this are always very questionable.
> >>>>> Don't do that please. If you need to expose sfnum, please think about
> >>>>> some common way. Why exactly you need to expose it?
> >>>>
> >>>> Uh, hard question. I will drop it and check if it still needed to expose
> >>>> the sfnum, probably no, as I have never used this sysfs during testing.
> >>>>
> >>>> Should devlink be used for it?
> >>>
> >>> sfnum is exposed over devlink on the port representor. If you need to
> >>> expose it on the actual SF, we have to figure it out. But again, why?
> >>>
> >>>
> >
> >I vaguely remember some internal discussion about orchestration software
> >wanting to know which subfunction was associated with which auxiliary
> >device. However, I think a much better solution would be to expose the
> >auxiliary device ID out of devlink_port instead, through devlink port.
> >
> >I can't find any notes on this and it was quite some time ago so maybe
> >things have changed.
> >
> >If we enable support for user-space configurable sfnum, then we can just
> >have the orchestration software pick its sfnum (or check the netlink
> >return value from the port add), so probably this is not that useful.
>
> This is already solved by nested devlink. When you properly call
> devl_port_fn_devlink_set(), you link the SF devlink instance with the
> eswitch port representor. Then the user sees:
>
> $ devlink port
> pci/0000:08:00.1/98304: type eth netdev eth4 flavour pcisf controller 0 pfnum 1
> sfnum 109 splittable false
> function:
> hw_addr 00:00:00:00:00:00 state active opstate attached roce enable
> nested_devlink:
> auxiliary/mlx5_core.sf.2
>
Excellent. That looks to resolve this entirely then.
Thanks,
Jake
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [iwl-next v1 04/15] ice: add basic devlink subfunctions support
2024-02-13 8:55 ` Jiri Pirko
2024-02-13 9:39 ` [Intel-wired-lan] " Michal Swiatkowski
@ 2024-02-14 19:45 ` Jacob Keller
1 sibling, 0 replies; 36+ messages in thread
From: Jacob Keller @ 2024-02-14 19:45 UTC (permalink / raw)
To: Jiri Pirko, Michal Swiatkowski
Cc: intel-wired-lan, netdev, michal.kubiak, maciej.fijalkowski,
sridhar.samudrala, przemyslaw.kitszel, wojciech.drewek,
pio.raczynski, Piotr Raczynski
On 2/13/2024 12:55 AM, Jiri Pirko wrote:
> Tue, Feb 13, 2024 at 08:27:13AM CET, michal.swiatkowski@linux.intel.com wrote:
>> From: Piotr Raczynski <piotr.raczynski@intel.com>
>>
>> Implement devlink port handlers responsible for ethernet type devlink
>> subfunctions. Create subfunction devlink port and setup all resources
>> needed for a subfunction netdev to operate. Configure new VSI for each
>> new subfunction, initialize and configure interrupts and Tx/Rx resources.
>> Set correct MAC filters and create new netdev.
>>
>> For now, subfunction is limited to only one Tx/Rx queue pair.
>>
>> Only allocate new subfunction VSI with devlink port new command.
>> This makes sure that real resources are configured only when a new
>> subfunction gets activated. Allocate and free subfunction MSIX
>> interrupt vectors using new API calls with pci_msix_alloc_irq_at
>> and pci_msix_free_irq.
>>
>> Temporarily, before adding auxiliary bus driver for subfunctions,
>> configure subfunction netdev directly for the created devlink
>> port. This will be modified in the next patch to properly that handle
>> devlink port as the port representor.
>>
>> Support both automatic and manual subfunction numbers. If no subfunction
>> number is provided, use xa_alloc to pick a number automatically. This
>> will find the first free index and use that as the number. This reduces
>> burden on users in the simple case where a specific number is not
>> required. It may also be slightly faster to check that a number exists
>> since xarray lookup should be faster than a linear scan of the dyn_ports
>> xarray.
>>
>> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
>> Co-developed-by: Jacob Keller <jacob.e.keller@intel.com>
>> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
>> Signed-off-by: Piotr Raczynski <piotr.raczynski@intel.com>
>> Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>> ---
>> drivers/net/ethernet/intel/ice/Makefile | 1 +
>> .../intel/ice/devlink/ice_devlink_port.c | 508 ++++++++++++++++++
>> .../intel/ice/devlink/ice_devlink_port.h | 30 ++
>> drivers/net/ethernet/intel/ice/ice.h | 4 +
>> drivers/net/ethernet/intel/ice/ice_devlink.c | 3 +
>> drivers/net/ethernet/intel/ice/ice_lib.c | 5 +-
>> drivers/net/ethernet/intel/ice/ice_lib.h | 2 +
>> drivers/net/ethernet/intel/ice/ice_main.c | 14 +-
>> drivers/net/ethernet/intel/ice/ice_sf_eth.c | 138 +++++
>> drivers/net/ethernet/intel/ice/ice_sf_eth.h | 15 +
>> 10 files changed, 716 insertions(+), 4 deletions(-)
>> create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.c
>> create mode 100644 drivers/net/ethernet/intel/ice/ice_sf_eth.h
>>
>> diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
>> index cd4ab46d72a7..d56a7165df95 100644
>> --- a/drivers/net/ethernet/intel/ice/Makefile
>> +++ b/drivers/net/ethernet/intel/ice/Makefile
>> @@ -31,6 +31,7 @@ ice-y := ice_main.o \
>> ice_idc.o \
>> ice_devlink.o \
>> devlink/ice_devlink_port.o \
>> + ice_sf_eth.o \
>> ice_ddp.o \
>> ice_fw_update.o \
>> ice_lag.o \
>> diff --git a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>> index c8c823467fcf..90efceaddb02 100644
>> --- a/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>> +++ b/drivers/net/ethernet/intel/ice/devlink/ice_devlink_port.c
>> @@ -10,6 +10,8 @@
>> #include "ice_eswitch.h"
>> #include "ice_fw_update.h"
>> #include "ice_dcb_lib.h"
>> +#include "ice_sf_eth.h"
>> +#include "ice_fltr.h"
>>
>> static int ice_active_port_option = -1;
>>
>> @@ -432,3 +434,509 @@ void ice_devlink_destroy_vf_port(struct ice_vf *vf)
>> devlink_port_unregister(&vf->devlink_port);
>> }
>>
>> +/**
>> + * ice_activate_dynamic_port - Activate a dynamic port
>> + * @dyn_port: dynamic port instance to activate
>> + * @extack: extack for reporting error messages
>> + *
>> + * Activate the dynamic port based on its flavour.
>> + *
>> + * Return: zero on success or an error code on failure.
>> + */
>> +static int
>> +ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,
>> + struct netlink_ext_ack *extack)
>> +{
>> + int err;
>> +
>> + switch (dyn_port->devlink_port.attrs.flavour) {
>> + case DEVLINK_PORT_FLAVOUR_PCI_SF:
>
> Pointless switch case.
>
> It looks like you have odd habbit of checking things that cannot happen
> all over this patch :) See more below...
>
>
I remember asking for this kind of split because I have some work for
supporting dynamic creation of Scalable IOV VFs which create a VF port
instead of a SF port. Since it only makes sense in that context, it
makes sense to remove it from this series and add it when its actually
necessary.
That's where the whole "dynamic_port" stuff comes from rather than just
calling it all "sf_port".
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2024-02-14 19:45 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-13 7:27 [iwl-next v1 00/15] ice: support devlink subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 01/15] ice: move devlink port code to a separate file Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 02/15] ice: add new VSI type for subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 03/15] ice: export ice ndo_ops functions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 04/15] ice: add basic devlink subfunctions support Michal Swiatkowski
2024-02-13 8:55 ` Jiri Pirko
2024-02-13 9:39 ` [Intel-wired-lan] " Michal Swiatkowski
2024-02-13 11:27 ` Jiri Pirko
2024-02-13 12:02 ` Michal Swiatkowski
2024-02-13 14:57 ` Jiri Pirko
2024-02-14 6:26 ` Michal Swiatkowski
2024-02-14 19:45 ` Jacob Keller
2024-02-13 7:27 ` [iwl-next v1 05/15] ice: add subfunctions ethtool ops Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 06/15] ice: add subfunction aux driver support Michal Swiatkowski
2024-02-13 8:57 ` Jiri Pirko
2024-02-13 9:43 ` Michal Swiatkowski
2024-02-13 11:28 ` Jiri Pirko
2024-02-13 12:03 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 07/15] ice: add auxiliary device sfnum attribute Michal Swiatkowski
2024-02-13 8:59 ` Jiri Pirko
2024-02-13 9:53 ` Michal Swiatkowski
2024-02-13 11:29 ` Jiri Pirko
2024-02-13 11:55 ` Michal Swiatkowski
2024-02-13 22:04 ` Jacob Keller
2024-02-14 8:45 ` Jiri Pirko
2024-02-14 19:41 ` Keller, Jacob E
2024-02-13 7:27 ` [iwl-next v1 08/15] ice: store SF data in VSI struct Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 09/15] ice: store representor ID in bridge port Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 10/15] ice: create port representor for SF Michal Swiatkowski
2024-02-13 9:00 ` Jiri Pirko
2024-02-13 9:55 ` Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 11/15] ice: check if SF is ready in ethtool ops Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 12/15] ice: netdevice ops for SF representor Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 13/15] ice: support subfunction devlink Tx topology Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 14/15] ice: basic support for VLAN in subfunctions Michal Swiatkowski
2024-02-13 7:27 ` [iwl-next v1 15/15] ice: move ice_devlink.[ch] to devlink folder Michal Swiatkowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).