xref: /linux/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
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