[v2,1/4] common/sfc_efx/base: discover NIC partitioning mode

Message ID 20230622034738.51288-2-denis.pryazhennikov@arknetworks.am (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: support KEEP_CRC offload |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Denis Pryazhennikov June 22, 2023, 3:47 a.m. UTC
  From: Sandilya Bhagi <sbhagi@solarflare.com>

NIC Partitioning mode in SFC devices means multiple PFs
per network port. When NIC Partitioning is configured,
apart from the privileged adapter(s) the other
unprivileged adapter(s) will share the same physical port.
Determining NIC Partitioning mode is required to take
necessary action(s) for unprivileged adapter to work seamlessly.
BNIC Partitioning is determined using heuristic approach.
If the physical ports are shared between PFs then either
NIC Partitioning or SR-IOV is in use.

Signed-off-by: Sandilya Bhagi <sbhagi@solarflare.com>
Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_nic.c | 102 +++++++++++++++++++++++++
 drivers/common/sfc_efx/base/efx.h      |   8 ++
 2 files changed, 110 insertions(+)
  

Comments

Andrew Rybchenko June 22, 2023, 9:48 a.m. UTC | #1
On 6/22/23 06:47, Denis Pryazhennikov wrote:
> From: Sandilya Bhagi <sbhagi@solarflare.com>
> 
> NIC Partitioning mode in SFC devices means multiple PFs
> per network port. When NIC Partitioning is configured,
> apart from the privileged adapter(s) the other
> unprivileged adapter(s) will share the same physical port.
> Determining NIC Partitioning mode is required to take
> necessary action(s) for unprivileged adapter to work seamlessly.
> BNIC Partitioning is determined using heuristic approach.
> If the physical ports are shared between PFs then either
> NIC Partitioning or SR-IOV is in use.
> 
> Signed-off-by: Sandilya Bhagi <sbhagi@solarflare.com>
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

Overall LGMT with few style notes:

Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

[snip]

> +#define CAP_PFS_TO_PORTS(_n)	\
> +	(MC_CMD_GET_CAPABILITIES_V2_OUT_PFS_TO_PORTS_ASSIGNMENT_ ## _n)
> +
> +	encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
> +
> +	if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) {
> +		/* PFs to ports assignment */
> +		uint8_t pfs_to_ports[CAP_PFS_TO_PORTS(NUM)];
> +
> +		EFX_STATIC_ASSERT((CAP_PFS_TO_PORTS(NUM) * CAP_PFS_TO_PORTS(LEN)) ==
> +				  EFX_ARRAY_SIZE(pfs_to_ports));

As far as I remember libefx style, it should be 4 spaces indent above
relative to mail line.

> +
> +		memcpy(pfs_to_ports, MCDI_OUT(req, efx_byte_t, CAP_PFS_TO_PORTS(OFST)),
> +		       EFX_ARRAY_SIZE(pfs_to_ports));

same here, 4 spaces indent

> +
> +		rc = ef10_nic_get_physical_port_usage(enp, pfs_to_ports,
> +						      EFX_ARRAY_SIZE(pfs_to_ports),
> +						      &encp->enc_port_usage);

same here, 4 spaces indent

> +		if (rc != 0) {
> +			/* PF to port mapping lookup failed */
> +			encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
> +		}
> +	}
> +#undef  CAP_PFS_TO_PORTS
> +
>   	/*
>   	 * Check if firmware reports the VI window mode.
>   	 * Medford2 has a variable VI window size (8K, 16K or 64K).

[snip]
  

Patch

diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index e1709d120093..507b784b25cd 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1044,6 +1044,83 @@  ef10_mcdi_get_pf_count(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+ef10_nic_get_physical_port_usage(
+	__in				efx_nic_t *enp,
+	__in_ecount(pfs_to_ports_size)	uint8_t *pfs_to_ports,
+	__in				size_t pfs_to_ports_size,
+	__out				efx_port_usage_t *port_usagep)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_port_usage_t port_usage;
+	uint8_t phy_port;
+	efx_rc_t rc;
+	size_t pf;
+
+	/*
+	 * The sharing of physical ports between functions are determined
+	 * in the following way.
+	 * 1. If VFs are enabled then the physical port is shared.
+	 * 2. Retrieve PFs to ports assignment.
+	 * 3. If PF 0 assignment cannot be retrieved(ACCESS_DENIED), it
+	 *    implies this is an unprivileged function. An unprivileged
+	 *    function indicates the physical port must be shared with
+	 *    another privileged function.
+	 * 4. If PF 0 assignment can be retrieved, it indicates this
+	 *    function is privileged. Now, read all other PF's physical
+	 *    port number assignment and check if the current PF's physical
+	 *    port is shared with any other PF's physical port.
+	 * NOTE: PF 0 is always privileged function.
+	 */
+
+	if (EFX_PCI_FUNCTION_IS_VF(encp)) {
+		port_usage = EFX_PORT_USAGE_SHARED;
+		goto out;
+	}
+
+	if (pfs_to_ports[0] ==
+	    MC_CMD_GET_CAPABILITIES_V2_OUT_ACCESS_NOT_PERMITTED) {
+		/*
+		 * This is unprivileged function as it do not have sufficient
+		 * privileges to read the value, this implies the physical port
+		 * is shared between this function and another privileged
+		 * function
+		 */
+		port_usage = EFX_PORT_USAGE_SHARED;
+		goto out;
+	}
+
+	if (encp->enc_pf >= pfs_to_ports_size) {
+		rc = EINVAL;
+		goto fail1;
+	}
+	phy_port = pfs_to_ports[encp->enc_pf];
+
+	/*
+	 * This is privileged function as it is able read the value of
+	 * PF 0. Now, check if any other function share the same physical
+	 * port number as this function.
+	 */
+	for (pf = 0; pf < pfs_to_ports_size; pf++) {
+		if ((encp->enc_pf != pf) && (phy_port == pfs_to_ports[pf])) {
+			/* Found match, PFs share the same physical port */
+			port_usage = EFX_PORT_USAGE_SHARED;
+			goto out;
+		}
+	}
+
+	port_usage = EFX_PORT_USAGE_EXCLUSIVE;
+
+out:
+	*port_usagep = port_usage;
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 static	__checkReturn	efx_rc_t
 ef10_get_datapath_caps(
 	__in		efx_nic_t *enp)
@@ -1307,6 +1384,31 @@  ef10_get_datapath_caps(
 		encp->enc_tunnel_config_udp_entries_max = 0;
 	}
 
+#define CAP_PFS_TO_PORTS(_n)	\
+	(MC_CMD_GET_CAPABILITIES_V2_OUT_PFS_TO_PORTS_ASSIGNMENT_ ## _n)
+
+	encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
+
+	if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) {
+		/* PFs to ports assignment */
+		uint8_t pfs_to_ports[CAP_PFS_TO_PORTS(NUM)];
+
+		EFX_STATIC_ASSERT((CAP_PFS_TO_PORTS(NUM) * CAP_PFS_TO_PORTS(LEN)) ==
+				  EFX_ARRAY_SIZE(pfs_to_ports));
+
+		memcpy(pfs_to_ports, MCDI_OUT(req, efx_byte_t, CAP_PFS_TO_PORTS(OFST)),
+		       EFX_ARRAY_SIZE(pfs_to_ports));
+
+		rc = ef10_nic_get_physical_port_usage(enp, pfs_to_ports,
+						      EFX_ARRAY_SIZE(pfs_to_ports),
+						      &encp->enc_port_usage);
+		if (rc != 0) {
+			/* PF to port mapping lookup failed */
+			encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
+		}
+	}
+#undef  CAP_PFS_TO_PORTS
+
 	/*
 	 * Check if firmware reports the VI window mode.
 	 * Medford2 has a variable VI window size (8K, 16K or 64K).
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f156f8b5b31a..a63211612249 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -311,6 +311,12 @@  efx_nic_check_pcie_link_speed(
 	__in		uint32_t pcie_link_gen,
 	__out		efx_pcie_link_performance_t *resultp);
 
+typedef enum efx_port_usage_e {
+	EFX_PORT_USAGE_UNKNOWN = 0,
+	EFX_PORT_USAGE_EXCLUSIVE,	/* Port only used by this PF */
+	EFX_PORT_USAGE_SHARED,		/* Port shared with other PFs */
+} efx_port_usage_t;
+
 #define	EFX_MAC_ADDR_LEN 6
 
 #if EFSYS_OPT_MCDI
@@ -1682,6 +1688,8 @@  typedef struct efx_nic_cfg_s {
 	uint32_t		enc_assigned_port;
 	/* NIC DMA mapping type */
 	efx_nic_dma_mapping_t	enc_dma_mapping;
+	/* Physical ports shared by PFs */
+	efx_port_usage_t	enc_port_usage;
 } efx_nic_cfg_t;
 
 #define	EFX_PCI_VF_INVALID 0xffff