xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_main.c (revision 2c7e4a2663a1ab5a740c59c31991579b6b865a26)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3 
4 #include <linux/etherdevice.h>
5 #include <linux/netdevice.h>
6 
7 #include "hinic3_common.h"
8 #include "hinic3_hw_comm.h"
9 #include "hinic3_hwdev.h"
10 #include "hinic3_hwif.h"
11 #include "hinic3_lld.h"
12 #include "hinic3_nic_cfg.h"
13 #include "hinic3_nic_dev.h"
14 #include "hinic3_nic_io.h"
15 #include "hinic3_rx.h"
16 #include "hinic3_tx.h"
17 
18 #define HINIC3_NIC_DRV_DESC  "Intelligent Network Interface Card Driver"
19 
20 #define HINIC3_RX_BUF_LEN            2048
21 #define HINIC3_LRO_REPLENISH_THLD    256
22 #define HINIC3_NIC_DEV_WQ_NAME       "hinic3_nic_dev_wq"
23 
24 #define HINIC3_SQ_DEPTH              1024
25 #define HINIC3_RQ_DEPTH              1024
26 
hinic3_alloc_txrxqs(struct net_device * netdev)27 static int hinic3_alloc_txrxqs(struct net_device *netdev)
28 {
29 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
30 	struct hinic3_hwdev *hwdev = nic_dev->hwdev;
31 	int err;
32 
33 	err = hinic3_alloc_txqs(netdev);
34 	if (err) {
35 		dev_err(hwdev->dev, "Failed to alloc txqs\n");
36 		return err;
37 	}
38 
39 	err = hinic3_alloc_rxqs(netdev);
40 	if (err) {
41 		dev_err(hwdev->dev, "Failed to alloc rxqs\n");
42 		goto err_free_txqs;
43 	}
44 
45 	return 0;
46 
47 err_free_txqs:
48 	hinic3_free_txqs(netdev);
49 
50 	return err;
51 }
52 
hinic3_free_txrxqs(struct net_device * netdev)53 static void hinic3_free_txrxqs(struct net_device *netdev)
54 {
55 	hinic3_free_rxqs(netdev);
56 	hinic3_free_txqs(netdev);
57 }
58 
hinic3_init_nic_dev(struct net_device * netdev,struct hinic3_hwdev * hwdev)59 static int hinic3_init_nic_dev(struct net_device *netdev,
60 			       struct hinic3_hwdev *hwdev)
61 {
62 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
63 	struct pci_dev *pdev = hwdev->pdev;
64 
65 	nic_dev->netdev = netdev;
66 	SET_NETDEV_DEV(netdev, &pdev->dev);
67 	nic_dev->hwdev = hwdev;
68 	nic_dev->pdev = pdev;
69 
70 	nic_dev->rx_buf_len = HINIC3_RX_BUF_LEN;
71 	nic_dev->lro_replenish_thld = HINIC3_LRO_REPLENISH_THLD;
72 	nic_dev->nic_svc_cap = hwdev->cfg_mgmt->cap.nic_svc_cap;
73 
74 	return 0;
75 }
76 
hinic3_sw_init(struct net_device * netdev)77 static int hinic3_sw_init(struct net_device *netdev)
78 {
79 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
80 	struct hinic3_hwdev *hwdev = nic_dev->hwdev;
81 	int err;
82 
83 	nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
84 	nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
85 
86 	/* VF driver always uses random MAC address. During VM migration to a
87 	 * new device, the new device should learn the VMs old MAC rather than
88 	 * provide its own MAC. The product design assumes that every VF is
89 	 * suspectable to migration so the device avoids offering MAC address
90 	 * to VFs.
91 	 */
92 	eth_hw_addr_random(netdev);
93 	err = hinic3_set_mac(hwdev, netdev->dev_addr, 0,
94 			     hinic3_global_func_id(hwdev));
95 	if (err) {
96 		dev_err(hwdev->dev, "Failed to set default MAC\n");
97 		return err;
98 	}
99 
100 	err = hinic3_alloc_txrxqs(netdev);
101 	if (err) {
102 		dev_err(hwdev->dev, "Failed to alloc qps\n");
103 		goto err_del_mac;
104 	}
105 
106 	return 0;
107 
108 err_del_mac:
109 	hinic3_del_mac(hwdev, netdev->dev_addr, 0,
110 		       hinic3_global_func_id(hwdev));
111 
112 	return err;
113 }
114 
hinic3_sw_uninit(struct net_device * netdev)115 static void hinic3_sw_uninit(struct net_device *netdev)
116 {
117 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
118 
119 	hinic3_free_txrxqs(netdev);
120 	hinic3_del_mac(nic_dev->hwdev, netdev->dev_addr, 0,
121 		       hinic3_global_func_id(nic_dev->hwdev));
122 }
123 
hinic3_assign_netdev_ops(struct net_device * netdev)124 static void hinic3_assign_netdev_ops(struct net_device *netdev)
125 {
126 	hinic3_set_netdev_ops(netdev);
127 }
128 
netdev_feature_init(struct net_device * netdev)129 static void netdev_feature_init(struct net_device *netdev)
130 {
131 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
132 	netdev_features_t cso_fts = 0;
133 	netdev_features_t tso_fts = 0;
134 	netdev_features_t dft_fts;
135 
136 	dft_fts = NETIF_F_SG | NETIF_F_HIGHDMA;
137 	if (hinic3_test_support(nic_dev, HINIC3_NIC_F_CSUM))
138 		cso_fts |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
139 	if (hinic3_test_support(nic_dev, HINIC3_NIC_F_SCTP_CRC))
140 		cso_fts |= NETIF_F_SCTP_CRC;
141 	if (hinic3_test_support(nic_dev, HINIC3_NIC_F_TSO))
142 		tso_fts |= NETIF_F_TSO | NETIF_F_TSO6;
143 
144 	netdev->features |= dft_fts | cso_fts | tso_fts;
145 }
146 
hinic3_set_default_hw_feature(struct net_device * netdev)147 static int hinic3_set_default_hw_feature(struct net_device *netdev)
148 {
149 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
150 	struct hinic3_hwdev *hwdev = nic_dev->hwdev;
151 	int err;
152 
153 	err = hinic3_set_nic_feature_to_hw(nic_dev);
154 	if (err) {
155 		dev_err(hwdev->dev, "Failed to set nic features\n");
156 		return err;
157 	}
158 
159 	return 0;
160 }
161 
hinic3_link_status_change(struct net_device * netdev,bool link_status_up)162 static void hinic3_link_status_change(struct net_device *netdev,
163 				      bool link_status_up)
164 {
165 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
166 
167 	if (link_status_up) {
168 		if (netif_carrier_ok(netdev))
169 			return;
170 
171 		nic_dev->link_status_up = true;
172 		netif_carrier_on(netdev);
173 		netdev_dbg(netdev, "Link is up\n");
174 	} else {
175 		if (!netif_carrier_ok(netdev))
176 			return;
177 
178 		nic_dev->link_status_up = false;
179 		netif_carrier_off(netdev);
180 		netdev_dbg(netdev, "Link is down\n");
181 	}
182 }
183 
hinic3_nic_event(struct auxiliary_device * adev,struct hinic3_event_info * event)184 static void hinic3_nic_event(struct auxiliary_device *adev,
185 			     struct hinic3_event_info *event)
186 {
187 	struct hinic3_nic_dev *nic_dev = dev_get_drvdata(&adev->dev);
188 	struct net_device *netdev;
189 
190 	netdev = nic_dev->netdev;
191 
192 	switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
193 	case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
194 				   HINIC3_NIC_EVENT_LINK_UP):
195 		hinic3_link_status_change(netdev, true);
196 		break;
197 	case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
198 				   HINIC3_NIC_EVENT_LINK_DOWN):
199 		hinic3_link_status_change(netdev, false);
200 		break;
201 	default:
202 		break;
203 	}
204 }
205 
hinic3_nic_probe(struct auxiliary_device * adev,const struct auxiliary_device_id * id)206 static int hinic3_nic_probe(struct auxiliary_device *adev,
207 			    const struct auxiliary_device_id *id)
208 {
209 	struct hinic3_hwdev *hwdev = hinic3_adev_get_hwdev(adev);
210 	struct pci_dev *pdev = hwdev->pdev;
211 	struct hinic3_nic_dev *nic_dev;
212 	struct net_device *netdev;
213 	u16 max_qps, glb_func_id;
214 	int err;
215 
216 	if (!hinic3_support_nic(hwdev)) {
217 		dev_dbg(&adev->dev, "HW doesn't support nic\n");
218 		return 0;
219 	}
220 
221 	hinic3_adev_event_register(adev, hinic3_nic_event);
222 
223 	glb_func_id = hinic3_global_func_id(hwdev);
224 	err = hinic3_func_reset(hwdev, glb_func_id, COMM_FUNC_RESET_BIT_NIC);
225 	if (err) {
226 		dev_err(&adev->dev, "Failed to reset function\n");
227 		goto err_unregister_adev_event;
228 	}
229 
230 	max_qps = hinic3_func_max_qnum(hwdev);
231 	netdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps);
232 	if (!netdev) {
233 		dev_err(&adev->dev, "Failed to allocate netdev\n");
234 		err = -ENOMEM;
235 		goto err_unregister_adev_event;
236 	}
237 
238 	nic_dev = netdev_priv(netdev);
239 	dev_set_drvdata(&adev->dev, nic_dev);
240 	err = hinic3_init_nic_dev(netdev, hwdev);
241 	if (err)
242 		goto err_free_netdev;
243 
244 	err = hinic3_init_nic_io(nic_dev);
245 	if (err)
246 		goto err_free_netdev;
247 
248 	err = hinic3_sw_init(netdev);
249 	if (err)
250 		goto err_free_nic_io;
251 
252 	hinic3_assign_netdev_ops(netdev);
253 
254 	netdev_feature_init(netdev);
255 	err = hinic3_set_default_hw_feature(netdev);
256 	if (err)
257 		goto err_uninit_sw;
258 
259 	netif_carrier_off(netdev);
260 
261 	err = register_netdev(netdev);
262 	if (err)
263 		goto err_uninit_nic_feature;
264 
265 	return 0;
266 
267 err_uninit_nic_feature:
268 	hinic3_update_nic_feature(nic_dev, 0);
269 	hinic3_set_nic_feature_to_hw(nic_dev);
270 
271 err_uninit_sw:
272 	hinic3_sw_uninit(netdev);
273 
274 err_free_nic_io:
275 	hinic3_free_nic_io(nic_dev);
276 
277 err_free_netdev:
278 	free_netdev(netdev);
279 
280 err_unregister_adev_event:
281 	hinic3_adev_event_unregister(adev);
282 	dev_err(&pdev->dev, "NIC service probe failed\n");
283 
284 	return err;
285 }
286 
hinic3_nic_remove(struct auxiliary_device * adev)287 static void hinic3_nic_remove(struct auxiliary_device *adev)
288 {
289 	struct hinic3_nic_dev *nic_dev = dev_get_drvdata(&adev->dev);
290 	struct net_device *netdev;
291 
292 	if (!hinic3_support_nic(nic_dev->hwdev))
293 		return;
294 
295 	netdev = nic_dev->netdev;
296 	unregister_netdev(netdev);
297 
298 	hinic3_update_nic_feature(nic_dev, 0);
299 	hinic3_set_nic_feature_to_hw(nic_dev);
300 	hinic3_sw_uninit(netdev);
301 
302 	hinic3_free_nic_io(nic_dev);
303 
304 	free_netdev(netdev);
305 }
306 
307 static const struct auxiliary_device_id hinic3_nic_id_table[] = {
308 	{
309 		.name = HINIC3_NIC_DRV_NAME ".nic",
310 	},
311 	{}
312 };
313 
314 static struct auxiliary_driver hinic3_nic_driver = {
315 	.probe    = hinic3_nic_probe,
316 	.remove   = hinic3_nic_remove,
317 	.suspend  = NULL,
318 	.resume   = NULL,
319 	.name     = "nic",
320 	.id_table = hinic3_nic_id_table,
321 };
322 
hinic3_nic_lld_init(void)323 static __init int hinic3_nic_lld_init(void)
324 {
325 	int err;
326 
327 	err = hinic3_lld_init();
328 	if (err)
329 		return err;
330 
331 	err = auxiliary_driver_register(&hinic3_nic_driver);
332 	if (err) {
333 		hinic3_lld_exit();
334 		return err;
335 	}
336 
337 	return 0;
338 }
339 
hinic3_nic_lld_exit(void)340 static __exit void hinic3_nic_lld_exit(void)
341 {
342 	auxiliary_driver_unregister(&hinic3_nic_driver);
343 
344 	hinic3_lld_exit();
345 }
346 
347 module_init(hinic3_nic_lld_init);
348 module_exit(hinic3_nic_lld_exit);
349 
350 MODULE_AUTHOR("Huawei Technologies CO., Ltd");
351 MODULE_DESCRIPTION(HINIC3_NIC_DRV_DESC);
352 MODULE_LICENSE("GPL");
353