Commit 15115b1a authored by David Arinzon's avatar David Arinzon Committed by Jakub Kicinski
Browse files

net: ena: Add device reload capability through devlink



Adding basic devlink capability support of reloading the driver.
This capability is required to support driver init type
devlink params (DEVLINK_PARAM_CMODE_DRIVERINIT). Such params
require reloading of the driver (destroy/restore sequence).
The reloading is done by the devlink framework using the
hooks provided by the driver.

Signed-off-by: default avatarDavid Arinzon <darinzon@amazon.com>
Link: https://patch.msgid.link/20250617110545.5659-4-darinzon@amazon.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 51d58804
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ ena_ethtool.c ethtool callbacks.
ena_xdp.[ch]        XDP files
ena_pci_id_tbl.h    Supported device IDs.
ena_phc.[ch]        PTP hardware clock infrastructure (see `PHC`_ for more info)
ena_devlink.[ch]    devlink files.
=================   ======================================================

Management Interface:
@@ -269,6 +270,18 @@ RSS
- The user can provide a hash key, hash function, and configure the
  indirection table through `ethtool(8)`.

DEVLINK SUPPORT
===============
.. _`devlink`: https://www.kernel.org/doc/html/latest/networking/devlink/index.html

`devlink`_ supports reloading the driver and initiating re-negotiation with the ENA device

.. code-block:: shell

  sudo devlink dev reload pci/<domain:bus:slot.function>
  # for example:
  sudo devlink dev reload pci/0000:00:06.0

DATA PATH
=========

+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ config ENA_ETHERNET
	depends on PCI_MSI && !CPU_BIG_ENDIAN
	depends on PTP_1588_CLOCK_OPTIONAL
	select DIMLIB
	select NET_DEVLINK
	help
	  This driver supports Elastic Network Adapter (ENA)"

+1 −1
Original line number Diff line number Diff line
@@ -5,4 +5,4 @@

obj-$(CONFIG_ENA_ETHERNET) += ena.o

ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o ena_phc.o
ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o ena_phc.o ena_devlink.o
+94 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) Amazon.com, Inc. or its affiliates.
 * All rights reserved.
 */

#include "linux/pci.h"
#include "ena_devlink.h"

static int ena_devlink_reload_down(struct devlink *devlink,
				   bool netns_change,
				   enum devlink_reload_action action,
				   enum devlink_reload_limit limit,
				   struct netlink_ext_ack *extack)
{
	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);

	if (netns_change) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Namespace change is not supported");
		return -EOPNOTSUPP;
	}

	rtnl_lock();
	ena_destroy_device(adapter, false);
	rtnl_unlock();

	return 0;
}

static int ena_devlink_reload_up(struct devlink *devlink,
				 enum devlink_reload_action action,
				 enum devlink_reload_limit limit,
				 u32 *actions_performed,
				 struct netlink_ext_ack *extack)
{
	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
	int err = 0;

	rtnl_lock();
	/* Check that no other routine initialized the device (e.g.
	 * ena_fw_reset_device()). Also we're under devlink_mutex here,
	 * so devlink isn't freed under our feet.
	 */
	if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
		err = ena_restore_device(adapter);

	rtnl_unlock();

	if (!err)
		*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);

	return err;
}

static const struct devlink_ops ena_devlink_ops = {
	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
	.reload_down	= ena_devlink_reload_down,
	.reload_up	= ena_devlink_reload_up,
};

struct devlink *ena_devlink_alloc(struct ena_adapter *adapter)
{
	struct device *dev = &adapter->pdev->dev;
	struct devlink *devlink;

	devlink = devlink_alloc(&ena_devlink_ops,
				sizeof(struct ena_adapter *),
				dev);
	if (!devlink) {
		netdev_err(adapter->netdev,
			   "Failed to allocate devlink struct\n");
		return NULL;
	}

	ENA_DEVLINK_PRIV(devlink) = adapter;
	adapter->devlink = devlink;

	return devlink;
}

void ena_devlink_free(struct devlink *devlink)
{
	devlink_free(devlink);
}

void ena_devlink_register(struct devlink *devlink, struct device *dev)
{
	devlink_register(devlink);
}

void ena_devlink_unregister(struct devlink *devlink)
{
	devlink_unregister(devlink);
}
+19 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) Amazon.com, Inc. or its affiliates.
 * All rights reserved.
 */
#ifndef DEVLINK_H
#define DEVLINK_H

#include "ena_netdev.h"
#include <net/devlink.h>

#define ENA_DEVLINK_PRIV(devlink) \
	(*(struct ena_adapter **)devlink_priv(devlink))

struct devlink *ena_devlink_alloc(struct ena_adapter *adapter);
void ena_devlink_free(struct devlink *devlink);
void ena_devlink_register(struct devlink *devlink, struct device *dev);
void ena_devlink_unregister(struct devlink *devlink);

#endif /* DEVLINK_H */
Loading