From nobody Wed Oct 8 02:02:21 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 F1EBC1DE3A8; Thu, 3 Jul 2025 01:51:09 +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=1751507476; cv=none; b=WJAChONdeRk5WByC9T2XBEHulw165IVIJ3YZUU4vcBI6zC3sHDlZXF3hg6xvir55F1uRFusRZZaRt6rafBk0VodH7t/AFh/AsoEGE2Wi3CJa+AG+diXsHxYYtqyob0KM8kwnfvB+b7s5YHbtlSzZuGbKCY6D+mVHExm/UFYKHr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507476; c=relaxed/simple; bh=GDBVF8MbBKihHLAEADIj6Yzy4W/NWhpQ/T+e33mdqj0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TnyNf4sE+XnvS9+AYm151ipoX4yfErKFkfwK6bJSGpF26Yvgl8DYcOSKVphC2pM355WQgx3kCVjWw5iDN1zvByu7Tx/jiU/L7S4mDfVBUP2es887fKPIeY+vDm5xWdOFAUsnSOS3Lr/jl55ch3xWiCXi7RIqf4BPvBW8c/Kdwsc= 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: zesmtpsz8t1751507364t9f52d5e6 X-QQ-Originating-IP: 3WdHkXG3DVFWUdOPnJvBMmcdSR+BRgxfgU/F3IOkH2o= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:21 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 15554768658210106800 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 01/15] net: rnpgbe: Add build support for rnpgbe Date: Thu, 3 Jul 2025 09:48:45 +0800 Message-Id: <20250703014859.210110-2-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: N76rkG23tQ5KZRRkwnBTeLkjOVm7NPdia357h369/D5SfMX8o6yAHcZr TkF6qllkVUKh+wlwQPVS7al/1B81AtulHlWoiK88NgwMTwxn12rAdLv4G70SWdZQGT6Rm+2 CVUhQSZ6FDUFEdMPbQgEeUrjAf8Dsg3/aEaxGLq3FLTzMxAIq1fTGAfsHb4X35CsxE+55Xx Pm+Fe6bX3DRLugIlmUJgPbEf6yoCud2ubs6uaAfbBrsNGcdFw3yp/5qo873C5uMnS3xcI/W Xnb9pNugmtqiFa3z+Efi2/cuzED4jFy9ABvVDTj+3kQ6LQ7ihHfPAGLq/EDPq7UHRJMQAYt xnSaMPB90ZeBSSqr9Wme0FAQCXUEa3ByXTLMl2h3e7EjJGT4lSQyY0C5NQ209xpoF21e7aW Y6Lc9ZfTqvLl8ucyftO8/6sivUq25dVe0u/Czbf6H9qCJQmRN1nLgEa8lwszvaEL4qZuBn2 67zgATlVhrqfdbhlM9AB8fe9i8Y1jnq7s+OPhymgqAembjn9bx1Dd1t70w5dkclJgda38zT Qhgj9tjkH3vlFIoYLrdj/5MkAxWH9QTKHzk/Xc+pzjym2FZscKMjxsOKx1grnSRRUl29MPh O7eARIXsC9hqy8iAdEWJmwKSWwBHX7ZSJ01RT+uJBTVGPFBYdi50eTRsSW+RMK1IAUyM1Hd /+55+Sjens7W8QnraxAenvYxh18pEUL+9gcKBkBxi1OfiXRrOB0hIGhcoTmVYV3lBXMqURX GZ7PnivpCyPekIHZdFkpNW5pNRJ0NKDgZ8cYcYpwhS/3jR78lOn6tQ7+Zpi0lHTP+NKAPHm j62ZNR9ckhVc5oIn1fdHDL+ISTigjQBBuJEtl1SO0/EosDkjtKUYPbTd/QeFP3eD7Ljugan 3qeBpmmbSEucFMLm/p84g+hXbW18prpv0uxNK+x3pfU92oZKC9Uiriy+uuHfZEm+hZSQKyj 9W201WJR5vPv7JEJPOoKSRxig3QUDldmkBxxSVl+Ol4hygu6KSsBhoo+syuzDde3BEDETqW Q66q3Ii6v1+myIFzNZ/K+sGxr5k09BgoKBht+gyhiAOTGCn3jKZ/C0l1XIrP6I6+zbO7D9M Z0jvnOL2+1O X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= 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 | 14 +- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/mucse/Kconfig | 35 +++ drivers/net/ethernet/mucse/Makefile | 7 + drivers/net/ethernet/mucse/rnpgbe/Makefile | 9 + drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 35 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 221 ++++++++++++++++++ 10 files changed, 340 insertions(+), 5 deletions(-) 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 139b4c75a191..f6db071210d9 100644 --- a/Documentation/networking/device_drivers/ethernet/index.rst +++ b/Documentation/networking/device_drivers/ethernet/index.rst @@ -59,6 +59,7 @@ Contents: ti/icssg_prueth wangxun/txgbe wangxun/ngbe + 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..5f0f338dc3d4 --- /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 marketing@mucse.com or check our websi= te + at https://www.mucse.com/en/ diff --git a/MAINTAINERS b/MAINTAINERS index bb9df569a3ff..b43ca711cc5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16001,11 +16001,7 @@ F: tools/testing/vma/ =20 MEMORY MAPPING - LOCKING M: Andrew Morton -M: Suren Baghdasaryan -M: Liam R. Howlett -M: Lorenzo Stoakes -R: Vlastimil Babka -R: Shakeel Butt +M: Suren Baghdasaryan M: Liam R. Howlett M: Lorenzo Stoakes R: Vlastimil B= abka R: Shakeel Butt L: linux-mm@kvack.org S: Maintained W: http://www.linux-mm.org @@ -16986,6 +16982,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..5825b37fcd50 --- /dev/null +++ b/drivers/net/ethernet/mucse/Kconfig @@ -0,0 +1,35 @@ +# 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 belonging to this class, s= ay 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 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..a44e6b6255d8 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2020 - 2025 Mucse Corporation. */ + +#ifndef _RNPGBE_H +#define _RNPGBE_H + +#define RNPGBE_MAX_QUEUES (8) + +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..b32b70c98b46 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -0,0 +1,221 @@ +// 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"; +static const char rnpgbe_driver_string[] =3D + "mucse 1 Gigabit PCI Express Network Driver"; +#define DRV_VERSION "1.0.0" +const char rnpgbe_driver_version[] =3D DRV_VERSION; +static const char rnpgbe_copyright[] =3D + "Copyright (c) 2020-2025 mucse Corporation."; + +/* 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_adpater - add netdev for this pci_dev + * @pdev: PCI device information structure + * + * rnpgbe_add_adpater initializes a netdev for this pci_dev + * structure. Initializes Bar map, private structure, and a + * hardware reset occur. + * + * Returns 0 on success, negative on failure + **/ +static int rnpgbe_add_adpater(struct pci_dev *pdev) +{ + struct mucse *mucse =3D NULL; + struct net_device *netdev; + static int bd_number; + + pr_info("=3D=3D=3D=3D add rnpgbe queues:%d =3D=3D=3D=3D", RNPGBE_MAX_QUE= UES); + netdev =3D alloc_etherdev_mq(sizeof(struct mucse), RNPGBE_MAX_QUEUES); + if (!netdev) + return -ENOMEM; + + mucse =3D netdev_priv(netdev); + memset((char *)mucse, 0x00, sizeof(struct mucse)); + 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_adpater + * to initializes netdev. + * + * Returns 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_adpater(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_adpater - remove netdev for this mucse structure + * @mucse: pointer to private structure + * + * rnpgbe_rm_adpater remove a netdev for this mucse structure + **/ +static void rnpgbe_rm_adpater(struct mucse *mucse) +{ + struct net_device *netdev; + + netdev =3D mucse->netdev; + pr_info("=3D remove rnpgbe:%s =3D\n", netdev->name); + free_netdev(netdev); + pr_info("remove complete\n"); +} + +/** + * 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_adpater(mucse); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +static void __rnpgbe_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_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, +}; + +static int __init rnpgbe_init_module(void) +{ + int ret; + + pr_info("%s - version %s\n", rnpgbe_driver_string, + rnpgbe_driver_version); + pr_info("%s\n", rnpgbe_copyright); + ret =3D pci_register_driver(&rnpgbe_driver); + if (ret) + return ret; + + return 0; +} + +module_init(rnpgbe_init_module); + +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 Wed Oct 8 02:02:21 2025 Received: from bg5.exmail.qq.com (bg5.exmail.qq.com [43.155.80.173]) (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 825902248A4; Thu, 3 Jul 2025 01:51:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=43.155.80.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507500; cv=none; b=WvQXAffBxc8frtRQMC0wWcaz3S/Q8AUkeq2C9ulCghy9KVXvXGZPiXYA0jGwnldPWbwjE7Mohps2jZoCwRCPgpazApP56Ten/3hXuQRfbvXtXGFOJAJBi7iQ9oHcjgm3rxNCVcFROx1BhafSs4wYFHPS4rKTAl5LMcUXuud/6o0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507500; c=relaxed/simple; bh=F6A6W3DZygzS9mfL758gzynoQ02XyvHfV3PwPDKNATE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PIpzg7tHLmUVZf9UVOKkCXZawTRcV/wOgfvmNGlx/dv/2br8sPau2wWwVwas9u0jrCAdmh+z0QGkkWCWpgeIVpeTQqog8tXGH83ftaab0g0GlNiNRdmEE6LpWaOZR2vfbLYewQSFpEYYHqqPyaCWeMh5dLmwUhWp+5scoZAaGnE= 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=43.155.80.173 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: zesmtpsz8t1751507367ted607381 X-QQ-Originating-IP: gmOFNm0kXs3InMfAirLbCmO88tJZmqesIzDah3Snyg8= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:25 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13013126927958381173 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 02/15] net: rnpgbe: Add n500/n210 chip support Date: Thu, 3 Jul 2025 09:48:46 +0800 Message-Id: <20250703014859.210110-3-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MRiFTjyIbtS1MnC1bVz/TJSMJhd6UAmfIrzhEx8NKY/RzI8GMbwsuagp xNxUiqBaRd59jONMnHOUbTe+e1aiG6YAqWSe6RRnCVO+8/CBp9tjzWE4gXytHt9ewieHeal qvBS3/htRS6YzlDdeED+E5Di4SEzBtwIpKpuMyuyVWlKXHCNZ4rAhpQl4fXWFgWsLy6GJmc 5w4KlhqsUw4JX6d+sqmOINGNfScKg+GLydkxcSfKf/Ue4TiFDkSwqMSOKKWjdZzJSD+nphI ZDtHUEsJu6I1q6dVS4xXOv9ipjAXeG0zBdtSzhQnuf6o4xj5mMgx/kuxGdHJI6iMG1pjs2Z Py1k1ibrrejBbXrvYpEtlPRUn8xV8tziTPN40zNiR23qLG4YXgB8uX3x6Hq7gd3MEUsqdBo Ax1LOqI7GkRlJFFdS224d1ER3vriAsjjCp0WbZEshhvo1Jm5YmFN+fA5BzC2gHcArH2NOfR qsXN8/0EZx5XaOo4fqdJDafIDyfsWO921MVe6dvDp2d6RazcV6rQZcoNcka+MpI1v9OjZnG ZVf/PqrtK0mtSffOqpAzKVIGZXyFSnldkKkTu/byZXvzqgrLkRvTAfy2h9iPOcvEieZk7HC XfeTFTx5XUh3FQ1fR8EUBk3sOVjks3JrYtbUdE61ZH6QpJUi6qJ/B0P5D+gHMHloi6cNVqC KKY7SLs8VSWJrFfcvbEu3Acf+RSTifzne/kEqGvCMSKRUX1NAGhhQaipVgwWtOOVlbJYJWp aLBWNxBkumQP5dmA4u4butNH8wwwqPHuDVDoy+hG0msIERb0MbKPhXFxAMX1CqeoXEJkTmd C8EojdFX/QwCktgLcO6tRISy986yExSvqwMQijnfHqfPQCC6evtxGtSKAKP4sBXRh3drDAZ /lrOnYA5zslGVdbsB9QU8H25a+zAKXCGMaZMd/yL7rXmsjckZMucL2e16d80eqpluFvj0s7 P/3p18nWPJdzCJ67xktWS7I/nvIXN1KDdrejPpE7SR6XsstGIjnVqENnx04o6Oxt4dzrWb+ VJGr6xZgLxmsSmcw3WDvPF03QkYW5JZzQ3Uzx2n9bYSN72EABFWrNgVXkkZ7CnN+Z56Nn5a g== X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= 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 | 139 +++++++++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 126 ++++++++++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 27 ++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 83 ++++++++++- 5 files changed, 372 insertions(+), 7 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 a44e6b6255d8..664b6c86819a 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -4,7 +4,12 @@ #ifndef _RNPGBE_H #define _RNPGBE_H =20 -#define RNPGBE_MAX_QUEUES (8) +#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; =20 enum rnpgbe_boards { board_n500, @@ -12,15 +17,144 @@ enum rnpgbe_boards { board_n210L, }; =20 +enum rnpgbe_hw_type { + rnpgbe_hw_n500 =3D 0, + rnpgbe_hw_n210, + rnpgbe_hw_n210L, +}; + +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]; + s32 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; + u8 addr[ETH_ALEN]; + u8 perm_addr[ETH_ALEN]; +}; + +#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 cpu_req; + u16 cpu_ack; + /* lock for only one user */ + struct mutex lock; + bool other_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; + /* cm3 <-> pf mbx */ + u32 cpu_pf_shm_base; + u32 pf2cpu_mbox_ctrl; + u32 pf2cpu_mbox_mask; + u32 cpu_pf_mbox_mask; + u32 cpu2pf_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 cpu_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 ((u32)(1 << 0)) +#define M_NET_FEATURE_TX_CHECKSUM ((u32)(1 << 1)) +#define M_NET_FEATURE_RX_CHECKSUM ((u32)(1 << 2)) +#define M_NET_FEATURE_TSO ((u32)(1 << 3)) +#define M_NET_FEATURE_TX_UDP_TUNNEL ((u32)(1 << 4)) +#define M_NET_FEATURE_VLAN_FILTER ((u32)(1 << 5)) +#define M_NET_FEATURE_VLAN_OFFLOAD ((u32)(1 << 6)) +#define M_NET_FEATURE_RX_NTUPLE_FILTER ((u32)(1 << 7)) +#define M_NET_FEATURE_TCAM ((u32)(1 << 8)) +#define M_NET_FEATURE_RX_HASH ((u32)(1 << 9)) +#define M_NET_FEATURE_RX_FCS ((u32)(1 << 10)) +#define M_NET_FEATURE_HW_TC ((u32)(1 << 11)) +#define M_NET_FEATURE_USO ((u32)(1 << 12)) +#define M_NET_FEATURE_STAG_FILTER ((u32)(1 << 13)) +#define M_NET_FEATURE_STAG_OFFLOAD ((u32)(1 << 14)) +#define M_NET_FEATURE_VF_FIXED ((u32)(1 << 15)) +#define M_VEB_VLAN_MASK_EN ((u32)(1 << 16)) +#define M_HW_FEATURE_EEE ((u32)(1 << 17)) +#define M_HW_SOFT_MASK_OTHER_IRQ ((u32)(1 << 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 @@ -32,4 +166,7 @@ struct mucse { #define PCI_DEVICE_ID_N210 0x8208 #define PCI_DEVICE_ID_N210L 0x820a =20 +#define rnpgbe_rd_reg(reg) readl((void *)(reg)) +#define rnpgbe_wr_reg(reg, val) writel((val), (void *)(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..5580298eabb6 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -0,0 +1,126 @@ +// 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 + * + **/ +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->cpu2pf_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->cpu_pf_shm_base =3D 0x2d000; + mbx->pf2cpu_mbox_ctrl =3D 0x2e000; + mbx->cpu_pf_mbox_mask =3D 0x2e200; + mbx->cpu_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; +} + +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->cpu2pf_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->cpu_pf_shm_base =3D 0x2d900; + mbx->pf2cpu_mbox_ctrl =3D 0x2e900; + mbx->cpu_pf_mbox_mask =3D 0x2eb00; + mbx->cpu_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 b32b70c98b46..30c5a4874929 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -17,6 +17,11 @@ static const char rnpgbe_driver_string[] =3D const char rnpgbe_driver_version[] =3D DRV_VERSION; static const char rnpgbe_copyright[] =3D "Copyright (c) 2020-2025 mucse Corporation."; +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 * @@ -36,9 +41,24 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +/** + * init_firmware_for_n210 - download firmware + * @hw: hardware structure + * + * init_firmware_for_n210 try to download firmware + * for n210, by bar0(hw->hw_addr). + * + * Returns 0 on success, negative on failure + **/ +static int init_firmware_for_n210(struct mucse_hw *hw) +{ + return 0; +} + /** * rnpgbe_add_adpater - add netdev for this pci_dev * @pdev: PCI device information structure + * @ii: chip info structure * * rnpgbe_add_adpater initializes a netdev for this pci_dev * structure. Initializes Bar map, private structure, and a @@ -46,17 +66,24 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { * * Returns 0 on success, negative on failure **/ -static int rnpgbe_add_adpater(struct pci_dev *pdev) +static int rnpgbe_add_adpater(struct pci_dev *pdev, + const struct rnpgbe_info *ii) { + int err =3D 0; struct mucse *mucse =3D NULL; struct net_device *netdev; + struct mucse_hw *hw =3D NULL; + u8 __iomem *hw_addr =3D NULL; + u32 dma_version =3D 0; static int bd_number; + u32 queues =3D ii->total_queue_pair_cnts; =20 - pr_info("=3D=3D=3D=3D add rnpgbe queues:%d =3D=3D=3D=3D", RNPGBE_MAX_QUE= UES); - netdev =3D alloc_etherdev_mq(sizeof(struct mucse), RNPGBE_MAX_QUEUES); + pr_info("=3D=3D=3D=3D add rnpgbe queues:%d =3D=3D=3D=3D", queues); + 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); memset((char *)mucse, 0x00, sizeof(struct mucse)); mucse->netdev =3D netdev; @@ -66,7 +93,54 @@ static int rnpgbe_add_adpater(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 rnpgbe_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 init_firmware_for_n210(hw); + /* 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 rnpgbe_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 /** @@ -83,6 +157,7 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev) static int rnpgbe_probe(struct pci_dev *pdev, const struct pci_device_id *= id) { int err; + const struct rnpgbe_info *ii =3D rnpgbe_info_tbl[id->driver_data]; =20 err =3D pci_enable_device_mem(pdev); if (err) @@ -105,7 +180,7 @@ static int rnpgbe_probe(struct pci_dev *pdev, const str= uct pci_device_id *id) =20 pci_set_master(pdev); pci_save_state(pdev); - err =3D rnpgbe_add_adpater(pdev); + err =3D rnpgbe_add_adpater(pdev, ii); if (err) goto err_regions; =20 --=20 2.25.1 From nobody Wed Oct 8 02:02:21 2025 Received: from smtpbg154.qq.com (smtpbg154.qq.com [15.184.224.54]) (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 B775922CBC6; Thu, 3 Jul 2025 01:51:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=15.184.224.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507484; cv=none; b=hvXkzpMCjenyc7VgufdbxccYldHxPoIOJSJv64bIsfVQI8spnUv9ADayxomNfB58geBH3Fh9gQPOviftNauKp2iEG2xn9M9PxpZE/Sz4SJJHBiKbzjqFdtdpONc8A8elSWRL85u3iZuq34Qrr5n/KXdLkZoC8du5EKQ1XzZo/VY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507484; c=relaxed/simple; bh=vHopI+3vdmWvIlIfdJ0fD4kaUzUytHLGFx5YrKept3M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HgMkrzR8w7fLR6XTSenLWkSGIEczZqbKjuMrtLhltOB+qG78qdTChGlzvNgYN/Sk4XXjQ9q+tJsn2NbzQoZzOHAVPZajyVY70JnvTf60rrHfMTuH5yuTezN87FdbTyN5lZeRsTxkdc2BRb9JKbFmfidndOqwDjM63uDTWDBJ3zs= 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=15.184.224.54 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: zesmtpsz8t1751507371t3fc1a580 X-QQ-Originating-IP: VPb6hTKB8nKZGBv13sKuqW1skGno5GiMXeoDkm4OP5o= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:28 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 2793561445784462735 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 03/15] net: rnpgbe: Add basic mbx ops support Date: Thu, 3 Jul 2025 09:48:47 +0800 Message-Id: <20250703014859.210110-4-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NCjYbQ0FTrEVY33nszPOHbcJE68vfUSobTt33UEk+ZnDirT6kCunKIuH MoJxD2q+6majlhK5dXAYKNIaN8F5ibUK6ivJIxchT4PsSm6/0wbDZyVri1TSnkCJu842CPq vJGrIoi6qRPGYW/jWvNSjFl678VM0mHT3X/DzLjSzNfp79wwkXnD9Y47lbbq8IJJXFvYUoJ nupOIiy3RwV6ds8YFlmd1IbO1idQwxXKrra5Q2lARkDqIa9xy7fts4bwRJdBYLwEPGeKR8U fGDWhhG8AtpYx6W3PGW3BB2ij7KuodAiqCojyeK+KK4fP0xNF7yvN6B2i5g/wxtzTz992MA JgyLBVcYscTGYxP2GdgyhX42LoJOKu5cqQa5Cn3gHfUOUEc7eY/cdxHJu1X6H2c9IXB82ot OdEK1ISxtjErir1csAaW78fd2K04+NjfnKDBGUe8F9/7arkMSINgKDT9snRmVmhSLkCYtwe +OfRjHJSVXuvMhQpveHLryZ1USP19Pp4fQ6KSPQ9qEm7qYzz9BRvwF5stJjtKRDXGTiOQsv 6r6mxpwnoHTDYkjFPe8cQbEW+VF90WPnzhvN4hgX4XoLN42sx0Q8+4qHQEEc+9VebZ69utm j8t9dKh0gkJBd3pnvaORnJ50unOCK99QaL5dsZWJITWo+S61e36x/j5P/VRNU1fl9ut3qiW x8FxjSN7GPI9ATmZGPHXtpGSfPmIm2pImS8Ed5zlObcvZ9YXJTlAtqFzXmADlHQHIEfwIAy ajLHS7ocNrdIeWjsuYBitXdiNjf5XOYrIJl5yE8fLX9iDYs1VSHe3+gPBTSxfYUnC36o4Xn pbFM7KpNrnAzjg9cp0Hhw5Ez8VqTL0V322kASxBlhZlbkYjtN0WHYEPOKIaTm3PQc/Q8WYt lFoGUrMWnPbLYZalcskOpNEJVERWKGPPib93OOOh8hI1xxnIbz6M99nMW1pt7tGWmyQTkx7 YY20yGocHJJAagA57ADxKoCeykkzAbnDs8UqcUT9nasHs/Xxs3roB+mVGex/S8vAQwmV6HT l/fdGmGXS508W2kXnMhmgBZpSqlW02msp0l0SVsOBSsleus25y X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= 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 | 64 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 25 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 1 + .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c | 622 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h | 48 ++ 7 files changed, 745 insertions(+), 22 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 664b6c86819a..4cafab16f5bf 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -64,18 +64,60 @@ struct mucse_mac_info { u8 perm_addr[ETH_ALEN]; }; =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 { + s32 (*init_params)(struct mucse_hw *hw); + s32 (*read)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + s32 (*write)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + s32 (*read_posted)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + s32 (*write_posted)(struct mucse_hw *hw, u32 *msg, + u16 size, enum MBX_ID id); + s32 (*check_for_msg)(struct mucse_hw *hw, enum MBX_ID id); + s32 (*check_for_ack)(struct mucse_hw *hw, enum MBX_ID id); + s32 (*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; u16 size; u16 vf_req[MAX_VF_NUM]; u16 vf_ack[MAX_VF_NUM]; - u16 cpu_req; - u16 cpu_ack; - /* lock for only one user */ + u16 fw_req; + u16 fw_ack; + /* lock for only one use mbx */ struct mutex lock; bool other_irq_enabled; int mbx_size; @@ -84,11 +126,11 @@ struct mucse_mbx_info { #define MBX_FEATURE_WRITE_DELAY BIT(1) u32 mbx_feature; /* cm3 <-> pf mbx */ - u32 cpu_pf_shm_base; - u32 pf2cpu_mbox_ctrl; - u32 pf2cpu_mbox_mask; - u32 cpu_pf_mbox_mask; - u32 cpu2pf_mbox_vec; + 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; @@ -96,10 +138,12 @@ struct mucse_mbx_info { u32 pf_vf_mbox_mask_hi; u32 pf2vf_mbox_vec_base; u32 vf2pf_mbox_vec_base; - u32 cpu_vf_share_ram; + u32 fw_vf_share_ram; int share_size; }; =20 +#include "rnpgbe_mbx.h" + struct mucse_hw { void *back; u8 pfvfnum; @@ -111,6 +155,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 5580298eabb6..08d082fa3066 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 @@ -57,18 +58,18 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw = *hw) mbx->mbx_feature |=3D MBX_FEATURE_NO_ZERO; /* mbx offset */ mbx->vf2pf_mbox_vec_base =3D 0x28900; - mbx->cpu2pf_mbox_vec =3D 0x28b00; + 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->cpu_pf_shm_base =3D 0x2d000; - mbx->pf2cpu_mbox_ctrl =3D 0x2e000; - mbx->cpu_pf_mbox_mask =3D 0x2e200; - mbx->cpu_vf_share_ram =3D 0x2b000; + 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; - + 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 | @@ -79,6 +80,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *h= w) M_NET_FEATURE_STAG_FILTER | M_NET_FEATURE_STAG_OFFLOAD; /* start the default ahz, update later*/ hw->usecstocount =3D 125; + hw->max_vfs =3D 7; } =20 static void rnpgbe_get_invariants_n210(struct mucse_hw *hw) @@ -91,20 +93,21 @@ static void rnpgbe_get_invariants_n210(struct mucse_hw = *hw) hw->ring_msix_base =3D hw->hw_addr + 0x29000; /* update mbx offset */ mbx->vf2pf_mbox_vec_base =3D 0x29200; - mbx->cpu2pf_mbox_vec =3D 0x29400; + 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->cpu_pf_shm_base =3D 0x2d900; - mbx->pf2cpu_mbox_ctrl =3D 0x2e900; - mbx->cpu_pf_mbox_mask =3D 0x2eb00; - mbx->cpu_vf_share_ram =3D 0x2b900; + 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; + 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 30c5a4874929..e125b609ba09 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -135,6 +135,7 @@ static int rnpgbe_add_adpater(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..f4bfa69fdb41 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ + +#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 + * + * returns 0 if it successfully read message or else + * MUCSE_ERR_MBX. + **/ +s32 mucse_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + s32 ret_val =3D MUCSE_ERR_MBX; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size =3D mbx->size; + + if (mbx->ops.read) + ret_val =3D mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * 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 + * + * returns 0 if it successfully write message or else + * MUCSE_ERR_MBX. + **/ +s32 mucse_write_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + s32 ret_val =3D 0; + + if (size > mbx->size) + ret_val =3D MUCSE_ERR_MBX; + else if (mbx->ops.write) + ret_val =3D mbx->ops.write(hw, msg, size, mbx_id); + + return ret_val; +} + +static inline u16 mucse_mbx_get_req(struct mucse_hw *hw, int reg) +{ + /* force memory barrier */ + mb(); + return ioread32(hw->hw_addr + reg) & 0xffff; +} + +static inline u16 mucse_mbx_get_ack(struct mucse_hw *hw, int reg) +{ + /* force memory barrier */ + mb(); + return (mbx_rd32(hw, reg) >> 16); +} + +static inline void mucse_mbx_inc_pf_req(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + u16 req; + u32 reg; + u32 v; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + 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 & 0xffff); + req++; + v &=3D ~(0x0000ffff); + v |=3D req; + /* force before write to hw */ + mb(); + mbx_wr32(hw, reg, v); + /* update stats */ + hw->mbx.stats.msgs_tx++; +} + +static inline void mucse_mbx_inc_pf_ack(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + u16 ack; + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 reg =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_COUNTER(mbx) : + PF2VF_COUNTER(mbx, mbx_id); + u32 v; + + v =3D mbx_rd32(hw, reg); + ack =3D (v >> 16) & 0xffff; + ack++; + v &=3D ~(0xffff0000); + 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 + * + * returns SUCCESS if the Status bit was found or else + * MUCSE_ERR_MBX + **/ +s32 mucse_check_for_msg(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + s32 ret_val =3D MUCSE_ERR_MBX; + + if (mbx->ops.check_for_msg) + ret_val =3D mbx->ops.check_for_msg(hw, mbx_id); + + return ret_val; +} + +/** + * 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 + * + * returns SUCCESS if the Status bit was found or + * else MUCSE_ERR_MBX + **/ +s32 mucse_check_for_ack(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + struct mucse_mbx_info *mbx =3D &hw->mbx; + s32 ret_val =3D MUCSE_ERR_MBX; + + if (mbx->ops.check_for_ack) + ret_val =3D mbx->ops.check_for_ack(hw, mbx_id); + + return ret_val; +} + +/** + * mucse_poll_for_msg - Wait for message notification + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to poll + * + * returns 0 if it successfully received a message notification + **/ +static s32 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; + + if (!countdown || !mbx->ops.check_for_msg) + goto out; + + while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } +out: + return countdown ? 0 : -ETIME; +} + +/** + * mucse_poll_for_ack - Wait for message acknowledgment + * @hw: Pointer to the HW structure + * @mbx_id: Id of vf/fw to poll + * + * returns 0 if it successfully received a message acknowledgment + **/ +static s32 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; + + if (!countdown || !mbx->ops.check_for_ack) + goto out; + + while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + +out: + return countdown ? 0 : MUCSE_ERR_MBX; +} + +/** + * 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 + * + * returns 0 if it successfully received a message notification and + * copied it into the receive buffer. + **/ +static s32 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; + s32 ret_val =3D MUCSE_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + 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); +out: + 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 + * + * returns 0 if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +static s32 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; + s32 ret_val =3D MUCSE_ERR_MBX; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + /* exit if either we can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + goto out; + + /* 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); + +out: + 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 + * + * returns 0 if the vf/fw has set the Status bit or else + * MUCSE_ERR_MBX + **/ +static s32 mucse_check_for_msg_pf(struct mucse_hw *hw, + enum MBX_ID mbx_id) +{ + s32 ret_val =3D MUCSE_ERR_MBX; + u16 hw_req_count =3D 0; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -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 + * + * returns SUCCESS if the vf/fw has set the Status bit or else + * MUCSE_ERR_MBX + **/ +static s32 mucse_check_for_ack_pf(struct mucse_hw *hw, enum MBX_ID mbx_id) +{ + s32 ret_val =3D MUCSE_ERR_MBX; + u16 hw_fw_ack =3D 0; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + 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 + * + * return 0 if we obtained the mailbox lock + **/ +static s32 mucse_obtain_mbx_lock_pf(struct mucse_hw *hw, enum MBX_ID mbx_i= d) +{ + int try_cnt =3D 5000; + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 CTRL_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, CTRL_REG, MBOX_CTRL_PF_HOLD_SHM); + /* force write back before check */ + wmb(); + /* reserve mailbox for fw use */ + if (mbx_rd32(hw, CTRL_REG) & MBOX_CTRL_PF_HOLD_SHM) + return 0; + udelay(100); + } + return -EPERM; +} + +/** + * 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 + * + * returns 0 if it successfully copied message into the buffer + **/ +static s32 mucse_write_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + s32 ret_val =3D 0; + u16 i; + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 DATA_REG =3D (mbx_id =3D=3D MBX_FW) ? FW_PF_SHM_DATA(mbx) : + PF_VF_SHM_DATA(mbx, mbx_id); + u32 CTRL_REG =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_MBOX_CTRL(mbx) : + PF2VF_MBOX_CTRL(mbx, mbx_id); + /* if pcie is off, we cannot exchange with hw */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + 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. + **/ +static s32 mucse_read_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id) +{ + s32 ret_val =3D -EIO; + u32 i; + struct mucse_mbx_info *mbx =3D &hw->mbx; + u32 BUF_REG =3D (mbx_id =3D=3D MBX_FW) ? FW_PF_SHM_DATA(mbx) : + PF_VF_SHM_DATA(mbx, mbx_id); + u32 CTRL_REG =3D (mbx_id =3D=3D MBX_FW) ? PF2FW_MBOX_CTRL(mbx) : + PF2VF_MBOX_CTRL(mbx, mbx_id); + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + 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, BUF_REG + 4 * i); + mbx_wr32(hw, BUF_REG, 0); + + /* update req. used by rnpvf_check_for_msg_vf */ + 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) +{ + int idx, v; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + 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 & 0xffff; + hw->mbx.vf_ack[idx] =3D (v >> 16) & 0xffff; + mbx_wr32(hw, PF2VF_MBOX_CTRL(mbx, idx), 0); + } + v =3D mbx_rd32(hw, FW2PF_COUNTER(mbx)); + hw->mbx.fw_req =3D v & 0xffff; + hw->mbx.fw_ack =3D (v >> 16) & 0xffff; + + 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), 0xffff0000); +} + +/** + * 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 int mucse_mbx_configure_pf(struct mucse_hw *hw, int nr_vec, + bool enable) +{ + int idx =3D 0; + u32 v; + struct mucse_mbx_info *mbx =3D &hw->mbx; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + 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 & 0xffff; + hw->mbx.vf_ack[idx] =3D (v >> 16) & 0xffff; + + mbx_wr32(hw, PF2VF_MBOX_CTRL(mbx, idx), 0); + } + v =3D mbx_rd32(hw, FW2PF_COUNTER(mbx)); + hw->mbx.fw_req =3D v & 0xffff; + hw->mbx.fw_ack =3D (v >> 16) & 0xffff; + mbx_wr32(hw, PF2FW_MBOX_CTRL(mbx), 0); + + for (idx =3D 0; idx < hw->max_vfs; idx++) { + mbx_wr32(hw, VF2PF_MBOX_VEC(mbx, idx), + nr_vec); + /* vf to pf req interrupt */ + } + + 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), 0xffff0000); + } else { + if (PF_VF_MBOX_MASK_LO(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_LO(mbx), + 0xffffffff); + /* disable irq */ + if (PF_VF_MBOX_MASK_HI(mbx)) + mbx_wr32(hw, PF_VF_MBOX_MASK_HI(mbx), + 0xffffffff); + + /* 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); + } + return 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 s32 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); + return 0; +} + +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..05231c76718e --- /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" +#define MUCSE_ERR_MBX -100 +/* 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_CTRL_PF_HOLD_SHM (BIT(3)) /* VF:RO, PF:WR */ +#define MBOX_IRQ_EN 0 +#define MBOX_IRQ_DISABLE 1 +#define mbx_rd32(hw, reg) rnpgbe_rd_reg((hw)->hw_addr + (reg)) +#define mbx_wr32(hw, reg, val) rnpgbe_wr_reg((hw)->hw_addr + (reg), (val)) + +extern struct mucse_mbx_operations mucse_mbx_ops_generic; + +s32 mucse_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id); +s32 mucse_write_mbx(struct mucse_hw *hw, u32 *msg, u16 size, + enum MBX_ID mbx_id); +s32 mucse_check_for_msg(struct mucse_hw *hw, enum MBX_ID mbx_id); +s32 mucse_check_for_ack(struct mucse_hw *hw, enum MBX_ID mbx_id); +#endif /* _RNPGBE_MBX_H */ --=20 2.25.1 From nobody Wed Oct 8 02:02:21 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 A5BA1372; Thu, 3 Jul 2025 01:51:03 +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=1751507468; cv=none; b=iZSz3lY2y7gBLCjKZPXTcZBK5yqdZR8ngyL60AsUHE0+ZKPTga6MJ/Cj5f6NVUI/IaZKpHn5QQj2VfqZ5UovpV/UQuuyGV/JKAb6Rkcw3aRO4c3zzX9PEnYuKtBN8PV8cI+jepCpeatc/roD8+Rr3Vejp6wZHU5UuWeiJ6bZC/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507468; c=relaxed/simple; bh=+FuXJwO2gVvDCxf9FsIgdSTN9qW1omMF2pI9Vn3CV+4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=keepBLPjxjMx599tvQ+hmkPy83Ot3WK5QZh/piqxITjA4ivR6rp1ph4LM5wqibhPmQIQIVu/CyTPKJ97oLbV5X/INeRtbWvH+6jZA5bEXteEUaaZZcWHctyJnr5rHkX17YPrRXHajlonIaxL0tr6DCuXE6zFd1XRStP01y9zxtk= 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: zesmtpsz8t1751507375t4f3b0fbd X-QQ-Originating-IP: 8BsPzddpkEccYH8mZsA/G+DyULy2beM/J8NvWAM62Zc= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:32 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 16203619772304485558 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 04/15] net: rnpgbe: Add get_capability mbx_fw ops support Date: Thu, 3 Jul 2025 09:48:48 +0800 Message-Id: <20250703014859.210110-5-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MHAMmLg4tmnVK7zscIPptvxXL+Xq9dN6j6UOs7k92mIwyxKcBFDy9DUz nOi/g2wudijUNA5u1dU2k6n9jlkSLPRDTaP3n+iARXWLGKumPtrMnGZDkNJy1FjwAtnnfrQ hjSaqQCt8CUxpdJwQYcy2uvVuPHFpA/LnvBa7BYoNVczp5HIVEea+3+pN2TnZub5HY/CHcN jZBKvTPCCIZF4axRoMndd/uKG9tY5lf+oEcPbwE1dhH9Nx878nfCMvD7+5L53FHe0gkVTX6 xShw+8rJVdDqK7WA+vA3OyDwaxwZvs2TEkvKNSraWWKwijePsVOqXFCgMJBXzMYZJlxthpS +pb0Z/wsMA58HHNOe9YTfcFK/p99Oh8y3x466FHcr8SgtAv3OOY4gQ0MDm11WoSkviXTIiV wwhngzHuRPRE+jbwxYk+xB20lBZxMHfAqYNIB5JejPxMhlfyfZwuLW8gshvi/5VanZ9INUr GlRwJAtdZzihFOOHyHJNvAVHg9e4Ve6Sj7RVqOuDXK5Yv6dP1udhX4azir+YNDcs1fusNk5 Furr1NkKeBq6/wwmw3BGYqgza5JjYg30CbymmoXSbwPPsf6XK9XvTQ4caJxE/qC28qqa881 mx313Os3MV23THp/gxL3nwMYQXDb1Rk0gQ5yQCWtAaOvJVdfrTV9wYaYcOtkFOn4rOfswjB YcPcF1tPo119Tp7niBE9FwF3P3K8xTSWY+Nk8hbnVFTwkX86ch7Lalw8+azw2lusGJB+sLM FXsSIWecj/aqG/khuPCrVc1X4mr3OWf31ZpWTdPpQG+rk4kkvVS426HE0bV3iSGm1mNvO2t 5fwxf6KfPGfgEl79AYush6zZr5kg8dAy5FlaOY4vD/C3H2LtNokk7Oa5ROtQ3EHPAtRbTGQ reYjfi3+kuWjBduG+vNowdnrJgzZDgX17lyDjbf79XXKxyMqlg3RS/NGawTtlTdZPQGB+VR G85IS3uk1dgY2UcKcS5Lynl+ZsVnKzpP+cv9v0EM/0PWp2wdtMhwyL9rC5maAMFXPy+2o+y ZFpPurccFn2d+mMe4PSZMMnpHuAIg= X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= 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.h | 3 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 141 +++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 530 ++++++++++++++++++ 6 files changed, 691 insertions(+), 2 deletions(-) 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 4cafab16f5bf..fd1610318c75 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -155,6 +155,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 e125b609ba09..b701b42b7c42 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 char rnpgbe_driver_string[] =3D @@ -137,6 +138,13 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, ii->get_invariants(hw); hw->mbx.ops.init_params(hw); =20 + if (mucse_mbx_get_capability(hw)) { + dev_err(&pdev->dev, + "mucse_mbx_get_capability failed!\n"); + err =3D -EIO; + goto err_free_net; + } + return 0; =20 err_free_net: diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_mbx.h index 05231c76718e..2040b86f4cad 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2020 - 2025 Mucse Corporation. */ +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ =20 #ifndef _RNPGBE_MBX_H #define _RNPGBE_MBX_H @@ -36,6 +36,7 @@ static inline u32 PF_VF_SHM(struct mucse_mbx_info *mbx, i= nt vf) #define MBOX_IRQ_DISABLE 1 #define mbx_rd32(hw, reg) rnpgbe_rd_reg((hw)->hw_addr + (reg)) #define mbx_wr32(hw, reg, val) rnpgbe_wr_reg((hw)->hw_addr + (reg), (val)) +#define hw_wr32(hw, reg, val) rnpgbe_wr_reg((hw)->hw_addr + (reg), (val)) =20 extern struct mucse_mbx_operations mucse_mbx_ops_generic; =20 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..7fdfccdba80b --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -0,0 +1,141 @@ +// 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-cm3 mailbox and wait + * reply from fw. + * + * Returns 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 err; + int retry_cnt =3D 3; + + if (!hw || !req || !reply || !hw->mbx.ops.read_posted) + return -EINVAL; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)req, + L_WD(req->datalen + MBX_REQ_HDR_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 -reply->error_code; + + return 0; +} + +/** + * mucse_fw_get_capablity - Get hw abilities from fw + * @hw: Pointer to the HW structure + * @abil: Pointer to the hw_abilities structure + * + * mucse_fw_get_capablity tries to get hw abilities from + * hw. + * + * Returns 0 on success, negative on failure + **/ +static int mucse_fw_get_capablity(struct mucse_hw *hw, + struct hw_abilities *abil) +{ + int err =3D 0; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + 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. + * + * Returns 0 on success, negative on failure + **/ +int mucse_mbx_get_capability(struct mucse_hw *hw) +{ + int err =3D 0; + struct hw_abilities ablity; + int try_cnt =3D 3; + + memset(&ablity, 0, sizeof(ablity)); + + while (try_cnt--) { + err =3D mucse_fw_get_capablity(hw, &ablity); + if (err =3D=3D 0) { + hw->ncsi_en =3D (ablity.nic_mode & 0x4) ? 1 : 0; + hw->pfvfnum =3D ablity.pfnum; + hw->fw_version =3D ablity.fw_version; + hw->axi_mhz =3D ablity.axi_mhz; + hw->bd_uid =3D ablity.bd_uid; + + if (hw->fw_version >=3D 0x0001012C) { + /* this version can get wol_en from hw */ + hw->wol =3D ablity.wol_status & 0xff; + hw->wol_en =3D ablity.wol_status & 0x100; + } else { + /* other version only pf0 or ncsi can wol */ + hw->wol =3D ablity.wol_status & 0xff; + if (hw->ncsi_en || !ablity.pfnum) + hw->wol_en =3D 1; + } + /* 0.1.5.0 can get force status from fw */ + if (hw->fw_version >=3D 0x00010500) { + hw->force_en =3D ablity.e.force_down_en; + hw->force_cap =3D 1; + } + return 0; + } + } + + return -EIO; +} 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..c5f2c3ff4068 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -0,0 +1,530 @@ +/* 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[64]; +}; + +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; + int speed; + u16 phy_type; + u16 nic_mode; + u16 pfnum; + u32 fw_version; + u32 axi_mhz; + union { + u8 port_id[4]; + u32 port_ids; + }; + u32 bd_uid; + int phy_id; + int wol_status; + union { + int ext_ablity; + 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_ablity : 1; /* 12 */ + u32 lldp_enabled : 1; /* 13 */ + u32 only_1g : 1; /* 14 */ + u32 force_down_en: 1; + } e; + }; +} __packed; + +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; + u16 linkup : 1; + u16 duplex : 1; + u16 autoneg : 1; + u16 fec : 1; + u16 an : 1; + u16 link_traing : 1; + u16 media_availble : 1; + u16 is_sgmii : 1; + u16 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) + u16 is_backplane : 1; + u16 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; + u32 speed; + u32 si_main; + u32 si_pre; + u32 si_post; + u32 si_tx_boost; + u32 supported_link; + u32 phy_id; + u32 advertised_link; +} __packed; + +struct yt_phy_statistics { + u32 pkg_ib_valid; /* rx crc good and length 64-1518 */ + u32 pkg_ib_os_good; /* rx crc good and length >1518 */ + u32 pkg_ib_us_good; /* rx crc good and length <64 */ + u16 pkg_ib_err; /* rx crc wrong and length 64-1518 */ + u16 pkg_ib_os_bad; /* rx crc wrong and length >1518 */ + u16 pkg_ib_frag; /* rx crc wrong and length <64 */ + u16 pkg_ib_nosfd; /* rx sfd missed */ + u32 pkg_ob_valid; /* tx crc good and length 64-1518 */ + u32 pkg_ob_os_good; /* tx crc good and length >1518 */ + u32 pkg_ob_us_good; /* tx crc good and length <64 */ + u16 pkg_ob_err; /* tx crc wrong and length 64-1518 */ + u16 pkg_ob_os_bad; /* tx crc wrong and length >1518 */ + u16 pkg_ob_frag; /* tx crc wrong and length <64 */ + u16 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; + u16 speed; + u16 pause : 4; + u16 local_eee : 3; + u16 partner_eee : 3; + u16 tp_mdx : 2; + u16 lldp_status : 1; + u16 revs : 3; +} __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 { + u16 flags; /* 0-1 */ + u16 opcode; /* 2-3 enum GENERIC_CMD */ + u16 datalen; /* 4-5 */ + u16 ret_value; /* 6-7 */ + union { + struct { + u32 cookie_lo; /* 8-11 */ + u32 cookie_hi; /* 12-15 */ + }; + + void *cookie; + }; + u32 reply_lo; /* 16-19 5dw */ + u32 reply_hi; /* 20-23 */ + union { + u8 data[32]; + struct { + u32 addr; + u32 bytes; + } r_reg; + + struct { + u32 addr; + u32 bytes; + u32 data[4]; + } w_reg; + + struct { + u32 lanes; + } ptp; + + struct { + u32 lane; + u32 up; + } ifup; + + struct { + u32 sec; + u32 nanosec; + + } tstamps; + + struct { + u32 lane; + u32 status; + } ifinsmod; + + struct { + u32 lane; + u32 status; + } ifforce; + + struct { + u32 lane; + u32 status; + } ifsuspuse; + + struct { + int nr_lane; + } get_lane_st; + + struct { + int nr_lane; + u32 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 + u32 value0; + u32 value1; + u32 value2; + u32 value3; + } set_lane_fun; + + struct { + u32 flag; + int nr_lane; + } set_dump; + + struct { + u32 lane; + u32 enable; + } wol; + + struct { + u32 lane; + u32 mode; + } gephy_test; + + struct { + u32 lane; + u32 op; + u32 enable; + u32 inteval; + } lldp_tx; + + struct { + u32 bytes; + int nr_lane; + u32 bin_offset; + u32 no_use; + } get_dump; + + struct { + int nr_lane; + u32 value; +#define LED_IDENTIFY_INACTIVE 0 +#define LED_IDENTIFY_ACTIVE 1 +#define LED_IDENTIFY_ON 2 +#define LED_IDENTIFY_OFF 3 + } led_set; + + struct { + u32 addr; + u32 data; + u32 mask; + } modify_reg; + + struct { + u32 adv_speed_mask; + u32 autoneg; + u32 speed; + u32 duplex; + int nr_lane; + u32 tp_mdix_ctrl; + } phy_link_set; + + struct { + u32 pause_mode; + int nr_lane; + } phy_pause_set; + + struct { + u32 pause_mode; + int nr_lane; + } phy_pause_get; + + struct { + u32 local_eee; + u32 tx_lpi_timer; + int nr_lane; + } phy_eee_set; + + struct { + int nr_lane; + u32 sfp_adr; /* 0xa0 or 0xa2 */ + u32 reg; + u32 cnt; + } sfp_read; + + struct { + int nr_lane; + u32 sfp_adr; /* 0xa0 or 0xa2 */ + u32 reg; + u32 val; + } sfp_write; + + struct { + int nr_lane; /* 0-3 */ + } get_linkstat; + + struct { + u16 changed_lanes; + u16 lane_status; + u32 port_st_magic; +#define SPEED_VALID_MAGIC 0xa4a6a8a9 + struct port_stat st[4]; + } link_stat; /* FW->RC */ + + struct { + u16 enable_stat; + u16 event_mask; + } stat_event_mask; + + struct { + u32 cmd; + u32 arg0; + u32 req_bytes; + u32 reply_bytes; + u32 ddr_lo; + u32 ddr_hi; + } maintain; + + struct { /* set phy register */ + u8 phy_interface; + union { + u8 page_num; + u8 external_phy_addr; + }; + u32 phy_reg_addr; + u32 phy_w_data; + u32 reg_addr; + u32 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 { + int lane_mask; + u32 pfvf_num; + } get_mac_addr; + + struct { + u8 phy_interface; + union { + u8 page_num; + u8 external_phy_addr; + }; + int phy_reg_addr; + u8 nr_lane; + } get_phy_reg; + + struct { + int nr_lane; + } phy_statistics; + + struct { + u8 paration; + u32 bytes; + u32 bin_phy_lo; + u32 bin_phy_hi; + } fw_update; + }; +} __packed; + +#define EEE_1000BT BIT(2) +#define EEE_100BT BIT(1) + +struct rnpgbe_eee_cap { + u32 local_capability; + u32 local_eee; + u32 partner_eee; +}; + +/* firmware -> driver */ +struct mbx_fw_cmd_reply { + /* fw must set: DD, CMP, Error(if error), copy value */ + u16 flags; + /* from command: LB,RD,VFC,BUF,SI,EI,FE */ + u16 opcode; /* 2-3: copy from req */ + u16 error_code; /* 4-5: 0 if no error */ + u16 datalen; /* 6-7: */ + union { + struct { + u32 cookie_lo; /* 8-11: */ + u32 cookie_hi; /* 12-15: */ + }; + void *cookie; + }; + /* =3D=3D=3D=3D=3D data =3D=3D=3D=3D [16-64] */ + union { + u8 data[40]; + + struct version { + u32 major; + u32 sub; + u32 modify; + } version; + + struct { + u32 value[4]; + } r_reg; + + struct { + u32 new_value; + } modify_reg; + + struct get_temp { + int temp; + int volatage; + } get_temp; + + struct { +#define MBX_SFP_READ_MAX_CNT 32 + u8 value[MBX_SFP_READ_MAX_CNT]; + } sfp_read; + + struct mac_addr { + int 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 { + u32 flags; + u32 version; + u32 bytes; + u32 data[4]; + } get_dump; + + struct get_lldp_reply { + u32 value; + u32 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 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 Wed Oct 8 02:02:21 2025 Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) (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 0EF6F1D5175; Thu, 3 Jul 2025 01:51:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.254.200.128 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507471; cv=none; b=Uq4sH2xzn+PtrxdH4l1FYqvq8l92qnL+QZoQF47iYDoCTccNWMqrpxV6B7KsisBzD5Ghov2vWDFUCnsc3rq/6+TUlzblXmA7nnkm9CZ79qt8JV7xY9b1f5DtPjASbXse+vKGz4olvaIdkrClM5yhrUnTDN3VIvfwfjWDWN92oU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507471; c=relaxed/simple; bh=Vn+aA7uPhGzMdjU385zXjKNP1FA9dT5ECEnJIeOVM08=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jQQCfcBM2zg62Pk1WJ1wbqYqzaSVPnHFBFGxxW+i/Ko39cELwWzjOZ0//H2+dhXfHB0YMzgo2lofglwOJYWd7FCOAnX1FrM/ldSOim8RmMuF3tKoKdOuPkXu4ZvhcWbkyt7EMunEIhQT6OLMkCg9Q5If+FvSo1xjaPyy3lBhJRs= 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.128 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: zesmtpsz8t1751507378t1fabd4f1 X-QQ-Originating-IP: 0ZGAHRp1K9Aluz8ij7tIazDn5ZoBGaxkXRJ8PGc30Uw= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:36 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 4960571315379612490 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 05/15] net: rnpgbe: Add download firmware for n210 chip Date: Thu, 3 Jul 2025 09:48:49 +0800 Message-Id: <20250703014859.210110-6-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NzcdIqQ5dcY0nOgHeeTq3Z/+8MxVweIyQlCXr4X0KGGNlrY3N1yyt1UR oP3aaLBcHnmRhL+CxLqvAhp5SeeOs5bdL6jroclxRrlewGw0Ffev4ggHhTGvErHIPsduEtd ng8SreziFsmywh0KZ4OivfcEGzQUSJ4ofjldIk0ZBHJRR2f9f/dCKjaTeeo3YsNTvVVpW5T TWz7W5evYjaiaXP3gi/gZu8VCVeAFt6vPZY07KRLvbpOwnBTTTqVXBNH1VPRblxQ6FCB+oK Cd1EuLEISGXrpDqPYTxZuNNeW8dpPXoof+iIeWGzvxZVg/eMcd3hTb5Jadq/G/ljJWeIAyI 3ol9SIT8wT3jYdO87fi4zLHRfSfnm4BkfHgcMU6Hwa5liKS57FQAZXiuaoSe7l2wV46g+p+ 2Rwg7OnMwmp/WSshPIGWPhgHktn1YQ2H8j6dOH1JOFh4g0+VEyjtLNoKIlVQ2SSMK581rj7 QVwfyGgvxWL8KHNFoaC0BwTOmxFksG4KRswkNePPva5GSFto3BAzn+dnEHahkdlr2Xh6yPh sRzkT0TyVBe7s158d0af5H7Lv6TzgKncSfJ/O77sFN4dxln/G/47r9obdL25IwtGK/ogAFF lp3BgUGmPr8zvEFyJo+jB3rREwaUGTTpQw89ealhNrm3l7tHoF4VAr0FR/zGHMQIa8PQkfy xDhB+tBzaUwRFE3c4xf0QwwfFktjJn1MZeQBSeUXb+hu6wPERq2F8g0E2Ou1mSa1VLwsTb0 /VyYqzYErDht9Ys0yj/Yb4x8cDp3n09akSQ79vKjU+51Fdzyqu69sM8fjspovmaggnRP5C+ 920zLX5CYXBZa790pF5Ymb0v8qAOrsvugKUaUWWn8A1YmP11gvRIfri5UFAom7XmygqY43h 4B0r2VO99wxS9LYPzK0ebTf8eCik8CXL0BABpevz93ugq08zUVwE5Abdky9wrmzJLoLk44z qAQqyJwClNKGnK9QlL75+wECSqiDInkXSl1KmoP3f6jgi+P+C6RB75BjQ 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/rnpgbe/Makefile | 3 +- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 3 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 94 ++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c | 236 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_sfc.h | 30 +++ 5 files changed, 364 insertions(+), 2 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/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 fd1610318c75..4e07d39d55ba 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -21,6 +21,7 @@ enum rnpgbe_hw_type { rnpgbe_hw_n500 =3D 0, rnpgbe_hw_n210, rnpgbe_hw_n210L, + rnpgbe_hw_unknow, }; =20 struct mucse_dma_info { @@ -199,6 +200,8 @@ struct mucse { struct mucse_hw hw; /* board number */ u16 bd_number; + u32 flags2; +#define M_FLAG2_NO_NET_REG ((u32)(1 << 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 b701b42b7c42..a7b8eb53cd69 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 char rnpgbe_driver_string[] =3D @@ -42,6 +44,56 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +/** + * rnpgbe_check_fw_from_flash - Check chip-id and bin-id + * @hw: hardware structure + * @data: data from bin files + * + * rnpgbe_check_fw_from_flash tries to match chip-id and bin-id + * + * + * Returns 0 on mactch, negative on failure + **/ +static int rnpgbe_check_fw_from_flash(struct mucse_hw *hw, const u8 *data) +{ + u32 device_id; + int ret =3D 0; + u32 chip_data; + enum rnpgbe_hw_type hw_type =3D rnpgbe_hw_unknow; +#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) + /* we should get hw_type from sfc-flash */ + chip_data =3D ioread32(hw->hw_addr + CHIP_OFFSET); + if (chip_data =3D=3D 0x11111111) + 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 -1; + break; + case rnpgbe_hw_n210L: + if (device_id !=3D 0x820a) + ret =3D -1; + break; + default: + ret =3D -1; + } + + return ret; +} + /** * init_firmware_for_n210 - download firmware * @hw: hardware structure @@ -53,7 +105,46 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { **/ static int init_firmware_for_n210(struct mucse_hw *hw) { - return 0; + char *filename =3D "n210_driver_update.bin"; + const struct firmware *fw; + struct pci_dev *pdev =3D hw->pdev; + int rc =3D 0; + int err =3D 0; + struct mucse *mucse =3D (struct mucse *)hw->back; + + rc =3D request_firmware(&fw, filename, &pdev->dev); + + if (rc !=3D 0) { + dev_err(&pdev->dev, "requesting firmware file failed\n"); + return rc; + } + + if (rnpgbe_check_fw_from_flash(hw, fw->data)) { + dev_info(&pdev->dev, "firmware type error\n"); + release_firmware(fw); + return -EIO; + } + /* first protect off */ + mucse_sfc_write_protect(hw); + 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; + } + dev_info(&pdev->dev, "init firmware successfully."); + dev_info(&pdev->dev, "Please reboot."); + +out: + release_firmware(fw); + mucse->flags2 |=3D M_FLAG2_NO_NET_REG; + + return err; } =20 /** @@ -97,6 +188,7 @@ static int rnpgbe_add_adpater(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: 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..8e0919f5d47e --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_sfc.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2022 - 2025 Mucse Corporation. */ + +#include + +#include "rnpgbe_sfc.h" +#include "rnpgbe.h" + +static inline void mucse_sfc_command(u8 __iomem *hw_addr, u32 cmd) +{ + iowrite32(cmd, (hw_addr + 0x8)); + iowrite32(1, (hw_addr + 0x0)); + while (ioread32(hw_addr) !=3D 0) + ; +} + +static inline void mucse_sfc_flash_write_disable(u8 __iomem *hw_addr) +{ + iowrite32(CMD_CYCLE(8), (hw_addr + 0x10)); + iowrite32(WR_DATA_CYCLE(0), (hw_addr + 0x14)); + + mucse_sfc_command(hw_addr, CMD_WRITE_DISABLE); +} + +static int32_t mucse_sfc_flash_wait_idle(u8 __iomem *hw_addr) +{ + int time =3D 0; + int ret =3D HAL_OK; + + iowrite32(CMD_CYCLE(8), (hw_addr + 0x10)); + iowrite32(RD_DATA_CYCLE(8), (hw_addr + 0x14)); + + while (1) { + mucse_sfc_command(hw_addr, CMD_READ_STATUS); + if ((ioread32(hw_addr + 0x4) & 0x1) =3D=3D 0) + break; + time++; + if (time > 1000) + ret =3D HAL_FAIL; + } + return ret; +} + +static inline void 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)); + + mucse_sfc_command(hw_addr, CMD_WRITE_ENABLE); +} + +static int mucse_sfc_flash_erase_sector(u8 __iomem *hw_addr, + u32 address) +{ + int ret =3D HAL_OK; + + if (address >=3D RSP_FLASH_HIGH_16M_OFFSET) + return HAL_EINVAL; + + if (address % 4096) + return HAL_EINVAL; + + mucse_sfc_flash_write_enable(hw_addr); + + 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)); + mucse_sfc_command(hw_addr, CMD_SECTOR_ERASE); + if (mucse_sfc_flash_wait_idle(hw_addr)) { + ret =3D HAL_FAIL; + goto failed; + } + mucse_sfc_flash_write_disable(hw_addr); + +failed: + return ret; +} + +void mucse_sfc_write_protect(struct mucse_hw *hw) +{ + mucse_sfc_flash_write_enable(hw->hw_addr); + + iowrite32(CMD_CYCLE(8), (hw->hw_addr + 0x10)); + iowrite32(WR_DATA_CYCLE(8), (hw->hw_addr + 0x14)); + iowrite32(0, (hw->hw_addr + 0x04)); + mucse_sfc_command(hw->hw_addr, CMD_WRITE_STATUS); +} + +/** + * mucse_sfc_flash_erase - Erase flash + * @hw: Hw structure + * @size: Data length + * + * mucse_sfc_flash_erase tries to erase sfc_flash + * + * Returns HAL_OK on success, negative on failure + **/ +int mucse_sfc_flash_erase(struct mucse_hw *hw, u32 size) +{ + u32 addr =3D SFC_MEM_BASE; + u32 i =3D 0; + u32 page_size =3D 0x1000; + + size =3D ((size + (page_size - 1)) / page_size) * page_size; + + addr =3D addr - SFC_MEM_BASE; + + if (size =3D=3D 0) + return HAL_EINVAL; + + if ((addr + size) > RSP_FLASH_HIGH_16M_OFFSET) + return HAL_EINVAL; + + if (addr % page_size) + return HAL_EINVAL; + + if (size % page_size) + return HAL_EINVAL; + /* skip some info */ + for (i =3D 0; i < size; i +=3D page_size) { + if (i >=3D 0x1f000 && i < 0x20000) + continue; + + mucse_sfc_flash_erase_sector(hw->hw_addr, (addr + i)); + } + + return HAL_OK; +} + +/** + * mucse_download_firmware - Download data to chip + * @hw: Hw structure + * @data: Data to use + * @file_size: Data length + * + * mucse_download_firmware tries to download data to white-chip + * by hw_addr regs. + * + * Returns 0 on success, negative on failure + **/ +int mucse_download_firmware(struct mucse_hw *hw, const u8 *data, + int file_size) +{ + struct device *dev =3D &hw->pdev->dev; + loff_t old_pos =3D 0; + loff_t pos =3D 0; + loff_t end_pos =3D file_size; + u32 rd_len =3D 0x1000; + int get_len =3D 0; + u32 iter =3D 0; + int err =3D 0; + u32 fw_off =3D 0; + u32 old_data =3D 0; + u32 new_data =3D 0; + char *buf =3D kzalloc(0x1000, GFP_KERNEL); + + dev_info(dev, "initializing firmware, which will take some time."); + /* capy 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)); + } + dev_info(dev, "Checking for firmware. Wait a moment, please."); + /* 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; +} 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..9c381bcda960 --- /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 HAL_OK (0) +#define HAL_FAIL (-1) +#define HAL_EINVAL (-3) /* Invalid argument */ +#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) + +void mucse_sfc_write_protect(struct mucse_hw *hw); +int mucse_sfc_flash_erase(struct mucse_hw *hw, u32 size); +int mucse_download_firmware(struct mucse_hw *hw, const u8 *data, + int file_size); +#endif /* _RNPGBE_SFC_H */ --=20 2.25.1 From nobody Wed Oct 8 02:02:21 2025 Received: from smtpbg154.qq.com (smtpbg154.qq.com [15.184.224.54]) (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 9F0302206BE; Thu, 3 Jul 2025 01:51:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=15.184.224.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507481; cv=none; b=rKlVqg4CvZ27DFOsez0oM0mX0vEOmCdYsr3SimmpbXBE/Hylgbsjpt1A18LZJ8CnKMmzYgjhY2vEJwKINUJ7iLVrNqElI4AiMjwUQhTg72bDIl3Hup8zXp1yk6vmglMtA7ajEzxrni/gFarBFP9/j6e3XFxdwvMXc2ZhHJA3tfE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507481; c=relaxed/simple; bh=6nh/VQZP1yp5oaO0NBYX4L0oSdeEk8O7IH7gIRviAbA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Obh/LSxIqvT77wMK8JQMEbrmD6A0flbb3eScO7hv6jllMSxIojXXrOgHhwncRPUzMc7yc19sJaPg2syxn5lZkXDLLIQsTvsMPpjKOOASYq3HOxLgLfA8DfATw/IuE2GF6SoyX40X4tAV5kM3wF0WbuL7s7kNl3zKMNLCc0mCCc4= 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=15.184.224.54 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: zesmtpsz8t1751507382td1c89071 X-QQ-Originating-IP: xJeTsFil+XDuLv8iZYorRJWz8bl9sbrolKBgQiPhEQM= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:39 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 9439932055034713164 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 06/15] net: rnpgbe: Add some functions for hw->ops Date: Thu, 3 Jul 2025 09:48:50 +0800 Message-Id: <20250703014859.210110-7-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: N/18iCB8Aki/unHBuxg3fMIT/Vd2WPZCFwCIYECJOI+BYAzHpiA3/UfI /nVnI+5UWRU+hJwWZr7L/hlpDNiyk2pS6exYDbwotdFKAUa4bqisZlPmRYXAO2MIFtbaBP8 vfut+6ihA9radWBWguhXHyKqI2m80SiK/qRnavRKLuWwiJmTlRmPwK/iJWYhFZTqO69J+pV 2R7BbDjhAcFhtmNqZp67TA+ZlaadbC9V1dfLbfouc4Nz+xx9ypvI7lRKtzFPPVRfrOQsLzH tn765RjZeyZcepmK9mt0F9EVEpfXwzgoXkIsZnsvB02PQrXzeMDLavHlAekd00LLHktUQXs SXKKL9BE52MHLe+Ju8dR3X5qbqppG9Rhs64PPhHEf1WKBbYy8ZcFVgoGi6z2zOxnkRU1APZ c7JmYAFctp+edWudQAk7r2O/INmMLm5XYXpZTdrWH1Ohch3tBhiayfsHTdocjZZH0GJtGfZ 1iy9KHRG42TM+2F3FgTsjseVsglfByg6A3Pda0KpZS8CIPyu0rrjjtS9mXv1cW4Mk9O3UhO SOz5Cx/y6sBflhZ5s9cmpyFfMEe5ouvO42PyPP/1EbANT5q9k0ew5SnAqytI5FSxASZ1mXr NLCeDFc8oXNy8OQ52cQGaL7qm4662gS5qm9WmrOoz8t52fU2an/+/0Osna2tGzZ4jnMGD0S 74vUtshPswjjTULF6pjBwV4KrTH3LDPnjC8hnjv4Ujt3RRwSUQjBi5S+1CfddhFHk364Lx9 oteReGVwTQWaYIyhhvD/mZ9YR/HCMf4RQr+KZ3NiIePA2DCWdblBWW9ChhhbRd8AjgbTx7t vqo9ttBevYh/J/mXgqlekXHU8p/I531PqiMyNFlWYXybMrBhA4hFXBAxBpUZ0nCpkRsi8Lf /NBYwjDJavMzIz1b2B/o1kRpwsPTTIGq5HeYb4Hce0TYyIaRJrGa6aFxPHd73tLxBm4Pjzf OXGRGLZuk0uIz0zgtot2RLdHVjwNRjJeOAaN1+3C2MTFScvnM0Hzt6ry0Qpv9QZK/TnXYrd mrqMJMfdhmzKUjPGTrJcrHtpTvdmA= X-QQ-XMRINFO: NS+P29fieYNw95Bth2bWPxk= 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 | 39 +++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 90 ++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 15 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 27 ++- .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h | 5 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 209 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 76 ++++++- 7 files changed, 452 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 4e07d39d55ba..17297f9ff9c1 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -145,6 +145,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; @@ -167,6 +186,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; @@ -191,7 +211,11 @@ struct mucse_hw { #define M_HW_FEATURE_EEE ((u32)(1 << 17)) #define M_HW_SOFT_MASK_OTHER_IRQ ((u32)(1 << 18)) u32 feature_flags; + u32 driver_version; u16 usecstocount; + int nr_lane; + struct lldp_status lldp_status; + int link; }; =20 struct mucse { @@ -223,7 +247,18 @@ struct rnpgbe_info { #define PCI_DEVICE_ID_N210 0x8208 #define PCI_DEVICE_ID_N210L 0x820a =20 -#define rnpgbe_rd_reg(reg) readl((void *)(reg)) -#define rnpgbe_wr_reg(reg, val) writel((val), (void *)(reg)) +#define m_rd_reg(reg) readl((void *)(reg)) +#define m_wr_reg(reg, val) writel((val), (void *)(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 08d082fa3066..c495a6f79fd0 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -7,6 +7,94 @@ #include "rnpgbe.h" #include "rnpgbe_hw.h" #include "rnpgbe_mbx.h" +#include "rnpgbe_mbx_fw.h" + +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. + * + **/ +static int rnpgbe_reset_hw_ops_n500(struct mucse_hw *hw) +{ + int i; + struct mucse_dma_info *dma =3D &hw->dma; + struct mucse_eth_info *eth =3D &hw->eth; + /* Call adapter stop to dma */ + dma_wr32(dma, RNPGBE_DMA_AXI_EN, 0); + if (mucse_mbx_fw_reset_phy(hw)) + return -EIO; + + 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); +} + +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 @@ -80,7 +168,9 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *= hw) M_NET_FEATURE_STAG_FILTER | 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 static void rnpgbe_get_invariants_n210(struct mucse_hw *hw) 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 a7b8eb53cd69..e811e9624ead 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -17,6 +17,7 @@ char rnpgbe_driver_name[] =3D "rnpgbe"; static const char rnpgbe_driver_string[] =3D "mucse 1 Gigabit PCI Express Network Driver"; #define DRV_VERSION "1.0.0" +static u32 driver_version =3D 0x01000000; const char rnpgbe_driver_version[] =3D DRV_VERSION; static const char rnpgbe_copyright[] =3D "Copyright (c) 2020-2025 mucse Corporation."; @@ -147,6 +148,11 @@ static int init_firmware_for_n210(struct mucse_hw *hw) return err; } =20 +static int rnpgbe_sw_init(struct mucse *mucse) +{ + return 0; +} + /** * rnpgbe_add_adpater - add netdev for this pci_dev * @pdev: PCI device information structure @@ -202,7 +208,7 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, } =20 /* get dma version */ - dma_version =3D rnpgbe_rd_reg(hw_addr); + dma_version =3D m_rd_reg(hw_addr); break; case rnpgbe_hw_n210: case rnpgbe_hw_n210L: @@ -219,7 +225,7 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, } =20 /* get dma version */ - dma_version =3D rnpgbe_rd_reg(hw_addr); + dma_version =3D m_rd_reg(hw_addr); break; default: err =3D -EIO; @@ -227,8 +233,12 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, } hw->hw_addr =3D hw_addr; hw->dma.dma_version =3D dma_version; + hw->driver_version =3D driver_version; + 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 if (mucse_mbx_get_capability(hw)) { dev_err(&pdev->dev, @@ -237,6 +247,16 @@ static int rnpgbe_add_adpater(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: @@ -303,10 +323,13 @@ static int rnpgbe_probe(struct pci_dev *pdev, const s= truct pci_device_id *id) static void rnpgbe_rm_adpater(struct mucse *mucse) { struct net_device *netdev; + struct mucse_hw *hw =3D &mucse->hw; =20 netdev =3D mucse->netdev; pr_info("=3D remove rnpgbe:%s =3D\n", netdev->name); + hw->ops.driver_status(hw, false, mucse_driver_insmod); free_netdev(netdev); + mucse->netdev =3D NULL; pr_info("remove complete\n"); } =20 diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_mbx.h index 2040b86f4cad..fbb154051313 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h @@ -34,9 +34,8 @@ static inline u32 PF_VF_SHM(struct mucse_mbx_info *mbx, i= nt vf) #define MBOX_CTRL_PF_HOLD_SHM (BIT(3)) /* VF:RO, PF:WR */ #define MBOX_IRQ_EN 0 #define MBOX_IRQ_DISABLE 1 -#define mbx_rd32(hw, reg) rnpgbe_rd_reg((hw)->hw_addr + (reg)) -#define mbx_wr32(hw, reg, val) rnpgbe_wr_reg((hw)->hw_addr + (reg), (val)) -#define hw_wr32(hw, reg, val) rnpgbe_wr_reg((hw)->hw_addr + (reg), (val)) +#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)) =20 extern struct mucse_mbx_operations mucse_mbx_ops_generic; =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 7fdfccdba80b..8e26ffcabfda 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 /** @@ -139,3 +140,211 @@ int mucse_mbx_get_capability(struct mucse_hw *hw) =20 return -EIO; } + +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. + * + * Returns 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 err =3D 0; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + cookie->errcode =3D 0; + cookie->done =3D 0; + init_waitqueue_head(&cookie->wait); + + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + err =3D mucse_write_mbx(hw, (u32 *)req, + L_WD(req->datalen + MBX_REQ_HDR_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 { + wait_event_interruptible(cookie->wait, cookie->done =3D=3D 1); + } + + mutex_unlock(&hw->mbx.lock); + + if (cookie->errcode) + err =3D cookie->errcode; + + return err; +} + +int rnpgbe_mbx_lldp_get(struct mucse_hw *hw) +{ + int err; + struct mbx_req_cookie *cookie =3D NULL; + struct mbx_fw_cmd_reply reply; + struct mbx_fw_cmd_req req; + struct get_lldp_reply *get_lldp; + + 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.other_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 get_lldp->value; + hw->lldp_status.inteval =3D get_lldp->inteval; + } + + kfree(cookie); + + return err ? -err : 0; +} + +int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status) +{ + int err; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifinsmod(&req, hw->driver_version, status); + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + if (status) { + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD((req.datalen + MBX_REQ_HDR_LEN)), + MBX_FW); + } else { + err =3D hw->mbx.ops.write(hw, (u32 *)&req, + L_WD((req.datalen + MBX_REQ_HDR_LEN)), + MBX_FW); + } + + mutex_unlock(&hw->mbx.lock); + return err; +} + +int mucse_mbx_ifsuspuse(struct mucse_hw *hw, int status) +{ + int err; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifsuspuse(&req, hw->nr_lane, status); + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD((req.datalen + MBX_REQ_HDR_LEN)), + MBX_FW); + mutex_unlock(&hw->mbx.lock); + + return err; +} + +int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, int status) +{ + int err; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + build_ifforce(&req, hw->nr_lane, status); + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + err =3D hw->mbx.ops.write_posted(hw, (u32 *)&req, + L_WD((req.datalen + MBX_REQ_HDR_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. + * + * Returns 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.other_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 c5f2c3ff4068..66d8cd02bc0e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -25,7 +25,7 @@ struct mbx_req_cookie { wait_queue_head_t wait; int done; int priv_len; - char priv[64]; + char priv[]; }; =20 enum MUCSE_FW_CMD { @@ -525,6 +525,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 LLDP_TX_CTRL; + req->datalen =3D sizeof(req->lldp_tx); + req->cookie =3D cookie; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->lldp_tx.lane =3D nr_lane; + req->lldp_tx.op =3D 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 DRIVER_INSMOD; + req->datalen =3D sizeof(req->ifinsmod); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifinsmod.lane =3D nr_lane; + req->ifinsmod.status =3D 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 SYSTEM_SUSPUSE; + req->datalen =3D sizeof(req->ifsuspuse); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifinsmod.lane =3D nr_lane; + req->ifinsmod.status =3D 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 SYSTEM_FORCE; + req->datalen =3D sizeof(req->ifforce); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifforce.lane =3D nr_lane; + req->ifforce.status =3D status; +} + +static inline void build_reset_phy_req(struct mbx_fw_cmd_req *req, + void *cookie) +{ + req->flags =3D 0; + req->opcode =3D 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 Wed Oct 8 02:02:21 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 7E8CA22B586; Thu, 3 Jul 2025 01:51:19 +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=1751507484; cv=none; b=QWSOkeSmQrFvIBp5/a3Zixnhd2aPPSSMRDuvotC0rbCaszvc5lPkOaSXFq+mH8lVc3kB2MRJJKpClk9KsmSb/34Gg9tNbQH9RSvQ29vIIp5JNTmPzTZlr8OBy7PwPaWOlsUV61yOvgDvcOOCEsrqJ0RQeBJCBryYZwSceqqf59Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507484; c=relaxed/simple; bh=9g4GBw6m7mzqCB5Pyr6fGNrygVgMLUzguxIfCWh6rss=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=G1sSyVvrZFnRZk8hf9g7T5Dj+6n0k0256oroVk2LsNrgKzm0pfvOLkDp2EZjoSqj7VtQezFMHj3bbEztH+oCAFvEc8roZh9idWpgJQzw8oII9Y+ZhSB98u51mi6zD9ciiNZc2itMnPAcJJLlRoGtao5uk+7aTBAhXrP9otEdVBI= 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: zesmtpsz8t1751507385t818e014a X-QQ-Originating-IP: 7JeNi3AoQC3CFgZ0kdYBrgsn6pYpinF8HbBya7I4NxU= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:43 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13769363806065482046 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 07/15] net: rnpgbe: Add get mac from hw Date: Thu, 3 Jul 2025 09:48:51 +0800 Message-Id: <20250703014859.210110-8-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MIGBBOK2RQC4c3EnJqNhyc0JztNpSaKRIXZMkAyWlR47RR3/F5C+2NK9 0fSYF+Se9er+GulS5kf65VHbFL7sk2qCqln6c8Fa0FgDfIq9i3kFbCwcujZFiUCcKk10Opd Fyk7s1VOoTMHX9Cx+OudQ6dyOfOMyD1jdBlVVgDCD7HE3+NoV/fzuA9hOcBuHE8WP1F+m4K f5B6+8Hiyj5DYlMQ0Edw4jnifZFyRMR/4paGJtP6HQHTor1lR2GQkIDbLk+jYQwSsTjE/ZF m+uIgmH9+gx/swedeeclZY8fEFuUb7Sn/erNv73uE0doXzaLSRFr65M7VqvFTCRZ26ZsHcA zI/YsL7qtR7i8W+3x1BVObA0PgHPhKNyCWNw4wt+lo8r6WSZJEVRvDDa/5Q+VgFEtr5Bjhs dYoG3x0W+j1E4EKmDtEW8/4j93rCCE9YaA4XKbY8FRxaFK5hDVzf8TRQg9nhLDDFk5Uyp2l fOjHaE55NTpAEm0IjxZAD1KKXJQF3iuK1EwkaBEloL3pdShu1GH5nkMESERsu4LF4QSyVoo 3ZSQ46Uwhs4Yzwsqg0P1PRG+J627m5LdMTgpArp1EWh8KsgqmWxR8wMdUrvAw7GYlFJpBfj /v2Gs6pAkhg7AWeMYpIPOouOd3rCD7lFIAA7TR/HOLVcvTUZZyIow5jxO6FMP9ucEyZgXHm SMGUFUJQf6VB3aBO8fjo+KY0Wbpkg/iVMCJKwQA8nXxZM20hf57Jpu0x8WbiHPR2HASLo4H 5EXaz3Xu1bmNPxgtsvJHrQ4rH8HoNhv8XpZZ0qL9F/VtqJlOy8dLLMjjgzWRYL5BKT0Fkwc Mf5g0btlWVGtIHNaHgeHUZ8QPO3gYQfKiR9A/lkfXhGgRnER+UJH0HPgNHVqYFT2dEZt+tV nvAI2CebyR3RVTMBwDTCob3nM/MJ+OBaJnIyHshXHF2CaofVcSr2sVt+1WokR1u0IKpUPdB v+SZo7otFhyfIDxg+DDZUACqNhr3Om3tcJXv9o6xN6BT53SWBEmn0aZ2ZgL1KQySUIqqj6/ 8NhEJF2A== X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= 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 | 65 ++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 126 ++++++++++++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 9 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 30 +++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 63 +++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 17 +++ 6 files changed, 306 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 17297f9ff9c1..93c3e8f50a80 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -33,8 +33,18 @@ struct mucse_dma_info { u32 dma_version; }; =20 +struct mucse_eth_info; + +struct mucse_eth_operations { + s32 (*get_mac_addr)(struct mucse_eth_info *eth, u8 *addr); + s32 (*set_rar)(struct mucse_eth_info *eth, u32 index, u8 *addr); + s32 (*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]; @@ -61,8 +71,13 @@ struct mucse_mac_info { struct mii_regs mii; int phy_addr; int clk_csr; - u8 addr[ETH_ALEN]; - u8 perm_addr[ETH_ALEN]; +}; + +struct mucse_addr_filter_info { + u32 num_mc_addrs; + u32 rar_used_count; + u32 mta_in_use; + bool user_set_promisc; }; =20 struct mucse_hw; @@ -154,6 +169,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); }; @@ -177,6 +193,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; @@ -191,6 +211,7 @@ struct mucse_hw { struct mucse_eth_info eth; struct mucse_mac_info mac; struct mucse_mbx_info mbx; + struct mucse_addr_filter_info addr_ctrl; #define M_NET_FEATURE_SG ((u32)(1 << 0)) #define M_NET_FEATURE_TX_CHECKSUM ((u32)(1 << 1)) #define M_NET_FEATURE_RX_CHECKSUM ((u32)(1 << 2)) @@ -211,11 +232,27 @@ struct mucse_hw { #define M_HW_FEATURE_EEE ((u32)(1 << 17)) #define M_HW_SOFT_MASK_OTHER_IRQ ((u32)(1 << 18)) u32 feature_flags; + u32 flags; +#define M_FLAGS_INIT_MAC_ADDRESS ((u32)(1 << 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 +261,20 @@ struct mucse { struct mucse_hw hw; /* board number */ u16 bd_number; + u16 tx_work_limit; u32 flags2; #define M_FLAG2_NO_NET_REG ((u32)(1 << 0)) - + u32 priv_flags; +#define M_PRIV_FLAG_TX_COALESCE ((u32)(1 << 25)) +#define M_PRIV_FLAG_RX_COALESCE ((u32)(1 << 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 +295,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((void *)(reg)) #define m_wr_reg(reg, val) writel((val), (void *)(reg)) #define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) @@ -261,4 +318,6 @@ struct rnpgbe_info { #define mucse_dbg(mucse, fmt, arg...) \ dev_dbg(&(mucse)->pdev->dev, fmt, ##arg) =20 +/* error codes */ +#define MUCSE_ERR_INVALID_ARGUMENT (-1) #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index c495a6f79fd0..5b01ecd641f2 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -3,12 +3,88 @@ =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 + * + * Puts an ethernet address into a receive address register. + **/ +static s32 rnpgbe_eth_set_rar_n500(struct mucse_eth_info *eth, + u32 index, u8 *addr) +{ + u32 mcstctrl; + u32 rar_low, rar_high =3D 0; + u32 rar_entries =3D eth->num_rar_entries; + + /* Make sure we are using a valid rar index range */ + if (index >=3D rar_entries) + return MUCSE_ERR_INVALID_ARGUMENT; + + /* + * HW expects these in big endian so we reverse the byte + * order from network order (big endian) to little endian + */ + 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 + * + * Clears an ethernet address from a receive address register. + **/ +static s32 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 MUCSE_ERR_INVALID_ARGUMENT; + + eth_wr32(eth, RNPGBE_ETH_RAR_RL(index), 0); + eth_wr32(eth, RNPGBE_ETH_RAR_RH(index), 0); + + return 0; +} + +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 +}; + static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) { int status =3D 0; @@ -20,6 +96,19 @@ static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) return status; } =20 +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 @@ -37,7 +126,13 @@ static int rnpgbe_reset_hw_ops_n500(struct mucse_hw *hw) dma_wr32(dma, RNPGBE_DMA_AXI_EN, 0); if (mucse_mbx_fw_reset_phy(hw)) return -EIO; + /* 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); + } =20 + 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); @@ -89,10 +184,38 @@ static void rnpgbe_driver_status_hw_ops_n500(struct mu= cse_hw *hw, } } =20 +static void rnpgbe_init_rx_addrs_hw_ops_n500(struct mucse_hw *hw) +{ + struct mucse_eth_info *eth =3D &hw->eth; + u32 i; + u32 rar_entries =3D eth->num_rar_entries; + u32 v; + + /* 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 @@ -121,6 +244,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; @@ -170,6 +294,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 e811e9624ead..d99da9838e27 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -150,6 +150,27 @@ static int init_firmware_for_n210(struct mucse_hw *hw) =20 static int rnpgbe_sw_init(struct mucse *mucse) { + struct mucse_hw *hw =3D &mucse->hw; + struct pci_dev *pdev =3D mucse->pdev; + + 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 @@ -257,6 +278,15 @@ static int rnpgbe_add_adpater(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); + strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); + 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 8e26ffcabfda..a9c5caa764a0 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -348,3 +348,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. + * + * Returns 0 on success, negative on failure + **/ +int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum, + u8 *mac_addr, + int nr_lane) +{ + int err =3D 0; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + if (!mac_addr) + return -EINVAL; + + if (hw->mbx.other_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 66d8cd02bc0e..babdfc1f56f1 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -594,11 +594,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 GET_MAC_ADDRES; + req->datalen =3D 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 lane_mask; + req->get_mac_addr.pfvf_num =3D 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 Wed Oct 8 02:02:21 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 AFFEB15746F; Thu, 3 Jul 2025 01:51:00 +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=1751507465; cv=none; b=cIIbBA7u4giTvbmbeX/9mWyqy/iR7Yrqgwbph1PJlDmG0BRgC8TIBkmX+aA8Zan2IjXfprynhzRDw91ZwubqgEUMwtFfQCYFNMfb1pHJNFolq30o6/Mwe7IDwW6jmLIE8e6tKoqLE/qJDsh5XcOXlCXiH4nRcKJdJsXTo5kQVDY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507465; c=relaxed/simple; bh=dAKh3sy8U2m4jz7eGA6EANeYapH2VNM50Tyl/WurccQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WUdW01ZjgAo6s9HRA04Pgm9MUNeQXQrvwoM6EERwjMcO0QdUXJc/Ur1YnzhwOKC2SA7ojmmApSHu2zL5UnNp7cRU3ed9VTv0IoVSyK+l7aIeMBBobcnQV+4QbCSLpDfCmdOrlJfW0e2VXRj31H3jsY7KL6TMSCE4OcRAOO+/a5E= 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: zesmtpsz8t1751507389t87e1356e X-QQ-Originating-IP: WqNPlsAG6yqfJCbEaL7ZF4GVDSGKNCYuUNJCDi74CrA= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:46 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 790028881953019986 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 08/15] net: rnpgbe: Add irq support Date: Thu, 3 Jul 2025 09:48:52 +0800 Message-Id: <20250703014859.210110-9-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: N7IP8+eIyBrZoaQmRCvhXpmfkKEG6c2+taUvBb62RM5IwfB7iRu//x0F G+8yIFMgL9pQFwa5MurkDg9Se3cDzObcjMiu4oDBRjQKts8NsLxK2biGi0K8dQ+pSUhqCoe bl2Yu4y1uYRvWdvGydLxK4Td0GMMmGuZXpvTdH7elIkmvyvjjRInMFPxOPXoxw9IZHzDgKe uyJkFPTU88XtXoZF+RHig/G5vP1R+8OjaXdALu2bvJf7YmAD6HHv2nRpMMwbIyUoHhpfVIp iSPRA2cWJLEJJMP2FmZrAcWa1q1Ci5477lm+cL207Uafn/KAnc2rXd05vgZS5tpuSY+nckZ qGIAZ8k5uTlb6ez1PMgQwnV818LaeaUAY/C3XyH+8VUKa5tZDScmo8KyCpu1xGq7Nj+pWrQ c9m34VIVcA8s8HzgFa6ZYqDoOLMRuV0yuG96DugsdZQkNLmtW2mBArASn9VpalZSnWgaVY6 wgs0wTkAY382EjyzOnmlSLX0FypeXmFgtB3Cdm8sRaAvLxMgrIdjN1caqeEYHJXqadZgsCY U/BvbfVIehyvfy5Hl+jJQh/JDsPwiywCjAAR+XrCXTwKc9REmzvXRT5noLz4YNHV5c6GAnf YoQE3c9L5u+cnpSN3ximsYTpgGHs2I952vqt5xXQdJauPhX1vtw/qAL4WyjNw1Fjt7gFPpS P9sQ+JecnGtkqkcIqyDlTzgPfLnKHItiMff6NFVex/Aapoe2E4yj7wCyq6M0SfYvUicLBG8 Tg9akyXGSbBVUxcJeweIb1Su0uRKDGvV0zDsv0MplwR2sN1xKmWjcOrwni+vMlSskF/83o3 M755HIlijkofXJ7hFu6YV4i1jTxohAOA4otX1Hy+hwY9/w08Ve03aTls4goaLEX1BbcZUF3 Ef8wMz6rIbl65Il0h0qzElTxWrZ6ixcCiWrfew7zRI1Ur6mkzXArACr1cpnQxgpMr/7mSQ2 pdn8deqLuxG3DY8zPvQ5MUIREWQ4r01wqQI2M96eJCJxqOwFBh3/Fob109II1t3W9C2Q+nx tFRibtfAMz2KaccBRa X-QQ-XMRINFO: OWPUhxQsoeAVDbp3OJHYyFg= 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 | 156 +++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 462 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 26 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 129 ++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 6 +- 7 files changed, 777 insertions(+), 7 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 93c3e8f50a80..82df7f133f10 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; @@ -135,7 +136,7 @@ struct mucse_mbx_info { u16 fw_ack; /* lock for only one use mbx */ struct mutex lock; - bool other_irq_enabled; + bool irq_enabled; int mbx_size; int mbx_mem_size; #define MBX_FEATURE_NO_ZERO BIT(0) @@ -233,6 +234,7 @@ struct mucse_hw { #define M_HW_SOFT_MASK_OTHER_IRQ ((u32)(1 << 18)) u32 feature_flags; u32 flags; +#define M_FLAG_MSI_CAPABLE ((u32)(1 << 0)) #define M_FLAGS_INIT_MAC_ADDRESS ((u32)(1 << 27)) u32 driver_version; u16 usecstocount; @@ -255,6 +257,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 ((u32)(1 << 0)) +#define M_RING_FLAG_CHANGE_RX_LEN ((u32)(1 << 1)) +#define M_RING_FLAG_DO_RESET_RX_LEN ((u32)(1 << 2)) +#define M_RING_SKIP_TX_START ((u32)(1 << 3)) +#define M_RING_NO_TUNNEL_SUPPORT ((u32)(1 << 4)) +#define M_RING_SIZE_CHANGE_FIX ((u32)(1 << 5)) +#define M_RING_SCATER_SETUP ((u32)(1 << 6)) +#define M_RING_STAGS_SUPPORT ((u32)(1 << 7)) +#define M_RING_DOUBLE_VLAN_SUPPORT ((u32)(1 << 8)) +#define M_RING_VEB_MULTI_FIX ((u32)(1 << 9)) +#define M_RING_IRQ_MISS_FIX ((u32)(1 << 10)) +#define M_RING_OUTER_VLAN_FIX ((u32)(1 << 11)) +#define M_RING_CHKSM_FIX ((u32)(1 << 12)) +#define M_RING_LOWER_ITR ((u32)(1 << 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 ((u32)(1 << 0)) +#define M_QVECTOR_FLAG_ITR_FEATURE ((u32)(1 << 1)) +#define M_QVECTOR_FLAG_REDUCE_TX_IRQ_MISS ((u32)(1 << 2)) + char name[IFNAMSIZ + 9]; + /* 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; @@ -262,19 +394,37 @@ struct mucse { /* board number */ u16 bd_number; u16 tx_work_limit; + u32 flags; +#define M_FLAG_NEED_LINK_UPDATE ((u32)(1 << 0)) +#define M_FLAG_MSIX_ENABLED ((u32)(1 << 1)) +#define M_FLAG_MSI_ENABLED ((u32)(1 << 2)) u32 flags2; #define M_FLAG2_NO_NET_REG ((u32)(1 << 0)) +#define M_FLAG2_INSMOD ((u32)(1 << 1)) u32 priv_flags; #define M_PRIV_FLAG_TX_COALESCE ((u32)(1 << 25)) #define M_PRIV_FLAG_RX_COALESCE ((u32)(1 << 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,8 @@ struct rnpgbe_info { =20 /* error codes */ #define MUCSE_ERR_INVALID_ARGUMENT (-1) + +void rnpgbe_service_event_schedule(struct mucse *mucse); +int rnpgbe_poll(struct napi_struct *napi, int budget); + #endif /* _RNPGBE_H */ diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_chip.c index 5b01ecd641f2..e94a432dd7b6 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -296,6 +296,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..95c913212182 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -0,0 +1,462 @@ +// 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. + * + **/ +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); +} + +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 -EINVAL; + } + + 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. + **/ +static int rnpgbe_set_interrupt_capability(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + int vector, v_budget, err =3D 0; + int irq_mode_back =3D mucse->irq_mode; + + 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 -EINVAL; + + 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; +} + +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; + } +} + +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_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 + * + * We allocate one q_vector. 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) +{ + struct mucse_q_vector *q_vector; + struct mucse_ring *ring; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma =3D &hw->dma; + int node =3D NUMA_NO_NODE; + int cpu =3D -1; + int ring_count, size; + int txr_count, rxr_count, idx; + int rxr_idx =3D r_idx, txr_idx =3D r_idx; + int cpu_offset =3D 0; + + 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 + * + * We allocate one q_vector per tx/rx queue pair. If allocation fails we + * return -ENOMEM. + **/ +static int rnpgbe_alloc_q_vectors(struct mucse *mucse) +{ + int v_idx =3D mucse->q_vector_off; + int ring_idx =3D 0; + int r_remaing =3D min_t(int, mucse->num_tx_queues, + mucse->num_rx_queues); + int ring_step =3D 1; + int err, ring_cnt, v_remaing =3D mucse->num_q_vectors; + int q_vector_nums =3D 0; + int eth_queue_idx =3D 0; + + /* can support muti 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) +{ + int i; + /* setup here */ + int ring_step =3D 1; + struct mucse_ring *ring; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *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); +} + +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; + /* clean msix flags */ + 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) + **/ +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..ab55c5ae1482 --- /dev/null +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -0,0 +1,26 @@ +/* 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 (pos =3D (head).ring; pos; 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 d99da9838e27..bfe7b34be78e 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 char rnpgbe_driver_string[] =3D @@ -45,6 +46,51 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +static struct workqueue_struct *rnpgbe_wq; + +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) +{ +} + +int rnpgbe_poll(struct napi_struct *napi, int budget) +{ + return 0; +} + /** * rnpgbe_check_fw_from_flash - Check chip-id and bin-id * @hw: hardware structure @@ -169,11 +215,67 @@ 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 +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; + } + } +} + +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; +} + +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_adpater - add netdev for this pci_dev * @pdev: PCI device information structure @@ -260,7 +362,6 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, hw->mbx.ops.init_params(hw); /* echo fw driver insmod */ hw->ops.driver_status(hw, true, mucse_driver_insmod); - if (mucse_mbx_get_capability(hw)) { dev_err(&pdev->dev, "mucse_mbx_get_capability failed!\n"); @@ -286,9 +387,20 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, eth_hw_addr_set(netdev, hw->perm_addr); strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); 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; @@ -357,7 +469,11 @@ static void rnpgbe_rm_adpater(struct mucse *mucse) =20 netdev =3D mucse->netdev; pr_info("=3D remove rnpgbe:%s =3D\n", netdev->name); + 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; pr_info("remove complete\n"); @@ -391,6 +507,8 @@ static void __rnpgbe_shutdown(struct pci_dev *pdev, boo= l *enable_wake) =20 *enable_wake =3D false; netif_device_detach(netdev); + remove_mbx_irq(mucse); + rnpgbe_clear_interrupt_scheme(mucse); pci_disable_device(pdev); } =20 @@ -428,6 +546,12 @@ static int __init rnpgbe_init_module(void) pr_info("%s - version %s\n", rnpgbe_driver_string, rnpgbe_driver_version); pr_info("%s\n", rnpgbe_copyright); + 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; @@ -440,6 +564,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); diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index a9c5caa764a0..f86fb81f4db4 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -231,7 +231,7 @@ int rnpgbe_mbx_lldp_get(struct mucse_hw *hw) memset(&req, 0, sizeof(req)); memset(&reply, 0, sizeof(reply)); build_get_lldp_req(&req, cookie, hw->nr_lane); - if (hw->mbx.other_irq_enabled) { + 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); @@ -332,7 +332,7 @@ int mucse_mbx_fw_reset_phy(struct mucse_hw *hw) =20 memset(&req, 0, sizeof(req)); memset(&reply, 0, sizeof(reply)); - if (hw->mbx.other_irq_enabled) { + if (hw->mbx.irq_enabled) { struct mbx_req_cookie *cookie =3D mbx_cookie_zalloc(0); =20 if (!cookie) @@ -376,7 +376,7 @@ int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfn= um, if (!mac_addr) return -EINVAL; =20 - if (hw->mbx.other_irq_enabled) { + 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; --=20 2.25.1 From nobody Wed Oct 8 02:02:21 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 246E9219A9B; Thu, 3 Jul 2025 01:51:14 +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=1751507479; cv=none; b=RPxVSU1Pky6hMS+fZHzRCi+b3pFUKHa4qKsBXu12FO0oV9biO9ESOLsaTMrqv8hQ3O5j/KpgGmvzhU1RzJA757+Zcyso+WU8cLJz7fRrM/rygT7REt0T4VJgMIkSbEd5NI/HN/d5L56eqqsKAFtqIVLDoRpaj/aPDUvpuxlj90Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507479; c=relaxed/simple; bh=sNEQEnKuqE5ED2CNiceZlJzn+qdC9+MNHxfFb1fe/yQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pbKLr9Dpy+Ov9XV/sX2itlmK+axW3LP6ls3Tqo522x3pTKxL7Jy4pgEkA6AqmJZmRTRYxVEnVCm7OeuXhk4wUf6Htmh3VojYFcU9VSc/4b5j11mlLtvedqEjz/ZEgSlyIqEmjZGaMnaGYrSjehMIT7zBTpPEa+Mz8ikKjaj+sfo= 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: zesmtpsz8t1751507392t1dde0829 X-QQ-Originating-IP: UupTy+JW8obp2Fp4CFy/3t2/sY69ThsAUW9vldRuxBk= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:50 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 3269869034678843262 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 09/15] net: rnpgbe: Add netdev register and init tx/rx memory Date: Thu, 3 Jul 2025 09:48:53 +0800 Message-Id: <20250703014859.210110-10-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NWwUqlpH66YH7Ld0SX/SKKkbzkZlEZoNq4x2YGrGBaIOWru30/YAz2V8 eQT3MnEqBA0bEqZjVoN3wg5ks9jjaZf2+u67KLssZATZMYnr8lP6Lwb0eVRiUb3WkTda5rZ vKqSPW569RO8iMYVQNFQU+rqWUat0jHy2vB6ScDwwcQz6Jcc2+3EowwcZrKMkzlJ99Waa1u 954oZiGR3RKSRGoaarPb4/nwiPYYOazXt7Q5+ymVFjM2+eGUrzwc106pM9T6hf7/IKjgfLd Ks4bDCxzPfgTHYj+mEnQ8kGpnZlrPPO09IpJzR81OCnSJpqtlDGEpMcEBVOV8rXBvdgtxZ6 pOvZeCgIfTmWVNLflVIiy1oZ6RNsyJBwxnKIldC0rsNdLb/wuhHK97XUgVr/vimMb3pYh/m kI5jmuVC2V2jdArQrzuWgBZeARVk+S4rHtqVKt+gN/SLT002KR70xnrkdjg8+ijkrBcALbi Lh/YTPKJe7uOKtvb5MZJKLy+sVB6XMGrL0IOB2B7T1E1pX8wuhbblbIMH2t7s/DW7HxI0dO 0KVfVYUP/83hAEyo/V0fTauraNaeT8/ARJcxWOXa06Z6KfhqDNm6gh3UQmmYd7SnMwFCA6U 1UiCRZcqmlS+ziokmafSqFk3iOdUufrPPhBg+XhpAzl1UXE7uZMIujAVTpOOBdvYJNfW0Ci 17dOa9YVkdTsbQ3XwM3iM/itJCuzZzU3vCK9igZHMT2ofOqaO4gvFePyhZKeghzif2ru9E0 cRS3yiroqLq4LxjNDr0PeS07h7XMCzROZ05vgcOrt8gPjcCR4VNTKERKud15v5W7iaAmtQ3 r36ydNblG2lL25J+C0LqHxfdvYYiftIrrUUdiUyPZfcQr3/rDMH301CUePfL3oJfSf0n5kW Vn3zmyJGnsdNjWsn6vXuwNs2Zff/ZmGZTrb9qr5oaNHNaEpkiwiM5q6tCeVqOfhbt6tUasw zRVe4ji9KHWgmXtRKaCWcXfJuitOKpG9kD2wfNHc3IRW2t+z2dlwIUp/hB0tq1nNL6gV19z c0dKsXLsVviJOq4MeR X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= 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 | 145 +++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 358 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 2 + .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 84 +++- 4 files changed, 586 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 82df7f133f10..feb74048b9e0 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -247,6 +247,7 @@ struct mucse_hw { }; =20 enum mucse_state_t { + __MMUCSE_TESTING, __MUCSE_DOWN, __MUCSE_SERVICE_SCHED, __MUCSE_PTP_TX_IN_PROGRESS, @@ -306,6 +307,134 @@ 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 { + __le16 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; +#if (BITS_PER_LONG > 32) || (PAGE_SIZE >=3D 65536) + __u32 page_offset; +#else /* (BITS_PER_LONG > 32) || (PAGE_SIZE >=3D 65536) */ + __u16 page_offset; +#endif /* (BITS_PER_LONG > 32) || (PAGE_SIZE >=3D 65536) */ + __u16 pagecnt_bias; +}; + struct mucse_ring { struct mucse_ring *next; struct mucse_q_vector *q_vector; @@ -349,6 +478,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 { @@ -434,6 +564,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 95c913212182..0dbb942eb4c7 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 @@ -460,3 +462,359 @@ 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) +{ + unsigned long size; + u16 i =3D tx_ring->next_to_clean; + struct mucse_tx_buffer *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 + * + * Returns 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) +{ + u16 i =3D rx_ring->next_to_clean; + struct mucse_rx_buffer *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); + /* free resources associated with mapping */ + dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, + PAGE_SIZE, + DMA_FROM_DEVICE, + M_RX_DMA_ATTR); + __page_frag_cache_drain(rx_buffer->page, + rx_buffer->pagecnt_bias); + 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 + **/ +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 ab55c5ae1482..150d03f9ada9 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h @@ -22,5 +22,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 bfe7b34be78e..95a68b6d08a5 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" @@ -194,6 +195,67 @@ static int init_firmware_for_n210(struct mucse_hw *hw) return err; } =20 +/** + * rnpgbe_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). + **/ +static int rnpgbe_open(struct net_device *netdev) +{ + struct mucse *mucse =3D netdev_priv(netdev); + int err; + + /* disallow open during test */ + if (test_bit(__MMUCSE_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 + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. + **/ +static int rnpgbe_close(struct net_device *netdev) +{ + struct mucse *mucse =3D netdev_priv(netdev); + + rnpgbe_free_txrx(mucse); + + return 0; +} + +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, +}; + +static void rnpgbe_assign_netdev_ops(struct net_device *dev) +{ + dev->netdev_ops =3D &rnpgbe_netdev_ops; + dev->watchdog_timeo =3D 5 * HZ; +} + static int rnpgbe_sw_init(struct mucse *mucse) { struct mucse_hw *hw =3D &mucse->hw; @@ -368,7 +430,7 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, err =3D -EIO; goto err_free_net; } - + rnpgbe_assign_netdev_ops(netdev); err =3D rnpgbe_sw_init(mucse); if (err) goto err_free_net; @@ -384,8 +446,8 @@ static int rnpgbe_add_adpater(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); - strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); 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); @@ -394,11 +456,17 @@ static int rnpgbe_add_adpater(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: @@ -468,9 +536,15 @@ static void rnpgbe_rm_adpater(struct mucse *mucse) struct mucse_hw *hw =3D &mucse->hw; =20 netdev =3D mucse->netdev; + if (mucse->flags2 & M_FLAG2_NO_NET_REG) { + free_netdev(netdev); + return; + } pr_info("=3D remove rnpgbe:%s =3D\n", netdev->name); 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); @@ -507,6 +581,10 @@ static void __rnpgbe_shutdown(struct pci_dev *pdev, bo= ol *enable_wake) =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 Wed Oct 8 02:02:21 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 BBCA7226D00; Thu, 3 Jul 2025 01:51: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=1751507520; cv=none; b=Ab/+qoqDphhcs0acbXZIv1hICnOHAdRmh0rJxAAEIm2EAQF3MCF9dYG/sRzN2xcfW2IZ2WpNyR9iprOY8YKyt38jnFG5KmBg+hzwcSR7FHPwkgs86sX2gGME8JY1KPY/pFclfYIiObXkZY43Ld+/H0uET8zxoiadgiy4mExTjkY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507520; c=relaxed/simple; bh=t7l1xHJ2NhriGtQRpiQZC6zLgc52a8TsjZ5vYLMEsxY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cQOlPf+6ChJjmdUlNx0Z8piZ2ccIeqWKt/2zfTmB3Zi92iqxyK46s2tAtLbBQVlvrQPUVCQp6F5amn3q8Jd8UtmqE2n0nNyPsT5B4sEZvrRUkmaupZYfFC9jlLyUZbLRRJxEHsrb6b3y6/tnbW7QFNShiqEqEmkZinGdmIGlrwA= 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: zesmtpsz8t1751507396tbee45c33 X-QQ-Originating-IP: xUSpMF06R0P0r4wNtjiCkARXJ8NrWwSZ5ZtplOE6EPo= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:54 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13682066848690000920 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 10/15] net: rnpgbe: Add netdev irq in open Date: Thu, 3 Jul 2025 09:48:54 +0800 Message-Id: <20250703014859.210110-11-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: M87FkSnslKhoTCsVDeCn5GQcQLDpJJUAqc0Ob+x4idRPLZqZhl161j6G /GrJSuh51hw3ULDxAbAGtC21uNfMHiQkNQXb/gvXsg/dPRe3dZc94gFfgs+yMFvHK6dkGas 5MZSh1cgTYGihcD4WCPz2uXNN16MetsOGmKwaFWPHielLQPS08DVWpEQpfWXar4A8HxDPEb Vh+AQ1NmW0O8fXyNMly2ddvleREz+qIffnYsa6Nt72NkYW5klCT+ZT5l+oXBxZCtmf2SBoU Zk+oqGIWGLCjar35wI6vlKwf8SSDWR6PYQjnus1Yi6ZMcW8P1PKiq/oqk89i2ugAxLZhnkN w2cSzEQM/RcuSwmyYl2XtSH2R/37+EYePeBN8RmVZ5Cy/m1v51JEZEkqwJeQBWEg4wd6uT8 D/u+PqCUupr8TKyUx98U1RIn8VxhsBrpe0A2iZ2nJNlepaYLndb6+blMgb6Q46OYw/Qe2z0 YVt73fIJZ41ejvv6LoYdSjtDMlumAvO9N5lbsq0KX+a+0fDxocWyfd0sUvUL0qWkyD9xxQU RmoRU6PBiTOIvE5FI9++9R4qbdEpXLWBKppTxhjOORNaDCSu1EoHvswDepTPu6ZvKAMpZ7c hzmTQ22zF7POcjMNvpVocBbl0fQ7gVm/Q7qWXrhMwLCYAAowGOW2dY9s2CqDIZ0j2iJLdq+ HzCZO4D5afTgwX9enxLDvlYwwNuJrsCOq4KS2gD+6DpCbkOBdwkjCR/0Vy6HlpoDIQLDLR3 NZscFeQ1ZbHxj//RMea5OGMeQoodmc8Gm/LiVzwK1IHkCupb5PhoS9tSN53EeJ8UVs3ZhhY 4unG/NkRKCykZX3taI7MHEBchPqmpl8jzb/LlSBKpBdKEfq6YF/3HQlWS0hMlmAO4lsjD4h T42KMWONOawuhJaVxbA19Zhu+fnUIuGgcJC6vKPnfnBC9NpCmL8/MYfXJLsLyJpWLLUC6aU QoT3dmNEEMoA48th2BgRdL/oFG2lQQRmgkxcA3AHOqeMzmZlXMG4B4KajzZRg4wt6VTs7BK QHAzvinCDbCNSnafkE1ir6Kt/j2Os= 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 | 307 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 30 ++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 30 +- 6 files changed, 471 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index feb74048b9e0..d4e150c14582 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -66,7 +66,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; @@ -173,6 +180,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 { @@ -606,6 +616,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 e94a432dd7b6..5ad287e398a7 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -71,6 +71,12 @@ static s32 rnpgbe_eth_clear_rar_n500(struct mucse_eth_in= fo *eth, return 0; } =20 +/** + * rnpgbe_eth_clr_mc_addr_n500 - Clear multicast register + * @eth: pointer to eth structure + * + * Clears all multicast address register. + **/ static void rnpgbe_eth_clr_mc_addr_n500(struct mucse_eth_info *eth) { int i; @@ -85,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, +}; + static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) { int status =3D 0; @@ -211,12 +241,62 @@ 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); +} + +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 /** @@ -252,6 +332,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 0dbb942eb4c7..26fdac7d52a9 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -818,3 +818,310 @@ 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; + int timeout =3D 0; + 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); + do { + status =3D ring_rd32(ring, DMA_TX_READY); + usleep_range(100, 200); + timeout++; + } while ((status !=3D 1) && (timeout < 100)); + 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]); +} + +void rnpgbe_disable_rx_queue(struct mucse_ring *ring) +{ + ring_wr32(ring, DMA_RX_START, 0); +} + +#if (PAGE_SIZE < 8192) +static inline int rnpgbe_compute_pad(int rx_buf_len) +{ + int page_size, pad_size; + + page_size =3D ALIGN(rx_buf_len, PAGE_SIZE / 2); + pad_size =3D SKB_WITH_OVERHEAD(page_size) - rx_buf_len; + + return pad_size; +} + +static inline int rnpgbe_sg_size(void) +{ + int sg_size =3D SKB_WITH_OVERHEAD(PAGE_SIZE / 2) - NET_SKB_PAD; + + sg_size -=3D NET_IP_ALIGN; + sg_size =3D ALIGN_DOWN(sg_size, 4); + + return sg_size; +} + +#define SG_SIZE rnpgbe_sg_size() +static inline int rnpgbe_skb_pad(void) +{ + int rx_buf_len =3D SG_SIZE; + + return rnpgbe_compute_pad(rx_buf_len); +} + +#define RNP_SKB_PAD rnpgbe_skb_pad() +static inline unsigned int rnpgbe_rx_offset(void) +{ + return RNP_SKB_PAD; +} + +#else /* PAGE_SIZE < 8192 */ +#define RNP_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) +#endif + +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; + +#if (PAGE_SIZE < 8192) + split_size =3D SG_SIZE; + split_size =3D split_size >> 4; +#else + /* we use fixed sg size */ + split_size =3D 96; +#endif + 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 ,maybe should setup this */ + /* drop packets if no rx-desc in 100000 clks, maybe os crash */ + 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 8259x 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]); +} + +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 err; + int i =3D 0; + int q_off =3D mucse->q_vector_off; + struct msix_entry *entry; + + 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-%d", netdev->name, "TxRx", i, + q_vector->v_idx); + } 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; +} + +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) +{ + int err; + struct mucse_hw *hw =3D &mucse->hw; + + if (mucse->flags & M_FLAG_MSIX_ENABLED) { + pr_info("msix mode is used\n"); + 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 */ + pr_info("msi mode is used\n"); + 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 { + pr_info("legacy mode is used\n"); + 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. + **/ +static int rnpgbe_free_msix_irqs(struct mucse *mucse) +{ + int i; + int q_off =3D mucse->q_vector_off; + struct msix_entry *entry; + struct mucse_q_vector *q_vector; + + 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 150d03f9ada9..818bd0cabe0c 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 (pos =3D (head).ring; pos; pos =3D pos->next) @@ -24,5 +49,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 95a68b6d08a5..82acf45ad901 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -195,6 +195,16 @@ static int init_firmware_for_n210(struct mucse_hw *hw) return err; } =20 +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 @@ -215,7 +225,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 @@ -232,6 +255,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; @@ -582,8 +606,10 @@ static void __rnpgbe_shutdown(struct pci_dev *pdev, bo= ol *enable_wake) *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 Wed Oct 8 02:02:21 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 BBC47226533; Thu, 3 Jul 2025 01:51: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=1751507518; cv=none; b=o4/pxWqd/MuHMFQsoZNnNW2cmYwN6C7h9QSKXry6xhCptYWWvaESni/HeOrMya0TML0oG6I4/r/P8cG6iD0zePYo3+MNqyInK/Ei2hKtwqSlIi+zLiyZ3Ia1oMkbWjTWY+X0ZRgq3DtOZffe2r19KCKtnbZk0BTz9f7HNAuTLt0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507518; c=relaxed/simple; bh=965q5vXFtWuP2DXkHm05coRtEPgFhuYFgYRgzq8yeAU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QQkRVVdX73dPHdMhZoWXDIUOp+LRh5SnZdKOV0I8yMa+So90kJ/Jkmf8EiiyZB+pS0iTwxUdusaJwoxkNfuabH6Q9ALIzdEUgLJ1xIRVpcI3TSnMidsG0qrJBWvbGiPdDhedoLqlw6JfX4f9e/CP7jADi7jfupC7isJW8Qyb9FQ= 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: zesmtpsz8t1751507399t22dfacec X-QQ-Originating-IP: 0XKdggV4wgrunhABTiF4S3HYclyofwQskYnEzqtSOEc= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:49:57 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 12444229288644496651 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 11/15] net: rnpgbe: Add setup hw ring-vector, true up/down hw Date: Thu, 3 Jul 2025 09:48:55 +0800 Message-Id: <20250703014859.210110-12-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NEuxXjgkfD8wo+5BQvI+TBpQBwcHyDasOd6by/PRaSeOfiGpafpBq5F+ f0yR/NUgWXz+ToOEFnIZ9Xhd2NCi5BjL7DBGbQKl1T1x+W994tYwV/1a+0nbRvEVRkt2t0u OayYWLteLilElpf+nmh/DCXig/8IzSIWYhGZncIaQo/5AOpLMiNJHcf5P7r4X7J0y826lj6 8yzH3etPADkVhNZPRP5nELSwWk3Sk567ZilLAtG8CzifLjkpONmJ5KtL97zYHR55xsyGx9q yoCr4dmhDFx8hz5QTIU9U1UYl05RlV4/JGt0X7+r12T8zD/N4MpkTQfNtktdLmXdY9opwJ6 bl3xRG+2tw/PIWoC4zpGNtaP2C7QbC13otYCBZ3yeRqsKPRKW1mtVFqFlosjQ0BRJaI3rTH 5IROd3Cmt2mNvrgXHjTKkawB9r22vm+CRugRzYUR9sOfGu388nRB2FUFFLFGmKqxK7xYDSw NsCjl5t/G5GGYxIZJoEY1q2mnxWNPdeIS6oulNQZP2TNFAc5dJc0vzsVkld/xZ52w1Sopaa +Uzrj2mlHm/Aan/XljNsZonmEHvgX79/qdLAXUCgvoSBC6ejqfuNCGSm52rYXceIbWaSDh8 73HqF18zdHJ+EA+eXPRbFBerwOneNocEyvsAm/KfI/FfgfY/4vHTPyVCzw7KXRqPC3GpiBl Iz+rwH5QyAnJISpeQySkqhXkVD4azt8lkiYJzEwspsa2ZngKVIuNCSCrB4Q2jhVaxZ1Qfee I+bOZqA9rG6DrvXaaS0JM//+39veh1ZcSI9PSckbGMLJJSFXhUaJretIqsz+KQczMoI6ikL 8aoS6ZFfgVpIg4sXUM5dA34crSsN6IyfHW32jv4k2x1ZnnmV/KplHVdPXv8jsUIE1JrNaxh eSk0CizI3PnTx1HRz3UNoh8sbDfEeFvOWNIiMnp9bbbN8hhjWbgsaJ+cg0SL17IzEXTkmbm +lQJvcqcj3FMLKV+1K/ZbdnvBAedwE3mdy2YyZOqlMJwgozVmf6vex1bOZAiHmZex+ZjBmD tbKzjzGWJ1m7Kh0aVaKW9ZDmLS+eTWZfsXlKwvefqB8Bsnb3S8la/NF2RD+Dk= X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= 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 | 14 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 113 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 72 +++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 56 +++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 90 ++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 31 ++++- 7 files changed, 379 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index d4e150c14582..c049952f41e8 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -183,6 +183,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 { @@ -531,6 +533,7 @@ struct mucse { struct net_device *netdev; struct pci_dev *pdev; struct mucse_hw hw; + u16 msg_enable; /* board number */ u16 bd_number; u16 tx_work_limit; @@ -563,6 +566,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 5ad287e398a7..7cc9134952bf 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -288,6 +288,18 @@ static void rnpgbe_set_irq_mode_n500(struct mucse_hw *= hw, bool legacy) } } =20 +static void rnpgbe_set_mbx_link_event_hw_ops_n500(struct mucse_hw *hw, + int enable) +{ + mucse_mbx_link_event_enable(hw, enable); +} + +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, @@ -297,6 +309,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 26fdac7d52a9..fec084e20513 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -1125,3 +1125,116 @@ 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 adapter struct + * @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_q_vector *q_vector; + int i; + struct mucse_hw *hw =3D &mucse->hw; + + /* + * 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 818bd0cabe0c..65bd97c26eaf 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) @@ -42,9 +45,75 @@ #define RX_DEFAULT_LINE (32) #define RX_DEFAULT_BURST (16) =20 +#define RING_VECTOR(n) (0x04 * (n)) #define mucse_for_each_ring(pos, head) \ for (pos =3D (head).ring; pos; pos =3D pos->next) =20 +#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 + * @adapter: board 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); + } +} + int rnpgbe_init_interrupt_scheme(struct mucse *mucse); void rnpgbe_clear_interrupt_scheme(struct mucse *mucse); int rnpgbe_setup_txrx(struct mucse *mucse); @@ -54,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 82acf45ad901..01cff0a780ff 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -47,6 +47,11 @@ static struct pci_device_id rnpgbe_pci_tbl[] =3D { {0, }, }; =20 +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LI= NK) +static int debug =3D -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=3Dnone,...,16=3Dall)"); + static struct workqueue_struct *rnpgbe_wq; =20 void rnpgbe_service_event_schedule(struct mucse *mucse) @@ -205,6 +210,36 @@ static void rnpgbe_configure(struct mucse *mucse) rnpgbe_configure_rx(mucse); } =20 +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); + + /* Set PF Reset Done bit so PF/VF Mail Ops can work */ + /* maybe differ in n500 */ + 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 @@ -235,6 +270,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: @@ -242,6 +278,24 @@ static int rnpgbe_open(struct net_device *netdev) return err; } =20 +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 @@ -255,6 +309,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 @@ -443,6 +498,7 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev, hw->hw_addr =3D hw_addr; hw->dma.dma_version =3D dma_version; hw->driver_version =3D driver_version; + mucse->msg_enable =3D netif_msg_init(debug, DEFAULT_MSG_ENABLE); hw->nr_lane =3D 0; ii->get_invariants(hw); hw->mbx.ops.init_params(hw); diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/ne= t/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c index f86fb81f4db4..fc6c0dbfff84 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 /** @@ -215,6 +216,47 @@ 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. + * + * Returns 0 on success, negative on failure + **/ +static int mucse_mbx_write_posted_locked(struct mucse_hw *hw, + struct mbx_fw_cmd_req *req) +{ + int err =3D 0; + int retry =3D 3; + + /* if pcie off, nothing todo */ + if (pci_channel_offline(hw->pdev)) + return -EIO; + + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; +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(req->datalen + MBX_REQ_HDR_LEN), + MBX_FW); + if (err) + goto try_again; + + mutex_unlock(&hw->mbx.lock); + + return err; +} + int rnpgbe_mbx_lldp_get(struct mucse_hw *hw) { int err; @@ -411,3 +453,51 @@ int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvf= num, out: return err; } + +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; +} + +int mucse_mbx_ifup_down(struct mucse_hw *hw, int up) +{ + int err; + struct mbx_fw_cmd_req req; + struct mbx_fw_cmd_reply reply; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + build_ifup_down(&req, hw->nr_lane, up); + + if (mutex_lock_interruptible(&hw->mbx.lock)) + return -EAGAIN; + + err =3D hw->mbx.ops.write_posted(hw, + (u32 *)&req, + L_WD(req.datalen + MBX_REQ_HDR_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 babdfc1f56f1..cd5a98acd983 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -609,6 +609,34 @@ static inline void build_get_macaddress_req(struct mbx= _fw_cmd_req *req, req->get_mac_addr.pfvf_num =3D 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 SET_EVENT_MASK; + req->datalen =3D 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 event_mask; + req->stat_event_mask.enable_stat =3D 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 IFUP_DOWN; + req->datalen =3D sizeof(req->ifup); + req->cookie =3D NULL; + req->reply_lo =3D 0; + req->reply_hi =3D 0; + req->ifup.lane =3D nr_lane; + req->ifup.up =3D 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); @@ -617,5 +645,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 Wed Oct 8 02:02:21 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 EFDB3248F73; Thu, 3 Jul 2025 01:52:07 +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=1751507531; cv=none; b=dNJRNi3B8xLJr+vYtIBN1BJ03G0L2TZxG75RkoaDbBywcbzJ02RUMFEffvc4bqbCnnspjHRcTR3ijqHIWIaPvR6afRyYkYbu6Vf0doqSzcP8ExHs+KaVMLWpCHNRdKwPCz1qRHNsrTAf+twAzKxl3p/bAohdsYPUkk+rZt++gLo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507531; c=relaxed/simple; bh=ihO9YbPnP8iNCV5NmH2yfc9a4/oEZ7qLZ8fmKO09ye0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hIUGsyp97UPUCBI1VW4EA/3Ad+ymB+PEHVqJN+T8iRv566SXJXoLjEhfCJhVDOjZPgYQ3Rqrqk9C6IjJ7fUB8F4P/X+J4PENE6X3rZaj4jHRN8UDbALriLnW7WYFH2f86nEImew+Jn9bQgU78R6zwMQ1OPBEE5xVDm2nyGOQ7FI= 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: zesmtpsz8t1751507403tc24b536c X-QQ-Originating-IP: 6jaqYZdkiWt/CIy1mBUqH84phgg54kjOR8/S2ofXLdQ= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:50:00 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 6159585008016695815 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 12/15] net: rnpgbe: Add link up handler Date: Thu, 3 Jul 2025 09:48:56 +0800 Message-Id: <20250703014859.210110-13-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: OHca88UHYcuYMzxNxwx0vPm0c2zQp/Fb/i9la4xbHs/PoHxcHN/AfJpY 4bZ2wnh4vjBz4Uy8oLHNWvopZCFTiuot2IJib/yliBRvI9u9HDYZleqNmKiWmpRoryOMMUX ZBsw4AhMpAHPecNlNifVrpEXv0uErEqoRh7ywmXBLARWARiFRFF+I2WFznqaAXgiIx4XvhR ma1/WzOgt8kABOA+4unz00BWhGTWm6zn3hIF88iLD/Fum2ATKWcT0f9ji89QLmV4IL3IRpD ZHtiy5ZqYjHJT3U0dXLiZwnj1VMerRsQISeqD18L3fWZJvSvZknz2dlNZuyzFPQxfU6LuLX HWnYgKl/YGeMBnygijz7FS59DVoOcfwhCZBDdV3fpFPiZdWcxOIPzzTucJ3V6O4iaWnDjg+ QBwu9PQS3LJbVWihh5pT9dmM2GwhU9HmtOnZNJM/7tKuzjKaW7aOd/lrkCATCbQR8beEwyk 6RriAKCSHtQ5f3Dp+9Wi4rdWMidv6hnkWOZXKBieKcW+Dx+7bexGIsYZZ3u9FZrqsdIKFWv cstj8BG+78PekqdvyrGCEHZMZ0ZgNEDpeGONd0bnSTP+SjQmOMUu0rav+0FmPRtzb50qbpf B7hKxrYNzoXNUT+uw7he2M3+dBNFtY35PyixoMSZ72p2Gjz0lehYeeGQbgw2CBY2ySlojYq IkCZO2hYlb7snCWhD6MK8dC3hyS7WrmLY+W187dCyz0lwzL0c80aeZ2abVSEc7MJGGcYBbQ EXavXnLBsQVhWFwSj/rGd+o+KVzNeH7UN6iE4Xz1ZRXoQHeg7ADC+oyIe/WdcU4Ha0U126f MaLAHxJTj6xx35IhGQIu0CYcJVFgBXNCm9BdsGUUl2EdIy+b946dNm6mH3f9Tga24Db7JL0 ThxhKft5syaHS82JDvjG8/AATTg6Jr4/k8ucG0LLPh9mmYfgN3nJk0vfAZpVmu3ReLY5/Ne 3AVoWffdAfOrK7K14Bhz63WqFC8yQMQT7HsdLLd6pGaKyoIDO11f2/5DPNIsMpdiCk8ZcEI fHdoTS4X2kx9yjPNDtLsTVKSgEmY3oIAKsL/OobY54ra4uOiKhm13PXJqyXUS64hmzmKP17 w== 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 | 55 ++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 19 +++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 138 +++++++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h | 1 + .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 147 ++++++++++++++++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 1 + 6 files changed, 359 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index c049952f41e8..5ca2ec73bbe7 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -25,6 +25,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; @@ -120,6 +129,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; @@ -185,6 +219,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 { @@ -223,6 +259,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; struct mucse_addr_filter_info addr_ctrl; #define M_NET_FEATURE_SG ((u32)(1 << 0)) @@ -253,13 +290,17 @@ 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]; }; =20 enum mucse_state_t { - __MMUCSE_TESTING, + __MUCSE_TESTING, + __MUCSE_RESETTING, __MUCSE_DOWN, __MUCSE_SERVICE_SCHED, __MUCSE_PTP_TX_IN_PROGRESS, @@ -547,6 +588,7 @@ struct mucse { u32 priv_flags; #define M_PRIV_FLAG_TX_COALESCE ((u32)(1 << 25)) #define M_PRIV_FLAG_RX_COALESCE ((u32)(1 << 26)) +#define M_PRIV_FLAG_LLDP ((u32)(1 << 27)) struct mucse_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; int tx_ring_item_count; int num_tx_queues; @@ -565,6 +607,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; @@ -613,9 +658,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((void *)(reg)) #define m_wr_reg(reg, val) writel((val), (void *)(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 7cc9134952bf..cb2448f497fe 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -300,6 +300,24 @@ static void rnpgbe_set_mbx_ifup_hw_ops_n500(struct muc= se_hw *hw, mucse_mbx_ifup_down(hw, enable); } =20 +static void rnpgbe_check_mac_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, @@ -311,6 +329,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_mac_link_hw_ops_n500, }; =20 /** diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/= ethernet/mucse/rnpgbe/rnpgbe_main.c index 01cff0a780ff..c2f53af3de09 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -84,12 +84,144 @@ static void rnpgbe_service_timer(struct timer_list *t) rnpgbe_service_event_schedule(mucse); } =20 +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 adapter structure + **/ +static void rnpgbe_watchdog_update_link(struct mucse *mucse) +{ + struct mucse_hw *hw =3D &mucse->hw; + u32 link_speed =3D mucse->link_speed; + bool link_up; + bool duplex; + bool flow_rx =3D true, flow_tx =3D true; + + 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; + } + + 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 adapter 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 adapter 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 adapter structure + **/ +static void rnpgbe_watchdog_subtask(struct mucse *mucse) +{ + /* if interface is down do nothing */ + /* should do link status if in sriov */ + 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 int rnpgbe_poll(struct napi_struct *napi, int budget) @@ -255,7 +387,7 @@ static int rnpgbe_open(struct net_device *netdev) int err; =20 /* disallow open during test */ - if (test_bit(__MMUCSE_TESTING, &mucse->state)) + if (test_bit(__MUCSE_TESTING, &mucse->state)) return -EBUSY; =20 netif_carrier_off(netdev); @@ -271,6 +403,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: @@ -387,6 +521,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 fbb154051313..666896de1f9f 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h @@ -8,6 +8,7 @@ #define MUCSE_ERR_MBX -100 /* 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 fc6c0dbfff84..066bf450cf59 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c @@ -501,3 +501,150 @@ int mucse_mbx_ifup_down(struct mucse_hw *hw, int up) =20 return err; } + +static void rnpgbe_link_stat_mark(struct mucse_hw *hw, int up) +{ + u32 v; + struct mucse *mucse =3D (struct mucse *)hw->back; + + 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); +} + +static int rnpgbe_mbx_fw_reply_handler(struct mucse *adapter, + 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 reply->error_code; + else + cookie->errcode =3D 0; + wake_up_interruptible(&cookie->wait); + return 0; +} + +static int rnpgbe_mbx_fw_req_handler(struct mucse *mucse, + struct mbx_fw_cmd_req *req) +{ + struct mucse_hw *hw =3D &mucse->hw; + + switch (req->opcode) { + case LINK_STATUS_EVENT: + if (req->link_stat.lane_status) + hw->link =3D 1; + else + hw->link =3D 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) { + /* fw_version more than 0.1.5.0 can up lldp_status */ + if (hw->fw_version >=3D 0x00010500) { + if (req->link_stat.st[0].lldp_status) + mucse->priv_flags |=3D M_PRIV_FLAG_LLDP; + else + mucse->priv_flags &=3D (~M_PRIV_FLAG_LLDP); + } + } + if (req->link_stat.port_st_magic =3D=3D SPEED_VALID_MAGIC) { + hw->speed =3D 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].pause; + hw->tp_mdx =3D req->link_stat.st[0].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; +} + +static int rnpgbe_rcv_msg_from_fw(struct mucse *mucse) +{ + u32 msgbuf[MUCSE_FW_MAILBOX_SIZE]; + struct mucse_hw *hw =3D &mucse->hw; + s32 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 */ +} + +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 cd5a98acd983..2700eebf5873 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h @@ -647,4 +647,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 Wed Oct 8 02:02:21 2025 Received: from smtpbgbr1.qq.com (smtpbgbr1.qq.com [54.207.19.206]) (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 D4B5924EA80; Thu, 3 Jul 2025 01:52:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.207.19.206 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507544; cv=none; b=FPxO7LOM9yLvpA8nRTx5ZkAfbNyC3wxgueCrkpWYhWAA0EdpS2I6L30LBz6KCjxJFen3BHr3g5Jrqsfo07NBcLbpwSmFceOfLU3TSksHZ7aoBSunvDhnFbGnAwBjyJxi2rM8JF5BCQyKLnBcFfEcbtrWSBQVTHgl+iaJlWdpG7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507544; c=relaxed/simple; bh=1r+MM5LxhP85M349rKeCiNBVRTXnGgq76j9rvxSybn4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=B8mKu2pWrbBKjpkIfE5XV3NgDnIvR712w9enYtONJrA1NkLfoD3czhuOLd29osvTEccb0WRvD8Yad9Ro4jUgkSanRM6u0pO668k4Fo3oGc6ZFdEmWwcXPSCaOC/+GuUomth/ft4yJ65R3k6KOnLTjgsSEAIzS8lKalHd9BXYliA= 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.19.206 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: zesmtpsz8t1751507406t4d32d43c X-QQ-Originating-IP: Ee29eVjraGbxx9oc0Nka5zWm1lLrbzewMyiIMFTEgdI= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:50:04 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 2215868535102422593 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 13/15] net: rnpgbe: Add base tx functions Date: Thu, 3 Jul 2025 09:48:57 +0800 Message-Id: <20250703014859.210110-14-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: NRYSeI3Ux+UPEovXoG0KJZrxAX5hRf4jKz+iyUCEm4Z2arkky3qGgxKi jnA1zxtgtYkpix1ERX+gqKa5+YcXNL2NCv7pZ1Yi3UdkgrXvnlypoLYBj6vQiU8k02OkSJz /fF11YnowsQfhOhSRMDNFrUDobRQwe5vLML62LX2LVR3Dit/zuSIJZYHuYZXvTSaqjgcsPM jd45rzumFX/eiEXJqCVt9ctNqqeb+FUBVDitNDZg5DNce9nNjOAEYvskPJFDHh+mChbXfM2 TBolCICqtuoSFO1/ZObNh+yNOV2ISw8QjsrcsNU4pRPizRH1LOEcphEhqU8cB7WPMpAl1iU gpW9H6uHEnPcRzu2IhafVZYlzlc2S3dXF8NJHBtYSIRQejGMd+o3Cipy9UyyLtW+GPBNhS7 nVxPjMfONb6BG48RJpzUrjizwRr2ZT8ARc3YDagDhi0OZrbUq60+epIh+6gxzysVcbqLrjq Y2fs7swIPCgWDpcw7HArjImC5h538Qr/9YUZiuZ5w3Zm0yOnR2NZIPfgoLrHywzyw5eV6u3 1V1QKgEtg9U0pQOqR5wt2y2gPEr/CBL+uqgMTSvO3N6smcMKjm/QBxSOiS/6umWMB7tu+CW 7SMGsW/PfYlYgckEeZ41yEah6YnyKEt3+UhkVk1tl0DW9rFaR/ViNGWQyAk7YxA5inRw/00 uaUh+yciIHXPk2+dnRb4S+GjcLz1te3OL8VodPk2PY3RxWeNpYMICXCXUhfZBE4RAEIRN/O zXpIOECY4CiFO1MybUrnWVlJ3k0NyQpJJcDGTvtVGelEitu96DO3NaEP2Yiok2xydOlHRuQ ajYgiVHI1HqOyQcCnisXcOdXp756iiHray/UtF2ihrIRk9rxSOvlW7FFKUiQSyRwTIdu2/3 6HPWQ+DKZfV+ajVYhEHUtmTbb/bcwAmsj7HRdntZKwvYcujdgs0LkOXvpkxRYyt85Xtm4cV /AcpAeys6veIdeL8Bp4PyLcboG4Y8F3alNUlOrlVe8Aw8Zji0UadF+pALCyvzTpnogdXCaB f9ixHLY7F6I1ktbJ7N X-QQ-XMRINFO: NI4Ajvh11aEj8Xl/2s1/T8w= 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 | 20 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 56 ++- drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 6 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 406 +++++++++++++++++- .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 14 +- .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 79 +++- 6 files changed, 568 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 5ca2ec73bbe7..7871cb30db58 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -50,6 +50,7 @@ struct mucse_eth_operations { s32 (*set_rar)(struct mucse_eth_info *eth, u32 index, u8 *addr); s32 (*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 @@ -79,6 +80,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 { @@ -221,6 +223,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 { @@ -542,6 +545,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; }; @@ -623,11 +628,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) { @@ -688,6 +707,5 @@ static inline unsigned int mucse_rx_bufsz(struct mucse_= ring *ring) #define MUCSE_ERR_INVALID_ARGUMENT (-1) =20 void rnpgbe_service_event_schedule(struct mucse *mucse); -int rnpgbe_poll(struct napi_struct *napi, int budget); =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 cb2448f497fe..edc3f697fa3a 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c @@ -85,10 +85,23 @@ 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 +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 +124,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 static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw) @@ -318,6 +354,23 @@ static void rnpgbe_check_mac_link_hw_ops_n500(struct m= ucse_hw *hw, *duplex =3D !!hw->duplex; } =20 +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 (pci_channel_offline(hw->pdev)) + return; + + 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, @@ -330,6 +383,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_mac_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 fec084e20513..1aab4cb0bbaa 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -131,6 +131,174 @@ 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 + **/ +static bool rnpgbe_clean_tx_irq(struct mucse_q_vector *q_vector, + struct mucse_ring *tx_ring, + int napi_budget) +{ + struct mucse *mucse =3D q_vector->mucse; + struct mucse_tx_buffer *tx_buffer; + struct rnpgbe_tx_desc *tx_desc; + u64 total_bytes =3D 0, total_packets =3D 0; + int budget =3D q_vector->tx.work_limit; + 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 Rx polling callback + * @napi: structure for representing this polling device + * @budget: how many packets driver is allowed to clean + * + * This function is used for legacy and MSI, NAPI mode + **/ +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; + struct mucse_ring *ring; + int work_done =3D 0; + bool clean_complete =3D true; + + 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); +} + /** * rnpgbe_alloc_q_vector - Allocate memory for a single interrupt vector * @mucse: pointer to private structure @@ -863,8 +1031,14 @@ static void rnpgbe_configure_tx_ring(struct mucse *mu= cse, **/ void rnpgbe_configure_tx(struct mucse *mucse) { - u32 i; + u32 i, dma_axi_ctl; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma =3D &hw->dma; =20 + /* 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]); @@ -955,21 +1129,47 @@ static void rnpgbe_configure_rx_ring(struct mucse *m= ucse, } =20 /** - * rnpgbe_configure_rx - Configure 8259x Receive Unit after Reset + * 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; + int i, dma_axi_ctl; + struct mucse_hw *hw =3D &mucse->hw; + struct mucse_dma_info *dma =3D &hw->dma; =20 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 + * @adapter: board 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 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 @@ -1238,3 +1438,203 @@ void rnpgbe_configure_msix(struct mucse *mucse) } } } + +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); +} + +static int rnpgbe_tx_map(struct mucse_ring *tx_ring, + struct mucse_tx_buffer *first, u32 mac_ip_len, + u32 tx_flags) +{ + struct sk_buff *skb =3D first->skb; + struct mucse_tx_buffer *tx_buffer; + struct rnpgbe_tx_desc *tx_desc; + skb_frag_t *frag; + dma_addr_t dma; + unsigned int data_len, size; + u16 i =3D tx_ring->next_to_use; + u64 fun_id =3D ((u64)(tx_ring->pfvfnum) << (56)); + + 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; +} + +static int __rnpgbe_maybe_stop_tx(struct mucse_ring *tx_ring, u16 size) +{ + 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; +} + +static inline int rnpgbe_maybe_stop_tx(struct mucse_ring *tx_ring, u16 siz= e) +{ + if (likely(mucse_desc_unused(tx_ring) >=3D size)) + return 0; + return __rnpgbe_maybe_stop_tx(tx_ring, size); +} + +netdev_tx_t rnpgbe_xmit_frame_ring(struct sk_buff *skb, + struct mucse *mucse, + struct mucse_ring *tx_ring) +{ + struct mucse_tx_buffer *first; + u16 count =3D TXD_USE_COUNT(skb_headlen(skb)); + /* 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; + /* maybe consider len smaller than 60 */ + 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 65bd97c26eaf..7179e5ebfbf0 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 c2f53af3de09..ea41a758ac49 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c @@ -166,12 +166,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 /** @@ -182,6 +184,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; @@ -191,6 +194,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 /** @@ -224,11 +228,6 @@ static void rnpgbe_service_task(struct work_struct *wo= rk) rnpgbe_service_event_complete(mucse); } =20 -int rnpgbe_poll(struct napi_struct *napi, int budget) -{ - return 0; -} - /** * rnpgbe_check_fw_from_flash - Check chip-id and bin-id * @hw: hardware structure @@ -418,6 +417,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)) @@ -425,6 +425,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; @@ -453,14 +454,78 @@ 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); +} + +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 static void rnpgbe_assign_netdev_ops(struct net_device *dev) --=20 2.25.1 From nobody Wed Oct 8 02:02:21 2025 Received: from smtpbg151.qq.com (smtpbg151.qq.com [18.169.211.239]) (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 D16091DEFC5; Thu, 3 Jul 2025 01:52:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.169.211.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507554; cv=none; b=UtLZUu+yIC+BPvcFasc+S+hzjpLODXPTeH4060QOLPMmhHGh6R/GiwkZnqOCyT6t9xkjO4eeMCtc7wWsA8aCJ/7bG7cMuQaRNllTmRmoyeOOwgCIthEb0aM6IU2SDN8jVmPEqWlyxXvDCqlqh68684cPDb4h+tZFpUL3VW0gUoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507554; c=relaxed/simple; bh=fFTFy7YY4e24+F3RbE9XZGNg8pB5yX/3s4KeQyJhAzs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hWSEOyWgiWa5GxtcIHLaVlWdAhmIgV544ZJI4AgaCEdzc6rObZGM0sjX91O2SAMyKcr6TZwKOHEAYO+aMe6yLy0srKles2eaUt/HgY4CyBAKpKCoiFc8+8J3MB4Xe+IALyPYwTWoJZ4Qiru35BFSMYFuPkbtcArKrYOmpDhjgc0= 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.169.211.239 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: zesmtpsz8t1751507410t0972093c X-QQ-Originating-IP: wTxALNgEqKEpNzQPNcVqHT64xQ5wRt1JfIsr+7SOrGs= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:50:08 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 12658208802092347414 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 14/15] net: rnpgbe: Add base rx function Date: Thu, 3 Jul 2025 09:48:58 +0800 Message-Id: <20250703014859.210110-15-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: MBREESna/OUiZZgeoaS+E/+VEXJhm8T2Ok9VfsST1V3+re7/zXdkQNjq YbHfdr4QEyvQZlWFpxGaBzPa5hgoAZsZFNe8zQdCGpNNnqLRqm5S7tTYoSQP1k04yGfm1FW RtgOkeecPejANfLWzleT6JGUr8ojE2n0fVhydhBMqp1kwougdtutCXmZMd0JQl30ULWZMuj rmJg4G8A8zoAWYgQKmylBlZusIvrw8M5hK5sX2n/99Ngd8wxJbDNWj+DrCJypv6onYWiIQq ZQCKGZJRi+ZopxXLSAiX5tcHY3oWApw3C5EAq29MH9Ki9SeuhX2UzCpbysjnpQ8H8N3e84B AI3edZMX6tuCNNwyXG6uiae8zxtsCn0d2Llfbjj8wILiIQZcbaTXfu5VgiIgnXlOCPVmfyJ NlnRH/6iiaLPM2/WU5RSwviqH1S30NSfHIq9hRij3JC2h22e0u2AN7jazt1z/RmieRld0Dx maauF9q0VuvRpe+Gx6gfa3pdNlx7y8hohBwJXCYMMoj9i95Tk9nDsJh4uusQLb5qdW8GMql 5R+mXpSh8Oji5QPMQQ153p/4OvZ93r9Pi1RZgAuPmMVcA53kh1sNrSK3+FRHy/LvAw8rkuz S2oPOm0gFGUFnmWioZrotgVuogvLDQ6+QoPqMmaSCPH7I8QtCD5GzSuT6haomAaMkI6YOwE RVppJMnGx7RaDoNSVRiybmX3w4RdS3A1qQBxmC9KF/o1xAJfr20DA53F5ZOfYN47eDzRO9f I3QnROQN/qlttvCLdmaV6InQYHRkijj1qsfske+trp4a6UA6LUTRvo91mFsbDyMTiGva7AY frkPGPGDsLDdjfG9H9CDorhZ/JVHwc6HdVGG5r2t+MSBwQo90fCMKd/q1sQ2KD+V1cT9UD5 1RMXSwTG870tko47xDIHpJpsT534Cpc5Xti6e9/03BYnqb4rKTaYSTHsFYjDqJ05jo7x15q b8xpCAL/ogovc//CnttS/23uiDlSLLnf19IH5P2LCoeKkRh84ycg8XgqZUndfov6QQymT6D Vp2YXHH9r4nKv5kXEB X-QQ-XMRINFO: NI4Ajvh11aEj8Xl/2s1/T8w= 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 | 22 + .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.c | 586 ++++++++++++++++-- .../net/ethernet/mucse/rnpgbe/rnpgbe_lib.h | 3 +- 3 files changed, 575 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 7871cb30db58..0b6ba4c3a6cb 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -361,6 +361,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 { @@ -496,6 +497,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; @@ -587,6 +589,7 @@ struct mucse { #define M_FLAG_NEED_LINK_UPDATE ((u32)(1 << 0)) #define M_FLAG_MSIX_ENABLED ((u32)(1 << 1)) #define M_FLAG_MSI_ENABLED ((u32)(1 << 2)) +#define M_FLAG_SRIOV_ENABLED ((u32)(1 << 23)) u32 flags2; #define M_FLAG2_NO_NET_REG ((u32)(1 << 0)) #define M_FLAG2_INSMOD ((u32)(1 << 1)) @@ -636,6 +639,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); @@ -647,12 +658,22 @@ 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 + +/* rnpgbe_test_staterr - tests bits in Rx descriptor status and error fiel= ds */ +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 @@ -684,6 +705,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((void *)(reg)) #define m_wr_reg(reg, val) writel((val), (void *)(reg)) #define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val)) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 1aab4cb0bbaa..05073663ad0e 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -2,10 +2,15 @@ /* Copyright(c) 2020 - 2025 Mucse Corporation. */ =20 #include +#include +#include +#include =20 #include "rnpgbe.h" #include "rnpgbe_lib.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 @@ -263,6 +268,419 @@ static bool rnpgbe_clean_tx_irq(struct mucse_q_vector= *q_vector, return total_bytes =3D=3D 0; } =20 +#if (PAGE_SIZE < 8192) +static inline int rnpgbe_compute_pad(int rx_buf_len) +{ + int page_size, pad_size; + + page_size =3D ALIGN(rx_buf_len, PAGE_SIZE / 2); + pad_size =3D SKB_WITH_OVERHEAD(page_size) - rx_buf_len; + + return pad_size; +} + +static inline int rnpgbe_skb_pad(void) +{ + int rx_buf_len =3D M_RXBUFFER_1536; + + return rnpgbe_compute_pad(rx_buf_len); +} + +#define RNP_SKB_PAD rnpgbe_skb_pad() + +static inline int rnpgbe_sg_size(void) +{ + int sg_size =3D SKB_WITH_OVERHEAD(PAGE_SIZE / 2) - RNP_SKB_PAD; + + sg_size -=3D NET_IP_ALIGN; + sg_size =3D ALIGN_DOWN(sg_size, 4); + + return sg_size; +} + +#define SG_SIZE rnpgbe_sg_size() + +static inline unsigned int rnpgbe_rx_offset(void) +{ + return RNP_SKB_PAD; +} + +#else /* PAGE_SIZE < 8192 */ +#define RNP_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) +#endif + +static struct mucse_rx_buffer *rnpgbe_get_rx_buffer(struct mucse_ring *rx_= ring, + 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; +} + +static void rnpgbe_add_rx_frag(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *rx_buffer, + struct sk_buff *skb, + unsigned int size) +{ +#if (PAGE_SIZE < 8192) + unsigned int truesize =3D PAGE_SIZE / 2; +#else + unsigned int truesize =3D SKB_DATA_ALIGN(RNP_SKB_PAD + size) : +#endif + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, + rx_buffer->page_offset, size, truesize); +} + +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) +{ + void *va =3D page_address(rx_buffer->page) + rx_buffer->page_offset; + unsigned int truesize =3D SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(size + RNP_SKB_PAD); + struct sk_buff *skb; + + net_prefetch(va); + /* build an skb around the page buffer */ + skb =3D build_skb(va - RNP_SKB_PAD, truesize); + if (unlikely(!skb)) + return NULL; + + /* update pointers within the skb to store the data */ + skb_reserve(skb, RNP_SKB_PAD); + __skb_put(skb, size); + + skb_mark_for_recycle(skb); + + return skb; +} + +static void rnpgbe_put_rx_buffer(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *rx_buffer, + struct sk_buff *skb) +{ + /* 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. + **/ +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; +} + +static void rnpgbe_pull_tail(struct sk_buff *skb) +{ + skb_frag_t *frag =3D &skb_shinfo(skb)->frags[0]; + unsigned char *va; + unsigned int pull_len; + + /* + * 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; +} + +static bool rnpgbe_cleanup_headers(struct mucse_ring __maybe_unused *rx_ri= ng, + union rnpgbe_rx_desc *rx_desc, + 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 */ + /* will padding skb->len to 60 */ + if (eth_skb_pad(skb)) + return true; + + return false; +} + +static inline 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 inline 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; +} + +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 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 vid_outer; + u16 vlan_tci =3D htons(ETH_P_8021Q); + + __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 - bounce= buf + * @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 + * + * This function provides a "bounce buffer" approach to Rx interrupt + * processing. The advantage to this is that on systems that have + * expensive overhead for IOMMU access this provides a means of avoiding + * it by maintaining the mapping of the page to the system. + * + * Returns 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; + unsigned int driver_drop_packets =3D 0; + u16 cleaned_count =3D mucse_desc_unused_rx(rx_ring); + bool fail_alloc =3D false; + + while (likely(total_rx_packets < budget)) { + union rnpgbe_rx_desc *rx_desc; + struct mucse_rx_buffer *rx_buffer; + 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) { + fail_alloc =3D rnpgbe_alloc_rx_buffers(rx_ring, cleaned_count) || 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_rx_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, skb); + 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(rx_ring, rx_desc, 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 Rx polling callback * @napi: structure for representing this polling device @@ -276,11 +694,26 @@ static int rnpgbe_poll(struct napi_struct *napi, int = budget) container_of(napi, struct mucse_q_vector, napi); struct mucse *mucse =3D q_vector->mucse; struct mucse_ring *ring; - int work_done =3D 0; + int per_ring_budget, work_done =3D 0; bool clean_complete =3D true; + 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; @@ -799,6 +1232,30 @@ static void rnpgbe_free_all_tx_resources(struct mucse= *mucse) rnpgbe_free_tx_resources(mucse->tx_ring[i]); } =20 +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 @@ -841,6 +1298,7 @@ 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; + mucse_alloc_page_pool(rx_ring); =20 return 0; err: @@ -870,13 +1328,7 @@ static void rnpgbe_clean_rx_ring(struct mucse_ring *r= x_ring) rx_buffer->page_offset, mucse_rx_bufsz(rx_ring), DMA_FROM_DEVICE); - /* free resources associated with mapping */ - dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, - PAGE_SIZE, - DMA_FROM_DEVICE, - M_RX_DMA_ATTR); - __page_frag_cache_drain(rx_buffer->page, - rx_buffer->pagecnt_bias); + page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, false); rx_buffer->page =3D NULL; i++; rx_buffer++; @@ -909,6 +1361,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 /** @@ -1049,44 +1505,103 @@ void rnpgbe_disable_rx_queue(struct mucse_ring *ri= ng) ring_wr32(ring, DMA_RX_START, 0); } =20 -#if (PAGE_SIZE < 8192) -static inline int rnpgbe_compute_pad(int rx_buf_len) +static bool mucse_alloc_mapped_page(struct mucse_ring *rx_ring, + struct mucse_rx_buffer *bi) { - int page_size, pad_size; - - page_size =3D ALIGN(rx_buf_len, PAGE_SIZE / 2); - pad_size =3D SKB_WITH_OVERHEAD(page_size) - rx_buf_len; + struct page *page =3D bi->page; + dma_addr_t dma; =20 - return pad_size; -} + /* since we are recycling buffers we should seldom need to alloc */ + if (likely(page)) + return true; =20 -static inline int rnpgbe_sg_size(void) -{ - int sg_size =3D SKB_WITH_OVERHEAD(PAGE_SIZE / 2) - NET_SKB_PAD; + page =3D page_pool_dev_alloc_pages(rx_ring->page_pool); + dma =3D page_pool_get_dma_addr(page); =20 - sg_size -=3D NET_IP_ALIGN; - sg_size =3D ALIGN_DOWN(sg_size, 4); + bi->dma =3D dma; + bi->page =3D page; + bi->page_offset =3D RNP_SKB_PAD; =20 - return sg_size; + return true; } =20 -#define SG_SIZE rnpgbe_sg_size() -static inline int rnpgbe_skb_pad(void) +static inline void mucse_update_rx_tail(struct mucse_ring *rx_ring, + u32 val) { - int rx_buf_len =3D SG_SIZE; - - return rnpgbe_compute_pad(rx_buf_len); + 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); } =20 -#define RNP_SKB_PAD rnpgbe_skb_pad() -static inline unsigned int rnpgbe_rx_offset(void) +/** + * 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) { - return RNP_SKB_PAD; -} + union rnpgbe_rx_desc *rx_desc; + struct mucse_rx_buffer *bi; + u16 i =3D rx_ring->next_to_use; + u64 fun_id =3D ((u64)(rx_ring->pfvfnum) << (32 + 24)); + bool err =3D false; + u16 bufsz; + /* nothing to do */ + if (!cleaned_count) + return err; =20 -#else /* PAGE_SIZE < 8192 */ -#define RNP_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) -#endif + 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; + } + + { + u16 *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; +} =20 static void rnpgbe_configure_rx_ring(struct mucse *mucse, struct mucse_ring *ring) @@ -1126,6 +1641,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 /** @@ -1151,7 +1667,7 @@ void rnpgbe_configure_rx(struct mucse *mucse) =20 /** * rnpgbe_clean_all_tx_rings - Free Tx Buffers for all queues - * @adapter: board private structure + * @mucse: board private structure **/ void rnpgbe_clean_all_tx_rings(struct mucse *mucse) { diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.h b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.h index 7179e5ebfbf0..5c7e4bd6297f 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) @@ -106,7 +107,7 @@ static inline void rnpgbe_irq_disable_queues(struct muc= se_q_vector *q_vector) =20 /** * rnpgbe_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure + * @mucse: board private structure **/ static inline void rnpgbe_irq_disable(struct mucse *mucse) { --=20 2.25.1 From nobody Wed Oct 8 02:02:21 2025 Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) (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 49AAA246BC1; Thu, 3 Jul 2025 01:52:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.254.200.128 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507526; cv=none; b=iMLe5oademVraVGEcXaREDPiZGZWzkYnQSXknRk+UD9MY3P9KC96ro7EQlfsnCunGqY8n9rxhx2/VFSg5qTJNbOkgBg4uUe2rJDyjeRdAYgxUH99enEnBCWpQ3wkWtGvYMIaisTyuGhvJx37VP142VuK8qHUBjmH3AiV+6VpGrE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507526; c=relaxed/simple; bh=Mm7IZiFNMnbxKSXQgtSuhJG0N/BFhn7Go1NY+dUy9fM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AJ81yJQCvijFf50uK7OLyLjZe0Smv0713PcGdbdhEzd+6tliyWKbcLUiato0aQYBMBgrhNUUOjnUwu9s63b/WgdSe0vQXMUcX1+5diFuXrxZTSbWXwNSD6M6NnPPFpmWb6UCCURZnvc60j3TmJZ0YArSN4R7Xv8QsmxfesIVbdQ= 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.128 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: zesmtpsz8t1751507413tdf0abb81 X-QQ-Originating-IP: +QrC9xChzcH6HQz/g7luc9deusWmGb+bP+AHfYQz9fI= Received: from localhost.localdomain ( [203.174.112.180]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 03 Jul 2025 09:50:11 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 11652823405052598181 EX-QQ-RecipientCnt: 22 From: Dong Yibo To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, corbet@lwn.net, andrew+netdev@lunn.ch, 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 Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dong100@mucse.com Subject: [PATCH 15/15] net: rnpgbe: Add ITR for rx Date: Thu, 3 Jul 2025 09:48:59 +0800 Message-Id: <20250703014859.210110-16-dong100@mucse.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250703014859.210110-1-dong100@mucse.com> References: <20250703014859.210110-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: zesmtpsz:mucse.com:qybglogicsvrgz:qybglogicsvrgz8a-1 X-QQ-XMAILINFO: Mwdq8jAc4iJQ29n369uInzBmbrxH3n79YHKv6bFVykyD3qhJv2ffwALa yxI57zkMoujfqd6hP99eH2JremvaELM8TAKEj93PqCUHF7SFtG4IChGsLzeFj+3Aa8b8Asl 1rhSBawUhEDE+HINYT9vaE6Nm2UbZZKNj+NsQmguMDsq+/qJRIs/PHOhMFbEG1SsqujZ9Ao XxDbfnL0Ba0h5Y7IE1QqxdfW2jrsYcwjwJZ9uHj6gnPDpE2oigbl0NQTi6kU30BXyrjlW6u chyt9nfVZ9d44rSYW9KCCRRBXxckUSIhPq+cAWupd/6uTrVaPxp0WQpDLpUd9M3c+rVG0sM PVkFh80bH9ByPr+9Y4kVOehxNkdZJVMTPWVIiaZQeQmJM113fRuKUZst3qTxyYYR4lkhSCp BumBSW2kQwIfyTfy064bZrzNqD2XEuZW8b2qEQU1eGX2dejHah5tsodIvIT4erNEEctuwWF 13xs6Jm0REhTLooTu1M4JpwUcyNdtuTbMPQ9UEMdMJTx1KcSdcVdDfpgtCRCBAI+J/65AJj X4LJKm9JN59TKZMv9rcl+8OpIAd/hLdJUxEb9ImbKiW18k+qNVCLeo8MYqBf5D1rO4P3IR1 JTx01o6KvLODyUiIHZ00QLMUv4vLUwh50KCeyjLihMv2ogbk29Tjjfz4Rnty1lWrwoW2pzW dQtNy10SpDiqpmTPl9zvq40fJ3crOgASfASERvSVbAjTtx5kUg8xi4pAv5wXGs41PmZQULO AWdYpNH8QwncM3QUTvPA0YgHy+8cQbrX5+68COkEOyV67w5sutxSnxKTzPGfL3eJU1hTAQc nbIlsfKX3gMvwWgTa1GLL0zNc4PYCBlekz02ryzbYHCrVD5cH4soQL07hHxvP5mpBskblbY VhIPEFKw9JXVpTCHde1O/fkMtjvcMQk8XrDiD4mBGec+vCc/7xhBykoTDLNzJFN61+yt1pt TbLFhKJlSmuDGn29UEBmpNe4P13CKsni7hzea8ZxZynTjhdp26nIrDs93zl6enshDsxwUxA Zd5Xwzff0uUh309dZBOAkr5abfIsC/1HxgfFwvbyqnn9kdIG9z 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 | 91 ++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ether= net/mucse/rnpgbe/rnpgbe.h index 0b6ba4c3a6cb..8e692da05eb7 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h @@ -551,6 +551,8 @@ struct mucse_ring_container { unsigned int total_packets; u16 work_limit; u16 count; + u16 itr; + int update_count; }; =20 struct mucse_q_vector { @@ -705,6 +707,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((void *)(reg)) #define m_wr_reg(reg, val) writel((val), (void *)(reg)) diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/e= thernet/mucse/rnpgbe/rnpgbe_lib.c index 05073663ad0e..5d82f063eade 100644 --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c @@ -681,6 +681,62 @@ static int rnpgbe_clean_rx_irq(struct mucse_q_vector *= q_vector, return fail_alloc ? budget : total_rx_packets; } =20 +static void rnpgbe_update_ring_itr_rx(struct mucse_q_vector *q_vector) +{ + int new_val =3D q_vector->itr_rx; + int avg_wire_size =3D 0; + struct mucse *mucse =3D q_vector->mucse; + 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 Rx polling callback * @napi: structure for representing this polling device @@ -725,6 +781,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); } @@ -1677,12 +1734,44 @@ void rnpgbe_clean_all_tx_rings(struct mucse *mucse) rnpgbe_clean_tx_ring(mucse->tx_ring[i]); } =20 +static void rnpgbe_write_eitr_rx(struct mucse_q_vector *q_vector) +{ + struct mucse *mucse =3D q_vector->mucse; + struct mucse_hw *hw =3D &mucse->hw; + u32 new_itr_rx =3D q_vector->rx.itr; + u32 old_itr_rx =3D q_vector->rx.itr; + 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; + } + } +} + static irqreturn_t rnpgbe_msix_clean_rings(int irq, void *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