]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. | |
3 | * | |
4 | * Copyright (c) 2015 QLogic Corporation. | |
5 | * All rights reserved. | |
6 | * www.qlogic.com | |
7 | * | |
8 | * See LICENSE.bnx2x_pmd for copyright and licensing details. | |
9 | */ | |
10 | ||
11 | #include "bnx2x.h" | |
12 | #include "bnx2x_rxtx.h" | |
13 | ||
14 | #include <rte_dev.h> | |
15 | ||
16 | /* | |
17 | * The set of PCI devices this driver supports | |
18 | */ | |
19 | #define BROADCOM_PCI_VENDOR_ID 0x14E4 | |
20 | static struct rte_pci_id pci_id_bnx2x_map[] = { | |
21 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57800) }, | |
22 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57711) }, | |
23 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57810) }, | |
24 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811) }, | |
25 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_OBS) }, | |
26 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_4_10) }, | |
27 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_2_20) }, | |
28 | #ifdef RTE_LIBRTE_BNX2X_MF_SUPPORT | |
29 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57810_MF) }, | |
30 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811_MF) }, | |
31 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_MF) }, | |
32 | #endif | |
33 | { .vendor_id = 0, } | |
34 | }; | |
35 | ||
36 | static struct rte_pci_id pci_id_bnx2xvf_map[] = { | |
37 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57800_VF) }, | |
38 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57810_VF) }, | |
39 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811_VF) }, | |
40 | { RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_VF) }, | |
41 | { .vendor_id = 0, } | |
42 | }; | |
43 | ||
44 | struct rte_bnx2x_xstats_name_off { | |
45 | char name[RTE_ETH_XSTATS_NAME_SIZE]; | |
46 | uint32_t offset_hi; | |
47 | uint32_t offset_lo; | |
48 | }; | |
49 | ||
50 | static const struct rte_bnx2x_xstats_name_off bnx2x_xstats_strings[] = { | |
51 | {"rx_buffer_drops", | |
52 | offsetof(struct bnx2x_eth_stats, brb_drop_hi), | |
53 | offsetof(struct bnx2x_eth_stats, brb_drop_lo)}, | |
54 | {"rx_buffer_truncates", | |
55 | offsetof(struct bnx2x_eth_stats, brb_truncate_hi), | |
56 | offsetof(struct bnx2x_eth_stats, brb_truncate_lo)}, | |
57 | {"rx_buffer_truncate_discard", | |
58 | offsetof(struct bnx2x_eth_stats, brb_truncate_discard), | |
59 | offsetof(struct bnx2x_eth_stats, brb_truncate_discard)}, | |
60 | {"mac_filter_discard", | |
61 | offsetof(struct bnx2x_eth_stats, mac_filter_discard), | |
62 | offsetof(struct bnx2x_eth_stats, mac_filter_discard)}, | |
63 | {"no_match_vlan_tag_discard", | |
64 | offsetof(struct bnx2x_eth_stats, mf_tag_discard), | |
65 | offsetof(struct bnx2x_eth_stats, mf_tag_discard)}, | |
66 | {"tx_pause", | |
67 | offsetof(struct bnx2x_eth_stats, pause_frames_sent_hi), | |
68 | offsetof(struct bnx2x_eth_stats, pause_frames_sent_lo)}, | |
69 | {"rx_pause", | |
70 | offsetof(struct bnx2x_eth_stats, pause_frames_received_hi), | |
71 | offsetof(struct bnx2x_eth_stats, pause_frames_received_lo)}, | |
72 | {"tx_priority_flow_control", | |
73 | offsetof(struct bnx2x_eth_stats, pfc_frames_sent_hi), | |
74 | offsetof(struct bnx2x_eth_stats, pfc_frames_sent_lo)}, | |
75 | {"rx_priority_flow_control", | |
76 | offsetof(struct bnx2x_eth_stats, pfc_frames_received_hi), | |
77 | offsetof(struct bnx2x_eth_stats, pfc_frames_received_lo)} | |
78 | }; | |
79 | ||
80 | static void | |
81 | bnx2x_link_update(struct rte_eth_dev *dev) | |
82 | { | |
83 | struct bnx2x_softc *sc = dev->data->dev_private; | |
84 | ||
85 | PMD_INIT_FUNC_TRACE(); | |
86 | bnx2x_link_status_update(sc); | |
87 | mb(); | |
88 | dev->data->dev_link.link_speed = sc->link_vars.line_speed; | |
89 | switch (sc->link_vars.duplex) { | |
90 | case DUPLEX_FULL: | |
91 | dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; | |
92 | break; | |
93 | case DUPLEX_HALF: | |
94 | dev->data->dev_link.link_duplex = ETH_LINK_HALF_DUPLEX; | |
95 | break; | |
96 | } | |
97 | dev->data->dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & | |
98 | ETH_LINK_SPEED_FIXED); | |
99 | dev->data->dev_link.link_status = sc->link_vars.link_up; | |
100 | } | |
101 | ||
102 | static void | |
103 | bnx2x_interrupt_action(struct rte_eth_dev *dev) | |
104 | { | |
105 | struct bnx2x_softc *sc = dev->data->dev_private; | |
106 | uint32_t link_status; | |
107 | ||
108 | PMD_DEBUG_PERIODIC_LOG(INFO, "Interrupt handled"); | |
109 | ||
110 | bnx2x_intr_legacy(sc, 0); | |
111 | ||
112 | if (sc->periodic_flags & PERIODIC_GO) | |
113 | bnx2x_periodic_callout(sc); | |
114 | link_status = REG_RD(sc, sc->link_params.shmem_base + | |
115 | offsetof(struct shmem_region, | |
116 | port_mb[sc->link_params.port].link_status)); | |
117 | if ((link_status & LINK_STATUS_LINK_UP) != dev->data->dev_link.link_status) | |
118 | bnx2x_link_update(dev); | |
119 | } | |
120 | ||
121 | static __rte_unused void | |
122 | bnx2x_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) | |
123 | { | |
124 | struct rte_eth_dev *dev = (struct rte_eth_dev *)param; | |
125 | ||
126 | bnx2x_interrupt_action(dev); | |
127 | rte_intr_enable(&(dev->pci_dev->intr_handle)); | |
128 | } | |
129 | ||
130 | /* | |
131 | * Devops - helper functions can be called from user application | |
132 | */ | |
133 | ||
134 | static int | |
135 | bnx2x_dev_configure(struct rte_eth_dev *dev) | |
136 | { | |
137 | struct bnx2x_softc *sc = dev->data->dev_private; | |
138 | int mp_ncpus = sysconf(_SC_NPROCESSORS_CONF); | |
139 | ||
140 | PMD_INIT_FUNC_TRACE(); | |
141 | ||
142 | if (dev->data->dev_conf.rxmode.jumbo_frame) | |
143 | sc->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len; | |
144 | ||
145 | if (dev->data->nb_tx_queues > dev->data->nb_rx_queues) { | |
146 | PMD_DRV_LOG(ERR, "The number of TX queues is greater than number of RX queues"); | |
147 | return -EINVAL; | |
148 | } | |
149 | ||
150 | sc->num_queues = MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues); | |
151 | if (sc->num_queues > mp_ncpus) { | |
152 | PMD_DRV_LOG(ERR, "The number of queues is more than number of CPUs"); | |
153 | return -EINVAL; | |
154 | } | |
155 | ||
156 | PMD_DRV_LOG(DEBUG, "num_queues=%d, mtu=%d", | |
157 | sc->num_queues, sc->mtu); | |
158 | ||
159 | /* allocate ilt */ | |
160 | if (bnx2x_alloc_ilt_mem(sc) != 0) { | |
161 | PMD_DRV_LOG(ERR, "bnx2x_alloc_ilt_mem was failed"); | |
162 | return -ENXIO; | |
163 | } | |
164 | ||
165 | /* allocate the host hardware/software hsi structures */ | |
166 | if (bnx2x_alloc_hsi_mem(sc) != 0) { | |
167 | PMD_DRV_LOG(ERR, "bnx2x_alloc_hsi_mem was failed"); | |
168 | bnx2x_free_ilt_mem(sc); | |
169 | return -ENXIO; | |
170 | } | |
171 | ||
172 | return 0; | |
173 | } | |
174 | ||
175 | static int | |
176 | bnx2x_dev_start(struct rte_eth_dev *dev) | |
177 | { | |
178 | struct bnx2x_softc *sc = dev->data->dev_private; | |
179 | int ret = 0; | |
180 | ||
181 | PMD_INIT_FUNC_TRACE(); | |
182 | ||
183 | ret = bnx2x_init(sc); | |
184 | if (ret) { | |
185 | PMD_DRV_LOG(DEBUG, "bnx2x_init failed (%d)", ret); | |
186 | return -1; | |
187 | } | |
188 | ||
189 | if (IS_PF(sc)) { | |
190 | rte_intr_callback_register(&(dev->pci_dev->intr_handle), | |
191 | bnx2x_interrupt_handler, (void *)dev); | |
192 | ||
193 | if(rte_intr_enable(&(dev->pci_dev->intr_handle))) | |
194 | PMD_DRV_LOG(ERR, "rte_intr_enable failed"); | |
195 | } | |
196 | ||
197 | ret = bnx2x_dev_rx_init(dev); | |
198 | if (ret != 0) { | |
199 | PMD_DRV_LOG(DEBUG, "bnx2x_dev_rx_init returned error code"); | |
200 | return -3; | |
201 | } | |
202 | ||
203 | /* Print important adapter info for the user. */ | |
204 | bnx2x_print_adapter_info(sc); | |
205 | ||
206 | return ret; | |
207 | } | |
208 | ||
209 | static void | |
210 | bnx2x_dev_stop(struct rte_eth_dev *dev) | |
211 | { | |
212 | struct bnx2x_softc *sc = dev->data->dev_private; | |
213 | int ret = 0; | |
214 | ||
215 | PMD_INIT_FUNC_TRACE(); | |
216 | ||
217 | if (IS_PF(sc)) { | |
218 | rte_intr_disable(&(dev->pci_dev->intr_handle)); | |
219 | rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), | |
220 | bnx2x_interrupt_handler, (void *)dev); | |
221 | } | |
222 | ||
223 | ret = bnx2x_nic_unload(sc, UNLOAD_NORMAL, FALSE); | |
224 | if (ret) { | |
225 | PMD_DRV_LOG(DEBUG, "bnx2x_nic_unload failed (%d)", ret); | |
226 | return; | |
227 | } | |
228 | ||
229 | return; | |
230 | } | |
231 | ||
232 | static void | |
233 | bnx2x_dev_close(struct rte_eth_dev *dev) | |
234 | { | |
235 | struct bnx2x_softc *sc = dev->data->dev_private; | |
236 | ||
237 | PMD_INIT_FUNC_TRACE(); | |
238 | ||
239 | if (IS_VF(sc)) | |
240 | bnx2x_vf_close(sc); | |
241 | ||
242 | bnx2x_dev_clear_queues(dev); | |
243 | memset(&(dev->data->dev_link), 0 , sizeof(struct rte_eth_link)); | |
244 | ||
245 | /* free the host hardware/software hsi structures */ | |
246 | bnx2x_free_hsi_mem(sc); | |
247 | ||
248 | /* free ilt */ | |
249 | bnx2x_free_ilt_mem(sc); | |
250 | } | |
251 | ||
252 | static void | |
253 | bnx2x_promisc_enable(struct rte_eth_dev *dev) | |
254 | { | |
255 | struct bnx2x_softc *sc = dev->data->dev_private; | |
256 | ||
257 | PMD_INIT_FUNC_TRACE(); | |
258 | sc->rx_mode = BNX2X_RX_MODE_PROMISC; | |
259 | bnx2x_set_rx_mode(sc); | |
260 | } | |
261 | ||
262 | static void | |
263 | bnx2x_promisc_disable(struct rte_eth_dev *dev) | |
264 | { | |
265 | struct bnx2x_softc *sc = dev->data->dev_private; | |
266 | ||
267 | PMD_INIT_FUNC_TRACE(); | |
268 | sc->rx_mode = BNX2X_RX_MODE_NORMAL; | |
269 | bnx2x_set_rx_mode(sc); | |
270 | } | |
271 | ||
272 | static void | |
273 | bnx2x_dev_allmulticast_enable(struct rte_eth_dev *dev) | |
274 | { | |
275 | struct bnx2x_softc *sc = dev->data->dev_private; | |
276 | ||
277 | PMD_INIT_FUNC_TRACE(); | |
278 | sc->rx_mode = BNX2X_RX_MODE_ALLMULTI; | |
279 | bnx2x_set_rx_mode(sc); | |
280 | } | |
281 | ||
282 | static void | |
283 | bnx2x_dev_allmulticast_disable(struct rte_eth_dev *dev) | |
284 | { | |
285 | struct bnx2x_softc *sc = dev->data->dev_private; | |
286 | ||
287 | PMD_INIT_FUNC_TRACE(); | |
288 | sc->rx_mode = BNX2X_RX_MODE_NORMAL; | |
289 | bnx2x_set_rx_mode(sc); | |
290 | } | |
291 | ||
292 | static int | |
293 | bnx2x_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) | |
294 | { | |
295 | PMD_INIT_FUNC_TRACE(); | |
296 | ||
297 | int old_link_status = dev->data->dev_link.link_status; | |
298 | ||
299 | bnx2x_link_update(dev); | |
300 | ||
301 | return old_link_status == dev->data->dev_link.link_status ? -1 : 0; | |
302 | } | |
303 | ||
304 | static int | |
305 | bnx2xvf_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) | |
306 | { | |
307 | int old_link_status = dev->data->dev_link.link_status; | |
308 | struct bnx2x_softc *sc = dev->data->dev_private; | |
309 | ||
310 | bnx2x_link_update(dev); | |
311 | ||
312 | bnx2x_check_bull(sc); | |
313 | if (sc->old_bulletin.valid_bitmap & (1 << CHANNEL_DOWN)) { | |
314 | PMD_DRV_LOG(ERR, "PF indicated channel is down." | |
315 | "VF device is no longer operational"); | |
316 | dev->data->dev_link.link_status = ETH_LINK_DOWN; | |
317 | } | |
318 | ||
319 | return old_link_status == dev->data->dev_link.link_status ? -1 : 0; | |
320 | } | |
321 | ||
322 | static void | |
323 | bnx2x_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) | |
324 | { | |
325 | struct bnx2x_softc *sc = dev->data->dev_private; | |
326 | uint32_t brb_truncate_discard; | |
327 | uint64_t brb_drops; | |
328 | uint64_t brb_truncates; | |
329 | ||
330 | PMD_INIT_FUNC_TRACE(); | |
331 | ||
332 | bnx2x_stats_handle(sc, STATS_EVENT_UPDATE); | |
333 | ||
334 | memset(stats, 0, sizeof (struct rte_eth_stats)); | |
335 | ||
336 | stats->ipackets = | |
337 | HILO_U64(sc->eth_stats.total_unicast_packets_received_hi, | |
338 | sc->eth_stats.total_unicast_packets_received_lo) + | |
339 | HILO_U64(sc->eth_stats.total_multicast_packets_received_hi, | |
340 | sc->eth_stats.total_multicast_packets_received_lo) + | |
341 | HILO_U64(sc->eth_stats.total_broadcast_packets_received_hi, | |
342 | sc->eth_stats.total_broadcast_packets_received_lo); | |
343 | ||
344 | stats->opackets = | |
345 | HILO_U64(sc->eth_stats.total_unicast_packets_transmitted_hi, | |
346 | sc->eth_stats.total_unicast_packets_transmitted_lo) + | |
347 | HILO_U64(sc->eth_stats.total_multicast_packets_transmitted_hi, | |
348 | sc->eth_stats.total_multicast_packets_transmitted_lo) + | |
349 | HILO_U64(sc->eth_stats.total_broadcast_packets_transmitted_hi, | |
350 | sc->eth_stats.total_broadcast_packets_transmitted_lo); | |
351 | ||
352 | stats->ibytes = | |
353 | HILO_U64(sc->eth_stats.total_bytes_received_hi, | |
354 | sc->eth_stats.total_bytes_received_lo); | |
355 | ||
356 | stats->obytes = | |
357 | HILO_U64(sc->eth_stats.total_bytes_transmitted_hi, | |
358 | sc->eth_stats.total_bytes_transmitted_lo); | |
359 | ||
360 | stats->ierrors = | |
361 | HILO_U64(sc->eth_stats.error_bytes_received_hi, | |
362 | sc->eth_stats.error_bytes_received_lo); | |
363 | ||
364 | stats->oerrors = 0; | |
365 | ||
366 | stats->rx_nombuf = | |
367 | HILO_U64(sc->eth_stats.no_buff_discard_hi, | |
368 | sc->eth_stats.no_buff_discard_lo); | |
369 | ||
370 | brb_drops = | |
371 | HILO_U64(sc->eth_stats.brb_drop_hi, | |
372 | sc->eth_stats.brb_drop_lo); | |
373 | ||
374 | brb_truncates = | |
375 | HILO_U64(sc->eth_stats.brb_truncate_hi, | |
376 | sc->eth_stats.brb_truncate_lo); | |
377 | ||
378 | brb_truncate_discard = sc->eth_stats.brb_truncate_discard; | |
379 | ||
380 | stats->imissed = brb_drops + brb_truncates + | |
381 | brb_truncate_discard + stats->rx_nombuf; | |
382 | } | |
383 | ||
384 | static int | |
385 | bnx2x_get_xstats_names(__rte_unused struct rte_eth_dev *dev, | |
386 | struct rte_eth_xstat_name *xstats_names, | |
387 | __rte_unused unsigned limit) | |
388 | { | |
389 | unsigned int i, stat_cnt = RTE_DIM(bnx2x_xstats_strings); | |
390 | ||
391 | if (xstats_names != NULL) | |
392 | for (i = 0; i < stat_cnt; i++) | |
393 | snprintf(xstats_names[i].name, | |
394 | sizeof(xstats_names[i].name), | |
395 | "%s", | |
396 | bnx2x_xstats_strings[i].name); | |
397 | ||
398 | return stat_cnt; | |
399 | } | |
400 | ||
401 | static int | |
402 | bnx2x_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, | |
403 | unsigned int n) | |
404 | { | |
405 | struct bnx2x_softc *sc = dev->data->dev_private; | |
406 | unsigned int num = RTE_DIM(bnx2x_xstats_strings); | |
407 | ||
408 | if (n < num) | |
409 | return num; | |
410 | ||
411 | bnx2x_stats_handle(sc, STATS_EVENT_UPDATE); | |
412 | ||
413 | for (num = 0; num < n; num++) { | |
414 | if (bnx2x_xstats_strings[num].offset_hi != | |
415 | bnx2x_xstats_strings[num].offset_lo) | |
416 | xstats[num].value = HILO_U64( | |
417 | *(uint32_t *)((char *)&sc->eth_stats + | |
418 | bnx2x_xstats_strings[num].offset_hi), | |
419 | *(uint32_t *)((char *)&sc->eth_stats + | |
420 | bnx2x_xstats_strings[num].offset_lo)); | |
421 | else | |
422 | xstats[num].value = | |
423 | *(uint64_t *)((char *)&sc->eth_stats + | |
424 | bnx2x_xstats_strings[num].offset_lo); | |
425 | } | |
426 | ||
427 | return num; | |
428 | } | |
429 | ||
430 | static void | |
431 | bnx2x_dev_infos_get(struct rte_eth_dev *dev, __rte_unused struct rte_eth_dev_info *dev_info) | |
432 | { | |
433 | struct bnx2x_softc *sc = dev->data->dev_private; | |
434 | dev_info->max_rx_queues = sc->max_rx_queues; | |
435 | dev_info->max_tx_queues = sc->max_tx_queues; | |
436 | dev_info->min_rx_bufsize = BNX2X_MIN_RX_BUF_SIZE; | |
437 | dev_info->max_rx_pktlen = BNX2X_MAX_RX_PKT_LEN; | |
438 | dev_info->max_mac_addrs = BNX2X_MAX_MAC_ADDRS; | |
439 | dev_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_20G; | |
440 | } | |
441 | ||
442 | static void | |
443 | bnx2x_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, | |
444 | uint32_t index, uint32_t pool) | |
445 | { | |
446 | struct bnx2x_softc *sc = dev->data->dev_private; | |
447 | ||
448 | if (sc->mac_ops.mac_addr_add) | |
449 | sc->mac_ops.mac_addr_add(dev, mac_addr, index, pool); | |
450 | } | |
451 | ||
452 | static void | |
453 | bnx2x_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) | |
454 | { | |
455 | struct bnx2x_softc *sc = dev->data->dev_private; | |
456 | ||
457 | if (sc->mac_ops.mac_addr_remove) | |
458 | sc->mac_ops.mac_addr_remove(dev, index); | |
459 | } | |
460 | ||
461 | static const struct eth_dev_ops bnx2x_eth_dev_ops = { | |
462 | .dev_configure = bnx2x_dev_configure, | |
463 | .dev_start = bnx2x_dev_start, | |
464 | .dev_stop = bnx2x_dev_stop, | |
465 | .dev_close = bnx2x_dev_close, | |
466 | .promiscuous_enable = bnx2x_promisc_enable, | |
467 | .promiscuous_disable = bnx2x_promisc_disable, | |
468 | .allmulticast_enable = bnx2x_dev_allmulticast_enable, | |
469 | .allmulticast_disable = bnx2x_dev_allmulticast_disable, | |
470 | .link_update = bnx2x_dev_link_update, | |
471 | .stats_get = bnx2x_dev_stats_get, | |
472 | .xstats_get = bnx2x_dev_xstats_get, | |
473 | .xstats_get_names = bnx2x_get_xstats_names, | |
474 | .dev_infos_get = bnx2x_dev_infos_get, | |
475 | .rx_queue_setup = bnx2x_dev_rx_queue_setup, | |
476 | .rx_queue_release = bnx2x_dev_rx_queue_release, | |
477 | .tx_queue_setup = bnx2x_dev_tx_queue_setup, | |
478 | .tx_queue_release = bnx2x_dev_tx_queue_release, | |
479 | .mac_addr_add = bnx2x_mac_addr_add, | |
480 | .mac_addr_remove = bnx2x_mac_addr_remove, | |
481 | }; | |
482 | ||
483 | /* | |
484 | * dev_ops for virtual function | |
485 | */ | |
486 | static const struct eth_dev_ops bnx2xvf_eth_dev_ops = { | |
487 | .dev_configure = bnx2x_dev_configure, | |
488 | .dev_start = bnx2x_dev_start, | |
489 | .dev_stop = bnx2x_dev_stop, | |
490 | .dev_close = bnx2x_dev_close, | |
491 | .promiscuous_enable = bnx2x_promisc_enable, | |
492 | .promiscuous_disable = bnx2x_promisc_disable, | |
493 | .allmulticast_enable = bnx2x_dev_allmulticast_enable, | |
494 | .allmulticast_disable = bnx2x_dev_allmulticast_disable, | |
495 | .link_update = bnx2xvf_dev_link_update, | |
496 | .stats_get = bnx2x_dev_stats_get, | |
497 | .xstats_get = bnx2x_dev_xstats_get, | |
498 | .xstats_get_names = bnx2x_get_xstats_names, | |
499 | .dev_infos_get = bnx2x_dev_infos_get, | |
500 | .rx_queue_setup = bnx2x_dev_rx_queue_setup, | |
501 | .rx_queue_release = bnx2x_dev_rx_queue_release, | |
502 | .tx_queue_setup = bnx2x_dev_tx_queue_setup, | |
503 | .tx_queue_release = bnx2x_dev_tx_queue_release, | |
504 | .mac_addr_add = bnx2x_mac_addr_add, | |
505 | .mac_addr_remove = bnx2x_mac_addr_remove, | |
506 | }; | |
507 | ||
508 | ||
509 | static int | |
510 | bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf) | |
511 | { | |
512 | int ret = 0; | |
513 | struct rte_pci_device *pci_dev; | |
514 | struct bnx2x_softc *sc; | |
515 | ||
516 | PMD_INIT_FUNC_TRACE(); | |
517 | ||
518 | eth_dev->dev_ops = is_vf ? &bnx2xvf_eth_dev_ops : &bnx2x_eth_dev_ops; | |
519 | pci_dev = eth_dev->pci_dev; | |
520 | ||
521 | rte_eth_copy_pci_info(eth_dev, pci_dev); | |
522 | ||
523 | sc = eth_dev->data->dev_private; | |
524 | sc->pcie_bus = pci_dev->addr.bus; | |
525 | sc->pcie_device = pci_dev->addr.devid; | |
526 | ||
527 | if (is_vf) | |
528 | sc->flags = BNX2X_IS_VF_FLAG; | |
529 | ||
530 | sc->devinfo.vendor_id = pci_dev->id.vendor_id; | |
531 | sc->devinfo.device_id = pci_dev->id.device_id; | |
532 | sc->devinfo.subvendor_id = pci_dev->id.subsystem_vendor_id; | |
533 | sc->devinfo.subdevice_id = pci_dev->id.subsystem_device_id; | |
534 | ||
535 | sc->pcie_func = pci_dev->addr.function; | |
536 | sc->bar[BAR0].base_addr = (void *)pci_dev->mem_resource[0].addr; | |
537 | if (is_vf) | |
538 | sc->bar[BAR1].base_addr = (void *) | |
539 | ((uintptr_t)pci_dev->mem_resource[0].addr + PXP_VF_ADDR_DB_START); | |
540 | else | |
541 | sc->bar[BAR1].base_addr = pci_dev->mem_resource[2].addr; | |
542 | ||
543 | assert(sc->bar[BAR0].base_addr); | |
544 | assert(sc->bar[BAR1].base_addr); | |
545 | ||
546 | bnx2x_load_firmware(sc); | |
547 | assert(sc->firmware); | |
548 | ||
549 | if (eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) | |
550 | sc->udp_rss = 1; | |
551 | ||
552 | sc->rx_budget = BNX2X_RX_BUDGET; | |
553 | sc->hc_rx_ticks = BNX2X_RX_TICKS; | |
554 | sc->hc_tx_ticks = BNX2X_TX_TICKS; | |
555 | ||
556 | sc->interrupt_mode = INTR_MODE_SINGLE_MSIX; | |
557 | sc->rx_mode = BNX2X_RX_MODE_NORMAL; | |
558 | ||
559 | sc->pci_dev = pci_dev; | |
560 | ret = bnx2x_attach(sc); | |
561 | if (ret) { | |
562 | PMD_DRV_LOG(ERR, "bnx2x_attach failed (%d)", ret); | |
563 | return ret; | |
564 | } | |
565 | ||
566 | eth_dev->data->mac_addrs = (struct ether_addr *)sc->link_params.mac_addr; | |
567 | ||
568 | PMD_DRV_LOG(INFO, "pcie_bus=%d, pcie_device=%d", | |
569 | sc->pcie_bus, sc->pcie_device); | |
570 | PMD_DRV_LOG(INFO, "bar0.addr=%p, bar1.addr=%p", | |
571 | sc->bar[BAR0].base_addr, sc->bar[BAR1].base_addr); | |
572 | PMD_DRV_LOG(INFO, "port=%d, path=%d, vnic=%d, func=%d", | |
573 | PORT_ID(sc), PATH_ID(sc), VNIC_ID(sc), FUNC_ID(sc)); | |
574 | PMD_DRV_LOG(INFO, "portID=%d vendorID=0x%x deviceID=0x%x", | |
575 | eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); | |
576 | ||
577 | if (IS_VF(sc)) { | |
578 | rte_spinlock_init(&sc->vf2pf_lock); | |
579 | ||
580 | if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_mbx_msg), | |
581 | &sc->vf2pf_mbox_mapping, "vf2pf_mbox", | |
582 | RTE_CACHE_LINE_SIZE) != 0) | |
583 | return -ENOMEM; | |
584 | ||
585 | sc->vf2pf_mbox = (struct bnx2x_vf_mbx_msg *) | |
586 | sc->vf2pf_mbox_mapping.vaddr; | |
587 | ||
588 | if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_bulletin), | |
589 | &sc->pf2vf_bulletin_mapping, "vf2pf_bull", | |
590 | RTE_CACHE_LINE_SIZE) != 0) | |
591 | return -ENOMEM; | |
592 | ||
593 | sc->pf2vf_bulletin = (struct bnx2x_vf_bulletin *) | |
594 | sc->pf2vf_bulletin_mapping.vaddr; | |
595 | ||
596 | ret = bnx2x_vf_get_resources(sc, sc->max_tx_queues, | |
597 | sc->max_rx_queues); | |
598 | if (ret) | |
599 | return ret; | |
600 | } | |
601 | ||
602 | return 0; | |
603 | } | |
604 | ||
605 | static int | |
606 | eth_bnx2x_dev_init(struct rte_eth_dev *eth_dev) | |
607 | { | |
608 | PMD_INIT_FUNC_TRACE(); | |
609 | return bnx2x_common_dev_init(eth_dev, 0); | |
610 | } | |
611 | ||
612 | static int | |
613 | eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev) | |
614 | { | |
615 | PMD_INIT_FUNC_TRACE(); | |
616 | return bnx2x_common_dev_init(eth_dev, 1); | |
617 | } | |
618 | ||
619 | static struct eth_driver rte_bnx2x_pmd = { | |
620 | .pci_drv = { | |
621 | .id_table = pci_id_bnx2x_map, | |
622 | .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, | |
623 | .probe = rte_eth_dev_pci_probe, | |
624 | .remove = rte_eth_dev_pci_remove, | |
625 | }, | |
626 | .eth_dev_init = eth_bnx2x_dev_init, | |
627 | .dev_private_size = sizeof(struct bnx2x_softc), | |
628 | }; | |
629 | ||
630 | /* | |
631 | * virtual function driver struct | |
632 | */ | |
633 | static struct eth_driver rte_bnx2xvf_pmd = { | |
634 | .pci_drv = { | |
635 | .id_table = pci_id_bnx2xvf_map, | |
636 | .drv_flags = RTE_PCI_DRV_NEED_MAPPING, | |
637 | .probe = rte_eth_dev_pci_probe, | |
638 | .remove = rte_eth_dev_pci_remove, | |
639 | }, | |
640 | .eth_dev_init = eth_bnx2xvf_dev_init, | |
641 | .dev_private_size = sizeof(struct bnx2x_softc), | |
642 | }; | |
643 | ||
644 | RTE_PMD_REGISTER_PCI(net_bnx2x, rte_bnx2x_pmd.pci_drv); | |
645 | RTE_PMD_REGISTER_PCI_TABLE(net_bnx2x, pci_id_bnx2x_map); | |
646 | RTE_PMD_REGISTER_PCI(net_bnx2xvf, rte_bnx2xvf_pmd.pci_drv); | |
647 | RTE_PMD_REGISTER_PCI_TABLE(net_bnx2xvf, pci_id_bnx2xvf_map); |