summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/sfc/efx_devlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/sfc/efx_devlink.c')
-rw-r--r--drivers/net/ethernet/sfc/efx_devlink.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index 01e75eb244e3..0af25dca7b53 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -9,6 +9,7 @@
*/
#include "net_driver.h"
+#include "ef100_nic.h"
#include "efx_devlink.h"
#include <linux/rtc.h>
#include "mcdi.h"
@@ -58,6 +59,56 @@ static int efx_devlink_add_port(struct efx_nic *efx,
return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
}
+
+static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
+ int *hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct efx_devlink *devlink = devlink_priv(port->devlink);
+ struct mae_mport_desc *mport_desc;
+ efx_qword_t pciefn;
+ u32 client_id;
+ int rc = 0;
+
+ mport_desc = container_of(port, struct mae_mport_desc, dl_port);
+
+ if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
+ rc = -EINVAL;
+ NL_SET_ERR_MSG_FMT(extack,
+ "Port not on local interface (mport: %u)",
+ mport_desc->mport_id);
+ goto out;
+ }
+
+ if (ef100_mport_is_vf(mport_desc))
+ EFX_POPULATE_QWORD_3(pciefn,
+ PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
+ PCIE_FUNCTION_VF, mport_desc->vf_idx,
+ PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
+ else
+ EFX_POPULATE_QWORD_3(pciefn,
+ PCIE_FUNCTION_PF, mport_desc->pf_idx,
+ PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
+ PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
+
+ rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
+ if (rc) {
+ NL_SET_ERR_MSG_FMT(extack,
+ "No internal client_ID for port (mport: %u)",
+ mport_desc->mport_id);
+ goto out;
+ }
+
+ rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
+ if (rc != 0)
+ NL_SET_ERR_MSG_FMT(extack,
+ "No available MAC for port (mport: %u)",
+ mport_desc->mport_id);
+out:
+ *hw_addr_len = ETH_ALEN;
+ return rc;
+}
+
#endif
static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
@@ -514,6 +565,9 @@ static int efx_devlink_info_get(struct devlink *devlink,
static const struct devlink_ops sfc_devlink_ops = {
.info_get = efx_devlink_info_get,
+#ifdef CONFIG_SFC_SRIOV
+ .port_function_hw_addr_get = efx_devlink_port_addr_get,
+#endif
};
#ifdef CONFIG_SFC_SRIOV