@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/auxiliary_bus.h>
#include "common/xsc_cmdq.h"
#define XSC_PCI_VENDOR_ID 0x1f67
@@ -228,6 +229,15 @@ struct xsc_irq_info {
char name[XSC_MAX_IRQ_NAME];
};
+// adev
+#define XSC_PCI_DRV_NAME "xsc_pci"
+#define XSC_ETH_ADEV_NAME "eth"
+
+struct xsc_adev {
+ struct auxiliary_device adev;
+ struct xsc_core_device *xdev;
+};
+
// hw
struct xsc_reg_addr {
u64 tx_db;
@@ -374,6 +384,8 @@ enum xsc_interface_state {
struct xsc_core_device {
struct pci_dev *pdev;
struct device *device;
+ int adev_id;
+ struct xsc_adev **xsc_adev_list;
void *eth_priv;
struct xsc_dev_resource *dev_res;
int numa_node;
@@ -6,4 +6,5 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/yunsilicon/xsc
obj-$(CONFIG_YUNSILICON_XSC_PCI) += xsc_pci.o
-xsc_pci-y := main.o cmdq.o hw.o qp.o cq.o alloc.o eq.o pci_irq.o
+xsc_pci-y := main.o cmdq.o hw.o qp.o cq.o alloc.o eq.o pci_irq.o adev.o
+
new file mode 100644
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/idr.h>
+#include "adev.h"
+
+static DEFINE_IDA(xsc_adev_ida);
+
+enum xsc_adev_idx {
+ XSC_ADEV_IDX_ETH,
+ XSC_ADEV_IDX_MAX
+};
+
+static const char * const xsc_adev_name[] = {
+ [XSC_ADEV_IDX_ETH] = XSC_ETH_ADEV_NAME,
+};
+
+static void xsc_release_adev(struct device *dev)
+{
+ /* Doing nothing, but auxiliary bus requires a release function */
+}
+
+static int xsc_reg_adev(struct xsc_core_device *xdev, int idx)
+{
+ struct auxiliary_device *adev;
+ struct xsc_adev *xsc_adev;
+ int ret;
+
+ xsc_adev = kzalloc(sizeof(*xsc_adev), GFP_KERNEL);
+ if (!xsc_adev)
+ return -ENOMEM;
+
+ adev = &xsc_adev->adev;
+ adev->name = xsc_adev_name[idx];
+ adev->id = xdev->adev_id;
+ adev->dev.parent = &xdev->pdev->dev;
+ adev->dev.release = xsc_release_adev;
+ xsc_adev->xdev = xdev;
+
+ ret = auxiliary_device_init(adev);
+ if (ret)
+ goto err_free_adev;
+
+ ret = auxiliary_device_add(adev);
+ if (ret)
+ goto err_uninit_adev;
+
+ xdev->xsc_adev_list[idx] = xsc_adev;
+
+ return 0;
+err_uninit_adev:
+ auxiliary_device_uninit(adev);
+err_free_adev:
+ kfree(xsc_adev);
+
+ return ret;
+}
+
+static void xsc_unreg_adev(struct xsc_core_device *xdev, int idx)
+{
+ struct xsc_adev *xsc_adev = xdev->xsc_adev_list[idx];
+ struct auxiliary_device *adev = &xsc_adev->adev;
+
+ auxiliary_device_delete(adev);
+ auxiliary_device_uninit(adev);
+
+ kfree(xsc_adev);
+ xdev->xsc_adev_list[idx] = NULL;
+}
+
+int xsc_adev_init(struct xsc_core_device *xdev)
+{
+ struct xsc_adev **xsc_adev_list;
+ int adev_id;
+ int ret;
+
+ xsc_adev_list = kzalloc(sizeof(void *) * XSC_ADEV_IDX_MAX, GFP_KERNEL);
+ if (!xsc_adev_list)
+ return -ENOMEM;
+ xdev->xsc_adev_list = xsc_adev_list;
+
+ adev_id = ida_alloc(&xsc_adev_ida, GFP_KERNEL);
+ if (adev_id < 0)
+ goto err_free_adev_list;
+ xdev->adev_id = adev_id;
+
+ ret = xsc_reg_adev(xdev, XSC_ADEV_IDX_ETH);
+ if (ret)
+ goto err_dalloc_adev_id;
+
+ return 0;
+err_dalloc_adev_id:
+ ida_free(&xsc_adev_ida, xdev->adev_id);
+err_free_adev_list:
+ kfree(xsc_adev_list);
+
+ return ret;
+}
+
+void xsc_adev_uninit(struct xsc_core_device *xdev)
+{
+ xsc_unreg_adev(xdev, XSC_ADEV_IDX_ETH);
+ ida_free(&xsc_adev_ida, xdev->adev_id);
+ kfree(xdev->xsc_adev_list);
+}
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#ifndef __ADEV_H
+#define __ADEV_H
+
+#include "common/xsc_core.h"
+
+int xsc_adev_init(struct xsc_core_device *xdev);
+void xsc_adev_uninit(struct xsc_core_device *xdev);
+
+#endif
@@ -10,6 +10,7 @@
#include "cq.h"
#include "eq.h"
#include "pci_irq.h"
+#include "adev.h"
static const struct pci_device_id xsc_pci_id_table[] = {
{ PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_MC_PF_DEV_ID) },
@@ -255,10 +256,18 @@ static int xsc_load(struct xsc_core_device *xdev)
goto err_hw_cleanup;
}
+ err = xsc_adev_init(xdev);
+ if (err) {
+ pci_err(xdev->pdev, "xsc_adev_init failed %d\n", err);
+ goto err_irq_eq_destroy;
+ }
+
set_bit(XSC_INTERFACE_STATE_UP, &xdev->intf_state);
mutex_unlock(&xdev->intf_state_mutex);
return 0;
+err_irq_eq_destroy:
+ xsc_irq_eq_destroy(xdev);
err_hw_cleanup:
xsc_hw_cleanup(xdev);
out:
@@ -268,6 +277,7 @@ static int xsc_load(struct xsc_core_device *xdev)
static int xsc_unload(struct xsc_core_device *xdev)
{
+ xsc_adev_uninit(xdev);
mutex_lock(&xdev->intf_state_mutex);
if (!test_bit(XSC_INTERFACE_STATE_UP, &xdev->intf_state)) {
xsc_hw_cleanup(xdev);