diff mbox series

[v4,net-next,1/8] sfc: add devlink support for ef100

Message ID 20230131145822.36208-2-alejandro.lucero-palau@amd.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series sfc: devlink support for ef100 | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1 this patch: 1
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1 this patch: 1
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
netdev/kdoc success Errors and warnings before: 57 this patch: 57
netdev/source_inline success Was 0 now: 0

Commit Message

Lucero Palau, Alejandro Jan. 31, 2023, 2:58 p.m. UTC
From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Basic devlink infrastructure support.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/Kconfig        |  1 +
 drivers/net/ethernet/sfc/Makefile       |  3 +-
 drivers/net/ethernet/sfc/ef100_netdev.c | 12 +++++
 drivers/net/ethernet/sfc/ef100_nic.c    |  3 +-
 drivers/net/ethernet/sfc/efx_devlink.c  | 71 +++++++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_devlink.h  | 22 ++++++++
 drivers/net/ethernet/sfc/net_driver.h   |  2 +
 7 files changed, 111 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h

Comments

Jiri Pirko Jan. 31, 2023, 4 p.m. UTC | #1
Tue, Jan 31, 2023 at 03:58:15PM CET, alejandro.lucero-palau@amd.com wrote:
>From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>
>Basic devlink infrastructure support.
>
>Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>---
> drivers/net/ethernet/sfc/Kconfig        |  1 +
> drivers/net/ethernet/sfc/Makefile       |  3 +-
> drivers/net/ethernet/sfc/ef100_netdev.c | 12 +++++
> drivers/net/ethernet/sfc/ef100_nic.c    |  3 +-
> drivers/net/ethernet/sfc/efx_devlink.c  | 71 +++++++++++++++++++++++++
> drivers/net/ethernet/sfc/efx_devlink.h  | 22 ++++++++
> drivers/net/ethernet/sfc/net_driver.h   |  2 +
> 7 files changed, 111 insertions(+), 3 deletions(-)
> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h
>
>diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
>index 0950e6b0508f..4af36ba8906b 100644
>--- a/drivers/net/ethernet/sfc/Kconfig
>+++ b/drivers/net/ethernet/sfc/Kconfig
>@@ -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.
>diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
>index 712a48d00069..55b9c73cd8ef 100644
>--- a/drivers/net/ethernet/sfc/Makefile
>+++ b/drivers/net/ethernet/sfc/Makefile
>@@ -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
>diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
>index ddcc325ed570..b10a226f4a07 100644
>--- a/drivers/net/ethernet/sfc/ef100_netdev.c
>+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
>@@ -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)
> {
>@@ -332,6 +333,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
> 		efx_ef100_pci_sriov_disable(efx, true);
> #endif
> 
>+	/* devlink lock */
>+	efx_fini_devlink_start(efx);
> 	ef100_unregister_netdev(efx);
> 
> #ifdef CONFIG_SFC_SRIOV
>@@ -345,6 +348,9 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
> 	kfree(efx->phy_data);
> 	efx->phy_data = NULL;
> 
>+	/* devlink unlock */
>+	efx_fini_devlink(efx);
>+
> 	free_netdev(efx->net_dev);
> 	efx->net_dev = NULL;
> 	efx->state = STATE_PROBED;
>@@ -405,6 +411,10 @@ 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);
> 
>+	/* devlink creation, registration and lock */
>+	if (efx_probe_devlink(efx))

Use variable to store the return value and check that in if.


>+		pci_info(efx->pci_dev, "devlink registration failed");
>+
> 	rc = ef100_register_netdev(efx);
> 	if (rc)
> 		goto fail;
>@@ -424,5 +434,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
> 	}
> 
> fail:
>+	/* devlink unlock */
>+	efx_probe_devlink_done(efx);
> 	return rc;
> }
>diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
>index ad686c671ab8..e4aacb4ec666 100644
>--- a/drivers/net/ethernet/sfc/ef100_nic.c
>+++ b/drivers/net/ethernet/sfc/ef100_nic.c
>@@ -1120,11 +1120,10 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
> 		return rc;
> 
> 	rc = efx_ef100_get_base_mport(efx);
>-	if (rc) {
>+	if (rc)
> 		netif_warn(efx, probe, net_dev,
> 			   "Failed to probe base mport rc %d; representors will not function\n",
> 			   rc);
>-	}

I don't see how this hunk is related to this patch. Please remove.


> 
> 	rc = efx_init_tc(efx);
> 	if (rc) {
>diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
>new file mode 100644
>index 000000000000..fab06aaa4b8a
>--- /dev/null
>+++ b/drivers/net/ethernet/sfc/efx_devlink.c
>@@ -0,0 +1,71 @@
>+// SPDX-License-Identifier: GPL-2.0-only
>+/****************************************************************************
>+ * Driver for AMD network controllers and boards
>+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
>+ *
>+ * This program is free software; you can redistribute it and/or modify it
>+ * under the terms of the GNU General Public License version 2 as published
>+ * by the Free Software Foundation, incorporated herein by reference.
>+ */
>+
>+#include <linux/rtc.h>
>+#include "net_driver.h"
>+#include "ef100_nic.h"
>+#include "efx_devlink.h"
>+#include "nic.h"
>+#include "mcdi.h"
>+#include "mcdi_functions.h"
>+#include "mcdi_pcol.h"
>+
>+struct efx_devlink {
>+	struct efx_nic *efx;
>+};
>+
>+static const struct devlink_ops sfc_devlink_ops = {
>+};
>+
>+void efx_fini_devlink_start(struct efx_nic *efx)
>+{
>+	if (efx->devlink)
>+		devl_lock(efx->devlink);
>+}
>+
>+void efx_fini_devlink(struct efx_nic *efx)
>+{
>+	if (efx->devlink) {
>+		devl_unregister(efx->devlink);
>+		devl_unlock(efx->devlink);
>+		devlink_free(efx->devlink);
>+		efx->devlink = NULL;
>+	}
>+}
>+
>+int efx_probe_devlink(struct efx_nic *efx)
>+{
>+	struct efx_devlink *devlink_private;
>+
>+	if (efx->type->is_vf)
>+		return 0;
>+
>+	efx->devlink = devlink_alloc(&sfc_devlink_ops,
>+				     sizeof(struct efx_devlink),
>+				     &efx->pci_dev->dev);
>+	if (!efx->devlink)
>+		return -ENOMEM;
>+
>+	devl_lock(efx->devlink);
>+	devlink_private = devlink_priv(efx->devlink);
>+	devlink_private->efx = efx;
>+
>+	devl_register(efx->devlink);
>+
>+	return 0;
>+}
>+
>+void efx_probe_devlink_done(struct efx_nic *efx)
>+{
>+	if (!efx->devlink)
>+		return;
>+
>+	devl_unlock(efx->devlink);
>+}
>diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
>new file mode 100644
>index 000000000000..55d0d8aeca1e
>--- /dev/null
>+++ b/drivers/net/ethernet/sfc/efx_devlink.h
>@@ -0,0 +1,22 @@
>+/* SPDX-License-Identifier: GPL-2.0-only */
>+/****************************************************************************
>+ * Driver for AMD network controllers and boards
>+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
>+ *
>+ * This program is free software; you can redistribute it and/or modify it
>+ * under the terms of the GNU General Public License version 2 as published
>+ * by the Free Software Foundation, incorporated herein by reference.
>+ */
>+
>+#ifndef _EFX_DEVLINK_H
>+#define _EFX_DEVLINK_H
>+
>+#include "net_driver.h"
>+#include <net/devlink.h>
>+
>+int efx_probe_devlink(struct efx_nic *efx);
>+void efx_probe_devlink_done(struct efx_nic *efx);
>+void efx_fini_devlink_start(struct efx_nic *efx);
>+void efx_fini_devlink(struct efx_nic *efx);

Odd naming... Just saying.


>+
>+#endif	/* _EFX_DEVLINK_H */
>diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
>index 3b49e216768b..d036641dc043 100644
>--- a/drivers/net/ethernet/sfc/net_driver.h
>+++ b/drivers/net/ethernet/sfc/net_driver.h
>@@ -994,6 +994,7 @@ enum efx_xdp_tx_queues_mode {
>  *      xdp_rxq_info structures?
>  * @netdev_notifier: Netdevice notifier.
>  * @tc: state for TC offload (EF100).
>+ * @devlink: reference to devlink structure owned by this device
>  * @mem_bar: The BAR that is mapped into membase.
>  * @reg_base: Offset from the start of the bar to the function control window.
>  * @monitor_work: Hardware monitor workitem
>@@ -1179,6 +1180,7 @@ struct efx_nic {
> 	struct notifier_block netdev_notifier;
> 	struct efx_tc_state *tc;
> 
>+	struct devlink *devlink;
> 	unsigned int mem_bar;
> 	u32 reg_base;
> 
>-- 
>2.17.1
>
Lucero Palau, Alejandro Feb. 1, 2023, 8:49 a.m. UTC | #2
On 1/31/23 16:00, Jiri Pirko wrote:
> Tue, Jan 31, 2023 at 03:58:15PM CET, alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com> wrote:
>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com>>
>>
>> Basic devlink infrastructure support.
>>
>> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com>>
>> ---
>> drivers/net/ethernet/sfc/Kconfig | 1 +
>> drivers/net/ethernet/sfc/Makefile | 3 +-
>> drivers/net/ethernet/sfc/ef100_netdev.c | 12 +++++
>> drivers/net/ethernet/sfc/ef100_nic.c | 3 +-
>> drivers/net/ethernet/sfc/efx_devlink.c | 71 +++++++++++++++++++++++++
>> drivers/net/ethernet/sfc/efx_devlink.h | 22 ++++++++
>> drivers/net/ethernet/sfc/net_driver.h | 2 +
>> 7 files changed, 111 insertions(+), 3 deletions(-)
>> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
>> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h
>>
>> diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
>> index 0950e6b0508f..4af36ba8906b 100644
>> --- a/drivers/net/ethernet/sfc/Kconfig
>> +++ b/drivers/net/ethernet/sfc/Kconfig
>> @@ -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.
>> diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
>> index 712a48d00069..55b9c73cd8ef 100644
>> --- a/drivers/net/ethernet/sfc/Makefile
>> +++ b/drivers/net/ethernet/sfc/Makefile
>> @@ -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
>> diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
>> index ddcc325ed570..b10a226f4a07 100644
>> --- a/drivers/net/ethernet/sfc/ef100_netdev.c
>> +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
>> @@ -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)
>> {
>> @@ -332,6 +333,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>> efx_ef100_pci_sriov_disable(efx, true);
>> #endif
>>
>> + /* devlink lock */
>> + efx_fini_devlink_start(efx);
>> ef100_unregister_netdev(efx);
>>
>> #ifdef CONFIG_SFC_SRIOV
>> @@ -345,6 +348,9 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>> kfree(efx->phy_data);
>> efx->phy_data = NULL;
>>
>> + /* devlink unlock */
>> + efx_fini_devlink(efx);
>> +
>> free_netdev(efx->net_dev);
>> efx->net_dev = NULL;
>> efx->state = STATE_PROBED;
>> @@ -405,6 +411,10 @@ 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);
>>
>> + /* devlink creation, registration and lock */
>> + if (efx_probe_devlink(efx))
> Use variable to store the return value and check that in if.
>

I'll do.

>> + pci_info(efx->pci_dev, "devlink registration failed");
>> +
>> rc = ef100_register_netdev(efx);
>> if (rc)
>> goto fail;
>> @@ -424,5 +434,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>> }
>>
>> fail:
>> + /* devlink unlock */
>> + efx_probe_devlink_done(efx);
>> return rc;
>> }
>> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
>> index ad686c671ab8..e4aacb4ec666 100644
>> --- a/drivers/net/ethernet/sfc/ef100_nic.c
>> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
>> @@ -1120,11 +1120,10 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
>> return rc;
>>
>> rc = efx_ef100_get_base_mport(efx);
>> - if (rc) {
>> + if (rc)
>> netif_warn(efx, probe, net_dev,
>> "Failed to probe base mport rc %d; representors will not function\n",
>> rc);
>> - }
> I don't see how this hunk is related to this patch. Please remove.
>
>

Running checkpatch on this specific patch triggered a warning about the 
netif_warn requiring brackets.

It is true it is not related to the patch itself, so I'll remove it.

>> rc = efx_init_tc(efx);
>> if (rc) {
>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
>> new file mode 100644
>> index 000000000000..fab06aaa4b8a
>> --- /dev/null
>> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
>> @@ -0,0 +1,71 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/****************************************************************************
>> + * Driver for AMD network controllers and boards
>> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published
>> + * by the Free Software Foundation, incorporated herein by reference.
>> + */
>> +
>> +#include <linux/rtc.h>
>> +#include "net_driver.h"
>> +#include "ef100_nic.h"
>> +#include "efx_devlink.h"
>> +#include "nic.h"
>> +#include "mcdi.h"
>> +#include "mcdi_functions.h"
>> +#include "mcdi_pcol.h"
>> +
>> +struct efx_devlink {
>> + struct efx_nic *efx;
>> +};
>> +
>> +static const struct devlink_ops sfc_devlink_ops = {
>> +};
>> +
>> +void efx_fini_devlink_start(struct efx_nic *efx)
>> +{
>> + if (efx->devlink)
>> + devl_lock(efx->devlink);
>> +}
>> +
>> +void efx_fini_devlink(struct efx_nic *efx)
>> +{
>> + if (efx->devlink) {
>> + devl_unregister(efx->devlink);
>> + devl_unlock(efx->devlink);
>> + devlink_free(efx->devlink);
>> + efx->devlink = NULL;
>> + }
>> +}
>> +
>> +int efx_probe_devlink(struct efx_nic *efx)
>> +{
>> + struct efx_devlink *devlink_private;
>> +
>> + if (efx->type->is_vf)
>> + return 0;
>> +
>> + efx->devlink = devlink_alloc(&sfc_devlink_ops,
>> + sizeof(struct efx_devlink),
>> + &efx->pci_dev->dev);
>> + if (!efx->devlink)
>> + return -ENOMEM;
>> +
>> + devl_lock(efx->devlink);
>> + devlink_private = devlink_priv(efx->devlink);
>> + devlink_private->efx = efx;
>> +
>> + devl_register(efx->devlink);
>> +
>> + return 0;
>> +}
>> +
>> +void efx_probe_devlink_done(struct efx_nic *efx)
>> +{
>> + if (!efx->devlink)
>> + return;
>> +
>> + devl_unlock(efx->devlink);
>> +}
>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
>> new file mode 100644
>> index 000000000000..55d0d8aeca1e
>> --- /dev/null
>> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
>> @@ -0,0 +1,22 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/****************************************************************************
>> + * Driver for AMD network controllers and boards
>> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published
>> + * by the Free Software Foundation, incorporated herein by reference.
>> + */
>> +
>> +#ifndef _EFX_DEVLINK_H
>> +#define _EFX_DEVLINK_H
>> +
>> +#include "net_driver.h"
>> +#include <net/devlink.h>
>> +
>> +int efx_probe_devlink(struct efx_nic *efx);
>> +void efx_probe_devlink_done(struct efx_nic *efx);
>> +void efx_fini_devlink_start(struct efx_nic *efx);
>> +void efx_fini_devlink(struct efx_nic *efx);
> Odd naming... Just saying.
>

This is due to the recommended/required devlink lock/unlock during 
driver initialization/removal.

I think it is better to keep the lock/unlock inside the specific driver 
devlink code, and the functions naming reflects a time window when 
devlink related/dependent processing is being done.

I'm not against changing this, maybe adding the lock/unlock suffix would 
be preferable?:

int efx_probe_devlink_and_lock(struct efx_nic *efx);
void efx_probe_devlink_unlock(struct efx_nic *efx);
void efx_fini_devlink_lock(struct efx_nic *efx);
void efx_fini_devlink_and_unlock(struct efx_nic *efx);

>> +
>> +#endif /* _EFX_DEVLINK_H */
>> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
>> index 3b49e216768b..d036641dc043 100644
>> --- a/drivers/net/ethernet/sfc/net_driver.h
>> +++ b/drivers/net/ethernet/sfc/net_driver.h
>> @@ -994,6 +994,7 @@ enum efx_xdp_tx_queues_mode {
>> * xdp_rxq_info structures?
>> * @netdev_notifier: Netdevice notifier.
>> * @tc: state for TC offload (EF100).
>> + * @devlink: reference to devlink structure owned by this device
>> * @mem_bar: The BAR that is mapped into membase.
>> * @reg_base: Offset from the start of the bar to the function control window.
>> * @monitor_work: Hardware monitor workitem
>> @@ -1179,6 +1180,7 @@ struct efx_nic {
>> struct notifier_block netdev_notifier;
>> struct efx_tc_state *tc;
>>
>> + struct devlink *devlink;
>> unsigned int mem_bar;
>> u32 reg_base;
>>
>> -- 
>> 2.17.1
>>
Jiri Pirko Feb. 1, 2023, 9:07 a.m. UTC | #3
Wed, Feb 01, 2023 at 09:49:52AM CET, alejandro.lucero-palau@amd.com wrote:
>
>
>On 1/31/23 16:00, Jiri Pirko wrote:
>> Tue, Jan 31, 2023 at 03:58:15PM CET, alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com> wrote:
>>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com>>
>>>
>>> Basic devlink infrastructure support.
>>>
>>> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com <mailto:alejandro.lucero-palau@amd.com>>
>>> ---
>>> drivers/net/ethernet/sfc/Kconfig | 1 +
>>> drivers/net/ethernet/sfc/Makefile | 3 +-
>>> drivers/net/ethernet/sfc/ef100_netdev.c | 12 +++++
>>> drivers/net/ethernet/sfc/ef100_nic.c | 3 +-
>>> drivers/net/ethernet/sfc/efx_devlink.c | 71 +++++++++++++++++++++++++
>>> drivers/net/ethernet/sfc/efx_devlink.h | 22 ++++++++
>>> drivers/net/ethernet/sfc/net_driver.h | 2 +
>>> 7 files changed, 111 insertions(+), 3 deletions(-)
>>> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
>>> create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h
>>>
>>> diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
>>> index 0950e6b0508f..4af36ba8906b 100644
>>> --- a/drivers/net/ethernet/sfc/Kconfig
>>> +++ b/drivers/net/ethernet/sfc/Kconfig
>>> @@ -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.
>>> diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
>>> index 712a48d00069..55b9c73cd8ef 100644
>>> --- a/drivers/net/ethernet/sfc/Makefile
>>> +++ b/drivers/net/ethernet/sfc/Makefile
>>> @@ -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
>>> diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
>>> index ddcc325ed570..b10a226f4a07 100644
>>> --- a/drivers/net/ethernet/sfc/ef100_netdev.c
>>> +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
>>> @@ -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)
>>> {
>>> @@ -332,6 +333,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>>> efx_ef100_pci_sriov_disable(efx, true);
>>> #endif
>>>
>>> + /* devlink lock */
>>> + efx_fini_devlink_start(efx);
>>> ef100_unregister_netdev(efx);
>>>
>>> #ifdef CONFIG_SFC_SRIOV
>>> @@ -345,6 +348,9 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>>> kfree(efx->phy_data);
>>> efx->phy_data = NULL;
>>>
>>> + /* devlink unlock */
>>> + efx_fini_devlink(efx);
>>> +
>>> free_netdev(efx->net_dev);
>>> efx->net_dev = NULL;
>>> efx->state = STATE_PROBED;
>>> @@ -405,6 +411,10 @@ 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);
>>>
>>> + /* devlink creation, registration and lock */
>>> + if (efx_probe_devlink(efx))
>> Use variable to store the return value and check that in if.
>>
>
>I'll do.
>
>>> + pci_info(efx->pci_dev, "devlink registration failed");
>>> +
>>> rc = ef100_register_netdev(efx);
>>> if (rc)
>>> goto fail;
>>> @@ -424,5 +434,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>>> }
>>>
>>> fail:
>>> + /* devlink unlock */
>>> + efx_probe_devlink_done(efx);
>>> return rc;
>>> }
>>> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
>>> index ad686c671ab8..e4aacb4ec666 100644
>>> --- a/drivers/net/ethernet/sfc/ef100_nic.c
>>> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
>>> @@ -1120,11 +1120,10 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
>>> return rc;
>>>
>>> rc = efx_ef100_get_base_mport(efx);
>>> - if (rc) {
>>> + if (rc)
>>> netif_warn(efx, probe, net_dev,
>>> "Failed to probe base mport rc %d; representors will not function\n",
>>> rc);
>>> - }
>> I don't see how this hunk is related to this patch. Please remove.
>>
>>
>
>Running checkpatch on this specific patch triggered a warning about the 
>netif_warn requiring brackets.
>
>It is true it is not related to the patch itself, so I'll remove it.
>
>>> rc = efx_init_tc(efx);
>>> if (rc) {
>>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
>>> new file mode 100644
>>> index 000000000000..fab06aaa4b8a
>>> --- /dev/null
>>> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
>>> @@ -0,0 +1,71 @@
>>> +// SPDX-License-Identifier: GPL-2.0-only
>>> +/****************************************************************************
>>> + * Driver for AMD network controllers and boards
>>> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms of the GNU General Public License version 2 as published
>>> + * by the Free Software Foundation, incorporated herein by reference.
>>> + */
>>> +
>>> +#include <linux/rtc.h>
>>> +#include "net_driver.h"
>>> +#include "ef100_nic.h"
>>> +#include "efx_devlink.h"
>>> +#include "nic.h"
>>> +#include "mcdi.h"
>>> +#include "mcdi_functions.h"
>>> +#include "mcdi_pcol.h"
>>> +
>>> +struct efx_devlink {
>>> + struct efx_nic *efx;
>>> +};
>>> +
>>> +static const struct devlink_ops sfc_devlink_ops = {
>>> +};
>>> +
>>> +void efx_fini_devlink_start(struct efx_nic *efx)
>>> +{
>>> + if (efx->devlink)
>>> + devl_lock(efx->devlink);
>>> +}
>>> +
>>> +void efx_fini_devlink(struct efx_nic *efx)
>>> +{
>>> + if (efx->devlink) {
>>> + devl_unregister(efx->devlink);
>>> + devl_unlock(efx->devlink);
>>> + devlink_free(efx->devlink);
>>> + efx->devlink = NULL;
>>> + }
>>> +}
>>> +
>>> +int efx_probe_devlink(struct efx_nic *efx)
>>> +{
>>> + struct efx_devlink *devlink_private;
>>> +
>>> + if (efx->type->is_vf)
>>> + return 0;
>>> +
>>> + efx->devlink = devlink_alloc(&sfc_devlink_ops,
>>> + sizeof(struct efx_devlink),
>>> + &efx->pci_dev->dev);
>>> + if (!efx->devlink)
>>> + return -ENOMEM;
>>> +
>>> + devl_lock(efx->devlink);
>>> + devlink_private = devlink_priv(efx->devlink);
>>> + devlink_private->efx = efx;
>>> +
>>> + devl_register(efx->devlink);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +void efx_probe_devlink_done(struct efx_nic *efx)
>>> +{
>>> + if (!efx->devlink)
>>> + return;
>>> +
>>> + devl_unlock(efx->devlink);
>>> +}
>>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
>>> new file mode 100644
>>> index 000000000000..55d0d8aeca1e
>>> --- /dev/null
>>> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
>>> @@ -0,0 +1,22 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +/****************************************************************************
>>> + * Driver for AMD network controllers and boards
>>> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms of the GNU General Public License version 2 as published
>>> + * by the Free Software Foundation, incorporated herein by reference.
>>> + */
>>> +
>>> +#ifndef _EFX_DEVLINK_H
>>> +#define _EFX_DEVLINK_H
>>> +
>>> +#include "net_driver.h"
>>> +#include <net/devlink.h>
>>> +
>>> +int efx_probe_devlink(struct efx_nic *efx);
>>> +void efx_probe_devlink_done(struct efx_nic *efx);
>>> +void efx_fini_devlink_start(struct efx_nic *efx);
>>> +void efx_fini_devlink(struct efx_nic *efx);
>> Odd naming... Just saying.
>>
>
>This is due to the recommended/required devlink lock/unlock during 
>driver initialization/removal.
>
>I think it is better to keep the lock/unlock inside the specific driver 
>devlink code, and the functions naming reflects a time window when 
>devlink related/dependent processing is being done.
>
>I'm not against changing this, maybe adding the lock/unlock suffix would 
>be preferable?:
>
>int efx_probe_devlink_and_lock(struct efx_nic *efx);
>void efx_probe_devlink_unlock(struct efx_nic *efx);
>void efx_fini_devlink_lock(struct efx_nic *efx);
>void efx_fini_devlink_and_unlock(struct efx_nic *efx);

Sounds better. Thanks!

>
>>> +
>>> +#endif /* _EFX_DEVLINK_H */
>>> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
>>> index 3b49e216768b..d036641dc043 100644
>>> --- a/drivers/net/ethernet/sfc/net_driver.h
>>> +++ b/drivers/net/ethernet/sfc/net_driver.h
>>> @@ -994,6 +994,7 @@ enum efx_xdp_tx_queues_mode {
>>> * xdp_rxq_info structures?
>>> * @netdev_notifier: Netdevice notifier.
>>> * @tc: state for TC offload (EF100).
>>> + * @devlink: reference to devlink structure owned by this device
>>> * @mem_bar: The BAR that is mapped into membase.
>>> * @reg_base: Offset from the start of the bar to the function control window.
>>> * @monitor_work: Hardware monitor workitem
>>> @@ -1179,6 +1180,7 @@ struct efx_nic {
>>> struct notifier_block netdev_notifier;
>>> struct efx_tc_state *tc;
>>>
>>> + struct devlink *devlink;
>>> unsigned int mem_bar;
>>> u32 reg_base;
>>>
>>> -- 
>>> 2.17.1
>>>
>
>
>
Jakub Kicinski Feb. 1, 2023, 7:01 p.m. UTC | #4
On Wed, 1 Feb 2023 10:07:33 +0100 Jiri Pirko wrote:
> >This is due to the recommended/required devlink lock/unlock during 
> >driver initialization/removal.
> >
> >I think it is better to keep the lock/unlock inside the specific driver 
> >devlink code, and the functions naming reflects a time window when 
> >devlink related/dependent processing is being done.
> >
> >I'm not against changing this, maybe adding the lock/unlock suffix would 
> >be preferable?:
> >
> >int efx_probe_devlink_and_lock(struct efx_nic *efx);
> >void efx_probe_devlink_unlock(struct efx_nic *efx);
> >void efx_fini_devlink_lock(struct efx_nic *efx);
> >void efx_fini_devlink_and_unlock(struct efx_nic *efx);  
> 
> Sounds better. Thanks!

FWIW I'd just take the devl lock in the main driver code.
devlink should be viewed as a layer between bus and driver rather 
than as another subsystem the driver registers with. Otherwise reloads
and port creation get awkward.

But the above sounds okay, too.
Lucero Palau, Alejandro Feb. 2, 2023, 6:41 a.m. UTC | #5
On 2/1/23 19:01, Jakub Kicinski wrote:
> On Wed, 1 Feb 2023 10:07:33 +0100 Jiri Pirko wrote:
>>> This is due to the recommended/required devlink lock/unlock during
>>> driver initialization/removal.
>>>
>>> I think it is better to keep the lock/unlock inside the specific driver
>>> devlink code, and the functions naming reflects a time window when
>>> devlink related/dependent processing is being done.
>>>
>>> I'm not against changing this, maybe adding the lock/unlock suffix would
>>> be preferable?:
>>>
>>> int efx_probe_devlink_and_lock(struct efx_nic *efx);
>>> void efx_probe_devlink_unlock(struct efx_nic *efx);
>>> void efx_fini_devlink_lock(struct efx_nic *efx);
>>> void efx_fini_devlink_and_unlock(struct efx_nic *efx);
>> Sounds better. Thanks!
> FWIW I'd just take the devl lock in the main driver code.
> devlink should be viewed as a layer between bus and driver rather
> than as another subsystem the driver registers with. Otherwise reloads
> and port creation get awkward.
>
> But the above sounds okay, too.

That is what I have tried to do with these extra functions invoked from 
the main driver code.

The problem is one part of the protection needs to be done inside the 
driver's devlink code (if we want to avoid different calls for 
allocating then registering or unregistering then releasing), so it 
looked awkward to me the other protection part being directly in main 
driver code. So, I think the extra functions are worth for avoiding 
confusion.
Martin Habets Feb. 2, 2023, 9:24 a.m. UTC | #6
On Wed, Feb 01, 2023 at 11:01:48AM -0800, Jakub Kicinski wrote:
> On Wed, 1 Feb 2023 10:07:33 +0100 Jiri Pirko wrote:
> > >This is due to the recommended/required devlink lock/unlock during 
> > >driver initialization/removal.
> > >
> > >I think it is better to keep the lock/unlock inside the specific driver 
> > >devlink code, and the functions naming reflects a time window when 
> > >devlink related/dependent processing is being done.
> > >
> > >I'm not against changing this, maybe adding the lock/unlock suffix would 
> > >be preferable?:
> > >
> > >int efx_probe_devlink_and_lock(struct efx_nic *efx);
> > >void efx_probe_devlink_unlock(struct efx_nic *efx);
> > >void efx_fini_devlink_lock(struct efx_nic *efx);
> > >void efx_fini_devlink_and_unlock(struct efx_nic *efx);  
> > 
> > Sounds better. Thanks!
> 
> FWIW I'd just take the devl lock in the main driver code.
> devlink should be viewed as a layer between bus and driver rather 
> than as another subsystem the driver registers with. Otherwise reloads
> and port creation get awkward.

I see it a bit differently. For me devlink is another subsystem, it even is
an optional subsystem.
At the moment we don't support devlink port for VFs. If needed we'll add that
at some point, but likely only for newer NICs.
Do you think vDPA and RDMA devices will ever register with devlink?
At the moment I don't see devlink port ever applying to our older hardware,
like our sfn8000 or X2 cards. I do think devlink info and other commands
could apply more generally.

There definitely is a need to evolve to another layer between bus and
devices, and devlink can be used to administer that. But that does not
imply the reverse, that all devices register as devlink devices.
For security we would want to limit some operations (such as port creation)
to specific devlink instance(s). For example, normally we would not want a
tennant VM to flash new firmware that applies to the whole NIC.
I hope this makes sense.

Martin
Jakub Kicinski Feb. 2, 2023, 5:43 p.m. UTC | #7
On Thu, 2 Feb 2023 09:24:56 +0000 Martin Habets wrote:
> > FWIW I'd just take the devl lock in the main driver code.
> > devlink should be viewed as a layer between bus and driver rather 
> > than as another subsystem the driver registers with. Otherwise reloads
> > and port creation get awkward.  
> 
> I see it a bit differently. For me devlink is another subsystem, it even is
> an optional subsystem.
> At the moment we don't support devlink port for VFs. If needed we'll add that
> at some point, but likely only for newer NICs.

That's fine. I believe the structure I suggest is the easiest one 
to get right, but it's not a hard requirement.

> Do you think vDPA and RDMA devices will ever register with devlink?

Good question, I can't speak for the entire project but personally 
I have little interest in interfaces to proprietary world, 
so I hope not.

> At the moment I don't see devlink port ever applying to our older hardware,
> like our sfn8000 or X2 cards. I do think devlink info and other commands
> could apply more generally.
> 
> There definitely is a need to evolve to another layer between bus and
> devices, and devlink can be used to administer that. But that does not
> imply the reverse, that all devices register as devlink devices.
> For security we would want to limit some operations (such as port creation)
> to specific devlink instance(s). For example, normally we would not want a
> tennant VM to flash new firmware that applies to the whole NIC.
> I hope this makes sense.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 0950e6b0508f..4af36ba8906b 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -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.
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index 712a48d00069..55b9c73cd8ef 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -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
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index ddcc325ed570..b10a226f4a07 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -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)
 {
@@ -332,6 +333,8 @@  void ef100_remove_netdev(struct efx_probe_data *probe_data)
 		efx_ef100_pci_sriov_disable(efx, true);
 #endif
 
+	/* devlink lock */
+	efx_fini_devlink_start(efx);
 	ef100_unregister_netdev(efx);
 
 #ifdef CONFIG_SFC_SRIOV
@@ -345,6 +348,9 @@  void ef100_remove_netdev(struct efx_probe_data *probe_data)
 	kfree(efx->phy_data);
 	efx->phy_data = NULL;
 
+	/* devlink unlock */
+	efx_fini_devlink(efx);
+
 	free_netdev(efx->net_dev);
 	efx->net_dev = NULL;
 	efx->state = STATE_PROBED;
@@ -405,6 +411,10 @@  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);
 
+	/* devlink creation, registration and lock */
+	if (efx_probe_devlink(efx))
+		pci_info(efx->pci_dev, "devlink registration failed");
+
 	rc = ef100_register_netdev(efx);
 	if (rc)
 		goto fail;
@@ -424,5 +434,7 @@  int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	}
 
 fail:
+	/* devlink unlock */
+	efx_probe_devlink_done(efx);
 	return rc;
 }
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index ad686c671ab8..e4aacb4ec666 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1120,11 +1120,10 @@  int ef100_probe_netdev_pf(struct efx_nic *efx)
 		return rc;
 
 	rc = efx_ef100_get_base_mport(efx);
-	if (rc) {
+	if (rc)
 		netif_warn(efx, probe, net_dev,
 			   "Failed to probe base mport rc %d; representors will not function\n",
 			   rc);
-	}
 
 	rc = efx_init_tc(efx);
 	if (rc) {
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
new file mode 100644
index 000000000000..fab06aaa4b8a
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -0,0 +1,71 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/rtc.h>
+#include "net_driver.h"
+#include "ef100_nic.h"
+#include "efx_devlink.h"
+#include "nic.h"
+#include "mcdi.h"
+#include "mcdi_functions.h"
+#include "mcdi_pcol.h"
+
+struct efx_devlink {
+	struct efx_nic *efx;
+};
+
+static const struct devlink_ops sfc_devlink_ops = {
+};
+
+void efx_fini_devlink_start(struct efx_nic *efx)
+{
+	if (efx->devlink)
+		devl_lock(efx->devlink);
+}
+
+void efx_fini_devlink(struct efx_nic *efx)
+{
+	if (efx->devlink) {
+		devl_unregister(efx->devlink);
+		devl_unlock(efx->devlink);
+		devlink_free(efx->devlink);
+		efx->devlink = NULL;
+	}
+}
+
+int efx_probe_devlink(struct efx_nic *efx)
+{
+	struct efx_devlink *devlink_private;
+
+	if (efx->type->is_vf)
+		return 0;
+
+	efx->devlink = devlink_alloc(&sfc_devlink_ops,
+				     sizeof(struct efx_devlink),
+				     &efx->pci_dev->dev);
+	if (!efx->devlink)
+		return -ENOMEM;
+
+	devl_lock(efx->devlink);
+	devlink_private = devlink_priv(efx->devlink);
+	devlink_private->efx = efx;
+
+	devl_register(efx->devlink);
+
+	return 0;
+}
+
+void efx_probe_devlink_done(struct efx_nic *efx)
+{
+	if (!efx->devlink)
+		return;
+
+	devl_unlock(efx->devlink);
+}
diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
new file mode 100644
index 000000000000..55d0d8aeca1e
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_devlink.h
@@ -0,0 +1,22 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef _EFX_DEVLINK_H
+#define _EFX_DEVLINK_H
+
+#include "net_driver.h"
+#include <net/devlink.h>
+
+int efx_probe_devlink(struct efx_nic *efx);
+void efx_probe_devlink_done(struct efx_nic *efx);
+void efx_fini_devlink_start(struct efx_nic *efx);
+void efx_fini_devlink(struct efx_nic *efx);
+
+#endif	/* _EFX_DEVLINK_H */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 3b49e216768b..d036641dc043 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -994,6 +994,7 @@  enum efx_xdp_tx_queues_mode {
  *      xdp_rxq_info structures?
  * @netdev_notifier: Netdevice notifier.
  * @tc: state for TC offload (EF100).
+ * @devlink: reference to devlink structure owned by this device
  * @mem_bar: The BAR that is mapped into membase.
  * @reg_base: Offset from the start of the bar to the function control window.
  * @monitor_work: Hardware monitor workitem
@@ -1179,6 +1180,7 @@  struct efx_nic {
 	struct notifier_block netdev_notifier;
 	struct efx_tc_state *tc;
 
+	struct devlink *devlink;
 	unsigned int mem_bar;
 	u32 reg_base;