Skip to content

Commit

Permalink
Merge branch 'sfc-devlink-support-for-ef100'
Browse files Browse the repository at this point in the history
Alejandro Lucero says:

====================
sfc: devlink support for ef100

This patchset adds devlink port support for ef100 allowing setting VFs
mac addresses through the VF representor devlink ports.

Basic devlink infrastructure is first introduced, then support for info
command. Next changes for enumerating MAE ports which will be used for
devlink port creation when netdevs are registered.

Adding support for devlink port_function_hw_addr_get requires changes in
the ef100 driver for getting the mac address based on a client handle.
This allows to obtain VFs mac addresses during netdev initialization as
well what is included in patch 6.

Such client handle is used in patches 7 and 8 for getting and setting
devlink port addresses.
====================

Link: https://lore.kernel.org/r/20230215090828.11697-1-alejandro.lucero-palau@amd.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Feb 16, 2023
2 parents e9ab255 + 3b6096c commit fa15072
Show file tree
Hide file tree
Showing 17 changed files with 1,359 additions and 25 deletions.
1 change: 1 addition & 0 deletions Documentation/networking/devlink/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
prestera
iosm
octeontx2
sfc
57 changes: 57 additions & 0 deletions Documentation/networking/devlink/sfc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.. SPDX-License-Identifier: GPL-2.0
===================
sfc devlink support
===================

This document describes the devlink features implemented by the ``sfc``
device driver for the ef100 device.

Info versions
=============

The ``sfc`` driver reports the following versions

.. list-table:: devlink info versions implemented
:widths: 5 5 90

* - Name
- Type
- Description
* - ``fw.mgmt.suc``
- running
- For boards where the management function is split between multiple
control units, this is the SUC control unit's firmware version.
* - ``fw.mgmt.cmc``
- running
- For boards where the management function is split between multiple
control units, this is the CMC control unit's firmware version.
* - ``fpga.rev``
- running
- FPGA design revision.
* - ``fpga.app``
- running
- Datapath programmable logic version.
* - ``fw.app``
- running
- Datapath software/microcode/firmware version.
* - ``coproc.boot``
- running
- SmartNIC application co-processor (APU) first stage boot loader version.
* - ``coproc.uboot``
- running
- SmartNIC application co-processor (APU) co-operating system loader version.
* - ``coproc.main``
- running
- SmartNIC application co-processor (APU) main operating system version.
* - ``coproc.recovery``
- running
- SmartNIC application co-processor (APU) recovery operating system version.
* - ``fw.exprom``
- running
- Expansion ROM version. For boards where the expansion ROM is split between
multiple images (e.g. PXE and UEFI), this is the specifically the PXE boot
ROM version.
* - ``fw.uefi``
- running
- UEFI driver version (No UNDI support).
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -18937,6 +18937,7 @@ M: Edward Cree <ecree.xilinx@gmail.com>
M: Martin Habets <habetsm.xilinx@gmail.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/devlink/sfc.rst
F: drivers/net/ethernet/sfc/

SFF/SFP/SFP+ MODULE SUPPORT
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/sfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ config SFC
depends on PTP_1588_CLOCK_OPTIONAL
select MDIO
select CRC32
select NET_DEVLINK
help
This driver supports 10/40-gigabit Ethernet cards based on
the Solarflare SFC9100-family controllers.
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/sfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \
mcdi.o mcdi_port.o mcdi_port_common.o \
mcdi_functions.o mcdi_filters.o mcdi_mon.o \
ef100.o ef100_nic.o ef100_netdev.o \
ef100_ethtool.o ef100_rx.o ef100_tx.o
ef100_ethtool.o ef100_rx.o ef100_tx.o \
efx_devlink.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
mae.o tc.o tc_bindings.o tc_counters.o
Expand Down
30 changes: 30 additions & 0 deletions drivers/net/ethernet/sfc/ef100_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "rx_common.h"
#include "ef100_sriov.h"
#include "tc_bindings.h"
#include "efx_devlink.h"

static void ef100_update_name(struct efx_nic *efx)
{
Expand Down Expand Up @@ -332,9 +333,11 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
efx_ef100_pci_sriov_disable(efx, true);
#endif

efx_fini_devlink_lock(efx);
ef100_unregister_netdev(efx);

#ifdef CONFIG_SFC_SRIOV
ef100_pf_unset_devlink_port(efx);
efx_fini_tc(efx);
#endif

Expand All @@ -345,6 +348,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
kfree(efx->phy_data);
efx->phy_data = NULL;

efx_fini_devlink_and_unlock(efx);

free_netdev(efx->net_dev);
efx->net_dev = NULL;
efx->state = STATE_PROBED;
Expand All @@ -354,6 +359,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
{
struct efx_nic *efx = &probe_data->efx;
struct efx_probe_data **probe_ptr;
struct ef100_nic_data *nic_data;
struct net_device *net_dev;
int rc;

Expand Down Expand Up @@ -405,6 +411,20 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
/* Don't fail init if RSS setup doesn't work. */
efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);

nic_data = efx->nic_data;
rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF,
efx->type->is_vf);
if (rc)
return rc;
/* Assign MAC address */
eth_hw_addr_set(net_dev, net_dev->perm_addr);
ether_addr_copy(nic_data->port_id, net_dev->perm_addr);

/* devlink creation, registration and lock */
rc = efx_probe_devlink_and_lock(efx);
if (rc)
pci_info(efx->pci_dev, "devlink registration failed");

rc = ef100_register_netdev(efx);
if (rc)
goto fail;
Expand All @@ -413,6 +433,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
rc = ef100_probe_netdev_pf(efx);
if (rc)
goto fail;
#ifdef CONFIG_SFC_SRIOV
ef100_pf_set_devlink_port(efx);
#endif
}

efx->netdev_notifier.notifier_call = ef100_netdev_event;
Expand All @@ -423,6 +446,13 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
goto fail;
}

efx_probe_devlink_unlock(efx);
return rc;
fail:
#ifdef CONFIG_SFC_SRIOV
/* remove devlink port if does exist */
ef100_pf_unset_devlink_port(efx);
#endif
efx_probe_devlink_unlock(efx);
return rc;
}
93 changes: 74 additions & 19 deletions drivers/net/ethernet/sfc/ef100_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,34 @@ static void ef100_mcdi_reboot_detected(struct efx_nic *efx)

/* MCDI calls
*/
static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address)
int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
int client_handle, bool empty_ok)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1));
MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN);
size_t outlen;
int rc;

BUILD_BUG_ON(MC_CMD_GET_MAC_ADDRESSES_IN_LEN != 0);
MCDI_SET_DWORD(inbuf, GET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
client_handle);

rc = efx_mcdi_rpc(efx, MC_CMD_GET_MAC_ADDRESSES, NULL, 0,
outbuf, sizeof(outbuf), &outlen);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_MAC_ADDRESSES, inbuf,
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
if (rc)
return rc;
if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
return -EIO;

ether_addr_copy(mac_address,
MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE));
if (outlen >= MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1)) {
ether_addr_copy(mac_address,
MCDI_PTR(outbuf, GET_CLIENT_MAC_ADDRESSES_OUT_MAC_ADDRS));
} else if (empty_ok) {
pci_warn(efx->pci_dev,
"No MAC address provisioned for client ID %#x.\n",
client_handle);
eth_zero_addr(mac_address);
} else {
return -ENOENT;
}
return 0;
}

Expand Down Expand Up @@ -736,7 +747,7 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
/* Construct mport selector for "physical network port" */
efx_mae_mport_wire(efx, &selector);
/* Look up actual mport ID */
rc = efx_mae_lookup_mport(efx, selector, &id);
rc = efx_mae_fw_lookup_mport(efx, selector, &id);
if (rc)
return rc;
/* The ID should always fit in 16 bits, because that's how wide the
Expand All @@ -747,6 +758,19 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
id);
nic_data->base_mport = id;
nic_data->have_mport = true;

/* Construct mport selector for "calling PF" */
efx_mae_mport_uplink(efx, &selector);
/* Look up actual mport ID */
rc = efx_mae_fw_lookup_mport(efx, selector, &id);
if (rc)
return rc;
if (id >> 16)
netif_warn(efx, probe, efx->net_dev, "Bad own m-port id %#x\n",
id);
nic_data->own_mport = id;
nic_data->have_own_mport = true;

return 0;
}
#endif
Expand Down Expand Up @@ -1098,19 +1122,39 @@ static int ef100_probe_main(struct efx_nic *efx)
return rc;
}

/* MCDI commands are related to the same device issuing them. This function
* allows to do an MCDI command on behalf of another device, mainly PFs setting
* things for VFs.
*/
int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_HANDLE_OUT_LEN);
MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_HANDLE_IN_LEN);
u64 pciefn_flat = le64_to_cpu(pciefn.u64[0]);
size_t outlen;
int rc;

MCDI_SET_DWORD(inbuf, GET_CLIENT_HANDLE_IN_TYPE,
MC_CMD_GET_CLIENT_HANDLE_IN_TYPE_FUNC);
MCDI_SET_QWORD(inbuf, GET_CLIENT_HANDLE_IN_FUNC,
pciefn_flat);

rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_HANDLE, inbuf, sizeof(inbuf),
outbuf, sizeof(outbuf), &outlen);
if (rc)
return rc;
if (outlen < sizeof(outbuf))
return -EIO;
*id = MCDI_DWORD(outbuf, GET_CLIENT_HANDLE_OUT_HANDLE);
return 0;
}

int ef100_probe_netdev_pf(struct efx_nic *efx)
{
struct ef100_nic_data *nic_data = efx->nic_data;
struct net_device *net_dev = efx->net_dev;
int rc;

rc = ef100_get_mac_address(efx, net_dev->perm_addr);
if (rc)
goto fail;
/* Assign MAC address */
eth_hw_addr_set(net_dev, net_dev->perm_addr);
memcpy(nic_data->port_id, net_dev->perm_addr, ETH_ALEN);

if (!nic_data->grp_mae)
return 0;

Expand All @@ -1126,6 +1170,14 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
rc);
}

rc = efx_init_mae(efx);
if (rc)
netif_warn(efx, probe, net_dev,
"Failed to init MAE rc %d; representors will not function\n",
rc);
else
efx_ef100_init_reps(efx);

rc = efx_init_tc(efx);
if (rc) {
/* Either we don't have an MAE at all (i.e. legacy v-switching),
Expand All @@ -1142,9 +1194,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
efx->fixed_features |= NETIF_F_HW_TC;
}
#endif
return 0;

fail:
return rc;
}

Expand All @@ -1157,6 +1206,12 @@ void ef100_remove(struct efx_nic *efx)
{
struct ef100_nic_data *nic_data = efx->nic_data;

#ifdef CONFIG_SFC_SRIOV
if (efx->mae) {
efx_ef100_fini_reps(efx);
efx_fini_mae(efx);
}
#endif
efx_mcdi_detach(efx);
efx_mcdi_fini(efx);
if (nic_data)
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/sfc/ef100_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ struct ef100_nic_data {
u64 stats[EF100_STAT_COUNT];
u32 base_mport;
bool have_mport; /* base_mport was populated successfully */
u32 own_mport;
u32 local_mae_intf; /* interface_idx that corresponds to us, in mport enumerate */
bool have_own_mport; /* own_mport was populated successfully */
bool have_local_intf; /* local_mae_intf was populated successfully */
bool grp_mae; /* MAE Privilege */
u16 tso_max_hdr_len;
u16 tso_max_payload_num_segs;
Expand All @@ -88,4 +92,7 @@ int efx_ef100_init_datapath_caps(struct efx_nic *efx);
int ef100_phy_probe(struct efx_nic *efx);
int ef100_filter_table_probe(struct efx_nic *efx);

int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
int client_handle, bool empty_ok);
int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id);
#endif /* EFX_EF100_NIC_H */
Loading

0 comments on commit fa15072

Please sign in to comment.