[PATCH net-next 13/27] can: kvaser_pciefd: Add devlink support
From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: 2025-07-25 16:13:39
Also in:
linux-can
Subsystem:
can network drivers, the rest · Maintainers:
Marc Kleine-Budde, Vincent Mailhol, Linus Torvalds
From: Jimmy Assarsson <redacted>
Add devlink support at device level.
Example output:
$ devlink dev
pci/0000:07:00.0
pci/0000:08:00.0
pci/0000:09:00.0
$ devlink dev info
pci/0000:07:00.0:
driver kvaser_pciefd
pci/0000:08:00.0:
driver kvaser_pciefd
pci/0000:09:00.0:
driver kvaser_pciefd
Reviewed-by: Vincent Mailhol <redacted>
Signed-off-by: Jimmy Assarsson <redacted>
Link: https://patch.msgid.link/20250725123230.8-8-extja@kvaser.com
[mkl: kvaser_pciefd_remove(): fix use-after-free]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/Kconfig | 1 +
drivers/net/can/kvaser_pciefd/Makefile | 2 +-
drivers/net/can/kvaser_pciefd/kvaser_pciefd.h | 2 ++
.../net/can/kvaser_pciefd/kvaser_pciefd_core.c | 15 ++++++++++++---
.../net/can/kvaser_pciefd/kvaser_pciefd_devlink.c | 11 +++++++++++
5 files changed, 27 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/can/kvaser_pciefd/kvaser_pciefd_devlink.c
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index d58fab0161b3..d43d56694667 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig@@ -154,6 +154,7 @@ config CAN_JANZ_ICAN3 config CAN_KVASER_PCIEFD depends on PCI tristate "Kvaser PCIe FD cards" + select NET_DEVLINK help This is a driver for the Kvaser PCI Express CAN FD family.
diff --git a/drivers/net/can/kvaser_pciefd/Makefile b/drivers/net/can/kvaser_pciefd/Makefile
index ea1bf1000760..8c5b8cdc6b5f 100644
--- a/drivers/net/can/kvaser_pciefd/Makefile
+++ b/drivers/net/can/kvaser_pciefd/Makefile@@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CAN_KVASER_PCIEFD) += kvaser_pciefd.o -kvaser_pciefd-y = kvaser_pciefd_core.o +kvaser_pciefd-y = kvaser_pciefd_core.o kvaser_pciefd_devlink.o
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd.h b/drivers/net/can/kvaser_pciefd/kvaser_pciefd.h
index 55bb7e078340..34ba393d6093 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd.h
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd.h@@ -13,6 +13,7 @@ #include <linux/spinlock.h> #include <linux/timer.h> #include <linux/types.h> +#include <net/devlink.h> #define KVASER_PCIEFD_MAX_CAN_CHANNELS 8UL #define KVASER_PCIEFD_DMA_COUNT 2U
@@ -87,4 +88,5 @@ struct kvaser_pciefd { struct kvaser_pciefd_fw_version fw_version; }; +extern const struct devlink_ops kvaser_pciefd_devlink_ops; #endif /* _KVASER_PCIEFD_H */
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
index 97cbe07c4ee3..86509a2d2b90 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c@@ -1751,14 +1751,16 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret; + struct devlink *devlink; struct device *dev = &pdev->dev; struct kvaser_pciefd *pcie; const struct kvaser_pciefd_irq_mask *irq_mask; - pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); - if (!pcie) + devlink = devlink_alloc(&kvaser_pciefd_devlink_ops, sizeof(*pcie), dev); + if (!devlink) return -ENOMEM; + pcie = devlink_priv(devlink); pci_set_drvdata(pdev, pcie); pcie->pci = pdev; pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data;
@@ -1766,7 +1768,7 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) - return ret; + goto err_free_devlink; ret = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME); if (ret)
@@ -1830,6 +1832,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, if (ret) goto err_free_irq; + devlink_register(devlink); + return 0; err_free_irq:
@@ -1853,6 +1857,9 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, err_disable_pci: pci_disable_device(pdev); +err_free_devlink: + devlink_free(devlink); + return ret; }
@@ -1876,9 +1883,11 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev) for (i = 0; i < pcie->nr_channels; ++i) free_candev(pcie->can[i]->can.dev); + devlink_unregister(priv_to_devlink(pcie)); pci_iounmap(pdev, pcie->reg_base); pci_release_regions(pdev); pci_disable_device(pdev); + devlink_free(priv_to_devlink(pcie)); } static struct pci_driver kvaser_pciefd = {
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_devlink.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_devlink.c
new file mode 100644
index 000000000000..7c2040ed53d7
--- /dev/null
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_devlink.c@@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* kvaser_pciefd devlink functions + * + * Copyright (C) 2025 KVASER AB, Sweden. All rights reserved. + */ +#include "kvaser_pciefd.h" + +#include <net/devlink.h> + +const struct devlink_ops kvaser_pciefd_devlink_ops = { +};
--
2.47.2