1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
7 #include <rte_common.h>
8 #include <ethdev_pci.h>
10 #include <rte_alarm.h>
12 #include "ngbe_logs.h"
14 #include "ngbe_ethdev.h"
16 static int ngbe_dev_close(struct rte_eth_dev *dev);
18 static void ngbe_dev_interrupt_handler(void *param);
19 static void ngbe_dev_interrupt_delayed_handler(void *param);
22 * The set of PCI devices this driver supports
24 static const struct rte_pci_id pci_id_ngbe_map[] = {
25 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2) },
26 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2S) },
27 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4) },
28 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4S) },
29 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2) },
30 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S) },
31 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4) },
32 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S) },
33 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860NCSI) },
34 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1) },
35 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1L) },
36 { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W) },
37 { .vendor_id = 0, /* sentinel */ },
40 static const struct eth_dev_ops ngbe_eth_dev_ops;
43 ngbe_enable_intr(struct rte_eth_dev *dev)
45 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
46 struct ngbe_hw *hw = ngbe_dev_hw(dev);
48 wr32(hw, NGBE_IENMISC, intr->mask_misc);
49 wr32(hw, NGBE_IMC(0), intr->mask & BIT_MASK32);
54 ngbe_disable_intr(struct ngbe_hw *hw)
56 PMD_INIT_FUNC_TRACE();
58 wr32(hw, NGBE_IMS(0), NGBE_IMS_MASK);
63 * Ensure that all locks are released before first NVM or PHY access
66 ngbe_swfw_lock_reset(struct ngbe_hw *hw)
71 * These ones are more tricky since they are common to all ports; but
72 * swfw_sync retries last long enough (1s) to be almost sure that if
73 * lock can not be taken it is due to an improper lock of the
76 mask = NGBE_MNGSEM_SWPHY |
79 if (hw->mac.acquire_swfw_sync(hw, mask) < 0)
80 PMD_DRV_LOG(DEBUG, "SWFW common locks released");
82 hw->mac.release_swfw_sync(hw, mask);
86 eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
88 struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
89 struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
90 struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
91 const struct rte_memzone *mz;
95 PMD_INIT_FUNC_TRACE();
97 eth_dev->dev_ops = &ngbe_eth_dev_ops;
99 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
102 rte_eth_copy_pci_info(eth_dev, pci_dev);
104 /* Vendor and Device ID need to be set before init of shared code */
105 hw->device_id = pci_dev->id.device_id;
106 hw->vendor_id = pci_dev->id.vendor_id;
107 hw->sub_system_id = pci_dev->id.subsystem_device_id;
108 ngbe_map_device_id(hw);
109 hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
111 /* Reserve memory for interrupt status block */
112 mz = rte_eth_dma_zone_reserve(eth_dev, "ngbe_driver", -1,
113 NGBE_ISB_SIZE, NGBE_ALIGN, SOCKET_ID_ANY);
117 hw->isb_dma = TMZ_PADDR(mz);
118 hw->isb_mem = TMZ_VADDR(mz);
120 /* Initialize the shared code (base driver) */
121 err = ngbe_init_shared_code(hw);
123 PMD_INIT_LOG(ERR, "Shared code init failed: %d", err);
127 /* Unlock any pending hardware semaphore */
128 ngbe_swfw_lock_reset(hw);
130 err = hw->rom.init_params(hw);
132 PMD_INIT_LOG(ERR, "The EEPROM init failed: %d", err);
136 /* Make sure we have a good EEPROM before we read from it */
137 err = hw->rom.validate_checksum(hw, NULL);
139 PMD_INIT_LOG(ERR, "The EEPROM checksum is not valid: %d", err);
143 err = hw->mac.init_hw(hw);
145 PMD_INIT_LOG(ERR, "Hardware Initialization Failure: %d", err);
149 /* disable interrupt */
150 ngbe_disable_intr(hw);
152 /* Allocate memory for storing MAC addresses */
153 eth_dev->data->mac_addrs = rte_zmalloc("ngbe", RTE_ETHER_ADDR_LEN *
154 hw->mac.num_rar_entries, 0);
155 if (eth_dev->data->mac_addrs == NULL) {
157 "Failed to allocate %u bytes needed to store MAC addresses",
158 RTE_ETHER_ADDR_LEN * hw->mac.num_rar_entries);
162 /* Copy the permanent MAC address */
163 rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.perm_addr,
164 ð_dev->data->mac_addrs[0]);
166 /* Allocate memory for storing hash filter MAC addresses */
167 eth_dev->data->hash_mac_addrs = rte_zmalloc("ngbe",
168 RTE_ETHER_ADDR_LEN * NGBE_VMDQ_NUM_UC_MAC, 0);
169 if (eth_dev->data->hash_mac_addrs == NULL) {
171 "Failed to allocate %d bytes needed to store MAC addresses",
172 RTE_ETHER_ADDR_LEN * NGBE_VMDQ_NUM_UC_MAC);
173 rte_free(eth_dev->data->mac_addrs);
174 eth_dev->data->mac_addrs = NULL;
178 ctrl_ext = rd32(hw, NGBE_PORTCTL);
179 /* let hardware know driver is loaded */
180 ctrl_ext |= NGBE_PORTCTL_DRVLOAD;
181 /* Set PF Reset Done bit so PF/VF Mail Ops can work */
182 ctrl_ext |= NGBE_PORTCTL_RSTDONE;
183 wr32(hw, NGBE_PORTCTL, ctrl_ext);
186 rte_intr_callback_register(intr_handle,
187 ngbe_dev_interrupt_handler, eth_dev);
189 /* enable uio/vfio intr/eventfd mapping */
190 rte_intr_enable(intr_handle);
192 /* enable support intr */
193 ngbe_enable_intr(eth_dev);
199 eth_ngbe_dev_uninit(struct rte_eth_dev *eth_dev)
201 PMD_INIT_FUNC_TRACE();
203 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
206 ngbe_dev_close(eth_dev);
212 eth_ngbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
213 struct rte_pci_device *pci_dev)
215 return rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
216 sizeof(struct ngbe_adapter),
217 eth_dev_pci_specific_init, pci_dev,
218 eth_ngbe_dev_init, NULL);
221 static int eth_ngbe_pci_remove(struct rte_pci_device *pci_dev)
223 struct rte_eth_dev *ethdev;
225 ethdev = rte_eth_dev_allocated(pci_dev->device.name);
229 return rte_eth_dev_destroy(ethdev, eth_ngbe_dev_uninit);
232 static struct rte_pci_driver rte_ngbe_pmd = {
233 .id_table = pci_id_ngbe_map,
234 .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
235 RTE_PCI_DRV_INTR_LSC,
236 .probe = eth_ngbe_pci_probe,
237 .remove = eth_ngbe_pci_remove,
241 ngbe_dev_configure(struct rte_eth_dev *dev)
243 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
245 PMD_INIT_FUNC_TRACE();
247 /* set flag to update link status after init */
248 intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE;
254 * Reset and stop device.
257 ngbe_dev_close(struct rte_eth_dev *dev)
259 PMD_INIT_FUNC_TRACE();
267 ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
271 dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_100M |
277 /* return 0 means link status changed, -1 means not changed */
279 ngbe_dev_link_update_share(struct rte_eth_dev *dev,
280 int wait_to_complete)
282 struct ngbe_hw *hw = ngbe_dev_hw(dev);
283 struct rte_eth_link link;
284 u32 link_speed = NGBE_LINK_SPEED_UNKNOWN;
286 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
291 memset(&link, 0, sizeof(link));
292 link.link_status = ETH_LINK_DOWN;
293 link.link_speed = ETH_SPEED_NUM_NONE;
294 link.link_duplex = ETH_LINK_HALF_DUPLEX;
295 link.link_autoneg = !(dev->data->dev_conf.link_speeds &
296 ~ETH_LINK_SPEED_AUTONEG);
298 hw->mac.get_link_status = true;
300 if (intr->flags & NGBE_FLAG_NEED_LINK_CONFIG)
301 return rte_eth_linkstatus_set(dev, &link);
303 /* check if it needs to wait to complete, if lsc interrupt is enabled */
304 if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)
307 err = hw->mac.check_link(hw, &link_speed, &link_up, wait);
309 link.link_speed = ETH_SPEED_NUM_NONE;
310 link.link_duplex = ETH_LINK_FULL_DUPLEX;
311 return rte_eth_linkstatus_set(dev, &link);
315 return rte_eth_linkstatus_set(dev, &link);
317 intr->flags &= ~NGBE_FLAG_NEED_LINK_CONFIG;
318 link.link_status = ETH_LINK_UP;
319 link.link_duplex = ETH_LINK_FULL_DUPLEX;
321 switch (link_speed) {
323 case NGBE_LINK_SPEED_UNKNOWN:
324 link.link_speed = ETH_SPEED_NUM_NONE;
327 case NGBE_LINK_SPEED_10M_FULL:
328 link.link_speed = ETH_SPEED_NUM_10M;
332 case NGBE_LINK_SPEED_100M_FULL:
333 link.link_speed = ETH_SPEED_NUM_100M;
337 case NGBE_LINK_SPEED_1GB_FULL:
338 link.link_speed = ETH_SPEED_NUM_1G;
344 wr32m(hw, NGBE_LAN_SPEED, NGBE_LAN_SPEED_MASK, lan_speed);
345 if (link_speed & (NGBE_LINK_SPEED_1GB_FULL |
346 NGBE_LINK_SPEED_100M_FULL |
347 NGBE_LINK_SPEED_10M_FULL)) {
348 wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_SPEED_MASK,
349 NGBE_MACTXCFG_SPEED_1G | NGBE_MACTXCFG_TE);
353 return rte_eth_linkstatus_set(dev, &link);
357 ngbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
359 return ngbe_dev_link_update_share(dev, wait_to_complete);
363 * It reads ICR and sets flag for the link_update.
366 * Pointer to struct rte_eth_dev.
369 * - On success, zero.
370 * - On failure, a negative value.
373 ngbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
376 struct ngbe_hw *hw = ngbe_dev_hw(dev);
377 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
379 /* clear all cause mask */
380 ngbe_disable_intr(hw);
382 /* read-on-clear nic registers here */
383 eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC];
384 PMD_DRV_LOG(DEBUG, "eicr %x", eicr);
388 /* set flag for async link update */
389 if (eicr & NGBE_ICRMISC_PHY)
390 intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE;
392 if (eicr & NGBE_ICRMISC_VFMBX)
393 intr->flags |= NGBE_FLAG_MAILBOX;
395 if (eicr & NGBE_ICRMISC_LNKSEC)
396 intr->flags |= NGBE_FLAG_MACSEC;
398 if (eicr & NGBE_ICRMISC_GPIO)
399 intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE;
405 * It gets and then prints the link status.
408 * Pointer to struct rte_eth_dev.
411 * - On success, zero.
412 * - On failure, a negative value.
415 ngbe_dev_link_status_print(struct rte_eth_dev *dev)
417 struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
418 struct rte_eth_link link;
420 rte_eth_linkstatus_get(dev, &link);
422 if (link.link_status == ETH_LINK_UP) {
423 PMD_INIT_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s",
424 (int)(dev->data->port_id),
425 (unsigned int)link.link_speed,
426 link.link_duplex == ETH_LINK_FULL_DUPLEX ?
427 "full-duplex" : "half-duplex");
429 PMD_INIT_LOG(INFO, " Port %d: Link Down",
430 (int)(dev->data->port_id));
432 PMD_INIT_LOG(DEBUG, "PCI Address: " PCI_PRI_FMT,
433 pci_dev->addr.domain,
436 pci_dev->addr.function);
440 * It executes link_update after knowing an interrupt occurred.
443 * Pointer to struct rte_eth_dev.
446 * - On success, zero.
447 * - On failure, a negative value.
450 ngbe_dev_interrupt_action(struct rte_eth_dev *dev)
452 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
455 PMD_DRV_LOG(DEBUG, "intr action type %d", intr->flags);
457 if (intr->flags & NGBE_FLAG_NEED_LINK_UPDATE) {
458 struct rte_eth_link link;
460 /*get the link status before link update, for predicting later*/
461 rte_eth_linkstatus_get(dev, &link);
463 ngbe_dev_link_update(dev, 0);
466 if (link.link_status != ETH_LINK_UP)
467 /* handle it 1 sec later, wait it being stable */
468 timeout = NGBE_LINK_UP_CHECK_TIMEOUT;
471 /* handle it 4 sec later, wait it being stable */
472 timeout = NGBE_LINK_DOWN_CHECK_TIMEOUT;
474 ngbe_dev_link_status_print(dev);
475 if (rte_eal_alarm_set(timeout * 1000,
476 ngbe_dev_interrupt_delayed_handler,
478 PMD_DRV_LOG(ERR, "Error setting alarm");
480 /* remember original mask */
481 intr->mask_misc_orig = intr->mask_misc;
482 /* only disable lsc interrupt */
483 intr->mask_misc &= ~NGBE_ICRMISC_PHY;
485 intr->mask_orig = intr->mask;
486 /* only disable all misc interrupts */
487 intr->mask &= ~(1ULL << NGBE_MISC_VEC_ID);
491 PMD_DRV_LOG(DEBUG, "enable intr immediately");
492 ngbe_enable_intr(dev);
498 * Interrupt handler which shall be registered for alarm callback for delayed
499 * handling specific interrupt to wait for the stable nic state. As the
500 * NIC interrupt state is not stable for ngbe after link is just down,
501 * it needs to wait 4 seconds to get the stable status.
504 * The address of parameter (struct rte_eth_dev *) registered before.
507 ngbe_dev_interrupt_delayed_handler(void *param)
509 struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
510 struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
511 struct ngbe_hw *hw = ngbe_dev_hw(dev);
514 ngbe_disable_intr(hw);
516 eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC];
518 if (intr->flags & NGBE_FLAG_NEED_LINK_UPDATE) {
519 ngbe_dev_link_update(dev, 0);
520 intr->flags &= ~NGBE_FLAG_NEED_LINK_UPDATE;
521 ngbe_dev_link_status_print(dev);
522 rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
526 if (intr->flags & NGBE_FLAG_MACSEC) {
527 rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_MACSEC,
529 intr->flags &= ~NGBE_FLAG_MACSEC;
532 /* restore original mask */
533 intr->mask_misc = intr->mask_misc_orig;
534 intr->mask_misc_orig = 0;
535 intr->mask = intr->mask_orig;
538 PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
539 ngbe_enable_intr(dev);
543 * Interrupt handler triggered by NIC for handling
544 * specific interrupt.
547 * The address of parameter (struct rte_eth_dev *) registered before.
550 ngbe_dev_interrupt_handler(void *param)
552 struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
554 ngbe_dev_interrupt_get_status(dev);
555 ngbe_dev_interrupt_action(dev);
558 static const struct eth_dev_ops ngbe_eth_dev_ops = {
559 .dev_configure = ngbe_dev_configure,
560 .dev_infos_get = ngbe_dev_info_get,
561 .link_update = ngbe_dev_link_update,
564 RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd);
565 RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map);
566 RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci");
568 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_init, init, NOTICE);
569 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_driver, driver, NOTICE);
571 #ifdef RTE_ETHDEV_DEBUG_RX
572 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_rx, rx, DEBUG);
574 #ifdef RTE_ETHDEV_DEBUG_TX
575 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_tx, tx, DEBUG);