Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'add-driver-for-1gbe-network-chips-from-mucse'

Dong Yibo says:

====================
Add driver for 1Gbe network chips from MUCSE

This patch series adds support for MUCSE RNPGBE 1Gbps PCIe Ethernet controllers
(N500/N210 series), including build infrastructure, hardware initialization,
mailbox (MBX) communication with firmware, and basic netdev registration
(Can show mac witch is got from firmware, and tx/rx will be added later).

Series breakdown (5 patches):
01/05: net: ethernet/mucse: Add build support for rnpgbe
- Kconfig/Makefile for MUCSE vendor, basic PCI probe (no netdev)
02/05: net: ethernet/mucse: Add N500/N210 chip support
- netdev allocation, BAR mapping
03/05: net: ethernet/mucse: Add basic MBX ops for PF-FW communication
- base read/write, write with poll ack, poll and read data
04/05: net: ethernet/mucse: Add FW commands (sync, reset, MAC query)
- FW sync retry logic, MAC address retrieval, reset hw with
base mbx ops in patch4
05/05: net: ethernet/mucse: Complete netdev registration
- HW reset, MAC setup, netdev_ops registration
====================

Link: https://patch.msgid.link/20251101013849.120565-1-dong100@mucse.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1335
+1
Documentation/networking/device_drivers/ethernet/index.rst
··· 47 47 mellanox/mlx5/index 48 48 meta/fbnic 49 49 microsoft/netvsc 50 + mucse/rnpgbe 50 51 neterion/s2io 51 52 netronome/nfp 52 53 pensando/ionic
+17
Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + =========================================================== 4 + Linux Base Driver for MUCSE(R) Gigabit PCI Express Adapters 5 + =========================================================== 6 + 7 + Contents 8 + ======== 9 + 10 + - Identifying Your Adapter 11 + 12 + Identifying Your Adapter 13 + ======================== 14 + The driver is compatible with devices based on the following: 15 + 16 + * MUCSE(R) Ethernet Controller N210 series 17 + * MUCSE(R) Ethernet Controller N500 series
+8
MAINTAINERS
··· 17610 17610 F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml 17611 17611 F: drivers/media/i2c/mt9v111.c 17612 17612 17613 + MUCSE ETHERNET DRIVER 17614 + M: Yibo Dong <dong100@mucse.com> 17615 + L: netdev@vger.kernel.org 17616 + S: Maintained 17617 + W: https://www.mucse.com/en/ 17618 + F: Documentation/networking/device_drivers/ethernet/mucse/ 17619 + F: drivers/net/ethernet/mucse/ 17620 + 17613 17621 MULTIFUNCTION DEVICES (MFD) 17614 17622 M: Lee Jones <lee@kernel.org> 17615 17623 S: Maintained
+1
drivers/net/ethernet/Kconfig
··· 129 129 source "drivers/net/ethernet/mscc/Kconfig" 130 130 source "drivers/net/ethernet/microsoft/Kconfig" 131 131 source "drivers/net/ethernet/moxa/Kconfig" 132 + source "drivers/net/ethernet/mucse/Kconfig" 132 133 source "drivers/net/ethernet/myricom/Kconfig" 133 134 134 135 config FEALNX
+1
drivers/net/ethernet/Makefile
··· 65 65 obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ 66 66 obj-$(CONFIG_NET_VENDOR_MICROSEMI) += mscc/ 67 67 obj-$(CONFIG_NET_VENDOR_MOXART) += moxa/ 68 + obj-$(CONFIG_NET_VENDOR_MUCSE) += mucse/ 68 69 obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ 69 70 obj-$(CONFIG_FEALNX) += fealnx.o 70 71 obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/
+33
drivers/net/ethernet/mucse/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + # Mucse network device configuration 4 + # 5 + 6 + config NET_VENDOR_MUCSE 7 + bool "Mucse devices" 8 + default y 9 + help 10 + If you have a network (Ethernet) card from Mucse(R), say Y. 11 + 12 + Note that the answer to this question doesn't directly affect the 13 + kernel: saying N will just cause the configurator to skip all 14 + the questions about Mucse(R) cards. If you say Y, you will 15 + be asked for your specific card in the following questions. 16 + 17 + if NET_VENDOR_MUCSE 18 + 19 + config MGBE 20 + tristate "Mucse(R) 1GbE PCI Express adapters support" 21 + depends on PCI 22 + help 23 + This driver supports Mucse(R) 1GbE PCI Express family of 24 + adapters. 25 + 26 + More specific information on configuring the driver is in 27 + <file:Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.rst>. 28 + 29 + To compile this driver as a module, choose M here. The module 30 + will be called rnpgbe. 31 + 32 + endif # NET_VENDOR_MUCSE 33 +
+7
drivers/net/ethernet/mucse/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright(c) 2020 - 2025 MUCSE Corporation. 3 + # 4 + # Makefile for the MUCSE(R) network device drivers 5 + # 6 + 7 + obj-$(CONFIG_MGBE) += rnpgbe/
+11
drivers/net/ethernet/mucse/rnpgbe/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright(c) 2020 - 2025 MUCSE Corporation. 3 + # 4 + # Makefile for the MUCSE(R) 1GbE PCI Express ethernet driver 5 + # 6 + 7 + obj-$(CONFIG_MGBE) += rnpgbe.o 8 + rnpgbe-objs := rnpgbe_main.o\ 9 + rnpgbe_chip.o\ 10 + rnpgbe_mbx.o\ 11 + rnpgbe_mbx_fw.o
+71
drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #ifndef _RNPGBE_H 5 + #define _RNPGBE_H 6 + 7 + #include <linux/types.h> 8 + #include <linux/mutex.h> 9 + 10 + enum rnpgbe_boards { 11 + board_n500, 12 + board_n210 13 + }; 14 + 15 + struct mucse_mbx_info { 16 + u32 timeout_us; 17 + u32 delay_us; 18 + u16 fw_req; 19 + u16 fw_ack; 20 + /* lock for only one use mbx */ 21 + struct mutex lock; 22 + /* fw <--> pf mbx */ 23 + u32 fwpf_shm_base; 24 + u32 pf2fw_mbx_ctrl; 25 + u32 fwpf_mbx_mask; 26 + u32 fwpf_ctrl_base; 27 + }; 28 + 29 + /* Enum for firmware notification modes, 30 + * more modes (e.g., portup, link_report) will be added in future 31 + **/ 32 + enum { 33 + mucse_fw_powerup, 34 + }; 35 + 36 + struct mucse_hw { 37 + void __iomem *hw_addr; 38 + struct pci_dev *pdev; 39 + struct mucse_mbx_info mbx; 40 + int port; 41 + u8 pfvfnum; 42 + }; 43 + 44 + struct mucse_stats { 45 + u64 tx_dropped; 46 + }; 47 + 48 + struct mucse { 49 + struct net_device *netdev; 50 + struct pci_dev *pdev; 51 + struct mucse_hw hw; 52 + struct mucse_stats stats; 53 + }; 54 + 55 + int rnpgbe_get_permanent_mac(struct mucse_hw *hw, u8 *perm_addr); 56 + int rnpgbe_reset_hw(struct mucse_hw *hw); 57 + int rnpgbe_send_notify(struct mucse_hw *hw, 58 + bool enable, 59 + int mode); 60 + int rnpgbe_init_hw(struct mucse_hw *hw, int board_type); 61 + 62 + /* Device IDs */ 63 + #define PCI_VENDOR_ID_MUCSE 0x8848 64 + #define RNPGBE_DEVICE_ID_N500_QUAD_PORT 0x8308 65 + #define RNPGBE_DEVICE_ID_N500_DUAL_PORT 0x8318 66 + #define RNPGBE_DEVICE_ID_N210 0x8208 67 + #define RNPGBE_DEVICE_ID_N210L 0x820a 68 + 69 + #define mucse_hw_wr32(hw, reg, val) \ 70 + writel((val), (hw)->hw_addr + (reg)) 71 + #endif /* _RNPGBE_H */
+143
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #include <linux/pci.h> 5 + #include <linux/errno.h> 6 + #include <linux/etherdevice.h> 7 + 8 + #include "rnpgbe.h" 9 + #include "rnpgbe_hw.h" 10 + #include "rnpgbe_mbx.h" 11 + #include "rnpgbe_mbx_fw.h" 12 + 13 + /** 14 + * rnpgbe_get_permanent_mac - Get permanent mac 15 + * @hw: hw information structure 16 + * @perm_addr: pointer to store perm_addr 17 + * 18 + * rnpgbe_get_permanent_mac tries to get mac from hw 19 + * 20 + * Return: 0 on success, negative errno on failure 21 + **/ 22 + int rnpgbe_get_permanent_mac(struct mucse_hw *hw, u8 *perm_addr) 23 + { 24 + struct device *dev = &hw->pdev->dev; 25 + int err; 26 + 27 + err = mucse_mbx_get_macaddr(hw, hw->pfvfnum, perm_addr, hw->port); 28 + if (err) { 29 + dev_err(dev, "Failed to get MAC from FW %d\n", err); 30 + return err; 31 + } 32 + 33 + if (!is_valid_ether_addr(perm_addr)) { 34 + dev_err(dev, "Failed to get valid MAC from FW\n"); 35 + return -EINVAL; 36 + } 37 + 38 + return 0; 39 + } 40 + 41 + /** 42 + * rnpgbe_reset_hw - Do a hardware reset 43 + * @hw: hw information structure 44 + * 45 + * rnpgbe_reset_hw calls fw to do a hardware 46 + * reset, and cleans some regs to default. 47 + * 48 + * Return: 0 on success, negative errno on failure 49 + **/ 50 + int rnpgbe_reset_hw(struct mucse_hw *hw) 51 + { 52 + mucse_hw_wr32(hw, RNPGBE_DMA_AXI_EN, 0); 53 + return mucse_mbx_reset_hw(hw); 54 + } 55 + 56 + /** 57 + * rnpgbe_send_notify - Echo fw status 58 + * @hw: hw information structure 59 + * @enable: true or false status 60 + * @mode: status mode 61 + * 62 + * Return: 0 on success, negative errno on failure 63 + **/ 64 + int rnpgbe_send_notify(struct mucse_hw *hw, 65 + bool enable, 66 + int mode) 67 + { 68 + int err; 69 + /* Keep switch struct to support more modes in the future */ 70 + switch (mode) { 71 + case mucse_fw_powerup: 72 + err = mucse_mbx_powerup(hw, enable); 73 + break; 74 + default: 75 + err = -EINVAL; 76 + } 77 + 78 + return err; 79 + } 80 + 81 + /** 82 + * rnpgbe_init_n500 - Setup n500 hw info 83 + * @hw: hw information structure 84 + * 85 + * rnpgbe_init_n500 initializes all private 86 + * structure for n500 87 + **/ 88 + static void rnpgbe_init_n500(struct mucse_hw *hw) 89 + { 90 + struct mucse_mbx_info *mbx = &hw->mbx; 91 + 92 + mbx->fwpf_ctrl_base = MUCSE_N500_FWPF_CTRL_BASE; 93 + mbx->fwpf_shm_base = MUCSE_N500_FWPF_SHM_BASE; 94 + } 95 + 96 + /** 97 + * rnpgbe_init_n210 - Setup n210 hw info 98 + * @hw: hw information structure 99 + * 100 + * rnpgbe_init_n210 initializes all private 101 + * structure for n210 102 + **/ 103 + static void rnpgbe_init_n210(struct mucse_hw *hw) 104 + { 105 + struct mucse_mbx_info *mbx = &hw->mbx; 106 + 107 + mbx->fwpf_ctrl_base = MUCSE_N210_FWPF_CTRL_BASE; 108 + mbx->fwpf_shm_base = MUCSE_N210_FWPF_SHM_BASE; 109 + } 110 + 111 + /** 112 + * rnpgbe_init_hw - Setup hw info according to board_type 113 + * @hw: hw information structure 114 + * @board_type: board type 115 + * 116 + * rnpgbe_init_hw initializes all hw data 117 + * 118 + * Return: 0 on success, -EINVAL on failure 119 + **/ 120 + int rnpgbe_init_hw(struct mucse_hw *hw, int board_type) 121 + { 122 + struct mucse_mbx_info *mbx = &hw->mbx; 123 + 124 + hw->port = 0; 125 + 126 + mbx->pf2fw_mbx_ctrl = MUCSE_GBE_PFFW_MBX_CTRL_OFFSET; 127 + mbx->fwpf_mbx_mask = MUCSE_GBE_FWPF_MBX_MASK_OFFSET; 128 + 129 + switch (board_type) { 130 + case board_n500: 131 + rnpgbe_init_n500(hw); 132 + break; 133 + case board_n210: 134 + rnpgbe_init_n210(hw); 135 + break; 136 + default: 137 + return -EINVAL; 138 + } 139 + /* init_params with mbx base */ 140 + mucse_init_mbx_params_pf(hw); 141 + 142 + return 0; 143 + }
+17
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #ifndef _RNPGBE_HW_H 5 + #define _RNPGBE_HW_H 6 + 7 + #define MUCSE_N500_FWPF_CTRL_BASE 0x28b00 8 + #define MUCSE_N500_FWPF_SHM_BASE 0x2d000 9 + #define MUCSE_GBE_PFFW_MBX_CTRL_OFFSET 0x5500 10 + #define MUCSE_GBE_FWPF_MBX_MASK_OFFSET 0x5700 11 + #define MUCSE_N210_FWPF_CTRL_BASE 0x29400 12 + #define MUCSE_N210_FWPF_SHM_BASE 0x2d900 13 + 14 + #define RNPGBE_DMA_AXI_EN 0x0010 15 + 16 + #define RNPGBE_MAX_QUEUES 8 17 + #endif /* _RNPGBE_HW_H */
+320
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #include <linux/pci.h> 5 + #include <net/rtnetlink.h> 6 + #include <linux/etherdevice.h> 7 + 8 + #include "rnpgbe.h" 9 + #include "rnpgbe_hw.h" 10 + #include "rnpgbe_mbx_fw.h" 11 + 12 + static const char rnpgbe_driver_name[] = "rnpgbe"; 13 + 14 + /* rnpgbe_pci_tbl - PCI Device ID Table 15 + * 16 + * { PCI_VDEVICE(Vendor ID, Device ID), 17 + * private_data (used for different hw chip) } 18 + */ 19 + static struct pci_device_id rnpgbe_pci_tbl[] = { 20 + { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N210), board_n210 }, 21 + { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N210L), board_n210 }, 22 + { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N500_DUAL_PORT), board_n500 }, 23 + { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N500_QUAD_PORT), board_n500 }, 24 + /* required last entry */ 25 + {0, }, 26 + }; 27 + 28 + /** 29 + * rnpgbe_open - Called when a network interface is made active 30 + * @netdev: network interface device structure 31 + * 32 + * The open entry point is called when a network interface is made 33 + * active by the system (IFF_UP). 34 + * 35 + * Return: 0 36 + **/ 37 + static int rnpgbe_open(struct net_device *netdev) 38 + { 39 + return 0; 40 + } 41 + 42 + /** 43 + * rnpgbe_close - Disables a network interface 44 + * @netdev: network interface device structure 45 + * 46 + * The close entry point is called when an interface is de-activated 47 + * by the OS. 48 + * 49 + * Return: 0, this is not allowed to fail 50 + **/ 51 + static int rnpgbe_close(struct net_device *netdev) 52 + { 53 + return 0; 54 + } 55 + 56 + /** 57 + * rnpgbe_xmit_frame - Send a skb to driver 58 + * @skb: skb structure to be sent 59 + * @netdev: network interface device structure 60 + * 61 + * Return: NETDEV_TX_OK 62 + **/ 63 + static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, 64 + struct net_device *netdev) 65 + { 66 + struct mucse *mucse = netdev_priv(netdev); 67 + 68 + dev_kfree_skb_any(skb); 69 + mucse->stats.tx_dropped++; 70 + 71 + return NETDEV_TX_OK; 72 + } 73 + 74 + static const struct net_device_ops rnpgbe_netdev_ops = { 75 + .ndo_open = rnpgbe_open, 76 + .ndo_stop = rnpgbe_close, 77 + .ndo_start_xmit = rnpgbe_xmit_frame, 78 + }; 79 + 80 + /** 81 + * rnpgbe_add_adapter - Add netdev for this pci_dev 82 + * @pdev: PCI device information structure 83 + * @board_type: board type 84 + * 85 + * rnpgbe_add_adapter initializes a netdev for this pci_dev 86 + * structure. Initializes Bar map, private structure, and a 87 + * hardware reset occur. 88 + * 89 + * Return: 0 on success, negative errno on failure 90 + **/ 91 + static int rnpgbe_add_adapter(struct pci_dev *pdev, 92 + int board_type) 93 + { 94 + struct net_device *netdev; 95 + u8 perm_addr[ETH_ALEN]; 96 + void __iomem *hw_addr; 97 + struct mucse *mucse; 98 + struct mucse_hw *hw; 99 + int err, err_notify; 100 + 101 + netdev = alloc_etherdev_mq(sizeof(struct mucse), RNPGBE_MAX_QUEUES); 102 + if (!netdev) 103 + return -ENOMEM; 104 + 105 + SET_NETDEV_DEV(netdev, &pdev->dev); 106 + mucse = netdev_priv(netdev); 107 + mucse->netdev = netdev; 108 + mucse->pdev = pdev; 109 + pci_set_drvdata(pdev, mucse); 110 + 111 + hw = &mucse->hw; 112 + hw_addr = devm_ioremap(&pdev->dev, 113 + pci_resource_start(pdev, 2), 114 + pci_resource_len(pdev, 2)); 115 + if (!hw_addr) { 116 + err = -EIO; 117 + goto err_free_net; 118 + } 119 + 120 + hw->hw_addr = hw_addr; 121 + hw->pdev = pdev; 122 + 123 + err = rnpgbe_init_hw(hw, board_type); 124 + if (err) { 125 + dev_err(&pdev->dev, "Init hw err %d\n", err); 126 + goto err_free_net; 127 + } 128 + /* Step 1: Send power-up notification to firmware (no response expected) 129 + * This informs firmware to initialize hardware power state, but 130 + * firmware only acknowledges receipt without returning data. Must be 131 + * done before synchronization as firmware may be in low-power idle 132 + * state initially. 133 + */ 134 + err_notify = rnpgbe_send_notify(hw, true, mucse_fw_powerup); 135 + if (err_notify) { 136 + dev_warn(&pdev->dev, "Send powerup to hw failed %d\n", 137 + err_notify); 138 + dev_warn(&pdev->dev, "Maybe low performance\n"); 139 + } 140 + /* Step 2: Synchronize mailbox communication with firmware (requires 141 + * response) After power-up, confirm firmware is ready to process 142 + * requests with responses. This ensures subsequent request/response 143 + * interactions work reliably. 144 + */ 145 + err = mucse_mbx_sync_fw(hw); 146 + if (err) { 147 + dev_err(&pdev->dev, "Sync fw failed! %d\n", err); 148 + goto err_powerdown; 149 + } 150 + 151 + netdev->netdev_ops = &rnpgbe_netdev_ops; 152 + err = rnpgbe_reset_hw(hw); 153 + if (err) { 154 + dev_err(&pdev->dev, "Hw reset failed %d\n", err); 155 + goto err_powerdown; 156 + } 157 + 158 + err = rnpgbe_get_permanent_mac(hw, perm_addr); 159 + if (!err) { 160 + eth_hw_addr_set(netdev, perm_addr); 161 + } else if (err == -EINVAL) { 162 + dev_warn(&pdev->dev, "Using random MAC\n"); 163 + eth_hw_addr_random(netdev); 164 + } else if (err) { 165 + dev_err(&pdev->dev, "get perm_addr failed %d\n", err); 166 + goto err_powerdown; 167 + } 168 + 169 + err = register_netdev(netdev); 170 + if (err) 171 + goto err_powerdown; 172 + 173 + return 0; 174 + err_powerdown: 175 + /* notify powerdown only powerup ok */ 176 + if (!err_notify) { 177 + err_notify = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 178 + if (err_notify) 179 + dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", 180 + err_notify); 181 + } 182 + err_free_net: 183 + free_netdev(netdev); 184 + return err; 185 + } 186 + 187 + /** 188 + * rnpgbe_probe - Device initialization routine 189 + * @pdev: PCI device information struct 190 + * @id: entry in rnpgbe_pci_tbl 191 + * 192 + * rnpgbe_probe initializes a PF adapter identified by a pci_dev 193 + * structure. 194 + * 195 + * Return: 0 on success, negative errno on failure 196 + **/ 197 + static int rnpgbe_probe(struct pci_dev *pdev, const struct pci_device_id *id) 198 + { 199 + int board_type = id->driver_data; 200 + int err; 201 + 202 + err = pci_enable_device_mem(pdev); 203 + if (err) 204 + return err; 205 + 206 + err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(56)); 207 + if (err) { 208 + dev_err(&pdev->dev, 209 + "No usable DMA configuration, aborting %d\n", err); 210 + goto err_disable_dev; 211 + } 212 + 213 + err = pci_request_mem_regions(pdev, rnpgbe_driver_name); 214 + if (err) { 215 + dev_err(&pdev->dev, 216 + "pci_request_selected_regions failed %d\n", err); 217 + goto err_disable_dev; 218 + } 219 + 220 + pci_set_master(pdev); 221 + err = pci_save_state(pdev); 222 + if (err) { 223 + dev_err(&pdev->dev, "pci_save_state failed %d\n", err); 224 + goto err_free_regions; 225 + } 226 + 227 + err = rnpgbe_add_adapter(pdev, board_type); 228 + if (err) 229 + goto err_free_regions; 230 + 231 + return 0; 232 + err_free_regions: 233 + pci_release_mem_regions(pdev); 234 + err_disable_dev: 235 + pci_disable_device(pdev); 236 + return err; 237 + } 238 + 239 + /** 240 + * rnpgbe_rm_adapter - Remove netdev for this mucse structure 241 + * @pdev: PCI device information struct 242 + * 243 + * rnpgbe_rm_adapter remove a netdev for this mucse structure 244 + **/ 245 + static void rnpgbe_rm_adapter(struct pci_dev *pdev) 246 + { 247 + struct mucse *mucse = pci_get_drvdata(pdev); 248 + struct mucse_hw *hw = &mucse->hw; 249 + struct net_device *netdev; 250 + int err; 251 + 252 + if (!mucse) 253 + return; 254 + netdev = mucse->netdev; 255 + unregister_netdev(netdev); 256 + err = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 257 + if (err) 258 + dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", err); 259 + free_netdev(netdev); 260 + } 261 + 262 + /** 263 + * rnpgbe_remove - Device removal routine 264 + * @pdev: PCI device information struct 265 + * 266 + * rnpgbe_remove is called by the PCI subsystem to alert the driver 267 + * that it should release a PCI device. This could be caused by a 268 + * Hot-Plug event, or because the driver is going to be removed from 269 + * memory. 270 + **/ 271 + static void rnpgbe_remove(struct pci_dev *pdev) 272 + { 273 + rnpgbe_rm_adapter(pdev); 274 + pci_release_mem_regions(pdev); 275 + pci_disable_device(pdev); 276 + } 277 + 278 + /** 279 + * rnpgbe_dev_shutdown - Device shutdown routine 280 + * @pdev: PCI device information struct 281 + **/ 282 + static void rnpgbe_dev_shutdown(struct pci_dev *pdev) 283 + { 284 + struct mucse *mucse = pci_get_drvdata(pdev); 285 + struct net_device *netdev = mucse->netdev; 286 + 287 + rtnl_lock(); 288 + netif_device_detach(netdev); 289 + if (netif_running(netdev)) 290 + rnpgbe_close(netdev); 291 + rtnl_unlock(); 292 + pci_disable_device(pdev); 293 + } 294 + 295 + /** 296 + * rnpgbe_shutdown - Device shutdown routine 297 + * @pdev: PCI device information struct 298 + * 299 + * rnpgbe_shutdown is called by the PCI subsystem to alert the driver 300 + * that os shutdown. Device should setup wakeup state here. 301 + **/ 302 + static void rnpgbe_shutdown(struct pci_dev *pdev) 303 + { 304 + rnpgbe_dev_shutdown(pdev); 305 + } 306 + 307 + static struct pci_driver rnpgbe_driver = { 308 + .name = rnpgbe_driver_name, 309 + .id_table = rnpgbe_pci_tbl, 310 + .probe = rnpgbe_probe, 311 + .remove = rnpgbe_remove, 312 + .shutdown = rnpgbe_shutdown, 313 + }; 314 + 315 + module_pci_driver(rnpgbe_driver); 316 + 317 + MODULE_DEVICE_TABLE(pci, rnpgbe_pci_tbl); 318 + MODULE_AUTHOR("Yibo Dong, <dong100@mucse.com>"); 319 + MODULE_DESCRIPTION("Mucse(R) 1 Gigabit PCI Express Network Driver"); 320 + MODULE_LICENSE("GPL");
+406
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2022 - 2025 Mucse Corporation. */ 3 + 4 + #include <linux/errno.h> 5 + #include <linux/bitfield.h> 6 + #include <linux/iopoll.h> 7 + 8 + #include "rnpgbe_mbx.h" 9 + 10 + /** 11 + * mbx_data_rd32 - Reads reg with base mbx->fwpf_shm_base 12 + * @mbx: pointer to the MBX structure 13 + * @reg: register offset 14 + * 15 + * Return: register value 16 + **/ 17 + static u32 mbx_data_rd32(struct mucse_mbx_info *mbx, u32 reg) 18 + { 19 + struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 20 + 21 + return readl(hw->hw_addr + mbx->fwpf_shm_base + reg); 22 + } 23 + 24 + /** 25 + * mbx_data_wr32 - Writes value to reg with base mbx->fwpf_shm_base 26 + * @mbx: pointer to the MBX structure 27 + * @reg: register offset 28 + * @value: value to be written 29 + * 30 + **/ 31 + static void mbx_data_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value) 32 + { 33 + struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 34 + 35 + writel(value, hw->hw_addr + mbx->fwpf_shm_base + reg); 36 + } 37 + 38 + /** 39 + * mbx_ctrl_rd32 - Reads reg with base mbx->fwpf_ctrl_base 40 + * @mbx: pointer to the MBX structure 41 + * @reg: register offset 42 + * 43 + * Return: register value 44 + **/ 45 + static u32 mbx_ctrl_rd32(struct mucse_mbx_info *mbx, u32 reg) 46 + { 47 + struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 48 + 49 + return readl(hw->hw_addr + mbx->fwpf_ctrl_base + reg); 50 + } 51 + 52 + /** 53 + * mbx_ctrl_wr32 - Writes value to reg with base mbx->fwpf_ctrl_base 54 + * @mbx: pointer to the MBX structure 55 + * @reg: register offset 56 + * @value: value to be written 57 + * 58 + **/ 59 + static void mbx_ctrl_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value) 60 + { 61 + struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 62 + 63 + writel(value, hw->hw_addr + mbx->fwpf_ctrl_base + reg); 64 + } 65 + 66 + /** 67 + * mucse_mbx_get_lock_pf - Write ctrl and read back lock status 68 + * @hw: pointer to the HW structure 69 + * 70 + * Return: register value after write 71 + **/ 72 + static u32 mucse_mbx_get_lock_pf(struct mucse_hw *hw) 73 + { 74 + struct mucse_mbx_info *mbx = &hw->mbx; 75 + u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx); 76 + 77 + mbx_ctrl_wr32(mbx, reg, MUCSE_MBX_PFU); 78 + 79 + return mbx_ctrl_rd32(mbx, reg); 80 + } 81 + 82 + /** 83 + * mucse_obtain_mbx_lock_pf - Obtain mailbox lock 84 + * @hw: pointer to the HW structure 85 + * 86 + * Pair with mucse_release_mbx_lock_pf() 87 + * This function maybe used in an irq handler. 88 + * 89 + * Return: 0 on success, negative errno on failure 90 + **/ 91 + static int mucse_obtain_mbx_lock_pf(struct mucse_hw *hw) 92 + { 93 + struct mucse_mbx_info *mbx = &hw->mbx; 94 + u32 val; 95 + 96 + return read_poll_timeout_atomic(mucse_mbx_get_lock_pf, 97 + val, val & MUCSE_MBX_PFU, 98 + mbx->delay_us, 99 + mbx->timeout_us, 100 + false, hw); 101 + } 102 + 103 + /** 104 + * mucse_release_mbx_lock_pf - Release mailbox lock 105 + * @hw: pointer to the HW structure 106 + * @req: send a request or not 107 + * 108 + * Pair with mucse_obtain_mbx_lock_pf(): 109 + * - Releases the mailbox lock by clearing MUCSE_MBX_PFU bit 110 + * - Simultaneously sends the request by setting MUCSE_MBX_REQ bit 111 + * if req is true 112 + * (Both bits are in the same mailbox control register, 113 + * so operations are combined) 114 + **/ 115 + static void mucse_release_mbx_lock_pf(struct mucse_hw *hw, bool req) 116 + { 117 + struct mucse_mbx_info *mbx = &hw->mbx; 118 + u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx); 119 + 120 + mbx_ctrl_wr32(mbx, reg, req ? MUCSE_MBX_REQ : 0); 121 + } 122 + 123 + /** 124 + * mucse_mbx_get_fwreq - Read fw req from reg 125 + * @mbx: pointer to the mbx structure 126 + * 127 + * Return: the fwreq value 128 + **/ 129 + static u16 mucse_mbx_get_fwreq(struct mucse_mbx_info *mbx) 130 + { 131 + u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 132 + 133 + return FIELD_GET(GENMASK_U32(15, 0), val); 134 + } 135 + 136 + /** 137 + * mucse_mbx_inc_pf_ack - Increase ack 138 + * @hw: pointer to the HW structure 139 + * 140 + * mucse_mbx_inc_pf_ack reads pf_ack from hw, then writes 141 + * new value back after increase 142 + **/ 143 + static void mucse_mbx_inc_pf_ack(struct mucse_hw *hw) 144 + { 145 + struct mucse_mbx_info *mbx = &hw->mbx; 146 + u16 ack; 147 + u32 val; 148 + 149 + val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT); 150 + ack = FIELD_GET(GENMASK_U32(31, 16), val); 151 + ack++; 152 + val &= ~GENMASK_U32(31, 16); 153 + val |= FIELD_PREP(GENMASK_U32(31, 16), ack); 154 + mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val); 155 + } 156 + 157 + /** 158 + * mucse_read_mbx_pf - Read a message from the mailbox 159 + * @hw: pointer to the HW structure 160 + * @msg: the message buffer 161 + * @size: length of buffer 162 + * 163 + * mucse_read_mbx_pf copies a message from the mbx buffer to the caller's 164 + * memory buffer. The presumption is that the caller knows that there was 165 + * a message due to a fw request so no polling for message is needed. 166 + * 167 + * Return: 0 on success, negative errno on failure 168 + **/ 169 + static int mucse_read_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size) 170 + { 171 + const int size_in_words = size / sizeof(u32); 172 + struct mucse_mbx_info *mbx = &hw->mbx; 173 + int err; 174 + 175 + err = mucse_obtain_mbx_lock_pf(hw); 176 + if (err) 177 + return err; 178 + 179 + for (int i = 0; i < size_in_words; i++) 180 + msg[i] = mbx_data_rd32(mbx, MUCSE_MBX_FWPF_SHM + 4 * i); 181 + /* Hw needs write data_reg at last */ 182 + mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM, 0); 183 + /* flush reqs as we have read this request data */ 184 + hw->mbx.fw_req = mucse_mbx_get_fwreq(mbx); 185 + mucse_mbx_inc_pf_ack(hw); 186 + mucse_release_mbx_lock_pf(hw, false); 187 + 188 + return 0; 189 + } 190 + 191 + /** 192 + * mucse_check_for_msg_pf - Check to see if the fw has sent mail 193 + * @hw: pointer to the HW structure 194 + * 195 + * Return: 0 if the fw has set the Status bit or else -EIO 196 + **/ 197 + static int mucse_check_for_msg_pf(struct mucse_hw *hw) 198 + { 199 + struct mucse_mbx_info *mbx = &hw->mbx; 200 + u16 fw_req; 201 + 202 + fw_req = mucse_mbx_get_fwreq(mbx); 203 + /* chip's register is reset to 0 when rc send reset 204 + * mbx command. Return -EIO if in this state, others 205 + * fw == hw->mbx.fw_req means no new msg. 206 + **/ 207 + if (fw_req == 0 || fw_req == hw->mbx.fw_req) 208 + return -EIO; 209 + 210 + return 0; 211 + } 212 + 213 + /** 214 + * mucse_poll_for_msg - Wait for message notification 215 + * @hw: pointer to the HW structure 216 + * 217 + * Return: 0 on success, negative errno on failure 218 + **/ 219 + static int mucse_poll_for_msg(struct mucse_hw *hw) 220 + { 221 + struct mucse_mbx_info *mbx = &hw->mbx; 222 + int val; 223 + 224 + return read_poll_timeout(mucse_check_for_msg_pf, 225 + val, !val, mbx->delay_us, 226 + mbx->timeout_us, 227 + false, hw); 228 + } 229 + 230 + /** 231 + * mucse_poll_and_read_mbx - Wait for message notification and receive message 232 + * @hw: pointer to the HW structure 233 + * @msg: the message buffer 234 + * @size: length of buffer 235 + * 236 + * Return: 0 if it successfully received a message notification and 237 + * copied it into the receive buffer, negative errno on failure 238 + **/ 239 + int mucse_poll_and_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size) 240 + { 241 + int err; 242 + 243 + err = mucse_poll_for_msg(hw); 244 + if (err) 245 + return err; 246 + 247 + return mucse_read_mbx_pf(hw, msg, size); 248 + } 249 + 250 + /** 251 + * mucse_mbx_get_fwack - Read fw ack from reg 252 + * @mbx: pointer to the MBX structure 253 + * 254 + * Return: the fwack value 255 + **/ 256 + static u16 mucse_mbx_get_fwack(struct mucse_mbx_info *mbx) 257 + { 258 + u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 259 + 260 + return FIELD_GET(GENMASK_U32(31, 16), val); 261 + } 262 + 263 + /** 264 + * mucse_mbx_inc_pf_req - Increase req 265 + * @hw: pointer to the HW structure 266 + * 267 + * mucse_mbx_inc_pf_req reads pf_req from hw, then writes 268 + * new value back after increase 269 + **/ 270 + static void mucse_mbx_inc_pf_req(struct mucse_hw *hw) 271 + { 272 + struct mucse_mbx_info *mbx = &hw->mbx; 273 + u16 req; 274 + u32 val; 275 + 276 + val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT); 277 + req = FIELD_GET(GENMASK_U32(15, 0), val); 278 + req++; 279 + val &= ~GENMASK_U32(15, 0); 280 + val |= FIELD_PREP(GENMASK_U32(15, 0), req); 281 + mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val); 282 + } 283 + 284 + /** 285 + * mucse_write_mbx_pf - Place a message in the mailbox 286 + * @hw: pointer to the HW structure 287 + * @msg: the message buffer 288 + * @size: length of buffer 289 + * 290 + * Return: 0 if it successfully copied message into the buffer, 291 + * negative errno on failure 292 + **/ 293 + static int mucse_write_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size) 294 + { 295 + const int size_in_words = size / sizeof(u32); 296 + struct mucse_mbx_info *mbx = &hw->mbx; 297 + int err; 298 + 299 + err = mucse_obtain_mbx_lock_pf(hw); 300 + if (err) 301 + return err; 302 + 303 + for (int i = 0; i < size_in_words; i++) 304 + mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM + i * 4, msg[i]); 305 + 306 + /* flush acks as we are overwriting the message buffer */ 307 + hw->mbx.fw_ack = mucse_mbx_get_fwack(mbx); 308 + mucse_mbx_inc_pf_req(hw); 309 + mucse_release_mbx_lock_pf(hw, true); 310 + 311 + return 0; 312 + } 313 + 314 + /** 315 + * mucse_check_for_ack_pf - Check to see if the fw has ACKed 316 + * @hw: pointer to the HW structure 317 + * 318 + * Return: 0 if the fw has set the Status bit or else -EIO 319 + **/ 320 + static int mucse_check_for_ack_pf(struct mucse_hw *hw) 321 + { 322 + struct mucse_mbx_info *mbx = &hw->mbx; 323 + u16 fw_ack; 324 + 325 + fw_ack = mucse_mbx_get_fwack(mbx); 326 + /* chip's register is reset to 0 when rc send reset 327 + * mbx command. Return -EIO if in this state, others 328 + * fw_ack == hw->mbx.fw_ack means no new ack. 329 + **/ 330 + if (fw_ack == 0 || fw_ack == hw->mbx.fw_ack) 331 + return -EIO; 332 + 333 + return 0; 334 + } 335 + 336 + /** 337 + * mucse_poll_for_ack - Wait for message acknowledgment 338 + * @hw: pointer to the HW structure 339 + * 340 + * Return: 0 if it successfully received a message acknowledgment, 341 + * else negative errno 342 + **/ 343 + static int mucse_poll_for_ack(struct mucse_hw *hw) 344 + { 345 + struct mucse_mbx_info *mbx = &hw->mbx; 346 + int val; 347 + 348 + return read_poll_timeout(mucse_check_for_ack_pf, 349 + val, !val, mbx->delay_us, 350 + mbx->timeout_us, 351 + false, hw); 352 + } 353 + 354 + /** 355 + * mucse_write_and_wait_ack_mbx - Write a message to the mailbox, wait for ack 356 + * @hw: pointer to the HW structure 357 + * @msg: the message buffer 358 + * @size: length of buffer 359 + * 360 + * Return: 0 if it successfully copied message into the buffer and 361 + * received an ack to that message within delay * timeout_cnt period 362 + **/ 363 + int mucse_write_and_wait_ack_mbx(struct mucse_hw *hw, u32 *msg, u16 size) 364 + { 365 + int err; 366 + 367 + err = mucse_write_mbx_pf(hw, msg, size); 368 + if (err) 369 + return err; 370 + 371 + return mucse_poll_for_ack(hw); 372 + } 373 + 374 + /** 375 + * mucse_mbx_reset - Reset mbx info, sync info from regs 376 + * @hw: pointer to the HW structure 377 + * 378 + * mucse_mbx_reset resets all mbx variables to default. 379 + **/ 380 + static void mucse_mbx_reset(struct mucse_hw *hw) 381 + { 382 + struct mucse_mbx_info *mbx = &hw->mbx; 383 + u32 val; 384 + 385 + val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 386 + hw->mbx.fw_req = FIELD_GET(GENMASK_U32(15, 0), val); 387 + hw->mbx.fw_ack = FIELD_GET(GENMASK_U32(31, 16), val); 388 + mbx_ctrl_wr32(mbx, MUCSE_MBX_PF2FW_CTRL(mbx), 0); 389 + mbx_ctrl_wr32(mbx, MUCSE_MBX_FWPF_MASK(mbx), GENMASK_U32(31, 16)); 390 + } 391 + 392 + /** 393 + * mucse_init_mbx_params_pf - Set initial values for pf mailbox 394 + * @hw: pointer to the HW structure 395 + * 396 + * Initializes the hw->mbx struct to correct values for pf mailbox 397 + */ 398 + void mucse_init_mbx_params_pf(struct mucse_hw *hw) 399 + { 400 + struct mucse_mbx_info *mbx = &hw->mbx; 401 + 402 + mbx->delay_us = 100; 403 + mbx->timeout_us = 4 * USEC_PER_SEC; 404 + mutex_init(&mbx->lock); 405 + mucse_mbx_reset(hw); 406 + }
+20
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #ifndef _RNPGBE_MBX_H 5 + #define _RNPGBE_MBX_H 6 + 7 + #include "rnpgbe.h" 8 + 9 + #define MUCSE_MBX_FW2PF_CNT 0 10 + #define MUCSE_MBX_PF2FW_CNT 4 11 + #define MUCSE_MBX_FWPF_SHM 8 12 + #define MUCSE_MBX_PF2FW_CTRL(mbx) ((mbx)->pf2fw_mbx_ctrl) 13 + #define MUCSE_MBX_FWPF_MASK(mbx) ((mbx)->fwpf_mbx_mask) 14 + #define MUCSE_MBX_REQ BIT(0) /* Request a req to mailbox */ 15 + #define MUCSE_MBX_PFU BIT(3) /* PF owns the mailbox buffer */ 16 + 17 + int mucse_write_and_wait_ack_mbx(struct mucse_hw *hw, u32 *msg, u16 size); 18 + void mucse_init_mbx_params_pf(struct mucse_hw *hw); 19 + int mucse_poll_and_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size); 20 + #endif /* _RNPGBE_MBX_H */
+191
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #include <linux/if_ether.h> 5 + #include <linux/bitfield.h> 6 + 7 + #include "rnpgbe.h" 8 + #include "rnpgbe_mbx.h" 9 + #include "rnpgbe_mbx_fw.h" 10 + 11 + /** 12 + * mucse_fw_send_cmd_wait_resp - Send cmd req and wait for response 13 + * @hw: pointer to the HW structure 14 + * @req: pointer to the cmd req structure 15 + * @reply: pointer to the fw reply structure 16 + * 17 + * mucse_fw_send_cmd_wait_resp sends req to pf-fw mailbox and wait 18 + * reply from fw. 19 + * 20 + * Return: 0 on success, negative errno on failure 21 + **/ 22 + static int mucse_fw_send_cmd_wait_resp(struct mucse_hw *hw, 23 + struct mbx_fw_cmd_req *req, 24 + struct mbx_fw_cmd_reply *reply) 25 + { 26 + int len = le16_to_cpu(req->datalen); 27 + int retry_cnt = 3; 28 + int err; 29 + 30 + mutex_lock(&hw->mbx.lock); 31 + err = mucse_write_and_wait_ack_mbx(hw, (u32 *)req, len); 32 + if (err) 33 + goto out; 34 + do { 35 + err = mucse_poll_and_read_mbx(hw, (u32 *)reply, 36 + sizeof(*reply)); 37 + if (err) 38 + goto out; 39 + /* mucse_write_and_wait_ack_mbx return 0 means fw has 40 + * received request, wait for the expect opcode 41 + * reply with 'retry_cnt' times. 42 + */ 43 + } while (--retry_cnt >= 0 && reply->opcode != req->opcode); 44 + out: 45 + mutex_unlock(&hw->mbx.lock); 46 + if (!err && retry_cnt < 0) 47 + return -ETIMEDOUT; 48 + if (!err && reply->error_code) 49 + return -EIO; 50 + 51 + return err; 52 + } 53 + 54 + /** 55 + * mucse_mbx_get_info - Get hw info from fw 56 + * @hw: pointer to the HW structure 57 + * 58 + * mucse_mbx_get_info tries to get hw info from hw. 59 + * 60 + * Return: 0 on success, negative errno on failure 61 + **/ 62 + static int mucse_mbx_get_info(struct mucse_hw *hw) 63 + { 64 + struct mbx_fw_cmd_req req = { 65 + .datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN), 66 + .opcode = cpu_to_le16(GET_HW_INFO), 67 + }; 68 + struct mbx_fw_cmd_reply reply = {}; 69 + int err; 70 + 71 + err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply); 72 + if (!err) 73 + hw->pfvfnum = FIELD_GET(GENMASK_U16(7, 0), 74 + le16_to_cpu(reply.hw_info.pfnum)); 75 + 76 + return err; 77 + } 78 + 79 + /** 80 + * mucse_mbx_sync_fw - Try to sync with fw 81 + * @hw: pointer to the HW structure 82 + * 83 + * mucse_mbx_sync_fw tries to sync with fw. It is only called in 84 + * probe. Nothing (register network) todo if failed. 85 + * Try more times to do sync. 86 + * 87 + * Return: 0 on success, negative errno on failure 88 + **/ 89 + int mucse_mbx_sync_fw(struct mucse_hw *hw) 90 + { 91 + int try_cnt = 3; 92 + int err; 93 + 94 + do { 95 + err = mucse_mbx_get_info(hw); 96 + } while (err == -ETIMEDOUT && try_cnt--); 97 + 98 + return err; 99 + } 100 + 101 + /** 102 + * mucse_mbx_powerup - Echo fw to powerup 103 + * @hw: pointer to the HW structure 104 + * @is_powerup: true for powerup, false for powerdown 105 + * 106 + * mucse_mbx_powerup echo fw to change working frequency 107 + * to normal after received true, and reduce working frequency 108 + * if false. 109 + * 110 + * Return: 0 on success, negative errno on failure 111 + **/ 112 + int mucse_mbx_powerup(struct mucse_hw *hw, bool is_powerup) 113 + { 114 + struct mbx_fw_cmd_req req = { 115 + .datalen = cpu_to_le16(sizeof(req.powerup) + 116 + MUCSE_MBX_REQ_HDR_LEN), 117 + .opcode = cpu_to_le16(POWER_UP), 118 + .powerup = { 119 + /* fw needs this to reply correct cmd */ 120 + .version = cpu_to_le32(GENMASK_U32(31, 0)), 121 + .status = cpu_to_le32(is_powerup ? 1 : 0), 122 + }, 123 + }; 124 + int len, err; 125 + 126 + len = le16_to_cpu(req.datalen); 127 + mutex_lock(&hw->mbx.lock); 128 + err = mucse_write_and_wait_ack_mbx(hw, (u32 *)&req, len); 129 + mutex_unlock(&hw->mbx.lock); 130 + 131 + return err; 132 + } 133 + 134 + /** 135 + * mucse_mbx_reset_hw - Posts a mbx req to reset hw 136 + * @hw: pointer to the HW structure 137 + * 138 + * mucse_mbx_reset_hw posts a mbx req to firmware to reset hw. 139 + * We use mucse_fw_send_cmd_wait_resp to wait hw reset ok. 140 + * 141 + * Return: 0 on success, negative errno on failure 142 + **/ 143 + int mucse_mbx_reset_hw(struct mucse_hw *hw) 144 + { 145 + struct mbx_fw_cmd_req req = { 146 + .datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN), 147 + .opcode = cpu_to_le16(RESET_HW), 148 + }; 149 + struct mbx_fw_cmd_reply reply = {}; 150 + 151 + return mucse_fw_send_cmd_wait_resp(hw, &req, &reply); 152 + } 153 + 154 + /** 155 + * mucse_mbx_get_macaddr - Posts a mbx req to request macaddr 156 + * @hw: pointer to the HW structure 157 + * @pfvfnum: index of pf/vf num 158 + * @mac_addr: pointer to store mac_addr 159 + * @port: port index 160 + * 161 + * mucse_mbx_get_macaddr posts a mbx req to firmware to get mac_addr. 162 + * 163 + * Return: 0 on success, negative errno on failure 164 + **/ 165 + int mucse_mbx_get_macaddr(struct mucse_hw *hw, int pfvfnum, 166 + u8 *mac_addr, 167 + int port) 168 + { 169 + struct mbx_fw_cmd_req req = { 170 + .datalen = cpu_to_le16(sizeof(req.get_mac_addr) + 171 + MUCSE_MBX_REQ_HDR_LEN), 172 + .opcode = cpu_to_le16(GET_MAC_ADDRESS), 173 + .get_mac_addr = { 174 + .port_mask = cpu_to_le32(BIT(port)), 175 + .pfvf_num = cpu_to_le32(pfvfnum), 176 + }, 177 + }; 178 + struct mbx_fw_cmd_reply reply = {}; 179 + int err; 180 + 181 + err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply); 182 + if (err) 183 + return err; 184 + 185 + if (le32_to_cpu(reply.mac_addr.ports) & BIT(port)) 186 + memcpy(mac_addr, reply.mac_addr.addrs[port].mac, ETH_ALEN); 187 + else 188 + return -ENODATA; 189 + 190 + return 0; 191 + }
+88
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 + 4 + #ifndef _RNPGBE_MBX_FW_H 5 + #define _RNPGBE_MBX_FW_H 6 + 7 + #include <linux/types.h> 8 + 9 + #include "rnpgbe.h" 10 + 11 + #define MUCSE_MBX_REQ_HDR_LEN 24 12 + 13 + enum MUCSE_FW_CMD { 14 + GET_HW_INFO = 0x0601, 15 + GET_MAC_ADDRESS = 0x0602, 16 + RESET_HW = 0x0603, 17 + POWER_UP = 0x0803, 18 + }; 19 + 20 + struct mucse_hw_info { 21 + u8 link_stat; 22 + u8 port_mask; 23 + __le32 speed; 24 + __le16 phy_type; 25 + __le16 nic_mode; 26 + __le16 pfnum; 27 + __le32 fw_version; 28 + __le32 axi_mhz; 29 + union { 30 + u8 port_id[4]; 31 + __le32 port_ids; 32 + }; 33 + __le32 bd_uid; 34 + __le32 phy_id; 35 + __le32 wol_status; 36 + __le32 ext_info; 37 + } __packed; 38 + 39 + struct mbx_fw_cmd_req { 40 + __le16 flags; 41 + __le16 opcode; 42 + __le16 datalen; 43 + __le16 ret_value; 44 + __le32 cookie_lo; 45 + __le32 cookie_hi; 46 + __le32 reply_lo; 47 + __le32 reply_hi; 48 + union { 49 + u8 data[32]; 50 + struct { 51 + __le32 version; 52 + __le32 status; 53 + } powerup; 54 + struct { 55 + __le32 port_mask; 56 + __le32 pfvf_num; 57 + } get_mac_addr; 58 + }; 59 + } __packed; 60 + 61 + struct mbx_fw_cmd_reply { 62 + __le16 flags; 63 + __le16 opcode; 64 + __le16 error_code; 65 + __le16 datalen; 66 + __le32 cookie_lo; 67 + __le32 cookie_hi; 68 + union { 69 + u8 data[40]; 70 + struct mac_addr { 71 + __le32 ports; 72 + struct _addr { 73 + /* for macaddr:01:02:03:04:05:06 74 + * mac-hi=0x01020304 mac-lo=0x05060000 75 + */ 76 + u8 mac[8]; 77 + } addrs[4]; 78 + } mac_addr; 79 + struct mucse_hw_info hw_info; 80 + }; 81 + } __packed; 82 + 83 + int mucse_mbx_sync_fw(struct mucse_hw *hw); 84 + int mucse_mbx_powerup(struct mucse_hw *hw, bool is_powerup); 85 + int mucse_mbx_reset_hw(struct mucse_hw *hw); 86 + int mucse_mbx_get_macaddr(struct mucse_hw *hw, int pfvfnum, 87 + u8 *mac_addr, int port); 88 + #endif /* _RNPGBE_MBX_FW_H */