common/sfc_efx/base: manage VNIC MAC address by MCDI handle

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>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
This commit is contained in:
Ivan Malov 2022-05-26 11:45:49 +03:00 committed by Andrew Rybchenko
parent b85f50487e
commit 78b82063df
4 changed files with 127 additions and 6 deletions

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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;