mirror of
https://github.com/fpganinja/taxi.git
synced 2026-01-18 01:30:36 -08:00
cndm: Add support for devlink
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -5,6 +5,7 @@ ifneq ($(KERNELRELEASE),)
|
|||||||
|
|
||||||
obj-m += cndm.o
|
obj-m += cndm.o
|
||||||
cndm-y += cndm_main.o
|
cndm-y += cndm_main.o
|
||||||
|
cndm-y += cndm_devlink.o
|
||||||
cndm-y += cndm_netdev.o
|
cndm-y += cndm_netdev.o
|
||||||
cndm-y += cndm_tx.o
|
cndm-y += cndm_tx.o
|
||||||
cndm-y += cndm_rx.o
|
cndm-y += cndm_rx.o
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Authors:
|
|||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/ptp_clock_kernel.h>
|
#include <linux/ptp_clock_kernel.h>
|
||||||
|
#include <net/devlink.h>
|
||||||
|
|
||||||
#define DRIVER_NAME "cndm"
|
#define DRIVER_NAME "cndm"
|
||||||
#define DRIVER_VERSION "0.1"
|
#define DRIVER_VERSION "0.1"
|
||||||
@@ -122,14 +123,21 @@ struct cndm_cpl {
|
|||||||
__u8 phase;
|
__u8 phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// cndm_devlink.c
|
||||||
|
struct devlink *cndm_devlink_alloc(struct device *dev);
|
||||||
|
void cndm_devlink_free(struct devlink *devlink);
|
||||||
|
|
||||||
|
// cndm_netdev.c
|
||||||
irqreturn_t cndm_irq(int irqn, void *data);
|
irqreturn_t cndm_irq(int irqn, void *data);
|
||||||
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __iomem *hw_addr);
|
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __iomem *hw_addr);
|
||||||
void cndm_destroy_netdev(struct net_device *ndev);
|
void cndm_destroy_netdev(struct net_device *ndev);
|
||||||
|
|
||||||
|
// cndm_tx.c
|
||||||
int cndm_free_tx_buf(struct cndm_priv *priv);
|
int cndm_free_tx_buf(struct cndm_priv *priv);
|
||||||
int cndm_poll_tx_cq(struct napi_struct *napi, int budget);
|
int cndm_poll_tx_cq(struct napi_struct *napi, int budget);
|
||||||
int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev);
|
int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev);
|
||||||
|
|
||||||
|
// cndm_rx.c
|
||||||
int cndm_free_rx_buf(struct cndm_priv *priv);
|
int cndm_free_rx_buf(struct cndm_priv *priv);
|
||||||
int cndm_refill_rx_buffers(struct cndm_priv *priv);
|
int cndm_refill_rx_buffers(struct cndm_priv *priv);
|
||||||
int cndm_poll_rx_cq(struct napi_struct *napi, int budget);
|
int cndm_poll_rx_cq(struct napi_struct *napi, int budget);
|
||||||
|
|||||||
76
src/cndm/modules/cndm/cndm_devlink.c
Normal file
76
src/cndm/modules/cndm/cndm_devlink.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// SPDX-License-Identifier: GPL
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2025 FPGA Ninja, LLC
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
- Alex Forencich
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cndm.h"
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
static int cndm_devlink_info_get(struct devlink *devlink,
|
||||||
|
struct devlink_info_req *req, struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct cndm_dev *cdev = devlink_priv(devlink);
|
||||||
|
char str[32];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0)
|
||||||
|
ret = devlink_info_driver_name_put(req, KBUILD_MODNAME);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%08x", 0); // TODO
|
||||||
|
|
||||||
|
ret = devlink_info_version_fixed_put(req, "fpga.id", str);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%08x", 0); // TODO
|
||||||
|
|
||||||
|
ret = devlink_info_version_fixed_put(req, DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, str);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%08x", 0); // TODO
|
||||||
|
|
||||||
|
ret = devlink_info_version_fixed_put(req, DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, str);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%08x", 0); // TODO
|
||||||
|
|
||||||
|
ret = devlink_info_version_running_put(req, "fw.id", str);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%08x", 0); // TODO
|
||||||
|
|
||||||
|
ret = devlink_info_version_running_put(req, DEVLINK_INFO_VERSION_GENERIC_FW, str);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct devlink_ops cndm_devlink_ops = {
|
||||||
|
.info_get = cndm_devlink_info_get,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct devlink *cndm_devlink_alloc(struct device *dev)
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||||
|
return devlink_alloc(&cndm_devlink_ops, sizeof(struct cndm_dev), dev);
|
||||||
|
#else
|
||||||
|
return devlink_alloc(&cndm_devlink_ops, sizeof(struct cndm_dev));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cndm_devlink_free(struct devlink *devlink) {
|
||||||
|
devlink_free(devlink);
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ Authors:
|
|||||||
#include "cndm.h"
|
#include "cndm.h"
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Corundum device driver");
|
MODULE_DESCRIPTION("Corundum device driver");
|
||||||
MODULE_AUTHOR("FPGA Ninja");
|
MODULE_AUTHOR("FPGA Ninja");
|
||||||
@@ -20,6 +21,7 @@ MODULE_VERSION(DRIVER_VERSION);
|
|||||||
static int cndm_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
static int cndm_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
struct devlink *devlink;
|
||||||
struct cndm_dev *cdev;
|
struct cndm_dev *cdev;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int k;
|
int k;
|
||||||
@@ -32,10 +34,11 @@ static int cndm_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
|
|
||||||
pcie_print_link_status(pdev);
|
pcie_print_link_status(pdev);
|
||||||
|
|
||||||
cdev = devm_kzalloc(dev, sizeof(struct cndm_dev), GFP_KERNEL);
|
devlink = cndm_devlink_alloc(dev);
|
||||||
if (!cdev)
|
if (!devlink)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cdev = devlink_priv(devlink);
|
||||||
cdev->pdev = pdev;
|
cdev->pdev = pdev;
|
||||||
cdev->dev = dev;
|
cdev->dev = dev;
|
||||||
pci_set_drvdata(pdev, cdev);
|
pci_set_drvdata(pdev, cdev);
|
||||||
@@ -76,6 +79,12 @@ static int cndm_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
goto fail_map_bars;
|
goto fail_map_bars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||||
|
devlink_register(devlink);
|
||||||
|
#else
|
||||||
|
devlink_register(devlink, dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
cdev->port_count = ioread32(cdev->bar + 0x0100);
|
cdev->port_count = ioread32(cdev->bar + 0x0100);
|
||||||
cdev->port_offset = ioread32(cdev->bar + 0x0104);
|
cdev->port_offset = ioread32(cdev->bar + 0x0104);
|
||||||
cdev->port_stride = ioread32(cdev->bar + 0x0108);
|
cdev->port_stride = ioread32(cdev->bar + 0x0108);
|
||||||
@@ -113,6 +122,7 @@ fail_netdev:
|
|||||||
cdev->ndev[k] = NULL;
|
cdev->ndev[k] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
devlink_unregister(devlink);
|
||||||
pci_free_irq_vectors(pdev);
|
pci_free_irq_vectors(pdev);
|
||||||
fail_map_bars:
|
fail_map_bars:
|
||||||
if (cdev->bar)
|
if (cdev->bar)
|
||||||
@@ -122,6 +132,7 @@ fail_regions:
|
|||||||
pci_clear_master(pdev);
|
pci_clear_master(pdev);
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
fail_enable_device:
|
fail_enable_device:
|
||||||
|
cndm_devlink_free(devlink);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +140,7 @@ static void cndm_pci_remove(struct pci_dev *pdev)
|
|||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct cndm_dev *cdev = pci_get_drvdata(pdev);
|
struct cndm_dev *cdev = pci_get_drvdata(pdev);
|
||||||
|
struct devlink *devlink = priv_to_devlink(cdev);
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
dev_info(dev, DRIVER_NAME " PCI remove");
|
dev_info(dev, DRIVER_NAME " PCI remove");
|
||||||
@@ -140,12 +152,14 @@ static void cndm_pci_remove(struct pci_dev *pdev)
|
|||||||
cdev->ndev[k] = NULL;
|
cdev->ndev[k] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
devlink_unregister(devlink);
|
||||||
pci_free_irq_vectors(pdev);
|
pci_free_irq_vectors(pdev);
|
||||||
if (cdev->bar)
|
if (cdev->bar)
|
||||||
pci_iounmap(pdev, cdev->bar);
|
pci_iounmap(pdev, cdev->bar);
|
||||||
pci_release_regions(pdev);
|
pci_release_regions(pdev);
|
||||||
pci_clear_master(pdev);
|
pci_clear_master(pdev);
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
|
cndm_devlink_free(devlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pci_device_id cndm_pci_id_table[] = {
|
static const struct pci_device_id cndm_pci_id_table[] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user