Commit | Line | Data |
---|---|---|
2025cf9e | 1 | // SPDX-License-Identifier: GPL-2.0-only |
51ba902a AK |
2 | /* |
3 | * Huawei HiNIC PCI Express Linux driver | |
4 | * Copyright(c) 2017 Huawei Technologies Co., Ltd | |
51ba902a AK |
5 | */ |
6 | ||
25a3ba61 | 7 | #include <linux/kernel.h> |
51ba902a | 8 | #include <linux/module.h> |
e2585ea7 | 9 | #include <linux/moduleparam.h> |
51ba902a AK |
10 | #include <linux/pci.h> |
11 | #include <linux/device.h> | |
12 | #include <linux/errno.h> | |
13 | #include <linux/types.h> | |
14 | #include <linux/etherdevice.h> | |
15 | #include <linux/netdevice.h> | |
25a3ba61 AK |
16 | #include <linux/slab.h> |
17 | #include <linux/if_vlan.h> | |
18 | #include <linux/semaphore.h> | |
c4d06d2d | 19 | #include <linux/workqueue.h> |
25a3ba61 AK |
20 | #include <net/ip.h> |
21 | #include <linux/bitops.h> | |
22 | #include <linux/bitmap.h> | |
c4d06d2d | 23 | #include <linux/delay.h> |
51ba902a AK |
24 | #include <linux/err.h> |
25 | ||
c3e79baf | 26 | #include "hinic_hw_qp.h" |
51ba902a | 27 | #include "hinic_hw_dev.h" |
25a3ba61 | 28 | #include "hinic_port.h" |
c3e79baf AK |
29 | #include "hinic_tx.h" |
30 | #include "hinic_rx.h" | |
51ba902a AK |
31 | #include "hinic_dev.h" |
32 | ||
33 | MODULE_AUTHOR("Huawei Technologies CO., Ltd"); | |
34 | MODULE_DESCRIPTION("Huawei Intelligent NIC driver"); | |
35 | MODULE_LICENSE("GPL"); | |
36 | ||
00e57a6d AK |
37 | static unsigned int tx_weight = 64; |
38 | module_param(tx_weight, uint, 0644); | |
39 | MODULE_PARM_DESC(tx_weight, "Number Tx packets for NAPI budget (default=64)"); | |
40 | ||
e2585ea7 AK |
41 | static unsigned int rx_weight = 64; |
42 | module_param(rx_weight, uint, 0644); | |
43 | MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)"); | |
44 | ||
6679cf09 XC |
45 | #define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822 |
46 | #define HINIC_DEV_ID_DUAL_PORT_100GE 0x0200 | |
47 | #define HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ 0x0205 | |
48 | #define HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ 0x0210 | |
51ba902a | 49 | |
c4d06d2d AK |
50 | #define HINIC_WQ_NAME "hinic_dev" |
51 | ||
51ba902a AK |
52 | #define MSG_ENABLE_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \ |
53 | NETIF_MSG_IFUP | \ | |
54 | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR) | |
55 | ||
25a3ba61 AK |
56 | #define VLAN_BITMAP_SIZE(nic_dev) (ALIGN(VLAN_N_VID, 8) / 8) |
57 | ||
c4d06d2d AK |
58 | #define work_to_rx_mode_work(work) \ |
59 | container_of(work, struct hinic_rx_mode_work, work) | |
60 | ||
61 | #define rx_mode_work_to_nic_dev(rx_mode_work) \ | |
62 | container_of(rx_mode_work, struct hinic_dev, rx_mode_work) | |
63 | ||
64 | static int change_mac_addr(struct net_device *netdev, const u8 *addr); | |
65 | ||
edd384f6 AK |
66 | static void set_link_speed(struct ethtool_link_ksettings *link_ksettings, |
67 | enum hinic_speed speed) | |
68 | { | |
69 | switch (speed) { | |
70 | case HINIC_SPEED_10MB_LINK: | |
71 | link_ksettings->base.speed = SPEED_10; | |
72 | break; | |
73 | ||
74 | case HINIC_SPEED_100MB_LINK: | |
75 | link_ksettings->base.speed = SPEED_100; | |
76 | break; | |
77 | ||
78 | case HINIC_SPEED_1000MB_LINK: | |
79 | link_ksettings->base.speed = SPEED_1000; | |
80 | break; | |
81 | ||
82 | case HINIC_SPEED_10GB_LINK: | |
83 | link_ksettings->base.speed = SPEED_10000; | |
84 | break; | |
85 | ||
86 | case HINIC_SPEED_25GB_LINK: | |
87 | link_ksettings->base.speed = SPEED_25000; | |
88 | break; | |
89 | ||
90 | case HINIC_SPEED_40GB_LINK: | |
91 | link_ksettings->base.speed = SPEED_40000; | |
92 | break; | |
93 | ||
94 | case HINIC_SPEED_100GB_LINK: | |
95 | link_ksettings->base.speed = SPEED_100000; | |
96 | break; | |
97 | ||
98 | default: | |
99 | link_ksettings->base.speed = SPEED_UNKNOWN; | |
100 | break; | |
101 | } | |
102 | } | |
103 | ||
104 | static int hinic_get_link_ksettings(struct net_device *netdev, | |
105 | struct ethtool_link_ksettings | |
106 | *link_ksettings) | |
107 | { | |
108 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
109 | enum hinic_port_link_state link_state; | |
110 | struct hinic_port_cap port_cap; | |
111 | int err; | |
112 | ||
113 | ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); | |
114 | ethtool_link_ksettings_add_link_mode(link_ksettings, supported, | |
115 | Autoneg); | |
116 | ||
117 | link_ksettings->base.speed = SPEED_UNKNOWN; | |
118 | link_ksettings->base.autoneg = AUTONEG_DISABLE; | |
119 | link_ksettings->base.duplex = DUPLEX_UNKNOWN; | |
120 | ||
121 | err = hinic_port_get_cap(nic_dev, &port_cap); | |
122 | if (err) { | |
123 | netif_err(nic_dev, drv, netdev, | |
124 | "Failed to get port capabilities\n"); | |
125 | return err; | |
126 | } | |
127 | ||
128 | err = hinic_port_link_state(nic_dev, &link_state); | |
129 | if (err) { | |
130 | netif_err(nic_dev, drv, netdev, | |
131 | "Failed to get port link state\n"); | |
132 | return err; | |
133 | } | |
134 | ||
135 | if (link_state != HINIC_LINK_STATE_UP) { | |
136 | netif_info(nic_dev, drv, netdev, "No link\n"); | |
137 | return err; | |
138 | } | |
139 | ||
140 | set_link_speed(link_ksettings, port_cap.speed); | |
141 | ||
142 | if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED)) | |
143 | ethtool_link_ksettings_add_link_mode(link_ksettings, | |
144 | advertising, Autoneg); | |
145 | ||
146 | if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE) | |
147 | link_ksettings->base.autoneg = AUTONEG_ENABLE; | |
148 | ||
149 | link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ? | |
150 | DUPLEX_FULL : DUPLEX_HALF; | |
151 | return 0; | |
152 | } | |
153 | ||
154 | static void hinic_get_drvinfo(struct net_device *netdev, | |
155 | struct ethtool_drvinfo *info) | |
156 | { | |
157 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
158 | struct hinic_hwdev *hwdev = nic_dev->hwdev; | |
159 | struct hinic_hwif *hwif = hwdev->hwif; | |
160 | ||
161 | strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver)); | |
162 | strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info)); | |
163 | } | |
164 | ||
165 | static void hinic_get_ringparam(struct net_device *netdev, | |
166 | struct ethtool_ringparam *ring) | |
167 | { | |
168 | ring->rx_max_pending = HINIC_RQ_DEPTH; | |
169 | ring->tx_max_pending = HINIC_SQ_DEPTH; | |
170 | ring->rx_pending = HINIC_RQ_DEPTH; | |
171 | ring->tx_pending = HINIC_SQ_DEPTH; | |
172 | } | |
173 | ||
174 | static void hinic_get_channels(struct net_device *netdev, | |
175 | struct ethtool_channels *channels) | |
176 | { | |
177 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
178 | struct hinic_hwdev *hwdev = nic_dev->hwdev; | |
179 | ||
180 | channels->max_rx = hwdev->nic_cap.max_qps; | |
181 | channels->max_tx = hwdev->nic_cap.max_qps; | |
182 | channels->max_other = 0; | |
183 | channels->max_combined = 0; | |
184 | channels->rx_count = hinic_hwdev_num_qps(hwdev); | |
185 | channels->tx_count = hinic_hwdev_num_qps(hwdev); | |
186 | channels->other_count = 0; | |
187 | channels->combined_count = 0; | |
188 | } | |
189 | ||
190 | static const struct ethtool_ops hinic_ethtool_ops = { | |
191 | .get_link_ksettings = hinic_get_link_ksettings, | |
192 | .get_drvinfo = hinic_get_drvinfo, | |
193 | .get_link = ethtool_op_get_link, | |
194 | .get_ringparam = hinic_get_ringparam, | |
195 | .get_channels = hinic_get_channels, | |
196 | }; | |
197 | ||
198 | static void update_rx_stats(struct hinic_dev *nic_dev, struct hinic_rxq *rxq) | |
199 | { | |
200 | struct hinic_rxq_stats *nic_rx_stats = &nic_dev->rx_stats; | |
201 | struct hinic_rxq_stats rx_stats; | |
202 | ||
203 | u64_stats_init(&rx_stats.syncp); | |
204 | ||
205 | hinic_rxq_get_stats(rxq, &rx_stats); | |
206 | ||
207 | u64_stats_update_begin(&nic_rx_stats->syncp); | |
208 | nic_rx_stats->bytes += rx_stats.bytes; | |
209 | nic_rx_stats->pkts += rx_stats.pkts; | |
210 | u64_stats_update_end(&nic_rx_stats->syncp); | |
211 | ||
212 | hinic_rxq_clean_stats(rxq); | |
213 | } | |
214 | ||
215 | static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq) | |
216 | { | |
217 | struct hinic_txq_stats *nic_tx_stats = &nic_dev->tx_stats; | |
218 | struct hinic_txq_stats tx_stats; | |
219 | ||
220 | u64_stats_init(&tx_stats.syncp); | |
221 | ||
222 | hinic_txq_get_stats(txq, &tx_stats); | |
223 | ||
224 | u64_stats_update_begin(&nic_tx_stats->syncp); | |
225 | nic_tx_stats->bytes += tx_stats.bytes; | |
226 | nic_tx_stats->pkts += tx_stats.pkts; | |
227 | nic_tx_stats->tx_busy += tx_stats.tx_busy; | |
228 | nic_tx_stats->tx_wake += tx_stats.tx_wake; | |
229 | nic_tx_stats->tx_dropped += tx_stats.tx_dropped; | |
230 | u64_stats_update_end(&nic_tx_stats->syncp); | |
231 | ||
232 | hinic_txq_clean_stats(txq); | |
233 | } | |
234 | ||
235 | static void update_nic_stats(struct hinic_dev *nic_dev) | |
236 | { | |
237 | int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); | |
238 | ||
239 | for (i = 0; i < num_qps; i++) | |
240 | update_rx_stats(nic_dev, &nic_dev->rxqs[i]); | |
241 | ||
242 | for (i = 0; i < num_qps; i++) | |
243 | update_tx_stats(nic_dev, &nic_dev->txqs[i]); | |
244 | } | |
245 | ||
c3e79baf AK |
246 | /** |
247 | * create_txqs - Create the Logical Tx Queues of specific NIC device | |
248 | * @nic_dev: the specific NIC device | |
249 | * | |
250 | * Return 0 - Success, negative - Failure | |
251 | **/ | |
252 | static int create_txqs(struct hinic_dev *nic_dev) | |
253 | { | |
254 | int err, i, j, num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev); | |
255 | struct net_device *netdev = nic_dev->netdev; | |
256 | size_t txq_size; | |
257 | ||
258 | if (nic_dev->txqs) | |
259 | return -EINVAL; | |
260 | ||
261 | txq_size = num_txqs * sizeof(*nic_dev->txqs); | |
262 | nic_dev->txqs = devm_kzalloc(&netdev->dev, txq_size, GFP_KERNEL); | |
263 | if (!nic_dev->txqs) | |
264 | return -ENOMEM; | |
265 | ||
266 | for (i = 0; i < num_txqs; i++) { | |
267 | struct hinic_sq *sq = hinic_hwdev_get_sq(nic_dev->hwdev, i); | |
268 | ||
269 | err = hinic_init_txq(&nic_dev->txqs[i], sq, netdev); | |
270 | if (err) { | |
271 | netif_err(nic_dev, drv, netdev, | |
272 | "Failed to init Txq\n"); | |
273 | goto err_init_txq; | |
274 | } | |
275 | } | |
276 | ||
277 | return 0; | |
278 | ||
279 | err_init_txq: | |
280 | for (j = 0; j < i; j++) | |
281 | hinic_clean_txq(&nic_dev->txqs[j]); | |
282 | ||
283 | devm_kfree(&netdev->dev, nic_dev->txqs); | |
284 | return err; | |
285 | } | |
286 | ||
287 | /** | |
288 | * free_txqs - Free the Logical Tx Queues of specific NIC device | |
289 | * @nic_dev: the specific NIC device | |
290 | **/ | |
291 | static void free_txqs(struct hinic_dev *nic_dev) | |
292 | { | |
293 | int i, num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev); | |
294 | struct net_device *netdev = nic_dev->netdev; | |
295 | ||
296 | if (!nic_dev->txqs) | |
297 | return; | |
298 | ||
299 | for (i = 0; i < num_txqs; i++) | |
300 | hinic_clean_txq(&nic_dev->txqs[i]); | |
301 | ||
302 | devm_kfree(&netdev->dev, nic_dev->txqs); | |
303 | nic_dev->txqs = NULL; | |
304 | } | |
305 | ||
306 | /** | |
307 | * create_txqs - Create the Logical Rx Queues of specific NIC device | |
308 | * @nic_dev: the specific NIC device | |
309 | * | |
310 | * Return 0 - Success, negative - Failure | |
311 | **/ | |
312 | static int create_rxqs(struct hinic_dev *nic_dev) | |
313 | { | |
314 | int err, i, j, num_rxqs = hinic_hwdev_num_qps(nic_dev->hwdev); | |
315 | struct net_device *netdev = nic_dev->netdev; | |
316 | size_t rxq_size; | |
317 | ||
318 | if (nic_dev->rxqs) | |
319 | return -EINVAL; | |
320 | ||
321 | rxq_size = num_rxqs * sizeof(*nic_dev->rxqs); | |
322 | nic_dev->rxqs = devm_kzalloc(&netdev->dev, rxq_size, GFP_KERNEL); | |
323 | if (!nic_dev->rxqs) | |
324 | return -ENOMEM; | |
325 | ||
326 | for (i = 0; i < num_rxqs; i++) { | |
327 | struct hinic_rq *rq = hinic_hwdev_get_rq(nic_dev->hwdev, i); | |
328 | ||
329 | err = hinic_init_rxq(&nic_dev->rxqs[i], rq, netdev); | |
330 | if (err) { | |
331 | netif_err(nic_dev, drv, netdev, | |
332 | "Failed to init rxq\n"); | |
333 | goto err_init_rxq; | |
334 | } | |
335 | } | |
336 | ||
337 | return 0; | |
338 | ||
339 | err_init_rxq: | |
340 | for (j = 0; j < i; j++) | |
341 | hinic_clean_rxq(&nic_dev->rxqs[j]); | |
342 | ||
343 | devm_kfree(&netdev->dev, nic_dev->rxqs); | |
344 | return err; | |
345 | } | |
346 | ||
347 | /** | |
348 | * free_txqs - Free the Logical Rx Queues of specific NIC device | |
349 | * @nic_dev: the specific NIC device | |
350 | **/ | |
351 | static void free_rxqs(struct hinic_dev *nic_dev) | |
352 | { | |
353 | int i, num_rxqs = hinic_hwdev_num_qps(nic_dev->hwdev); | |
354 | struct net_device *netdev = nic_dev->netdev; | |
355 | ||
356 | if (!nic_dev->rxqs) | |
357 | return; | |
358 | ||
359 | for (i = 0; i < num_rxqs; i++) | |
360 | hinic_clean_rxq(&nic_dev->rxqs[i]); | |
361 | ||
362 | devm_kfree(&netdev->dev, nic_dev->rxqs); | |
363 | nic_dev->rxqs = NULL; | |
364 | } | |
365 | ||
c4d06d2d AK |
366 | static int hinic_open(struct net_device *netdev) |
367 | { | |
368 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
369 | enum hinic_port_link_state link_state; | |
c3e79baf AK |
370 | int err, ret, num_qps; |
371 | ||
372 | if (!(nic_dev->flags & HINIC_INTF_UP)) { | |
373 | err = hinic_hwdev_ifup(nic_dev->hwdev); | |
374 | if (err) { | |
375 | netif_err(nic_dev, drv, netdev, | |
376 | "Failed - HW interface up\n"); | |
377 | return err; | |
378 | } | |
379 | } | |
380 | ||
381 | err = create_txqs(nic_dev); | |
382 | if (err) { | |
383 | netif_err(nic_dev, drv, netdev, | |
384 | "Failed to create Tx queues\n"); | |
385 | goto err_create_txqs; | |
386 | } | |
387 | ||
388 | err = create_rxqs(nic_dev); | |
389 | if (err) { | |
390 | netif_err(nic_dev, drv, netdev, | |
391 | "Failed to create Rx queues\n"); | |
392 | goto err_create_rxqs; | |
393 | } | |
394 | ||
395 | num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); | |
396 | netif_set_real_num_tx_queues(netdev, num_qps); | |
397 | netif_set_real_num_rx_queues(netdev, num_qps); | |
c4d06d2d AK |
398 | |
399 | err = hinic_port_set_state(nic_dev, HINIC_PORT_ENABLE); | |
400 | if (err) { | |
401 | netif_err(nic_dev, drv, netdev, | |
402 | "Failed to set port state\n"); | |
c3e79baf | 403 | goto err_port_state; |
c4d06d2d AK |
404 | } |
405 | ||
e2585ea7 AK |
406 | err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_ENABLE); |
407 | if (err) { | |
408 | netif_err(nic_dev, drv, netdev, | |
409 | "Failed to set func port state\n"); | |
410 | goto err_func_port_state; | |
411 | } | |
412 | ||
c4d06d2d AK |
413 | /* Wait up to 3 sec between port enable to link state */ |
414 | msleep(3000); | |
415 | ||
416 | down(&nic_dev->mgmt_lock); | |
417 | ||
418 | err = hinic_port_link_state(nic_dev, &link_state); | |
419 | if (err) { | |
420 | netif_err(nic_dev, drv, netdev, "Failed to get link state\n"); | |
421 | goto err_port_link; | |
422 | } | |
423 | ||
424 | if (link_state == HINIC_LINK_STATE_UP) | |
425 | nic_dev->flags |= HINIC_LINK_UP; | |
426 | ||
427 | nic_dev->flags |= HINIC_INTF_UP; | |
428 | ||
429 | if ((nic_dev->flags & (HINIC_LINK_UP | HINIC_INTF_UP)) == | |
430 | (HINIC_LINK_UP | HINIC_INTF_UP)) { | |
431 | netif_info(nic_dev, drv, netdev, "link + intf UP\n"); | |
432 | netif_carrier_on(netdev); | |
433 | netif_tx_wake_all_queues(netdev); | |
434 | } | |
435 | ||
436 | up(&nic_dev->mgmt_lock); | |
437 | ||
438 | netif_info(nic_dev, drv, netdev, "HINIC_INTF is UP\n"); | |
439 | return 0; | |
440 | ||
441 | err_port_link: | |
442 | up(&nic_dev->mgmt_lock); | |
e2585ea7 AK |
443 | ret = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE); |
444 | if (ret) | |
445 | netif_warn(nic_dev, drv, netdev, | |
446 | "Failed to revert func port state\n"); | |
447 | ||
448 | err_func_port_state: | |
c4d06d2d AK |
449 | ret = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE); |
450 | if (ret) | |
451 | netif_warn(nic_dev, drv, netdev, | |
452 | "Failed to revert port state\n"); | |
c3e79baf AK |
453 | |
454 | err_port_state: | |
455 | free_rxqs(nic_dev); | |
456 | ||
457 | err_create_rxqs: | |
458 | free_txqs(nic_dev); | |
459 | ||
460 | err_create_txqs: | |
461 | if (!(nic_dev->flags & HINIC_INTF_UP)) | |
462 | hinic_hwdev_ifdown(nic_dev->hwdev); | |
c4d06d2d AK |
463 | return err; |
464 | } | |
465 | ||
466 | static int hinic_close(struct net_device *netdev) | |
467 | { | |
468 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
469 | unsigned int flags; | |
470 | int err; | |
471 | ||
472 | down(&nic_dev->mgmt_lock); | |
473 | ||
474 | flags = nic_dev->flags; | |
475 | nic_dev->flags &= ~HINIC_INTF_UP; | |
476 | ||
477 | netif_carrier_off(netdev); | |
478 | netif_tx_disable(netdev); | |
479 | ||
edd384f6 AK |
480 | update_nic_stats(nic_dev); |
481 | ||
c4d06d2d AK |
482 | up(&nic_dev->mgmt_lock); |
483 | ||
e2585ea7 AK |
484 | err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE); |
485 | if (err) { | |
486 | netif_err(nic_dev, drv, netdev, | |
487 | "Failed to set func port state\n"); | |
488 | nic_dev->flags |= (flags & HINIC_INTF_UP); | |
489 | return err; | |
490 | } | |
491 | ||
c4d06d2d AK |
492 | err = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE); |
493 | if (err) { | |
494 | netif_err(nic_dev, drv, netdev, "Failed to set port state\n"); | |
495 | nic_dev->flags |= (flags & HINIC_INTF_UP); | |
496 | return err; | |
497 | } | |
498 | ||
c3e79baf AK |
499 | free_rxqs(nic_dev); |
500 | free_txqs(nic_dev); | |
501 | ||
502 | if (flags & HINIC_INTF_UP) | |
503 | hinic_hwdev_ifdown(nic_dev->hwdev); | |
504 | ||
c4d06d2d AK |
505 | netif_info(nic_dev, drv, netdev, "HINIC_INTF is DOWN\n"); |
506 | return 0; | |
507 | } | |
508 | ||
25a3ba61 AK |
509 | static int hinic_change_mtu(struct net_device *netdev, int new_mtu) |
510 | { | |
511 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
512 | int err; | |
513 | ||
514 | netif_info(nic_dev, drv, netdev, "set_mtu = %d\n", new_mtu); | |
515 | ||
516 | err = hinic_port_set_mtu(nic_dev, new_mtu); | |
517 | if (err) | |
518 | netif_err(nic_dev, drv, netdev, "Failed to set port mtu\n"); | |
519 | else | |
520 | netdev->mtu = new_mtu; | |
521 | ||
522 | return err; | |
523 | } | |
524 | ||
525 | /** | |
526 | * change_mac_addr - change the main mac address of network device | |
527 | * @netdev: network device | |
528 | * @addr: mac address to set | |
529 | * | |
530 | * Return 0 - Success, negative - Failure | |
531 | **/ | |
532 | static int change_mac_addr(struct net_device *netdev, const u8 *addr) | |
533 | { | |
534 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
535 | u16 vid = 0; | |
536 | int err; | |
537 | ||
538 | if (!is_valid_ether_addr(addr)) | |
539 | return -EADDRNOTAVAIL; | |
540 | ||
541 | netif_info(nic_dev, drv, netdev, "change mac addr = %02x %02x %02x %02x %02x %02x\n", | |
542 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | |
543 | ||
544 | down(&nic_dev->mgmt_lock); | |
545 | ||
546 | do { | |
547 | err = hinic_port_del_mac(nic_dev, netdev->dev_addr, vid); | |
548 | if (err) { | |
549 | netif_err(nic_dev, drv, netdev, | |
550 | "Failed to delete mac\n"); | |
551 | break; | |
552 | } | |
553 | ||
554 | err = hinic_port_add_mac(nic_dev, addr, vid); | |
555 | if (err) { | |
556 | netif_err(nic_dev, drv, netdev, "Failed to add mac\n"); | |
557 | break; | |
558 | } | |
559 | ||
560 | vid = find_next_bit(nic_dev->vlan_bitmap, VLAN_N_VID, vid + 1); | |
561 | } while (vid != VLAN_N_VID); | |
562 | ||
563 | up(&nic_dev->mgmt_lock); | |
564 | return err; | |
565 | } | |
566 | ||
567 | static int hinic_set_mac_addr(struct net_device *netdev, void *addr) | |
568 | { | |
569 | unsigned char new_mac[ETH_ALEN]; | |
570 | struct sockaddr *saddr = addr; | |
571 | int err; | |
572 | ||
573 | memcpy(new_mac, saddr->sa_data, ETH_ALEN); | |
574 | ||
575 | err = change_mac_addr(netdev, new_mac); | |
576 | if (!err) | |
577 | memcpy(netdev->dev_addr, new_mac, ETH_ALEN); | |
578 | ||
579 | return err; | |
580 | } | |
581 | ||
c4d06d2d AK |
582 | /** |
583 | * add_mac_addr - add mac address to network device | |
584 | * @netdev: network device | |
585 | * @addr: mac address to add | |
586 | * | |
587 | * Return 0 - Success, negative - Failure | |
588 | **/ | |
589 | static int add_mac_addr(struct net_device *netdev, const u8 *addr) | |
590 | { | |
591 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
592 | u16 vid = 0; | |
593 | int err; | |
594 | ||
c4d06d2d AK |
595 | netif_info(nic_dev, drv, netdev, "set mac addr = %02x %02x %02x %02x %02x %02x\n", |
596 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | |
597 | ||
598 | down(&nic_dev->mgmt_lock); | |
599 | ||
600 | do { | |
601 | err = hinic_port_add_mac(nic_dev, addr, vid); | |
602 | if (err) { | |
603 | netif_err(nic_dev, drv, netdev, "Failed to add mac\n"); | |
604 | break; | |
605 | } | |
606 | ||
607 | vid = find_next_bit(nic_dev->vlan_bitmap, VLAN_N_VID, vid + 1); | |
608 | } while (vid != VLAN_N_VID); | |
609 | ||
610 | up(&nic_dev->mgmt_lock); | |
611 | return err; | |
612 | } | |
613 | ||
614 | /** | |
615 | * remove_mac_addr - remove mac address from network device | |
616 | * @netdev: network device | |
617 | * @addr: mac address to remove | |
618 | * | |
619 | * Return 0 - Success, negative - Failure | |
620 | **/ | |
621 | static int remove_mac_addr(struct net_device *netdev, const u8 *addr) | |
622 | { | |
623 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
624 | u16 vid = 0; | |
625 | int err; | |
626 | ||
627 | if (!is_valid_ether_addr(addr)) | |
628 | return -EADDRNOTAVAIL; | |
629 | ||
630 | netif_info(nic_dev, drv, netdev, "remove mac addr = %02x %02x %02x %02x %02x %02x\n", | |
631 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | |
632 | ||
633 | down(&nic_dev->mgmt_lock); | |
634 | ||
635 | do { | |
636 | err = hinic_port_del_mac(nic_dev, addr, vid); | |
637 | if (err) { | |
638 | netif_err(nic_dev, drv, netdev, | |
639 | "Failed to delete mac\n"); | |
640 | break; | |
641 | } | |
642 | ||
643 | vid = find_next_bit(nic_dev->vlan_bitmap, VLAN_N_VID, vid + 1); | |
644 | } while (vid != VLAN_N_VID); | |
645 | ||
646 | up(&nic_dev->mgmt_lock); | |
647 | return err; | |
648 | } | |
649 | ||
25a3ba61 AK |
650 | static int hinic_vlan_rx_add_vid(struct net_device *netdev, |
651 | __always_unused __be16 proto, u16 vid) | |
652 | { | |
653 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
654 | int ret, err; | |
655 | ||
656 | netif_info(nic_dev, drv, netdev, "add vid = %d\n", vid); | |
657 | ||
658 | down(&nic_dev->mgmt_lock); | |
659 | ||
660 | err = hinic_port_add_vlan(nic_dev, vid); | |
661 | if (err) { | |
662 | netif_err(nic_dev, drv, netdev, "Failed to add vlan\n"); | |
663 | goto err_vlan_add; | |
664 | } | |
665 | ||
666 | err = hinic_port_add_mac(nic_dev, netdev->dev_addr, vid); | |
667 | if (err) { | |
668 | netif_err(nic_dev, drv, netdev, "Failed to set mac\n"); | |
669 | goto err_add_mac; | |
670 | } | |
671 | ||
672 | bitmap_set(nic_dev->vlan_bitmap, vid, 1); | |
673 | ||
674 | up(&nic_dev->mgmt_lock); | |
675 | return 0; | |
676 | ||
677 | err_add_mac: | |
678 | ret = hinic_port_del_vlan(nic_dev, vid); | |
679 | if (ret) | |
680 | netif_err(nic_dev, drv, netdev, | |
681 | "Failed to revert by removing vlan\n"); | |
682 | ||
683 | err_vlan_add: | |
684 | up(&nic_dev->mgmt_lock); | |
685 | return err; | |
686 | } | |
687 | ||
688 | static int hinic_vlan_rx_kill_vid(struct net_device *netdev, | |
689 | __always_unused __be16 proto, u16 vid) | |
690 | { | |
691 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
692 | int err; | |
693 | ||
694 | netif_info(nic_dev, drv, netdev, "remove vid = %d\n", vid); | |
695 | ||
696 | down(&nic_dev->mgmt_lock); | |
697 | ||
698 | err = hinic_port_del_vlan(nic_dev, vid); | |
699 | if (err) { | |
700 | netif_err(nic_dev, drv, netdev, "Failed to delete vlan\n"); | |
701 | goto err_del_vlan; | |
702 | } | |
703 | ||
704 | bitmap_clear(nic_dev->vlan_bitmap, vid, 1); | |
705 | ||
706 | up(&nic_dev->mgmt_lock); | |
707 | return 0; | |
708 | ||
709 | err_del_vlan: | |
710 | up(&nic_dev->mgmt_lock); | |
711 | return err; | |
712 | } | |
713 | ||
c4d06d2d AK |
714 | static void set_rx_mode(struct work_struct *work) |
715 | { | |
716 | struct hinic_rx_mode_work *rx_mode_work = work_to_rx_mode_work(work); | |
717 | struct hinic_dev *nic_dev = rx_mode_work_to_nic_dev(rx_mode_work); | |
9ea72dc9 | 718 | struct netdev_hw_addr *ha; |
c4d06d2d AK |
719 | |
720 | netif_info(nic_dev, drv, nic_dev->netdev, "set rx mode work\n"); | |
721 | ||
722 | hinic_port_set_rx_mode(nic_dev, rx_mode_work->rx_mode); | |
723 | ||
724 | __dev_uc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); | |
725 | __dev_mc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); | |
9ea72dc9 XC |
726 | |
727 | netdev_for_each_mc_addr(ha, nic_dev->netdev) | |
728 | add_mac_addr(nic_dev->netdev, ha->addr); | |
c4d06d2d AK |
729 | } |
730 | ||
731 | static void hinic_set_rx_mode(struct net_device *netdev) | |
732 | { | |
733 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
734 | struct hinic_rx_mode_work *rx_mode_work; | |
735 | u32 rx_mode; | |
736 | ||
737 | rx_mode_work = &nic_dev->rx_mode_work; | |
738 | ||
739 | rx_mode = HINIC_RX_MODE_UC | | |
740 | HINIC_RX_MODE_MC | | |
741 | HINIC_RX_MODE_BC; | |
742 | ||
743 | if (netdev->flags & IFF_PROMISC) | |
744 | rx_mode |= HINIC_RX_MODE_PROMISC; | |
745 | else if (netdev->flags & IFF_ALLMULTI) | |
746 | rx_mode |= HINIC_RX_MODE_MC_ALL; | |
747 | ||
748 | rx_mode_work->rx_mode = rx_mode; | |
749 | ||
750 | queue_work(nic_dev->workq, &rx_mode_work->work); | |
751 | } | |
752 | ||
00e57a6d | 753 | static void hinic_tx_timeout(struct net_device *netdev) |
c4d06d2d | 754 | { |
00e57a6d AK |
755 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
756 | ||
757 | netif_err(nic_dev, drv, netdev, "Tx timeout\n"); | |
c4d06d2d AK |
758 | } |
759 | ||
edd384f6 AK |
760 | static void hinic_get_stats64(struct net_device *netdev, |
761 | struct rtnl_link_stats64 *stats) | |
762 | { | |
763 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
764 | struct hinic_rxq_stats *nic_rx_stats; | |
765 | struct hinic_txq_stats *nic_tx_stats; | |
766 | ||
767 | nic_rx_stats = &nic_dev->rx_stats; | |
768 | nic_tx_stats = &nic_dev->tx_stats; | |
769 | ||
770 | down(&nic_dev->mgmt_lock); | |
771 | ||
772 | if (nic_dev->flags & HINIC_INTF_UP) | |
773 | update_nic_stats(nic_dev); | |
774 | ||
775 | up(&nic_dev->mgmt_lock); | |
776 | ||
777 | stats->rx_bytes = nic_rx_stats->bytes; | |
778 | stats->rx_packets = nic_rx_stats->pkts; | |
779 | ||
780 | stats->tx_bytes = nic_tx_stats->bytes; | |
781 | stats->tx_packets = nic_tx_stats->pkts; | |
782 | stats->tx_errors = nic_tx_stats->tx_dropped; | |
783 | } | |
784 | ||
51ba902a | 785 | static const struct net_device_ops hinic_netdev_ops = { |
c4d06d2d AK |
786 | .ndo_open = hinic_open, |
787 | .ndo_stop = hinic_close, | |
25a3ba61 AK |
788 | .ndo_change_mtu = hinic_change_mtu, |
789 | .ndo_set_mac_address = hinic_set_mac_addr, | |
790 | .ndo_validate_addr = eth_validate_addr, | |
791 | .ndo_vlan_rx_add_vid = hinic_vlan_rx_add_vid, | |
792 | .ndo_vlan_rx_kill_vid = hinic_vlan_rx_kill_vid, | |
c4d06d2d AK |
793 | .ndo_set_rx_mode = hinic_set_rx_mode, |
794 | .ndo_start_xmit = hinic_xmit_frame, | |
00e57a6d | 795 | .ndo_tx_timeout = hinic_tx_timeout, |
edd384f6 | 796 | .ndo_get_stats64 = hinic_get_stats64, |
51ba902a AK |
797 | }; |
798 | ||
25a3ba61 AK |
799 | static void netdev_features_init(struct net_device *netdev) |
800 | { | |
cc18a754 | 801 | netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | |
4a61abb1 XC |
802 | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | |
803 | NETIF_F_RXCSUM; | |
25a3ba61 AK |
804 | |
805 | netdev->vlan_features = netdev->hw_features; | |
806 | ||
807 | netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; | |
808 | } | |
809 | ||
c4d06d2d AK |
810 | /** |
811 | * link_status_event_handler - link event handler | |
812 | * @handle: nic device for the handler | |
813 | * @buf_in: input buffer | |
814 | * @in_size: input size | |
815 | * @buf_in: output buffer | |
816 | * @out_size: returned output size | |
817 | * | |
818 | * Return 0 - Success, negative - Failure | |
819 | **/ | |
820 | static void link_status_event_handler(void *handle, void *buf_in, u16 in_size, | |
821 | void *buf_out, u16 *out_size) | |
822 | { | |
823 | struct hinic_port_link_status *link_status, *ret_link_status; | |
824 | struct hinic_dev *nic_dev = handle; | |
825 | ||
826 | link_status = buf_in; | |
827 | ||
828 | if (link_status->link == HINIC_LINK_STATE_UP) { | |
829 | down(&nic_dev->mgmt_lock); | |
830 | ||
831 | nic_dev->flags |= HINIC_LINK_UP; | |
832 | ||
833 | if ((nic_dev->flags & (HINIC_LINK_UP | HINIC_INTF_UP)) == | |
834 | (HINIC_LINK_UP | HINIC_INTF_UP)) { | |
835 | netif_carrier_on(nic_dev->netdev); | |
836 | netif_tx_wake_all_queues(nic_dev->netdev); | |
837 | } | |
838 | ||
839 | up(&nic_dev->mgmt_lock); | |
840 | ||
841 | netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is UP\n"); | |
842 | } else { | |
843 | down(&nic_dev->mgmt_lock); | |
844 | ||
845 | nic_dev->flags &= ~HINIC_LINK_UP; | |
846 | ||
847 | netif_carrier_off(nic_dev->netdev); | |
848 | netif_tx_disable(nic_dev->netdev); | |
849 | ||
850 | up(&nic_dev->mgmt_lock); | |
851 | ||
852 | netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is DOWN\n"); | |
853 | } | |
854 | ||
855 | ret_link_status = buf_out; | |
856 | ret_link_status->status = 0; | |
857 | ||
858 | *out_size = sizeof(*ret_link_status); | |
859 | } | |
860 | ||
cc18a754 ZC |
861 | static int set_features(struct hinic_dev *nic_dev, |
862 | netdev_features_t pre_features, | |
863 | netdev_features_t features, bool force_change) | |
864 | { | |
865 | netdev_features_t changed = force_change ? ~0 : pre_features ^ features; | |
4a61abb1 | 866 | u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN; |
cc18a754 ZC |
867 | int err = 0; |
868 | ||
869 | if (changed & NETIF_F_TSO) | |
870 | err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ? | |
871 | HINIC_TSO_ENABLE : HINIC_TSO_DISABLE); | |
872 | ||
4a61abb1 XC |
873 | if (changed & NETIF_F_RXCSUM) |
874 | err = hinic_set_rx_csum_offload(nic_dev, csum_en); | |
875 | ||
cc18a754 ZC |
876 | return err; |
877 | } | |
878 | ||
51ba902a AK |
879 | /** |
880 | * nic_dev_init - Initialize the NIC device | |
881 | * @pdev: the NIC pci device | |
882 | * | |
883 | * Return 0 - Success, negative - Failure | |
884 | **/ | |
885 | static int nic_dev_init(struct pci_dev *pdev) | |
886 | { | |
c4d06d2d | 887 | struct hinic_rx_mode_work *rx_mode_work; |
edd384f6 AK |
888 | struct hinic_txq_stats *tx_stats; |
889 | struct hinic_rxq_stats *rx_stats; | |
51ba902a AK |
890 | struct hinic_dev *nic_dev; |
891 | struct net_device *netdev; | |
892 | struct hinic_hwdev *hwdev; | |
893 | int err, num_qps; | |
894 | ||
895 | hwdev = hinic_init_hwdev(pdev); | |
896 | if (IS_ERR(hwdev)) { | |
897 | dev_err(&pdev->dev, "Failed to initialize HW device\n"); | |
898 | return PTR_ERR(hwdev); | |
899 | } | |
900 | ||
901 | num_qps = hinic_hwdev_num_qps(hwdev); | |
902 | if (num_qps <= 0) { | |
903 | dev_err(&pdev->dev, "Invalid number of QPS\n"); | |
904 | err = -EINVAL; | |
905 | goto err_num_qps; | |
906 | } | |
907 | ||
908 | netdev = alloc_etherdev_mq(sizeof(*nic_dev), num_qps); | |
909 | if (!netdev) { | |
910 | dev_err(&pdev->dev, "Failed to allocate Ethernet device\n"); | |
911 | err = -ENOMEM; | |
912 | goto err_alloc_etherdev; | |
913 | } | |
914 | ||
915 | netdev->netdev_ops = &hinic_netdev_ops; | |
edd384f6 | 916 | netdev->ethtool_ops = &hinic_ethtool_ops; |
52f31422 | 917 | netdev->max_mtu = ETH_MAX_MTU; |
51ba902a AK |
918 | |
919 | nic_dev = netdev_priv(netdev); | |
920 | nic_dev->netdev = netdev; | |
921 | nic_dev->hwdev = hwdev; | |
922 | nic_dev->msg_enable = MSG_ENABLE_DEFAULT; | |
c4d06d2d | 923 | nic_dev->flags = 0; |
c3e79baf AK |
924 | nic_dev->txqs = NULL; |
925 | nic_dev->rxqs = NULL; | |
00e57a6d | 926 | nic_dev->tx_weight = tx_weight; |
e2585ea7 | 927 | nic_dev->rx_weight = rx_weight; |
51ba902a | 928 | |
25a3ba61 AK |
929 | sema_init(&nic_dev->mgmt_lock, 1); |
930 | ||
edd384f6 AK |
931 | tx_stats = &nic_dev->tx_stats; |
932 | rx_stats = &nic_dev->rx_stats; | |
933 | ||
934 | u64_stats_init(&tx_stats->syncp); | |
935 | u64_stats_init(&rx_stats->syncp); | |
936 | ||
25a3ba61 AK |
937 | nic_dev->vlan_bitmap = devm_kzalloc(&pdev->dev, |
938 | VLAN_BITMAP_SIZE(nic_dev), | |
939 | GFP_KERNEL); | |
940 | if (!nic_dev->vlan_bitmap) { | |
941 | err = -ENOMEM; | |
942 | goto err_vlan_bitmap; | |
943 | } | |
944 | ||
c4d06d2d AK |
945 | nic_dev->workq = create_singlethread_workqueue(HINIC_WQ_NAME); |
946 | if (!nic_dev->workq) { | |
947 | err = -ENOMEM; | |
948 | goto err_workq; | |
949 | } | |
950 | ||
51ba902a AK |
951 | pci_set_drvdata(pdev, netdev); |
952 | ||
25a3ba61 AK |
953 | err = hinic_port_get_mac(nic_dev, netdev->dev_addr); |
954 | if (err) | |
955 | dev_warn(&pdev->dev, "Failed to get mac address\n"); | |
956 | ||
957 | err = hinic_port_add_mac(nic_dev, netdev->dev_addr, 0); | |
958 | if (err) { | |
959 | dev_err(&pdev->dev, "Failed to add mac\n"); | |
960 | goto err_add_mac; | |
961 | } | |
962 | ||
963 | err = hinic_port_set_mtu(nic_dev, netdev->mtu); | |
964 | if (err) { | |
965 | dev_err(&pdev->dev, "Failed to set mtu\n"); | |
966 | goto err_set_mtu; | |
967 | } | |
968 | ||
c4d06d2d AK |
969 | rx_mode_work = &nic_dev->rx_mode_work; |
970 | INIT_WORK(&rx_mode_work->work, set_rx_mode); | |
971 | ||
25a3ba61 AK |
972 | netdev_features_init(netdev); |
973 | ||
51ba902a AK |
974 | netif_carrier_off(netdev); |
975 | ||
c4d06d2d AK |
976 | hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS, |
977 | nic_dev, link_status_event_handler); | |
978 | ||
cc18a754 ZC |
979 | err = set_features(nic_dev, 0, nic_dev->netdev->features, true); |
980 | if (err) | |
981 | goto err_set_features; | |
982 | ||
7856e861 | 983 | SET_NETDEV_DEV(netdev, &pdev->dev); |
cc18a754 | 984 | |
51ba902a AK |
985 | err = register_netdev(netdev); |
986 | if (err) { | |
987 | dev_err(&pdev->dev, "Failed to register netdev\n"); | |
988 | goto err_reg_netdev; | |
989 | } | |
990 | ||
991 | return 0; | |
992 | ||
993 | err_reg_netdev: | |
cc18a754 | 994 | err_set_features: |
c4d06d2d AK |
995 | hinic_hwdev_cb_unregister(nic_dev->hwdev, |
996 | HINIC_MGMT_MSG_CMD_LINK_STATUS); | |
997 | cancel_work_sync(&rx_mode_work->work); | |
998 | ||
25a3ba61 AK |
999 | err_set_mtu: |
1000 | err_add_mac: | |
51ba902a | 1001 | pci_set_drvdata(pdev, NULL); |
c4d06d2d | 1002 | destroy_workqueue(nic_dev->workq); |
25a3ba61 | 1003 | |
c4d06d2d | 1004 | err_workq: |
25a3ba61 | 1005 | err_vlan_bitmap: |
51ba902a AK |
1006 | free_netdev(netdev); |
1007 | ||
1008 | err_alloc_etherdev: | |
1009 | err_num_qps: | |
1010 | hinic_free_hwdev(hwdev); | |
1011 | return err; | |
1012 | } | |
1013 | ||
1014 | static int hinic_probe(struct pci_dev *pdev, | |
1015 | const struct pci_device_id *id) | |
1016 | { | |
1017 | int err = pci_enable_device(pdev); | |
1018 | ||
1019 | if (err) { | |
1020 | dev_err(&pdev->dev, "Failed to enable PCI device\n"); | |
1021 | return err; | |
1022 | } | |
1023 | ||
1024 | err = pci_request_regions(pdev, HINIC_DRV_NAME); | |
1025 | if (err) { | |
1026 | dev_err(&pdev->dev, "Failed to request PCI regions\n"); | |
1027 | goto err_pci_regions; | |
1028 | } | |
1029 | ||
1030 | pci_set_master(pdev); | |
1031 | ||
1032 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | |
1033 | if (err) { | |
1034 | dev_warn(&pdev->dev, "Couldn't set 64-bit DMA mask\n"); | |
1035 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | |
1036 | if (err) { | |
1037 | dev_err(&pdev->dev, "Failed to set DMA mask\n"); | |
1038 | goto err_dma_mask; | |
1039 | } | |
1040 | } | |
1041 | ||
1042 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | |
1043 | if (err) { | |
1044 | dev_warn(&pdev->dev, | |
1045 | "Couldn't set 64-bit consistent DMA mask\n"); | |
1046 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | |
1047 | if (err) { | |
1048 | dev_err(&pdev->dev, | |
1049 | "Failed to set consistent DMA mask\n"); | |
1050 | goto err_dma_consistent_mask; | |
1051 | } | |
1052 | } | |
1053 | ||
1054 | err = nic_dev_init(pdev); | |
1055 | if (err) { | |
1056 | dev_err(&pdev->dev, "Failed to initialize NIC device\n"); | |
1057 | goto err_nic_dev_init; | |
1058 | } | |
1059 | ||
1060 | dev_info(&pdev->dev, "HiNIC driver - probed\n"); | |
1061 | return 0; | |
1062 | ||
1063 | err_nic_dev_init: | |
1064 | err_dma_consistent_mask: | |
1065 | err_dma_mask: | |
1066 | pci_release_regions(pdev); | |
1067 | ||
1068 | err_pci_regions: | |
1069 | pci_disable_device(pdev); | |
1070 | return err; | |
1071 | } | |
1072 | ||
1073 | static void hinic_remove(struct pci_dev *pdev) | |
1074 | { | |
1075 | struct net_device *netdev = pci_get_drvdata(pdev); | |
1076 | struct hinic_dev *nic_dev = netdev_priv(netdev); | |
c4d06d2d | 1077 | struct hinic_rx_mode_work *rx_mode_work; |
51ba902a AK |
1078 | |
1079 | unregister_netdev(netdev); | |
1080 | ||
c4d06d2d AK |
1081 | hinic_hwdev_cb_unregister(nic_dev->hwdev, |
1082 | HINIC_MGMT_MSG_CMD_LINK_STATUS); | |
1083 | ||
1084 | rx_mode_work = &nic_dev->rx_mode_work; | |
1085 | cancel_work_sync(&rx_mode_work->work); | |
1086 | ||
51ba902a AK |
1087 | pci_set_drvdata(pdev, NULL); |
1088 | ||
c4d06d2d AK |
1089 | destroy_workqueue(nic_dev->workq); |
1090 | ||
51ba902a AK |
1091 | hinic_free_hwdev(nic_dev->hwdev); |
1092 | ||
1093 | free_netdev(netdev); | |
1094 | ||
1095 | pci_release_regions(pdev); | |
1096 | pci_disable_device(pdev); | |
1097 | ||
1098 | dev_info(&pdev->dev, "HiNIC driver - removed\n"); | |
1099 | } | |
1100 | ||
53fe3ed1 XC |
1101 | static void hinic_shutdown(struct pci_dev *pdev) |
1102 | { | |
1103 | pci_disable_device(pdev); | |
1104 | } | |
1105 | ||
51ba902a | 1106 | static const struct pci_device_id hinic_pci_table[] = { |
724e47a1 | 1107 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE), 0}, |
724e47a1 | 1108 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE), 0}, |
6679cf09 XC |
1109 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ), 0}, |
1110 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ), 0}, | |
51ba902a AK |
1111 | { 0, 0} |
1112 | }; | |
1113 | MODULE_DEVICE_TABLE(pci, hinic_pci_table); | |
1114 | ||
1115 | static struct pci_driver hinic_driver = { | |
1116 | .name = HINIC_DRV_NAME, | |
1117 | .id_table = hinic_pci_table, | |
1118 | .probe = hinic_probe, | |
1119 | .remove = hinic_remove, | |
53fe3ed1 | 1120 | .shutdown = hinic_shutdown, |
51ba902a AK |
1121 | }; |
1122 | ||
1123 | module_pci_driver(hinic_driver); |