@@ -4,5 +4,5 @@
# Makefile for the Yunsilicon device drivers.
#
-# obj-$(CONFIG_YUNSILICON_XSC_ETH) += xsc/net/
+obj-$(CONFIG_YUNSILICON_XSC_ETH) += xsc/net/
obj-$(CONFIG_YUNSILICON_XSC_PCI) += xsc/pci/
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/auxiliary_bus.h>
+#include "common/xsc_core.h"
+#include "xsc_eth_common.h"
+#include "xsc_eth.h"
+
+static int xsc_get_max_num_channels(struct xsc_core_device *xdev)
+{
+ return min_t(int, xdev->dev_res->eq_table.num_comp_vectors,
+ XSC_ETH_MAX_NUM_CHANNELS);
+}
+
+static int xsc_eth_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *adev_id)
+{
+ struct xsc_adev *xsc_adev = container_of(adev, struct xsc_adev, adev);
+ struct xsc_core_device *xdev = xsc_adev->xdev;
+ struct xsc_adapter *adapter;
+ struct net_device *netdev;
+ int num_chl, num_tc;
+ int err;
+
+ num_chl = xsc_get_max_num_channels(xdev);
+ num_tc = xdev->caps.max_tc;
+
+ netdev = alloc_etherdev_mqs(sizeof(struct xsc_adapter),
+ num_chl * num_tc, num_chl);
+ if (!netdev) {
+ pr_err("alloc_etherdev_mqs failed, txq=%d, rxq=%d\n",
+ (num_chl * num_tc), num_chl);
+ return -ENOMEM;
+ }
+
+ netdev->dev.parent = &xdev->pdev->dev;
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pdev = xdev->pdev;
+ adapter->dev = &adapter->pdev->dev;
+ adapter->xdev = xdev;
+ xdev->eth_priv = adapter;
+
+ err = register_netdev(netdev);
+ if (err) {
+ netdev_err(netdev, "register_netdev failed, err=%d\n", err);
+ goto err_free_netdev;
+ }
+
+ return 0;
+
+err_free_netdev:
+ free_netdev(netdev);
+
+ return err;
+}
+
+static void xsc_eth_remove(struct auxiliary_device *adev)
+{
+ struct xsc_adev *xsc_adev = container_of(adev, struct xsc_adev, adev);
+ struct xsc_core_device *xdev = xsc_adev->xdev;
+ struct xsc_adapter *adapter;
+
+ if (!xdev)
+ return;
+
+ adapter = xdev->eth_priv;
+ if (!adapter) {
+ netdev_err(adapter->netdev, "failed! adapter is null\n");
+ return;
+ }
+
+ unregister_netdev(adapter->netdev);
+
+ free_netdev(adapter->netdev);
+
+ xdev->eth_priv = NULL;
+}
+
+static const struct auxiliary_device_id xsc_eth_id_table[] = {
+ { .name = XSC_PCI_DRV_NAME "." XSC_ETH_ADEV_NAME },
+ {},
+};
+MODULE_DEVICE_TABLE(auxiliary, xsc_eth_id_table);
+
+static struct auxiliary_driver xsc_eth_driver = {
+ .name = "eth",
+ .probe = xsc_eth_probe,
+ .remove = xsc_eth_remove,
+ .id_table = xsc_eth_id_table,
+};
+module_auxiliary_driver(xsc_eth_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Yunsilicon XSC ethernet driver");
new file mode 100644
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#ifndef __XSC_ETH_H
+#define __XSC_ETH_H
+
+struct xsc_adapter {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct device *dev;
+ struct xsc_core_device *xdev;
+};
+
+#endif /* __XSC_ETH_H */
new file mode 100644
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#ifndef __XSC_ETH_COMMON_H
+#define __XSC_ETH_COMMON_H
+
+#define XSC_LOG_INDIR_RQT_SIZE 0x8
+
+#define XSC_INDIR_RQT_SIZE BIT(XSC_LOG_INDIR_RQT_SIZE)
+#define XSC_ETH_MIN_NUM_CHANNELS 2
+#define XSC_ETH_MAX_NUM_CHANNELS XSC_INDIR_RQT_SIZE
+
+#endif