Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfc: add support for devlink port_function_hw_addr_get in ef100

Using the builtin client handle id infrastructure, add support for
obtaining the mac address linked to mports in ef100. This implies
to execute an MCDI command for getting the data from the firmware
for each devlink port.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Acked-by: Martin Habets <habetsm.xilinx@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Alejandro Lucero and committed by
Paolo Abeni
fa78b017 7e056e23

+91
+27
drivers/net/ethernet/sfc/ef100_nic.c
··· 1122 1122 return rc; 1123 1123 } 1124 1124 1125 + /* MCDI commands are related to the same device issuing them. This function 1126 + * allows to do an MCDI command on behalf of another device, mainly PFs setting 1127 + * things for VFs. 1128 + */ 1129 + int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id) 1130 + { 1131 + MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_HANDLE_OUT_LEN); 1132 + MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_HANDLE_IN_LEN); 1133 + u64 pciefn_flat = le64_to_cpu(pciefn.u64[0]); 1134 + size_t outlen; 1135 + int rc; 1136 + 1137 + MCDI_SET_DWORD(inbuf, GET_CLIENT_HANDLE_IN_TYPE, 1138 + MC_CMD_GET_CLIENT_HANDLE_IN_TYPE_FUNC); 1139 + MCDI_SET_QWORD(inbuf, GET_CLIENT_HANDLE_IN_FUNC, 1140 + pciefn_flat); 1141 + 1142 + rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_HANDLE, inbuf, sizeof(inbuf), 1143 + outbuf, sizeof(outbuf), &outlen); 1144 + if (rc) 1145 + return rc; 1146 + if (outlen < sizeof(outbuf)) 1147 + return -EIO; 1148 + *id = MCDI_DWORD(outbuf, GET_CLIENT_HANDLE_OUT_HANDLE); 1149 + return 0; 1150 + } 1151 + 1125 1152 int ef100_probe_netdev_pf(struct efx_nic *efx) 1126 1153 { 1127 1154 struct ef100_nic_data *nic_data = efx->nic_data;
+1
drivers/net/ethernet/sfc/ef100_nic.h
··· 94 94 95 95 int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address, 96 96 int client_handle, bool empty_ok); 97 + int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id); 97 98 #endif /* EFX_EF100_NIC_H */
+8
drivers/net/ethernet/sfc/ef100_rep.c
··· 361 361 mport_desc->interface_idx == nic_data->local_mae_intf; 362 362 } 363 363 364 + bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc) 365 + { 366 + bool pcie_func; 367 + 368 + pcie_func = ef100_mport_is_pcie_vnic(mport_desc); 369 + return pcie_func && (mport_desc->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL); 370 + } 371 + 364 372 void efx_ef100_init_reps(struct efx_nic *efx) 365 373 { 366 374 struct ef100_nic_data *nic_data = efx->nic_data;
+1
drivers/net/ethernet/sfc/ef100_rep.h
··· 76 76 struct mae_mport_desc; 77 77 bool ef100_mport_on_local_intf(struct efx_nic *efx, 78 78 struct mae_mport_desc *mport_desc); 79 + bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc); 79 80 #endif /* EF100_REP_H */
+54
drivers/net/ethernet/sfc/efx_devlink.c
··· 9 9 */ 10 10 11 11 #include "net_driver.h" 12 + #include "ef100_nic.h" 12 13 #include "efx_devlink.h" 13 14 #include <linux/rtc.h> 14 15 #include "mcdi.h" ··· 59 58 60 59 return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id); 61 60 } 61 + 62 + static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr, 63 + int *hw_addr_len, 64 + struct netlink_ext_ack *extack) 65 + { 66 + struct efx_devlink *devlink = devlink_priv(port->devlink); 67 + struct mae_mport_desc *mport_desc; 68 + efx_qword_t pciefn; 69 + u32 client_id; 70 + int rc = 0; 71 + 72 + mport_desc = container_of(port, struct mae_mport_desc, dl_port); 73 + 74 + if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) { 75 + rc = -EINVAL; 76 + NL_SET_ERR_MSG_FMT(extack, 77 + "Port not on local interface (mport: %u)", 78 + mport_desc->mport_id); 79 + goto out; 80 + } 81 + 82 + if (ef100_mport_is_vf(mport_desc)) 83 + EFX_POPULATE_QWORD_3(pciefn, 84 + PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL, 85 + PCIE_FUNCTION_VF, mport_desc->vf_idx, 86 + PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER); 87 + else 88 + EFX_POPULATE_QWORD_3(pciefn, 89 + PCIE_FUNCTION_PF, mport_desc->pf_idx, 90 + PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL, 91 + PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER); 92 + 93 + rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id); 94 + if (rc) { 95 + NL_SET_ERR_MSG_FMT(extack, 96 + "No internal client_ID for port (mport: %u)", 97 + mport_desc->mport_id); 98 + goto out; 99 + } 100 + 101 + rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true); 102 + if (rc != 0) 103 + NL_SET_ERR_MSG_FMT(extack, 104 + "No available MAC for port (mport: %u)", 105 + mport_desc->mport_id); 106 + out: 107 + *hw_addr_len = ETH_ALEN; 108 + return rc; 109 + } 110 + 62 111 #endif 63 112 64 113 static int efx_devlink_info_nvram_partition(struct efx_nic *efx, ··· 565 514 566 515 static const struct devlink_ops sfc_devlink_ops = { 567 516 .info_get = efx_devlink_info_get, 517 + #ifdef CONFIG_SFC_SRIOV 518 + .port_function_hw_addr_get = efx_devlink_port_addr_get, 519 + #endif 568 520 }; 569 521 570 522 #ifdef CONFIG_SFC_SRIOV