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

net: rnpgbe: Add register_netdev

Complete the network device (netdev) registration flow for Mucse Gbe
Ethernet chips, including:
1. Hardware state initialization:
- Send powerup notification to firmware (via echo_fw_status)
- Sync with firmware
- Reset hardware
2. MAC address handling:
- Retrieve permanent MAC from firmware (via mucse_mbx_get_macaddr)
- Fallback to random valid MAC (eth_random_addr) if not valid mac
from Fw

Signed-off-by: Dong Yibo <dong100@mucse.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20251101013849.120565-6-dong100@mucse.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Dong Yibo and committed by
Jakub Kicinski
2ee95ec1 c6d3f019

+214 -2
+22
drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
··· 26 26 u32 fwpf_ctrl_base; 27 27 }; 28 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 + 29 36 struct mucse_hw { 30 37 void __iomem *hw_addr; 38 + struct pci_dev *pdev; 31 39 struct mucse_mbx_info mbx; 40 + int port; 32 41 u8 pfvfnum; 42 + }; 43 + 44 + struct mucse_stats { 45 + u64 tx_dropped; 33 46 }; 34 47 35 48 struct mucse { 36 49 struct net_device *netdev; 37 50 struct pci_dev *pdev; 38 51 struct mucse_hw hw; 52 + struct mucse_stats stats; 39 53 }; 40 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); 41 60 int rnpgbe_init_hw(struct mucse_hw *hw, int board_type); 42 61 43 62 /* Device IDs */ ··· 65 46 #define RNPGBE_DEVICE_ID_N500_DUAL_PORT 0x8318 66 47 #define RNPGBE_DEVICE_ID_N210 0x8208 67 48 #define RNPGBE_DEVICE_ID_N210L 0x820a 49 + 50 + #define mucse_hw_wr32(hw, reg, val) \ 51 + writel((val), (hw)->hw_addr + (reg)) 68 52 #endif /* _RNPGBE_H */
+73
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3 3 4 + #include <linux/pci.h> 4 5 #include <linux/errno.h> 6 + #include <linux/etherdevice.h> 5 7 6 8 #include "rnpgbe.h" 7 9 #include "rnpgbe_hw.h" 8 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 + } 9 80 10 81 /** 11 82 * rnpgbe_init_n500 - Setup n500 hw info ··· 120 49 int rnpgbe_init_hw(struct mucse_hw *hw, int board_type) 121 50 { 122 51 struct mucse_mbx_info *mbx = &hw->mbx; 52 + 53 + hw->port = 0; 123 54 124 55 mbx->pf2fw_mbx_ctrl = MUCSE_GBE_PFFW_MBX_CTRL_OFFSET; 125 56 mbx->fwpf_mbx_mask = MUCSE_GBE_FWPF_MBX_MASK_OFFSET;
+2
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
··· 11 11 #define MUCSE_N210_FWPF_CTRL_BASE 0x29400 12 12 #define MUCSE_N210_FWPF_SHM_BASE 0x2d900 13 13 14 + #define RNPGBE_DMA_AXI_EN 0x0010 15 + 14 16 #define RNPGBE_MAX_QUEUES 8 15 17 #endif /* _RNPGBE_HW_H */
+117 -2
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
··· 7 7 8 8 #include "rnpgbe.h" 9 9 #include "rnpgbe_hw.h" 10 + #include "rnpgbe_mbx_fw.h" 10 11 11 12 static const char rnpgbe_driver_name[] = "rnpgbe"; 12 13 ··· 26 25 }; 27 26 28 27 /** 28 + * rnpgbe_open - Called when a network interface is made active 29 + * @netdev: network interface device structure 30 + * 31 + * The open entry point is called when a network interface is made 32 + * active by the system (IFF_UP). 33 + * 34 + * Return: 0 35 + **/ 36 + static int rnpgbe_open(struct net_device *netdev) 37 + { 38 + return 0; 39 + } 40 + 41 + /** 42 + * rnpgbe_close - Disables a network interface 43 + * @netdev: network interface device structure 44 + * 45 + * The close entry point is called when an interface is de-activated 46 + * by the OS. 47 + * 48 + * Return: 0, this is not allowed to fail 49 + **/ 50 + static int rnpgbe_close(struct net_device *netdev) 51 + { 52 + return 0; 53 + } 54 + 55 + /** 56 + * rnpgbe_xmit_frame - Send a skb to driver 57 + * @skb: skb structure to be sent 58 + * @netdev: network interface device structure 59 + * 60 + * Return: NETDEV_TX_OK 61 + **/ 62 + static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, 63 + struct net_device *netdev) 64 + { 65 + struct mucse *mucse = netdev_priv(netdev); 66 + 67 + dev_kfree_skb_any(skb); 68 + mucse->stats.tx_dropped++; 69 + 70 + return NETDEV_TX_OK; 71 + } 72 + 73 + static const struct net_device_ops rnpgbe_netdev_ops = { 74 + .ndo_open = rnpgbe_open, 75 + .ndo_stop = rnpgbe_close, 76 + .ndo_start_xmit = rnpgbe_xmit_frame, 77 + }; 78 + 79 + /** 29 80 * rnpgbe_add_adapter - Add netdev for this pci_dev 30 81 * @pdev: PCI device information structure 31 82 * @board_type: board type ··· 92 39 int board_type) 93 40 { 94 41 struct net_device *netdev; 42 + u8 perm_addr[ETH_ALEN]; 95 43 void __iomem *hw_addr; 96 44 struct mucse *mucse; 97 45 struct mucse_hw *hw; 98 - int err; 46 + int err, err_notify; 99 47 100 48 netdev = alloc_etherdev_mq(sizeof(struct mucse), RNPGBE_MAX_QUEUES); 101 49 if (!netdev) ··· 118 64 } 119 65 120 66 hw->hw_addr = hw_addr; 67 + hw->pdev = pdev; 68 + 121 69 err = rnpgbe_init_hw(hw, board_type); 122 70 if (err) { 123 71 dev_err(&pdev->dev, "Init hw err %d\n", err); 124 72 goto err_free_net; 125 73 } 74 + /* Step 1: Send power-up notification to firmware (no response expected) 75 + * This informs firmware to initialize hardware power state, but 76 + * firmware only acknowledges receipt without returning data. Must be 77 + * done before synchronization as firmware may be in low-power idle 78 + * state initially. 79 + */ 80 + err_notify = rnpgbe_send_notify(hw, true, mucse_fw_powerup); 81 + if (err_notify) { 82 + dev_warn(&pdev->dev, "Send powerup to hw failed %d\n", 83 + err_notify); 84 + dev_warn(&pdev->dev, "Maybe low performance\n"); 85 + } 86 + /* Step 2: Synchronize mailbox communication with firmware (requires 87 + * response) After power-up, confirm firmware is ready to process 88 + * requests with responses. This ensures subsequent request/response 89 + * interactions work reliably. 90 + */ 91 + err = mucse_mbx_sync_fw(hw); 92 + if (err) { 93 + dev_err(&pdev->dev, "Sync fw failed! %d\n", err); 94 + goto err_powerdown; 95 + } 96 + 97 + netdev->netdev_ops = &rnpgbe_netdev_ops; 98 + err = rnpgbe_reset_hw(hw); 99 + if (err) { 100 + dev_err(&pdev->dev, "Hw reset failed %d\n", err); 101 + goto err_powerdown; 102 + } 103 + 104 + err = rnpgbe_get_permanent_mac(hw, perm_addr); 105 + if (!err) { 106 + eth_hw_addr_set(netdev, perm_addr); 107 + } else if (err == -EINVAL) { 108 + dev_warn(&pdev->dev, "Using random MAC\n"); 109 + eth_hw_addr_random(netdev); 110 + } else if (err) { 111 + dev_err(&pdev->dev, "get perm_addr failed %d\n", err); 112 + goto err_powerdown; 113 + } 114 + 115 + err = register_netdev(netdev); 116 + if (err) 117 + goto err_powerdown; 126 118 127 119 return 0; 128 - 120 + err_powerdown: 121 + /* notify powerdown only powerup ok */ 122 + if (!err_notify) { 123 + err_notify = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 124 + if (err_notify) 125 + dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", 126 + err_notify); 127 + } 129 128 err_free_net: 130 129 free_netdev(netdev); 131 130 return err; ··· 245 138 static void rnpgbe_rm_adapter(struct pci_dev *pdev) 246 139 { 247 140 struct mucse *mucse = pci_get_drvdata(pdev); 141 + struct mucse_hw *hw = &mucse->hw; 248 142 struct net_device *netdev; 143 + int err; 249 144 250 145 if (!mucse) 251 146 return; 252 147 netdev = mucse->netdev; 148 + unregister_netdev(netdev); 149 + err = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 150 + if (err) 151 + dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", err); 253 152 free_netdev(netdev); 254 153 } 255 154 ··· 286 173 287 174 rtnl_lock(); 288 175 netif_device_detach(netdev); 176 + if (netif_running(netdev)) 177 + rnpgbe_close(netdev); 289 178 rtnl_unlock(); 290 179 pci_disable_device(pdev); 291 180 }