[2/3] common/sfc_efx/base: manage VNIC MAC address by MCDI handle

Message ID 20220526084550.243121-2-ivan.malov@oktetlabs.ru (mailing list archive)
State Accepted, archived
Delegated to: Andrew Rybchenko
Headers
Series [1/3] common/sfc_efx/base: convert EFX PCIe INTF to MCDI value |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Ivan Malov May 26, 2022, 8:45 a.m. UTC
  The board admin may need to assign a MAC address to a guest
VNIC identified by its MCDI handle. Provide an API for that.

In the case when a libefx-based driver is used at the guest,
it will need to check its MAC address using the symmetrical
API if the admin has tweaked it by means of its representor.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_nic.c |   9 ++-
 drivers/common/sfc_efx/base/efx.h      |  21 ++++-
 drivers/common/sfc_efx/base/efx_mcdi.c | 101 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 127 insertions(+), 6 deletions(-)
  

Comments

Ray Kinsella May 26, 2022, 9:54 a.m. UTC | #1
Ivan Malov <ivan.malov@oktetlabs.ru> writes:

> The board admin may need to assign a MAC address to a guest
> VNIC identified by its MCDI handle. Provide an API for that.
>
> In the case when a libefx-based driver is used at the guest,
> it will need to check its MAC address using the symmetrical
> API if the admin has tweaked it by means of its representor.
>
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>  drivers/common/sfc_efx/base/ef10_nic.c |   9 ++-
>  drivers/common/sfc_efx/base/efx.h      |  21 ++++-
>  drivers/common/sfc_efx/base/efx_mcdi.c | 101 +++++++++++++++++++++++++
>  drivers/common/sfc_efx/version.map     |   2 +
>  4 files changed, 127 insertions(+), 6 deletions(-)
>

Acked-by: Ray Kinsella <mdr@ashoe.eu>
  

Patch

diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index aa667309ab..b27fc64210 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1991,8 +1991,9 @@  efx_mcdi_nic_board_cfg(
 	if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
 		goto fail4;
 
-	/* MAC address for this function */
-	if (EFX_PCI_FUNCTION_IS_PF(encp)) {
+	rc = efx_mcdi_client_mac_addr_get(enp, CLIENT_HANDLE_SELF, mac_addr);
+	if ((rc != 0) && EFX_PCI_FUNCTION_IS_PF(encp)) {
+		/* Fallback for legacy MAC address get approach (PF) */
 		rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
 #if EFSYS_OPT_ALLOW_UNCONFIGURED_NIC
 		/*
@@ -2011,9 +2012,11 @@  efx_mcdi_nic_board_cfg(
 			rc = EINVAL;
 		}
 #endif /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
-	} else {
+	} else if (rc != 0) {
+		/* Fallback for legacy MAC address get approach (VF) */
 		rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
 	}
+
 	if (rc != 0)
 		goto fail5;
 
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 854527e0fd..95f5fb6bc0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -311,6 +311,8 @@  efx_nic_check_pcie_link_speed(
 	__in		uint32_t pcie_link_gen,
 	__out		efx_pcie_link_performance_t *resultp);
 
+#define	EFX_MAC_ADDR_LEN 6
+
 #if EFSYS_OPT_MCDI
 
 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
@@ -406,6 +408,20 @@  efx_mcdi_get_own_client_handle(
 	__in		efx_nic_t *enp,
 	__out		uint32_t *handle);
 
+LIBEFX_API
+extern	__checkReturn	efx_rc_t
+efx_mcdi_client_mac_addr_get(
+	__in		efx_nic_t *enp,
+	__in		uint32_t client_handle,
+	__out		uint8_t addr_bytes[EFX_MAC_ADDR_LEN]);
+
+LIBEFX_API
+extern	__checkReturn	efx_rc_t
+efx_mcdi_client_mac_addr_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t client_handle,
+	__in		const uint8_t addr_bytes[EFX_MAC_ADDR_LEN]);
+
 LIBEFX_API
 extern			void
 efx_mcdi_fini(
@@ -616,11 +632,10 @@  typedef enum efx_link_mode_e {
 	EFX_LINK_NMODES
 } efx_link_mode_t;
 
-#define	EFX_MAC_ADDR_LEN 6
-
 #define	EFX_VNI_OR_VSID_LEN 3
 
-#define	EFX_MAC_ADDR_IS_MULTICAST(_address) (((uint8_t *)_address)[0] & 0x01)
+#define	EFX_MAC_ADDR_IS_MULTICAST(_address)	\
+	(((const uint8_t *)_address)[0] & 0x01)
 
 #define	EFX_MAC_MULTICAST_LIST_MAX	256
 
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c
index 404ca23d58..6274cf6bac 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.c
+++ b/drivers/common/sfc_efx/base/efx_mcdi.c
@@ -727,6 +727,107 @@  efx_mcdi_get_own_client_handle(
 	return (rc);
 }
 
+	__checkReturn	efx_rc_t
+efx_mcdi_client_mac_addr_get(
+	__in		efx_nic_t *enp,
+	__in		uint32_t client_handle,
+	__out		uint8_t addr_bytes[EFX_MAC_ADDR_LEN])
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN,
+	    MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1));
+	efx_rc_t rc;
+
+	req.emr_cmd = MC_CMD_GET_CLIENT_MAC_ADDRESSES;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, GET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
+	    client_handle);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used <
+	    MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1)) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	memcpy(addr_bytes,
+	    MCDI_OUT2(req, uint8_t, GET_CLIENT_MAC_ADDRESSES_OUT_MAC_ADDRS),
+	    EFX_MAC_ADDR_LEN);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn	efx_rc_t
+efx_mcdi_client_mac_addr_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t client_handle,
+	__in		const uint8_t addr_bytes[EFX_MAC_ADDR_LEN])
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1),
+	    MC_CMD_SET_CLIENT_MAC_ADDRESSES_OUT_LEN);
+	uint32_t oui;
+	efx_rc_t rc;
+
+	if (EFX_MAC_ADDR_IS_MULTICAST(addr_bytes)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	oui = addr_bytes[0] << 16 | addr_bytes[1] << 8 | addr_bytes[2];
+	if (oui == 0x000000) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_SET_CLIENT_MAC_ADDRESSES;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_SET_CLIENT_MAC_ADDRESSES_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
+	    client_handle);
+
+	memcpy(MCDI_IN2(req, uint8_t, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
+	    addr_bytes, EFX_MAC_ADDR_LEN);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 			void
 efx_mcdi_get_timeout(
 	__in		efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 9510897b83..a54aab0a08 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -144,6 +144,8 @@  INTERNAL {
 	efx_mae_outer_rule_remove;
 	efx_mae_read_mport_journal;
 
+	efx_mcdi_client_mac_addr_get;
+	efx_mcdi_client_mac_addr_set;
 	efx_mcdi_fini;
 	efx_mcdi_get_client_handle;
 	efx_mcdi_get_own_client_handle;