From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FB1E2BE04E; Mon, 21 Jul 2025 11:34:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.59.177.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097654; cv=none; b=RpKa/UAuaNO+ZohveHMgmBnCsigFUTmryfqORJ68sfkRXTORNz6+dOpAUKzJgwjmnEOhNCPadKU9ipiKMAQdtKVCvCuIyQP6g07x/9hzRBKA3O555VHVkyDcYRuBAvSab7X166nJgFoTMdpbWckPiaj5PvxBIA/SYM4hhbqxjoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097654; c=relaxed/simple; bh=uZSfa6ZarJJVp4ixplN5Zas5ypjBwkWGTv6U/H50zdk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QF9Bh7aYrusr6wrZCdjd4PuSXSiwyuCK9sboeyFNlGQpPvdglXVNg1KBhA6N8jOdcIG3/eF1XLFAv1UZxI5aVtz80Oiii7ZFulw+iNMgGm7JXQFN2gIOclnCoSoo0PSXEo+KEc9srVX4nesgUGiq/0X1LyQm3Y95R9DKujpR/1o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=52.59.177.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097571tb79f57e9 X-QQ-Originating-IP: grWXWpapzJS8mvDKGaDnulyivtQXCKqW/oj5lG8HJiM= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:32:48 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 16218708113185260639 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 01/15] net: rnpgbe: Add build support for rnpgbe Date: Mon, 21 Jul 2025 19:32:24 +0800 Message-Id: <20250721113238.18615-2-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MDo0YgvfYJuRcH5lBAUhM0aDn8aWsDPigcZe9lRzSCrNrfam2kHUlJS+ 1c4F2wlhOcmd/N9GpMwanltCucDtCwOohdlXc3MvEkT8NAYoTOhH8YiMRKaxfN7ZyHhiXa/ T3vkqgXk/JEWxk7g44BzmMA1gZE/V633DVdZTd67tLZQAyqjwQRZyZeuk9sKh04xuarNbBF 65SuWF62qS6mX9hJLJw8GejjQ4KnjwG4CDP0XWec0Ru1G5pBRXnrgx+/z5BskHnEJI86vMl IoEBxOh6CVJpmYB0xxfDV1h6+Dw026+Pv9nnK32Ic1sEjdiqMs1LTNmMC2yjaHUUCbG3z9V T5JHyGtScHWOodhwthc6OT4EPDEkW1xMV8bR1z46yhYpWjLIBbr6uGXQmNRpMAJCOvBokMX GPLPdSCj94ckq34uXVVRZacsJBnyKVsoQR6RGVnl4yWZI4XwIWr+ecCVyNjNlK8b+ro3QS9 6SCIBmbLvH3eUinqgkxeMkm4p+DoVZ1HPzFp5D7nlb/KfW7Svj9mXHyt5ORwAylZ0UU9f5J CmGn5gYg0k/3Oy6VQKXD9+RYS911xADaHsr2JRS1WOFVg2q1mbbW7cua1M/pdJgYeODBuLT 400WirpShy2xJAn8tYqoHCCvLnbsDWmVCuL6JVpCUVNcFWvQYpOLPuI3aCXivu/+7LHB9T/ dwvxm0CAA8Eltk2fiHfItIsk+KvilLX0OWbnj2XQT2aXbxCxX1fK7nTPcavnKiimO0jRXna wfwipVxqdFC8glzeCY4FT+ltJbOlVgn+0ooeSnRzVUM9G1UHzLxXUD0/j07Sy9SEs1p1R76 cSj2So2R64MmeEo8RCTxe+e8i3ZG3lF77YUvRiCK1IoDI5kgvJ2h3g89rXBZjXxE/31JyxK ooXkkkbUaaYqmsweUMFMSVzRDeab3vwUDIqen56q2VIS+IGH1jA56f0djElY8dsCGllWRYI ZCpM5AYI75JuZoI75wVxbIivIlsomAxWcgSu4ymhlaFz/3poKESxJI6Lx1BKKkjiUXH7n9g q6MEG0fhLQ1tYLc6KJaOYq/3y8tYO/Uzy2pFyITJ5XEsxK7R1LbUqd46aY1+yUrr88fuCKy SadRCy4V2ZW X-QQ-XMRINFO: OWPUhxQsoeAVDbp3OJHYyFg= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Add build options and doc for mucse. Initialize pci device access for MUCSE devices. Signed-off-by: Dong Yibo --- .../device_drivers/ethernet/index.rst | 1 + .../device_drivers/ethernet/mucse/rnpgbe.rst | 21 ++ MAINTAINERS | 8 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/mucse/Kconfig | 34 +++ drivers/net/ethernet/mucse/Makefile | 7 + drivers/net/ethernet/mucse/rnpgbe/Makefile | 9 + drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 33 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 226 ++++++++++++++++++ 10 files changed, 341 insertions(+) create mode 100644 Documentation/networking/device_drivers/ethernet/mucse/= rnpgbe.rst create mode 100644 drivers/net/ethernet/mucse/Kconfig create mode 100644 drivers/net/ethernet/mucse/Makefile create mode 100644 drivers/net/ethernet/mucse/rnpgbe/Makefile create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/D= ocumentation/networking/device_drivers/ethernet/index.rst index 40ac552641a3..0e03c5c10d30 100644 --- a/Documentation/networking/device_drivers/ethernet/index.rst +++ b/Documentation/networking/device_drivers/ethernet/index.rst @@ -61,6 +61,7 @@ Contents: wangxun/txgbevf wangxun/ngbe wangxun/ngbevf + mucse/rnpgbe =20 .. only:: subproject and html =20 diff --git a/Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.= rst b/Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.rst new file mode 100644 index 000000000000..7562fb6b8f61 --- /dev/null +++ b/Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Linux Base Driver for MUCSE(R) Gigabit PCI Express Adapters +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +MUCSE Gigabit Linux driver. +Copyright (c) 2020 - 2025 MUCSE Co.,Ltd. + +Identifying Your Adapter +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The driver is compatible with devices based on the following: + + * MUCSE(R) Ethernet Controller N500 series + * MUCSE(R) Ethernet Controller N210 series + +Support +=3D=3D=3D=3D=3D=3D=3D + If you have problems with the software or hardware, please contact our + customer support team via email at techsupport@mucse.com or check our + website at https://www.mucse.com/en/ diff --git a/MAINTAINERS b/MAINTAINERS index 1bc1698bc5ae..da0d12e77ddc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17033,6 +17033,14 @@ T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml F: drivers/media/i2c/mt9v111.c =20 +MUCSE ETHERNET DRIVER +M: Yibo Dong +L: netdev@vger.kernel.org +S: Maintained +W: https://www.mucse.com/en/ +F: Documentation/networking/device_drivers/ethernet/mucse/* +F: drivers/net/ethernet/mucse/* + MULTIFUNCTION DEVICES (MFD) M: Lee Jones S: Maintained diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index f86d4557d8d7..77c55fa11942 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -202,5 +202,6 @@ source "drivers/net/ethernet/wangxun/Kconfig" source "drivers/net/ethernet/wiznet/Kconfig" source "drivers/net/ethernet/xilinx/Kconfig" source "drivers/net/ethernet/xircom/Kconfig" +source "drivers/net/ethernet/mucse/Kconfig" =20 endif # ETHERNET diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 67182339469a..696825bd1211 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -107,3 +107,4 @@ obj-$(CONFIG_NET_VENDOR_XIRCOM) +=3D xircom/ obj-$(CONFIG_NET_VENDOR_SYNOPSYS) +=3D synopsys/ obj-$(CONFIG_NET_VENDOR_PENSANDO) +=3D pensando/ obj-$(CONFIG_OA_TC6) +=3D oa_tc6.o +obj-$(CONFIG_NET_VENDOR_MUCSE) +=3D mucse/ diff --git a/drivers/net/ethernet/mucse/Kconfig b/drivers/net/ethernet/mucs= e/Kconfig new file mode 100644 index 000000000000..be0fdf268484 --- /dev/null +++ b/drivers/net/ethernet/mucse/Kconfig @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Mucse network device configuration +# + +config NET_VENDOR_MUCSE + bool "Mucse devices" + default y + help + If you have a network (Ethernet) card from Mucse(R), say Y. + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about Mucse(R) cards. If you say Y, you will + be asked for your specific card in the following questions. + +if NET_VENDOR_MUCSE + +config MGBE + tristate "Mucse(R) 1GbE PCI Express adapters support" + depends on PCI + select PAGE_POOL + help + This driver supports Mucse(R) 1GbE PCI Express family of + adapters. + + More specific information on configuring the driver is in + . + + To compile this driver as a module, choose M here. The module + will be called rnpgbe. + +endif # NET_VENDOR_MUCSE + diff --git a/drivers/net/ethernet/mucse/Makefile b/drivers/net/ethernet/muc= se/Makefile new file mode 100644 index 000000000000..f0bd79882488 --- /dev/null +++ b/drivers/net/ethernet/mucse/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Mucse(R) network device drivers. +# + +obj-$(CONFIG_MGBE) +=3D rnpgbe/ + diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile new file mode 100644 index 000000000000..0942e27f5913 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2020 - 2025 MUCSE Corporation. +# +# Makefile for the MUCSE(R) 1GbE PCI Express ethernet driver +# + +obj-$(CONFIG_MGBE) +=3D rnpgbe.o + +rnpgbe-objs :=3D rnpgbe_main.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h new file mode 100644 index 000000000000..224e395d6be3 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_H +#define _RNPGBE_H + +enum rnpgbe_boards { + board_n500, + board_n210, + board_n210L, +}; + +struct mucse { + struct net_device *netdev; + struct pci_dev *pdev; + /* board number */ + u16 bd_number; + + char name[60]; +}; + +/* Device IDs */ +#ifndef PCI_VENDOR_ID_MUCSE +#define PCI_VENDOR_ID_MUCSE 0x8848 +#endif /* PCI_VENDOR_ID_MUCSE */ + +#define PCI_DEVICE_ID_N500_QUAD_PORT 0x8308 +#define PCI_DEVICE_ID_N500_DUAL_PORT 0x8318 +#define PCI_DEVICE_ID_N500_VF 0x8309 +#define PCI_DEVICE_ID_N210 0x8208 +#define PCI_DEVICE_ID_N210L 0x820a + +#endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c new file mode 100644 index 000000000000..13b49875006b --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#include +#include +#include +#include +#include +#include + +#include "rnpgbe.h" + +char rnpgbe_driver_name[] =3D "rnpgbe"; + +/* rnpgbe_pci_tbl - PCI Device ID Table + * + * { PCI_DEVICE(Vendor ID, Device ID), + * driver_data (used for different hw chip) } + */ +static struct pci_device_id rnpgbe_pci_tbl[] =3D { + { PCI_DEVICE(PCI_VENDOR_ID_MUCSE, PCI_DEVICE_ID_N500_QUAD_PORT), + .driver_data =3D board_n500}, + { PCI_DEVICE(PCI_VENDOR_ID_MUCSE, PCI_DEVICE_ID_N500_DUAL_PORT), + .driver_data =3D board_n500}, + { PCI_DEVICE(PCI_VENDOR_ID_MUCSE, PCI_DEVICE_ID_N210), + .driver_data =3D board_n210}, + { PCI_DEVICE(PCI_VENDOR_ID_MUCSE, PCI_DEVICE_ID_N210L), + .driver_data =3D board_n210L}, + /* required last entry */ + {0, }, +}; + +/** + * rnpgbe_add_adapter - add netdev for this pci_dev + * @pdev: PCI device information structure + * + * rnpgbe_add_adapter initializes a netdev for this pci_dev + * structure. Initializes Bar map, private structure, and a + * hardware reset occur. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_add_adapter(struct pci_dev *pdev) +{ + struct mucse *mucse =3D NULL; + struct net_device *netdev; + static int bd_number; + + netdev =3D alloc_etherdev_mq(sizeof(struct mucse), 1); + if (!netdev) + return -ENOMEM; + + mucse =3D netdev_priv(netdev); + mucse->netdev =3D netdev; + mucse->pdev =3D pdev; + mucse->bd_number =3D bd_number++; + snprintf(mucse->name, sizeof(netdev->name), "%s%d", + rnpgbe_driver_name, mucse->bd_number); + pci_set_drvdata(pdev, mucse); + + return 0; +} + +/** + * rnpgbe_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @id: entry in rnpgbe_pci_tbl + * + * rnpgbe_probe initializes a PF adapter identified by a pci_dev + * structure. The OS initialization, then call rnpgbe_add_adapter + * to initializes netdev. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_probe(struct pci_dev *pdev, const struct pci_device_id *= id) +{ + int err; + + err =3D pci_enable_device_mem(pdev); + if (err) + return err; + + /* hw only support 56-bits dma mask */ + err =3D dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(56)); + if (err) { + dev_err(&pdev->dev, + "No usable DMA configuration, aborting\n"); + goto err_dma; + } + + err =3D pci_request_mem_regions(pdev, rnpgbe_driver_name); + if (err) { + dev_err(&pdev->dev, + "pci_request_selected_regions failed 0x%x\n", err); + goto err_pci_req; + } + + pci_set_master(pdev); + pci_save_state(pdev); + err =3D rnpgbe_add_adapter(pdev); + if (err) + goto err_regions; + + return 0; +err_regions: + pci_release_mem_regions(pdev); +err_dma: +err_pci_req: + pci_disable_device(pdev); + return err; +} + +/** + * rnpgbe_rm_adapter - remove netdev for this mucse structure + * @mucse: pointer to private structure + * + * rnpgbe_rm_adapter remove a netdev for this mucse structure + **/ +static void rnpgbe_rm_adapter(struct mucse *mucse) +{ + struct net_device *netdev; + + netdev =3D mucse->netdev; + free_netdev(netdev); +} + +/** + * rnpgbe_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * rnpgbe_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. This could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ +static void rnpgbe_remove(struct pci_dev *pdev) +{ + struct mucse *mucse =3D pci_get_drvdata(pdev); + + if (!mucse) + return; + + rnpgbe_rm_adapter(mucse); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +/** + * rnpgbe_dev_shutdown - Device Shutdown Routine + * @pdev: PCI device information struct + * @enable_wake: wakeup status + **/ +static void rnpgbe_dev_shutdown(struct pci_dev *pdev, + bool *enable_wake) +{ + struct mucse *mucse =3D pci_get_drvdata(pdev); + struct net_device *netdev =3D mucse->netdev; + + *enable_wake =3D false; + netif_device_detach(netdev); + pci_disable_device(pdev); +} + +/** + * rnpgbe_shutdown - Device Shutdown Routine + * @pdev: PCI device information struct + * + * rnpgbe_shutdown is called by the PCI subsystem to alert the driver + * that os shutdown. Device should setup wakeup state here. + **/ +static void rnpgbe_shutdown(struct pci_dev *pdev) +{ + bool wake =3D false; + + rnpgbe_dev_shutdown(pdev, &wake); + + if (system_state =3D=3D SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, wake); + pci_set_power_state(pdev, PCI_D3hot); + } +} + +static struct pci_driver rnpgbe_driver =3D { + .name =3D rnpgbe_driver_name, + .id_table =3D rnpgbe_pci_tbl, + .probe =3D rnpgbe_probe, + .remove =3D rnpgbe_remove, + .shutdown =3D rnpgbe_shutdown, +}; + +/** + * rnpgbe_init_module - driver init routine + * + * rnpgbe_init_module is called when driver insmod + * + * @return: 0 on success, negative on failure + **/ +static int __init rnpgbe_init_module(void) +{ + int ret; + + ret =3D pci_register_driver(&rnpgbe_driver); + if (ret) + return ret; + + return 0; +} + +module_init(rnpgbe_init_module); + +/** + * rnpgbe_exit_module - driver remove routine + * + * rnpgbe_exit_module is called when driver is removed + **/ +static void __exit rnpgbe_exit_module(void) +{ + pci_unregister_driver(&rnpgbe_driver); +} + +module_exit(rnpgbe_exit_module); + +MODULE_DEVICE_TABLE(pci, rnpgbe_pci_tbl); +MODULE_AUTHOR("Mucse Corporation, "); +MODULE_DESCRIPTION("Mucse(R) 1 Gigabit PCI Express Network Driver"); +MODULE_LICENSE("GPL"); --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 192192BEFE8; Mon, 21 Jul 2025 11:34:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.206.16.166 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097661; cv=none; b=UzX8Okjxoq6v3aNiykDF6FJtiMXOFl5sOMZt9RmDmY+LixHQ8J0pfW5em0TuAZoBO6VJ+HwavF9qyH+lz7EWqLcn/P3ggTBySW7rXqdfHfnOD9oEUlDvdAI5WMaFvy5Jp8ZWhpkbbM5tZuDZyuBE/nwWlaMjX8uO7rDdspa+xm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097661; c=relaxed/simple; bh=vooNi8Qwa04jUbTjnsV5eGfpLwOHfFuFlTtcqHfy/m4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cAQqvQxhWvU8GqJSN5iw+KYO50Gpf2Oh67d7ADE+rTz5o4FajxmPiaXt5sU2LmUFQf/RqjBpfbmBenZwzqRQiO5ajxMbhjNIf0PwC5bn6e0U53CLVjMlkfmcqTStF8JHkcShGoQDk1PYv8GLiBIBij7ELFyN9UaQHDtA8vb9nfA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.206.16.166 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097576t82dafd45 X-QQ-Originating-IP: NptqxyzNrOyGF1w/m/llX/4RyiTdPPY+OIS7ay9CfnA= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:32:52 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 17080768655325101157 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 02/15] net: rnpgbe: Add n500/n210 chip support Date: Mon, 21 Jul 2025 19:32:25 +0800 Message-Id: <20250721113238.18615-3-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: N/BWsBa1EZaJ3hIMGwNAu8GgyGNIk3waizjKwxowUKGKYfzkEj3WijUE R8nwSBwzn+PNL9etZRHtlQkCUWoNE6MA0Wwb87vtCmJ9K6IlAMl0zkviMe5/SNA9zDXDLt1 MZPXN7bNFAIlz2K2TzXraVImlPTdPbHu/woWnCm13IGZ8xRYmklHLP3DCbPAeN59ffUN9QU V0yk4HNEKKyYwmUNBdHWbFfwp8IG8wqlobC0y+Vspxaj/hlEEEU19N+donH9SFS52F2a1g5 L+iYNFqgwS3ebW/fMw2/sBCEiLajIZby2+aMJqagk3qQY//T5EkO49hxL1+csWtIjtuKYNF HzKe0fyteGIfb7frksVKOb9CSaFY4t0jKtDrZq0bop8oMvGq9n3xhM3lHhSbmmeU8kEDYBx DJuQU8F7IFT+RB4SiF1dWutYzZ4BpodABXiKA/FdSFsfd5yhs/GjwOeaSlPvmmTcbjwV1+N 6BUDjy3TmYVOojO6iv9UuZfyzntW0UhvPA9RmvOGw+wL0LRTGsbDY78YACq1u6ZN+qWs6Er ybB1SLqVsjP9zgQSwGcP/SQAxrs0YBJ2Rnek4qEnr0a9gHcdX1iyDv0hYY8oTkFZ4sYWn0X SPdz23V1rqcNwKx9V64llIvBCaopt0WFr+4LPQXwR0a0V0kdrfPO5ZfPQnZtXXQ106DNjuo dj8i4l47nX5HYl9eOyGF4PgfcjUQfVGL4q6HF/LSMoGw5QheEsch8NNvMEv2dsPa0WTedgV JxVYxbHoQKt0pImwRgXSIN/UpaYaRe0NFvNTn1oM4L/i9IRQb53Hf4b7MQZBM3+bNi3tC/I mMBe5EarF6LS8ctdkQ1M8nf1Oqw5lu06uH177sVNM4kLO41oxSmV+Qn5gMFbXCwymis3WbG oUJI2+PRWZKaQFe1vIta27KoCSRm5f+143SRBcmh2YUZPs68xZwc/EkS/dAEAxqXZMaFlN1 Y9+RTTQ0ww6voz5X9C/V7moCNhPTuRRirjnLNC041LLYRtzJPWA0MnoAbCPQ7NRflyh/W46 WhjqDAgilPjir94bdzJ65N7LpsfRVg0oTZwjYpEjTKUNZhsH6TqBi/HS1tlCwAIbuN+lQu+ ePuBIjGrOWm X-QQ-XMRINFO: NS+P29fieYNw95Bth2bWPxk= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize n500/n210 chip bar resource map and dma, eth, mbx ... info for future use. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/Makefile | 4 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 138 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 138 ++++++++++++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 27 ++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 68 ++++++++- 5 files changed, 370 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile index 0942e27f5913..42c359f459d9 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -5,5 +5,5 @@ # =20 obj-$(CONFIG_MGBE) +=3D rnpgbe.o - -rnpgbe-objs :=3D rnpgbe_main.o +rnpgbe-objs :=3D rnpgbe_main.o\ + rnpgbe_chip.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 224e395d6be3..2ae836fc8951 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -4,21 +4,156 @@ #ifndef _RNPGBE_H #define _RNPGBE_H =20 +#include +#include + +extern const struct rnpgbe_info rnpgbe_n500_info; +extern const struct rnpgbe_info rnpgbe_n210_info; +extern const struct rnpgbe_info rnpgbe_n210L_info; + enum rnpgbe_boards { board_n500, board_n210, board_n210L, }; =20 +enum rnpgbe_hw_type { + rnpgbe_hw_n500 =3D 0, + rnpgbe_hw_n210, + rnpgbe_hw_n210L, + rnpgbe_hw_unknow +}; + +struct mucse_dma_info { + u8 __iomem *dma_base_addr; + u8 __iomem *dma_ring_addr; + void *back; + u32 max_tx_queues; + u32 max_rx_queues; + u32 dma_version; +}; + +#define RNPGBE_MAX_MTA 128 +struct mucse_eth_info { + u8 __iomem *eth_base_addr; + void *back; + u32 mta_shadow[RNPGBE_MAX_MTA]; + int mc_filter_type; + u32 mcft_size; + u32 vft_size; + u32 num_rar_entries; +}; + +struct mii_regs { + unsigned int addr; /* MII Address */ + unsigned int data; /* MII Data */ + unsigned int addr_shift; /* MII address shift */ + unsigned int reg_shift; /* MII reg shift */ + unsigned int addr_mask; /* MII address mask */ + unsigned int reg_mask; /* MII reg mask */ + unsigned int clk_csr_shift; + unsigned int clk_csr_mask; +}; + +struct mucse_mac_info { + u8 __iomem *mac_addr; + void *back; + struct mii_regs mii; + int phy_addr; + int clk_csr; +}; + +#define MAX_VF_NUM (8) + +struct mucse_mbx_info { + u32 timeout; + u32 usec_delay; + u32 v2p_mailbox; + u16 size; + u16 vf_req[MAX_VF_NUM]; + u16 vf_ack[MAX_VF_NUM]; + u16 fw_req; + u16 fw_ack; + /* lock for only one use mbx */ + struct mutex lock; + bool irq_enabled; + int mbx_size; + int mbx_mem_size; +#define MBX_FEATURE_NO_ZERO BIT(0) +#define MBX_FEATURE_WRITE_DELAY BIT(1) + u32 mbx_feature; + /* fw <--> pf mbx */ + u32 fw_pf_shm_base; + u32 pf2fw_mbox_ctrl; + u32 pf2fw_mbox_mask; + u32 fw_pf_mbox_mask; + u32 fw2pf_mbox_vec; + /* pf <--> vf mbx */ + u32 pf_vf_shm_base; + u32 pf2vf_mbox_ctrl_base; + u32 pf_vf_mbox_mask_lo; + u32 pf_vf_mbox_mask_hi; + u32 pf2vf_mbox_vec_base; + u32 vf2pf_mbox_vec_base; + u32 fw_vf_share_ram; + int share_size; +}; + +struct mucse_hw { + void *back; + u8 pfvfnum; + u8 pfvfnum_system; + u8 __iomem *hw_addr; + u8 __iomem *ring_msix_base; + struct pci_dev *pdev; + u16 device_id; + u16 vendor_id; + u16 subsystem_device_id; + u16 subsystem_vendor_id; + enum rnpgbe_hw_type hw_type; + struct mucse_dma_info dma; + struct mucse_eth_info eth; + struct mucse_mac_info mac; + struct mucse_mbx_info mbx; +#define M_NET_FEATURE_SG BIT(0) +#define M_NET_FEATURE_TX_CHECKSUM BIT(1) +#define M_NET_FEATURE_RX_CHECKSUM BIT(2) +#define M_NET_FEATURE_TSO BIT(3) +#define M_NET_FEATURE_TX_UDP_TUNNEL BIT(4) +#define M_NET_FEATURE_VLAN_FILTER BIT(5) +#define M_NET_FEATURE_VLAN_OFFLOAD BIT(6) +#define M_NET_FEATURE_RX_NTUPLE_FILTER BIT(7) +#define M_NET_FEATURE_TCAM BIT(8) +#define M_NET_FEATURE_RX_HASH BIT(9) +#define M_NET_FEATURE_RX_FCS BIT(10) +#define M_NET_FEATURE_HW_TC BIT(11) +#define M_NET_FEATURE_USO BIT(12) +#define M_NET_FEATURE_STAG_FILTER BIT(13) +#define M_NET_FEATURE_STAG_OFFLOAD BIT(14) +#define M_NET_FEATURE_VF_FIXED BIT(15) +#define M_VEB_VLAN_MASK_EN BIT(16) +#define M_HW_FEATURE_EEE BIT(17) +#define M_HW_SOFT_MASK_OTHER_IRQ BIT(18) + u32 feature_flags; + u16 usecstocount; +}; + struct mucse { struct net_device *netdev; struct pci_dev *pdev; + struct mucse_hw hw; /* board number */ u16 bd_number; =20 char name[60]; }; =20 +struct rnpgbe_info { + int total_queue_pair_cnts; + enum rnpgbe_hw_type hw_type; + void (*get_invariants)(struct mucse_hw *hw); +}; + /* Device IDs */ #ifndef PCI_VENDOR_ID_MUCSE #define PCI_VENDOR_ID_MUCSE 0x8848 @@ -30,4 +165,7 @@ struct mucse { #define PCI_DEVICE_ID_N210 0x8208 #define PCI_DEVICE_ID_N210L 0x820a =20 +#define m_rd_reg(reg) readl(reg) +#define m_wr_reg(reg, val) writel((val), reg) + #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c new file mode 100644 index 000000000000..38c094965db9 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#include +#include + +#include "rnpgbe.h" +#include "rnpgbe_hw.h" + +/** + * rnpgbe_get_invariants_n500 - setup for hw info + * @hw: hw information structure + * + * rnpgbe_get_invariants_n500 initializes all private + * structure, such as dma, eth, mac and mbx base on + * hw->addr for n500 + **/ +static void rnpgbe_get_invariants_n500(struct mucse_hw *hw) +{ + struct mucse_dma_info *dma =3D &hw->dma; + struct mucse_eth_info *eth =3D &hw->eth; + struct mucse_mac_info *mac =3D &hw->mac; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + /* setup msix base */ + hw->ring_msix_base =3D hw->hw_addr + 0x28700; + /* setup dma info */ + dma->dma_base_addr =3D hw->hw_addr; + dma->dma_ring_addr =3D hw->hw_addr + RNPGBE_RING_BASE; + dma->max_tx_queues =3D RNPGBE_MAX_QUEUES; + dma->max_rx_queues =3D RNPGBE_MAX_QUEUES; + dma->back =3D hw; + /* setup eth info */ + eth->eth_base_addr =3D hw->hw_addr + RNPGBE_ETH_BASE; + eth->back =3D hw; + eth->mc_filter_type =3D 0; + eth->mcft_size =3D RNPGBE_MC_TBL_SIZE; + eth->vft_size =3D RNPGBE_VFT_TBL_SIZE; + eth->num_rar_entries =3D RNPGBE_RAR_ENTRIES; + /* setup mac info */ + mac->mac_addr =3D hw->hw_addr + RNPGBE_MAC_BASE; + mac->back =3D hw; + /* set mac->mii */ + mac->mii.addr =3D RNPGBE_MII_ADDR; + mac->mii.data =3D RNPGBE_MII_DATA; + mac->mii.addr_shift =3D 11; + mac->mii.addr_mask =3D 0x0000F800; + mac->mii.reg_shift =3D 6; + mac->mii.reg_mask =3D 0x000007C0; + mac->mii.clk_csr_shift =3D 2; + mac->mii.clk_csr_mask =3D GENMASK(5, 2); + mac->clk_csr =3D 0x02; /* csr 25M */ + /* hw fixed phy_addr */ + mac->phy_addr =3D 0x11; + + mbx->mbx_feature |=3D MBX_FEATURE_NO_ZERO; + /* mbx offset */ + mbx->vf2pf_mbox_vec_base =3D 0x28900; + mbx->fw2pf_mbox_vec =3D 0x28b00; + mbx->pf_vf_shm_base =3D 0x29000; + mbx->mbx_mem_size =3D 64; + mbx->pf2vf_mbox_ctrl_base =3D 0x2a100; + mbx->pf_vf_mbox_mask_lo =3D 0x2a200; + mbx->pf_vf_mbox_mask_hi =3D 0; + mbx->fw_pf_shm_base =3D 0x2d000; + mbx->pf2fw_mbox_ctrl =3D 0x2e000; + mbx->fw_pf_mbox_mask =3D 0x2e200; + mbx->fw_vf_share_ram =3D 0x2b000; + mbx->share_size =3D 512; + + /* setup net feature here */ + hw->feature_flags |=3D M_NET_FEATURE_SG | + M_NET_FEATURE_TX_CHECKSUM | + M_NET_FEATURE_RX_CHECKSUM | + M_NET_FEATURE_TSO | + M_NET_FEATURE_VLAN_FILTER | + M_NET_FEATURE_VLAN_OFFLOAD | + M_NET_FEATURE_RX_NTUPLE_FILTER | + M_NET_FEATURE_RX_HASH | + M_NET_FEATURE_USO | + M_NET_FEATURE_RX_FCS | + M_NET_FEATURE_STAG_FILTER | + M_NET_FEATURE_STAG_OFFLOAD; + /* start the default ahz, update later */ + hw->usecstocount =3D 125; +} + +/** + * rnpgbe_get_invariants_n210 - setup for hw info + * @hw: hw information structure + * + * rnpgbe_get_invariants_n210 initializes all private + * structure, such as dma, eth, mac and mbx base on + * hw->addr for n210 + **/ +static void rnpgbe_get_invariants_n210(struct mucse_hw *hw) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + /* get invariants based from n500 */ + rnpgbe_get_invariants_n500(hw); + + /* update msix base */ + hw->ring_msix_base =3D hw->hw_addr + 0x29000; + /* update mbx offset */ + mbx->vf2pf_mbox_vec_base =3D 0x29200; + mbx->fw2pf_mbox_vec =3D 0x29400; + mbx->pf_vf_shm_base =3D 0x29900; + mbx->mbx_mem_size =3D 64; + mbx->pf2vf_mbox_ctrl_base =3D 0x2aa00; + mbx->pf_vf_mbox_mask_lo =3D 0x2ab00; + mbx->pf_vf_mbox_mask_hi =3D 0; + mbx->fw_pf_shm_base =3D 0x2d900; + mbx->pf2fw_mbox_ctrl =3D 0x2e900; + mbx->fw_pf_mbox_mask =3D 0x2eb00; + mbx->fw_vf_share_ram =3D 0x2b900; + mbx->share_size =3D 512; + /* update hw feature */ + hw->feature_flags |=3D M_HW_FEATURE_EEE; + hw->usecstocount =3D 62; +} + +const struct rnpgbe_info rnpgbe_n500_info =3D { + .total_queue_pair_cnts =3D RNPGBE_MAX_QUEUES, + .hw_type =3D rnpgbe_hw_n500, + .get_invariants =3D &rnpgbe_get_invariants_n500, +}; + +const struct rnpgbe_info rnpgbe_n210_info =3D { + .total_queue_pair_cnts =3D RNPGBE_MAX_QUEUES, + .hw_type =3D rnpgbe_hw_n210, + .get_invariants =3D &rnpgbe_get_invariants_n210, +}; + +const struct rnpgbe_info rnpgbe_n210L_info =3D { + .total_queue_pair_cnts =3D RNPGBE_MAX_QUEUES, + .hw_type =3D rnpgbe_hw_n210L, + .get_invariants =3D &rnpgbe_get_invariants_n210, +}; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h new file mode 100644 index 000000000000..2c7372a5e88d --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_HW_H +#define _RNPGBE_HW_H +/* BAR */ +/* ----------------------------------------- */ +/* module | size | start | end */ +/* DMA | 32KB | 0_0000H | 0_7FFFH */ +/* ETH | 64KB | 1_0000H | 1_FFFFH */ +/* MAC | 32KB | 2_0000H | 2_7FFFH */ +/* MSIX | 32KB | 2_8000H | 2_FFFFH */ + +#define RNPGBE_RING_BASE (0x1000) +#define RNPGBE_MAC_BASE (0x20000) +#define RNPGBE_ETH_BASE (0x10000) +/* chip resourse */ +#define RNPGBE_MAX_QUEUES (8) +/* multicast control table */ +#define RNPGBE_MC_TBL_SIZE (128) +/* vlan filter table */ +#define RNPGBE_VFT_TBL_SIZE (128) +#define RNPGBE_RAR_ENTRIES (32) + +#define RNPGBE_MII_ADDR 0x00000010 /* MII Address */ +#define RNPGBE_MII_DATA 0x00000014 /* MII Data */ +#endif /* _RNPGBE_HW_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 13b49875006b..08f773199e9b 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -11,6 +11,11 @@ #include "rnpgbe.h" =20 char rnpgbe_driver_name[] =3D "rnpgbe"; +static const struct rnpgbe_info *rnpgbe_info_tbl[] =3D { + [board_n500] =3D &rnpgbe_n500_info, + [board_n210] =3D &rnpgbe_n210_info, + [board_n210L] =3D &rnpgbe_n210L_info, +}; =20 /* rnpgbe_pci_tbl - PCI Device ID Table * @@ -33,6 +38,7 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { /** * rnpgbe_add_adapter - add netdev for this pci_dev * @pdev: PCI device information structure + * @ii: chip info structure * * rnpgbe_add_adapter initializes a netdev for this pci_dev * structure. Initializes Bar map, private structure, and a @@ -40,16 +46,24 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { * * @return: 0 on success, negative on failure **/ -static int rnpgbe_add_adapter(struct pci_dev *pdev) +static int rnpgbe_add_adapter(struct pci_dev *pdev, + const struct rnpgbe_info *ii) { struct mucse *mucse =3D NULL; + struct mucse_hw *hw =3D NULL; + u8 __iomem *hw_addr =3D NULL; struct net_device *netdev; static int bd_number; + u32 dma_version =3D 0; + int err =3D 0; + u32 queues; =20 - netdev =3D alloc_etherdev_mq(sizeof(struct mucse), 1); + queues =3D ii->total_queue_pair_cnts; + netdev =3D alloc_etherdev_mq(sizeof(struct mucse), queues); if (!netdev) return -ENOMEM; =20 + SET_NETDEV_DEV(netdev, &pdev->dev); mucse =3D netdev_priv(netdev); mucse->netdev =3D netdev; mucse->pdev =3D pdev; @@ -58,7 +72,54 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev) rnpgbe_driver_name, mucse->bd_number); pci_set_drvdata(pdev, mucse); =20 + hw =3D &mucse->hw; + hw->back =3D mucse; + hw->hw_type =3D ii->hw_type; + + switch (hw->hw_type) { + case rnpgbe_hw_n500: + /* n500 use bar2 */ + hw_addr =3D devm_ioremap(&pdev->dev, + pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + if (!hw_addr) { + dev_err(&pdev->dev, "map bar2 failed!\n"); + return -EIO; + } + + /* get dma version */ + dma_version =3D m_rd_reg(hw_addr); + break; + case rnpgbe_hw_n210: + case rnpgbe_hw_n210L: + /* check bar0 to load firmware */ + if (pci_resource_len(pdev, 0) =3D=3D 0x100000) + return -EIO; + /* n210 use bar2 */ + hw_addr =3D devm_ioremap(&pdev->dev, + pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + if (!hw_addr) { + dev_err(&pdev->dev, "map bar2 failed!\n"); + return -EIO; + } + + /* get dma version */ + dma_version =3D m_rd_reg(hw_addr); + break; + default: + err =3D -EIO; + goto err_free_net; + } + hw->hw_addr =3D hw_addr; + hw->dma.dma_version =3D dma_version; + ii->get_invariants(hw); + return 0; + +err_free_net: + free_netdev(netdev); + return err; } =20 /** @@ -74,6 +135,7 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev) **/ static int rnpgbe_probe(struct pci_dev *pdev, const struct pci_device_id *= id) { + const struct rnpgbe_info *ii =3D rnpgbe_info_tbl[id->driver_data]; int err; =20 err =3D pci_enable_device_mem(pdev); @@ -97,7 +159,7 @@ static int rnpgbe_probe(struct pci_dev *pdev, const stru= ct pci_device_id *id) =20 pci_set_master(pdev); pci_save_state(pdev); - err =3D rnpgbe_add_adapter(pdev); + err =3D rnpgbe_add_adapter(pdev, ii); if (err) goto err_regions; =20 --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BEF7129E0F6; Mon, 21 Jul 2025 11:33:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.207.22.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097648; cv=none; b=pBtpb/pFVrkXag8Ul3T2yHZck+HjauMFm+LM+++8GZp4JrI8c6Ovm5hMcHOjHsyTcgg5PFyzm15NK8EQUQOYv5GYk9xypzK54Nnzh0bx4iT2TvbtEi17xt2NNGcCzbq2dB0NPlhowlxCV5gyODllJmTQd/r+OgoT/rd8zMk081A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097648; c=relaxed/simple; bh=SCP//Rm0JLeoCAlIOLQz4+G+wwzmlIPHfWtCfFmt7A4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XeCTYn6h998xxd6254VbrzTDVVf5o6bnJ5LzYoGMQzh29nZGqXxnFlH5Uu65KNazlT6OtUlyTLConr7tg64Tx5o6qfnOJq9UNLPAPkz7JWv6jBhse9SUMwh+RzmCys25QZy8NHJmSS09IMOgn9Qyx6X8kgo+r7TW0kvVGCS3bF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.207.22.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097580tc73f08ec X-QQ-Originating-IP: /8z6Hp0On905J8D0G+sDNB8Ef3Ye0eEfRoFz+PeHE/g= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:32:57 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 2044852615640205610 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 03/15] net: rnpgbe: Add basic mbx ops support Date: Mon, 21 Jul 2025 19:32:26 +0800 Message-Id: <20250721113238.18615-4-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NU206xxuabmsUretmDyprvZ2FEP8cb9K1uDISnousBt5TIQ1ZOA26ck2 W3QnbyXZSuSQhZgtLXvFbAy7eYCCJHuXfbFmNmUkueXrOV0F6cQo0HFzh/tyWABze+FQqiz jVdkQS55XqNACKR5DYTB3kUNiISBqNBTMg48Q4JeipLFKGk/NKZIwuyId1sZONdhiNQouS0 CXu1o+jwJGurYtMplN7L672bUNGfFnmeFFSA2PYFJ6HWMnkn/LV61KMIXfqJATnxH/kCbEW xw4Evwt2wF6gquEI71iZFAoGG4JW4ri7lUdL52Z1Sjo6SWdvXXn6ZOcLUHxR8bhwPEia0Au UUSaLkkP0zYGyJ9lu/FvD+1kOOFsvpAoO9jmvpjkdQ/kTMA0QudXn42fzhypo19239lXRdZ h1uo+bscoDofNDaALrJJQ7KaXb8IhbOGFa/A2y8ZYsAKT0XUlzRJIAcaeYMfuvZKy+hRoIl IVpVGgvf22AvnBDZPkIsBTD/ye5Pi67pTfJZ5OKpY48tfvuywAoBC4LA721WAFSaIes0MX2 NcvQK+Z399d8Oh4LdeJXRd0fk5+aQc3UHxmup5g8s9NgjNejb1eEAjCi/O4T74SCGPdw7AP SaR0McUsgx6rRuD7nY8lOur0v7c/g8oflXcztP40eDyJQKxF1o5RQIU38r7trs/MrBmjz0A 2CmSzHdUgQOP/+DSjOygqE+BslHrFhmhbHz4Wt3unf54yGzaGpuRusQmlMgB7SZRpij53M9 +F8YLDSlSjc0p5PJqxjYqnUwGZqnRGpZyZIs00hJ4Now+kTsNxcy2TpG0IDdIWAInSS3Z5i JprGFYzDhmeX67iKanOnHi4elvHDKrcBKTMsHwbamKGjZ5D2XO72r4Ede2iC6OlJsUk9cFR jfNqV+N54IDNlVJzu7ZDkk0M+vaFdDsY7wf5+t2+GYMDr0dWLPy7LtiJgg6ABp58roRObN3 bYQFRrk4seZ2thOkhEWTNuLyVQDNmEOOE7NqDRTmyciclU+qCWQC+wP6JSS5oQkrw9/rvht sNop14vXMpLryKXOJ22YKlRsB4Kq7xAmbgSFggD5sE8WbCsmbn X-QQ-XMRINFO: OWPUhxQsoeAVDbp3OJHYyFg= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize basic mbx function. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/Makefile | 5 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 46 ++ .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 5 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 1 + .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c | 623 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h | 48 ++ 7 files changed, 727 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile index 42c359f459d9..41177103b50c 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -5,5 +5,6 @@ # =20 obj-$(CONFIG_MGBE) +=3D rnpgbe.o -rnpgbe-objs :=3D rnpgbe_main.o\ - rnpgbe_chip.o +rnpgbe-objs :=3D rnpgbe_main.o \ + rnpgbe_chip.o \ + rnpgbe_mbx.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 2ae836fc8951..46e2bb2fe71e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -63,9 +63,51 @@ struct mucse_mac_info { int clk_csr; }; =20 +struct mucse_hw; + +enum MBX_ID { + MBX_VF0 =3D 0, + MBX_VF1, + MBX_VF2, + MBX_VF3, + MBX_VF4, + MBX_VF5, + MBX_VF6, + MBX_VF7, + MBX_CM3CPU, + MBX_FW =3D MBX_CM3CPU, + MBX_VFCNT +}; + +struct mucse_mbx_operations { + void (*init_params)(struct mucse_hw *hw); + int (*read)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + int (*write)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + int (*read_posted)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + int (*write_posted)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + int (*check_for_msg)(struct mucse_hw *hw, enum MBX_ID id); + int (*check_for_ack)(struct mucse_hw *hw, enum MBX_ID id); + void (*configure)(struct mucse_hw *hw, int num_vec, + bool enable); +}; + +struct mucse_mbx_stats { + u32 msgs_tx; + u32 msgs_rx; + u32 acks; + u32 reqs; + u32 rsts; +}; + #define MAX_VF_NUM (8) =20 struct mucse_mbx_info { + struct mucse_mbx_operations ops; + struct mucse_mbx_stats stats; u32 timeout; u32 usec_delay; u32 v2p_mailbox; @@ -99,6 +141,8 @@ struct mucse_mbx_info { int share_size; }; =20 +#include "rnpgbe_mbx.h" + struct mucse_hw { void *back; u8 pfvfnum; @@ -110,6 +154,8 @@ struct mucse_hw { u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; + int max_vfs; + int max_vfs_noari; enum rnpgbe_hw_type hw_type; struct mucse_dma_info dma; struct mucse_eth_info eth; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index 38c094965db9..b0e5fda632f3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -6,6 +6,7 @@ =20 #include "rnpgbe.h" #include "rnpgbe_hw.h" +#include "rnpgbe_mbx.h" =20 /** * rnpgbe_get_invariants_n500 - setup for hw info @@ -67,7 +68,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *h= w) mbx->fw_pf_mbox_mask =3D 0x2e200; mbx->fw_vf_share_ram =3D 0x2b000; mbx->share_size =3D 512; - + memcpy(&hw->mbx.ops, &mucse_mbx_ops_generic, sizeof(hw->mbx.ops)); /* setup net feature here */ hw->feature_flags |=3D M_NET_FEATURE_SG | M_NET_FEATURE_TX_CHECKSUM | @@ -83,6 +84,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *h= w) M_NET_FEATURE_STAG_OFFLOAD; /* start the default ahz, update later */ hw->usecstocount =3D 125; + hw->max_vfs =3D 7; } =20 /** @@ -117,6 +119,7 @@ static void rnpgbe_get_invariants_n210(struct mucse_hw = *hw) /* update hw feature */ hw->feature_flags |=3D M_HW_FEATURE_EEE; hw->usecstocount =3D 62; + hw->max_vfs_noari =3D 7; } =20 const struct rnpgbe_info rnpgbe_n500_info =3D { diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h index 2c7372a5e88d..ff7bd9b21550 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -14,6 +14,8 @@ #define RNPGBE_RING_BASE (0x1000) #define RNPGBE_MAC_BASE (0x20000) #define RNPGBE_ETH_BASE (0x10000) + +#define RNPGBE_DMA_DUMY (0x000c) /* chip resourse */ #define RNPGBE_MAX_QUEUES (8) /* multicast control table */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 08f773199e9b..1e8360cae560 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -114,6 +114,7 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, hw->hw_addr =3D hw_addr; hw->dma.dma_version =3D dma_version; ii->get_invariants(hw); + hw->mbx.ops.init_params(hw); =20 return 0; =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_mbx.c new file mode 100644 index 000000000000..56ace3057fea --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ + +#include +#include +#include +#include +#include "rnpgbe.h" +#include "rnpgbe_mbx.h" +#include "rnpgbe_hw.h" + +/** + * mucse_read_mbx - Reads a message from the mailbox + * @hw: Pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to read + * + * @return: 0 on success, negative on failure + **/ +int mucse_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size =3D mbx->size; + + if (!mbx->ops.read) + return -EIO; + + return mbx->ops.read(hw, msg, size, mbx_id); +} + +/** + * mucse_write_mbx - Write a message to the mailbox + * @hw: Pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to write + * + * @return: 0 on success, negative on failure + **/ +int mucse_write_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + + if (size > mbx->size) + return -EINVAL; + + if (!mbx->ops.write) + return -EIO; + + return mbx->ops.write(hw, msg, size, mbx_id); +} + +/** + * mucse_mbx_get_req - Read req from reg + * @hw: Pointer to the HW structure + * @reg: Register to read + * + * @return: the req value + **/ +static u16 mucse_mbx_get_req(struct mucse_hw *hw, int reg) +{ + /* force memory barrier */ + mb(); + return ioread32(hw->hw_addr + reg) & GENMASK(15, 0); +} + +/** + * mucse_mbx_get_ack - Read ack from reg + * @hw: Pointer to the HW structure + * @reg: Register to read + * + * @return: the ack value + **/ +static u16 mucse_mbx_get_ack(struct mucse_hw *hw, int reg) +{ + /* force memory barrier */ + mb(); + return (mbx_rd32(hw, reg) >> 16); +} + +/** + * mucse_mbx_inc_pf_req - Increase req + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to read + * + * mucse_mbx_inc_pf_req read pf_req from hw, then write + * new value back after increase + **/ +static void mucse_mbx_inc_pf_req(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 reg, v; + u16 req; + + reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_COUNTER(mbx) : + PF2VF_COUNTER(mbx, mbx_id); + v =3D mbx_rd32(hw, reg); + req =3D (v & GENMASK(15, 0)); + req++; + v &=3D GENMASK(31, 16); + v |=3D req; + /* force before write to hw */ + mb(); + mbx_wr32(hw, reg, v); + /* update stats */ + hw->mbx.stats.msgs_tx++; +} + +/** + * mucse_mbx_inc_pf_ack - Increase ack + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to read + * + * mucse_mbx_inc_pf_ack read pf_ack from hw, then write + * new value back after increase + **/ +static void mucse_mbx_inc_pf_ack(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 reg, v; + u16 ack; + + reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_COUNTER(mbx) : + PF2VF_COUNTER(mbx, mbx_id); + v =3D mbx_rd32(hw, reg); + ack =3D (v >> 16) & GENMASK(15, 0); + ack++; + v &=3D GENMASK(15, 0); + v |=3D (ack << 16); + /* force before write to hw */ + mb(); + mbx_wr32(hw, reg, v); + /* update stats */ + hw->mbx.stats.msgs_rx++; +} + +/** + * mucse_check_for_msg - Checks to see if vf/fw sent us mail + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to check + * + * @return: 0 on success, negative on failure + **/ +int mucse_check_for_msg(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + + if (!mbx->ops.check_for_msg) + return -EIO; + + return mbx->ops.check_for_msg(hw, mbx_id); +} + +/** + * mucse_check_for_ack - Checks to see if vf/fw sent us ACK + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to check + * + * @return: 0 on success, negative on failure + **/ +int mucse_check_for_ack(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + + if (!mbx->ops.check_for_ack) + return -EIO; + return mbx->ops.check_for_ack(hw, mbx_id); +} + +/** + * mucse_poll_for_msg - Wait for message notification + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to poll + * + * @return: 0 on success, negative on failure + **/ +static int mucse_poll_for_msg(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int countdown =3D mbx->timeout; + int val; + + if (!countdown || !mbx->ops.check_for_msg) + return -EIO; + + return read_poll_timeout(mbx->ops.check_for_msg, + val, val =3D=3D 0, mbx->usec_delay, + countdown * mbx->usec_delay, + false, hw, mbx_id); +} + +/** + * mucse_poll_for_ack - Wait for message acknowledgment + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to poll + * + * @return: 0 if it successfully received a message acknowledgment + **/ +static int mucse_poll_for_ack(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int countdown =3D mbx->timeout; + int val; + + if (!countdown || !mbx->ops.check_for_ack) + return -EIO; + + return read_poll_timeout(mbx->ops.check_for_ack, + val, val =3D=3D 0, mbx->usec_delay, + countdown * mbx->usec_delay, + false, hw, mbx_id); +} + +/** + * mucse_read_posted_mbx - Wait for message notification and receive messa= ge + * @hw: Pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to read + * + * @return: 0 if it successfully received a message notification and + * copied it into the receive buffer. + **/ +static int mucse_read_posted_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int ret_val; + + if (!mbx->ops.read) + return -EIO; + + ret_val =3D mucse_poll_for_msg(hw, mbx_id); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val =3D mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * mucse_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: Pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to write + * + * @return: 0 if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +static int mucse_write_posted_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int ret_val; + + /* exit if either we can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + return -EIO; + + /* send msg and hold buffer lock */ + ret_val =3D mbx->ops.write(hw, msg, size, mbx_id); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val =3D mucse_poll_for_ack(hw, mbx_id); + + return ret_val; +} + +/** + * mucse_check_for_msg_pf - checks to see if the vf/fw has sent mail + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to check + * + * @return: 0 if the vf/fw has set the Status bit or else + * -EIO + **/ +static int mucse_check_for_msg_pf(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + u16 hw_req_count =3D 0; + int ret_val =3D -EIO; + + if (mbx_id =3D=3D MBX_FW) { + hw_req_count =3D mucse_mbx_get_req(hw, FW2PF_COUNTER(mbx)); + /* reg in hw should avoid 0 check */ + if (mbx->mbx_feature & MBX_FEATURE_NO_ZERO) { + if (hw_req_count !=3D 0 && + hw_req_count !=3D hw->mbx.fw_req) { + ret_val =3D 0; + hw->mbx.stats.reqs++; + } + } else { + if (hw_req_count !=3D hw->mbx.fw_req) { + ret_val =3D 0; + hw->mbx.stats.reqs++; + } + } + } else { + if (mucse_mbx_get_req(hw, VF2PF_COUNTER(mbx, mbx_id)) !=3D + hw->mbx.vf_req[mbx_id]) { + ret_val =3D 0; + hw->mbx.stats.reqs++; + } + } + + return ret_val; +} + +/** + * mucse_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to check + * + * @return: 0 if the vf/fw has set the Status bit or else + * -EIO + **/ +static int mucse_check_for_ack_pf(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int ret_val =3D -EIO; + u16 hw_fw_ack; + + if (mbx_id =3D=3D MBX_FW) { + hw_fw_ack =3D mucse_mbx_get_ack(hw, FW2PF_COUNTER(mbx)); + if (hw_fw_ack !=3D 0 && + hw_fw_ack !=3D hw->mbx.fw_ack) { + ret_val =3D 0; + hw->mbx.stats.acks++; + } + } else { + if (mucse_mbx_get_ack(hw, VF2PF_COUNTER(mbx, mbx_id)) !=3D + hw->mbx.vf_ack[mbx_id]) { + ret_val =3D 0; + hw->mbx.stats.acks++; + } + } + + return ret_val; +} + +/** + * mucse_obtain_mbx_lock_pf - obtain mailbox lock + * @hw: pointer to the HW structure + * @mbx_id: Id of vf/fw to obtain + * + * This function maybe used in an irq handler. + * + * @return: 0 if we obtained the mailbox lock + **/ +static int mucse_obtain_mbx_lock_pf(struct mucse_hw *hw, enum MBX_ID mbx_i= d) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int try_cnt =3D 5000, ret; + u32 reg; + + reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_MBOX_CTRL(mbx) : + PF2VF_MBOX_CTRL(mbx, mbx_id); + while (try_cnt-- > 0) { + /* Take ownership of the buffer */ + mbx_wr32(hw, reg, MBOX_PF_HOLD); + /* force write back before check */ + wmb(); + if (mbx_rd32(hw, reg) & MBOX_PF_HOLD) + return 0; + udelay(100); + } + return ret; +} + +/** + * mucse_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to write + * + * This function maybe used in an irq handler. + * + * @return: 0 if it successfully copied message into the buffer + **/ +static int mucse_write_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 data_reg, ctrl_reg; + int ret_val =3D 0; + u16 i; + + data_reg =3D (mbx_id =3D=3D MBX_FW) ? FW_PF_SHM_DATA(mbx) : + PF_VF_SHM_DATA(mbx, mbx_id); + ctrl_reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_MBOX_CTRL(mbx) : + PF2VF_MBOX_CTRL(mbx, mbx_id); + if (size > MUCSE_VFMAILBOX_SIZE) + return -EINVAL; + + /* lock the mailbox to prevent pf/vf/fw race condition */ + ret_val =3D mucse_obtain_mbx_lock_pf(hw, mbx_id); + if (ret_val) + goto out_no_write; + + /* copy the caller specified message to the mailbox memory buffer */ + for (i =3D 0; i < size; i++) + mbx_wr32(hw, data_reg + i * 4, msg[i]); + + /* flush msg and acks as we are overwriting the message buffer */ + if (mbx_id =3D=3D MBX_FW) { + hw->mbx.fw_ack =3D mucse_mbx_get_ack(hw, FW2PF_COUNTER(mbx)); + } else { + hw->mbx.vf_ack[mbx_id] =3D + mucse_mbx_get_ack(hw, VF2PF_COUNTER(mbx, mbx_id)); + } + mucse_mbx_inc_pf_req(hw, mbx_id); + + /* Interrupt VF/FW to tell it a message + * has been sent and release buffer + */ + if (mbx->mbx_feature & MBX_FEATURE_WRITE_DELAY) + udelay(300); + mbx_wr32(hw, ctrl_reg, MBOX_CTRL_REQ); + +out_no_write: + return ret_val; +} + +/** + * mucse_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: Id of vf/fw to read + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a vf/fw request so no polling for message is needed. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_read_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 data_reg, ctrl_reg; + int ret_val; + u32 i; + + data_reg =3D (mbx_id =3D=3D MBX_FW) ? FW_PF_SHM_DATA(mbx) : + PF_VF_SHM_DATA(mbx, mbx_id); + ctrl_reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_MBOX_CTRL(mbx) : + PF2VF_MBOX_CTRL(mbx, mbx_id); + + if (size > MUCSE_VFMAILBOX_SIZE) + return -EINVAL; + /* lock the mailbox to prevent pf/vf race condition */ + ret_val =3D mucse_obtain_mbx_lock_pf(hw, mbx_id); + if (ret_val) + goto out_no_read; + + /* we need this */ + mb(); + /* copy the message from the mailbox memory buffer */ + for (i =3D 0; i < size; i++) + msg[i] =3D mbx_rd32(hw, data_reg + 4 * i); + mbx_wr32(hw, data_reg, 0); + + /* update req */ + if (mbx_id =3D=3D MBX_FW) { + hw->mbx.fw_req =3D mucse_mbx_get_req(hw, FW2PF_COUNTER(mbx)); + } else { + hw->mbx.vf_req[mbx_id] =3D + mucse_mbx_get_req(hw, VF2PF_COUNTER(mbx, mbx_id)); + } + /* Acknowledge receipt and release mailbox, then we're done */ + mucse_mbx_inc_pf_ack(hw, mbx_id); + /* free ownership of the buffer */ + mbx_wr32(hw, ctrl_reg, 0); + +out_no_read: + return ret_val; +} + +/** + * mucse_mbx_reset - reset mbx info, sync info from regs + * @hw: Pointer to the HW structure + * + * This function reset all mbx variables to default. + **/ +static void mucse_mbx_reset(struct mucse_hw *hw) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int idx, v; + + for (idx =3D 0; idx < hw->max_vfs; idx++) { + v =3D mbx_rd32(hw, VF2PF_COUNTER(mbx, idx)); + hw->mbx.vf_req[idx] =3D v & GENMASK(15, 0); + hw->mbx.vf_ack[idx] =3D (v >> 16) & GENMASK(15, 0); + mbx_wr32(hw, PF2VF_MBOX_CTRL(mbx, idx), 0); + } + v =3D mbx_rd32(hw, FW2PF_COUNTER(mbx)); + hw->mbx.fw_req =3D v & GENMASK(15, 0); + hw->mbx.fw_ack =3D (v >> 16) & GENMASK(15, 0); + + mbx_wr32(hw, PF2FW_MBOX_CTRL(mbx), 0); + + if (PF_VF_MBOX_MASK_LO(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_LO(mbx), 0); + if (PF_VF_MBOX_MASK_HI(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_HI(mbx), 0); + + mbx_wr32(hw, FW_PF_MBOX_MASK(mbx), GENMASK(31, 16)); +} + +/** + * mucse_mbx_configure_pf - configure mbx to use nr_vec interrupt + * @hw: Pointer to the HW structure + * @nr_vec: Vector number for mbx + * @enable: TRUE for enable, FALSE for disable + * + * This function configure mbx to use interrupt nr_vec. + **/ +static void mucse_mbx_configure_pf(struct mucse_hw *hw, int nr_vec, + bool enable) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + int idx =3D 0; + u32 v; + + if (enable) { + for (idx =3D 0; idx < hw->max_vfs; idx++) { + v =3D mbx_rd32(hw, VF2PF_COUNTER(mbx, idx)); + hw->mbx.vf_req[idx] =3D v & GENMASK(15, 0); + hw->mbx.vf_ack[idx] =3D (v >> 16) & GENMASK(15, 0); + + mbx_wr32(hw, PF2VF_MBOX_CTRL(mbx, idx), 0); + } + v =3D mbx_rd32(hw, FW2PF_COUNTER(mbx)); + hw->mbx.fw_req =3D v & GENMASK(15, 0); + hw->mbx.fw_ack =3D (v >> 16) & GENMASK(15, 0); + mbx_wr32(hw, PF2FW_MBOX_CTRL(mbx), 0); + + for (idx =3D 0; idx < hw->max_vfs; idx++) { + /* vf to pf req interrupt */ + mbx_wr32(hw, VF2PF_MBOX_VEC(mbx, idx), + nr_vec); + } + + if (PF_VF_MBOX_MASK_LO(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_LO(mbx), 0); + /* allow vf to vectors */ + + if (PF_VF_MBOX_MASK_HI(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_HI(mbx), 0); + /* enable irq */ + /* bind fw mbx to irq */ + mbx_wr32(hw, FW2PF_MBOX_VEC(mbx), nr_vec); + /* allow CM3FW to PF MBX IRQ */ + mbx_wr32(hw, FW_PF_MBOX_MASK(mbx), GENMASK(31, 16)); + } else { + if (PF_VF_MBOX_MASK_LO(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_LO(mbx), + GENMASK(31, 0)); + /* disable irq */ + if (PF_VF_MBOX_MASK_HI(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_HI(mbx), + GENMASK(31, 0)); + + /* disable CM3FW to PF MBX IRQ */ + mbx_wr32(hw, FW_PF_MBOX_MASK(mbx), 0xfffffffe); + + /* reset vf->pf status/ctrl */ + for (idx =3D 0; idx < hw->max_vfs; idx++) + mbx_wr32(hw, PF2VF_MBOX_CTRL(mbx, idx), 0); + /* reset pf->cm3 ctrl */ + mbx_wr32(hw, PF2FW_MBOX_CTRL(mbx), 0); + /* used to sync link status */ + mbx_wr32(hw, RNPGBE_DMA_DUMY, 0); + } +} + +/** + * mucse_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for pf mailbox + */ +static void mucse_init_mbx_params_pf(struct mucse_hw *hw) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + + mbx->usec_delay =3D 100; + mbx->timeout =3D (4 * 1000 * 1000) / mbx->usec_delay; + mbx->stats.msgs_tx =3D 0; + mbx->stats.msgs_rx =3D 0; + mbx->stats.reqs =3D 0; + mbx->stats.acks =3D 0; + mbx->stats.rsts =3D 0; + mbx->size =3D MUCSE_VFMAILBOX_SIZE; + + mutex_init(&mbx->lock); + mucse_mbx_reset(hw); +} + +struct mucse_mbx_operations mucse_mbx_ops_generic =3D { + .init_params =3D mucse_init_mbx_params_pf, + .read =3D mucse_read_mbx_pf, + .write =3D mucse_write_mbx_pf, + .read_posted =3D mucse_read_posted_mbx, + .write_posted =3D mucse_write_posted_mbx, + .check_for_msg =3D mucse_check_for_msg_pf, + .check_for_ack =3D mucse_check_for_ack_pf, + .configure =3D mucse_mbx_configure_pf, +}; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_mbx.h new file mode 100644 index 000000000000..0b4183e53e61 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_MBX_H +#define _RNPGBE_MBX_H + +#include "rnpgbe.h" + +/* 14 words */ +#define MUCSE_VFMAILBOX_SIZE 14 +/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D PF <--> VF mailbox =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */ +#define SHARE_MEM_BYTES 64 +static inline u32 PF_VF_SHM(struct mucse_mbx_info *mbx, int vf) +{ + return mbx->pf_vf_shm_base + mbx->mbx_mem_size * vf; +} + +#define PF2VF_COUNTER(mbx, vf) (PF_VF_SHM(mbx, vf) + 0) +#define VF2PF_COUNTER(mbx, vf) (PF_VF_SHM(mbx, vf) + 4) +#define PF_VF_SHM_DATA(mbx, vf) (PF_VF_SHM(mbx, vf) + 8) +#define VF2PF_MBOX_VEC(mbx, vf) ((mbx)->vf2pf_mbox_vec_base + 4 * (vf)) +#define PF2VF_MBOX_CTRL(mbx, vf) ((mbx)->pf2vf_mbox_ctrl_base + 4 * (vf)) +#define PF_VF_MBOX_MASK_LO(mbx) ((mbx)->pf_vf_mbox_mask_lo) +#define PF_VF_MBOX_MASK_HI(mbx) ((mbx)->pf_vf_mbox_mask_hi) +/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D PF <--> FW mailbox =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */ +#define FW_PF_SHM(mbx) ((mbx)->fw_pf_shm_base) +#define FW2PF_COUNTER(mbx) (FW_PF_SHM(mbx) + 0) +#define PF2FW_COUNTER(mbx) (FW_PF_SHM(mbx) + 4) +#define FW_PF_SHM_DATA(mbx) (FW_PF_SHM(mbx) + 8) +#define FW2PF_MBOX_VEC(mbx) ((mbx)->fw2pf_mbox_vec) +#define PF2FW_MBOX_CTRL(mbx) ((mbx)->pf2fw_mbox_ctrl) +#define FW_PF_MBOX_MASK(mbx) ((mbx)->fw_pf_mbox_mask) +#define MBOX_CTRL_REQ BIT(0) /* WO */ +#define MBOX_PF_HOLD (BIT(3)) /* VF:RO, PF:WR */ +#define MBOX_IRQ_EN 0 +#define MBOX_IRQ_DISABLE 1 +#define mbx_rd32(hw, reg) m_rd_reg((hw)->hw_addr + (reg)) +#define mbx_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) + +extern struct mucse_mbx_operations mucse_mbx_ops_generic; + +int mucse_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id); +int mucse_write_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id); +int mucse_check_for_msg(struct mucse_hw *hw, enum MBX_ID mbx_id); +int mucse_check_for_ack(struct mucse_hw *hw, enum MBX_ID mbx_id); +#endif /* _RNPGBE_MBX_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46A202BF00A; Mon, 21 Jul 2025 11:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.194.254.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097676; cv=none; b=jurBh5bdupMQRVxkoDLaQKOVkotk0Ftb4j+ddEStF6lXcLDtDjdHQs5j0krvu4P/rsg9nQBcFMGPVGPIOPUV74bqQmpnSSsq1HYuh2QGmmKVdgP07f00eheDtK6njR6c8kO4nf9N6qOQVOfGlNzoThMSTi3MwNND56xlRcVEJxM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097676; c=relaxed/simple; bh=/5tRiCruW16YP1EWsW8VPd7uw4Tx08ZfkHHwSdGir/s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ufN95sszPPxcBqBKYHyt1vW4+PjB+RTGrloRCUYVdM2HRNCc+zzAH9coTspi/ATjD9YNmMIjTWXvKiPXuJuOCG7ZUVfRKizj5llR1x8y4Snz9LqTUTWZ9OpvMrLykh8lcbnpH4PIYdSQYtBNb648zhq42IoGAHmWpkvg7Liiqcs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=18.194.254.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097585ta82c196e X-QQ-Originating-IP: ojWMH25vXFN9Vox2NJyof+ppRKgPqk+huNUdYYgAAbM= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:02 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 6991744939570703964 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support Date: Mon, 21 Jul 2025 19:32:27 +0800 Message-Id: <20250721113238.18615-5-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: OaT+pqEEl7HNweYJmzPIevHrkn399SWQl+jtYNTXSqdSU6C6CA6q9sVn avrXck3kWku46q3RBBBTwk5Au9cg6AmrXftMckfZNm0zsrIHzqu7MjgQfINNqvYgGDAMZp5 GzpKioKHuYRRXY+iwWVZ0x4eLvB67J9sqe7caPIet0SK14p7+6oYOnDsWGiitGDQjBIM9Vu mL1OXvriFa7HLlLLlQVGO2/Q+GPftZ3woJAFuS5THVX6yhx5qfFYbjtw8pIRij2jax9bq31 FJxTU/lmNxCNFTKaXLKWaCmHzs4MVRrCCT8x2K3dQMPT84gUlLWBnXYXJ2G+FYs698s+oz0 pkMb4pwwjwfzyWOL2gkUwq0SXbPz6HkMsG53hGgzcoliMi2a3O9Ipb0DTSpqMoMCrRem32q f4fR4auCrjf8fLhJXbn8JJiQEWFF/moILCPlBGYiMRE1KR5xbN7ntXBPWgnhRR8lUvCddTy KmrKnJVX+kQsK8RWZoCRner2rh7eao2dP3sbRMZTrz35SBTThaGlDKRVPDIRR7kbNLPAHYm 5+nDa7i495B6OzLBnT3eTHo9ZXkZbxvQkNCPzS3S8vx0TkQ2y4ZDlT3fZFbNhxNIG7VkbIY PrXLLRiVwtoXGbz4o7s+LwHYCROacz76afysfjISMbU2E2lRH1kpMP0Uq5XX2Nbqgj5B3cM P8QvVCwTO1b6rs7O7PojeYag9//p5NnpVIXNI3ln6ICsCqzMyiUYI3tg2qgF91aL1qv7LsZ V3EgpbMNmswYYT1Yju363GfA8SIF+TRwrxDWV4U0sOGeG9oGg6YIIWPdD6pkJfJeInPj32B Kh84+0Nu7vPhJnl2jtvwy7VzDJfUqVDcB4tNe7acJaRrMpMwBQKm8WImUIH3nAru9pHCku6 wiwAbxr0y6PGIUq26/QM/NZ3u4WhHQ7HC/YGczHNbfxB/OnjBYLBL5Xf8xz0Uc05pGOshkR pbDNgscJzKRBCQskRDU5VH4rPZs5/BYCC00TQDGLJznCq5N4ldBU//nTW6J3DG5G1yp9gRG RT06jP5pXFNaqyVEYYh9twGTE+nJCIDqDahF31tF/pR9wN8AXw X-QQ-XMRINFO: NI4Ajvh11aEj8Xl/2s1/T8w= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize get hw capability from mbx_fw ops. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/Makefile | 3 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 8 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 8 + .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 140 +++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 568 ++++++++++++++++++ 5 files changed, 726 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile index 41177103b50c..fd455cb111a9 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_MGBE) +=3D rnpgbe.o rnpgbe-objs :=3D rnpgbe_main.o \ rnpgbe_chip.o \ - rnpgbe_mbx.o + rnpgbe_mbx.o \ + rnpgbe_mbx_fw.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 46e2bb2fe71e..4514bc1223c1 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -154,6 +154,14 @@ struct mucse_hw { u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; + u32 wol; + u32 wol_en; + u32 fw_version; + u32 axi_mhz; + u32 bd_uid; + int ncsi_en; + int force_en; + int force_cap; int max_vfs; int max_vfs_noari; enum rnpgbe_hw_type hw_type; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 1e8360cae560..aeb560145c47 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -9,6 +9,7 @@ #include =20 #include "rnpgbe.h" +#include "rnpgbe_mbx_fw.h" =20 char rnpgbe_driver_name[] =3D "rnpgbe"; static const struct rnpgbe_info *rnpgbe_info_tbl[] =3D { @@ -116,6 +117,13 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, ii->get_invariants(hw); hw->mbx.ops.init_params(hw); =20 + err =3D mucse_mbx_get_capability(hw); + if (err) { + dev_err(&pdev->dev, + "mucse_mbx_get_capability failed!\n"); + goto err_free_net; + } + return 0; =20 err_free_net: diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c new file mode 100644 index 000000000000..1674229fcd43 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#include + +#include "rnpgbe_mbx_fw.h" + +/** + * mucse_fw_send_cmd_wait - Send cmd req and wait for response + * @hw: Pointer to the HW structure + * @req: Pointer to the cmd req structure + * @reply: Pointer to the fw reply structure + * + * mucse_fw_send_cmd_wait sends req to pf-fw mailbox and wait + * reply from fw. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_fw_send_cmd_wait(struct mucse_hw *hw, + struct mbx_fw_cmd_req *req, + struct mbx_fw_cmd_reply *reply) +{ + int len =3D le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN; + int retry_cnt =3D 3; + int err; + + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)req, + L_WD(len), + MBX_FW); + if (err) { + mutex_unlock(&hw->mbx.lock); + return err; + } + +retry: + retry_cnt--; + if (retry_cnt < 0) + return -EIO; + + err =3D hw->mbx.ops.read_posted(hw, (u32 *)reply, + L_WD(sizeof(*reply)), + MBX_FW); + if (err) { + mutex_unlock(&hw->mbx.lock); + return err; + } + + if (reply->opcode !=3D req->opcode) + goto retry; + + mutex_unlock(&hw->mbx.lock); + + if (reply->error_code) + return -EIO; + + return 0; +} + +/** + * mucse_fw_get_capability - Get hw abilities from fw + * @hw: Pointer to the HW structure + * @abil: Pointer to the hw_abilities structure + * + * mucse_fw_get_capability tries to get hw abilities from + * hw. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_fw_get_capability(struct mucse_hw *hw, + struct hw_abilities *abil) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int err =3D 0; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_phy_abalities_req(&req, &req); + err =3D mucse_fw_send_cmd_wait(hw, &req, &reply); + if (err =3D=3D 0) + memcpy(abil, &reply.hw_abilities, sizeof(*abil)); + + return err; +} + +/** + * mucse_mbx_get_capability - Get hw abilities from fw + * @hw: Pointer to the HW structure + * + * mucse_mbx_get_capability tries to some capabities from + * hw. Many retrys will do if it is failed. + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_get_capability(struct mucse_hw *hw) +{ + struct hw_abilities ability; + int try_cnt =3D 3; + int err =3D 0; + + memset(&ability, 0, sizeof(ability)); + + while (try_cnt--) { + err =3D mucse_fw_get_capability(hw, &ability); + if (err =3D=3D 0) { + u16 nic_mode =3D le16_to_cpu(ability.nic_mode); + u32 wol =3D le32_to_cpu(ability.wol_status); + + hw->ncsi_en =3D (nic_mode & 0x4) ? 1 : 0; + hw->pfvfnum =3D le16_to_cpu(ability.pfnum); + hw->fw_version =3D le32_to_cpu(ability.fw_version); + hw->axi_mhz =3D le32_to_cpu(ability.axi_mhz); + hw->bd_uid =3D le32_to_cpu(ability.bd_uid); + + if (hw->fw_version >=3D 0x0001012C) { + /* this version can get wol_en from hw */ + hw->wol =3D wol & 0xff; + hw->wol_en =3D wol & 0x100; + } else { + /* other version only pf0 or ncsi can wol */ + hw->wol =3D wol & 0xff; + if (hw->ncsi_en || !hw->pfvfnum) + hw->wol_en =3D 1; + } + /* 0.1.5.0 can get force status from fw */ + if (hw->fw_version >=3D 0x00010500) { + ability_update_host_endian(&ability); + hw->force_en =3D ability.e_host.force_down_en; + hw->force_cap =3D 1; + } + return 0; + } + } + + return err; +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h new file mode 100644 index 000000000000..a24c5d4e0075 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -0,0 +1,568 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_MBX_FW_H +#define _RNPGBE_MBX_FW_H + +#include +#include +#include + +#include "rnpgbe.h" + +#define MBX_REQ_HDR_LEN 24 +#define L_WD(x) ((x) / 4) + +struct mbx_fw_cmd_reply; +typedef void (*cookie_cb)(struct mbx_fw_cmd_reply *reply, void *priv); + +struct mbx_req_cookie { + int magic; +#define COOKIE_MAGIC 0xCE + cookie_cb cb; + int timeout_jiffes; + int errcode; + wait_queue_head_t wait; + int done; + int priv_len; + char priv[]; +}; + +enum MUCSE_FW_CMD { + GET_VERSION =3D 0x0001, + READ_REG =3D 0xFF03, + WRITE_REG =3D 0xFF04, + MODIFY_REG =3D 0xFF07, + IFUP_DOWN =3D 0x0800, + SEND_TO_PF =3D 0x0801, + SEND_TO_VF =3D 0x0802, + DRIVER_INSMOD =3D 0x0803, + SYSTEM_SUSPUSE =3D 0x0804, + SYSTEM_FORCE =3D 0x0805, + GET_PHY_ABALITY =3D 0x0601, + GET_MAC_ADDRES =3D 0x0602, + RESET_PHY =3D 0x0603, + LED_SET =3D 0x0604, + GET_LINK_STATUS =3D 0x0607, + LINK_STATUS_EVENT =3D 0x0608, + SET_LANE_FUN =3D 0x0609, + GET_LANE_STATUS =3D 0x0610, + SFP_SPEED_CHANGED_EVENT =3D 0x0611, + SET_EVENT_MASK =3D 0x0613, + SET_LOOPBACK_MODE =3D 0x0618, + SET_PHY_REG =3D 0x0628, + GET_PHY_REG =3D 0x0629, + PHY_LINK_SET =3D 0x0630, + GET_PHY_STATISTICS =3D 0x0631, + PHY_PAUSE_SET =3D 0x0632, + PHY_PAUSE_GET =3D 0x0633, + PHY_EEE_SET =3D 0x0636, + PHY_EEE_GET =3D 0x0637, + SFP_MODULE_READ =3D 0x0900, + SFP_MODULE_WRITE =3D 0x0901, + FW_UPDATE =3D 0x0700, + FW_MAINTAIN =3D 0x0701, + FW_UPDATE_GBE =3D 0x0702, + WOL_EN =3D 0x0910, + GET_DUMP =3D 0x0a00, + SET_DUMP =3D 0x0a10, + GET_TEMP =3D 0x0a11, + SET_WOL =3D 0x0a12, + SET_TEST_MODE =3D 0x0a13, + SHOW_TX_STAMP =3D 0x0a14, + LLDP_TX_CTRL =3D 0x0a15, +}; + +struct hw_abilities { + u8 link_stat; + u8 lane_mask; + __le32 speed; + __le16 phy_type; + __le16 nic_mode; + __le16 pfnum; + __le32 fw_version; + __le32 axi_mhz; + union { + u8 port_id[4]; + __le32 port_ids; + }; + __le32 bd_uid; + __le32 phy_id; + __le32 wol_status; + union { + __le32 ext_ability; + struct { + __le32 valid : 1; /* 0 */ + __le32 wol_en : 1; /* 1 */ + __le32 pci_preset_runtime_en : 1; /* 2 */ + __le32 smbus_en : 1; /* 3 */ + __le32 ncsi_en : 1; /* 4 */ + __le32 rpu_en : 1; /* 5 */ + __le32 v2 : 1; /* 6 */ + __le32 pxe_en : 1; /* 7 */ + __le32 mctp_en : 1; /* 8 */ + __le32 yt8614 : 1; /* 9 */ + __le32 pci_ext_reset : 1; /* 10 */ + __le32 rpu_availble : 1; /* 11 */ + __le32 fw_lldp_ability : 1; /* 12 */ + __le32 lldp_enabled : 1; /* 13 */ + __le32 only_1g : 1; /* 14 */ + __le32 force_down_en: 1; /* 15 */ + } e; + struct { + u32 valid : 1; /* 0 */ + u32 wol_en : 1; /* 1 */ + u32 pci_preset_runtime_en : 1; /* 2 */ + u32 smbus_en : 1; /* 3 */ + u32 ncsi_en : 1; /* 4 */ + u32 rpu_en : 1; /* 5 */ + u32 v2 : 1; /* 6 */ + u32 pxe_en : 1; /* 7 */ + u32 mctp_en : 1; /* 8 */ + u32 yt8614 : 1; /* 9 */ + u32 pci_ext_reset : 1; /* 10 */ + u32 rpu_availble : 1; /* 11 */ + u32 fw_lldp_ability : 1; /* 12 */ + u32 lldp_enabled : 1; /* 13 */ + u32 only_1g : 1; /* 14 */ + u32 force_down_en: 1; /* 15 */ + } e_host; + }; +} __packed; + +static inline void ability_update_host_endian(struct hw_abilities *abi) +{ + u32 host_val =3D le32_to_cpu(abi->ext_ability); + + abi->e_host =3D *(typeof(abi->e_host) *)&host_val; +} + +struct phy_pause_data { + u32 pause_mode; +}; + +struct lane_stat_data { + u8 nr_lane; + u8 pci_gen : 4; + u8 pci_lanes : 4; + u8 pma_type; + u8 phy_type; + __le16 linkup : 1; + __le16 duplex : 1; + __le16 autoneg : 1; + __le16 fec : 1; + __le16 an : 1; + __le16 link_traing : 1; + __le16 media_availble : 1; + __le16 is_sgmii : 1; + __le16 link_fault : 4; +#define LINK_LINK_FAULT BIT(0) +#define LINK_TX_FAULT BIT(1) +#define LINK_RX_FAULT BIT(2) +#define LINK_REMOTE_FAULT BIT(3) + __le16 is_backplane : 1; + __le16 tp_mdx : 2; + union { + u8 phy_addr; + struct { + u8 mod_abs : 1; + u8 fault : 1; + u8 tx_dis : 1; + u8 los : 1; + } sfp; + }; + u8 sfp_connector; + __le32 speed; + __le32 si_main; + __le32 si_pre; + __le32 si_post; + __le32 si_tx_boost; + __le32 supported_link; + __le32 phy_id; + __le32 advertised_link; +} __packed; + +struct yt_phy_statistics { + __le32 pkg_ib_valid; /* rx crc good and length 64-1518 */ + __le32 pkg_ib_os_good; /* rx crc good and length >1518 */ + __le32 pkg_ib_us_good; /* rx crc good and length <64 */ + __le16 pkg_ib_err; /* rx crc wrong and length 64-1518 */ + __le16 pkg_ib_os_bad; /* rx crc wrong and length >1518 */ + __le16 pkg_ib_frag; /* rx crc wrong and length <64 */ + __le16 pkg_ib_nosfd; /* rx sfd missed */ + __le32 pkg_ob_valid; /* tx crc good and length 64-1518 */ + __le32 pkg_ob_os_good; /* tx crc good and length >1518 */ + __le32 pkg_ob_us_good; /* tx crc good and length <64 */ + __le16 pkg_ob_err; /* tx crc wrong and length 64-1518 */ + __le16 pkg_ob_os_bad; /* tx crc wrong and length >1518 */ + __le16 pkg_ob_frag; /* tx crc wrong and length <64 */ + __le16 pkg_ob_nosfd; /* tx sfd missed */ +} __packed; + +struct phy_statistics { + union { + struct yt_phy_statistics yt; + }; +} __packed; + +struct port_stat { + u8 phyid; + u8 duplex : 1; + u8 autoneg : 1; + u8 fec : 1; + __le16 speed; + union { + __le16 stat; + struct { + __le16 pause : 4; + __le16 local_eee : 3; + __le16 partner_eee : 3; + __le16 tp_mdx : 2; + __le16 lldp_status : 1; + __le16 revs : 3; + } v; + struct { + u16 pause : 4; + u16 local_eee : 3; + u16 partner_eee : 3; + u16 tp_mdx : 2; + u16 lldp_status : 1; + u16 revs : 3; + } v_host; + }; +} __packed; + +#define FLAGS_DD BIT(0) /* driver clear 0, FW must set 1 */ +/* driver clear 0, FW must set only if it reporting an error */ +#define FLAGS_ERR BIT(2) + +/* req is little endian. bigendian should be conserened */ +struct mbx_fw_cmd_req { + __le16 flags; /* 0-1 */ + __le16 opcode; /* 2-3 enum GENERIC_CMD */ + __le16 datalen; /* 4-5 */ + __le16 ret_value; /* 6-7 */ + union { + struct { + __le32 cookie_lo; /* 8-11 */ + __le32 cookie_hi; /* 12-15 */ + }; + + void *cookie; + }; + __le32 reply_lo; /* 16-19 5dw */ + __le32 reply_hi; /* 20-23 */ + union { + u8 data[32]; + struct { + __le32 addr; + __le32 bytes; + } r_reg; + + struct { + __le32 addr; + __le32 bytes; + __le32 data[4]; + } w_reg; + + struct { + __le32 lanes; + } ptp; + + struct { + __le32 lane; + __le32 up; + } ifup; + + struct { + __le32 sec; + __le32 nanosec; + + } tstamps; + + struct { + __le32 lane; + __le32 status; + } ifinsmod; + + struct { + __le32 lane; + __le32 status; + } ifforce; + + struct { + __le32 lane; + __le32 status; + } ifsuspuse; + + struct { + __le32 nr_lane; + } get_lane_st; + + struct { + __le32 nr_lane; + __le32 func; +#define LANE_FUN_AN 0 +#define LANE_FUN_LINK_TRAING 1 +#define LANE_FUN_FEC 2 +#define LANE_FUN_SI 3 +#define LANE_FUN_SFP_TX_DISABLE 4 +#define LANE_FUN_PCI_LANE 5 +#define LANE_FUN_PRBS 6 +#define LANE_FUN_SPEED_CHANGE 7 + __le32 value0; + __le32 value1; + __le32 value2; + __le32 value3; + } set_lane_fun; + + struct { + __le32 flag; + __le32 nr_lane; + } set_dump; + + struct { + __le32 lane; + __le32 enable; + } wol; + + struct { + __le32 lane; + __le32 mode; + } gephy_test; + + struct { + __le32 lane; + __le32 op; + __le32 enable; + __le32 inteval; + } lldp_tx; + + struct { + __le32 bytes; + __le32 nr_lane; + __le32 bin_offset; + __le32 no_use; + } get_dump; + + struct { + __le32 nr_lane; + __le32 value; +#define LED_IDENTIFY_INACTIVE 0 +#define LED_IDENTIFY_ACTIVE 1 +#define LED_IDENTIFY_ON 2 +#define LED_IDENTIFY_OFF 3 + } led_set; + + struct { + __le32 addr; + __le32 data; + __le32 mask; + } modify_reg; + + struct { + __le32 adv_speed_mask; + __le32 autoneg; + __le32 speed; + __le32 duplex; + __le32 nr_lane; + __le32 tp_mdix_ctrl; + } phy_link_set; + + struct { + __le32 pause_mode; + __le32 nr_lane; + } phy_pause_set; + + struct { + __le32 pause_mode; + __le32 nr_lane; + } phy_pause_get; + + struct { + __le32 local_eee; + __le32 tx_lpi_timer; + __le32 nr_lane; + } phy_eee_set; + + struct { + __le32 nr_lane; + __le32 sfp_adr; /* 0xa0 or 0xa2 */ + __le32 reg; + __le32 cnt; + } sfp_read; + + struct { + __le32 nr_lane; + __le32 sfp_adr; /* 0xa0 or 0xa2 */ + __le32 reg; + __le32 val; + } sfp_write; + + struct { + __le32 nr_lane; /* 0-3 */ + } get_linkstat; + + struct { + __le16 changed_lanes; + __le16 lane_status; + __le32 port_st_magic; +#define SPEED_VALID_MAGIC 0xa4a6a8a9 + struct port_stat st[4]; + } link_stat; /* FW->RC */ + + struct { + __le16 enable_stat; + __le16 event_mask; + } stat_event_mask; + + struct { + __le32 cmd; + __le32 arg0; + __le32 req_bytes; + __le32 reply_bytes; + __le32 ddr_lo; + __le32 ddr_hi; + } maintain; + + struct { /* set phy register */ + u8 phy_interface; + union { + u8 page_num; + u8 external_phy_addr; + }; + __le32 phy_reg_addr; + __le32 phy_w_data; + __le32 reg_addr; + __le32 w_data; + /* 1 =3D ignore page_num, use last QSFP */ + u8 recall_qsfp_page : 1; + /* page value */ + /* 0 =3D use page_num for QSFP */ + u8 nr_lane; + } set_phy_reg; + + struct { + __le32 lane_mask; + __le32 pfvf_num; + } get_mac_addr; + + struct { + u8 phy_interface; + union { + u8 page_num; + u8 external_phy_addr; + }; + __le32 phy_reg_addr; + u8 nr_lane; + } get_phy_reg; + + struct { + __le32 nr_lane; + } phy_statistics; + + struct { + u8 paration; + __le32 bytes; + __le32 bin_phy_lo; + __le32 bin_phy_hi; + } fw_update; + }; +} __packed; + +#define EEE_1000BT BIT(2) +#define EEE_100BT BIT(1) + +struct rnpgbe_eee_cap { + __le32 local_capability; + __le32 local_eee; + __le32 partner_eee; +}; + +/* firmware -> driver */ +struct mbx_fw_cmd_reply { + /* fw must set: DD, CMP, Error(if error), copy value */ + __le16 flags; + /* from command: LB,RD,VFC,BUF,SI,EI,FE */ + __le16 opcode; /* 2-3: copy from req */ + __le16 error_code; /* 4-5: 0 if no error */ + __le16 datalen; /* 6-7: */ + union { + struct { + __le32 cookie_lo; /* 8-11: */ + __le32 cookie_hi; /* 12-15: */ + }; + void *cookie; + }; + /* =3D=3D=3D=3D=3D data =3D=3D=3D=3D [16-64] */ + union { + u8 data[40]; + + struct version { + __le32 major; + __le32 sub; + __le32 modify; + } version; + + struct { + __le32 value[4]; + } r_reg; + + struct { + __le32 new_value; + } modify_reg; + + struct get_temp { + __le32 temp; + __le32 volatage; + } get_temp; + + struct { +#define MBX_SFP_READ_MAX_CNT 32 + u8 value[MBX_SFP_READ_MAX_CNT]; + } sfp_read; + + struct mac_addr { + __le32 lanes; + struct _addr { + /* + * for macaddr:01:02:03:04:05:06 + * mac-hi=3D0x01020304 mac-lo=3D0x05060000 + */ + u8 mac[8]; + } addrs[4]; + } mac_addr; + + struct get_dump_reply { + __le32 flags; + __le32 version; + __le32 bytes; + __le32 data[4]; + } get_dump; + + struct get_lldp_reply { + __le32 value; + __le32 inteval; + } get_lldp; + + struct rnpgbe_eee_cap phy_eee_abilities; + struct lane_stat_data lanestat; + struct hw_abilities hw_abilities; + struct phy_statistics phy_statistics; + }; +} __packed; + +static inline void build_phy_abalities_req(struct mbx_fw_cmd_req *req, + void *cookie) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(GET_PHY_ABALITY); + req->datalen =3D 0; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->cookie =3D cookie; +} + +int mucse_mbx_get_capability(struct mucse_hw *hw); + +#endif /* _RNPGBE_MBX_FW_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbguseast3.qq.com (smtpbguseast3.qq.com [54.243.244.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83F8485C5E; Mon, 21 Jul 2025 11:34:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.243.244.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097673; cv=none; b=kWiR2Okbr/dtg0+Rz54Z0FM4TozSa6iTF6+jLVl/KBD6lgkhGJSWDex9pn34BUqLeHocA5+b1SXBBnjTY6IyV5aODeygUl3Spabq+8vk2PWsSuTypyRqZKceqk5xtCl7lD0puDFcgc3nTEvwzXN04d7D8xszG10xl4FVaXSWsDk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097673; c=relaxed/simple; bh=QARVXmFDhKHGkAz+aNCzN9wjhcH2VoDGGykDndqLf08=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uAFfbiOHQGSSlykl0hBXVUJWGrlk9pWmKB+9dmwjfSHihxsY/3lvXDjvr4GdvDBEhE4jeCqnZtwlVu7FUJ2ypgz8Lk71Au8hBeq5wMegXQmP6feLZZEiyfRjIevZsBotsUEm+lAiaTIS77s5G1zpIXM1aGShMalf16POcRVvkSI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.243.244.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097590t6f230f0a X-QQ-Originating-IP: bOXwxOcmGXYDuczOHQZkRQUchsl9P/pLlk7DAq06JEU= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:06 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 3178325155967448401 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 05/15] net: rnpgbe: Add download firmware for n210 chip Date: Mon, 21 Jul 2025 19:32:28 +0800 Message-Id: <20250721113238.18615-6-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MYha8DeKTomkDCLz8CmFQCWyDvMtImQ5terAuZ4eaL3zYZ8fTBcB5816 mEEtTIAdba4qS4Xq+mQmKp6zzpm6SVQHhj0eAr78BmYEHw9tvyxvRLT5z7IOi1aYz93FuyU TOHDFWDf8sszU/i3Y5DcmsZwCvdZZoJIt7lZnRKqeLoQcL0RQXgeZTic0rbIOLo/6EM4q4q mGquqCa1EiDEqHTSHzjC2EFExj67xXVtKz5VJZZyGSrwdTj/11O5m/+8qmjId8xUAeVi0Yi DB7VX7sh1mt3cCfgmyf0hTx4SbIL/gOQkvkBfvIBwTx/zgKUIgtCcqQyuZKFSRqEV+UVZn5 pkGP5nPiRm4qfX+FcoRQyAeEj/ttm9faTFPU6oc5jGY0YKcxratq19pnZc1EkwJCHGYQK9+ GmrSke+af2YxsjeqSxFekTSKnQQ37oTZVa6aEor0HxbWUfI0UdI/4TKE+XUDwDwdRQC2Zju jxYZ9JMAN1EtvbLZe48hHG+8No8UMT9NGIea9md8kKgtf611Sj53DEklxqOhAnNI3wyuI/V cDIZpeLHaWxp8rEWh8q8BWB3CyubpGUAhTZdpe1GzjYIMX6WtwIBif3Ve0pOTui3BilDNra p9HoCbLQqXEbxGJ87dkRoVhksvG0nAr+kQJZ4uvvwgcqLICuiRlwcvyIvR15kY5xvFIDUhD AaoK9wpjz3yZOhDVUhiUpH8jwTIuE5z8wFQNHgpa8EGP7p69+vOZq7PhqDQ/L5t/cwdw5Bs XzFWa+iMgNAVghkGsj+7HyXJ1jyqKBPuo7yUoi5wK1RHMVQG2CQXO19L/vBBxTSJWIvskgB kYSS4ByG37o/FfGJWgjpkPK6SK28OjBUi7nDSfes/7ewm18/O1Y6vKlmZ9UQMxKkJofJAaR xtTAH4lrnLDwIK1TWJ0u9fnN5lMQP/IZoP60PFFGxgZnrMxsLEQBAfm+L5JoFCBjjyy9b38 PF+3iZcsnEoHI4ydwQ+2QXsR/xKjYPPd3f4ZIuqxGzMJ7A6tTM3xd/eV/oJQ0KVePt3d+os iEpIE6tA== X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize download fw function for n210 series. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/Kconfig | 1 + drivers/net/ethernet/mucse/rnpgbe/Makefile | 3 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 4 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 18 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c | 476 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_sfc.h | 30 ++ 6 files changed, 529 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.h diff --git a/drivers/net/ethernet/mucse/Kconfig b/drivers/net/ethernet/mucs= e/Kconfig index be0fdf268484..8a0262a70036 100644 --- a/drivers/net/ethernet/mucse/Kconfig +++ b/drivers/net/ethernet/mucse/Kconfig @@ -20,6 +20,7 @@ config MGBE tristate "Mucse(R) 1GbE PCI Express adapters support" depends on PCI select PAGE_POOL + select NET_DEVLINK help This driver supports Mucse(R) 1GbE PCI Express family of adapters. diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile index fd455cb111a9..db7d3a8140b2 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_MGBE) +=3D rnpgbe.o rnpgbe-objs :=3D rnpgbe_main.o \ rnpgbe_chip.o \ rnpgbe_mbx.o \ - rnpgbe_mbx_fw.o + rnpgbe_mbx_fw.o \ + rnpgbe_sfc.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 4514bc1223c1..ea28236669e3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -6,6 +6,7 @@ =20 #include #include +#include =20 extern const struct rnpgbe_info rnpgbe_n500_info; extern const struct rnpgbe_info rnpgbe_n210_info; @@ -195,9 +196,12 @@ struct mucse_hw { struct mucse { struct net_device *netdev; struct pci_dev *pdev; + struct devlink *dl; struct mucse_hw hw; /* board number */ u16 bd_number; + u32 flags2; +#define M_FLAG2_NO_NET_REG BIT(0) =20 char name[60]; }; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index aeb560145c47..61dd0d232d99 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -7,9 +7,11 @@ #include #include #include +#include =20 #include "rnpgbe.h" #include "rnpgbe_mbx_fw.h" +#include "rnpgbe_sfc.h" =20 char rnpgbe_driver_name[] =3D "rnpgbe"; static const struct rnpgbe_info *rnpgbe_info_tbl[] =3D { @@ -76,6 +78,7 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, hw =3D &mucse->hw; hw->back =3D mucse; hw->hw_type =3D ii->hw_type; + hw->pdev =3D pdev; =20 switch (hw->hw_type) { case rnpgbe_hw_n500: @@ -94,8 +97,18 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, case rnpgbe_hw_n210: case rnpgbe_hw_n210L: /* check bar0 to load firmware */ - if (pci_resource_len(pdev, 0) =3D=3D 0x100000) - return -EIO; + if (pci_resource_len(pdev, 0) =3D=3D 0x100000) { + hw->hw_addr =3D ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + + if (!hw->hw_addr) { + dev_err(&pdev->dev, "map bar0 failed!\n"); + return -EIO; + } + rnpgbe_devlink_register(mucse); + mucse->flags2 |=3D M_FLAG2_NO_NET_REG; + return 0; + } /* n210 use bar2 */ hw_addr =3D devm_ioremap(&pdev->dev, pci_resource_start(pdev, 2), @@ -191,6 +204,7 @@ static void rnpgbe_rm_adapter(struct mucse *mucse) { struct net_device *netdev; =20 + rnpgbe_devlink_unregister(mucse); netdev =3D mucse->netdev; free_netdev(netdev); } diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_sfc.c new file mode 100644 index 000000000000..91a637b3ac19 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ + +#include +#include +#include + +#include "rnpgbe_sfc.h" +#include "rnpgbe.h" + +/** + * mucse_sfc_command - Write sfc cmd to hw and wait ok + * @hw_addr: bar addr for sfc controller + * @cmd: sfc command + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_command(u8 __iomem *hw_addr, u32 cmd) +{ + int val; + + iowrite32(cmd, (hw_addr + 0x8)); + iowrite32(1, (hw_addr + 0x0)); + + return read_poll_timeout(ioread32, val, !val, + 100, 10000, true, + hw_addr); +} + +/** + * mucse_sfc_flash_write_disable - Enable flash cmd protect + * @hw_addr: bar addr for sfc controller + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_flash_write_disable(u8 __iomem *hw_addr) +{ + iowrite32(CMD_CYCLE(8), (hw_addr + 0x10)); + iowrite32(WR_DATA_CYCLE(0), (hw_addr + 0x14)); + + return mucse_sfc_command(hw_addr, CMD_WRITE_DISABLE); +} + +/** + * mucse_sfc_flash_wait_idle - Wait sfc controller idle + * @hw_addr: bar addr for sfc controller + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_flash_wait_idle(u8 __iomem *hw_addr) +{ + int try_count =3D 100; + int err, val; + + iowrite32(CMD_CYCLE(8), (hw_addr + 0x10)); + iowrite32(RD_DATA_CYCLE(8), (hw_addr + 0x14)); + +try: + try_count--; + err =3D mucse_sfc_command(hw_addr, CMD_READ_STATUS); + if (err && try_count) + goto try; + err =3D read_poll_timeout(ioread32, val, !(val & 0x1), + 100, 1000, true, + hw_addr + 0x4); + if (err && try_count) + goto try; + + return err; +} + +/** + * mucse_sfc_flash_write_enable - Disable flash cmd protect + * @hw_addr: bar addr for sfc controller + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_flash_write_enable(u8 __iomem *hw_addr) +{ + iowrite32(CMD_CYCLE(8), (hw_addr + 0x10)); + iowrite32(0x1f, (hw_addr + 0x18)); + iowrite32(0x100000, (hw_addr + 0x14)); + + return mucse_sfc_command(hw_addr, CMD_WRITE_ENABLE); +} + +/** + * mucse_sfc_flash_erase_sector - Erase flash sector + * @hw_addr: bar addr for sfc controller + * @address: sector start address + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_flash_erase_sector(u8 __iomem *hw_addr, + u32 address) +{ + int err; + + if (address >=3D RSP_FLASH_HIGH_16M_OFFSET) + return -EINVAL; + + if (address % 4096) + return -EINVAL; + + err =3D mucse_sfc_flash_write_enable(hw_addr); + if (err) + return err; + iowrite32((CMD_CYCLE(8) | ADDR_CYCLE(24)), (hw_addr + 0x10)); + iowrite32((RD_DATA_CYCLE(0) | WR_DATA_CYCLE(0)), (hw_addr + 0x14)); + iowrite32(SFCADDR(address), (hw_addr + 0xc)); + err =3D mucse_sfc_command(hw_addr, CMD_SECTOR_ERASE); + if (err) + return err; + err =3D mucse_sfc_flash_wait_idle(hw_addr); + if (err) + return err; + err =3D mucse_sfc_flash_write_disable(hw_addr); + + return err; +} + +/** + * mucse_sfc_write_protect - set flash write protect off + * @hw: Pointer to the HW structure + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_write_protect(struct mucse_hw *hw) +{ + int err; + + err =3D mucse_sfc_flash_write_enable(hw->hw_addr); + if (err) + return err; + + iowrite32(CMD_CYCLE(8), (hw->hw_addr + 0x10)); + iowrite32(WR_DATA_CYCLE(8), (hw->hw_addr + 0x14)); + iowrite32(0, (hw->hw_addr + 0x04)); + err =3D mucse_sfc_command(hw->hw_addr, CMD_WRITE_STATUS); + + return err; +} + +/** + * mucse_sfc_flash_erase - Erase flash + * @hw: Pointer to the HW structure + * @size: Data length + * + * mucse_sfc_flash_erase tries to erase sfc_flash + * + * @return: 0 on success, negative on failure + **/ +static int mucse_sfc_flash_erase(struct mucse_hw *hw, u32 size) +{ + u32 addr =3D SFC_MEM_BASE; + u32 page_size =3D 0x1000; + u32 i =3D 0; + int err; + + size =3D ((size + (page_size - 1)) / page_size) * page_size; + addr =3D addr - SFC_MEM_BASE; + + if (size =3D=3D 0) + return -EINVAL; + + if ((addr + size) > RSP_FLASH_HIGH_16M_OFFSET) + return -EINVAL; + + if (addr % page_size) + return -EINVAL; + + if (size % page_size) + return -EINVAL; + /* skip some info */ + for (i =3D 0; i < size; i +=3D page_size) { + if (i >=3D 0x1f000 && i < 0x20000) + continue; + + err =3D mucse_sfc_flash_erase_sector(hw->hw_addr, (addr + i)); + if (err) + break; + } + + return err; +} + +/** + * mucse_download_firmware - Download data to chip + * @hw: Pointer to the HW structure + * @data: Data to use + * @file_size: Data length + * + * mucse_download_firmware tries to download data to white-chip + * by hw_addr regs. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_download_firmware(struct mucse_hw *hw, const u8 *data, + int file_size) +{ + char *buf =3D kzalloc(0x1000, GFP_KERNEL); + loff_t end_pos =3D file_size; + u32 rd_len =3D 0x1000; + loff_t old_pos =3D 0; + u32 old_data =3D 0; + u32 new_data =3D 0; + int get_len =3D 0; + u32 fw_off =3D 0; + loff_t pos =3D 0; + u32 iter =3D 0; + int err =3D 0; + + if (!buf) + return -ENOMEM; + /* copy bin to bar */ + while (pos < end_pos) { + /* we must skip header 4k */ + if ((pos >=3D 0x1f000 && pos < 0x20000) || pos =3D=3D 0) { + pos +=3D rd_len; + continue; + } + + old_pos =3D pos; + if (end_pos - pos < rd_len) + get_len =3D end_pos - pos; + else + get_len =3D rd_len; + + memcpy(buf, data + pos, get_len); + if ((get_len < rd_len && ((old_pos + get_len) !=3D end_pos)) || + get_len < 0) { + err =3D -EIO; + goto out; + } + + for (iter =3D 0; iter < get_len; iter +=3D 4) { + old_data =3D *((u32 *)(buf + iter)); + fw_off =3D (u32)old_pos + iter + 0x1000; + iowrite32(old_data, (hw->hw_addr + fw_off)); + } + + if (pos =3D=3D old_pos) + pos +=3D get_len; + } + /* write first 4k header */ + pos =3D 0; + old_pos =3D pos; + get_len =3D rd_len; + memcpy(buf, data + pos, get_len); + + for (iter =3D 0; iter < get_len; iter +=3D 4) { + old_data =3D *((u32 *)(buf + iter)); + fw_off =3D (u32)old_pos + iter + 0x1000; + iowrite32(old_data, (hw->hw_addr + fw_off)); + } + /* check */ + pos =3D 0x0; + while (pos < end_pos) { + if (pos >=3D 0x1f000 && pos < 0x20000) { + pos +=3D rd_len; + continue; + } + + old_pos =3D pos; + if (end_pos - pos < rd_len) + get_len =3D end_pos - pos; + else + get_len =3D rd_len; + + memcpy(buf, data + pos, get_len); + if ((get_len < rd_len && ((old_pos + get_len) !=3D end_pos)) || + get_len < 0) { + err =3D -EIO; + goto out; + } + + for (iter =3D 0; iter < get_len; iter +=3D 4) { + old_data =3D *((u32 *)(buf + iter)); + fw_off =3D (u32)old_pos + iter + 0x1000; + new_data =3D ioread32(hw->hw_addr + fw_off); + if (old_data !=3D new_data) + err =3D -EIO; + } + + if (pos =3D=3D old_pos) + pos +=3D get_len; + } +out: + kfree(buf); + return err; +} + +/** + * rnpgbe_check_fw_from_flash - Check chip-id and bin-id + * @hw: Pointer to the HW structure + * @data: data from bin files + * + * rnpgbe_check_fw_from_flash tries to match chip-id and bin-id + * + * @return: 0 on mactch, negative on failure + **/ +static int rnpgbe_check_fw_from_flash(struct mucse_hw *hw, const u8 *data) +{ + enum rnpgbe_hw_type hw_type =3D rnpgbe_hw_unknow; + u32 device_id; + u32 chip_data; + int ret =3D 0; + +#define RNPGBE_BIN_HEADER (0xa55aa55a) + if (*((u32 *)(data)) !=3D RNPGBE_BIN_HEADER) + return -EINVAL; + + device_id =3D *((u16 *)data + 30); + + /* if no device_id no check */ + if (device_id =3D=3D 0 || device_id =3D=3D 0xffff) + return 0; + +#define CHIP_OFFSET (0x1f014 + 0x1000) +#define CHIP_N210_FLAG (0x11111111) + /* we should get hw_type from sfc-flash */ + chip_data =3D ioread32(hw->hw_addr + CHIP_OFFSET); + if (chip_data =3D=3D CHIP_N210_FLAG) + hw_type =3D rnpgbe_hw_n210; + else if (chip_data =3D=3D 0x0) + hw_type =3D rnpgbe_hw_n210L; + + switch (hw_type) { + case rnpgbe_hw_n210: + if (device_id !=3D 0x8208) + ret =3D -EINVAL; + break; + case rnpgbe_hw_n210L: + if (device_id !=3D 0x820a) + ret =3D -EINVAL; + break; + default: + ret =3D -EINVAL; + } + + return ret; +} + +/** + * init_firmware_for_n210 - download firmware + * @hw: Pointer to the HW structure + * @fw: pointer to the firmware + * + * init_firmware_for_n210 try to download firmware + * for n210, by bar0(hw->hw_addr). + * + * @return: 0 on success, negative on failure + **/ +static int init_firmware_for_n210(struct mucse_hw *hw, + const struct firmware *fw) +{ + struct pci_dev *pdev =3D hw->pdev; + int err =3D 0; + + if (rnpgbe_check_fw_from_flash(hw, fw->data)) { + dev_err(&pdev->dev, "firmware type error\n"); + return -EINVAL; + } + /* first protect off */ + err =3D mucse_sfc_write_protect(hw); + if (err) { + dev_err(&pdev->dev, "protect off command failed!"); + goto out; + } + + err =3D mucse_sfc_flash_erase(hw, fw->size); + if (err) { + dev_err(&pdev->dev, "erase flash failed!"); + goto out; + } + + err =3D mucse_download_firmware(hw, fw->data, fw->size); + if (err) { + dev_err(&pdev->dev, "init firmware failed!"); + goto out; + } + +out: + return err; +} + +/** + * rnpgbe_dl_info_get - return card fw info + * @dl: devlink structure + * @req: devlink info req + * @extack: extack info + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_dl_info_get(struct devlink *dl, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + int err; + + err =3D devlink_info_version_running_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + "NULL"); + + return err; +} + +/** + * rnpgbe_dl_flash_update - Update fw to chip flash + * @dl: devlink structure + * @params: flash update params + * @extack: extack info + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_dl_flash_update(struct devlink *dl, + struct devlink_flash_update_params *params, + struct netlink_ext_ack *extack) +{ + struct rnpgbe_devlink *rnpgbe_devlink =3D devlink_priv(dl); + struct mucse *mucse =3D rnpgbe_devlink->priv; + struct mucse_hw *hw =3D &mucse->hw; + int err; + + err =3D init_firmware_for_n210(hw, params->fw); + if (err) { + devlink_flash_update_status_notify(dl, + "Flash failed", + NULL, 0, 0); + } else { + devlink_flash_update_status_notify(dl, + "Flash done", + NULL, 0, 0); + } + return err; +} + +static const struct devlink_ops rnpgbe_dl_ops =3D { + .info_get =3D rnpgbe_dl_info_get, + .flash_update =3D rnpgbe_dl_flash_update, +}; + +/** + * rnpgbe_devlink_register - Regist devlink + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +int rnpgbe_devlink_register(struct mucse *mucse) +{ + struct device *dev =3D &mucse->pdev->dev; + struct rnpgbe_devlink *rnpgbe_devlink; + struct devlink *dl; + + dl =3D devlink_alloc(&rnpgbe_dl_ops, sizeof(struct rnpgbe_devlink), dev); + if (!dl) + return -EIO; + mucse->dl =3D dl; + rnpgbe_devlink =3D devlink_priv(dl); + rnpgbe_devlink->priv =3D mucse; + + devlink_register(dl); + return 0; +} + +/** + * rnpgbe_devlink_unregister - remove devlink + * @mucse: pointer to private structure + **/ +void rnpgbe_devlink_unregister(struct mucse *mucse) +{ + if (!mucse->dl) + return; + devlink_unregister(mucse->dl); + devlink_free(mucse->dl); +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_sfc.h new file mode 100644 index 000000000000..523a873d65c8 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_SFC_H +#define _RNPGBE_SFC_H + +#include "rnpgbe.h" + +/* Return value */ +#define RSP_FLASH_HIGH_16M_OFFSET 0x1000000 +#define SFC_MEM_BASE 0x28000000 +#define CMD_WRITE_DISABLE 0x04000000 +#define CMD_READ_STATUS 0x05000000 +#define CMD_WRITE_STATUS 0x01000000 +#define CMD_WRITE_ENABLE 0x06000000 +#define CMD_SECTOR_ERASE 0x20000000 +#define SFCADDR(a) ((a) << 8) +#define CMD_CYCLE(c) (((c) & 0xff) << 0) +#define RD_DATA_CYCLE(c) (((c) & 0xff) << 8) +#define WR_DATA_CYCLE(c) (((c) & 0xff) << 0) +#define ADDR_CYCLE(c) (((c) & 0xff) << 16) + +struct rnpgbe_devlink { + struct mucse *priv; +}; + +int rnpgbe_devlink_register(struct mucse *mucse); +void rnpgbe_devlink_unregister(struct mucse *mucse); + +#endif /* _RNPGBE_SFC_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 212CE2D29B5; Mon, 21 Jul 2025 11:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.194.254.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097685; cv=none; b=rwtlGehEKiT1H2qyOFERc1QtAg6ipvFKLP8tHM37h5TRIhlSneMle6UVJliY/RUaMFDyiUWsOkotwR0iq+Rw3kQKK/YGOsgBRvXBQ89dpHSONZGZPOwIl7M3FIUh9cIj3TQUs1EtD1cLsuY51Hmf5/UvbYRAyG2OLB6bPLGolvg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097685; c=relaxed/simple; bh=9k8/HCCq3MQpVaHDwu3CP1V7EMK0zK5PNQmNTzeIYgY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pxC0Qh5W6hMibwfGfV5oRPfsxMBufpRe96i97yQiFF0WTDUcnSh3Nc8AsKdM2VU7tszjpNrh9Biqbp7sGXeT0SldSPDcuIjnCF6qaiU0YjGm2YArIJ+iRvWSnys9io/zeWB4aLFA1Qc99nf8SyEk3UEv2cr1tkofz0F8O9LjNYo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=18.194.254.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097594tfdda31d7 X-QQ-Originating-IP: Vt/tiO7TvsfG2aaZyYNcDWVQ16RkHy59UJCH1drGIpQ= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:12 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 6926418822098371029 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 06/15] net: rnpgbe: Add some functions for hw->ops Date: Mon, 21 Jul 2025 19:32:29 +0800 Message-Id: <20250721113238.18615-7-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MxFwHSywoLiFF95UQJ+D2tKOKS7iGHEW1iO5G1X7yzFWmUcvdt7llyN+ MdFQNQ3ZJhAuVBtOMLA/MNVFiQpmbdBYadtkc/a0sxurgNR0BwJdt7Nr0rXIm5hE0t6SDo+ qgbcINGnRNdd06IezovewlERg2TSVoaTjfDpsZAvCGHaPK5zBKiwrXHKP9mo8R3rTHwVvGS pcH17Dn9xYP+WD+tM1Cuk9Yn10os75mh+L3ojY1+NUwjaibIC5E8hiV00lRffbW/dJOE4+B wtO7j+u8R2l7wCwnetZ6GWZGIXcR15gCT/sOyH7/GQspnLGIxk6auP1k8b5eRZCQ1YflmJD ysyFvlxfITpkC6cAPsvN9lYtTNUBfPr3cV20CYurM3DChp72YmK+XH/T+B4VOug15z+HVC9 pcrNOug9cIWfE+gb+2cARbFiFBslEUilao2f/vFC8GxyUNDOiR/HDIZMQ6pCquSRGxTR93h +BTCNkZWvT1bBcUZoxxXBm5mZTXIN5v9nKBOS/ZkpQhosVGMvoSBixZACSUaraav+xZmlK5 Blm74s5z5Uily0I9efiEla/R526T+oSmQKqKLg6ERt28ZJ5VwZssuXJ1rF6RNtVQM86ypp+ uDfBHNtByQqMkfV6OXD7VPF8Zgw91+Wj7h4TVumaxWS2tDwxM5sIeNc/l9SHwdHWiPxA3+b bRuMaX2xjPJzNNMx1p8phntaLItgSD1UC/oh954jRkR10gIlUFqflNN8NRGu7RfuZKVE2sx LI7goJ2b01FZxfV7emSBfXG8IsfGsluH7KhZWIoPrX+WKfuQ2vl4mdE8S1ImaaAmFK/BeUM 3bsnG4vJJuWkA3MDiFVwVKreDvyP/Lm0fGiZO6tJ2BQF6Dvn2Jmf1qfYOi+JPforqRu9SFS j6LQIOhdScLJeTEU4Ns/brDwATPGRIy/rc0tzP/1WV2sq7QZmYNctJwvRmxU5TrqoJhJoX3 em//2zX3dgdnpoZKzZeNS+m5I16JtdtWX22rSXvfGpbYvRgYFbpCeEjPg2HSjhN049401z0 2S4FBwge+bzrdZZaNo3juUBR2Ovn5+rihjUdeQ1ayDeowV00hfKXjzy3HLHJs= X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize functions (init, reset ...) to control chip. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 35 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 107 ++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 15 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 28 ++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 255 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 74 +++++ 6 files changed, 513 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index ea28236669e3..527091e6a680 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -144,6 +144,25 @@ struct mucse_mbx_info { =20 #include "rnpgbe_mbx.h" =20 +struct lldp_status { + int enable; + int inteval; +}; + +struct mucse_hw_operations { + int (*init_hw)(struct mucse_hw *hw); + int (*reset_hw)(struct mucse_hw *hw); + void (*start_hw)(struct mucse_hw *hw); + /* ops to fw */ + void (*driver_status)(struct mucse_hw *hw, bool enable, int mode); +}; + +enum { + mucse_driver_insmod, + mucse_driver_suspuse, + mucse_driver_force_control_phy, +}; + struct mucse_hw { void *back; u8 pfvfnum; @@ -166,6 +185,7 @@ struct mucse_hw { int max_vfs; int max_vfs_noari; enum rnpgbe_hw_type hw_type; + struct mucse_hw_operations ops; struct mucse_dma_info dma; struct mucse_eth_info eth; struct mucse_mac_info mac; @@ -190,7 +210,11 @@ struct mucse_hw { #define M_HW_FEATURE_EEE BIT(17) #define M_HW_SOFT_MASK_OTHER_IRQ BIT(18) u32 feature_flags; + u32 driver_version; u16 usecstocount; + int nr_lane; + struct lldp_status lldp_status; + int link; }; =20 struct mucse { @@ -225,5 +249,16 @@ struct rnpgbe_info { =20 #define m_rd_reg(reg) readl(reg) #define m_wr_reg(reg, val) writel((val), reg) +#define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) +#define dma_wr32(dma, reg, val) m_wr_reg((dma)->dma_base_addr + (reg), (va= l)) +#define dma_rd32(dma, reg) m_rd_reg((dma)->dma_base_addr + (reg)) +#define eth_wr32(eth, reg, val) m_wr_reg((eth)->eth_base_addr + (reg), (va= l)) +#define eth_rd32(eth, reg) m_rd_reg((eth)->eth_base_addr + (reg)) + +#define mucse_err(mucse, fmt, arg...) \ + dev_err(&(mucse)->pdev->dev, fmt, ##arg) + +#define mucse_dbg(mucse, fmt, arg...) \ + dev_dbg(&(mucse)->pdev->dev, fmt, ##arg) =20 #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index b0e5fda632f3..7a162b844fe4 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -7,6 +7,111 @@ #include "rnpgbe.h" #include "rnpgbe_hw.h" #include "rnpgbe_mbx.h" +#include "rnpgbe_mbx_fw.h" + +/** + * rnpgbe_init_hw_ops_n500 - Init hardware + * @hw: hw information structure + * + * rnpgbe_init_hw_ops_n500 first do a hw reset, then + * tries to start hw + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) +{ + int status =3D 0; + /* Reset the hardware */ + status =3D hw->ops.reset_hw(hw); + if (status =3D=3D 0) + hw->ops.start_hw(hw); + + return status; +} + +/** + * rnpgbe_reset_hw_ops_n500 - Do a hardware reset + * @hw: hw information structure + * + * rnpgbe_reset_hw_ops_n500 calls fw to do a hardware + * reset, and cleans some regs to default. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_reset_hw_ops_n500(struct mucse_hw *hw) +{ + struct mucse_dma_info *dma =3D &hw->dma; + struct mucse_eth_info *eth =3D &hw->eth; + int err; + int i; + /* Call hw to stop dma */ + dma_wr32(dma, RNPGBE_DMA_AXI_EN, 0); + err =3D mucse_mbx_fw_reset_phy(hw); + if (err) + return err; + eth_wr32(eth, RNPGBE_ETH_ERR_MASK_VECTOR, + RNPGBE_PKT_LEN_ERR | RNPGBE_HDR_LEN_ERR); + dma_wr32(dma, RNPGBE_DMA_RX_PROG_FULL_THRESH, 0xa); + for (i =3D 0; i < 12; i++) + m_wr_reg(hw->ring_msix_base + RING_VECTOR(i), 0); + + hw->link =3D 0; + + return 0; +} + +/** + * rnpgbe_start_hw_ops_n500 - Setup hw to start + * @hw: hw information structure + * + * rnpgbe_start_hw_ops_n500 initializes default + * hw status, ready to start. + * + **/ +static void rnpgbe_start_hw_ops_n500(struct mucse_hw *hw) +{ + struct mucse_eth_info *eth =3D &hw->eth; + struct mucse_dma_info *dma =3D &hw->dma; + u32 value; + + value =3D dma_rd32(dma, RNPGBE_DMA_DUMY); + value |=3D BIT(0); + dma_wr32(dma, RNPGBE_DMA_DUMY, value); + dma_wr32(dma, RNPGBE_DMA_CONFIG, DMA_VEB_BYPASS); + dma_wr32(dma, RNPGBE_DMA_AXI_EN, (RX_AXI_RW_EN | TX_AXI_RW_EN)); + eth_wr32(eth, RNPGBE_ETH_BYPASS, 0); + eth_wr32(eth, RNPGBE_ETH_DEFAULT_RX_RING, 0); +} + +/** + * rnpgbe_driver_status_hw_ops_n500 - Echo driver status to hw + * @hw: hw information structure + * @enable: true or false status + * @mode: status mode + **/ +static void rnpgbe_driver_status_hw_ops_n500(struct mucse_hw *hw, + bool enable, + int mode) +{ + switch (mode) { + case mucse_driver_insmod: + mucse_mbx_ifinsmod(hw, enable); + break; + case mucse_driver_suspuse: + mucse_mbx_ifsuspuse(hw, enable); + break; + case mucse_driver_force_control_phy: + mucse_mbx_ifforce_control_mac(hw, enable); + break; + } +} + +static struct mucse_hw_operations hw_ops_n500 =3D { + .init_hw =3D &rnpgbe_init_hw_ops_n500, + .reset_hw =3D &rnpgbe_reset_hw_ops_n500, + .start_hw =3D &rnpgbe_start_hw_ops_n500, + .driver_status =3D &rnpgbe_driver_status_hw_ops_n500, +}; =20 /** * rnpgbe_get_invariants_n500 - setup for hw info @@ -84,7 +189,9 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *= hw) M_NET_FEATURE_STAG_OFFLOAD; /* start the default ahz, update later */ hw->usecstocount =3D 125; + hw->max_vfs_noari =3D 1; hw->max_vfs =3D 7; + memcpy(&hw->ops, &hw_ops_n500, sizeof(hw->ops)); } =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h index ff7bd9b21550..35e3cb77a38b 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -14,8 +14,21 @@ #define RNPGBE_RING_BASE (0x1000) #define RNPGBE_MAC_BASE (0x20000) #define RNPGBE_ETH_BASE (0x10000) - +/* dma regs */ +#define DMA_VEB_BYPASS BIT(4) +#define RNPGBE_DMA_CONFIG (0x0004) #define RNPGBE_DMA_DUMY (0x000c) +#define RNPGBE_DMA_AXI_EN (0x0010) +#define RX_AXI_RW_EN (0x03 << 0) +#define TX_AXI_RW_EN (0x03 << 2) +#define RNPGBE_DMA_RX_PROG_FULL_THRESH (0x00a0) +#define RING_VECTOR(n) (0x04 * (n)) +/* eth regs */ +#define RNPGBE_ETH_BYPASS (0x8000) +#define RNPGBE_ETH_ERR_MASK_VECTOR (0x8060) +#define RNPGBE_ETH_DEFAULT_RX_RING (0x806c) +#define RNPGBE_PKT_LEN_ERR (2) +#define RNPGBE_HDR_LEN_ERR (1) /* chip resourse */ #define RNPGBE_MAX_QUEUES (8) /* multicast control table */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 61dd0d232d99..ba21e3858c0e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -38,6 +38,17 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +/** + * rnpgbe_sw_init - Init driver private status + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_sw_init(struct mucse *mucse) +{ + return 0; +} + /** * rnpgbe_add_adapter - add netdev for this pci_dev * @pdev: PCI device information structure @@ -127,8 +138,12 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, } hw->hw_addr =3D hw_addr; hw->dma.dma_version =3D dma_version; + hw->driver_version =3D 0x0002040f; + hw->nr_lane =3D 0; ii->get_invariants(hw); hw->mbx.ops.init_params(hw); + /* echo fw driver insmod */ + hw->ops.driver_status(hw, true, mucse_driver_insmod); =20 err =3D mucse_mbx_get_capability(hw); if (err) { @@ -137,6 +152,16 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, goto err_free_net; } =20 + err =3D rnpgbe_sw_init(mucse); + if (err) + goto err_free_net; + + err =3D hw->ops.reset_hw(hw); + if (err) { + dev_err(&pdev->dev, "Hw reset failed\n"); + goto err_free_net; + } + return 0; =20 err_free_net: @@ -202,11 +227,14 @@ static int rnpgbe_probe(struct pci_dev *pdev, const s= truct pci_device_id *id) **/ static void rnpgbe_rm_adapter(struct mucse *mucse) { + struct mucse_hw *hw =3D &mucse->hw; struct net_device *netdev; =20 rnpgbe_devlink_unregister(mucse); netdev =3D mucse->netdev; + hw->ops.driver_status(hw, false, mucse_driver_insmod); free_netdev(netdev); + mucse->netdev =3D NULL; } =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index 1674229fcd43..18f57ef8b1ad 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -3,6 +3,7 @@ =20 #include =20 +#include "rnpgbe.h" #include "rnpgbe_mbx_fw.h" =20 /** @@ -138,3 +139,257 @@ int mucse_mbx_get_capability(struct mucse_hw *hw) =20 return err; } + +/** + * mbx_req_cookie - Alloc a cookie structure + * @priv_len: private length for this cookie + * + * @return: cookie structure on success + **/ +static struct mbx_req_cookie *mbx_cookie_zalloc(int priv_len) +{ + struct mbx_req_cookie *cookie; + + cookie =3D kzalloc(struct_size(cookie, priv, priv_len), GFP_KERNEL); + + if (cookie) { + cookie->timeout_jiffes =3D 30 * HZ; + cookie->magic =3D COOKIE_MAGIC; + cookie->priv_len =3D priv_len; + } + + return cookie; +} + +/** + * mucse_mbx_fw_post_req - Posts a mbx req to firmware and wait reply + * @hw: Pointer to the HW structure + * @req: Pointer to the cmd req structure + * @cookie: Pointer to the req cookie + * + * mucse_mbx_fw_post_req posts a mbx req to firmware and wait for the + * reply. cookie->wait will be set in irq handler. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_mbx_fw_post_req(struct mucse_hw *hw, + struct mbx_fw_cmd_req *req, + struct mbx_req_cookie *cookie) +{ + int len =3D le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN; + int err =3D 0; + + cookie->errcode =3D 0; + cookie->done =3D 0; + init_waitqueue_head(&cookie->wait); + + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + + err =3D mucse_write_mbx(hw, (u32 *)req, + L_WD(len), + MBX_FW); + if (err) { + mutex_unlock(&hw->mbx.lock); + return err; + } + + if (cookie->timeout_jiffes !=3D 0) { +retry: + err =3D wait_event_interruptible_timeout(cookie->wait, + cookie->done =3D=3D 1, + cookie->timeout_jiffes); + if (err =3D=3D -ERESTARTSYS) + goto retry; + if (err =3D=3D 0) + err =3D -ETIME; + else + err =3D 0; + } else { +retry_no_timeout: + err =3D wait_event_interruptible(cookie->wait, cookie->done =3D=3D 1); + if (err =3D=3D -ERESTARTSYS) + goto retry_no_timeout; + } + + mutex_unlock(&hw->mbx.lock); + + if (cookie->errcode) + err =3D cookie->errcode; + + return err; +} + +/** + * rnpgbe_mbx_lldp_get - Get lldp status from hw + * @hw: Pointer to the HW structure + * + * @return: 0 on success, negative on failure + **/ +int rnpgbe_mbx_lldp_get(struct mucse_hw *hw) +{ + struct mbx_req_cookie *cookie =3D NULL; + struct get_lldp_reply *get_lldp; + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int err; + + cookie =3D mbx_cookie_zalloc(sizeof(*get_lldp)); + if (!cookie) + return -ENOMEM; + + get_lldp =3D (struct get_lldp_reply *)cookie->priv; + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_get_lldp_req(&req, cookie, hw->nr_lane); + if (hw->mbx.irq_enabled) { + err =3D mucse_mbx_fw_post_req(hw, &req, cookie); + } else { + err =3D mucse_fw_send_cmd_wait(hw, &req, &reply); + get_lldp =3D &reply.get_lldp; + } + + if (err =3D=3D 0) { + hw->lldp_status.enable =3D le32_to_cpu(get_lldp->value); + hw->lldp_status.inteval =3D le32_to_cpu(get_lldp->inteval); + } + + kfree(cookie); + + return err; +} + +/** + * mucse_mbx_ifinsmod - Echo driver insmod status to hw + * @hw: Pointer to the HW structure + * @status: true for insmod, false for rmmod + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int len; + int err; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifinsmod(&req, hw->driver_version, status); + len =3D le32_to_cpu(req.datalen) + MBX_REQ_HDR_LEN; + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + + if (status) { + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD(len), + MBX_FW); + } else { + err =3D hw->mbx.ops.write(hw, (u32 *)&req, + L_WD(len), + MBX_FW); + } + + mutex_unlock(&hw->mbx.lock); + return err; +} + +/** + * mucse_mbx_ifsuspuse - Echo driver suspuse status to hw + * @hw: Pointer to the HW structure + * @status: true for suspuse, false for no susupuse + * + * mucse_mbx_ifsuspuse echo driver susupus status to hw. The + * status is used to enter wol status for hw. + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_ifsuspuse(struct mucse_hw *hw, int status) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int len; + int err; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifsuspuse(&req, hw->nr_lane, status); + len =3D le32_to_cpu(req.datalen) + MBX_REQ_HDR_LEN; + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD(len), + MBX_FW); + mutex_unlock(&hw->mbx.lock); + + return err; +} + +/** + * mucse_mbx_ifforce_control_mac - Echo force mac control to hw + * @hw: Pointer to the HW structure + * @status: true for force control, false for not + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, int status) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int len; + int err; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifforce(&req, hw->nr_lane, status); + len =3D le32_to_cpu(req.datalen) + MBX_REQ_HDR_LEN; + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD(len), + MBX_FW); + mutex_unlock(&hw->mbx.lock); + + return err; +} + +/** + * mucse_mbx_fw_reset_phy - Posts a mbx req to reset hw + * @hw: Pointer to the HW structure + * + * mucse_mbx_fw_reset_phy posts a mbx req to firmware to reset hw. + * It uses mucse_fw_send_cmd_wait if no irq, and mucse_mbx_fw_post_req + * if other irq is registered. + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_fw_reset_phy(struct mucse_hw *hw) +{ + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + int ret; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + if (hw->mbx.irq_enabled) { + struct mbx_req_cookie *cookie =3D mbx_cookie_zalloc(0); + + if (!cookie) + return -ENOMEM; + + build_reset_phy_req(&req, cookie); + ret =3D mucse_mbx_fw_post_req(hw, &req, cookie); + kfree(cookie); + return ret; + + } else { + build_reset_phy_req(&req, &req); + return mucse_fw_send_cmd_wait(hw, &req, &reply); + } +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h index a24c5d4e0075..9e07858f2733 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -563,6 +563,80 @@ static inline void build_phy_abalities_req(struct mbx_= fw_cmd_req *req, req->cookie =3D cookie; } =20 +static inline void build_get_lldp_req(struct mbx_fw_cmd_req *req, void *co= okie, + int nr_lane) +{ +#define LLDP_TX_GET (1) + + req->flags =3D 0; + req->opcode =3D cpu_to_le32(LLDP_TX_CTRL); + req->datalen =3D cpu_to_le32(sizeof(req->lldp_tx)); + req->cookie =3D cookie; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->lldp_tx.lane =3D cpu_to_le32(nr_lane); + req->lldp_tx.op =3D cpu_to_le32(LLDP_TX_GET); + req->lldp_tx.enable =3D 0; +} + +static inline void build_ifinsmod(struct mbx_fw_cmd_req *req, + unsigned int nr_lane, + int status) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(DRIVER_INSMOD); + req->datalen =3D cpu_to_le32(sizeof(req->ifinsmod)); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifinsmod.lane =3D cpu_to_le32(nr_lane); + req->ifinsmod.status =3D cpu_to_le32(status); +} + +static inline void build_ifsuspuse(struct mbx_fw_cmd_req *req, + unsigned int nr_lane, + int status) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(SYSTEM_SUSPUSE); + req->datalen =3D cpu_to_le32(sizeof(req->ifsuspuse)); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifinsmod.lane =3D cpu_to_le32(nr_lane); + req->ifinsmod.status =3D cpu_to_le32(status); +} + +static inline void build_ifforce(struct mbx_fw_cmd_req *req, + unsigned int nr_lane, + int status) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(SYSTEM_FORCE); + req->datalen =3D cpu_to_le32(sizeof(req->ifforce)); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifforce.lane =3D cpu_to_le32(nr_lane); + req->ifforce.status =3D cpu_to_le32(status); +} + +static inline void build_reset_phy_req(struct mbx_fw_cmd_req *req, + void *cookie) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(RESET_PHY); + req->datalen =3D 0; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->cookie =3D cookie; +} + int mucse_mbx_get_capability(struct mucse_hw *hw); +int rnpgbe_mbx_lldp_get(struct mucse_hw *hw); +int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status); +int mucse_mbx_ifsuspuse(struct mucse_hw *hw, int status); +int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, int status); +int mucse_mbx_fw_reset_phy(struct mucse_hw *hw); =20 #endif /* _RNPGBE_MBX_FW_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgau2.qq.com (smtpbgau2.qq.com [54.206.34.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F37A92BDC08; Mon, 21 Jul 2025 11:34:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.206.34.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097671; cv=none; b=Z/itLDFmrCLhCJcxyfPrz6enaunAn3I1a9+jn7HguQgOL868d+hiJzJDqqtS76FSNYYday8ShE3i3hAkJOi6cZdew8HcUEihj0sD+8fv2e2DJgT0w1ED02X5MjpFCT/KurczfCjZSgsiVExCtptBV+lxC0fZI5+BIhDwkGtUmtA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097671; c=relaxed/simple; bh=kuQzO4zbz5ZmXv8RDEeEJRQKrKDultQcgFVG/92CGQs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=neh2jCOsDYXXFCvV0EBZ4auch6fz9kBr5sZG6JbpCxbOL9vpseaGtIImfucJ6YbFHCk1ykl+p/yPzKPaDDji1qfYc7PeFjVOtkZnQlRgiSoCpBGaFn/0e3OM6NWPX8a5wGJHINL10IG7TfG+9S3jKuJtMw5mfW0h/BnUHXwcJIw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.206.34.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097599ta682fe7c X-QQ-Originating-IP: a/TqDkBFbxG0PO4YmPxED5Chj4UlQylmnz/+/N3xPfE= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:16 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 5680564977977561247 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 07/15] net: rnpgbe: Add get mac from hw Date: Mon, 21 Jul 2025 19:32:30 +0800 Message-Id: <20250721113238.18615-8-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NxcSjIkI5TJUDMlT3BU4gEOs4H7VowG5Gp9hPe9cbtTlzYB0qMk2ofqY 0IJMBWIACYnT0Jgpnw5m//ddJQCH/Cj2MY6nbwNuy/Qyk705huRi9c/24QNId1SBY2ijGj/ bcSbqS9iL+4QsCsM1k8Xyz4+vLF4L/PLPaEhtmk+ouyk9RkF3P0hOqRmAtTzfTuxv3tuSVz pbcljfGUsHfQQmwAAXDNzzduQQOYQd1XP3dmq1LCycQHF3c67+08OC8GgnloK9wpQWFBN3p 0iacu29l893xSZ/rC5mCKfyWfA6MNymHtpINybXDHSPXwJUrloLlYeVZr41Jrr4pOD/KxX+ 0yyQsfuIZHdo59l9nhXF5DlOXMAfiu3IL6w7fLNor5ieR6ttwSzfF9iAIjEGn1JXEtlF5xx jz6GAeclDgfatFxxITSXtVC5eTh+AMvuswz2pa8FvMJeiEQ9AjWiojpCYhD0RhS9QQq3JG1 wdKN3sS+rF62efwM2IDTq20/UW5Tj8l073JpzZmlKwn5p4CIHMzE7z+1nN07iJolVbNJHIX jb1Tq6HOI/67IEYGCfv1CuOivOyy/DIw/p5J285LySEPC+lCiT1VMgA3Cez0Fm97rn+n6Es sFL3sCQFusvGp450YCCJx2vYb+h0f3OH1isCQsfiuz23BNrC7maQedYFg4/m7wC1Z61lTl3 kS7wAHUiu86s+lu+PmoU4UjeJjk3DNVAvGT35RyLsY/r2jUKbaJBF1E0QtnD+lYc8gSuLWv 4X5bwWV6Q1U+T6QoO51HuZ71oJgQtffZA+Cr3QQU7DBIWbbTHIEzlSY3YQ9uf9iLnCYHf7T S7xQoO9hRsDQWLh5zo15adjsM0jAXzKXT8yPpPDdCUQa71eFzJ4J49R/9etfuZrDI5aWgKT OTV0mSqDbD9XuiCD4jt+FtxmX11yOwqFq3GyOxWYWisZIKVBnHH6ps8veoN74u4uzuM7qsv d9HYoNMxav3WE39ptIWOfD7K3y/56FO243R6+g8qJ9mJ+jt4PXd+YCsQ4cA91sMQ/F0vUfl Zb5anGn3A7Vod0o8Sh4UE+o/t4VH0= X-QQ-XMRINFO: NS+P29fieYNw95Bth2bWPxk= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize gets mac function for driver use. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 61 ++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 149 ++++++++++++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 9 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 29 ++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 63 ++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 17 ++ 6 files changed, 326 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 527091e6a680..30b5400241c3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -34,8 +34,18 @@ struct mucse_dma_info { u32 dma_version; }; =20 +struct mucse_eth_info; + +struct mucse_eth_operations { + int (*get_mac_addr)(struct mucse_eth_info *eth, u8 *addr); + int (*set_rar)(struct mucse_eth_info *eth, u32 index, u8 *addr); + int (*clear_rar)(struct mucse_eth_info *eth, u32 index); + void (*clr_mc_addr)(struct mucse_eth_info *eth); +}; + #define RNPGBE_MAX_MTA 128 struct mucse_eth_info { + struct mucse_eth_operations ops; u8 __iomem *eth_base_addr; void *back; u32 mta_shadow[RNPGBE_MAX_MTA]; @@ -64,6 +74,13 @@ struct mucse_mac_info { int clk_csr; }; =20 +struct mucse_addr_filter_info { + u32 num_mc_addrs; + u32 rar_used_count; + u32 mta_in_use; + bool user_set_promisc; +}; + struct mucse_hw; =20 enum MBX_ID { @@ -153,6 +170,7 @@ struct mucse_hw_operations { int (*init_hw)(struct mucse_hw *hw); int (*reset_hw)(struct mucse_hw *hw); void (*start_hw)(struct mucse_hw *hw); + void (*init_rx_addrs)(struct mucse_hw *hw); /* ops to fw */ void (*driver_status)(struct mucse_hw *hw, bool enable, int mode); }; @@ -176,6 +194,10 @@ struct mucse_hw { u16 subsystem_vendor_id; u32 wol; u32 wol_en; + u16 min_len_cap; + u16 max_len_cap; + u16 min_len_cur; + u16 max_len_cur; u32 fw_version; u32 axi_mhz; u32 bd_uid; @@ -209,12 +231,29 @@ struct mucse_hw { #define M_VEB_VLAN_MASK_EN BIT(16) #define M_HW_FEATURE_EEE BIT(17) #define M_HW_SOFT_MASK_OTHER_IRQ BIT(18) + struct mucse_addr_filter_info addr_ctrl; u32 feature_flags; + u32 flags; +#define M_FLAGS_INIT_MAC_ADDRESS BIT(27) u32 driver_version; u16 usecstocount; + u16 max_msix_vectors; int nr_lane; struct lldp_status lldp_status; int link; + u8 addr[ETH_ALEN]; + u8 perm_addr[ETH_ALEN]; +}; + +enum mucse_state_t { + __MUCSE_DOWN, + __MUCSE_SERVICE_SCHED, + __MUCSE_PTP_TX_IN_PROGRESS, + __MUCSE_USE_VFINFI, + __MUCSE_IN_IRQ, + __MUCSE_REMOVE, + __MUCSE_SERVICE_CHECK, + __MUCSE_EEE_REMOVE, }; =20 struct mucse { @@ -224,9 +263,20 @@ struct mucse { struct mucse_hw hw; /* board number */ u16 bd_number; + u16 tx_work_limit; u32 flags2; #define M_FLAG2_NO_NET_REG BIT(0) - + u32 priv_flags; +#define M_PRIV_FLAG_TX_COALESCE BIT(25) +#define M_PRIV_FLAG_RX_COALESCE BIT(26) + int tx_ring_item_count; + int rx_ring_item_count; + int napi_budge; + u16 rx_usecs; + u16 rx_frames; + u16 tx_frames; + u16 tx_usecs; + unsigned long state; char name[60]; }; =20 @@ -247,6 +297,15 @@ struct rnpgbe_info { #define PCI_DEVICE_ID_N210 0x8208 #define PCI_DEVICE_ID_N210L 0x820a =20 +#define M_DEFAULT_TXD (512) +#define M_DEFAULT_TX_WORK (128) +#define M_PKT_TIMEOUT_TX (200) +#define M_TX_PKT_POLL_BUDGET (0x30) + +#define M_DEFAULT_RXD (512) +#define M_PKT_TIMEOUT (30) +#define M_RX_PKT_POLL_BUDGET (64) + #define m_rd_reg(reg) readl(reg) #define m_wr_reg(reg, val) writel((val), reg) #define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index 7a162b844fe4..fc179eb8c516 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -3,12 +3,94 @@ =20 #include #include +#include =20 #include "rnpgbe.h" #include "rnpgbe_hw.h" #include "rnpgbe_mbx.h" #include "rnpgbe_mbx_fw.h" =20 +/** + * rnpgbe_eth_set_rar_n500 - Set Rx address register + * @eth: pointer to eth structure + * @index: Receive address register to write + * @addr: Address to put into receive address register + * + * rnpgbe_eth_set_rar_n500 puts an ethernet address + * into a receive address register. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_eth_set_rar_n500(struct mucse_eth_info *eth, + u32 index, u8 *addr) +{ + u32 rar_entries =3D eth->num_rar_entries; + u32 rar_low, rar_high =3D 0; + u32 mcstctrl; + + /* Make sure we are using a valid rar index range */ + if (index >=3D rar_entries) + return -EINVAL; + + rar_low =3D ((u32)addr[5] | ((u32)addr[4] << 8) | + ((u32)addr[3] << 16) | + ((u32)addr[2] << 24)); + rar_high |=3D ((u32)addr[1] | ((u32)addr[0] << 8)); + rar_high |=3D RNPGBE_RAH_AV; + + eth_wr32(eth, RNPGBE_ETH_RAR_RL(index), rar_low); + eth_wr32(eth, RNPGBE_ETH_RAR_RH(index), rar_high); + /* open unicast filter */ + mcstctrl =3D eth_rd32(eth, RNPGBE_ETH_DMAC_MCSTCTRL); + mcstctrl |=3D RNPGBE_MCSTCTRL_UNICASE_TBL_EN; + eth_wr32(eth, RNPGBE_ETH_DMAC_MCSTCTRL, mcstctrl); + + return 0; +} + +/** + * rnpgbe_eth_clear_rar_n500 - Remove Rx address register + * @eth: pointer to eth structure + * @index: Receive address register to write + * + * rnpgbe_eth_clear_rar_n500 clears an ethernet address + * from a receive address register. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_eth_clear_rar_n500(struct mucse_eth_info *eth, + u32 index) +{ + u32 rar_entries =3D eth->num_rar_entries; + + /* Make sure we are using a valid rar index range */ + if (index >=3D rar_entries) + return -EINVAL; + + eth_wr32(eth, RNPGBE_ETH_RAR_RL(index), 0); + eth_wr32(eth, RNPGBE_ETH_RAR_RH(index), 0); + + return 0; +} + +/** + * rnpgbe_eth_clr_mc_addr_n500 - clear all multicast table + * @eth: pointer to eth structure + **/ +static void rnpgbe_eth_clr_mc_addr_n500(struct mucse_eth_info *eth) +{ + int i; + + for (i =3D 0; i < eth->mcft_size; i++) + eth_wr32(eth, RNPGBE_ETH_MUTICAST_HASH_TABLE(i), 0); +} + +static struct mucse_eth_operations eth_ops_n500 =3D { + .set_rar =3D &rnpgbe_eth_set_rar_n500, + .clear_rar =3D &rnpgbe_eth_clear_rar_n500, + .clr_mc_addr =3D &rnpgbe_eth_clr_mc_addr_n500 +}; + /** * rnpgbe_init_hw_ops_n500 - Init hardware * @hw: hw information structure @@ -29,6 +111,27 @@ static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) return status; } =20 +/** + * rnpgbe_get_permtion_mac - Get permition mac + * @hw: hw information structure + * @mac_addr: pointer to store mac + * + * rnpgbe_get_permtion_mac tries to get mac from hw. + * It use eth_random_addr if failed. + **/ +static void rnpgbe_get_permtion_mac(struct mucse_hw *hw, + u8 *mac_addr) +{ + if (mucse_fw_get_macaddr(hw, hw->pfvfnum, mac_addr, hw->nr_lane)) { + eth_random_addr(mac_addr); + } else { + if (!is_valid_ether_addr(mac_addr)) + eth_random_addr(mac_addr); + } + + hw->flags |=3D M_FLAGS_INIT_MAC_ADDRESS; +} + /** * rnpgbe_reset_hw_ops_n500 - Do a hardware reset * @hw: hw information structure @@ -49,6 +152,13 @@ static int rnpgbe_reset_hw_ops_n500(struct mucse_hw *hw) err =3D mucse_mbx_fw_reset_phy(hw); if (err) return err; + /* Store the permanent mac address */ + if (!(hw->flags & M_FLAGS_INIT_MAC_ADDRESS)) { + rnpgbe_get_permtion_mac(hw, hw->perm_addr); + memcpy(hw->addr, hw->perm_addr, ETH_ALEN); + } + + hw->ops.init_rx_addrs(hw); eth_wr32(eth, RNPGBE_ETH_ERR_MASK_VECTOR, RNPGBE_PKT_LEN_ERR | RNPGBE_HDR_LEN_ERR); dma_wr32(dma, RNPGBE_DMA_RX_PROG_FULL_THRESH, 0xa); @@ -106,10 +216,46 @@ static void rnpgbe_driver_status_hw_ops_n500(struct m= ucse_hw *hw, } } =20 +/** + * rnpgbe_init_rx_addrs_hw_ops_n500 - Init rx addr setup to hw + * @hw: hw information structure + * + * rnpgbe_init_rx_addrs_hw_ops_n500 setup hw->addr to hw, it + * reset to hw->perm_addr if hw->addr is invalid. + **/ +static void rnpgbe_init_rx_addrs_hw_ops_n500(struct mucse_hw *hw) +{ + struct mucse_eth_info *eth =3D &hw->eth; + u32 rar_entries; + int i; + u32 v; + + rar_entries =3D eth->num_rar_entries; + /* hw->addr maybe set by sw */ + if (!is_valid_ether_addr(hw->addr)) + memcpy(hw->addr, hw->perm_addr, ETH_ALEN); + else + eth->ops.set_rar(eth, 0, hw->addr); + + hw->addr_ctrl.rar_used_count =3D 1; + /* Clear other rar addresses. */ + for (i =3D 1; i < rar_entries; i++) + eth->ops.clear_rar(eth, i); + + /* Clear the MTA */ + hw->addr_ctrl.mta_in_use =3D 0; + v =3D eth_rd32(eth, RNPGBE_ETH_DMAC_MCSTCTRL); + v &=3D (~0x3); + v |=3D eth->mc_filter_type; + eth_wr32(eth, RNPGBE_ETH_DMAC_MCSTCTRL, v); + eth->ops.clr_mc_addr(eth); +} + static struct mucse_hw_operations hw_ops_n500 =3D { .init_hw =3D &rnpgbe_init_hw_ops_n500, .reset_hw =3D &rnpgbe_reset_hw_ops_n500, .start_hw =3D &rnpgbe_start_hw_ops_n500, + .init_rx_addrs =3D &rnpgbe_init_rx_addrs_hw_ops_n500, .driver_status =3D &rnpgbe_driver_status_hw_ops_n500, }; =20 @@ -137,6 +283,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw = *hw) dma->max_rx_queues =3D RNPGBE_MAX_QUEUES; dma->back =3D hw; /* setup eth info */ + memcpy(&hw->eth.ops, ð_ops_n500, sizeof(hw->eth.ops)); eth->eth_base_addr =3D hw->hw_addr + RNPGBE_ETH_BASE; eth->back =3D hw; eth->mc_filter_type =3D 0; @@ -191,6 +338,8 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw = *hw) hw->usecstocount =3D 125; hw->max_vfs_noari =3D 1; hw->max_vfs =3D 7; + hw->min_len_cap =3D RNPGBE_MIN_LEN; + hw->max_len_cap =3D RNPGBE_MAX_LEN; memcpy(&hw->ops, &hw_ops_n500, sizeof(hw->ops)); } =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h index 35e3cb77a38b..bcb4da45feac 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -29,6 +29,12 @@ #define RNPGBE_ETH_DEFAULT_RX_RING (0x806c) #define RNPGBE_PKT_LEN_ERR (2) #define RNPGBE_HDR_LEN_ERR (1) +#define RNPGBE_MCSTCTRL_UNICASE_TBL_EN BIT(3) +#define RNPGBE_ETH_DMAC_MCSTCTRL (0x9114) +#define RNPGBE_RAH_AV (0x80000000) +#define RNPGBE_ETH_RAR_RL(n) (0xa000 + 0x04 * (n)) +#define RNPGBE_ETH_RAR_RH(n) (0xa400 + 0x04 * (n)) +#define RNPGBE_ETH_MUTICAST_HASH_TABLE(n) (0xac00 + 0x04 * (n)) /* chip resourse */ #define RNPGBE_MAX_QUEUES (8) /* multicast control table */ @@ -36,7 +42,8 @@ /* vlan filter table */ #define RNPGBE_VFT_TBL_SIZE (128) #define RNPGBE_RAR_ENTRIES (32) - +#define RNPGBE_MIN_LEN (68) +#define RNPGBE_MAX_LEN (9722) #define RNPGBE_MII_ADDR 0x00000010 /* MII Address */ #define RNPGBE_MII_DATA 0x00000014 /* MII Data */ #endif /* _RNPGBE_HW_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index ba21e3858c0e..1338ef01f545 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -46,6 +46,27 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { **/ static int rnpgbe_sw_init(struct mucse *mucse) { + struct pci_dev *pdev =3D mucse->pdev; + struct mucse_hw *hw =3D &mucse->hw; + + hw->vendor_id =3D pdev->vendor; + hw->device_id =3D pdev->device; + hw->subsystem_vendor_id =3D pdev->subsystem_vendor; + hw->subsystem_device_id =3D pdev->subsystem_device; + mucse->napi_budge =3D 64; + /* set default work limits */ + mucse->tx_work_limit =3D M_DEFAULT_TX_WORK; + mucse->tx_usecs =3D M_PKT_TIMEOUT_TX; + mucse->tx_frames =3D M_TX_PKT_POLL_BUDGET; + mucse->rx_usecs =3D M_PKT_TIMEOUT; + mucse->rx_frames =3D M_RX_PKT_POLL_BUDGET; + mucse->priv_flags &=3D ~M_PRIV_FLAG_RX_COALESCE; + mucse->priv_flags &=3D ~M_PRIV_FLAG_TX_COALESCE; + /* set default ring sizes */ + mucse->tx_ring_item_count =3D M_DEFAULT_TXD; + mucse->rx_ring_item_count =3D M_DEFAULT_RXD; + set_bit(__MUCSE_DOWN, &mucse->state); + return 0; } =20 @@ -162,6 +183,14 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, goto err_free_net; } =20 + netdev->min_mtu =3D hw->min_len_cap; + netdev->max_mtu =3D hw->max_len_cap - (ETH_HLEN + 2 * ETH_FCS_LEN); + netdev->features |=3D NETIF_F_HIGHDMA; + netdev->priv_flags |=3D IFF_UNICAST_FLT; + netdev->priv_flags |=3D IFF_SUPP_NOFCS; + eth_hw_addr_set(netdev, hw->perm_addr); + memcpy(netdev->perm_addr, hw->perm_addr, netdev->addr_len); + return 0; =20 err_free_net: diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index 18f57ef8b1ad..37ef75121898 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -393,3 +393,66 @@ int mucse_mbx_fw_reset_phy(struct mucse_hw *hw) return mucse_fw_send_cmd_wait(hw, &req, &reply); } } + +/** + * mucse_fw_get_macaddr - Posts a mbx req to request macaddr + * @hw: Pointer to the HW structure + * @pfvfnum: Index of pf/vf num + * @mac_addr: Pointer to store mac_addr + * @nr_lane: Lane index + * + * mucse_fw_get_macaddr posts a mbx req to firmware to get mac_addr. + * It uses mucse_fw_send_cmd_wait if no irq, and mucse_mbx_fw_post_req + * if other irq is registered. + * + * @return: 0 on success, negative on failure + **/ +int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum, + u8 *mac_addr, + int nr_lane) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int err =3D 0; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + if (!mac_addr) + return -EINVAL; + + if (hw->mbx.irq_enabled) { + struct mbx_req_cookie *cookie =3D + mbx_cookie_zalloc(sizeof(reply.mac_addr)); + struct mac_addr *mac =3D (struct mac_addr *)cookie->priv; + + if (!cookie) + return -ENOMEM; + + build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, cookie); + err =3D mucse_mbx_fw_post_req(hw, &req, cookie); + if (err) { + kfree(cookie); + goto out; + } + + if ((1 << nr_lane) & mac->lanes) + memcpy(mac_addr, mac->addrs[nr_lane].mac, ETH_ALEN); + else + err =3D -ENODATA; + + kfree(cookie); + } else { + build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, &req); + err =3D mucse_fw_send_cmd_wait(hw, &req, &reply); + if (err) + goto out; + + if ((1 << nr_lane) & reply.mac_addr.lanes) + memcpy(mac_addr, reply.mac_addr.addrs[nr_lane].mac, 6); + else + err =3D -ENODATA; + } +out: + return err; +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h index 9e07858f2733..65a4f74c7090 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -632,11 +632,28 @@ static inline void build_reset_phy_req(struct mbx_fw_= cmd_req *req, req->cookie =3D cookie; } =20 +static inline void build_get_macaddress_req(struct mbx_fw_cmd_req *req, + int lane_mask, int pfvfnum, + void *cookie) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(GET_MAC_ADDRES); + req->datalen =3D cpu_to_le32(sizeof(req->get_mac_addr)); + req->cookie =3D cookie; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + + req->get_mac_addr.lane_mask =3D cpu_to_le32(lane_mask); + req->get_mac_addr.pfvf_num =3D cpu_to_le32(pfvfnum); +} + int mucse_mbx_get_capability(struct mucse_hw *hw); int rnpgbe_mbx_lldp_get(struct mucse_hw *hw); int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status); int mucse_mbx_ifsuspuse(struct mucse_hw *hw, int status); int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, int status); int mucse_mbx_fw_reset_phy(struct mucse_hw *hw); +int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum, + u8 *mac_addr, int nr_lane); =20 #endif /* _RNPGBE_MBX_FW_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgau2.qq.com (smtpbgau2.qq.com [54.206.34.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E7622D3722; Mon, 21 Jul 2025 11:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.206.34.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097686; cv=none; b=CBSp0OSEkv80X+VQBKq2aXPijv7kf6xupnSNgjy2hdzVidPN4r/EuSlbvdVfbXORIjcCTyrZpMuHeTk/izC24r/hyYRn+w4G392sSpBWC69tQHdRYCQTkfT+Z1+Il0yFh6o+lf0qJ6WsCDNgK/jZ8hOYFyDLOp73oTXAifT/qpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097686; c=relaxed/simple; bh=cQaC8Nbow4sm5Ce7s7uzhXr9gnoF4fYzoiDAvFFudn0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AdrRsu4bKq8YH1klx79aysM6ZMLw0sDk83HVn2gA+VGI4H72gVOXLmDG6HoMf68lz8sDBDmxtYuwGkcERgP4uJXKyzddhBg0FkpiUr0ZxJNeTgc3B7gSeBGX2Uyir6qBRLSdSnk9p44T89V+JYYKYRFTCFoqVctVTTVDgwRsadc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.206.34.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097604tfc7a8ba3 X-QQ-Originating-IP: Unax/578hb1wbtzIY/X7l5HHwbQgTucIdqfrtq2mHXs= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:20 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 14314802722129751210 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 08/15] net: rnpgbe: Add irq support Date: Mon, 21 Jul 2025 19:32:31 +0800 Message-Id: <20250721113238.18615-9-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: OBsd15jA3tvBFcTRQWgS1liArhUIRyGAJTv65DNhBkSUm8A5bg3T4vK5 p+1+ICA5J8DAPJST4e1hremjC/zzKryd9L7VkrV7HJ730yQBN7xYLsN8UeD0gNKRDruumZL SdBRO47gvPy+J2+/7J2HLS710Ti4Y9wQslxMAy/yV8NfUKRlfHEakkvFUiUwtOfobXeItFl HU0ELMP95wjzDsGAp1xCJVlzMSgiqFM1JTsHl8OR0f02Duz1PI/cRAURMrAuOxVSYjuo5hm iqMAqHE1TT54exq85sPyIes51mKtKy5upztiX0/Yw2ct9YiUZCQT8i7kDYL0wXj+6hcamfX Vj4GrNcDNLcAUEnRbPLE1lJ0VQtn8Gv8ldWz2f+MPtQ1h5EX3bCuhFA4mY2vFj/54sY/Ohg YvyVQ7yKSbmI/CrQGz7RF8wsSUcmHKQ3Dszy9bPxK4ByQW/N2eAqG0EQ3dlj20mcw2b+Pim iaf8bMPkMfTrWGQHbPWjE9uPvPKoKBpWFtYnX955ikJzRJAb1omzS+NQI4TeA+uvcodpf+J Qxri+D1gVgIzGqJKttot3WDz3xLJJpMBAFLd0up+Q4QCaDSUBMUXdmrxm3svGvEFGXlFkxg cR1Ale7sBeE78+BVeH0U2EhZAYxBihYulDQ5CmE0+fBuccgw5iPA8VC20jFjl0VBZIbPGRb r9HUgdDtsx5CmLvioPW++YAHt5nHGArJ5HthluwUBF8lBCoXZ1HnleNGUgT3J8f0rq3qi7o lo9nNjTSZ1jHdyMT14FrYUTU7aK8SZV2DV+LvhcGZ56Sn+DNC4WB2VZj5AC8Q20tUHcznz5 Lf2T1D9JRyDgi+iPKHfR/sGTBYKtb9Deme1PUZtof4+sBalgkPrPdj6wSqoTkHfJE+riwkw mJm90LTv4jEgsOPIsQYBo7K4O9N44tdZZ1BXJKbZIBUWQ3SF8t/P7wrevY4YvhpWEC4XtCM NlPapYaq4kPMK32BKkswMV4IVrvg1dE8MqrWtT+vRlt34VpPcqzNwLPzXSpy+gES3lP9X/Y ihZsgJ0PORPs7IhA4hP33/u/dDaW2L6Lsb9rkSFw== X-QQ-XMRINFO: NyFYKkN4Ny6FSmKK/uo/jdU= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize irq functions for driver use. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/Makefile | 3 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 152 ++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 500 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 28 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 145 ++++- 6 files changed, 827 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ether= net/mucse/rnpgbe/Makefile index db7d3a8140b2..c5a41406fd60 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile @@ -9,4 +9,5 @@ rnpgbe-objs :=3D rnpgbe_main.o \ rnpgbe_chip.o \ rnpgbe_mbx.o \ rnpgbe_mbx_fw.o \ - rnpgbe_sfc.o + rnpgbe_sfc.o \ + rnpgbe_lib.o diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 30b5400241c3..212e5b8fd7b4 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -7,6 +7,7 @@ #include #include #include +#include =20 extern const struct rnpgbe_info rnpgbe_n500_info; extern const struct rnpgbe_info rnpgbe_n210_info; @@ -234,6 +235,7 @@ struct mucse_hw { struct mucse_addr_filter_info addr_ctrl; u32 feature_flags; u32 flags; +#define M_FLAG_MSI_CAPABLE BIT(0) #define M_FLAGS_INIT_MAC_ADDRESS BIT(27) u32 driver_version; u16 usecstocount; @@ -256,6 +258,136 @@ enum mucse_state_t { __MUCSE_EEE_REMOVE, }; =20 +enum irq_mode_enum { + irq_mode_legency, + irq_mode_msi, + irq_mode_msix, +}; + +struct mucse_queue_stats { + u64 packets; + u64 bytes; +}; + +struct mucse_tx_queue_stats { + u64 restart_queue; + u64 tx_busy; + u64 tx_done_old; + u64 clean_desc; + u64 poll_count; + u64 irq_more_count; + u64 send_bytes; + u64 send_bytes_to_hw; + u64 todo_update; + u64 send_done_bytes; + u64 vlan_add; + u64 tx_next_to_clean; + u64 tx_irq_miss; + u64 tx_equal_count; + u64 tx_clean_times; + u64 tx_clean_count; +}; + +struct mucse_rx_queue_stats { + u64 driver_drop_packets; + u64 rsc_count; + u64 rsc_flush; + u64 non_eop_descs; + u64 alloc_rx_page_failed; + u64 alloc_rx_buff_failed; + u64 alloc_rx_page; + u64 csum_err; + u64 csum_good; + u64 poll_again_count; + u64 vlan_remove; + u64 rx_next_to_clean; + u64 rx_irq_miss; + u64 rx_equal_count; + u64 rx_clean_times; + u64 rx_clean_count; +}; + +struct mucse_ring { + struct mucse_ring *next; + struct mucse_q_vector *q_vector; + struct net_device *netdev; + struct device *dev; + void *desc; + union { + struct mucse_tx_buffer *tx_buffer_info; + struct mucse_rx_buffer *rx_buffer_info; + }; + unsigned long last_rx_timestamp; + unsigned long state; + u8 __iomem *ring_addr; + u8 __iomem *tail; + u8 __iomem *dma_int_stat; + u8 __iomem *dma_int_mask; + u8 __iomem *dma_int_clr; + dma_addr_t dma; + unsigned int size; + u32 ring_flags; +#define M_RING_FLAG_DELAY_SETUP_RX_LEN BIT(0) +#define M_RING_FLAG_CHANGE_RX_LEN BIT(1) +#define M_RING_FLAG_DO_RESET_RX_LEN BIT(2) +#define M_RING_SKIP_TX_START BIT(3) +#define M_RING_NO_TUNNEL_SUPPORT BIT(4) +#define M_RING_SIZE_CHANGE_FIX BIT(5) +#define M_RING_SCATER_SETUP BIT(6) +#define M_RING_STAGS_SUPPORT BIT(7) +#define M_RING_DOUBLE_VLAN_SUPPORT BIT(8) +#define M_RING_VEB_MULTI_FIX BIT(9) +#define M_RING_IRQ_MISS_FIX BIT(10) +#define M_RING_OUTER_VLAN_FIX BIT(11) +#define M_RING_CHKSM_FIX BIT(12) +#define M_RING_LOWER_ITR BIT(13) + u8 pfvfnum; + u16 count; + u16 temp_count; + u16 reset_count; + u8 queue_index; + u8 rnpgbe_queue_idx; + u16 next_to_use; + u16 next_to_clean; + u16 device_id; + struct mucse_queue_stats stats; + struct u64_stats_sync syncp; + union { + struct mucse_tx_queue_stats tx_stats; + struct mucse_rx_queue_stats rx_stats; + }; +} ____cacheline_internodealigned_in_smp; + +struct mucse_ring_container { + struct mucse_ring *ring; + u16 work_limit; + u16 count; +}; + +struct mucse_q_vector { + struct mucse *mucse; + int v_idx; + u16 itr_rx; + u16 itr_tx; + struct mucse_ring_container rx, tx; + struct napi_struct napi; + cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; + int numa_node; + struct rcu_head rcu; /* to avoid race with update stats on free */ + u32 vector_flags; +#define M_QVECTOR_FLAG_IRQ_MISS_CHECK BIT(0) +#define M_QVECTOR_FLAG_ITR_FEATURE BIT(1) +#define M_QVECTOR_FLAG_REDUCE_TX_IRQ_MISS BIT(2) + char name[IFNAMSIZ + 17]; + /* for dynamic allocation of rings associated with this q_vector */ + struct mucse_ring ring[0] ____cacheline_internodealigned_in_smp; +}; + +#define MAX_TX_QUEUES (8) +#define MAX_RX_QUEUES (8) +#define MAX_Q_VECTORS (64) + struct mucse { struct net_device *netdev; struct pci_dev *pdev; @@ -264,19 +396,37 @@ struct mucse { /* board number */ u16 bd_number; u16 tx_work_limit; + u32 flags; +#define M_FLAG_NEED_LINK_UPDATE BIT(0) +#define M_FLAG_MSIX_ENABLED BIT(1) +#define M_FLAG_MSI_ENABLED BIT(2) u32 flags2; #define M_FLAG2_NO_NET_REG BIT(0) +#define M_FLAG2_INSMOD BIT(1) u32 priv_flags; #define M_PRIV_FLAG_TX_COALESCE BIT(25) #define M_PRIV_FLAG_RX_COALESCE BIT(26) + struct mucse_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; int tx_ring_item_count; + int num_tx_queues; + struct mucse_ring *rx_ring[MAX_RX_QUEUES] ____cacheline_aligned_in_smp; int rx_ring_item_count; + int num_rx_queues; + int num_other_vectors; + int irq_mode; + struct msix_entry *msix_entries; + struct mucse_q_vector *q_vector[MAX_Q_VECTORS]; + int num_q_vectors; + int max_q_vectors; + int q_vector_off; int napi_budge; u16 rx_usecs; u16 rx_frames; u16 tx_frames; u16 tx_usecs; unsigned long state; + struct timer_list service_timer; + struct work_struct service_task; char name[60]; }; =20 @@ -320,4 +470,6 @@ struct rnpgbe_info { #define mucse_dbg(mucse, fmt, arg...) \ dev_dbg(&(mucse)->pdev->dev, fmt, ##arg) =20 +void rnpgbe_service_event_schedule(struct mucse *mucse); + #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index fc179eb8c516..fa8317ae7642 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -340,6 +340,8 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw = *hw) hw->max_vfs =3D 7; hw->min_len_cap =3D RNPGBE_MIN_LEN; hw->max_len_cap =3D RNPGBE_MAX_LEN; + hw->max_msix_vectors =3D 26; + hw->flags |=3D M_FLAG_MSI_CAPABLE; memcpy(&hw->ops, &hw_ops_n500, sizeof(hw->ops)); } =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c new file mode 100644 index 000000000000..2bf8a7f7f303 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#include "rnpgbe.h" +#include "rnpgbe_lib.h" + +/** + * rnpgbe_set_rss_queues - Allocate queues for RSS + * @mucse: pointer to private structure + * + * Try to determine queue num with rss. + * + * @return: true on success, negative on failure + **/ +static bool rnpgbe_set_rss_queues(struct mucse *mucse) +{ + return true; +} + +/** + * rnpgbe_set_num_queues - Allocate queues for device, feature dependent + * @mucse: pointer to private structure + * + * Determine tx/rx queue nums + **/ +static void rnpgbe_set_num_queues(struct mucse *mucse) +{ + /* Start with base case */ + mucse->num_tx_queues =3D 1; + mucse->num_rx_queues =3D 1; + + rnpgbe_set_rss_queues(mucse); +} + +/** + * rnpgbe_acquire_msix_vectors - Allocate msix vectors + * @mucse: pointer to private structure + * @vectors: number of msix vectors + **/ +static int rnpgbe_acquire_msix_vectors(struct mucse *mucse, + int vectors) +{ + int err; + + err =3D pci_enable_msix_range(mucse->pdev, mucse->msix_entries, + vectors, vectors); + if (err < 0) { + kfree(mucse->msix_entries); + mucse->msix_entries =3D NULL; + return err; + } + + vectors -=3D mucse->num_other_vectors; + /* setup true q_vectors num */ + mucse->num_q_vectors =3D min(vectors, mucse->max_q_vectors); + + return 0; +} + +/** + * rnpgbe_set_interrupt_capability - set MSI-X or MSI if supported + * @mucse: pointer to private structure + * + * Attempt to configure the interrupts using the best available + * capabilities of the hardware. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_set_interrupt_capability(struct mucse *mucse) +{ + int irq_mode_back =3D mucse->irq_mode; + struct mucse_hw *hw =3D &mucse->hw; + int vector, v_budget, err =3D 0; + + v_budget =3D min_t(int, mucse->num_tx_queues, mucse->num_rx_queues); + v_budget =3D min_t(int, v_budget, num_online_cpus()); + v_budget +=3D mucse->num_other_vectors; + v_budget =3D min_t(int, v_budget, hw->max_msix_vectors); + + if (mucse->irq_mode =3D=3D irq_mode_msix) { + mucse->msix_entries =3D kcalloc(v_budget, + sizeof(struct msix_entry), + GFP_KERNEL); + + if (!mucse->msix_entries) + return -ENOMEM; + + for (vector =3D 0; vector < v_budget; vector++) + mucse->msix_entries[vector].entry =3D vector; + + err =3D rnpgbe_acquire_msix_vectors(mucse, v_budget); + if (!err) { + if (mucse->num_other_vectors) + mucse->q_vector_off =3D 1; + mucse->flags |=3D M_FLAG_MSIX_ENABLED; + goto out; + } + kfree(mucse->msix_entries); + /* if has msi capability try it */ + if (hw->flags & M_FLAG_MSI_CAPABLE) + mucse->irq_mode =3D irq_mode_msi; + } + /* if has msi capability or set irq_mode */ + if (mucse->irq_mode =3D=3D irq_mode_msi) { + err =3D pci_enable_msi(mucse->pdev); + /* msi mode use only 1 irq */ + if (!err) + mucse->flags |=3D M_FLAG_MSI_ENABLED; + } + /* write back origin irq_mode for next time */ + mucse->irq_mode =3D irq_mode_back; + /* legacy and msi only 1 vectors */ + mucse->num_q_vectors =3D 1; + err =3D 0; +out: + return err; +} + +/** + * update_ring_count - update ring num + * @mucse: pointer to private structure + * + * update_ring_count only update ring num when driver insmod + **/ +static void update_ring_count(struct mucse *mucse) +{ + if (mucse->flags2 & M_FLAG2_INSMOD) + return; + + mucse->flags2 |=3D M_FLAG2_INSMOD; + /* limit ring count if in msi or legacy mode */ + if (!(mucse->flags & M_FLAG_MSIX_ENABLED)) { + mucse->num_tx_queues =3D 1; + mucse->num_rx_queues =3D 1; + } +} + +/** + * mucse_add_ring - add ring to ring container + * @ring: ring to be added + * @head: ring container + **/ +static void mucse_add_ring(struct mucse_ring *ring, + struct mucse_ring_container *head) +{ + ring->next =3D head->ring; + head->ring =3D ring; + head->count++; +} + +/** + * rnpgbe_poll - NAPI polling RX/TX cleanup routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * Clean all queues associated with a q_vector + * + * @return: amount of work done in this call + **/ +static int rnpgbe_poll(struct napi_struct *napi, int budget) +{ + return 0; +} + +/** + * rnpgbe_alloc_q_vector - Allocate memory for a single interrupt vector + * @mucse: pointer to private structure + * @eth_queue_idx: queue_index idx for this q_vector + * @v_idx: index of vector used for this q_vector + * @r_idx: total number of rings to allocate + * @r_count: ring count + * @step: ring step + * + * @return: 0 on success. If allocation fails we return -ENOMEM. + **/ +static int rnpgbe_alloc_q_vector(struct mucse *mucse, + int eth_queue_idx, int v_idx, int r_idx, + int r_count, int step) +{ + int rxr_idx =3D r_idx, txr_idx =3D r_idx; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_q_vector *q_vector; + int txr_count, rxr_count, idx; + struct mucse_dma_info *dma; + struct mucse_ring *ring; + int node =3D NUMA_NO_NODE; + int ring_count, size; + int cpu_offset =3D 0; + int cpu =3D -1; + + dma =3D &hw->dma; + txr_count =3D r_count; + rxr_count =3D r_count; + ring_count =3D txr_count + rxr_count; + size =3D sizeof(struct mucse_q_vector) + + (sizeof(struct mucse_ring) * ring_count); + + /* should minis mucse->q_vector_off */ + if (cpu_online(cpu_offset + v_idx - mucse->q_vector_off)) { + cpu =3D cpu_offset + v_idx - mucse->q_vector_off; + node =3D cpu_to_node(cpu); + } + + /* allocate q_vector and rings */ + q_vector =3D kzalloc_node(size, GFP_KERNEL, node); + if (!q_vector) + q_vector =3D kzalloc(size, GFP_KERNEL); + if (!q_vector) + return -ENOMEM; + + /* setup affinity mask and node */ + if (cpu !=3D -1) + cpumask_set_cpu(cpu, &q_vector->affinity_mask); + q_vector->numa_node =3D node; + + netif_napi_add_weight(mucse->netdev, &q_vector->napi, rnpgbe_poll, + mucse->napi_budge); + /* tie q_vector and mucse together */ + mucse->q_vector[v_idx - mucse->q_vector_off] =3D q_vector; + q_vector->mucse =3D mucse; + q_vector->v_idx =3D v_idx; + /* initialize pointer to rings */ + ring =3D q_vector->ring; + + for (idx =3D 0; idx < txr_count; idx++) { + /* assign generic ring traits */ + ring->dev =3D &mucse->pdev->dev; + ring->netdev =3D mucse->netdev; + /* configure backlink on ring */ + ring->q_vector =3D q_vector; + /* update q_vector Tx values */ + mucse_add_ring(ring, &q_vector->tx); + + /* apply Tx specific ring traits */ + ring->count =3D mucse->tx_ring_item_count; + ring->queue_index =3D eth_queue_idx + idx; + /* it is used to location hw reg */ + ring->rnpgbe_queue_idx =3D txr_idx; + ring->ring_addr =3D dma->dma_ring_addr + RING_OFFSET(txr_idx); + ring->dma_int_stat =3D ring->ring_addr + DMA_INT_STAT; + ring->dma_int_mask =3D ring->ring_addr + DMA_INT_MASK; + ring->dma_int_clr =3D ring->ring_addr + DMA_INT_CLR; + ring->device_id =3D mucse->pdev->device; + ring->pfvfnum =3D hw->pfvfnum; + /* not support tunnel */ + ring->ring_flags |=3D M_RING_NO_TUNNEL_SUPPORT; + /* assign ring to mucse */ + mucse->tx_ring[ring->queue_index] =3D ring; + /* update count and index */ + txr_idx +=3D step; + /* push pointer to next ring */ + ring++; + } + + for (idx =3D 0; idx < rxr_count; idx++) { + /* assign generic ring traits */ + ring->dev =3D &mucse->pdev->dev; + ring->netdev =3D mucse->netdev; + /* configure backlink on ring */ + ring->q_vector =3D q_vector; + /* update q_vector Rx values */ + mucse_add_ring(ring, &q_vector->rx); + /* apply Rx specific ring traits */ + ring->count =3D mucse->rx_ring_item_count; + /* rnpgbe_queue_idx can be changed after */ + ring->queue_index =3D eth_queue_idx + idx; + ring->rnpgbe_queue_idx =3D rxr_idx; + ring->ring_addr =3D dma->dma_ring_addr + RING_OFFSET(rxr_idx); + ring->dma_int_stat =3D ring->ring_addr + DMA_INT_STAT; + ring->dma_int_mask =3D ring->ring_addr + DMA_INT_MASK; + ring->dma_int_clr =3D ring->ring_addr + DMA_INT_CLR; + ring->device_id =3D mucse->pdev->device; + ring->pfvfnum =3D hw->pfvfnum; + + ring->ring_flags |=3D M_RING_NO_TUNNEL_SUPPORT; + ring->ring_flags |=3D M_RING_STAGS_SUPPORT; + /* assign ring to mucse */ + mucse->rx_ring[ring->queue_index] =3D ring; + /* update count and index */ + rxr_idx +=3D step; + /* push pointer to next ring */ + ring++; + } + + q_vector->vector_flags |=3D M_QVECTOR_FLAG_ITR_FEATURE; + q_vector->itr_rx =3D mucse->rx_usecs; + + return 0; +} + +/** + * rnpgbe_free_q_vector - Free memory allocated for specific interrupt vec= tor + * @mucse: pointer to private structure + * @v_idx: Index of vector to be freed + * + * This function frees the memory allocated to the q_vector. In addition = if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void rnpgbe_free_q_vector(struct mucse *mucse, int v_idx) +{ + struct mucse_q_vector *q_vector =3D mucse->q_vector[v_idx]; + struct mucse_ring *ring; + + mucse_for_each_ring(ring, q_vector->tx) + mucse->tx_ring[ring->queue_index] =3D NULL; + + mucse_for_each_ring(ring, q_vector->rx) + mucse->rx_ring[ring->queue_index] =3D NULL; + + mucse->q_vector[v_idx] =3D NULL; + netif_napi_del(&q_vector->napi); + kfree_rcu(q_vector, rcu); +} + +/** + * rnpgbe_alloc_q_vectors - Allocate memory for interrupt vectors + * @mucse: pointer to private structure + * + * @return: 0 if success. if allocation fails we return -ENOMEM. + **/ +static int rnpgbe_alloc_q_vectors(struct mucse *mucse) +{ + int err, ring_cnt, v_remaing =3D mucse->num_q_vectors; + int r_remaing =3D min_t(int, mucse->num_tx_queues, + mucse->num_rx_queues); + int v_idx =3D mucse->q_vector_off; + int q_vector_nums =3D 0; + int eth_queue_idx =3D 0; + int ring_step =3D 1; + int ring_idx =3D 0; + + /* can support multi rings in one q_vector */ + for (; r_remaing > 0 && v_remaing > 0; v_remaing--) { + ring_cnt =3D DIV_ROUND_UP(r_remaing, v_remaing); + err =3D rnpgbe_alloc_q_vector(mucse, eth_queue_idx, + v_idx, ring_idx, ring_cnt, + ring_step); + if (err) + goto err_out; + ring_idx +=3D ring_step * ring_cnt; + r_remaing -=3D ring_cnt; + v_idx++; + q_vector_nums++; + eth_queue_idx +=3D ring_cnt; + } + /* should fix the real used q_vectors_nums */ + mucse->num_q_vectors =3D q_vector_nums; + + return 0; + +err_out: + mucse->num_tx_queues =3D 0; + mucse->num_rx_queues =3D 0; + mucse->num_q_vectors =3D 0; + + while (v_idx--) + rnpgbe_free_q_vector(mucse, v_idx); + + return -ENOMEM; +} + +/** + * rnpgbe_cache_ring_rss - Descriptor ring to register mapping for RSS + * @mucse: pointer to private structure + * + * Cache the descriptor ring offsets for RSS to the assigned rings. + * + **/ +static void rnpgbe_cache_ring_rss(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma; + struct mucse_ring *ring; + int ring_step =3D 1; + int i; + + dma =3D &hw->dma; + /* some ring alloc rules can be added here */ + for (i =3D 0; i < mucse->num_rx_queues; i++) { + ring =3D mucse->tx_ring[i]; + ring->rnpgbe_queue_idx =3D i * ring_step; + ring->ring_addr =3D dma->dma_ring_addr + + RING_OFFSET(ring->rnpgbe_queue_idx); + + ring->dma_int_stat =3D ring->ring_addr + DMA_INT_STAT; + ring->dma_int_mask =3D ring->ring_addr + DMA_INT_MASK; + ring->dma_int_clr =3D ring->ring_addr + DMA_INT_CLR; + } + + for (i =3D 0; i < mucse->num_tx_queues; i++) { + ring =3D mucse->rx_ring[i]; + ring->rnpgbe_queue_idx =3D i * ring_step; + ring->ring_addr =3D dma->dma_ring_addr + + RING_OFFSET(ring->rnpgbe_queue_idx); + ring->dma_int_stat =3D ring->ring_addr + DMA_INT_STAT; + ring->dma_int_mask =3D ring->ring_addr + DMA_INT_MASK; + ring->dma_int_clr =3D ring->ring_addr + DMA_INT_CLR; + } +} + +/** + * rnpgbe_cache_ring_register - Descriptor ring to register mapping + * @mucse: pointer to private structure + * + * Reset ring reg here to satisfy feature. + **/ +static void rnpgbe_cache_ring_register(struct mucse *mucse) +{ + rnpgbe_cache_ring_rss(mucse); +} + +/** + * rnpgbe_free_q_vectors - Free memory allocated for interrupt vectors + * @mucse: pointer to private structure + * + * This function frees the memory allocated to the q_vectors. In addition= if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void rnpgbe_free_q_vectors(struct mucse *mucse) +{ + int v_idx =3D mucse->num_q_vectors; + + mucse->num_rx_queues =3D 0; + mucse->num_tx_queues =3D 0; + mucse->num_q_vectors =3D 0; + + while (v_idx--) + rnpgbe_free_q_vector(mucse, v_idx); +} + +/** + * rnpgbe_reset_interrupt_capability - Reset irq capability setup + * @mucse: pointer to private structure + **/ +static void rnpgbe_reset_interrupt_capability(struct mucse *mucse) +{ + if (mucse->flags & M_FLAG_MSIX_ENABLED) + pci_disable_msix(mucse->pdev); + else if (mucse->flags & M_FLAG_MSI_CAPABLE) + pci_disable_msi(mucse->pdev); + + kfree(mucse->msix_entries); + mucse->msix_entries =3D NULL; + mucse->q_vector_off =3D 0; + mucse->flags &=3D (~M_FLAG_MSIX_ENABLED); + mucse->flags &=3D (~M_FLAG_MSI_ENABLED); +} + +/** + * rnpgbe_init_interrupt_scheme - Determine proper interrupt scheme + * @mucse: pointer to private structure + * + * We determine which interrupt scheme to use based on... + * - Hardware queue count + * - cpu numbers + * - irq mode (msi/legacy force 1) + * + * @return: 0 on success, negative on failure + **/ +int rnpgbe_init_interrupt_scheme(struct mucse *mucse) +{ + int err; + + /* Number of supported queues */ + rnpgbe_set_num_queues(mucse); + /* Set interrupt mode */ + err =3D rnpgbe_set_interrupt_capability(mucse); + if (err) + goto err_set_interrupt; + /* update ring num only init */ + update_ring_count(mucse); + err =3D rnpgbe_alloc_q_vectors(mucse); + if (err) + goto err_alloc_q_vectors; + rnpgbe_cache_ring_register(mucse); + set_bit(__MUCSE_DOWN, &mucse->state); + + return 0; + +err_alloc_q_vectors: + rnpgbe_reset_interrupt_capability(mucse); +err_set_interrupt: + return err; +} + +/** + * rnpgbe_clear_interrupt_scheme - Clear the current interrupt scheme sett= ings + * @mucse: pointer to private structure + * + * Clear interrupt specific resources and reset the structure + **/ +void rnpgbe_clear_interrupt_scheme(struct mucse *mucse) +{ + mucse->num_tx_queues =3D 0; + mucse->num_rx_queues =3D 0; + rnpgbe_free_q_vectors(mucse); + rnpgbe_reset_interrupt_capability(mucse); +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h new file mode 100644 index 000000000000..0df519a50185 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_LIB_H +#define _RNPGBE_LIB_H + +#include "rnpgbe.h" + +#define RING_OFFSET(n) (0x100 * (n)) +#define DMA_RX_START (0x10) +#define DMA_RX_READY (0x14) +#define DMA_TX_START (0x18) +#define DMA_TX_READY (0x1c) +#define DMA_INT_MASK (0x24) +#define TX_INT_MASK (0x02) +#define RX_INT_MASK (0x01) +#define DMA_INT_CLR (0x28) +#define DMA_INT_STAT (0x20) + +#define mucse_for_each_ring(pos, head)\ + for (typeof((head).ring) __pos =3D (head).ring;\ + __pos ? ({ pos =3D __pos; 1; }) : 0;\ + __pos =3D __pos->next) + +int rnpgbe_init_interrupt_scheme(struct mucse *mucse); +void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); + +#endif /* _RNPGBE_LIB_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 1338ef01f545..8fc1af1c00bc 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -12,6 +12,7 @@ #include "rnpgbe.h" #include "rnpgbe_mbx_fw.h" #include "rnpgbe_sfc.h" +#include "rnpgbe_lib.h" =20 char rnpgbe_driver_name[] =3D "rnpgbe"; static const struct rnpgbe_info *rnpgbe_info_tbl[] =3D { @@ -38,6 +39,50 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +static struct workqueue_struct *rnpgbe_wq; + +/** + * rnpgbe_service_event_schedule - schedule task + * @mucse: pointer to private structure + **/ +void rnpgbe_service_event_schedule(struct mucse *mucse) +{ + if (!test_bit(__MUCSE_DOWN, &mucse->state) && + !test_and_set_bit(__MUCSE_SERVICE_SCHED, &mucse->state)) + queue_work(rnpgbe_wq, &mucse->service_task); +} + +/** + * rnpgbe_service_timer - Timer Call-back + * @t: pointer to timer_list + **/ +static void rnpgbe_service_timer(struct timer_list *t) +{ + struct mucse *mucse =3D timer_container_of(mucse, t, service_timer); + unsigned long next_event_offset; + bool ready =3D true; + + /* poll faster when waiting for link */ + if (mucse->flags & M_FLAG_NEED_LINK_UPDATE) + next_event_offset =3D HZ / 10; + else + next_event_offset =3D HZ; + /* Reset the timer */ + if (!test_bit(__MUCSE_REMOVE, &mucse->state)) + mod_timer(&mucse->service_timer, next_event_offset + jiffies); + + if (ready) + rnpgbe_service_event_schedule(mucse); +} + +/** + * rnpgbe_service_task - manages and runs subtasks + * @work: pointer to work_struct containing our data + **/ +static void rnpgbe_service_task(struct work_struct *work) +{ +} + /** * rnpgbe_sw_init - Init driver private status * @mucse: pointer to private structure @@ -65,11 +110,84 @@ static int rnpgbe_sw_init(struct mucse *mucse) /* set default ring sizes */ mucse->tx_ring_item_count =3D M_DEFAULT_TXD; mucse->rx_ring_item_count =3D M_DEFAULT_RXD; + mucse->irq_mode =3D irq_mode_msix; + mucse->max_q_vectors =3D hw->max_msix_vectors; + mucse->num_other_vectors =3D 1; set_bit(__MUCSE_DOWN, &mucse->state); =20 return 0; } =20 +/** + * remove_mbx_irq - Remove mbx Routine + * @mucse: pointer to private structure + **/ +static void remove_mbx_irq(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + + if (mucse->num_other_vectors =3D=3D 0) + return; + /* only msix use indepented intr */ + if (mucse->flags & M_FLAG_MSIX_ENABLED) { + hw->mbx.ops.configure(hw, + mucse->msix_entries[0].entry, + false); + if (hw->mbx.irq_enabled) { + free_irq(mucse->msix_entries[0].vector, mucse); + hw->mbx.irq_enabled =3D false; + } + } +} + +/** + * rnpgbe_msix_other - Other irq handler + * @irq: irq num + * @data: private data + * + * @return: IRQ_HANDLED + **/ +static irqreturn_t rnpgbe_msix_other(int irq, void *data) +{ + struct mucse *mucse =3D (struct mucse *)data; + + set_bit(__MUCSE_IN_IRQ, &mucse->state); + clear_bit(__MUCSE_IN_IRQ, &mucse->state); + + return IRQ_HANDLED; +} + +/** + * register_mbx_irq - Regist mbx Routine + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +static int register_mbx_irq(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + struct net_device *netdev =3D mucse->netdev; + int err =3D 0; + + /* for mbx:vector0 */ + if (mucse->num_other_vectors =3D=3D 0) + return err; + /* only do this in msix mode */ + if (mucse->flags & M_FLAG_MSIX_ENABLED) { + err =3D request_irq(mucse->msix_entries[0].vector, + rnpgbe_msix_other, 0, netdev->name, + mucse); + if (err) + goto err_mbx; + hw->mbx.ops.configure(hw, + mucse->msix_entries[0].entry, + true); + hw->mbx.irq_enabled =3D true; + } +err_mbx: + return err; +} + /** * rnpgbe_add_adapter - add netdev for this pci_dev * @pdev: PCI device information structure @@ -165,7 +283,6 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, hw->mbx.ops.init_params(hw); /* echo fw driver insmod */ hw->ops.driver_status(hw, true, mucse_driver_insmod); - err =3D mucse_mbx_get_capability(hw); if (err) { dev_err(&pdev->dev, @@ -190,9 +307,20 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, netdev->priv_flags |=3D IFF_SUPP_NOFCS; eth_hw_addr_set(netdev, hw->perm_addr); memcpy(netdev->perm_addr, hw->perm_addr, netdev->addr_len); + ether_addr_copy(hw->addr, hw->perm_addr); + timer_setup(&mucse->service_timer, rnpgbe_service_timer, 0); + INIT_WORK(&mucse->service_task, rnpgbe_service_task); + clear_bit(__MUCSE_SERVICE_SCHED, &mucse->state); + err =3D rnpgbe_init_interrupt_scheme(mucse); + if (err) + goto err_free_net; + err =3D register_mbx_irq(mucse); + if (err) + goto err_free_irq; =20 return 0; - +err_free_irq: + rnpgbe_clear_interrupt_scheme(mucse); err_free_net: free_netdev(netdev); return err; @@ -261,7 +389,11 @@ static void rnpgbe_rm_adapter(struct mucse *mucse) =20 rnpgbe_devlink_unregister(mucse); netdev =3D mucse->netdev; + cancel_work_sync(&mucse->service_task); + timer_delete_sync(&mucse->service_timer); hw->ops.driver_status(hw, false, mucse_driver_insmod); + remove_mbx_irq(mucse); + rnpgbe_clear_interrupt_scheme(mucse); free_netdev(netdev); mucse->netdev =3D NULL; } @@ -300,6 +432,8 @@ static void rnpgbe_dev_shutdown(struct pci_dev *pdev, =20 *enable_wake =3D false; netif_device_detach(netdev); + remove_mbx_irq(mucse); + rnpgbe_clear_interrupt_scheme(mucse); pci_disable_device(pdev); } =20 @@ -341,6 +475,12 @@ static int __init rnpgbe_init_module(void) { int ret; =20 + rnpgbe_wq =3D create_singlethread_workqueue(rnpgbe_driver_name); + if (!rnpgbe_wq) { + pr_err("%s: Failed to create workqueue\n", rnpgbe_driver_name); + return -ENOMEM; + } + ret =3D pci_register_driver(&rnpgbe_driver); if (ret) return ret; @@ -358,6 +498,7 @@ module_init(rnpgbe_init_module); static void __exit rnpgbe_exit_module(void) { pci_unregister_driver(&rnpgbe_driver); + destroy_workqueue(rnpgbe_wq); } =20 module_exit(rnpgbe_exit_module); --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgsg1.qq.com (smtpbgsg1.qq.com [54.254.200.92]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BDE942D29D8; Mon, 21 Jul 2025 11:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.254.200.92 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097682; cv=none; b=rH5Pc3NLyZ+EqQ2NWOu3rxqP8MSjWT3f/4UfciyW9IbOoAGJG7umHwFqrfynNZS1b0zrtWzLwjcim4TEfK2/xJvT8x/TJBLaGgRa1zBc+5N0ZepyKFDv0HiB4TOBikdV+28THuDjgQ7h3JEoEp7Fn+aQpajlIgrlULHnIohWGhQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097682; c=relaxed/simple; bh=DTUYV1e6EHZF9z0ThQa5/erkc+t56AU4jOeZWsYYigw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nmhLMOy0knQpzMsF+0PBGe4XMOQzic9EqtTsXJDvDlIye+WR/fb4C3FQgTZlFP0BulrVFK69WMktKWHlusnYcHKNUzglD7YWEwKfhYIldEGHVimcs6HRUZmIYso+alzZJn6h6ewbN9U+tlfWFjD1TGw0m7xEjT+D7oorcuZVYFk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.254.200.92 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097608tbf371e3e X-QQ-Originating-IP: zGrKS85rYRkLmemFiNjwNtfEjBmyv8pxC+l/gyQv9Jo= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:25 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 7820022088678493601 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 09/15] net: rnpgbe: Add netdev register and init tx/rx memory Date: Mon, 21 Jul 2025 19:32:32 +0800 Message-Id: <20250721113238.18615-10-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MzDEtv5QipDt9Snp9S65y16728JGm38IG4udaC7Qk7QG12b0bF//73Kg ++xtirktcBoreYCb9YcelD7RUz7VWD1nXLVQ8e7IsYE43A8s9xdIuzxSwBc2ZcYTmD175Wx xnI/OFE7l1MFwZhlya6SruSR1j1j40oN+2pfT1lpGoGU+xdnDEWRwDGLEfkygAEVVTJeaw1 3kk4BkqrSWfichvuIJOmfZ/j5HE5xh0shXOddqULpAUbUIU6a8OiCMTkSWs+ykmgxMjVewZ GzkHbA1f8iRCah698Du2/HYFBXv4AO+fzrEMpqHKm94qZk0kSMNI6BKb7EaXy4B2C3F5aVB E1ffZYKgNEYfDb/zczMXQ67l2sM3mbGSM0D1vRgpBs1BiZSoc8MORBcojgtBKr23lkz7X7o xgd5HA4DrzeUKGv+0Bm2fzQxSF4sBhSSdsb6cjlGdwwPyvNiUw4pGSXPKTBfMpPkbssLI4l reazDG0GbH5UnC/1olugXHguYDkfsglfdugET9Ejx/Cw3/wWU2oJPFvm1oKNknvYC6Lions 26bL6cpkmddWQ0VHi7Z3vkAHS1Sh0qH+NnUTr/NaOshcOZHaAzK05C+7kWOW3CCQGx24Wdj YhcZ0hdkqWyTbBooytaoo4o2+EObKLHj/lNCMyylbeh/Bognf4goIs3ajEXg/0jTvtLmGsJ smC2rpoLp97rj9jBJpZqP84IRIAb65qQwbsdZ7eeXDqhcbQXbG3MKRQtVEoaHI8TZEJudT3 zYuI8Py6zXrzKeqat4w+ma9MhlNrQzYmU/b20+KuWBHbtYPxSJYc1fAQOMEhKrvmQOHSLXq SjL7radX3RrehZECr47DFvIwrA1XnotsPlxr1ubAVtrTTC7EPDjHpznmmOy1/4jyIZBzH/P UW2LD7I8XrMfzzgT0boza9rkNORXnVCFeJwSfU2J46ATTF+Tr/1PuK1a8tsD1H1v5c6fRJw rqM+G0zj4NXVM/NiKTfwKvwHXpH8D1WH9Wu86fcSSGlHRMLYhgIuury0jAcN8jF0/mZQLt3 uEJ4sjs7L67DVS2tyhtVoUJp8OH4ac3DNjzttb3lCscLQjKX4xM+gOLR1A8nk= X-QQ-XMRINFO: OWPUhxQsoeAVDbp3OJHYyFg= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize tx/rx memory for tx/rx desc. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 140 +++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 355 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 94 ++++- 4 files changed, 589 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 212e5b8fd7b4..cb0d73589687 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -248,6 +248,7 @@ struct mucse_hw { }; =20 enum mucse_state_t { + __MUCSE_TESTING, __MUCSE_DOWN, __MUCSE_SERVICE_SCHED, __MUCSE_PTP_TX_IN_PROGRESS, @@ -307,6 +308,129 @@ struct mucse_rx_queue_stats { u64 rx_clean_count; }; =20 +union rnpgbe_rx_desc { + struct { + union { + __le64 pkt_addr; + struct { + __le32 addr_lo; + __le32 addr_hi; + }; + }; + __le64 resv_cmd; +#define M_RXD_FLAG_RS (0) + }; + struct { + __le32 rss_hash; + __le16 mark; + __le16 rev1; +#define M_RX_L3_TYPE_MASK BIT(15) +#define VEB_VF_PKG BIT(1) +#define VEB_VF_IGNORE_VLAN BIT(0) +#define REV_OUTER_VLAN BIT(5) + __le16 len; + __le16 padding_len; + __le16 vlan; + __le16 cmd; +#define M_RXD_STAT_VLAN_VALID BIT(15) +#define M_RXD_STAT_STAG BIT(14) +#define M_RXD_STAT_TUNNEL_NVGRE (0x02 << 13) +#define M_RXD_STAT_TUNNEL_VXLAN (0x01 << 13) +#define M_RXD_STAT_TUNNEL_MASK (0x03 << 13) +#define M_RXD_STAT_ERR_MASK (0x1f << 8) +#define M_RXD_STAT_SCTP_MASK (0x04 << 8) +#define M_RXD_STAT_L4_MASK (0x02 << 8) +#define M_RXD_STAT_L4_SCTP (0x02 << 6) +#define M_RXD_STAT_L4_TCP (0x01 << 6) +#define M_RXD_STAT_L4_UDP (0x03 << 6) +#define M_RXD_STAT_IPV6 BIT(5) +#define M_RXD_STAT_IPV4 (0 << 5) +#define M_RXD_STAT_PTP BIT(4) +#define M_RXD_STAT_DD BIT(1) +#define M_RXD_STAT_EOP BIT(0) + } wb; +} __packed; + +struct rnpgbe_tx_desc { + union { + __le64 pkt_addr; + struct { + __le32 adr_lo; + __le32 adr_hi; + }; + }; + union { + __le64 vlan_cmd_bsz; + struct { + __le32 blen_mac_ip_len; + __le32 vlan_cmd; + }; + }; +#define M_TXD_FLAGS_VLAN_PRIO_MASK 0xe000 +#define M_TX_FLAGS_VLAN_PRIO_SHIFT 13 +#define M_TX_FLAGS_VLAN_CFI_SHIFT 12 +#define M_TXD_VLAN_VALID (0x80000000) +#define M_TXD_SVLAN_TYPE (0x02000000) +#define M_TXD_VLAN_CTRL_NOP (0x00 << 13) +#define M_TXD_VLAN_CTRL_RM_VLAN (0x20000000) +#define M_TXD_VLAN_CTRL_INSERT_VLAN (0x40000000) +#define M_TXD_L4_CSUM (0x10000000) +#define M_TXD_IP_CSUM (0x8000000) +#define M_TXD_TUNNEL_MASK (0x3000000) +#define M_TXD_TUNNEL_VXLAN (0x1000000) +#define M_TXD_TUNNEL_NVGRE (0x2000000) +#define M_TXD_L4_TYPE_UDP (0xc00000) +#define M_TXD_L4_TYPE_TCP (0x400000) +#define M_TXD_L4_TYPE_SCTP (0x800000) +#define M_TXD_FLAG_IPv4 (0) +#define M_TXD_FLAG_IPv6 (0x200000) +#define M_TXD_FLAG_TSO (0x100000) +#define M_TXD_FLAG_PTP (0x4000000) +#define M_TXD_CMD_RS (0x040000) +#define M_TXD_CMD_INNER_VLAN (0x08000000) +#define M_TXD_STAT_DD (0x020000) +#define M_TXD_CMD_EOP (0x010000) +#define M_TXD_PAD_CTRL (0x01000000) +}; + +struct mucse_tx_buffer { + struct rnpgbe_tx_desc *next_to_watch; + unsigned long time_stamp; + struct sk_buff *skb; + unsigned int bytecount; + unsigned short gso_segs; + bool gso_need_padding; + __be16 protocol; + __be16 priv_tags; + DEFINE_DMA_UNMAP_ADDR(dma); + DEFINE_DMA_UNMAP_LEN(len); + union { + u32 mss_len_vf_num; + struct { + u16 mss_len; + u8 vf_num; + u8 l4_hdr_len; + }; + }; + union { + u32 inner_vlan_tunnel_len; + struct { + u8 tunnel_hdr_len; + u8 inner_vlan_l; + u8 inner_vlan_h; + u8 resv; + }; + }; + bool ctx_flag; +}; + +struct mucse_rx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + struct page *page; + __u32 page_offset; +}; + struct mucse_ring { struct mucse_ring *next; struct mucse_q_vector *q_vector; @@ -350,6 +474,7 @@ struct mucse_ring { u16 next_to_use; u16 next_to_clean; u16 device_id; + u16 next_to_alloc; struct mucse_queue_stats stats; struct u64_stats_sync syncp; union { @@ -436,6 +561,21 @@ struct rnpgbe_info { void (*get_invariants)(struct mucse_hw *hw); }; =20 +static inline struct netdev_queue *txring_txq(const struct mucse_ring *rin= g) +{ + return netdev_get_tx_queue(ring->netdev, ring->queue_index); +} + +#define M_RXBUFFER_1536 (1536) +static inline unsigned int mucse_rx_bufsz(struct mucse_ring *ring) +{ + return (M_RXBUFFER_1536 - NET_IP_ALIGN); +} + +#define M_TX_DESC(R, i) (&(((struct rnpgbe_tx_desc *)((R)->desc))[i])) +#define M_RX_DESC(R, i) (&(((union rnpgbe_rx_desc *)((R)->desc))[i])) + +#define M_RX_DMA_ATTR (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) /* Device IDs */ #ifndef PCI_VENDOR_ID_MUCSE #define PCI_VENDOR_ID_MUCSE 0x8848 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 2bf8a7f7f303..abf3eef3291a 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2020 - 2025 Mucse Corporation. */ =20 +#include + #include "rnpgbe.h" #include "rnpgbe_lib.h" =20 @@ -498,3 +500,356 @@ void rnpgbe_clear_interrupt_scheme(struct mucse *mucs= e) rnpgbe_free_q_vectors(mucse); rnpgbe_reset_interrupt_capability(mucse); } + +/** + * rnpgbe_clean_tx_ring - Free Tx Buffers + * @tx_ring: ring to be cleaned + **/ +static void rnpgbe_clean_tx_ring(struct mucse_ring *tx_ring) +{ + struct mucse_tx_buffer *tx_buffer; + u16 i =3D tx_ring->next_to_clean; + unsigned long size; + + tx_buffer =3D &tx_ring->tx_buffer_info[i]; + /* ring already cleared, nothing to do */ + if (!tx_ring->tx_buffer_info) + return; + + while (i !=3D tx_ring->next_to_use) { + struct rnpgbe_tx_desc *eop_desc, *tx_desc; + + dev_kfree_skb_any(tx_buffer->skb); + /* unmap skb header data */ + dma_unmap_single(tx_ring->dev, dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); + eop_desc =3D tx_buffer->next_to_watch; + tx_desc =3D M_TX_DESC(tx_ring, i); + /* unmap remaining buffers */ + while (tx_desc !=3D eop_desc) { + tx_buffer++; + tx_desc++; + i++; + if (unlikely(i =3D=3D tx_ring->count)) { + i =3D 0; + tx_buffer =3D tx_ring->tx_buffer_info; + tx_desc =3D M_TX_DESC(tx_ring, 0); + } + + /* unmap any remaining paged data */ + if (dma_unmap_len(tx_buffer, len)) + dma_unmap_page(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + } + /* move us one more past the eop_desc for start of next pkt */ + tx_buffer++; + i++; + if (unlikely(i =3D=3D tx_ring->count)) { + i =3D 0; + tx_buffer =3D tx_ring->tx_buffer_info; + } + } + + netdev_tx_reset_queue(txring_txq(tx_ring)); + size =3D sizeof(struct mucse_tx_buffer) * tx_ring->count; + memset(tx_ring->tx_buffer_info, 0, size); + /* Zero out the descriptor ring */ + memset(tx_ring->desc, 0, tx_ring->size); + tx_ring->next_to_use =3D 0; + tx_ring->next_to_clean =3D 0; +} + +/** + * rnpgbe_free_tx_resources - Free Tx Resources per Queue + * @tx_ring: tx descriptor ring for a specific queue + * + * Free all transmit software resources + **/ +static void rnpgbe_free_tx_resources(struct mucse_ring *tx_ring) +{ + rnpgbe_clean_tx_ring(tx_ring); + vfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info =3D NULL; + /* if not set, then don't free */ + if (!tx_ring->desc) + return; + + dma_free_coherent(tx_ring->dev, tx_ring->size, tx_ring->desc, + tx_ring->dma); + tx_ring->desc =3D NULL; +} + +/** + * rnpgbe_setup_tx_resources - allocate Tx resources (Descriptors) + * @tx_ring: tx descriptor ring (for a specific queue) to setup + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_setup_tx_resources(struct mucse_ring *tx_ring, + struct mucse *mucse) +{ + struct device *dev =3D tx_ring->dev; + int orig_node =3D dev_to_node(dev); + int numa_node =3D NUMA_NO_NODE; + int size; + + size =3D sizeof(struct mucse_tx_buffer) * tx_ring->count; + + if (tx_ring->q_vector) + numa_node =3D tx_ring->q_vector->numa_node; + tx_ring->tx_buffer_info =3D vzalloc_node(size, numa_node); + if (!tx_ring->tx_buffer_info) + tx_ring->tx_buffer_info =3D vzalloc(size); + if (!tx_ring->tx_buffer_info) + goto err; + /* round up to nearest 4K */ + tx_ring->size =3D tx_ring->count * sizeof(struct rnpgbe_tx_desc); + tx_ring->size =3D ALIGN(tx_ring->size, 4096); + set_dev_node(dev, numa_node); + tx_ring->desc =3D dma_alloc_coherent(dev, tx_ring->size, &tx_ring->dma, + GFP_KERNEL); + set_dev_node(dev, orig_node); + if (!tx_ring->desc) + tx_ring->desc =3D dma_alloc_coherent(dev, tx_ring->size, + &tx_ring->dma, + GFP_KERNEL); + if (!tx_ring->desc) + goto err; + + memset(tx_ring->desc, 0, tx_ring->size); + tx_ring->next_to_use =3D 0; + tx_ring->next_to_clean =3D 0; + return 0; + +err: + vfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info =3D NULL; + return -ENOMEM; +} + +/** + * rnpgbe_setup_all_tx_resources - allocate all queues Tx resources + * @mucse: pointer to private structure + * + * Allocate memory for tx_ring. + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_setup_all_tx_resources(struct mucse *mucse) +{ + int i, err =3D 0; + + for (i =3D 0; i < (mucse->num_tx_queues); i++) { + err =3D rnpgbe_setup_tx_resources(mucse->tx_ring[i], mucse); + if (!err) + continue; + + goto err_setup_tx; + } + + return 0; +err_setup_tx: + while (i--) + rnpgbe_free_tx_resources(mucse->tx_ring[i]); + return err; +} + +/** + * rnpgbe_free_all_tx_resources - Free Tx Resources for All Queues + * @mucse: pointer to private structure + * + * Free all transmit software resources + **/ +static void rnpgbe_free_all_tx_resources(struct mucse *mucse) +{ + int i; + + for (i =3D 0; i < (mucse->num_tx_queues); i++) + rnpgbe_free_tx_resources(mucse->tx_ring[i]); +} + +/** + * rnpgbe_setup_rx_resources - allocate Rx resources (Descriptors) + * @rx_ring: rx descriptor ring (for a specific queue) to setup + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_setup_rx_resources(struct mucse_ring *rx_ring, + struct mucse *mucse) +{ + struct device *dev =3D rx_ring->dev; + int orig_node =3D dev_to_node(dev); + int numa_node =3D NUMA_NO_NODE; + int size; + + size =3D sizeof(struct mucse_rx_buffer) * rx_ring->count; + if (rx_ring->q_vector) + numa_node =3D rx_ring->q_vector->numa_node; + + rx_ring->rx_buffer_info =3D vzalloc_node(size, numa_node); + if (!rx_ring->rx_buffer_info) + rx_ring->rx_buffer_info =3D vzalloc(size); + + if (!rx_ring->rx_buffer_info) + goto err; + /* Round up to nearest 4K */ + rx_ring->size =3D rx_ring->count * sizeof(union rnpgbe_rx_desc); + rx_ring->size =3D ALIGN(rx_ring->size, 4096); + set_dev_node(dev, numa_node); + rx_ring->desc =3D dma_alloc_coherent(dev, rx_ring->size, + &rx_ring->dma, + GFP_KERNEL); + set_dev_node(dev, orig_node); + if (!rx_ring->desc) + rx_ring->desc =3D dma_alloc_coherent(dev, rx_ring->size, + &rx_ring->dma, + GFP_KERNEL); + if (!rx_ring->desc) + goto err; + memset(rx_ring->desc, 0, rx_ring->size); + rx_ring->next_to_clean =3D 0; + rx_ring->next_to_use =3D 0; + + return 0; +err: + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info =3D NULL; + return -ENOMEM; +} + +/** + * rnpgbe_clean_rx_ring - Free Rx Buffers per Queue + * @rx_ring: ring to free buffers from + **/ +static void rnpgbe_clean_rx_ring(struct mucse_ring *rx_ring) +{ + struct mucse_rx_buffer *rx_buffer; + u16 i =3D rx_ring->next_to_clean; + + rx_buffer =3D &rx_ring->rx_buffer_info[i]; + /* Free all the Rx ring sk_buffs */ + while (i !=3D rx_ring->next_to_alloc) { + if (rx_buffer->skb) { + struct sk_buff *skb =3D rx_buffer->skb; + + dev_kfree_skb(skb); + rx_buffer->skb =3D NULL; + } + dma_sync_single_range_for_cpu(rx_ring->dev, rx_buffer->dma, + rx_buffer->page_offset, + mucse_rx_bufsz(rx_ring), + DMA_FROM_DEVICE); + rx_buffer->page =3D NULL; + i++; + rx_buffer++; + if (i =3D=3D rx_ring->count) { + i =3D 0; + rx_buffer =3D rx_ring->rx_buffer_info; + } + } + + rx_ring->next_to_alloc =3D 0; + rx_ring->next_to_clean =3D 0; + rx_ring->next_to_use =3D 0; +} + +/** + * rnpgbe_free_rx_resources - Free Rx Resources + * @rx_ring: ring to clean the resources from + * + * Free all receive software resources + **/ +static void rnpgbe_free_rx_resources(struct mucse_ring *rx_ring) +{ + rnpgbe_clean_rx_ring(rx_ring); + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info =3D NULL; + /* if not set, then don't free */ + if (!rx_ring->desc) + return; + + dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc, + rx_ring->dma); + rx_ring->desc =3D NULL; +} + +/** + * rnpgbe_setup_all_rx_resources - allocate all queues Rx resources + * @mucse: pointer to private structure + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_setup_all_rx_resources(struct mucse *mucse) +{ + int i, err =3D 0; + + for (i =3D 0; i < mucse->num_rx_queues; i++) { + err =3D rnpgbe_setup_rx_resources(mucse->rx_ring[i], mucse); + if (!err) + continue; + + goto err_setup_rx; + } + + return 0; +err_setup_rx: + while (i--) + rnpgbe_free_rx_resources(mucse->rx_ring[i]); + return err; +} + +/** + * rnpgbe_free_all_rx_resources - Free Rx Resources for All Queues + * @mucse: pointer to private structure + * + * Free all receive software resources + **/ +static void rnpgbe_free_all_rx_resources(struct mucse *mucse) +{ + int i; + + for (i =3D 0; i < (mucse->num_rx_queues); i++) { + if (mucse->rx_ring[i]->desc) + rnpgbe_free_rx_resources(mucse->rx_ring[i]); + } +} + +/** + * rnpgbe_setup_txrx - Allocate Tx/Rx Resources for All Queues + * @mucse: pointer to private structure + * + * Allocate all send/receive software resources + * + * @return: 0 on success, negative on failure + **/ +int rnpgbe_setup_txrx(struct mucse *mucse) +{ + int err; + + err =3D rnpgbe_setup_all_tx_resources(mucse); + if (err) + return err; + + err =3D rnpgbe_setup_all_rx_resources(mucse); + if (err) + goto err_setup_rx; + return 0; +err_setup_rx: + rnpgbe_free_all_tx_resources(mucse); + return err; +} + +/** + * rnpgbe_free_txrx - Clean Tx/Rx Resources for All Queues + * @mucse: pointer to private structure + * + * Free all send/receive software resources + **/ +void rnpgbe_free_txrx(struct mucse *mucse) +{ + rnpgbe_free_all_tx_resources(mucse); + rnpgbe_free_all_rx_resources(mucse); +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index 0df519a50185..6b2f68320c9e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -24,5 +24,7 @@ =20 int rnpgbe_init_interrupt_scheme(struct mucse *mucse); void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); +int rnpgbe_setup_txrx(struct mucse *mucse); +void rnpgbe_free_txrx(struct mucse *mucse); =20 #endif /* _RNPGBE_LIB_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 8fc1af1c00bc..16a111a10862 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -8,6 +8,7 @@ #include #include #include +#include =20 #include "rnpgbe.h" #include "rnpgbe_mbx_fw.h" @@ -83,6 +84,78 @@ static void rnpgbe_service_task(struct work_struct *work) { } =20 +/** + * rnpgbe_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). + * + * @return: 0 on success, negative value on failure + **/ +static int rnpgbe_open(struct net_device *netdev) +{ + struct mucse *mucse =3D netdev_priv(netdev); + int err; + + /* disallow open during test */ + if (test_bit(__MUCSE_TESTING, &mucse->state)) + return -EBUSY; + + netif_carrier_off(netdev); + err =3D rnpgbe_setup_txrx(mucse); + + return err; +} + +/** + * rnpgbe_close - Disables a network interface + * @netdev: network interface device structure + * + * The close entry point is called when an interface is de-activated + * by the OS. + * + * @return: 0, this is not allowed to fail + **/ +static int rnpgbe_close(struct net_device *netdev) +{ + struct mucse *mucse =3D netdev_priv(netdev); + + rnpgbe_free_txrx(mucse); + + return 0; +} + +/** + * rnpgbe_xmit_frame - Send a skb to driver + * @skb: skb structure to be sent + * @netdev: network interface device structure + * + * @return: NETDEV_TX_OK or NETDEV_TX_BUSY + **/ +static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, + struct net_device *netdev) +{ + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +const struct net_device_ops rnpgbe_netdev_ops =3D { + .ndo_open =3D rnpgbe_open, + .ndo_stop =3D rnpgbe_close, + .ndo_start_xmit =3D rnpgbe_xmit_frame, +}; + +/** + * rnpgbe_assign_netdev_ops - Assign netdev ops to the device + * @dev: network interface device structure + **/ +static void rnpgbe_assign_netdev_ops(struct net_device *dev) +{ + dev->netdev_ops =3D &rnpgbe_netdev_ops; + dev->watchdog_timeo =3D 5 * HZ; +} + /** * rnpgbe_sw_init - Init driver private status * @mucse: pointer to private structure @@ -289,7 +362,7 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, "mucse_mbx_get_capability failed!\n"); goto err_free_net; } - + rnpgbe_assign_netdev_ops(netdev); err =3D rnpgbe_sw_init(mucse); if (err) goto err_free_net; @@ -305,6 +378,7 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, netdev->features |=3D NETIF_F_HIGHDMA; netdev->priv_flags |=3D IFF_UNICAST_FLT; netdev->priv_flags |=3D IFF_SUPP_NOFCS; + netdev->hw_features |=3D netdev->features; eth_hw_addr_set(netdev, hw->perm_addr); memcpy(netdev->perm_addr, hw->perm_addr, netdev->addr_len); ether_addr_copy(hw->addr, hw->perm_addr); @@ -314,11 +388,17 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev, err =3D rnpgbe_init_interrupt_scheme(mucse); if (err) goto err_free_net; + err =3D register_mbx_irq(mucse); if (err) goto err_free_irq; - + strscpy(netdev->name, "eth%d", sizeof(netdev->name)); + err =3D register_netdev(netdev); + if (err) + goto err_register; return 0; +err_register: + remove_mbx_irq(mucse); err_free_irq: rnpgbe_clear_interrupt_scheme(mucse); err_free_net: @@ -389,8 +469,14 @@ static void rnpgbe_rm_adapter(struct mucse *mucse) =20 rnpgbe_devlink_unregister(mucse); netdev =3D mucse->netdev; + if (mucse->flags2 & M_FLAG2_NO_NET_REG) { + free_netdev(netdev); + return; + } cancel_work_sync(&mucse->service_task); timer_delete_sync(&mucse->service_timer); + if (netdev->reg_state =3D=3D NETREG_REGISTERED) + unregister_netdev(netdev); hw->ops.driver_status(hw, false, mucse_driver_insmod); remove_mbx_irq(mucse); rnpgbe_clear_interrupt_scheme(mucse); @@ -432,6 +518,10 @@ static void rnpgbe_dev_shutdown(struct pci_dev *pdev, =20 *enable_wake =3D false; netif_device_detach(netdev); + rtnl_lock(); + if (netif_running(netdev)) + rnpgbe_free_txrx(mucse); + rtnl_unlock(); remove_mbx_irq(mucse); rnpgbe_clear_interrupt_scheme(mucse); pci_disable_device(pdev); --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D08FC286428; Mon, 21 Jul 2025 11:35:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.132.163.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097727; cv=none; b=jDMRFvwfebO4ynsFN0AGxhMHwI+0AsgNTq65w3Akh1ZX3TT7aZWM9k1WXR1c5Jnjv+y8UE6MvQGbb3ePb9HDpZUL8GUh1C45gewR9ARkvfMwE147w/76XTu7SVwxN/3MuDuCup/+WwptpKc6HTjR6bC+2GEdoAOTl88tCMah23I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097727; c=relaxed/simple; bh=3ppbU385kv4dMLin4tXAbzHF/eUk0BVL9kfaoRcEd90=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vu+YapmywEeC8QDqjizoziF9MG+IM7HCdj/BWADX4p0jqQBybF0oymlyNYOBPGGdur46zzKGla5RUo9ohVa8ssJx7I+ktyJbkQJPECIoNAr2LF4pGiG0NkVS/JLltVRrYJGoFUiJxWpRP+IQkrgAp/hXHc+lejNV6jJgv0vWLIU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=18.132.163.193 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097613tee8949d2 X-QQ-Originating-IP: o2F7LuSDoKtCINTvrYFk/JlyXSGtMaZlaGzwQFNRPdI= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:30 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 9302093029296525975 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 10/15] net: rnpgbe: Add netdev irq in open Date: Mon, 21 Jul 2025 19:32:33 +0800 Message-Id: <20250721113238.18615-11-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NR3PJyWXADsZT4eMNHN8tADFwOpggqIoU3709z2lOc5DGQwKiVeFikUF 6VgaaHcL02EMvoUkL29B0YOhe1UqxT26SVLZZWlFYQ/dTCJARnNdKw4GbtpbnmFm3ImP5Ai 94NLWDhI05Yat5fH93AKxlhL/R+mZyVjYtY6f9iPYi9aeK7lP/ferpwwLQoU2U7ESiQbmOz peP38zR/VBWyLHzKHeUKqWZUgzC3BMyketPeUrLib/wc1l+BjRPeyNlPjB3zE4C9FyB4K4t 5jsNrNGDTTbV+78zT7QJPRb14cScDSlhEyqNYk5LnlXm4atFa201tbYw7aASANAgPi5uJ4W jAhJE1NRtT1ICnq5MVfPMIUriflz3Rj9YSgEs0g8IueMJbkqJI9U7Cit4Hk2/B5QTQqRivD 8vmGgWoABIh0PUGthpQWPVXytP3/iMa4CmI9Dcy9rNVbUOt0OlzAMjogchkX0oHOAilay2z EBMmk+c6U5ixNjzV58v7qDmP6NOaZHMlNkn3410cuLCz2RsdLoFtouaLt5uOZlsgwzjVdqh JBOPXQPH8aCLPMbnnc4xAxX/j+tNn6Rd1XRs4VsAWpRwuVZh5UqOcZdjVHo/uoev9bR/nRV dfuVHVx3rDu4flNGh+EAwil+cyw+YAF5AactGy6lFoI1MdW41E4ot+S+avfkp6qxSa02VTV 8BbwZstnuLIu9aDIMlhDVMBacdigueQVPhyksvakVeR4tj52VJH04eN6DyDUlvy+h/YmcCG 0JO3vnNTJfHnI3xmRAF6hjuf+AzwNji3KbNjXS24DQJ3K3HgrJ2Lh+MYEZjFXkYpcrKsSRw J30YNq1yoApVtUfgeH/ZgC4FFctLrILyQCPKlMNi/Cn01X12E7UfKII5f6PgUGY/96RzuDE IN7tM1THZ7dgW+yPzOxddd6W7SvxwRR4BSj2G4zGiVufIAV0rSBlRsF9MATH2OeehZPzHGf iHk7/eHWkueesdrDErQ8xYYYv9TFNSLi7+yLK2SL5sKn4LHSlUdWYvtx41Q2hNepcGEPSvx 8J4uTWxCHUlmIuM5/DYoT81H5WHBFcSDpOGSB/i+EM0LzznIlJZyXC8AFmgHs= X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize irq for tx/rx in open func. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 14 + .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 81 +++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 11 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 280 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 30 ++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 36 ++- 6 files changed, 450 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index cb0d73589687..23fb93157b98 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -67,7 +67,14 @@ struct mii_regs { unsigned int clk_csr_mask; }; =20 +struct mucse_mac_info; + +struct mucse_mac_operations { + void (*set_mac)(struct mucse_mac_info *mac, u8 *addr, int index); +}; + struct mucse_mac_info { + struct mucse_mac_operations ops; u8 __iomem *mac_addr; void *back; struct mii_regs mii; @@ -174,6 +181,9 @@ struct mucse_hw_operations { void (*init_rx_addrs)(struct mucse_hw *hw); /* ops to fw */ void (*driver_status)(struct mucse_hw *hw, bool enable, int mode); + void (*update_hw_info)(struct mucse_hw *hw); + void (*set_mac)(struct mucse_hw *hw, u8 *mac); + void (*set_irq_mode)(struct mucse_hw *hw, bool legacy); }; =20 enum { @@ -603,6 +613,10 @@ static inline unsigned int mucse_rx_bufsz(struct mucse= _ring *ring) #define dma_rd32(dma, reg) m_rd_reg((dma)->dma_base_addr + (reg)) #define eth_wr32(eth, reg, val) m_wr_reg((eth)->eth_base_addr + (reg), (va= l)) #define eth_rd32(eth, reg) m_rd_reg((eth)->eth_base_addr + (reg)) +#define mac_wr32(mac, reg, val) m_wr_reg((mac)->mac_addr + (reg), (val)) +#define mac_rd32(mac, reg) m_rd_reg((mac)->mac_addr + (reg)) +#define ring_wr32(eth, reg, val) m_wr_reg((eth)->ring_addr + (reg), (val)) +#define ring_rd32(eth, reg) m_rd_reg((eth)->ring_addr + (reg)) =20 #define mucse_err(mucse, fmt, arg...) \ dev_err(&(mucse)->pdev->dev, fmt, ##arg) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index fa8317ae7642..266dc95c4ff2 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -91,6 +91,30 @@ static struct mucse_eth_operations eth_ops_n500 =3D { .clr_mc_addr =3D &rnpgbe_eth_clr_mc_addr_n500 }; =20 +/** + * rnpgbe_mac_set_mac_n500 - Setup mac address to mac module in hw + * @mac: pointer to mac structure + * @addr: pointer to addr + * @index: Receive address register to write + * + * Setup a mac address to mac module. + **/ +static void rnpgbe_mac_set_mac_n500(struct mucse_mac_info *mac, + u8 *addr, int index) +{ + u32 rar_low, rar_high =3D 0; + + rar_low =3D ((u32)addr[0] | ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); + rar_high =3D M_RAH_AV | ((u32)addr[4] | (u32)addr[5] << 8); + mac_wr32(mac, RNPGBE_MAC_UNICAST_HIGH(index), rar_high); + mac_wr32(mac, RNPGBE_MAC_UNICAST_LOW(index), rar_low); +} + +static struct mucse_mac_operations mac_ops_n500 =3D { + .set_mac =3D &rnpgbe_mac_set_mac_n500, +}; + /** * rnpgbe_init_hw_ops_n500 - Init hardware * @hw: hw information structure @@ -251,12 +275,68 @@ static void rnpgbe_init_rx_addrs_hw_ops_n500(struct m= ucse_hw *hw) eth->ops.clr_mc_addr(eth); } =20 +/** + * rnpgbe_set_mac_hw_ops_n500 - Setup mac address to hw + * @hw: pointer to hw structure + * @mac: pointer to mac addr + * + * Setup a mac address to hw. + **/ +static void rnpgbe_set_mac_hw_ops_n500(struct mucse_hw *hw, u8 *mac) +{ + struct mucse_eth_info *eth =3D &hw->eth; + struct mucse_mac_info *mac_info =3D &hw->mac; + + /* use idx 0 */ + eth->ops.set_rar(eth, 0, mac); + mac_info->ops.set_mac(mac_info, mac, 0); +} + +/** + * rnpgbe_update_hw_info_hw_ops_n500 - Update status to hw + * @hw: pointer to hw structure + * + * Setup status info to hw, such as some fifo, en regs. + **/ +static void rnpgbe_update_hw_info_hw_ops_n500(struct mucse_hw *hw) +{ + struct mucse_dma_info *dma =3D &hw->dma; + struct mucse_eth_info *eth =3D &hw->eth; + + /* 1 enable eth filter */ + eth_wr32(eth, RNPGBE_HOST_FILTER_EN, 1); + /* 2 open redir en */ + eth_wr32(eth, RNPGBE_REDIR_EN, 1); + /* 3 setup tso fifo */ + dma_wr32(dma, DMA_PKT_FIFO_DATA_PROG_FULL_THRESH, 36); +} + +/** + * rnpgbe_set_irq_mode_n500 - Setup hw irq mode + * @hw: pointer to hw structure + * @legacy: is legacy irq or not + * + * Setup irq mode to hw. + **/ +static void rnpgbe_set_irq_mode_n500(struct mucse_hw *hw, bool legacy) +{ + if (legacy) { + hw_wr32(hw, RNPGBE_LEGANCY_ENABLE, 1); + hw_wr32(hw, RNPGBE_LEGANCY_TIME, 0x200); + } else { + hw_wr32(hw, RNPGBE_LEGANCY_ENABLE, 1); + } +} + static struct mucse_hw_operations hw_ops_n500 =3D { .init_hw =3D &rnpgbe_init_hw_ops_n500, .reset_hw =3D &rnpgbe_reset_hw_ops_n500, .start_hw =3D &rnpgbe_start_hw_ops_n500, .init_rx_addrs =3D &rnpgbe_init_rx_addrs_hw_ops_n500, .driver_status =3D &rnpgbe_driver_status_hw_ops_n500, + .set_mac =3D &rnpgbe_set_mac_hw_ops_n500, + .update_hw_info =3D &rnpgbe_update_hw_info_hw_ops_n500, + .set_irq_mode =3D &rnpgbe_set_irq_mode_n500, }; =20 /** @@ -291,6 +371,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw = *hw) eth->vft_size =3D RNPGBE_VFT_TBL_SIZE; eth->num_rar_entries =3D RNPGBE_RAR_ENTRIES; /* setup mac info */ + memcpy(&hw->mac.ops, &mac_ops_n500, sizeof(hw->mac.ops)); mac->mac_addr =3D hw->hw_addr + RNPGBE_MAC_BASE; mac->back =3D hw; /* set mac->mii */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h index bcb4da45feac..98031600801b 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -22,9 +22,13 @@ #define RX_AXI_RW_EN (0x03 << 0) #define TX_AXI_RW_EN (0x03 << 2) #define RNPGBE_DMA_RX_PROG_FULL_THRESH (0x00a0) +#define DMA_PKT_FIFO_DATA_PROG_FULL_THRESH (0x0098) #define RING_VECTOR(n) (0x04 * (n)) + /* eth regs */ #define RNPGBE_ETH_BYPASS (0x8000) +#define RNPGBE_HOST_FILTER_EN (0x800c) +#define RNPGBE_REDIR_EN (0x8030) #define RNPGBE_ETH_ERR_MASK_VECTOR (0x8060) #define RNPGBE_ETH_DEFAULT_RX_RING (0x806c) #define RNPGBE_PKT_LEN_ERR (2) @@ -35,6 +39,13 @@ #define RNPGBE_ETH_RAR_RL(n) (0xa000 + 0x04 * (n)) #define RNPGBE_ETH_RAR_RH(n) (0xa400 + 0x04 * (n)) #define RNPGBE_ETH_MUTICAST_HASH_TABLE(n) (0xac00 + 0x04 * (n)) + +#define RNPGBE_LEGANCY_ENABLE (0xd004) +#define RNPGBE_LEGANCY_TIME (0xd000) +/* mac regs */ +#define M_RAH_AV 0x80000000 +#define RNPGBE_MAC_UNICAST_LOW(i) (0x44 + (i) * 0x08) +#define RNPGBE_MAC_UNICAST_HIGH(i) (0x40 + (i) * 0x08) /* chip resourse */ #define RNPGBE_MAX_QUEUES (8) /* multicast control table */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index abf3eef3291a..2ba1f5f5aa6c 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -2,6 +2,7 @@ /* Copyright(c) 2020 - 2025 Mucse Corporation. */ =20 #include +#include =20 #include "rnpgbe.h" #include "rnpgbe_lib.h" @@ -853,3 +854,282 @@ void rnpgbe_free_txrx(struct mucse *mucse) rnpgbe_free_all_tx_resources(mucse); rnpgbe_free_all_rx_resources(mucse); } + +/** + * rnpgbe_configure_tx_ring - Configure Tx ring after Reset + * @mucse: pointer to private structure + * @ring: structure containing ring specific data + * + * Configure the Tx descriptor ring after a reset. + **/ +static void rnpgbe_configure_tx_ring(struct mucse *mucse, + struct mucse_ring *ring) +{ + struct mucse_hw *hw =3D &mucse->hw; + u32 status =3D 0; + + ring_wr32(ring, DMA_TX_START, 0); + ring_wr32(ring, DMA_REG_TX_DESC_BUF_BASE_ADDR_LO, (u32)ring->dma); + ring_wr32(ring, DMA_REG_TX_DESC_BUF_BASE_ADDR_HI, + (u32)(((u64)ring->dma) >> 32) | (hw->pfvfnum << 24)); + ring_wr32(ring, DMA_REG_TX_DESC_BUF_LEN, ring->count); + ring->next_to_clean =3D ring_rd32(ring, DMA_REG_TX_DESC_BUF_HEAD); + ring->next_to_use =3D ring->next_to_clean; + ring->tail =3D ring->ring_addr + DMA_REG_TX_DESC_BUF_TAIL; + m_wr_reg(ring->tail, ring->next_to_use); + ring_wr32(ring, DMA_REG_TX_DESC_FETCH_CTRL, + (8 << 0) | (TX_DEFAULT_BURST << 16)); + ring_wr32(ring, DMA_REG_TX_INT_DELAY_TIMER, + mucse->tx_usecs * hw->usecstocount); + ring_wr32(ring, DMA_REG_TX_INT_DELAY_PKTCNT, mucse->tx_frames); + read_poll_timeout(ring_rd32, status, status =3D=3D 1, + 100, 20000, false, ring, DMA_TX_READY); + ring_wr32(ring, DMA_TX_START, 1); +} + +/** + * rnpgbe_configure_tx - Configure Transmit Unit after Reset + * @mucse: pointer to private structure + * + * Configure the Tx DMA after a reset. + **/ +void rnpgbe_configure_tx(struct mucse *mucse) +{ + u32 i; + + /* Setup the HW Tx Head and Tail descriptor pointers */ + for (i =3D 0; i < (mucse->num_tx_queues); i++) + rnpgbe_configure_tx_ring(mucse, mucse->tx_ring[i]); +} + +/** + * rnpgbe_disable_rx_queue - Disable start for ring + * @ring: structure containing ring specific data + **/ +void rnpgbe_disable_rx_queue(struct mucse_ring *ring) +{ + ring_wr32(ring, DMA_RX_START, 0); +} + +/** + * rnpgbe_configure_rx_ring - Configure Rx ring after Reset + * @mucse: pointer to private structure + * @ring: structure containing ring specific data + * + * Configure the Rx descriptor ring after a reset. + **/ +static void rnpgbe_configure_rx_ring(struct mucse *mucse, + struct mucse_ring *ring) +{ + struct mucse_hw *hw =3D &mucse->hw; + u64 desc_phy =3D ring->dma; + int split_size; + /* disable queue to avoid issues while updating state */ + rnpgbe_disable_rx_queue(ring); + + /* set descripts registers*/ + ring_wr32(ring, DMA_REG_RX_DESC_BUF_BASE_ADDR_LO, (u32)desc_phy); + ring_wr32(ring, DMA_REG_RX_DESC_BUF_BASE_ADDR_HI, + ((u32)(desc_phy >> 32)) | (hw->pfvfnum << 24)); + ring_wr32(ring, DMA_REG_RX_DESC_BUF_LEN, ring->count); + ring->tail =3D ring->ring_addr + DMA_REG_RX_DESC_BUF_TAIL; + ring->next_to_clean =3D ring_rd32(ring, DMA_REG_RX_DESC_BUF_HEAD); + ring->next_to_use =3D ring->next_to_clean; + + /* we use fixed sg size */ + split_size =3D 96; + ring_wr32(ring, DMA_REG_RX_SCATTER_LENGTH, split_size); + ring_wr32(ring, DMA_REG_RX_DESC_FETCH_CTRL, + 0 | (RX_DEFAULT_LINE << 0) | + (RX_DEFAULT_BURST << 16)); + /* if ncsi card, drop packets if no rx-desc in 100000 clks */ + if (hw->ncsi_en) + ring_wr32(ring, DMA_REG_RX_DESC_TIMEOUT_TH, 100000); + else + ring_wr32(ring, DMA_REG_RX_DESC_TIMEOUT_TH, 0); + ring_wr32(ring, DMA_REG_RX_INT_DELAY_TIMER, + mucse->rx_usecs * hw->usecstocount); + ring_wr32(ring, DMA_REG_RX_INT_DELAY_PKTCNT, mucse->rx_frames); +} + +/** + * rnpgbe_configure_rx - Configure Receive Unit after Reset + * @mucse: pointer to private structure + * + * Configure the Rx unit of the MAC after a reset. + **/ +void rnpgbe_configure_rx(struct mucse *mucse) +{ + int i; + + for (i =3D 0; i < mucse->num_rx_queues; i++) + rnpgbe_configure_rx_ring(mucse, mucse->rx_ring[i]); +} + +/** + * rnpgbe_msix_clean_rings - msix irq handler for ring irq + * @irq: irq num + * @data: private data + * + * rnpgbe_msix_clean_rings handle irq from ring, start napi + **/ +static irqreturn_t rnpgbe_msix_clean_rings(int irq, void *data) +{ + return IRQ_HANDLED; +} + +static void rnpgbe_irq_affinity_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct mucse_q_vector *q_vector =3D + container_of(notify, struct mucse_q_vector, affinity_notify); + + cpumask_copy(&q_vector->affinity_mask, mask); +} + +static void rnpgbe_irq_affinity_release(struct kref *ref) +{ +} + +/** + * rnpgbe_request_msix_irqs - Initialize MSI-X interrupts + * @mucse: pointer to private structure + * + * rnpgbe_request_msix_irqs allocates MSI-X vectors and requests + * interrupts from the kernel. + **/ +static int rnpgbe_request_msix_irqs(struct mucse *mucse) +{ + struct net_device *netdev =3D mucse->netdev; + int q_off =3D mucse->q_vector_off; + struct msix_entry *entry; + int i =3D 0; + int err; + + for (i =3D 0; i < mucse->num_q_vectors; i++) { + struct mucse_q_vector *q_vector =3D mucse->q_vector[i]; + + entry =3D &mucse->msix_entries[i + q_off]; + if (q_vector->tx.ring && q_vector->rx.ring) { + snprintf(q_vector->name, sizeof(q_vector->name) - 1, + "%s-%s-%d", netdev->name, "TxRx", i); + } else { + /* skip this unused q_vector */ + continue; + } + err =3D request_irq(entry->vector, &rnpgbe_msix_clean_rings, 0, + q_vector->name, q_vector); + if (err) + goto free_queue_irqs; + /* register for affinity change notifications */ + q_vector->affinity_notify.notify =3D rnpgbe_irq_affinity_notify; + q_vector->affinity_notify.release =3D rnpgbe_irq_affinity_release; + irq_set_affinity_notifier(entry->vector, + &q_vector->affinity_notify); + irq_set_affinity_hint(entry->vector, &q_vector->affinity_mask); + } + + return 0; + +free_queue_irqs: + while (i) { + i--; + entry =3D &mucse->msix_entries[i + q_off]; + irq_set_affinity_hint(entry->vector, NULL); + free_irq(entry->vector, mucse->q_vector[i]); + irq_set_affinity_notifier(entry->vector, NULL); + irq_set_affinity_hint(entry->vector, NULL); + } + return err; +} + +/** + * rnpgbe_intr - msi/legacy irq handler + * @irq: irq num + * @data: private data + **/ +static irqreturn_t rnpgbe_intr(int irq, void *data) +{ + return IRQ_HANDLED; +} + +/** + * rnpgbe_request_irq - initialize interrupts + * @mucse: pointer to private structure + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ +int rnpgbe_request_irq(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + int err; + + if (mucse->flags & M_FLAG_MSIX_ENABLED) { + err =3D rnpgbe_request_msix_irqs(mucse); + hw->ops.set_irq_mode(hw, 0); + } else if (mucse->flags & M_FLAG_MSI_ENABLED) { + /* in this case one for all */ + err =3D request_irq(mucse->pdev->irq, rnpgbe_intr, 0, + mucse->netdev->name, mucse); + mucse->hw.mbx.irq_enabled =3D true; + hw->ops.set_irq_mode(hw, 0); + } else { + err =3D request_irq(mucse->pdev->irq, rnpgbe_intr, IRQF_SHARED, + mucse->netdev->name, mucse); + hw->ops.set_irq_mode(hw, 1); + mucse->hw.mbx.irq_enabled =3D true; + } + return err; +} + +/** + * rnpgbe_free_msix_irqs - Free MSI-X interrupts + * @mucse: pointer to private structure + * + * rnpgbe_free_msix_irqs free MSI-X vectors and requests + * interrupts. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_free_msix_irqs(struct mucse *mucse) +{ + int q_off =3D mucse->q_vector_off; + struct mucse_q_vector *q_vector; + struct msix_entry *entry; + int i; + + for (i =3D 0; i < mucse->num_q_vectors; i++) { + q_vector =3D mucse->q_vector[i]; + entry =3D &mucse->msix_entries[i + q_off]; + /* free only the irqs that were actually requested */ + if (!q_vector->rx.ring && !q_vector->tx.ring) + continue; + /* clear the affinity notifier in the IRQ descriptor */ + irq_set_affinity_notifier(entry->vector, NULL); + /* clear the affinity_mask in the IRQ descriptor */ + irq_set_affinity_hint(entry->vector, NULL); + free_irq(entry->vector, q_vector); + } + return 0; +} + +/** + * rnpgbe_free_irq - free interrupts + * @mucse: pointer to private structure + * + * Attempts to free interrupts according initialized type. + **/ +void rnpgbe_free_irq(struct mucse *mucse) +{ + if (mucse->flags & M_FLAG_MSIX_ENABLED) { + rnpgbe_free_msix_irqs(mucse); + } else if (mucse->flags & M_FLAG_MSI_ENABLED) { + /* in this case one for all */ + free_irq(mucse->pdev->irq, mucse); + mucse->hw.mbx.irq_enabled =3D false; + } else { + free_irq(mucse->pdev->irq, mucse); + mucse->hw.mbx.irq_enabled =3D false; + } +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index 6b2f68320c9e..24859649199f 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -16,6 +16,31 @@ #define RX_INT_MASK (0x01) #define DMA_INT_CLR (0x28) #define DMA_INT_STAT (0x20) +#define DMA_REG_RX_DESC_BUF_BASE_ADDR_HI (0x30) +#define DMA_REG_RX_DESC_BUF_BASE_ADDR_LO (0x34) +#define DMA_REG_RX_DESC_BUF_LEN (0x38) +#define DMA_REG_RX_DESC_BUF_HEAD (0x3c) +#define DMA_REG_RX_DESC_BUF_TAIL (0x40) +#define DMA_REG_RX_DESC_FETCH_CTRL (0x44) +#define DMA_REG_RX_INT_DELAY_TIMER (0x48) +#define DMA_REG_RX_INT_DELAY_PKTCNT (0x4c) +#define DMA_REG_RX_ARB_DEF_LVL (0x50) +#define DMA_REG_RX_DESC_TIMEOUT_TH (0x54) +#define DMA_REG_RX_SCATTER_LENGTH (0x58) +#define DMA_REG_TX_DESC_BUF_BASE_ADDR_HI (0x60) +#define DMA_REG_TX_DESC_BUF_BASE_ADDR_LO (0x64) +#define DMA_REG_TX_DESC_BUF_LEN (0x68) +#define DMA_REG_TX_DESC_BUF_HEAD (0x6c) +#define DMA_REG_TX_DESC_BUF_TAIL (0x70) +#define DMA_REG_TX_DESC_FETCH_CTRL (0x74) +#define DMA_REG_TX_INT_DELAY_TIMER (0x78) +#define DMA_REG_TX_INT_DELAY_PKTCNT (0x7c) +#define DMA_REG_TX_ARB_DEF_LVL (0x80) +#define DMA_REG_TX_FLOW_CTRL_TH (0x84) +#define DMA_REG_TX_FLOW_CTRL_TM (0x88) +#define TX_DEFAULT_BURST (8) +#define RX_DEFAULT_LINE (32) +#define RX_DEFAULT_BURST (16) =20 #define mucse_for_each_ring(pos, head)\ for (typeof((head).ring) __pos =3D (head).ring;\ @@ -26,5 +51,10 @@ int rnpgbe_init_interrupt_scheme(struct mucse *mucse); void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); int rnpgbe_setup_txrx(struct mucse *mucse); void rnpgbe_free_txrx(struct mucse *mucse); +void rnpgbe_configure_tx(struct mucse *mucse); +void rnpgbe_disable_rx_queue(struct mucse_ring *ring); +void rnpgbe_configure_rx(struct mucse *mucse); +int rnpgbe_request_irq(struct mucse *mucse); +void rnpgbe_free_irq(struct mucse *mucse); =20 #endif /* _RNPGBE_LIB_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 16a111a10862..dc0990daf8b8 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -84,6 +84,22 @@ static void rnpgbe_service_task(struct work_struct *work) { } =20 +/** + * rnpgbe_configure - Configure info to hw + * @mucse: pointer to private structure + * + * rnpgbe_configure configure mac, tx, rx regs to hw + **/ +static void rnpgbe_configure(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + + hw->ops.set_mac(hw, hw->addr); + hw->ops.update_hw_info(hw); + rnpgbe_configure_tx(mucse); + rnpgbe_configure_rx(mucse); +} + /** * rnpgbe_open - Called when a network interface is made active * @netdev: network interface device structure @@ -104,7 +120,20 @@ static int rnpgbe_open(struct net_device *netdev) =20 netif_carrier_off(netdev); err =3D rnpgbe_setup_txrx(mucse); - + rnpgbe_configure(mucse); + err =3D rnpgbe_request_irq(mucse); + if (err) + goto err_req_irq; + err =3D netif_set_real_num_tx_queues(netdev, mucse->num_tx_queues); + if (err) + goto err_set_queues; + err =3D netif_set_real_num_rx_queues(netdev, mucse->num_rx_queues); + if (err) + goto err_set_queues; +err_req_irq: + rnpgbe_free_txrx(mucse); +err_set_queues: + rnpgbe_free_irq(mucse); return err; } =20 @@ -121,6 +150,7 @@ static int rnpgbe_close(struct net_device *netdev) { struct mucse *mucse =3D netdev_priv(netdev); =20 + rnpgbe_free_irq(mucse); rnpgbe_free_txrx(mucse); =20 return 0; @@ -519,8 +549,10 @@ static void rnpgbe_dev_shutdown(struct pci_dev *pdev, *enable_wake =3D false; netif_device_detach(netdev); rtnl_lock(); - if (netif_running(netdev)) + if (netif_running(netdev)) { + rnpgbe_free_irq(mucse); rnpgbe_free_txrx(mucse); + } rtnl_unlock(); remove_mbx_irq(mucse); rnpgbe_clear_interrupt_scheme(mucse); --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5ABC42BE7A6; Mon, 21 Jul 2025 11:35:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.59.177.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097735; cv=none; b=mNsNSUiWqKNyuRcEYHL+tCKhuBT9Bs6FyIMIES2/rBOvq2TikpJgrQz/KqW8+9rvcPKj62CafJt1NTMaKJHOc0ry6j5XH4ln5EeW4/Z/b2vueUJ7lpk5I2o+4OP9xfEQY3U56K2w/bjf9mokDynNOjZ7e0ZXzFcn1dVvjAzLZlw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097735; c=relaxed/simple; bh=b5qAP1Ee2xD+lSRxIfzVZh4fnqkqqdJhNFBtnMPaN94=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SM4Z2O6Z3yn9+DjpdcZrMEp2WJ8LK7lfXeoVD2Ll/C8svgXkfzOskB1E9jTdoINj3gdCSGaovOFkSQdFx/5zHSV5ysCjlRu+LzNkllf8IpGbGyxmyMmbjyG8VP7XCdlc7V66rAIAvRbkpP8p4xib4aY5u/zeEoFC9EkiPOPRPEY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=52.59.177.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097617t32dbf071 X-QQ-Originating-IP: ejkiecLOyq06LkPdQT1SKDLJ17cPJMC5XdIiJHeOoYw= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:34 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 15052698701912929417 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 11/15] net: rnpgbe: Add setup hw ring-vector, true up/down hw Date: Mon, 21 Jul 2025 19:32:34 +0800 Message-Id: <20250721113238.18615-12-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NPdR9eBl+Ml9kv5GkNMkZG/6nmalFjykbo4WMu2vkV+a8JM0Qijr3bgW LZZXgUuPdeP7rRGviyFMfblahoC9MEk48qBzKNXb7HUWwmb0YDH+Nr7UmpvTjx8KA5f6/bM qR+8F+f6dcdr7K9ky9N3hUqLSPLEZNhm2wVX+Pp+IM9SVc4SPWeJGQL5Gp5Q4tg29jHZtRX +Hr6B8WOwz75I73KTZYlByP4xOPlAFxeiVbiigdtyiPuBukhtGSur6v8F4yvEHOPnC8Ux5g x4Huvj2K8SMUMykQgfejezcn9N1wiL79GJ6KFhLRH7rD+yeTEnxI/WDW/0fvIHKz7gpDsVb egX47h8WIa9pwSv2TslaYf2R0ntSj1f0Eh9DjOFkbkVtARDj8AgiqGtGBGEvcNaE5zW3Fz5 2cwMZFMIxpi7G4+5THQMdFfKsRPDfg74PY2a/qOkqM03T+nKtv3uzhIU0RULPIR2mncb0+7 KFIFqjd4lUJuGKknX78XpHp0iLUHJH+ECfXl1iuzOpDSLcfRcO65kqptU0WLUHuXDHAU8AB XxAjeHxYA+PM23F+RSrDQXdxYDc6GhIXbWQiPqE+y4TR/ZeLry3t8PdMEqnPGJY8xfX5Wd8 M7Y2o6ZSCB2NzvDE/ltohQxieE4CcqoCGBjkE8pk109IvqaiS+T9Hw4ki5hf6yXIql/AnZK yrt4KiupTSqgFM4uDss2QGUXYNagL894IQFD76qLQyuRXPX7DW3ptJUfz1DBGudMB3O6juj 47JYGAbHarT7XmwuGQmAAMKJDsC9auiBBx+ZN3lWGtoWrNyiFCwmrM2K2sGptWIR9zlE2YT /k5S+L83kudQB0czBppoiSIB6Y0xxhjq5QQ/M8Opu5Xtuv6SjdfZCiq4IacbgY7KUOaXoYJ JExufVxn6r1NbQI70NfYI93dM9ZZqBcVC/0hG/l05JVMZl1CbGIKMrN0urXF7SDwqdzIDbL cjze4FYErP19mwN/0/tn85mxO71XuCWqdPMbdMurGX5pZRh12ibbfXGpuKUYP6A1qD6hoZt l17LrxlC9xASB3h/vV/bUdaE6rmtmb1AggA0TOiGq46/30YO23 X-QQ-XMRINFO: Nq+8W0+stu50PRdwbJxPCL0= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize ring-vector setup up hw in open func. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 4 + .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 24 ++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 111 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 72 +++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 56 +++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 108 +++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 31 ++++- 7 files changed, 404 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 23fb93157b98..624e0eec562a 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -184,6 +184,8 @@ struct mucse_hw_operations { void (*update_hw_info)(struct mucse_hw *hw); void (*set_mac)(struct mucse_hw *hw, u8 *mac); void (*set_irq_mode)(struct mucse_hw *hw, bool legacy); + void (*set_mbx_link_event)(struct mucse_hw *hw, int enable); + void (*set_mbx_ifup)(struct mucse_hw *hw, int enable); }; =20 enum { @@ -528,6 +530,7 @@ struct mucse { struct pci_dev *pdev; struct devlink *dl; struct mucse_hw hw; + u16 msg_enable; /* board number */ u16 bd_number; u16 tx_work_limit; @@ -560,6 +563,7 @@ struct mucse { u16 tx_frames; u16 tx_usecs; unsigned long state; + unsigned long link_check_timeout; struct timer_list service_timer; struct work_struct service_task; char name[60]; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index 266dc95c4ff2..b85d4d0e3dbc 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -328,6 +328,28 @@ static void rnpgbe_set_irq_mode_n500(struct mucse_hw *= hw, bool legacy) } } =20 +/** + * rnpgbe_set_mbx_link_event_hw_ops_n500 - Request link event status to hw + * @hw: hw information structure + * @enable: true for event on + **/ +static void rnpgbe_set_mbx_link_event_hw_ops_n500(struct mucse_hw *hw, + int enable) +{ + mucse_mbx_link_event_enable(hw, enable); +} + +/** + * rnpgbe_set_mbx_ifup_hw_ops_n500 - Request phy status to hw + * @hw: hw information structure + * @enable: true for phy up + **/ +static void rnpgbe_set_mbx_ifup_hw_ops_n500(struct mucse_hw *hw, + int enable) +{ + mucse_mbx_ifup_down(hw, enable); +} + static struct mucse_hw_operations hw_ops_n500 =3D { .init_hw =3D &rnpgbe_init_hw_ops_n500, .reset_hw =3D &rnpgbe_reset_hw_ops_n500, @@ -337,6 +359,8 @@ static struct mucse_hw_operations hw_ops_n500 =3D { .set_mac =3D &rnpgbe_set_mac_hw_ops_n500, .update_hw_info =3D &rnpgbe_update_hw_info_hw_ops_n500, .set_irq_mode =3D &rnpgbe_set_irq_mode_n500, + .set_mbx_link_event =3D &rnpgbe_set_mbx_link_event_hw_ops_n500, + .set_mbx_ifup =3D &rnpgbe_set_mbx_ifup_hw_ops_n500, }; =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 2ba1f5f5aa6c..0686bfbf55bf 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -1133,3 +1133,114 @@ void rnpgbe_free_irq(struct mucse *mucse) mucse->hw.mbx.irq_enabled =3D false; } } + +/** + * rnpgbe_napi_enable_all - enable all napi + * @mucse: pointer to private structure + * + * Enable all napi for this net. + **/ +void rnpgbe_napi_enable_all(struct mucse *mucse) +{ + int q_idx; + + for (q_idx =3D 0; q_idx < mucse->num_q_vectors; q_idx++) + napi_enable(&mucse->q_vector[q_idx]->napi); +} + +/** + * rnpgbe_napi_disable_all - disable all napi + * @mucse: pointer to private structure + * + * Disable all napi for this net. + **/ +void rnpgbe_napi_disable_all(struct mucse *mucse) +{ + int q_idx; + + for (q_idx =3D 0; q_idx < mucse->num_q_vectors; q_idx++) + napi_disable(&mucse->q_vector[q_idx]->napi); +} + +/** + * rnpgbe_set_ring_vector - set the ring_vector registers, + * mapping interrupt causes to vectors + * @mucse: pointer to private structure + * @queue: queue to map the corresponding interrupt to + * @msix_vector: the vector to map to the corresponding queue + * + */ +static void rnpgbe_set_ring_vector(struct mucse *mucse, + u8 queue, u8 msix_vector) +{ + struct mucse_hw *hw =3D &mucse->hw; + u32 data =3D 0; + + data =3D hw->pfvfnum << 24; + data |=3D (msix_vector << 8); + data |=3D (msix_vector << 0); + m_wr_reg(hw->ring_msix_base + RING_VECTOR(queue), data); +} + +/** + * rnpgbe_configure_msix - Configure MSI-X hardware + * @mucse: pointer to private structure + * + * rnpgbe_configure_msix sets up the hardware to properly generate MSI-X + * interrupts. + **/ +void rnpgbe_configure_msix(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_q_vector *q_vector; + int i; + + /* configure ring-msix Registers table */ + for (i =3D 0; i < mucse->num_q_vectors; i++) { + struct mucse_ring *ring; + + q_vector =3D mucse->q_vector[i]; + mucse_for_each_ring(ring, q_vector->rx) { + rnpgbe_set_ring_vector(mucse, ring->rnpgbe_queue_idx, + q_vector->v_idx); + } + } + /* n500 should mask other */ + if (hw->hw_type =3D=3D rnpgbe_hw_n500 || + hw->hw_type =3D=3D rnpgbe_hw_n210 || + hw->hw_type =3D=3D rnpgbe_hw_n210L) { + /* + * 8 lpi | PMT + * 9 BMC_RX_IRQ | + * 10 PHY_IRQ | LPI_IRQ + * 11 BMC_TX_IRQ | + * may DMAR error if set pf to vm + */ +#define OTHER_VECTOR_START (8) +#define OTHER_VECTOR_STOP (11) +#define MSIX_UNUSED (0x0f0f) + for (i =3D OTHER_VECTOR_START; i <=3D OTHER_VECTOR_STOP; i++) { + if (hw->feature_flags & M_HW_SOFT_MASK_OTHER_IRQ) { + m_wr_reg(hw->ring_msix_base + + RING_VECTOR(i), + MSIX_UNUSED); + } else { + m_wr_reg(hw->ring_msix_base + + RING_VECTOR(i), 0); + } + } + if (hw->feature_flags & M_HW_FEATURE_EEE) { +#define LPI_IRQ (8) + /* only open lpi irq */ + if (hw->feature_flags & M_HW_SOFT_MASK_OTHER_IRQ) { + m_wr_reg(hw->ring_msix_base + + RING_VECTOR(LPI_IRQ), + 0x000f); + } else { + m_wr_reg(hw->ring_msix_base + + RING_VECTOR(LPI_IRQ), + 0x0000); + } + } + } +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index 24859649199f..bdb8a393dad8 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -7,6 +7,7 @@ #include "rnpgbe.h" =20 #define RING_OFFSET(n) (0x100 * (n)) +#define DMA_DUMY (0xc) #define DMA_RX_START (0x10) #define DMA_RX_READY (0x14) #define DMA_TX_START (0x18) @@ -14,6 +15,8 @@ #define DMA_INT_MASK (0x24) #define TX_INT_MASK (0x02) #define RX_INT_MASK (0x01) +#define DMA_INT_TRIG (0x2c) +#define INT_VALID (0x3 << 16) #define DMA_INT_CLR (0x28) #define DMA_INT_STAT (0x20) #define DMA_REG_RX_DESC_BUF_BASE_ADDR_HI (0x30) @@ -41,11 +44,75 @@ #define TX_DEFAULT_BURST (8) #define RX_DEFAULT_LINE (32) #define RX_DEFAULT_BURST (16) - +#define RING_VECTOR(n) (0x04 * (n)) #define mucse_for_each_ring(pos, head)\ for (typeof((head).ring) __pos =3D (head).ring;\ __pos ? ({ pos =3D __pos; 1; }) : 0;\ __pos =3D __pos->next) +#define e_info(msglvl, format, arg...) \ + netif_info(mucse, msglvl, mucse->netdev, format, ##arg) + +enum link_event_mask { + EVT_LINK_UP =3D 1, + EVT_NO_MEDIA =3D 2, + EVT_LINK_FAULT =3D 3, + EVT_PHY_TEMP_ALARM =3D 4, + EVT_EXCESSIVE_ERRORS =3D 5, + EVT_SIGNAL_DETECT =3D 6, + EVT_AUTO_NEGOTIATION_DONE =3D 7, + EVT_MODULE_QUALIFICATION_FAILD =3D 8, + EVT_PORT_TX_SUSPEND =3D 9, +}; + +static inline void rnpgbe_irq_enable_queues(struct mucse *mucse, + struct mucse_q_vector *q_vector) +{ + struct mucse_ring *ring; + + mucse_for_each_ring(ring, q_vector->rx) { + m_wr_reg(ring->dma_int_mask, ~(RX_INT_MASK | TX_INT_MASK)); + ring_wr32(ring, DMA_INT_TRIG, INT_VALID | TX_INT_MASK | + RX_INT_MASK); + } +} + +static inline void rnpgbe_irq_enable(struct mucse *mucse) +{ + int i; + + for (i =3D 0; i < mucse->num_q_vectors; i++) + rnpgbe_irq_enable_queues(mucse, mucse->q_vector[i]); +} + +static inline void rnpgbe_irq_disable_queues(struct mucse_q_vector *q_vect= or) +{ + struct mucse_ring *ring; + + mucse_for_each_ring(ring, q_vector->tx) { + ring_wr32(ring, DMA_INT_TRIG, + (0x3 << 16) | (~(TX_INT_MASK | RX_INT_MASK))); + m_wr_reg(ring->dma_int_mask, (RX_INT_MASK | TX_INT_MASK)); + } +} + +/** + * rnpgbe_irq_disable - Mask off interrupt generation on the NIC + * @mucse: pointer to private structure + **/ +static inline void rnpgbe_irq_disable(struct mucse *mucse) +{ + int i, j; + + for (i =3D 0; i < mucse->num_q_vectors; i++) { + rnpgbe_irq_disable_queues(mucse->q_vector[i]); + j =3D i + mucse->q_vector_off; + + if (mucse->flags & M_FLAG_MSIX_ENABLED) + synchronize_irq(mucse->msix_entries[j].vector); + else + synchronize_irq(mucse->pdev->irq); + } +} =20 int rnpgbe_init_interrupt_scheme(struct mucse *mucse); void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); @@ -56,5 +123,8 @@ void rnpgbe_disable_rx_queue(struct mucse_ring *ring); void rnpgbe_configure_rx(struct mucse *mucse); int rnpgbe_request_irq(struct mucse *mucse); void rnpgbe_free_irq(struct mucse *mucse); +void rnpgbe_napi_enable_all(struct mucse *mucse); +void rnpgbe_napi_disable_all(struct mucse *mucse); +void rnpgbe_configure_msix(struct mucse *mucse); =20 #endif /* _RNPGBE_LIB_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index dc0990daf8b8..27beb0e6e705 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -100,6 +100,38 @@ static void rnpgbe_configure(struct mucse *mucse) rnpgbe_configure_rx(mucse); } =20 +/** + * rnpgbe_up_complete - Final step for port up + * @mucse: pointer to private structure + **/ +static void rnpgbe_up_complete(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + int i; + + rnpgbe_configure_msix(mucse); + /* we need this */ + smp_mb__before_atomic(); + clear_bit(__MUCSE_DOWN, &mucse->state); + rnpgbe_napi_enable_all(mucse); + /* clear any pending interrupts*/ + rnpgbe_irq_enable(mucse); + /* enable transmits */ + netif_tx_start_all_queues(mucse->netdev); + /* enable rx transmit */ + for (i =3D 0; i < mucse->num_rx_queues; i++) + ring_wr32(mucse->rx_ring[i], DMA_RX_START, 1); + + /* bring the link up in the watchdog */ + mucse->flags |=3D M_FLAG_NEED_LINK_UPDATE; + mucse->link_check_timeout =3D jiffies; + mod_timer(&mucse->service_timer, jiffies); + + hw->link =3D 0; + hw->ops.set_mbx_link_event(hw, 1); + hw->ops.set_mbx_ifup(hw, 1); +} + /** * rnpgbe_open - Called when a network interface is made active * @netdev: network interface device structure @@ -130,6 +162,7 @@ static int rnpgbe_open(struct net_device *netdev) err =3D netif_set_real_num_rx_queues(netdev, mucse->num_rx_queues); if (err) goto err_set_queues; + rnpgbe_up_complete(mucse); err_req_irq: rnpgbe_free_txrx(mucse); err_set_queues: @@ -137,6 +170,28 @@ static int rnpgbe_open(struct net_device *netdev) return err; } =20 +/** + * rnpgbe_down - Down a network interface + * @mucse: pointer to private structure + **/ +static void rnpgbe_down(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + struct net_device *netdev =3D mucse->netdev; + + set_bit(__MUCSE_DOWN, &mucse->state); + hw->ops.set_mbx_link_event(hw, 0); + hw->ops.set_mbx_ifup(hw, 0); + if (netif_carrier_ok(netdev)) + e_info(drv, "NIC Link is Down\n"); + netif_tx_stop_all_queues(netdev); + netif_carrier_off(netdev); + rnpgbe_irq_disable(mucse); + netif_tx_disable(netdev); + rnpgbe_napi_disable_all(mucse); + mucse->flags &=3D ~M_FLAG_NEED_LINK_UPDATE; +} + /** * rnpgbe_close - Disables a network interface * @netdev: network interface device structure @@ -150,6 +205,7 @@ static int rnpgbe_close(struct net_device *netdev) { struct mucse *mucse =3D netdev_priv(netdev); =20 + rnpgbe_down(mucse); rnpgbe_free_irq(mucse); rnpgbe_free_txrx(mucse); =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index 37ef75121898..291cdfbd16f3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -4,6 +4,7 @@ #include =20 #include "rnpgbe.h" +#include "rnpgbe_lib.h" #include "rnpgbe_mbx_fw.h" =20 /** @@ -221,6 +222,45 @@ static int mucse_mbx_fw_post_req(struct mucse_hw *hw, return err; } =20 +/** + * mucse_mbx_write_posted_locked - Posts a mbx req to firmware and + * polling until hw has read out. + * @hw: Pointer to the HW structure + * @req: Pointer to the cmd req structure + * + * mucse_mbx_write_posted_locked posts a mbx req to firmware and + * polling until hw has read out. + * + * @return: 0 on success, negative on failure + **/ +static int mucse_mbx_write_posted_locked(struct mucse_hw *hw, + struct mbx_fw_cmd_req *req) +{ + int len =3D le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN; + int retry =3D 3; + int err =3D 0; + + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; +try_again: + retry--; + if (retry < 0) { + mutex_unlock(&hw->mbx.lock); + return -EIO; + } + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)req, + L_WD(len), + MBX_FW); + if (err) + goto try_again; + + mutex_unlock(&hw->mbx.lock); + + return err; +} + /** * rnpgbe_mbx_lldp_get - Get lldp status from hw * @hw: Pointer to the HW structure @@ -456,3 +496,71 @@ int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvf= num, out: return err; } + +/** + * mucse_mbx_link_event_enable - Echo link event status to hw + * @hw: Pointer to the HW structure + * @enable: true for event on, false for event off + * + * mucse_mbx_link_event_enable echo driver link event status to hw. + * The status is used to echo link status change to driver. + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_link_event_enable(struct mucse_hw *hw, int enable) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int err; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + if (enable) + hw_wr32(hw, DMA_DUMY, 0xa0000000); + + build_link_set_event_mask(&req, BIT(EVT_LINK_UP), + (enable & 1) << EVT_LINK_UP, &req); + + err =3D mucse_mbx_write_posted_locked(hw, &req); + if (!enable) + hw_wr32(hw, DMA_DUMY, 0); + + return err; +} + +/** + * mucse_mbx_ifup_down - Echo phy up/down status to hw + * @hw: Pointer to the HW structure + * @up: true for phy up, false for phy down + * + * mucse_mbx_ifup_down echo driver phy status to hw. + * + * @return: 0 on success, negative on failure + **/ +int mucse_mbx_ifup_down(struct mucse_hw *hw, int up) +{ + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + int err; + int len; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + build_ifup_down(&req, hw->nr_lane, up); + err =3D mutex_lock_interruptible(&hw->mbx.lock); + if (err) + return err; + len =3D le32_to_cpu(req.datalen) + MBX_REQ_HDR_LEN; + err =3D hw->mbx.ops.write_posted(hw, + (u32 *)&req, + L_WD(len), + MBX_FW); + + mutex_unlock(&hw->mbx.lock); + if (up) + hw_wr32(hw, DMA_DUMY, 0xa0000000); + + return err; +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h index 65a4f74c7090..08f5e1950ae3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -647,6 +647,34 @@ static inline void build_get_macaddress_req(struct mbx= _fw_cmd_req *req, req->get_mac_addr.pfvf_num =3D cpu_to_le32(pfvfnum); } =20 +static inline void build_link_set_event_mask(struct mbx_fw_cmd_req *req, + unsigned short event_mask, + unsigned short enable, + void *cookie) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(SET_EVENT_MASK); + req->datalen =3D cpu_to_le32(sizeof(req->stat_event_mask)); + req->cookie =3D cookie; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->stat_event_mask.event_mask =3D cpu_to_le16(event_mask); + req->stat_event_mask.enable_stat =3D cpu_to_le16(enable); +} + +static inline void build_ifup_down(struct mbx_fw_cmd_req *req, + unsigned int nr_lane, int up) +{ + req->flags =3D 0; + req->opcode =3D cpu_to_le32(IFUP_DOWN); + req->datalen =3D cpu_to_le32(sizeof(req->ifup)); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifup.lane =3D cpu_to_le32(nr_lane); + req->ifup.up =3D cpu_to_le32(up); +} + int mucse_mbx_get_capability(struct mucse_hw *hw); int rnpgbe_mbx_lldp_get(struct mucse_hw *hw); int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status); @@ -655,5 +683,6 @@ int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, = int status); int mucse_mbx_fw_reset_phy(struct mucse_hw *hw); int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum, u8 *mac_addr, int nr_lane); - +int mucse_mbx_link_event_enable(struct mucse_hw *hw, int enable); +int mucse_mbx_ifup_down(struct mucse_hw *hw, int up); #endif /* _RNPGBE_MBX_FW_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B6D32C032C; Mon, 21 Jul 2025 11:35:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.132.163.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097758; cv=none; b=bGplNkoAgjGW0FV7EfIHa7B2IEz27E6H+hewbYvdrm0/0bEN9Z2YJsi430a+opaeacCMNwCAphvJJqKEe36UUoaEHo52O+iAEqyV/4Dlj1PHTovI+TNNNQ7lIfe53VFTqZv9vZ649DdpO3++trBWvj9eQQMTRmkStEaPEhE6CQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097758; c=relaxed/simple; bh=NGkH8POWMCUvWCC9DCll509gIgZQUqK9dDOtfMu2Zbs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bnz6Y/ZQUD9YgrjvidT4jgekX77f2NZCcX9mFCXVMvNOUNL1qAidqHkvhdaquGHKrXYigUcdjaLBDCUgziqdcq9fUljzvld510fS/ZN5IaC87r65bPVfcDx0Tv4kb0WRSY6K+MN1A8OkhXL+kSIHml0PS+TdgoZXuQOCFByZkec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=18.132.163.193 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097622tca2e3512 X-QQ-Originating-IP: eI9/Mm2GTAz7JMai5LpjBtPjDGhIZrqE87aX0mMU5RE= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:39 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13491831712532506601 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 12/15] net: rnpgbe: Add link up handler Date: Mon, 21 Jul 2025 19:32:35 +0800 Message-Id: <20250721113238.18615-13-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NlEtBhRRrtWGOVUahyF4YvGewwCO2RmDbOMPYXn6g8MPfOq4XQgixhiQ P5M0aBeBq1ZWCNxPocSmvG6yMzjiiWpJIaR8NtLcFlvQvA/C4XVN+Tv7gfJVPN7oBe37K+J 2Yh2/xGSq9Ep0FRB8+3Ztufv0HtWxLyyb8AvQK+QRKZYn1MJjyaf9d5olM8tFfvVWZNBVni Wa1/g1hM/SPNCt/j9aVS4zgBwTy8Iy0X9gG+tiuN3JH1AehI6JSv/sEFtzhQ4VlymNbbZEL fo6/lMStoCGgQverOJjAHnBm1v+vpQD2/IrCSj72hMPgCq5rkg1kQT/k8Ww64iJ55evXdYs ra6Fc3b+w9ZBSCbNLTCpADdg6Ow9dJMUB3TYMAM3TNseNAdwm32rRL5XdsZSSQ33N7E/5NZ pgQyzD8vGUWhib9lMaSkxx4XZqPbZVCP7sQy0qiZABz+2sg0VaamtBebWKQSWN6oHpX/OOU FieB5EMT7PopdJojYx/c4vakpS+LtDLg/nbyrm0vJ0zXyrE16rtheTMHOfvb6AalbPFaHN8 /FPrvUCL+JZa7Mdb2YfDCZ/NkF3PAhadlLxoQTTYHORN6RmceIvH1wHlFHco71DJQBXIj2m LtXL0gAgYB4eeNNq2pxTBPSZKa0SfebqoZZLs1jGIR9WjWVpQY8f+9bm+EaprWvmPWR33pj YoErCLv6X0UX+hWqLPJ790szytEcEYO7pKaNpR6P97daMjRl2LHZBYinGukEe86xkaFX1su RJK/Okd7TMVuXAf/izRe1XEvSdChb2eaRAT6tCoKx2c6xcDGjJdwN6YKdFYwPwhCd7Rbgyf GAbFAN6UexKu4/dlwu3sTg4GlnBYBBMuZhlSx4wfmCD3eLaZTETTQDJ9miqtg2SmAZGVf9l 078ETKaeoyb9fg7QFZebE+AHdWV6RwCKHm8o1X9nupk3x9SdczqvqbA77e6selH9J8glB6Q jvn7ZHeHBL17dt0r40/FROIBi5R8fh45gTLKhZ7+wz0vVEx6RrfOaFEryCTkSPKMsYnGFUb d2Yf/1OVk2WQKV2UOQUIlaEb0XPFU5b/krl3TtOFstudETjuGXiPsMIODaT1gay7tANBMjF O7DEE0U031L X-QQ-XMRINFO: NS+P29fieYNw95Bth2bWPxk= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize link status handler Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 53 +++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 26 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 7 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 139 +++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h | 1 + .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 187 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 7 + 7 files changed, 420 insertions(+) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 624e0eec562a..b241740d9cc5 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -26,6 +26,15 @@ enum rnpgbe_hw_type { rnpgbe_hw_unknow }; =20 +enum speed_enum { + speed_10, + speed_100, + speed_1000, + speed_10000, + speed_25000, + speed_40000, +}; + struct mucse_dma_info { u8 __iomem *dma_base_addr; u8 __iomem *dma_ring_addr; @@ -121,6 +130,31 @@ struct mucse_mbx_operations { bool enable); }; =20 +/* Flow Control Settings */ +enum mucse_fc_mode { + mucse_fc_none =3D 0, + mucse_fc_rx_pause, + mucse_fc_tx_pause, + mucse_fc_full, + mucse_fc_default +}; + +#define PAUSE_TX (0x1) +#define PAUSE_RX (0x2) +#define PAUSE_AUTO (0x10) +#define ASYM_PAUSE BIT(11) +#define SYM_PAUSE BIT(10) + +#define M_MAX_TRAFFIC_CLASS (4) +/* Flow control parameters */ +struct mucse_fc_info { + u32 high_water[M_MAX_TRAFFIC_CLASS]; + u32 low_water[M_MAX_TRAFFIC_CLASS]; + u16 pause_time; + enum mucse_fc_mode current_mode; + enum mucse_fc_mode requested_mode; +}; + struct mucse_mbx_stats { u32 msgs_tx; u32 msgs_rx; @@ -186,6 +220,8 @@ struct mucse_hw_operations { void (*set_irq_mode)(struct mucse_hw *hw, bool legacy); void (*set_mbx_link_event)(struct mucse_hw *hw, int enable); void (*set_mbx_ifup)(struct mucse_hw *hw, int enable); + void (*check_link)(struct mucse_hw *hw, u32 *speed, bool *link_up, + bool *duplex); }; =20 enum { @@ -224,6 +260,7 @@ struct mucse_hw { struct mucse_dma_info dma; struct mucse_eth_info eth; struct mucse_mac_info mac; + struct mucse_fc_info fc; struct mucse_mbx_info mbx; #define M_NET_FEATURE_SG BIT(0) #define M_NET_FEATURE_TX_CHECKSUM BIT(1) @@ -254,6 +291,9 @@ struct mucse_hw { u16 max_msix_vectors; int nr_lane; struct lldp_status lldp_status; + int speed; + u32 duplex; + u32 tp_mdx; int link; u8 addr[ETH_ALEN]; u8 perm_addr[ETH_ALEN]; @@ -261,6 +301,7 @@ struct mucse_hw { =20 enum mucse_state_t { __MUCSE_TESTING, + __MUCSE_RESETTING, __MUCSE_DOWN, __MUCSE_SERVICE_SCHED, __MUCSE_PTP_TX_IN_PROGRESS, @@ -544,6 +585,7 @@ struct mucse { u32 priv_flags; #define M_PRIV_FLAG_TX_COALESCE BIT(25) #define M_PRIV_FLAG_RX_COALESCE BIT(26) +#define M_PRIV_FLAG_LLDP BIT(27) struct mucse_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; int tx_ring_item_count; int num_tx_queues; @@ -562,6 +604,9 @@ struct mucse { u16 rx_frames; u16 tx_frames; u16 tx_usecs; + bool link_up; + u32 link_speed; + bool duplex; unsigned long state; unsigned long link_check_timeout; struct timer_list service_timer; @@ -610,9 +655,17 @@ static inline unsigned int mucse_rx_bufsz(struct mucse= _ring *ring) #define M_PKT_TIMEOUT (30) #define M_RX_PKT_POLL_BUDGET (64) =20 +#define M_LINK_SPEED_UNKNOWN 0 +#define M_LINK_SPEED_10_FULL BIT(2) +#define M_LINK_SPEED_100_FULL BIT(3) +#define M_LINK_SPEED_1GB_FULL BIT(4) + +#define M_TRY_LINK_TIMEOUT (4 * HZ) + #define m_rd_reg(reg) readl(reg) #define m_wr_reg(reg, val) writel((val), reg) #define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) +#define hw_rd32(hw, reg) m_rd_reg((hw)->hw_addr + (reg)) #define dma_wr32(dma, reg, val) m_wr_reg((dma)->dma_base_addr + (reg), (va= l)) #define dma_rd32(dma, reg) m_rd_reg((dma)->dma_base_addr + (reg)) #define eth_wr32(eth, reg, val) m_wr_reg((eth)->eth_base_addr + (reg), (va= l)) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index b85d4d0e3dbc..16eebe59915e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -350,6 +350,31 @@ static void rnpgbe_set_mbx_ifup_hw_ops_n500(struct muc= se_hw *hw, mucse_mbx_ifup_down(hw, enable); } =20 +/** + * rnpgbe_check_link_hw_ops_n500 - Check link status from hw + * @hw: hw information structure + * @speed: store speed + * @link_up: store link status + * @duplex: store duplex status + **/ +static void rnpgbe_check_link_hw_ops_n500(struct mucse_hw *hw, + u32 *speed, + bool *link_up, + bool *duplex) +{ + if (hw->speed =3D=3D 10) + *speed =3D M_LINK_SPEED_10_FULL; + else if (hw->speed =3D=3D 100) + *speed =3D M_LINK_SPEED_100_FULL; + else if (hw->speed =3D=3D 1000) + *speed =3D M_LINK_SPEED_1GB_FULL; + else + *speed =3D M_LINK_SPEED_UNKNOWN; + + *link_up =3D !!hw->link; + *duplex =3D !!hw->duplex; +} + static struct mucse_hw_operations hw_ops_n500 =3D { .init_hw =3D &rnpgbe_init_hw_ops_n500, .reset_hw =3D &rnpgbe_reset_hw_ops_n500, @@ -361,6 +386,7 @@ static struct mucse_hw_operations hw_ops_n500 =3D { .set_irq_mode =3D &rnpgbe_set_irq_mode_n500, .set_mbx_link_event =3D &rnpgbe_set_mbx_link_event_hw_ops_n500, .set_mbx_ifup =3D &rnpgbe_set_mbx_ifup_hw_ops_n500, + .check_link =3D &rnpgbe_check_link_hw_ops_n500, }; =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 0686bfbf55bf..b646aba48348 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -6,6 +6,7 @@ =20 #include "rnpgbe.h" #include "rnpgbe_lib.h" +#include "rnpgbe_mbx_fw.h" =20 /** * rnpgbe_set_rss_queues - Allocate queues for RSS @@ -1050,6 +1051,12 @@ static int rnpgbe_request_msix_irqs(struct mucse *mu= cse) **/ static irqreturn_t rnpgbe_intr(int irq, void *data) { + struct mucse *mucse =3D (struct mucse *)data; + + set_bit(__MUCSE_IN_IRQ, &mucse->state); + /* handle fw req and ack */ + rnpgbe_fw_msg_handler(mucse); + clear_bit(__MUCSE_IN_IRQ, &mucse->state); return IRQ_HANDLED; } =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 27beb0e6e705..90b4858597c1 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -76,12 +76,147 @@ static void rnpgbe_service_timer(struct timer_list *t) rnpgbe_service_event_schedule(mucse); } =20 +/** + * rnpgbe_service_event_complete - Call when service_task end + * @mucse: pointer to the device private structure + **/ +static void rnpgbe_service_event_complete(struct mucse *mucse) +{ + /* flush memory to make sure state is correct before next watchdog */ + smp_mb__before_atomic(); + clear_bit(__MUCSE_SERVICE_SCHED, &mucse->state); +} + +/** + * rnpgbe_watchdog_update_link - update the link status + * @mucse: pointer to the device private structure + **/ +static void rnpgbe_watchdog_update_link(struct mucse *mucse) +{ + bool flow_rx =3D true, flow_tx =3D true; + u32 link_speed =3D mucse->link_speed; + struct mucse_hw *hw =3D &mucse->hw; + bool link_up; + bool duplex; + + if (!(mucse->flags & M_FLAG_NEED_LINK_UPDATE)) + return; + + if (hw->ops.check_link) { + hw->ops.check_link(hw, &link_speed, &link_up, &duplex); + } else { + /* always assume link is up, if no check link function */ + link_speed =3D M_LINK_SPEED_1GB_FULL; + link_up =3D true; + duplex =3D true; + } + + if (link_up || time_after(jiffies, (mucse->link_check_timeout + + M_TRY_LINK_TIMEOUT))) { + mucse->flags &=3D ~M_FLAG_NEED_LINK_UPDATE; + } + mucse->link_up =3D link_up; + mucse->link_speed =3D link_speed; + mucse->duplex =3D duplex; + + switch (hw->fc.current_mode) { + case mucse_fc_none: + flow_rx =3D false; + flow_tx =3D false; + break; + case mucse_fc_tx_pause: + flow_rx =3D false; + flow_tx =3D true; + break; + case mucse_fc_rx_pause: + flow_rx =3D true; + flow_tx =3D false; + break; + + case mucse_fc_full: + flow_rx =3D true; + flow_tx =3D true; + break; + default: + flow_rx =3D false; + flow_tx =3D false; + } + + if (mucse->link_up) { + e_info(drv, "NIC Link is Up %s, %s Duplex, Flow Control: %s\n", + (link_speed =3D=3D M_LINK_SPEED_1GB_FULL ? "1000 Mbps" : + (link_speed =3D=3D M_LINK_SPEED_100_FULL ? "100 Mbps" : + (link_speed =3D=3D M_LINK_SPEED_10_FULL ? "10 Mbps" : + "unknown speed"))), + ((duplex) ? "Full" : "Half"), + ((flow_rx && flow_tx) ? "RX/TX" : + (flow_rx ? "RX" : (flow_tx ? "TX" : "None")))); + } +} + +/** + * rnpgbe_watchdog_link_is_up - update netif_carrier status and + * print link up message + * @mucse: pointer to the device private structure + **/ +static void rnpgbe_watchdog_link_is_up(struct mucse *mucse) +{ + struct net_device *netdev =3D mucse->netdev; + + /* only continue if link was previously down */ + if (netif_carrier_ok(netdev)) + return; + netif_carrier_on(netdev); + netif_tx_wake_all_queues(netdev); +} + +/** + * rnpgbe_watchdog_link_is_down - update netif_carrier status and + * print link down message + * @mucse: pointer to the private structure + **/ +static void rnpgbe_watchdog_link_is_down(struct mucse *mucse) +{ + struct net_device *netdev =3D mucse->netdev; + + mucse->link_up =3D false; + mucse->link_speed =3D 0; + /* only continue if link was up previously */ + if (!netif_carrier_ok(netdev)) + return; + e_info(drv, "NIC Link is Down\n"); + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); +} + +/** + * rnpgbe_watchdog_subtask - check and bring link up + * @mucse: pointer to the device private structure + **/ +static void rnpgbe_watchdog_subtask(struct mucse *mucse) +{ + /* if interface is down do nothing */ + if (test_bit(__MUCSE_DOWN, &mucse->state) || + test_bit(__MUCSE_RESETTING, &mucse->state)) + return; + + rnpgbe_watchdog_update_link(mucse); + if (mucse->link_up) + rnpgbe_watchdog_link_is_up(mucse); + else + rnpgbe_watchdog_link_is_down(mucse); +} + /** * rnpgbe_service_task - manages and runs subtasks * @work: pointer to work_struct containing our data **/ static void rnpgbe_service_task(struct work_struct *work) { + struct mucse *mucse =3D container_of(work, struct mucse, service_task); + + rnpgbe_watchdog_subtask(mucse); + rnpgbe_service_event_complete(mucse); } =20 /** @@ -163,6 +298,8 @@ static int rnpgbe_open(struct net_device *netdev) if (err) goto err_set_queues; rnpgbe_up_complete(mucse); + + return 0; err_req_irq: rnpgbe_free_txrx(mucse); err_set_queues: @@ -311,6 +448,8 @@ static irqreturn_t rnpgbe_msix_other(int irq, void *dat= a) struct mucse *mucse =3D (struct mucse *)data; =20 set_bit(__MUCSE_IN_IRQ, &mucse->state); + /* handle fw req and ack */ + rnpgbe_fw_msg_handler(mucse); clear_bit(__MUCSE_IN_IRQ, &mucse->state); =20 return IRQ_HANDLED; diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_mbx.h index 0b4183e53e61..0f554f3eff82 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h @@ -8,6 +8,7 @@ =20 /* 14 words */ #define MUCSE_VFMAILBOX_SIZE 14 +#define MUCSE_FW_MAILBOX_SIZE MUCSE_VFMAILBOX_SIZE /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D PF <--> VF mailbox =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */ #define SHARE_MEM_BYTES 64 static inline u32 PF_VF_SHM(struct mucse_mbx_info *mbx, int vf) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index 291cdfbd16f3..412d9d5da191 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -564,3 +564,190 @@ int mucse_mbx_ifup_down(struct mucse_hw *hw, int up) =20 return err; } + +/** + * rnpgbe_link_stat_mark - Mark driver link status in reg + * @hw: Pointer to the HW structure + * @up: true for link up, false for link down + * + * rnpgbe_link_stat_mark echo driver link status to hw by DMA_DUMY. + * Fw will echo true link status if mismatch it. + **/ +static void rnpgbe_link_stat_mark(struct mucse_hw *hw, int up) +{ + struct mucse *mucse =3D (struct mucse *)hw->back; + u32 v; + + v =3D hw_rd32(hw, DMA_DUMY); + v &=3D ~(0x0f000f11); + v |=3D 0xa0000000; + if (up) { + v |=3D BIT(0); + switch (hw->speed) { + case 10: + v |=3D (speed_10 << 8); + break; + case 100: + v |=3D (speed_100 << 8); + break; + case 1000: + v |=3D (speed_1000 << 8); + break; + case 10000: + v |=3D (speed_10000 << 8); + break; + case 25000: + v |=3D (speed_25000 << 8); + break; + case 40000: + v |=3D (speed_40000 << 8); + break; + } + v |=3D (hw->duplex << 4); + v |=3D (hw->fc.current_mode << 24); + } else { + v &=3D ~BIT(0); + } + /* we should update lldp_status */ + if (hw->fw_version >=3D 0x00010500) { + if (mucse->priv_flags & M_PRIV_FLAG_LLDP) + v |=3D BIT(6); + else + v &=3D (~BIT(6)); + } + hw_wr32(hw, DMA_DUMY, v); +} + +/** + * rnpgbe_mbx_fw_reply_handler - handle fw reply + * @mucse: pointer to the device private structure + * @reply: pointer to reply data + * + * rnpgbe_mbx_fw_reply_handler handler fw reply, it copy reply data + * to cookie->priv if no err. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_mbx_fw_reply_handler(struct mucse *mucse, + struct mbx_fw_cmd_reply *reply) +{ + struct mbx_req_cookie *cookie; + + cookie =3D reply->cookie; + if (!cookie || cookie->magic !=3D COOKIE_MAGIC) + return -EIO; + + if (cookie->priv_len > 0) + memcpy(cookie->priv, reply->data, cookie->priv_len); + + cookie->done =3D 1; + + if (reply->flags & FLAGS_ERR) + cookie->errcode =3D -EIO; + else + cookie->errcode =3D 0; + wake_up_interruptible(&cookie->wait); + return 0; +} + +/** + * rnpgbe_mbx_fw_req_handler - handle fw req + * @mucse: pointer to the device private structure + * @req: pointer to req data + * + * rnpgbe_mbx_fw_req_handler handler fw req, such as a link event req. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_mbx_fw_req_handler(struct mucse *mucse, + struct mbx_fw_cmd_req *req) +{ + u32 magic =3D le32_to_cpu(req->link_stat.port_st_magic); + struct mucse_hw *hw =3D &mucse->hw; + + switch (le16_to_cpu(req->opcode)) { + case LINK_STATUS_EVENT: + if (le16_to_cpu(req->link_stat.lane_status)) + hw->link =3D 1; + else + hw->link =3D 0; + port_stat_update_host_endian(&req->link_stat.st[0]); + if (hw->hw_type =3D=3D rnpgbe_hw_n500 || + hw->hw_type =3D=3D rnpgbe_hw_n210 || + hw->hw_type =3D=3D rnpgbe_hw_n210L) { + if (req->link_stat.st[0].v_host.lldp_status) + mucse->priv_flags |=3D M_PRIV_FLAG_LLDP; + else + mucse->priv_flags &=3D (~M_PRIV_FLAG_LLDP); + } + if (magic =3D=3D SPEED_VALID_MAGIC) { + hw->speed =3D le16_to_cpu(req->link_stat.st[0].speed); + hw->duplex =3D req->link_stat.st[0].duplex; + if (hw->hw_type =3D=3D rnpgbe_hw_n500 || + hw->hw_type =3D=3D rnpgbe_hw_n210 || + hw->hw_type =3D=3D rnpgbe_hw_n210L) { + hw->fc.current_mode =3D + req->link_stat.st[0].v_host.pause; + hw->tp_mdx =3D req->link_stat.st[0].v_host.tp_mdx; + } + } + if (req->link_stat.lane_status) + rnpgbe_link_stat_mark(hw, 1); + else + rnpgbe_link_stat_mark(hw, 0); + + mucse->flags |=3D M_FLAG_NEED_LINK_UPDATE; + break; + } + return 0; +} + +/** + * rnpgbe_rcv_msg_from_fw - Read msg from fw and handle it + * @mucse: pointer to the device private structure + * + * rnpgbe_rcv_msg_from_fw tries to read mbx from hw and check + * the mbx is req or reply. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_rcv_msg_from_fw(struct mucse *mucse) +{ + u32 msgbuf[MUCSE_FW_MAILBOX_SIZE]; + struct mucse_hw *hw =3D &mucse->hw; + int retval; + + retval =3D mucse_read_mbx(hw, msgbuf, MUCSE_FW_MAILBOX_SIZE, MBX_FW); + if (retval) + return retval; + /* this is a message we already processed, do nothing */ + if (((unsigned short *)msgbuf)[0] & FLAGS_DD) { + return rnpgbe_mbx_fw_reply_handler(mucse, + (struct mbx_fw_cmd_reply *)msgbuf); + } else { + return rnpgbe_mbx_fw_req_handler(mucse, + (struct mbx_fw_cmd_req *)msgbuf); + } +} + +static void rnpgbe_rcv_ack_from_fw(struct mucse *mucse) +{ + /* do-nothing */ +} + +/** + * rnpgbe_fw_msg_handler - Irq handler for mbx irq + * @mucse: pointer to the device private structure + * @return: 0 always + **/ +int rnpgbe_fw_msg_handler(struct mucse *mucse) +{ + /* check fw-req */ + if (!mucse_check_for_msg(&mucse->hw, MBX_FW)) + rnpgbe_rcv_msg_from_fw(mucse); + /* process any acks */ + if (!mucse_check_for_ack(&mucse->hw, MBX_FW)) + rnpgbe_rcv_ack_from_fw(mucse); + + return 0; +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h index 08f5e1950ae3..88c140832c5e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -232,6 +232,12 @@ struct port_stat { }; } __packed; =20 +static inline void port_stat_update_host_endian(struct port_stat *stat) +{ + u16 host_val =3D le16_to_cpu(stat->stat); + + stat->v_host =3D *(typeof(stat->v_host) *)&host_val; +} #define FLAGS_DD BIT(0) /* driver clear 0, FW must set 1 */ /* driver clear 0, FW must set only if it reporting an error */ #define FLAGS_ERR BIT(2) @@ -685,4 +691,5 @@ int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfn= um, u8 *mac_addr, int nr_lane); int mucse_mbx_link_event_enable(struct mucse_hw *hw, int enable); int mucse_mbx_ifup_down(struct mucse_hw *hw, int up); +int rnpgbe_fw_msg_handler(struct mucse *mucse); #endif /* _RNPGBE_MBX_FW_H */ --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C801A28D8DF; Mon, 21 Jul 2025 11:36:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.132.163.193 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097767; cv=none; b=HIdL4NJOaTGqUyD2UETlwlZqoJ+TrtH1fANiso45TdKUCAC+Sl9V79/HcOdzU49Dg1PAYFrBRs2lnPscTPPc5ZsOPTHcTIk0A1dG1wVM/xu3FYemkiBY0Ytj8EVQth6hMWzpze2jkETHwZWLmlAP3TmDXen3pkt/Ug+Ny/BwhME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097767; c=relaxed/simple; bh=Kj5c1GfTfhhBtsz9aBg/wTpCzwpJO1O/hCu6ppAtlTw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W4kaioKg2GTckive97j4MPaL5wO5m3FzIkT86sqXvmSAvhFd4J3cjXOjeWh2rsU+OxP+ik+JassvvXF3NHWVch7YulBlCdQH7P4/+oJUYv6LokgkhnFiMbovOfP7GBbXBhOvCXyRmQ9D8+apgrtp04xwb/2WqqAEdw/X7mZ8WFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=18.132.163.193 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097627t404d175b X-QQ-Originating-IP: r6hz5n/Fs1xR1a5ZNS7SNLJxhaA+ib6nlhbV+fzbnBE= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:44 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 43171819546396796 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 13/15] net: rnpgbe: Add base tx functions Date: Mon, 21 Jul 2025 19:32:36 +0800 Message-Id: <20250721113238.18615-14-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MrcPhcux9cyzzKDM9HanCoABaDT8ioaXPRw7NhlEsZo56BpPq2aMr43Z Ex5q61MR7nIo1fj5aHxd41tJ2Ca6XVakfJG8oQF0waq2FiMvOIGJLEdiyNoEHmWqXAQ9dE0 q1hvdrLPzmGd88aYGVWSgpRj48JJTERxd4Dj6CtcOruGQUiLY3Gnvpggdhl3LyNyQqEDQMq itWP6QVF1/ER/QyozSsff6TPPkDaeKmlNkYkB6g9nMUvmME9Q//J3/Ft5oXc88DKlJZpcAK wO+qzd5pCCrrt7PceqZQPad/Hl0H99OhnOV8L5sjeIC9stE+Kku4c3dCTFkUST2FKipmzyp lfzS8L9Wf41PyjF/h1G2uLKlzr43+bGLZna/M1Ne2vClMuAioiEcRtCxmb324qp2HSJG+HQ bUIn1U+tvBxejIL0SEeU+yzq3vmGAKnWTsczm323bo5BD5bBFs/6D5y5H4TNms4BnMY33IU JyJlPObBI8KIxIJLJLJrvvDnX+VBW98Z/XVRuMLcrxtd8Kgqu145KaRitbcQxcVPZmYRDol 4io3EV+3nea9+iz5dsi9mIftiR6pcplilY2yoiT/rEmbikAmtZSY78WoTgoDUa+mMxo3NqM MOFF9wAcHpccMuTG4Tlrz9xIw6+ZfpXGXZNgXAq5xAQUB4jcbW0JW+cT8Le7hcKT0EoV+sS rGeXg1A3dR1Qr3ygV6Ey3iAh6PasD3zIo+IRyZc8vM6oQRIXZFzdY/E6rm2PPpAcl5+4HZr YYxRf52CTvVB8mNbddGfcHhp4h3fAZtTww3pehwnOsMQo3D44/fYHahTiYfyXQ9DvQaTLOw nm7I3Hsu4qdyFY6oaedVmvJLOLq2smJOk2krEumuakewmwSZdW6wG55drvbvAmiGly1pxlS +MlPt1W4q9sCSRT7DdZpkOQ+MWb6ZtOHLBYQmksVRFgdkS+jgO7hLnPi5yFg6CGE5fG7coD P67LoTrXuzEBpDsE8kmkMsOzOnefpt6UjiEVZkzIhGMh5VvkuWyaPhzqAnnO42Y8yFHSLNC 6Kq9BRKM+b38bLnrsCDEfhJ6tz1TAwU0ubyPuBhtONgI6Gnkxoml78Dox8dbs= X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize tx-map and tx clean functions Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 19 + .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 65 ++- drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 6 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 431 +++++++++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 14 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 79 +++- 6 files changed, 607 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index b241740d9cc5..26774c214da0 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -51,6 +51,7 @@ struct mucse_eth_operations { int (*set_rar)(struct mucse_eth_info *eth, u32 index, u8 *addr); int (*clear_rar)(struct mucse_eth_info *eth, u32 index); void (*clr_mc_addr)(struct mucse_eth_info *eth); + void (*set_rx)(struct mucse_eth_info *eth, bool status); }; =20 #define RNPGBE_MAX_MTA 128 @@ -80,6 +81,7 @@ struct mucse_mac_info; =20 struct mucse_mac_operations { void (*set_mac)(struct mucse_mac_info *mac, u8 *addr, int index); + void (*set_mac_rx)(struct mucse_mac_info *mac, bool status); }; =20 struct mucse_mac_info { @@ -222,6 +224,7 @@ struct mucse_hw_operations { void (*set_mbx_ifup)(struct mucse_hw *hw, int enable); void (*check_link)(struct mucse_hw *hw, u32 *speed, bool *link_up, bool *duplex); + void (*set_mac_rx)(struct mucse_hw *hw, bool status); }; =20 enum { @@ -538,6 +541,8 @@ struct mucse_ring { =20 struct mucse_ring_container { struct mucse_ring *ring; + unsigned int total_bytes; + unsigned int total_packets; u16 work_limit; u16 count; }; @@ -620,11 +625,25 @@ struct rnpgbe_info { void (*get_invariants)(struct mucse_hw *hw); }; =20 +static inline u16 mucse_desc_unused(struct mucse_ring *ring) +{ + u16 ntc =3D ring->next_to_clean; + u16 ntu =3D ring->next_to_use; + + return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; +} + static inline struct netdev_queue *txring_txq(const struct mucse_ring *rin= g) { return netdev_get_tx_queue(ring->netdev, ring->queue_index); } =20 +static inline __le64 build_ctob(u32 vlan_cmd, u32 mac_ip_len, u32 size) +{ + return cpu_to_le64(((u64)vlan_cmd << 32) | ((u64)mac_ip_len << 16) | + ((u64)size)); +} + #define M_RXBUFFER_1536 (1536) static inline unsigned int mucse_rx_bufsz(struct mucse_ring *ring) { diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index 16eebe59915e..d7894891e098 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -85,10 +85,28 @@ static void rnpgbe_eth_clr_mc_addr_n500(struct mucse_et= h_info *eth) eth_wr32(eth, RNPGBE_ETH_MUTICAST_HASH_TABLE(i), 0); } =20 +/** + * rnpgbe_eth_set_rx_n500 - set eth rx status + * @eth: pointer to eth structure + * @status: true is enable rx, false is disable + **/ +static void rnpgbe_eth_set_rx_n500(struct mucse_eth_info *eth, + bool status) +{ + if (status) { + eth_wr32(eth, RNPGBE_ETH_EXCEPT_DROP_PROC, 0); + eth_wr32(eth, RNPGBE_ETH_TX_MUX_DROP, 0); + } else { + eth_wr32(eth, RNPGBE_ETH_EXCEPT_DROP_PROC, 1); + eth_wr32(eth, RNPGBE_ETH_TX_MUX_DROP, 1); + } +} + static struct mucse_eth_operations eth_ops_n500 =3D { .set_rar =3D &rnpgbe_eth_set_rar_n500, .clear_rar =3D &rnpgbe_eth_clear_rar_n500, - .clr_mc_addr =3D &rnpgbe_eth_clr_mc_addr_n500 + .clr_mc_addr =3D &rnpgbe_eth_clr_mc_addr_n500, + .set_rx =3D &rnpgbe_eth_set_rx_n500, }; =20 /** @@ -111,8 +129,31 @@ static void rnpgbe_mac_set_mac_n500(struct mucse_mac_i= nfo *mac, mac_wr32(mac, RNPGBE_MAC_UNICAST_LOW(index), rar_low); } =20 +/** + * rnpgbe_mac_set_rx_n500 - Setup mac rx status + * @mac: pointer to mac structure + * @status: true for rx on / false for rx off + * + * Setup mac rx status. + **/ +static void rnpgbe_mac_set_rx_n500(struct mucse_mac_info *mac, + bool status) +{ + u32 value =3D mac_rd32(mac, R_MAC_CONTROL); + + if (status) + value |=3D MAC_CONTROL_TE | MAC_CONTROL_RE; + else + value &=3D ~(MAC_CONTROL_RE); + + mac_wr32(mac, R_MAC_CONTROL, value); + value =3D mac_rd32(mac, R_MAC_FRAME_FILTER); + mac_wr32(mac, R_MAC_FRAME_FILTER, value | 1); +} + static struct mucse_mac_operations mac_ops_n500 =3D { .set_mac =3D &rnpgbe_mac_set_mac_n500, + .set_mac_rx =3D &rnpgbe_mac_set_rx_n500, }; =20 /** @@ -375,6 +416,27 @@ static void rnpgbe_check_link_hw_ops_n500(struct mucse= _hw *hw, *duplex =3D !!hw->duplex; } =20 +/** + * rnpgbe_set_mac_rx_hw_ops_n500 - Setup hw rx status + * @hw: hw information structure + * @status: true for rx on / false for rx off + * + * rnpgbe_set_mac_rx_hw_ops_n500 setup eth, mac rx status. + **/ +static void rnpgbe_set_mac_rx_hw_ops_n500(struct mucse_hw *hw, bool status) +{ + struct mucse_eth_info *eth =3D &hw->eth; + struct mucse_mac_info *mac =3D &hw->mac; + + if (status) { + mac->ops.set_mac_rx(mac, status); + eth->ops.set_rx(eth, status); + } else { + eth->ops.set_rx(eth, status); + mac->ops.set_mac_rx(mac, status); + } +} + static struct mucse_hw_operations hw_ops_n500 =3D { .init_hw =3D &rnpgbe_init_hw_ops_n500, .reset_hw =3D &rnpgbe_reset_hw_ops_n500, @@ -387,6 +449,7 @@ static struct mucse_hw_operations hw_ops_n500 =3D { .set_mbx_link_event =3D &rnpgbe_set_mbx_link_event_hw_ops_n500, .set_mbx_ifup =3D &rnpgbe_set_mbx_ifup_hw_ops_n500, .check_link =3D &rnpgbe_check_link_hw_ops_n500, + .set_mac_rx =3D &rnpgbe_set_mac_rx_hw_ops_n500, }; =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/et= hernet/mucse/rnpgbe/rnpgbe_hw.h index 98031600801b..71a408c941e3 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h @@ -26,6 +26,8 @@ #define RING_VECTOR(n) (0x04 * (n)) =20 /* eth regs */ +#define RNPGBE_ETH_TX_MUX_DROP (0x98) +#define RNPGBE_ETH_EXCEPT_DROP_PROC (0x0470) #define RNPGBE_ETH_BYPASS (0x8000) #define RNPGBE_HOST_FILTER_EN (0x800c) #define RNPGBE_REDIR_EN (0x8030) @@ -43,6 +45,10 @@ #define RNPGBE_LEGANCY_ENABLE (0xd004) #define RNPGBE_LEGANCY_TIME (0xd000) /* mac regs */ +#define R_MAC_CONTROL (0) +#define MAC_CONTROL_TE (0x8) +#define MAC_CONTROL_RE (0x4) +#define R_MAC_FRAME_FILTER (0x4) #define M_RAH_AV 0x80000000 #define RNPGBE_MAC_UNICAST_LOW(i) (0x44 + (i) * 0x08) #define RNPGBE_MAC_UNICAST_HIGH(i) (0x40 + (i) * 0x08) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index b646aba48348..1e1919750a9b 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -152,6 +152,139 @@ static void mucse_add_ring(struct mucse_ring *ring, head->count++; } =20 +/** + * rnpgbe_clean_tx_irq - Reclaim resources after transmit completes + * @q_vector: structure containing interrupt and ring information + * @tx_ring: tx ring to clean + * @napi_budget: how many packets driver is allowed to clean + * @return: true is no tx packets. + **/ +static bool rnpgbe_clean_tx_irq(struct mucse_q_vector *q_vector, + struct mucse_ring *tx_ring, + int napi_budget) +{ + u64 total_bytes =3D 0, total_packets =3D 0; + struct mucse *mucse =3D q_vector->mucse; + int budget =3D q_vector->tx.work_limit; + struct mucse_tx_buffer *tx_buffer; + struct rnpgbe_tx_desc *tx_desc; + int i =3D tx_ring->next_to_clean; + + if (test_bit(__MUCSE_DOWN, &mucse->state)) + return true; + + tx_ring->tx_stats.poll_count++; + tx_buffer =3D &tx_ring->tx_buffer_info[i]; + tx_desc =3D M_TX_DESC(tx_ring, i); + i -=3D tx_ring->count; + + do { + struct rnpgbe_tx_desc *eop_desc =3D tx_buffer->next_to_watch; + + /* if next_to_watch is not set then there is no work pending */ + if (!eop_desc) + break; + + /* prevent any other reads prior to eop_desc */ + rmb(); + + /* if eop DD is not set pending work has not been completed */ + if (!(eop_desc->vlan_cmd & cpu_to_le32(M_TXD_STAT_DD))) + break; + /* clear next_to_watch to prevent false hangs */ + tx_buffer->next_to_watch =3D NULL; + + /* update the statistics for this packet */ + total_bytes +=3D tx_buffer->bytecount; + total_packets +=3D tx_buffer->gso_segs; + + /* free the skb */ + napi_consume_skb(tx_buffer->skb, napi_budget); + + /* unmap skb header data */ + dma_unmap_single(tx_ring->dev, dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); + + /* clear tx_buffer data */ + tx_buffer->skb =3D NULL; + dma_unmap_len_set(tx_buffer, len, 0); + + /* unmap remaining buffers */ + while (tx_desc !=3D eop_desc) { + tx_buffer++; + tx_desc++; + i++; + if (unlikely(!i)) { + i -=3D tx_ring->count; + tx_buffer =3D tx_ring->tx_buffer_info; + tx_desc =3D M_TX_DESC(tx_ring, 0); + } + + /* unmap any remaining paged data */ + if (dma_unmap_len(tx_buffer, len)) { + dma_unmap_page(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + dma_unmap_len_set(tx_buffer, len, 0); + } + budget--; + } + + /* move us one more past the eop_desc for start of next pkt */ + tx_buffer++; + tx_desc++; + i++; + if (unlikely(!i)) { + i -=3D tx_ring->count; + tx_buffer =3D tx_ring->tx_buffer_info; + tx_desc =3D M_TX_DESC(tx_ring, 0); + } + + /* issue prefetch for next Tx descriptor */ + prefetch(tx_desc); + + /* update budget accounting */ + budget--; + } while (likely(budget > 0)); + netdev_tx_completed_queue(txring_txq(tx_ring), total_packets, + total_bytes); + i +=3D tx_ring->count; + tx_ring->next_to_clean =3D i; + u64_stats_update_begin(&tx_ring->syncp); + tx_ring->stats.bytes +=3D total_bytes; + tx_ring->stats.packets +=3D total_packets; + tx_ring->tx_stats.tx_clean_count +=3D total_packets; + tx_ring->tx_stats.tx_clean_times++; + if (tx_ring->tx_stats.tx_clean_times > 10) { + tx_ring->tx_stats.tx_clean_times =3D 0; + tx_ring->tx_stats.tx_clean_count =3D 0; + } + + u64_stats_update_end(&tx_ring->syncp); + q_vector->tx.total_bytes +=3D total_bytes; + q_vector->tx.total_packets +=3D total_packets; + tx_ring->tx_stats.send_done_bytes +=3D total_bytes; + +#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) + if (likely(netif_carrier_ok(tx_ring->netdev) && + (mucse_desc_unused(tx_ring) >=3D TX_WAKE_THRESHOLD))) { + /* Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ + smp_mb(); + if (__netif_subqueue_stopped(tx_ring->netdev, + tx_ring->queue_index) && + !test_bit(__MUCSE_DOWN, &mucse->state)) { + netif_wake_subqueue(tx_ring->netdev, + tx_ring->queue_index); + ++tx_ring->tx_stats.restart_queue; + } + } + + return total_bytes =3D=3D 0; +} + /** * rnpgbe_poll - NAPI polling RX/TX cleanup routine * @napi: napi struct with our devices info in it @@ -163,7 +296,31 @@ static void mucse_add_ring(struct mucse_ring *ring, **/ static int rnpgbe_poll(struct napi_struct *napi, int budget) { - return 0; + struct mucse_q_vector *q_vector =3D + container_of(napi, struct mucse_q_vector, napi); + struct mucse *mucse =3D q_vector->mucse; + bool clean_complete =3D true; + struct mucse_ring *ring; + int work_done =3D 0; + + mucse_for_each_ring(ring, q_vector->tx) + clean_complete =3D rnpgbe_clean_tx_irq(q_vector, ring, budget); + + if (!netif_running(mucse->netdev)) + clean_complete =3D true; + /* force done */ + if (test_bit(__MUCSE_DOWN, &mucse->state)) + clean_complete =3D true; + + if (!clean_complete) + return budget; + /* all work done, exit the polling mode */ + if (likely(napi_complete_done(napi, work_done))) { + if (!test_bit(__MUCSE_DOWN, &mucse->state)) + rnpgbe_irq_enable_queues(mucse, q_vector); + } + + return min(work_done, budget - 1); } =20 /** @@ -896,8 +1053,15 @@ static void rnpgbe_configure_tx_ring(struct mucse *mu= cse, **/ void rnpgbe_configure_tx(struct mucse *mucse) { - u32 i; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma; + u32 i, dma_axi_ctl; =20 + dma =3D &hw->dma; + /* dma_axi_en.tx_en must be before Tx queues are enabled */ + dma_axi_ctl =3D dma_rd32(dma, DMA_AXI_EN); + dma_axi_ctl |=3D TX_AXI_RW_EN; + dma_wr32(dma, DMA_AXI_EN, dma_axi_ctl); /* Setup the HW Tx Head and Tail descriptor pointers */ for (i =3D 0; i < (mucse->num_tx_queues); i++) rnpgbe_configure_tx_ring(mucse, mucse->tx_ring[i]); @@ -961,10 +1125,30 @@ static void rnpgbe_configure_rx_ring(struct mucse *m= ucse, **/ void rnpgbe_configure_rx(struct mucse *mucse) { - int i; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma; + int i, dma_axi_ctl; =20 + dma =3D &hw->dma; for (i =3D 0; i < mucse->num_rx_queues; i++) rnpgbe_configure_rx_ring(mucse, mucse->rx_ring[i]); + + /* dma_axi_en.tx_en must be before Tx queues are enabled */ + dma_axi_ctl =3D dma_rd32(dma, DMA_AXI_EN); + dma_axi_ctl |=3D RX_AXI_RW_EN; + dma_wr32(dma, DMA_AXI_EN, dma_axi_ctl); +} + +/** + * rnpgbe_clean_all_tx_rings - Free Tx Buffers for all queues + * @mucse: pointer to private structure + **/ +void rnpgbe_clean_all_tx_rings(struct mucse *mucse) +{ + int i; + + for (i =3D 0; i < mucse->num_tx_queues; i++) + rnpgbe_clean_tx_ring(mucse->tx_ring[i]); } =20 /** @@ -976,6 +1160,13 @@ void rnpgbe_configure_rx(struct mucse *mucse) **/ static irqreturn_t rnpgbe_msix_clean_rings(int irq, void *data) { + struct mucse_q_vector *q_vector =3D (struct mucse_q_vector *)data; + + rnpgbe_irq_disable_queues(q_vector); + + if (q_vector->rx.ring || q_vector->tx.ring) + napi_schedule_irqoff(&q_vector->napi); + return IRQ_HANDLED; } =20 @@ -1052,11 +1243,17 @@ static int rnpgbe_request_msix_irqs(struct mucse *m= ucse) static irqreturn_t rnpgbe_intr(int irq, void *data) { struct mucse *mucse =3D (struct mucse *)data; + struct mucse_q_vector *q_vector; =20 + q_vector =3D mucse->q_vector[0]; + rnpgbe_irq_disable_queues(q_vector); set_bit(__MUCSE_IN_IRQ, &mucse->state); /* handle fw req and ack */ rnpgbe_fw_msg_handler(mucse); clear_bit(__MUCSE_IN_IRQ, &mucse->state); + if (q_vector->rx.ring || q_vector->tx.ring) + napi_schedule_irqoff(&q_vector->napi); + return IRQ_HANDLED; } =20 @@ -1251,3 +1448,231 @@ void rnpgbe_configure_msix(struct mucse *mucse) } } } + +/** + * rnpgbe_unmap_and_free_tx_resource - Free tx resource + * @ring: ring to be freed + * @tx_buffer: pointer to tx_buffer + **/ +static void rnpgbe_unmap_and_free_tx_resource(struct mucse_ring *ring, + struct mucse_tx_buffer *tx_buffer) +{ + if (tx_buffer->skb) { + dev_kfree_skb_any(tx_buffer->skb); + if (dma_unmap_len(tx_buffer, len)) + dma_unmap_single(ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + } else if (dma_unmap_len(tx_buffer, len)) { + dma_unmap_page(ring->dev, dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); + } + tx_buffer->next_to_watch =3D NULL; + tx_buffer->skb =3D NULL; + dma_unmap_len_set(tx_buffer, len, 0); +} + +/** + * rnpgbe_tx_map - map skb to desc, and update tx tail + * @tx_ring: ring to send + * @first: pointer to first tx_buffer for this skb + * @mac_ip_len: mac_ip_len value + * @tx_flags: tx flags for this skb + * + * rnpgbe_tx_map tries to map first->skb to multi descs, and + * then update tx tail to echo hw. + * + * @return: 0 on success, negative on failure + **/ +static int rnpgbe_tx_map(struct mucse_ring *tx_ring, + struct mucse_tx_buffer *first, u32 mac_ip_len, + u32 tx_flags) +{ + u64 fun_id =3D ((u64)(tx_ring->pfvfnum) << (56)); + struct mucse_tx_buffer *tx_buffer; + struct sk_buff *skb =3D first->skb; + struct rnpgbe_tx_desc *tx_desc; + u16 i =3D tx_ring->next_to_use; + unsigned int data_len, size; + skb_frag_t *frag; + dma_addr_t dma; + + tx_desc =3D M_TX_DESC(tx_ring, i); + size =3D skb_headlen(skb); + data_len =3D skb->data_len; + dma =3D dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); + tx_buffer =3D first; + + for (frag =3D &skb_shinfo(skb)->frags[0];; frag++) { + if (dma_mapping_error(tx_ring->dev, dma)) + goto dma_error; + + /* record length, and DMA address */ + dma_unmap_len_set(tx_buffer, len, size); + dma_unmap_addr_set(tx_buffer, dma, dma); + + /* 1st desc */ + tx_desc->pkt_addr =3D cpu_to_le64(dma | fun_id); + + while (unlikely(size > M_MAX_DATA_PER_TXD)) { + tx_desc->vlan_cmd_bsz =3D build_ctob(tx_flags, + mac_ip_len, + M_MAX_DATA_PER_TXD); + i++; + tx_desc++; + if (i =3D=3D tx_ring->count) { + tx_desc =3D M_TX_DESC(tx_ring, 0); + i =3D 0; + } + dma +=3D M_MAX_DATA_PER_TXD; + size -=3D M_MAX_DATA_PER_TXD; + tx_desc->pkt_addr =3D cpu_to_le64(dma | fun_id); + } + + if (likely(!data_len)) + break; + tx_desc->vlan_cmd_bsz =3D build_ctob(tx_flags, mac_ip_len, size); + /* =3D=3D=3D=3D frag=3D=3D */ + i++; + tx_desc++; + if (i =3D=3D tx_ring->count) { + tx_desc =3D M_TX_DESC(tx_ring, 0); + i =3D 0; + } + + size =3D skb_frag_size(frag); + data_len -=3D size; + dma =3D skb_frag_dma_map(tx_ring->dev, frag, 0, size, + DMA_TO_DEVICE); + tx_buffer =3D &tx_ring->tx_buffer_info[i]; + } + + /* write last descriptor with RS and EOP bits */ + tx_desc->vlan_cmd_bsz =3D build_ctob(tx_flags | + M_TXD_CMD_EOP | + M_TXD_CMD_RS, + mac_ip_len, size); + /* set the timestamp */ + first->time_stamp =3D jiffies; + tx_ring->tx_stats.send_bytes +=3D first->bytecount; + + /* + * Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. (Only applicable for weak-ordered + * memory model archs, such as IA-64). + * + * We also need this memory barrier to make certain all of the + * status bits have been updated before next_to_watch is written. + */ + /* timestamp the skb as late as possible, just prior to notifying + * the MAC that it should transmit this packet + */ + wmb(); + /* set next_to_watch value indicating a packet is present */ + first->next_to_watch =3D tx_desc; + i++; + if (i =3D=3D tx_ring->count) + i =3D 0; + tx_ring->next_to_use =3D i; + skb_tx_timestamp(skb); + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); + /* notify HW of packet */ + m_wr_reg(tx_ring->tail, i); + return 0; +dma_error: + /* clear dma mappings for failed tx_buffer_info map */ + for (;;) { + tx_buffer =3D &tx_ring->tx_buffer_info[i]; + rnpgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer); + if (tx_buffer =3D=3D first) + break; + if (i =3D=3D 0) + i +=3D tx_ring->count; + i--; + } + dev_kfree_skb_any(first->skb); + first->skb =3D NULL; + tx_ring->next_to_use =3D i; + + return -1; +} + +/** + * rnpgbe_maybe_stop_tx - Stop tx queues if not enough desc count + * @tx_ring: tx ring to check + * @size: expect desc count + * + * @return: 0 for enough + **/ +static int rnpgbe_maybe_stop_tx(struct mucse_ring *tx_ring, u16 size) +{ + if (likely(mucse_desc_unused(tx_ring) >=3D size)) + return 0; + netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); + /* Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); + * but since that doesn't exist yet, just open code it. + */ + smp_mb(); + + /* We need to check again in a case another CPU has just + * made room available. + */ + if (likely(mucse_desc_unused(tx_ring) < size)) + return -EBUSY; + + /* A reprieve! - use start_queue because it doesn't call schedule */ + netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index); + ++tx_ring->tx_stats.restart_queue; + + return 0; +} + +/** + * rnpgbe_xmit_frame_ring - Send a skb to tx ring + * @skb: skb is to be sent + * @mucse: pointer to private structure + * @tx_ring: tx ring to check + * + * @return: NETDEV_TX_OK is ok, or NETDEV_TX_BUSY + **/ +netdev_tx_t rnpgbe_xmit_frame_ring(struct sk_buff *skb, + struct mucse *mucse, + struct mucse_ring *tx_ring) +{ + u16 count =3D TXD_USE_COUNT(skb_headlen(skb)); + struct mucse_tx_buffer *first; + /* keep it not zero */ + u32 mac_ip_len =3D 20; + u32 tx_flags =3D 0; + unsigned short f; + + for (f =3D 0; f < skb_shinfo(skb)->nr_frags; f++) { + skb_frag_t *frag_temp =3D &skb_shinfo(skb)->frags[f]; + + count +=3D TXD_USE_COUNT(skb_frag_size(frag_temp)); + } + + if (rnpgbe_maybe_stop_tx(tx_ring, count + 3)) { + tx_ring->tx_stats.tx_busy++; + return NETDEV_TX_BUSY; + } + + /* record the location of the first descriptor for this packet */ + first =3D &tx_ring->tx_buffer_info[tx_ring->next_to_use]; + first->skb =3D skb; + first->bytecount =3D (skb->len > 60) ? skb->len : 60; + first->gso_segs =3D 1; + first->priv_tags =3D 0; + first->mss_len_vf_num =3D 0; + first->inner_vlan_tunnel_len =3D 0; + first->ctx_flag =3D false; + + if (rnpgbe_tx_map(tx_ring, first, mac_ip_len, tx_flags)) + goto skip_check; + rnpgbe_maybe_stop_tx(tx_ring, DESC_NEEDED); + +skip_check: + return NETDEV_TX_OK; +} diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index bdb8a393dad8..5a3334789f66 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -8,6 +8,9 @@ =20 #define RING_OFFSET(n) (0x100 * (n)) #define DMA_DUMY (0xc) +#define DMA_AXI_EN (0x10) +#define RX_AXI_RW_EN (0x03 << 0) +#define TX_AXI_RW_EN (0x03 << 2) #define DMA_RX_START (0x10) #define DMA_RX_READY (0x14) #define DMA_TX_START (0x18) @@ -52,6 +55,12 @@ #define e_info(msglvl, format, arg...) \ netif_info(mucse, msglvl, mucse->netdev, format, ##arg) =20 +/* now tx max 4k for one desc */ +#define M_MAX_TXD_PWR 12 +#define M_MAX_DATA_PER_TXD (0x1 << M_MAX_TXD_PWR) +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), M_MAX_DATA_PER_TXD) +#define DESC_NEEDED (MAX_SKB_FRAGS + 4) + enum link_event_mask { EVT_LINK_UP =3D 1, EVT_NO_MEDIA =3D 2, @@ -119,6 +128,7 @@ void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); int rnpgbe_setup_txrx(struct mucse *mucse); void rnpgbe_free_txrx(struct mucse *mucse); void rnpgbe_configure_tx(struct mucse *mucse); +void rnpgbe_clean_all_tx_rings(struct mucse *mucse); void rnpgbe_disable_rx_queue(struct mucse_ring *ring); void rnpgbe_configure_rx(struct mucse *mucse); int rnpgbe_request_irq(struct mucse *mucse); @@ -126,5 +136,7 @@ void rnpgbe_free_irq(struct mucse *mucse); void rnpgbe_napi_enable_all(struct mucse *mucse); void rnpgbe_napi_disable_all(struct mucse *mucse); void rnpgbe_configure_msix(struct mucse *mucse); - +netdev_tx_t rnpgbe_xmit_frame_ring(struct sk_buff *skb, + struct mucse *mucse, + struct mucse_ring *tx_ring); #endif /* _RNPGBE_LIB_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 90b4858597c1..31a191b31c79 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -162,12 +162,14 @@ static void rnpgbe_watchdog_update_link(struct mucse = *mucse) static void rnpgbe_watchdog_link_is_up(struct mucse *mucse) { struct net_device *netdev =3D mucse->netdev; + struct mucse_hw *hw =3D &mucse->hw; =20 /* only continue if link was previously down */ if (netif_carrier_ok(netdev)) return; netif_carrier_on(netdev); netif_tx_wake_all_queues(netdev); + hw->ops.set_mac_rx(hw, true); } =20 /** @@ -178,6 +180,7 @@ static void rnpgbe_watchdog_link_is_up(struct mucse *mu= cse) static void rnpgbe_watchdog_link_is_down(struct mucse *mucse) { struct net_device *netdev =3D mucse->netdev; + struct mucse_hw *hw =3D &mucse->hw; =20 mucse->link_up =3D false; mucse->link_speed =3D 0; @@ -187,6 +190,7 @@ static void rnpgbe_watchdog_link_is_down(struct mucse *= mucse) e_info(drv, "NIC Link is Down\n"); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); + hw->ops.set_mac_rx(hw, false); } =20 /** @@ -317,6 +321,7 @@ static void rnpgbe_down(struct mucse *mucse) struct net_device *netdev =3D mucse->netdev; =20 set_bit(__MUCSE_DOWN, &mucse->state); + hw->ops.set_mac_rx(hw, false); hw->ops.set_mbx_link_event(hw, 0); hw->ops.set_mbx_ifup(hw, 0); if (netif_carrier_ok(netdev)) @@ -324,6 +329,7 @@ static void rnpgbe_down(struct mucse *mucse) netif_tx_stop_all_queues(netdev); netif_carrier_off(netdev); rnpgbe_irq_disable(mucse); + netif_tx_disable(netdev); rnpgbe_napi_disable_all(mucse); mucse->flags &=3D ~M_FLAG_NEED_LINK_UPDATE; @@ -359,14 +365,83 @@ static int rnpgbe_close(struct net_device *netdev) static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + struct mucse *mucse =3D netdev_priv(netdev); + struct mucse_ring *tx_ring; + + if (!netif_carrier_ok(netdev)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + if (skb->len < 33) { + if (skb_padto(skb, 33)) + return NETDEV_TX_OK; + skb->len =3D 33; + } + if (skb->len > 65535) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + tx_ring =3D mucse->tx_ring[skb->queue_mapping]; + return rnpgbe_xmit_frame_ring(skb, mucse, tx_ring); +} + +/** + * rnpgbe_get_stats64 - Get stats for this netdev + * @netdev: network interface device structure + * @stats: stats data + **/ +static void rnpgbe_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct mucse *mucse =3D netdev_priv(netdev); + int i; + + rcu_read_lock(); + for (i =3D 0; i < mucse->num_rx_queues; i++) { + struct mucse_ring *ring =3D READ_ONCE(mucse->rx_ring[i]); + u64 bytes, packets; + unsigned int start; + + if (ring) { + do { + start =3D u64_stats_fetch_begin(&ring->syncp); + packets =3D ring->stats.packets; + bytes =3D ring->stats.bytes; + } while (u64_stats_fetch_retry(&ring->syncp, start)); + stats->rx_packets +=3D packets; + stats->rx_bytes +=3D bytes; + } + } + + for (i =3D 0; i < mucse->num_tx_queues; i++) { + struct mucse_ring *ring =3D READ_ONCE(mucse->tx_ring[i]); + u64 bytes, packets; + unsigned int start; + + if (ring) { + do { + start =3D u64_stats_fetch_begin(&ring->syncp); + packets =3D ring->stats.packets; + bytes =3D ring->stats.bytes; + } while (u64_stats_fetch_retry(&ring->syncp, start)); + stats->tx_packets +=3D packets; + stats->tx_bytes +=3D bytes; + } + } + rcu_read_unlock(); + /* following stats updated by rnpgbe_watchdog_task() */ + stats->multicast =3D netdev->stats.multicast; + stats->rx_errors =3D netdev->stats.rx_errors; + stats->rx_length_errors =3D netdev->stats.rx_length_errors; + stats->rx_crc_errors =3D netdev->stats.rx_crc_errors; + stats->rx_missed_errors =3D netdev->stats.rx_missed_errors; } =20 const struct net_device_ops rnpgbe_netdev_ops =3D { .ndo_open =3D rnpgbe_open, .ndo_stop =3D rnpgbe_close, .ndo_start_xmit =3D rnpgbe_xmit_frame, + .ndo_get_stats64 =3D rnpgbe_get_stats64, }; =20 /** --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 324952877F5; Mon, 21 Jul 2025 11:35:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.207.22.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097756; cv=none; b=k6sdeRpXzlsH/ukd8CegfZUSOGls874GqaVyfnPlhyBC7cRVMpF38Vo6ntwBPwK3xML0UzLvdjbwKTtQz7sibVlj1jcczZt7aRiik2uiRmTaYem5+0E5uwSM/HfMzlYyxF95Aru3z/AzU/b+Dwe9Fo4aUTrFSWfPWsKnTlwvTRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097756; c=relaxed/simple; bh=RG6bwRcCcc1AiujH53GQyNTnkI+tnuAoYlt6gJnlQgA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=g1wUc7kdEhn6dqstKVuY5caeqJ6+w7g/FlI+nSP4HvWI0P7CvHfmnI/eKfFTqEnpHwGUyk7uTqvVwk5FE5z3bbfV2KLqgQvRqcUOKJalVX8tvXyd/tdkUav3rxLebJBuuwxemsjDGPv7IrNa3aXCs58S5eDRficTR8XsM4YHY6g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=54.207.22.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097632ta8b187fc X-QQ-Originating-IP: kQTHuZbwoijf/mBgLEJHmJzRAFSqrcNJP5vPuBlD6ck= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:49 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13417546290855177934 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 14/15] net: rnpgbe: Add base rx function Date: Mon, 21 Jul 2025 19:32:37 +0800 Message-Id: <20250721113238.18615-15-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: OURTxbnUKnooUJ6y2Az48U6J3xNy4TRCGfczQqV03qLl24qT6CC3V+tS iwVomMr9qaBZSi4Hrs4yJ5lVuzdCJqG+b3/aLCBaA1Gq5d0xVxo0Bmfd8DcDlB0jup5C+ES bMfFUA+IEXturv9D0b3qYXPSlfS1mlse/OmKaYdAso8qOBijtymYo4wjQdF8gCSL+df+WSF yHq+U0Js77jgS50/iwTybiRY/LxEtvxwb8/wmqkdtyXjVwiyJVmR2M18gCSqSyZCi6S0aXS ri8HREK7ZRR4cAp+wOnRzQT2WUbvRplRh9oMOvaiJ8rYmQnI77mla+thnWnENmP/96CVT9b 6vGuqRCXgRTBiitW45+q9EOJDcqY7mS5dLDrnVnmYft+m9auvO8q0+1nNFXk0Jm7rn2Yj0F a/orRHJfKQyOP+FfI/0U9K0ObyAH/wHw3PN+SAV3+NJb6FKdPguTf8K5VxX+X48fl/8ikxO 7VSymYlyQ6ZNmIw6IV/s4lj1dshq56WNRr7+EAdrCvl/35ZFbIxbbOcGBfegEejMgP4ZTTC 4+k+6O9Y5d1prDdOv7F7lKKEMu32fcW4uGNHqGEzl72GFUY3LYG8iEC1zbAh4UvHE5NGODS iRF1vNnAk6zTVYblLabFobltPJk5sOc4M99KEUBUseKBMBpMLn+x2PUu7MSfZDsv3M/UOwo bWxMy99D5QE4C7Pe0HuWhMr0HK1eQjZF9FSYoYuypH0VHcNkzka17cWmIX6w/M9d4PUGg9W 2vgFwFAomrjJ0gtuZcdDsuU4/lsg+NK1zYRTUfwRv8kuQSeA5fLS4yQ/HGEecb4yxFLPjjj 1LlGXp0Gca7tBjUd5mYGvfNGn3FhnWONJ/STbKXuSFH2Tbj1+0W9fU1AFPcmxo34FnwiOFP vtClG41Ewr14PisRu09d3GnWSZZ8JqwfSsB//cnCrBdDpJi01+gOIz9effbGSxWTHYXnfGt yEpNFg3pjCTAfiLP7DsutK9IJc36MFKmsdiCbHI5effIWAlbROre8X9kKlBcRa+VF3vBZqu 4iuYWRxfQbzM21SCCwtLaNK2sSjlKSI1cowsrlcJi3z77j7Qeh X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize rx clean function. Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 23 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 547 +++++++++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 33 ++ 3 files changed, 602 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 26774c214da0..9d8d939d81a4 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -362,6 +362,7 @@ struct mucse_rx_queue_stats { u64 rx_equal_count; u64 rx_clean_times; u64 rx_clean_count; + u64 rx_resync; }; =20 union rnpgbe_rx_desc { @@ -492,6 +493,7 @@ struct mucse_ring { struct mucse_q_vector *q_vector; struct net_device *netdev; struct device *dev; + struct page_pool *page_pool; void *desc; union { struct mucse_tx_buffer *tx_buffer_info; @@ -584,6 +586,7 @@ struct mucse { #define M_FLAG_NEED_LINK_UPDATE BIT(0) #define M_FLAG_MSIX_ENABLED BIT(1) #define M_FLAG_MSI_ENABLED BIT(2) +#define M_FLAG_SRIOV_ENABLED BIT(23) u32 flags2; #define M_FLAG2_NO_NET_REG BIT(0) #define M_FLAG2_INSMOD BIT(1) @@ -633,6 +636,14 @@ static inline u16 mucse_desc_unused(struct mucse_ring = *ring) return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; } =20 +static inline u16 mucse_desc_unused_rx(struct mucse_ring *ring) +{ + u16 ntc =3D ring->next_to_clean; + u16 ntu =3D ring->next_to_use; + + return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 16; +} + static inline struct netdev_queue *txring_txq(const struct mucse_ring *rin= g) { return netdev_get_tx_queue(ring->netdev, ring->queue_index); @@ -644,12 +655,21 @@ static inline __le64 build_ctob(u32 vlan_cmd, u32 mac= _ip_len, u32 size) ((u64)size)); } =20 +#define M_RXBUFFER_256 (256) #define M_RXBUFFER_1536 (1536) static inline unsigned int mucse_rx_bufsz(struct mucse_ring *ring) { return (M_RXBUFFER_1536 - NET_IP_ALIGN); } =20 +#define M_RX_HDR_SIZE M_RXBUFFER_256 + +static inline __le16 rnpgbe_test_staterr(union rnpgbe_rx_desc *rx_desc, + const u16 stat_err_bits) +{ + return rx_desc->wb.cmd & cpu_to_le16(stat_err_bits); +} + #define M_TX_DESC(R, i) (&(((struct rnpgbe_tx_desc *)((R)->desc))[i])) #define M_RX_DESC(R, i) (&(((union rnpgbe_rx_desc *)((R)->desc))[i])) =20 @@ -681,6 +701,7 @@ static inline unsigned int mucse_rx_bufsz(struct mucse_= ring *ring) =20 #define M_TRY_LINK_TIMEOUT (4 * HZ) =20 +#define M_RX_BUFFER_WRITE (16) #define m_rd_reg(reg) readl(reg) #define m_wr_reg(reg, val) writel((val), reg) #define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) @@ -700,6 +721,8 @@ static inline unsigned int mucse_rx_bufsz(struct mucse_= ring *ring) #define mucse_dbg(mucse, fmt, arg...) \ dev_dbg(&(mucse)->pdev->dev, fmt, ##arg) =20 +#define M_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) + void rnpgbe_service_event_schedule(struct mucse *mucse); =20 #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 1e1919750a9b..675ed12cffcb 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -3,11 +3,16 @@ =20 #include #include +#include +#include +#include =20 #include "rnpgbe.h" #include "rnpgbe_lib.h" #include "rnpgbe_mbx_fw.h" =20 +static bool rnpgbe_alloc_rx_buffers(struct mucse_ring *rx_ring, + u16 cleaned_count); /** * rnpgbe_set_rss_queues - Allocate queues for RSS * @mucse: pointer to private structure @@ -285,6 +290,409 @@ static bool rnpgbe_clean_tx_irq(struct mucse_q_vector= *q_vector, return total_bytes =3D=3D 0; } =20 +/** + * rnpgbe_get_buffer - get the rx_buffer to be used + * @rx_ring: pointer to rx ring + * @rx_desc: pointer to rx_ring for this packet + * @skb: pointer skb for this packet + * @size: data size in this desc + * @return: rx_buffer. + **/ +static struct mucse_rx_buffer *rnpgbe_get_buffer(struct mucse_ring *rx_rin= g, + union rnpgbe_rx_desc *rx_desc, + struct sk_buff **skb, + const unsigned int size) +{ + struct mucse_rx_buffer *rx_buffer; + int time =3D 0; + u16 *data; + + rx_buffer =3D &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; + data =3D page_address(rx_buffer->page) + rx_buffer->page_offset; + *skb =3D rx_buffer->skb; + + prefetchw(page_address(rx_buffer->page) + rx_buffer->page_offset); + + /* we are reusing so sync this buffer for CPU use */ +try_sync: + dma_sync_single_range_for_cpu(rx_ring->dev, rx_buffer->dma, + rx_buffer->page_offset, size, + DMA_FROM_DEVICE); + + if ((*data =3D=3D CHECK_DATA) && time < 4) { + time++; + udelay(5); + rx_ring->rx_stats.rx_resync++; + goto try_sync; + } + + return rx_buffer; +} + +/** + * rnpgbe_add_rx_frag - Add no-linear data to the skb + * @rx_ring: pointer to rx ring + * @rx_buffer: pointer to rx_buffer + * @skb: pointer skb for this packet + * @size: data size in this desc + **/ +static void rnpgbe_add_rx_frag(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *rx_buffer, + struct sk_buff *skb, + unsigned int size) +{ + unsigned int truesize =3D SKB_DATA_ALIGN(M_SKB_PAD + size); + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, + rx_buffer->page_offset, size, truesize); +} + +/** + * rnpgbe_build_skb - Try to build a sbk based on rx_buffer + * @rx_ring: pointer to rx ring + * @rx_buffer: pointer to rx_buffer + * @rx_desc: pointer to rx desc for this data + * @size: data size in this desc + * @return: skb for this rx_buffer + **/ +static struct sk_buff *rnpgbe_build_skb(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *rx_buffer, + union rnpgbe_rx_desc *rx_desc, + unsigned int size) +{ + unsigned int truesize =3D SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(size + M_SKB_PAD); + void *va =3D page_address(rx_buffer->page) + rx_buffer->page_offset; + struct sk_buff *skb; + + net_prefetch(va); + /* build an skb around the page buffer */ + skb =3D build_skb(va - M_SKB_PAD, truesize); + if (unlikely(!skb)) + return NULL; + + /* update pointers within the skb to store the data */ + skb_reserve(skb, M_SKB_PAD); + __skb_put(skb, size); + + skb_mark_for_recycle(skb); + + return skb; +} + +/** + * rnpgbe_put_rx_buffer - clear rx_buffer for next use + * @rx_ring: pointer to rx ring + * @rx_buffer: pointer to rx_buffer + **/ +static void rnpgbe_put_rx_buffer(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *rx_buffer) +{ + /* clear contents of rx_buffer */ + rx_buffer->page =3D NULL; + rx_buffer->skb =3D NULL; +} + +/** + * rnpgbe_is_non_eop - process handling of non-EOP buffers + * @rx_ring: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer + * @skb: Current socket buffer containing buffer in progress + * + * This function updates next to clean. If the buffer is an EOP buffer + * this function exits returning false, otherwise it will place the + * sk_buff in the next buffer to be chained and return true indicating + * that this is in fact a non-EOP buffer. + * + * @return: true for not end of packet + **/ +static bool rnpgbe_is_non_eop(struct mucse_ring *rx_ring, + union rnpgbe_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u32 ntc =3D rx_ring->next_to_clean + 1; + + /* fetch, update, and store next to clean */ + ntc =3D (ntc < rx_ring->count) ? ntc : 0; + rx_ring->next_to_clean =3D ntc; + + prefetch(M_RX_DESC(rx_ring, ntc)); + + /* if we are the last buffer then there is nothing else to do */ + if (likely(rnpgbe_test_staterr(rx_desc, M_RXD_STAT_EOP))) + return false; + /* place skb in next buffer to be received */ + rx_ring->rx_buffer_info[ntc].skb =3D skb; + rx_ring->rx_stats.non_eop_descs++; + /* we should clean it since we used all info in it */ + rx_desc->wb.cmd =3D 0; + + return true; +} + +/** + * rnpgbe_pull_tail - Pull header to linear portion of buffer + * @skb: Current socket buffer containing buffer in progress + **/ +static void rnpgbe_pull_tail(struct sk_buff *skb) +{ + skb_frag_t *frag =3D &skb_shinfo(skb)->frags[0]; + unsigned int pull_len; + unsigned char *va; + + /* + * it is valid to use page_address instead of kmap since we are + * working with pages allocated out of the lomem pool per + * alloc_page(GFP_ATOMIC) + */ + va =3D skb_frag_address(frag); + + /* + * we need the header to contain the greater of either ETH_HLEN or + * 60 bytes if the skb->len is less than 60 for skb_pad. + */ + pull_len =3D eth_get_headlen(skb->dev, va, M_RX_HDR_SIZE); + + /* align pull length to size of long to optimize memcpy performance */ + skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); + + /* update all of the pointers */ + skb_frag_size_sub(frag, pull_len); + skb_frag_off_add(frag, pull_len); + skb->data_len -=3D pull_len; + skb->tail +=3D pull_len; +} + +/** + * rnpgbe_cleanup_headers - Correct corrupted or empty headers + * @skb: Current socket buffer containing buffer in progress + * @return: true if an error was encountered and skb was freed. + **/ +static bool rnpgbe_cleanup_headers(struct sk_buff *skb) +{ + if (IS_ERR(skb)) + return true; + /* place header in linear portion of buffer */ + if (!skb_headlen(skb)) + rnpgbe_pull_tail(skb); + /* if eth_skb_pad returns an error the skb was freed */ + if (eth_skb_pad(skb)) + return true; + + return false; +} + +/** + * rnpgbe_rx_hash - Setup hash type for skb + * @ring: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer + * @skb: Current socket buffer containing buffer in progress + **/ +static void rnpgbe_rx_hash(struct mucse_ring *ring, + union rnpgbe_rx_desc *rx_desc, + struct sk_buff *skb) +{ + int rss_type; + + if (!(ring->netdev->features & NETIF_F_RXHASH)) + return; +#define M_RSS_TYPE_MASK 0xc0 + rss_type =3D rx_desc->wb.cmd & M_RSS_TYPE_MASK; + skb_set_hash(skb, le32_to_cpu(rx_desc->wb.rss_hash), + rss_type ? PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + +/** + * rnpgbe_rx_checksum - indicate in skb if hw indicated a good cksum + * @ring: structure containing ring specific data + * @rx_desc: current Rx descriptor being processed + * @skb: skb currently being received and modified + **/ +static void rnpgbe_rx_checksum(struct mucse_ring *ring, + union rnpgbe_rx_desc *rx_desc, + struct sk_buff *skb) +{ + skb_checksum_none_assert(skb); + /* Rx csum disabled */ + if (!(ring->netdev->features & NETIF_F_RXCSUM)) + return; + + /* if outer L3/L4 error */ + /* must in promisc mode or rx-all mode */ + if (rnpgbe_test_staterr(rx_desc, M_RXD_STAT_ERR_MASK)) + return; + ring->rx_stats.csum_good++; + /* at least it is a ip packet which has ip checksum */ + + /* It must be a TCP or UDP packet with a valid checksum */ + skb->ip_summed =3D CHECKSUM_UNNECESSARY; +} + +/** + * rnpgbe_process_skb_fields - Setup skb header fields from desc + * @rx_ring: structure containing ring specific data + * @rx_desc: current Rx descriptor being processed + * @skb: skb currently being received and modified + * + * rnpgbe_process_skb_fields checks the ring, descriptor information + * in order to setup the hash, chksum, vlan, protocol, and other + * fields within the skb. + **/ +static void rnpgbe_process_skb_fields(struct mucse_ring *rx_ring, + union rnpgbe_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct net_device *dev =3D rx_ring->netdev; + struct mucse *mucse =3D netdev_priv(dev); + + rnpgbe_rx_hash(rx_ring, rx_desc, skb); + rnpgbe_rx_checksum(rx_ring, rx_desc, skb); + + if (((dev->features & NETIF_F_HW_VLAN_CTAG_RX) || + (dev->features & NETIF_F_HW_VLAN_STAG_RX)) && + rnpgbe_test_staterr(rx_desc, M_RXD_STAT_VLAN_VALID) && + !ignore_veb_vlan(mucse, rx_desc)) { + if (rnpgbe_test_ext_cmd(rx_desc, REV_OUTER_VLAN)) { + u16 vid_inner =3D le16_to_cpu(rx_desc->wb.vlan); + u16 vlan_tci =3D htons(ETH_P_8021Q); + u16 vid_outer; + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + vid_inner); + /* check outer vlan type */ + if (rnpgbe_test_staterr(rx_desc, M_RXD_STAT_STAG)) + vlan_tci =3D htons(ETH_P_8021AD); + else + vlan_tci =3D htons(ETH_P_8021Q); + vid_outer =3D le16_to_cpu(rx_desc->wb.mark); + /* push outer */ + skb =3D __vlan_hwaccel_push_inside(skb); + __vlan_hwaccel_put_tag(skb, vlan_tci, vid_outer); + } else { + /* only inner vlan */ + u16 vid =3D le16_to_cpu(rx_desc->wb.vlan); + /* check vlan type */ + if (rnpgbe_test_staterr(rx_desc, M_RXD_STAT_STAG)) { + __vlan_hwaccel_put_tag(skb, + htons(ETH_P_8021AD), + vid); + } else { + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + vid); + } + } + rx_ring->rx_stats.vlan_remove++; + } + skb_record_rx_queue(skb, rx_ring->queue_index); + skb->protocol =3D eth_type_trans(skb, dev); +} + +/** + * rnpgbe_clean_rx_irq - Clean completed descriptors from Rx ring + * @q_vector: structure containing interrupt and ring information + * @rx_ring: rx descriptor ring to transact packets on + * @budget: Total limit on number of packets to process + * + * rnpgbe_clean_rx_irq tries to check dd in desc, handle this desc + * if dd is set which means data is write-back by hw + * + * @return: amount of work completed. + **/ +static int rnpgbe_clean_rx_irq(struct mucse_q_vector *q_vector, + struct mucse_ring *rx_ring, + int budget) +{ + unsigned int total_rx_bytes =3D 0, total_rx_packets =3D 0; + u16 cleaned_count =3D mucse_desc_unused_rx(rx_ring); + unsigned int driver_drop_packets =3D 0; + bool fail_alloc =3D false; + bool new =3D false; + + while (likely(total_rx_packets < budget)) { + struct mucse_rx_buffer *rx_buffer; + union rnpgbe_rx_desc *rx_desc; + struct sk_buff *skb; + unsigned int size; + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >=3D M_RX_BUFFER_WRITE) { + new =3D rnpgbe_alloc_rx_buffers(rx_ring, cleaned_count); + fail_alloc =3D new || fail_alloc; + cleaned_count =3D 0; + } + rx_desc =3D M_RX_DESC(rx_ring, rx_ring->next_to_clean); + + if (!rnpgbe_test_staterr(rx_desc, M_RXD_STAT_DD)) + break; + + /* This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc until we know the + * descriptor has been written back + */ + dma_rmb(); + size =3D le16_to_cpu(rx_desc->wb.len); + if (!size) + break; + + rx_buffer =3D rnpgbe_get_buffer(rx_ring, rx_desc, &skb, size); + + if (skb) + rnpgbe_add_rx_frag(rx_ring, rx_buffer, skb, size); + else + skb =3D rnpgbe_build_skb(rx_ring, rx_buffer, rx_desc, + size); + /* exit if we failed to retrieve a buffer */ + if (!skb) { + page_pool_recycle_direct(rx_ring->page_pool, + rx_buffer->page); + rx_ring->rx_stats.alloc_rx_buff_failed++; + break; + } + + rnpgbe_put_rx_buffer(rx_ring, rx_buffer); + cleaned_count++; + + /* place incomplete frames back on ring for completion */ + if (rnpgbe_is_non_eop(rx_ring, rx_desc, skb)) + continue; + + /* verify the packet layout is correct */ + if (rnpgbe_cleanup_headers(skb)) { + /* we should clean it since we used all info in it */ + rx_desc->wb.cmd =3D 0; + continue; + } + + /* probably a little skewed due to removing CRC */ + total_rx_bytes +=3D skb->len; + /* populate checksum, timestamp, VLAN, and protocol */ + rnpgbe_process_skb_fields(rx_ring, rx_desc, skb); + /* we should clean it since we used all info in it */ + rx_desc->wb.cmd =3D 0; + napi_gro_receive(&q_vector->napi, skb); + /* update budget accounting */ + total_rx_packets++; + } + + u64_stats_update_begin(&rx_ring->syncp); + rx_ring->stats.packets +=3D total_rx_packets; + rx_ring->stats.bytes +=3D total_rx_bytes; + rx_ring->rx_stats.driver_drop_packets +=3D driver_drop_packets; + rx_ring->rx_stats.rx_clean_count +=3D total_rx_packets; + rx_ring->rx_stats.rx_clean_times++; + if (rx_ring->rx_stats.rx_clean_times > 10) { + rx_ring->rx_stats.rx_clean_times =3D 0; + rx_ring->rx_stats.rx_clean_count =3D 0; + } + u64_stats_update_end(&rx_ring->syncp); + q_vector->rx.total_packets +=3D total_rx_packets; + q_vector->rx.total_bytes +=3D total_rx_bytes; + + if (total_rx_packets >=3D budget) + rx_ring->rx_stats.poll_again_count++; + return fail_alloc ? budget : total_rx_packets; +} + /** * rnpgbe_poll - NAPI polling RX/TX cleanup routine * @napi: napi struct with our devices info in it @@ -299,12 +707,27 @@ static int rnpgbe_poll(struct napi_struct *napi, int = budget) struct mucse_q_vector *q_vector =3D container_of(napi, struct mucse_q_vector, napi); struct mucse *mucse =3D q_vector->mucse; + int per_ring_budget, work_done =3D 0; bool clean_complete =3D true; struct mucse_ring *ring; - int work_done =3D 0; + int cleaned_total =3D 0; =20 mucse_for_each_ring(ring, q_vector->tx) clean_complete =3D rnpgbe_clean_tx_irq(q_vector, ring, budget); + if (q_vector->rx.count > 1) + per_ring_budget =3D max(budget / q_vector->rx.count, 1); + else + per_ring_budget =3D budget; + + mucse_for_each_ring(ring, q_vector->rx) { + int cleaned =3D 0; + + cleaned =3D rnpgbe_clean_rx_irq(q_vector, ring, per_ring_budget); + work_done +=3D cleaned; + cleaned_total +=3D cleaned; + if (cleaned >=3D per_ring_budget) + clean_complete =3D false; + } =20 if (!netif_running(mucse->netdev)) clean_complete =3D true; @@ -829,6 +1252,35 @@ static void rnpgbe_free_all_tx_resources(struct mucse= *mucse) rnpgbe_free_tx_resources(mucse->tx_ring[i]); } =20 +/** + * mucse_alloc_page_pool - Alloc page poll for tis ring + * @rx_ring: pointer to rx ring + * @return: 0 if success + **/ +static int mucse_alloc_page_pool(struct mucse_ring *rx_ring) +{ + int ret =3D 0; + + struct page_pool_params pp_params =3D { + .flags =3D PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .order =3D 0, + .pool_size =3D rx_ring->size, + .nid =3D dev_to_node(rx_ring->dev), + .dev =3D rx_ring->dev, + .dma_dir =3D DMA_FROM_DEVICE, + .offset =3D 0, + .max_len =3D PAGE_SIZE, + }; + + rx_ring->page_pool =3D page_pool_create(&pp_params); + if (IS_ERR(rx_ring->page_pool)) { + ret =3D PTR_ERR(rx_ring->page_pool); + rx_ring->page_pool =3D NULL; + } + + return ret; +} + /** * rnpgbe_setup_rx_resources - allocate Rx resources (Descriptors) * @rx_ring: rx descriptor ring (for a specific queue) to setup @@ -871,6 +1323,8 @@ static int rnpgbe_setup_rx_resources(struct mucse_ring= *rx_ring, memset(rx_ring->desc, 0, rx_ring->size); rx_ring->next_to_clean =3D 0; rx_ring->next_to_use =3D 0; + if (mucse_alloc_page_pool(rx_ring) + goto err; =20 return 0; err: @@ -901,6 +1355,7 @@ static void rnpgbe_clean_rx_ring(struct mucse_ring *rx= _ring) rx_buffer->page_offset, mucse_rx_bufsz(rx_ring), DMA_FROM_DEVICE); + page_pool_recycle_direct(rx_ring->page_pool, rx_buffer->page); rx_buffer->page =3D NULL; i++; rx_buffer++; @@ -933,6 +1388,10 @@ static void rnpgbe_free_rx_resources(struct mucse_rin= g *rx_ring) dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc =3D NULL; + if (rx_ring->page_pool) { + page_pool_destroy(rx_ring->page_pool); + rx_ring->page_pool =3D NULL; + } } =20 /** @@ -1076,6 +1535,91 @@ void rnpgbe_disable_rx_queue(struct mucse_ring *ring) ring_wr32(ring, DMA_RX_START, 0); } =20 +/** + * mucse_alloc_mapped_page - Alloc page for this rx_buffer + * @rx_ring: pointer to rx ring + * @bi: pointer to this rx_buffer structure + * + * mucse_alloc_mapped_page alloc memory page for this rx_buffer + **/ +static bool mucse_alloc_mapped_page(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *bi) +{ + struct page *page =3D bi->page; + dma_addr_t dma; + + page =3D page_pool_dev_alloc_pages(rx_ring->page_pool); + dma =3D page_pool_get_dma_addr(page); + + bi->dma =3D dma; + bi->page =3D page; + bi->page_offset =3D M_SKB_PAD; + + if (likely(page)) + return true; + else + return false; +} + +/** + * rnpgbe_alloc_rx_buffers - Replace used receive buffers + * @rx_ring: ring to place buffers on + * @cleaned_count: number of buffers to replace + **/ +static bool rnpgbe_alloc_rx_buffers(struct mucse_ring *rx_ring, + u16 cleaned_count) +{ + u64 fun_id =3D ((u64)(rx_ring->pfvfnum) << (32 + 24)); + union rnpgbe_rx_desc *rx_desc; + u16 i =3D rx_ring->next_to_use; + struct mucse_rx_buffer *bi; + bool err =3D false; + u16 *data; + u16 bufsz; + /* nothing to do */ + if (!cleaned_count) + return err; + + rx_desc =3D M_RX_DESC(rx_ring, i); + bi =3D &rx_ring->rx_buffer_info[i]; + i -=3D rx_ring->count; + bufsz =3D mucse_rx_bufsz(rx_ring); + + do { + if (!mucse_alloc_mapped_page(rx_ring, bi)) { + err =3D true; + break; + } + + data =3D page_address(bi->page) + bi->page_offset; + *data =3D CHECK_DATA; + dma_sync_single_range_for_device(rx_ring->dev, bi->dma, + bi->page_offset, bufsz, + DMA_FROM_DEVICE); + rx_desc->pkt_addr =3D + cpu_to_le64(bi->dma + bi->page_offset + fun_id); + + /* clean dd */ + rx_desc->resv_cmd =3D 0; + rx_desc++; + bi++; + i++; + if (unlikely(!i)) { + rx_desc =3D M_RX_DESC(rx_ring, 0); + bi =3D rx_ring->rx_buffer_info; + i -=3D rx_ring->count; + } + cleaned_count--; + } while (cleaned_count); + + i +=3D rx_ring->count; + + if (rx_ring->next_to_use !=3D i) + mucse_update_rx_tail(rx_ring, i); + + return err; +} + /** * rnpgbe_configure_rx_ring - Configure Rx ring after Reset * @mucse: pointer to private structure @@ -1115,6 +1659,7 @@ static void rnpgbe_configure_rx_ring(struct mucse *mu= cse, ring_wr32(ring, DMA_REG_RX_INT_DELAY_TIMER, mucse->rx_usecs * hw->usecstocount); ring_wr32(ring, DMA_REG_RX_INT_DELAY_PKTCNT, mucse->rx_frames); + rnpgbe_alloc_rx_buffers(ring, mucse_desc_unused_rx(ring)); } =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index 5a3334789f66..c138919c1b9a 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -6,6 +6,7 @@ =20 #include "rnpgbe.h" =20 +#define CHECK_DATA (0xabcd) #define RING_OFFSET(n) (0x100 * (n)) #define DMA_DUMY (0xc) #define DMA_AXI_EN (0x10) @@ -123,6 +124,38 @@ static inline void rnpgbe_irq_disable(struct mucse *mu= cse) } } =20 +static inline int ignore_veb_vlan(struct mucse *mucse, + union rnpgbe_rx_desc *rx_desc) +{ + if (unlikely((mucse->flags & M_FLAG_SRIOV_ENABLED) && + (cpu_to_le16(rx_desc->wb.rev1) & VEB_VF_IGNORE_VLAN))) { + return 1; + } + return 0; +} + +static inline __le16 rnpgbe_test_ext_cmd(union rnpgbe_rx_desc *rx_desc, + const u16 stat_err_bits) +{ + return rx_desc->wb.rev1 & cpu_to_le16(stat_err_bits); +} + +static inline void mucse_update_rx_tail(struct mucse_ring *rx_ring, + u32 val) +{ + rx_ring->next_to_use =3D val; + /* update next to alloc since we have filled the ring */ + rx_ring->next_to_alloc =3D val; + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + m_wr_reg(rx_ring->tail, val); +} + int rnpgbe_init_interrupt_scheme(struct mucse *mucse); void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); int rnpgbe_setup_txrx(struct mucse *mucse); --=20 2.25.1 From nobody Mon Oct 6 13:38:22 2025 Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 662EC2BD595; Mon, 21 Jul 2025 11:35:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.59.177.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097753; cv=none; b=XGg5KUZhfp7kmt1bftN9xuT/RVvGL9Ml323Ha8u2asIe+Acr5sV5n55/jQmjf5ZsTnodzFQOZ2H1Unde6+w2Jr+67p8eVW3sIgQrlVWmHiQWI+3DOnq1mgS3ESJh9QHhf7zBl/WRvqsLLKkinx+0mHBcUWL4qhXNNLOd31n7aHY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753097753; c=relaxed/simple; bh=kSqO5KJqMd0ShsTRf+YZa+U+68jPnc8xVojuiQAj/4I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uYhzhEfQWAuAeE1D42Qbi5XIJGOnHn+lTg4XB5roeR28/HKS9itu9jT7TP/B1A1jk8tTx04Hxo26Tu3FoFSmnQT+AtWVhE8aN40nHQQwTp3U35Gj63skT+QRMoEI2Hrtkf4viWLn7sGq6sFfNrrnSIQR+tWTKVCAx03/dcqD+dE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com; spf=pass smtp.mailfrom=mucse.com; arc=none smtp.client-ip=52.59.177.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=mucse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mucse.com X-QQ-mid: esmtpsz18t1753097637t10ed0f73 X-QQ-Originating-IP: AUZFOgkES0R6H72iICvKupyHsfemWHNYmBQqkItQFNA= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 21 Jul 2025 19:33:53 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 16800422432126434323 EX-QQ-RecipientCnt: 23 From: Dong Yibo To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, gur.stavi@huawei.com, maddy@linux.ibm.com, mpe@ellerman.id.au, danishanwar@ti.com, lee@trager.us, gongfan1@huawei.com, lorenzo@kernel.org, geert+renesas@glider.be, Parthiban.Veerasooran@microchip.com, lukas.bulwahn@redhat.com, alexanderduyck@fb.com, richardcochran@gmail.com Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH v2 15/15] net: rnpgbe: Add ITR for rx Date: Mon, 21 Jul 2025 19:32:38 +0800 Message-Id: <20250721113238.18615-16-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250721113238.18615-1-dong100@mucse.com> References: <20250721113238.18615-1-dong100@mucse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MxZCU/CcMqmTR5fpMEbbL1vpdrfH7ePor8jJNs5qjyXk8uQRsCWCKFoo RjbdtL8HgJ9gdZvKz9jSYeT2p8lzF9gH8JDZv9UanWQcwsulXG8JdmkFbWz/031roH/xdrz 19K+8gN7x75OZIP+bf/07HiYG/oOFb35uGoYjaYTa8WnwkLB70hnnYxQjykYzN+IwTnuGKG CjTbByNMeKz06iejWbSC66hbK5z8lcDohzwfPYG1BxRfJdgdEQ7OenQFdQUjNwL/4YcT59j Tp9uRO8LOKpNNAyJwQMYwy9g5EonSuX47tUVPK9rG6kNRLyr1ygdo0UIVLgyFGLDUY2ExUw h8kKZq3w6yIJgpyGK0SCUFSGBkBbztQtYeFOdH8/n1c6OwdPGbRldJTU1Sdnx1LIsD23j3p n6GLRSaWEoY1MCarf65Ao/nNj2wK6TGtWoCzV8bLpLvxXKKOa7bYXwcBJJvpjPzOT+UrqIn o9mQWfiT0AIXWLqdDn86sG0LGuS5vSF2N72Qwyx8Lj4vubUPUz39Qex0cS7c+4yqlCugFGj gb0c0kAV09bnGGxnBoN9NFihlEtrepulJMDUvJrXkHBf/JQA9nG++j0TYDtmE4CnYCeQAp2 H+hXJLbj9Qmc8g2roAltECBPk6rn+5fLa0Gq/Zmj49LNgRVSSLCr7vDZBohyAUbpkDtyDYO HGdSYizhP1ZP0ZF/dVZB7Wh1/iqgGnHZzi9EwEpkQkqsiQlREW9xIHXjn58hRsR2RAus1yk 6EneLwZ2DppaEn/5sTjeK209WeSCNcZfx7V4BZctOwXwwsXLgrY5VvLDcbasugmXviVY47m qQmstcvhMQmnCKxBL8Jk0UzrP4P6E/tWOspQkkWH1lC0/TE7rG8hQ+Ya99m5MMSWNvZXoOU 9ruPtCMC5YBQVGZ9UhphmH34MhEXQ8e8C1WcQ+sfj9fS56N/FF/vll7W5gwQofcRD7piKlT iZGsd0xA1RxEKnG79uKOIkJCTTG5ovE8/Ke5dcbRVe+hYQxdyUgLM/hL91Tg5LYUooduqHv l2MC+tQBssmvcRVr1TEgBVh24hManSSek/s987VmW393KV9QDoqqAlPuvvAXc= X-QQ-XMRINFO: NI4Ajvh11aEj8Xl/2s1/T8w= X-QQ-RECHKSPAM: 0 Content-Type: text/plain; charset="utf-8" Initialize itr function according to rx packets/bytes Signed-off-by: Dong Yibo --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 5 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 99 ++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 9d8d939d81a4..d24438f458ac 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -547,6 +547,8 @@ struct mucse_ring_container { unsigned int total_packets; u16 work_limit; u16 count; + u16 itr; + int update_count; }; =20 struct mucse_q_vector { @@ -701,6 +703,9 @@ static inline __le16 rnpgbe_test_staterr(union rnpgbe_r= x_desc *rx_desc, =20 #define M_TRY_LINK_TIMEOUT (4 * HZ) =20 +#define M_LOWEREST_ITR (5) +#define M_4K_ITR (980) + #define M_RX_BUFFER_WRITE (16) #define m_rd_reg(reg) readl(reg) #define m_wr_reg(reg, val) writel((val), reg) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 675ed12cffcb..1211b742223b 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -693,6 +693,66 @@ static int rnpgbe_clean_rx_irq(struct mucse_q_vector *= q_vector, return fail_alloc ? budget : total_rx_packets; } =20 +/** + * rnpgbe_update_ring_itr_rx - Update rx itr according received pacekts/by= tes + * @q_vector: structure containing interrupt and ring information + **/ +static void rnpgbe_update_ring_itr_rx(struct mucse_q_vector *q_vector) +{ + struct mucse *mucse =3D q_vector->mucse; + int new_val =3D q_vector->itr_rx; + int avg_wire_size =3D 0; + unsigned int packets; + + switch (mucse->link_speed) { + case M_LINK_SPEED_10_FULL: + case M_LINK_SPEED_100_FULL: + new_val =3D M_4K_ITR; + goto set_itr_val; + default: + break; + } + + packets =3D q_vector->rx.total_packets; + if (packets) + avg_wire_size =3D max_t(u32, avg_wire_size, + q_vector->rx.total_bytes / packets); + + /* if avg_wire_size isn't set no work was done */ + if (!avg_wire_size) + goto clear_counts; + + /* Add 24 bytes to size to account for CRC, preamble, and gap */ + avg_wire_size +=3D 24; + + /* Don't starve jumbo frames */ + avg_wire_size =3D min(avg_wire_size, 3000); + + /* Give a little boost to mid-size frames */ + if (avg_wire_size > 300 && avg_wire_size < 1200) + new_val =3D avg_wire_size / 3; + else + new_val =3D avg_wire_size / 2; + + if (new_val < M_LOWEREST_ITR) + new_val =3D M_LOWEREST_ITR; + +set_itr_val: + if (q_vector->rx.itr !=3D new_val) { + q_vector->rx.update_count++; + if (q_vector->rx.update_count >=3D 2) { + q_vector->rx.itr =3D new_val; + q_vector->rx.update_count =3D 0; + } + } else { + q_vector->rx.update_count =3D 0; + } + +clear_counts: + q_vector->rx.total_bytes =3D 0; + q_vector->rx.total_packets =3D 0; +} + /** * rnpgbe_poll - NAPI polling RX/TX cleanup routine * @napi: napi struct with our devices info in it @@ -739,6 +799,7 @@ static int rnpgbe_poll(struct napi_struct *napi, int bu= dget) return budget; /* all work done, exit the polling mode */ if (likely(napi_complete_done(napi, work_done))) { + rnpgbe_update_ring_itr_rx(q_vector); if (!test_bit(__MUCSE_DOWN, &mucse->state)) rnpgbe_irq_enable_queues(mucse, q_vector); } @@ -1696,6 +1757,42 @@ void rnpgbe_clean_all_tx_rings(struct mucse *mucse) rnpgbe_clean_tx_ring(mucse->tx_ring[i]); } =20 +/** + * rnpgbe_write_eitr_rx - write new itr to Hw + * @q_vector: structure containing interrupt and ring information + **/ +static void rnpgbe_write_eitr_rx(struct mucse_q_vector *q_vector) +{ + struct mucse *mucse =3D q_vector->mucse; + u32 new_itr_rx =3D q_vector->rx.itr; + u32 old_itr_rx =3D q_vector->rx.itr; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_ring *ring; + + new_itr_rx =3D new_itr_rx * hw->usecstocount; + /* if we are in auto mode write to hw */ + mucse_for_each_ring(ring, q_vector->rx) { + ring_wr32(ring, DMA_REG_RX_INT_DELAY_TIMER, new_itr_rx); + if (ring->ring_flags & M_RING_LOWER_ITR) { + /* if we are already in this mode skip */ + if (q_vector->itr_rx =3D=3D M_LOWEREST_ITR) + continue; + ring_wr32(ring, DMA_REG_RX_INT_DELAY_PKTCNT, 1); + ring_wr32(ring, DMA_REG_RX_INT_DELAY_TIMER, + M_LOWEREST_ITR); + q_vector->itr_rx =3D M_LOWEREST_ITR; + } else { + if (new_itr_rx =3D=3D q_vector->itr_rx) + continue; + ring_wr32(ring, DMA_REG_RX_INT_DELAY_TIMER, + new_itr_rx); + ring_wr32(ring, DMA_REG_RX_INT_DELAY_PKTCNT, + mucse->rx_frames); + q_vector->itr_rx =3D old_itr_rx; + } + } +} + /** * rnpgbe_msix_clean_rings - msix irq handler for ring irq * @irq: irq num @@ -1708,7 +1805,7 @@ static irqreturn_t rnpgbe_msix_clean_rings(int irq, v= oid *data) struct mucse_q_vector *q_vector =3D (struct mucse_q_vector *)data; =20 rnpgbe_irq_disable_queues(q_vector); - + rnpgbe_write_eitr_rx(q_vector); if (q_vector->rx.ring || q_vector->tx.ring) napi_schedule_irqoff(&q_vector->napi); =20 --=20 2.25.1