1ee61c10cSDong Yibo // SPDX-License-Identifier: GPL-2.0 2ee61c10cSDong Yibo /* Copyright(c) 2020 - 2025 Mucse Corporation. */ 3ee61c10cSDong Yibo 4ee61c10cSDong Yibo #include <linux/pci.h> 51b7f85f7SDong Yibo #include <net/rtnetlink.h> 61b7f85f7SDong Yibo #include <linux/etherdevice.h> 7ee61c10cSDong Yibo 8ee61c10cSDong Yibo #include "rnpgbe.h" 91b7f85f7SDong Yibo #include "rnpgbe_hw.h" 10*2ee95ec1SDong Yibo #include "rnpgbe_mbx_fw.h" 11ee61c10cSDong Yibo 12ee61c10cSDong Yibo static const char rnpgbe_driver_name[] = "rnpgbe"; 13ee61c10cSDong Yibo 14ee61c10cSDong Yibo /* rnpgbe_pci_tbl - PCI Device ID Table 15ee61c10cSDong Yibo * 16ee61c10cSDong Yibo * { PCI_VDEVICE(Vendor ID, Device ID), 17ee61c10cSDong Yibo * private_data (used for different hw chip) } 18ee61c10cSDong Yibo */ 19ee61c10cSDong Yibo static struct pci_device_id rnpgbe_pci_tbl[] = { 20ee61c10cSDong Yibo { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N210), board_n210 }, 21ee61c10cSDong Yibo { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N210L), board_n210 }, 22ee61c10cSDong Yibo { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N500_DUAL_PORT), board_n500 }, 23ee61c10cSDong Yibo { PCI_VDEVICE(MUCSE, RNPGBE_DEVICE_ID_N500_QUAD_PORT), board_n500 }, 24ee61c10cSDong Yibo /* required last entry */ 25ee61c10cSDong Yibo {0, }, 26ee61c10cSDong Yibo }; 27ee61c10cSDong Yibo 28ee61c10cSDong Yibo /** 29*2ee95ec1SDong Yibo * rnpgbe_open - Called when a network interface is made active 30*2ee95ec1SDong Yibo * @netdev: network interface device structure 31*2ee95ec1SDong Yibo * 32*2ee95ec1SDong Yibo * The open entry point is called when a network interface is made 33*2ee95ec1SDong Yibo * active by the system (IFF_UP). 34*2ee95ec1SDong Yibo * 35*2ee95ec1SDong Yibo * Return: 0 36*2ee95ec1SDong Yibo **/ 37*2ee95ec1SDong Yibo static int rnpgbe_open(struct net_device *netdev) 38*2ee95ec1SDong Yibo { 39*2ee95ec1SDong Yibo return 0; 40*2ee95ec1SDong Yibo } 41*2ee95ec1SDong Yibo 42*2ee95ec1SDong Yibo /** 43*2ee95ec1SDong Yibo * rnpgbe_close - Disables a network interface 44*2ee95ec1SDong Yibo * @netdev: network interface device structure 45*2ee95ec1SDong Yibo * 46*2ee95ec1SDong Yibo * The close entry point is called when an interface is de-activated 47*2ee95ec1SDong Yibo * by the OS. 48*2ee95ec1SDong Yibo * 49*2ee95ec1SDong Yibo * Return: 0, this is not allowed to fail 50*2ee95ec1SDong Yibo **/ 51*2ee95ec1SDong Yibo static int rnpgbe_close(struct net_device *netdev) 52*2ee95ec1SDong Yibo { 53*2ee95ec1SDong Yibo return 0; 54*2ee95ec1SDong Yibo } 55*2ee95ec1SDong Yibo 56*2ee95ec1SDong Yibo /** 57*2ee95ec1SDong Yibo * rnpgbe_xmit_frame - Send a skb to driver 58*2ee95ec1SDong Yibo * @skb: skb structure to be sent 59*2ee95ec1SDong Yibo * @netdev: network interface device structure 60*2ee95ec1SDong Yibo * 61*2ee95ec1SDong Yibo * Return: NETDEV_TX_OK 62*2ee95ec1SDong Yibo **/ 63*2ee95ec1SDong Yibo static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, 64*2ee95ec1SDong Yibo struct net_device *netdev) 65*2ee95ec1SDong Yibo { 66*2ee95ec1SDong Yibo struct mucse *mucse = netdev_priv(netdev); 67*2ee95ec1SDong Yibo 68*2ee95ec1SDong Yibo dev_kfree_skb_any(skb); 69*2ee95ec1SDong Yibo mucse->stats.tx_dropped++; 70*2ee95ec1SDong Yibo 71*2ee95ec1SDong Yibo return NETDEV_TX_OK; 72*2ee95ec1SDong Yibo } 73*2ee95ec1SDong Yibo 74*2ee95ec1SDong Yibo static const struct net_device_ops rnpgbe_netdev_ops = { 75*2ee95ec1SDong Yibo .ndo_open = rnpgbe_open, 76*2ee95ec1SDong Yibo .ndo_stop = rnpgbe_close, 77*2ee95ec1SDong Yibo .ndo_start_xmit = rnpgbe_xmit_frame, 78*2ee95ec1SDong Yibo }; 79*2ee95ec1SDong Yibo 80*2ee95ec1SDong Yibo /** 811b7f85f7SDong Yibo * rnpgbe_add_adapter - Add netdev for this pci_dev 821b7f85f7SDong Yibo * @pdev: PCI device information structure 831b7f85f7SDong Yibo * @board_type: board type 841b7f85f7SDong Yibo * 851b7f85f7SDong Yibo * rnpgbe_add_adapter initializes a netdev for this pci_dev 861b7f85f7SDong Yibo * structure. Initializes Bar map, private structure, and a 871b7f85f7SDong Yibo * hardware reset occur. 881b7f85f7SDong Yibo * 891b7f85f7SDong Yibo * Return: 0 on success, negative errno on failure 901b7f85f7SDong Yibo **/ 911b7f85f7SDong Yibo static int rnpgbe_add_adapter(struct pci_dev *pdev, 921b7f85f7SDong Yibo int board_type) 931b7f85f7SDong Yibo { 941b7f85f7SDong Yibo struct net_device *netdev; 95*2ee95ec1SDong Yibo u8 perm_addr[ETH_ALEN]; 961b7f85f7SDong Yibo void __iomem *hw_addr; 971b7f85f7SDong Yibo struct mucse *mucse; 981b7f85f7SDong Yibo struct mucse_hw *hw; 99*2ee95ec1SDong Yibo int err, err_notify; 1001b7f85f7SDong Yibo 1011b7f85f7SDong Yibo netdev = alloc_etherdev_mq(sizeof(struct mucse), RNPGBE_MAX_QUEUES); 1021b7f85f7SDong Yibo if (!netdev) 1031b7f85f7SDong Yibo return -ENOMEM; 1041b7f85f7SDong Yibo 1051b7f85f7SDong Yibo SET_NETDEV_DEV(netdev, &pdev->dev); 1061b7f85f7SDong Yibo mucse = netdev_priv(netdev); 1071b7f85f7SDong Yibo mucse->netdev = netdev; 1081b7f85f7SDong Yibo mucse->pdev = pdev; 1091b7f85f7SDong Yibo pci_set_drvdata(pdev, mucse); 1101b7f85f7SDong Yibo 1111b7f85f7SDong Yibo hw = &mucse->hw; 1121b7f85f7SDong Yibo hw_addr = devm_ioremap(&pdev->dev, 1131b7f85f7SDong Yibo pci_resource_start(pdev, 2), 1141b7f85f7SDong Yibo pci_resource_len(pdev, 2)); 1151b7f85f7SDong Yibo if (!hw_addr) { 1161b7f85f7SDong Yibo err = -EIO; 1171b7f85f7SDong Yibo goto err_free_net; 1181b7f85f7SDong Yibo } 1191b7f85f7SDong Yibo 1201b7f85f7SDong Yibo hw->hw_addr = hw_addr; 121*2ee95ec1SDong Yibo hw->pdev = pdev; 122*2ee95ec1SDong Yibo 1234543534cSDong Yibo err = rnpgbe_init_hw(hw, board_type); 1244543534cSDong Yibo if (err) { 1254543534cSDong Yibo dev_err(&pdev->dev, "Init hw err %d\n", err); 1264543534cSDong Yibo goto err_free_net; 1274543534cSDong Yibo } 128*2ee95ec1SDong Yibo /* Step 1: Send power-up notification to firmware (no response expected) 129*2ee95ec1SDong Yibo * This informs firmware to initialize hardware power state, but 130*2ee95ec1SDong Yibo * firmware only acknowledges receipt without returning data. Must be 131*2ee95ec1SDong Yibo * done before synchronization as firmware may be in low-power idle 132*2ee95ec1SDong Yibo * state initially. 133*2ee95ec1SDong Yibo */ 134*2ee95ec1SDong Yibo err_notify = rnpgbe_send_notify(hw, true, mucse_fw_powerup); 135*2ee95ec1SDong Yibo if (err_notify) { 136*2ee95ec1SDong Yibo dev_warn(&pdev->dev, "Send powerup to hw failed %d\n", 137*2ee95ec1SDong Yibo err_notify); 138*2ee95ec1SDong Yibo dev_warn(&pdev->dev, "Maybe low performance\n"); 139*2ee95ec1SDong Yibo } 140*2ee95ec1SDong Yibo /* Step 2: Synchronize mailbox communication with firmware (requires 141*2ee95ec1SDong Yibo * response) After power-up, confirm firmware is ready to process 142*2ee95ec1SDong Yibo * requests with responses. This ensures subsequent request/response 143*2ee95ec1SDong Yibo * interactions work reliably. 144*2ee95ec1SDong Yibo */ 145*2ee95ec1SDong Yibo err = mucse_mbx_sync_fw(hw); 146*2ee95ec1SDong Yibo if (err) { 147*2ee95ec1SDong Yibo dev_err(&pdev->dev, "Sync fw failed! %d\n", err); 148*2ee95ec1SDong Yibo goto err_powerdown; 149*2ee95ec1SDong Yibo } 150*2ee95ec1SDong Yibo 151*2ee95ec1SDong Yibo netdev->netdev_ops = &rnpgbe_netdev_ops; 152*2ee95ec1SDong Yibo err = rnpgbe_reset_hw(hw); 153*2ee95ec1SDong Yibo if (err) { 154*2ee95ec1SDong Yibo dev_err(&pdev->dev, "Hw reset failed %d\n", err); 155*2ee95ec1SDong Yibo goto err_powerdown; 156*2ee95ec1SDong Yibo } 157*2ee95ec1SDong Yibo 158*2ee95ec1SDong Yibo err = rnpgbe_get_permanent_mac(hw, perm_addr); 159*2ee95ec1SDong Yibo if (!err) { 160*2ee95ec1SDong Yibo eth_hw_addr_set(netdev, perm_addr); 161*2ee95ec1SDong Yibo } else if (err == -EINVAL) { 162*2ee95ec1SDong Yibo dev_warn(&pdev->dev, "Using random MAC\n"); 163*2ee95ec1SDong Yibo eth_hw_addr_random(netdev); 164*2ee95ec1SDong Yibo } else if (err) { 165*2ee95ec1SDong Yibo dev_err(&pdev->dev, "get perm_addr failed %d\n", err); 166*2ee95ec1SDong Yibo goto err_powerdown; 167*2ee95ec1SDong Yibo } 168*2ee95ec1SDong Yibo 169*2ee95ec1SDong Yibo err = register_netdev(netdev); 170*2ee95ec1SDong Yibo if (err) 171*2ee95ec1SDong Yibo goto err_powerdown; 1721b7f85f7SDong Yibo 1731b7f85f7SDong Yibo return 0; 174*2ee95ec1SDong Yibo err_powerdown: 175*2ee95ec1SDong Yibo /* notify powerdown only powerup ok */ 176*2ee95ec1SDong Yibo if (!err_notify) { 177*2ee95ec1SDong Yibo err_notify = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 178*2ee95ec1SDong Yibo if (err_notify) 179*2ee95ec1SDong Yibo dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", 180*2ee95ec1SDong Yibo err_notify); 181*2ee95ec1SDong Yibo } 1821b7f85f7SDong Yibo err_free_net: 1831b7f85f7SDong Yibo free_netdev(netdev); 1841b7f85f7SDong Yibo return err; 1851b7f85f7SDong Yibo } 1861b7f85f7SDong Yibo 1871b7f85f7SDong Yibo /** 188ee61c10cSDong Yibo * rnpgbe_probe - Device initialization routine 189ee61c10cSDong Yibo * @pdev: PCI device information struct 190ee61c10cSDong Yibo * @id: entry in rnpgbe_pci_tbl 191ee61c10cSDong Yibo * 192ee61c10cSDong Yibo * rnpgbe_probe initializes a PF adapter identified by a pci_dev 193ee61c10cSDong Yibo * structure. 194ee61c10cSDong Yibo * 195ee61c10cSDong Yibo * Return: 0 on success, negative errno on failure 196ee61c10cSDong Yibo **/ 197ee61c10cSDong Yibo static int rnpgbe_probe(struct pci_dev *pdev, const struct pci_device_id *id) 198ee61c10cSDong Yibo { 1991b7f85f7SDong Yibo int board_type = id->driver_data; 200ee61c10cSDong Yibo int err; 201ee61c10cSDong Yibo 202ee61c10cSDong Yibo err = pci_enable_device_mem(pdev); 203ee61c10cSDong Yibo if (err) 204ee61c10cSDong Yibo return err; 205ee61c10cSDong Yibo 206ee61c10cSDong Yibo err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(56)); 207ee61c10cSDong Yibo if (err) { 208ee61c10cSDong Yibo dev_err(&pdev->dev, 209ee61c10cSDong Yibo "No usable DMA configuration, aborting %d\n", err); 210ee61c10cSDong Yibo goto err_disable_dev; 211ee61c10cSDong Yibo } 212ee61c10cSDong Yibo 213ee61c10cSDong Yibo err = pci_request_mem_regions(pdev, rnpgbe_driver_name); 214ee61c10cSDong Yibo if (err) { 215ee61c10cSDong Yibo dev_err(&pdev->dev, 216ee61c10cSDong Yibo "pci_request_selected_regions failed %d\n", err); 217ee61c10cSDong Yibo goto err_disable_dev; 218ee61c10cSDong Yibo } 219ee61c10cSDong Yibo 220ee61c10cSDong Yibo pci_set_master(pdev); 221ee61c10cSDong Yibo err = pci_save_state(pdev); 222ee61c10cSDong Yibo if (err) { 223ee61c10cSDong Yibo dev_err(&pdev->dev, "pci_save_state failed %d\n", err); 224ee61c10cSDong Yibo goto err_free_regions; 225ee61c10cSDong Yibo } 226ee61c10cSDong Yibo 2271b7f85f7SDong Yibo err = rnpgbe_add_adapter(pdev, board_type); 2281b7f85f7SDong Yibo if (err) 2291b7f85f7SDong Yibo goto err_free_regions; 2301b7f85f7SDong Yibo 231ee61c10cSDong Yibo return 0; 232ee61c10cSDong Yibo err_free_regions: 233ee61c10cSDong Yibo pci_release_mem_regions(pdev); 234ee61c10cSDong Yibo err_disable_dev: 235ee61c10cSDong Yibo pci_disable_device(pdev); 236ee61c10cSDong Yibo return err; 237ee61c10cSDong Yibo } 238ee61c10cSDong Yibo 239ee61c10cSDong Yibo /** 2401b7f85f7SDong Yibo * rnpgbe_rm_adapter - Remove netdev for this mucse structure 2411b7f85f7SDong Yibo * @pdev: PCI device information struct 2421b7f85f7SDong Yibo * 2431b7f85f7SDong Yibo * rnpgbe_rm_adapter remove a netdev for this mucse structure 2441b7f85f7SDong Yibo **/ 2451b7f85f7SDong Yibo static void rnpgbe_rm_adapter(struct pci_dev *pdev) 2461b7f85f7SDong Yibo { 2471b7f85f7SDong Yibo struct mucse *mucse = pci_get_drvdata(pdev); 248*2ee95ec1SDong Yibo struct mucse_hw *hw = &mucse->hw; 2491b7f85f7SDong Yibo struct net_device *netdev; 250*2ee95ec1SDong Yibo int err; 2511b7f85f7SDong Yibo 2521b7f85f7SDong Yibo if (!mucse) 2531b7f85f7SDong Yibo return; 2541b7f85f7SDong Yibo netdev = mucse->netdev; 255*2ee95ec1SDong Yibo unregister_netdev(netdev); 256*2ee95ec1SDong Yibo err = rnpgbe_send_notify(hw, false, mucse_fw_powerup); 257*2ee95ec1SDong Yibo if (err) 258*2ee95ec1SDong Yibo dev_warn(&pdev->dev, "Send powerdown to hw failed %d\n", err); 2591b7f85f7SDong Yibo free_netdev(netdev); 2601b7f85f7SDong Yibo } 2611b7f85f7SDong Yibo 2621b7f85f7SDong Yibo /** 263ee61c10cSDong Yibo * rnpgbe_remove - Device removal routine 264ee61c10cSDong Yibo * @pdev: PCI device information struct 265ee61c10cSDong Yibo * 266ee61c10cSDong Yibo * rnpgbe_remove is called by the PCI subsystem to alert the driver 267ee61c10cSDong Yibo * that it should release a PCI device. This could be caused by a 268ee61c10cSDong Yibo * Hot-Plug event, or because the driver is going to be removed from 269ee61c10cSDong Yibo * memory. 270ee61c10cSDong Yibo **/ 271ee61c10cSDong Yibo static void rnpgbe_remove(struct pci_dev *pdev) 272ee61c10cSDong Yibo { 2731b7f85f7SDong Yibo rnpgbe_rm_adapter(pdev); 274ee61c10cSDong Yibo pci_release_mem_regions(pdev); 275ee61c10cSDong Yibo pci_disable_device(pdev); 276ee61c10cSDong Yibo } 277ee61c10cSDong Yibo 278ee61c10cSDong Yibo /** 279ee61c10cSDong Yibo * rnpgbe_dev_shutdown - Device shutdown routine 280ee61c10cSDong Yibo * @pdev: PCI device information struct 281ee61c10cSDong Yibo **/ 282ee61c10cSDong Yibo static void rnpgbe_dev_shutdown(struct pci_dev *pdev) 283ee61c10cSDong Yibo { 2841b7f85f7SDong Yibo struct mucse *mucse = pci_get_drvdata(pdev); 2851b7f85f7SDong Yibo struct net_device *netdev = mucse->netdev; 2861b7f85f7SDong Yibo 2871b7f85f7SDong Yibo rtnl_lock(); 2881b7f85f7SDong Yibo netif_device_detach(netdev); 289*2ee95ec1SDong Yibo if (netif_running(netdev)) 290*2ee95ec1SDong Yibo rnpgbe_close(netdev); 2911b7f85f7SDong Yibo rtnl_unlock(); 292ee61c10cSDong Yibo pci_disable_device(pdev); 293ee61c10cSDong Yibo } 294ee61c10cSDong Yibo 295ee61c10cSDong Yibo /** 296ee61c10cSDong Yibo * rnpgbe_shutdown - Device shutdown routine 297ee61c10cSDong Yibo * @pdev: PCI device information struct 298ee61c10cSDong Yibo * 299ee61c10cSDong Yibo * rnpgbe_shutdown is called by the PCI subsystem to alert the driver 300ee61c10cSDong Yibo * that os shutdown. Device should setup wakeup state here. 301ee61c10cSDong Yibo **/ 302ee61c10cSDong Yibo static void rnpgbe_shutdown(struct pci_dev *pdev) 303ee61c10cSDong Yibo { 304ee61c10cSDong Yibo rnpgbe_dev_shutdown(pdev); 305ee61c10cSDong Yibo } 306ee61c10cSDong Yibo 307ee61c10cSDong Yibo static struct pci_driver rnpgbe_driver = { 308ee61c10cSDong Yibo .name = rnpgbe_driver_name, 309ee61c10cSDong Yibo .id_table = rnpgbe_pci_tbl, 310ee61c10cSDong Yibo .probe = rnpgbe_probe, 311ee61c10cSDong Yibo .remove = rnpgbe_remove, 312ee61c10cSDong Yibo .shutdown = rnpgbe_shutdown, 313ee61c10cSDong Yibo }; 314ee61c10cSDong Yibo 315ee61c10cSDong Yibo module_pci_driver(rnpgbe_driver); 316ee61c10cSDong Yibo 317ee61c10cSDong Yibo MODULE_DEVICE_TABLE(pci, rnpgbe_pci_tbl); 318ee61c10cSDong Yibo MODULE_AUTHOR("Yibo Dong, <dong100@mucse.com>"); 319ee61c10cSDong Yibo MODULE_DESCRIPTION("Mucse(R) 1 Gigabit PCI Express Network Driver"); 320ee61c10cSDong Yibo MODULE_LICENSE("GPL"); 321