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