diff options
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r-- | drivers/net/bnx2x/bnx2x.c | 24 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 1 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethdev.c | 214 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethdev.h | 3 |
4 files changed, 174 insertions, 68 deletions
diff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c index 98b08d11..e58684d6 100644 --- a/drivers/net/bnx2x/bnx2x.c +++ b/drivers/net/bnx2x/bnx2x.c @@ -125,7 +125,6 @@ int bnx2x_nic_load(struct bnx2x_softc *sc); static int bnx2x_handle_sp_tq(struct bnx2x_softc *sc); static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp, int scan_fp); -static void bnx2x_periodic_stop(struct bnx2x_softc *sc); static void bnx2x_ack_sb(struct bnx2x_softc *sc, uint8_t igu_sb_id, uint8_t storm, uint16_t index, uint8_t op, uint8_t update); @@ -1971,9 +1970,6 @@ bnx2x_nic_unload(struct bnx2x_softc *sc, uint32_t unload_mode, uint8_t keep_link PMD_DRV_LOG(DEBUG, "Starting NIC unload..."); - /* stop the periodic callout */ - bnx2x_periodic_stop(sc); - /* mark driver as unloaded in shmem2 */ if (IS_PF(sc) && SHMEM2_HAS(sc, drv_capabilities_flag)) { val = SHMEM2_RD(sc, drv_capabilities_flag[SC_FW_MB_IDX(sc)]); @@ -4492,6 +4488,8 @@ static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp, int scan_fp) struct bnx2x_softc *sc = fp->sc; uint8_t more_rx = FALSE; + PMD_DRV_LOG(DEBUG, "---> FP TASK QUEUE (%d) <--", fp->index); + /* update the fastpath index */ bnx2x_update_fp_sb_idx(fp); @@ -4508,7 +4506,7 @@ static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp, int scan_fp) } bnx2x_ack_sb(sc, fp->igu_sb_id, USTORM_ID, - le16toh(fp->fp_hc_idx), IGU_INT_DISABLE, 1); + le16toh(fp->fp_hc_idx), IGU_INT_ENABLE, 1); } /* @@ -6999,16 +6997,6 @@ void bnx2x_link_status_update(struct bnx2x_softc *sc) } } -static void bnx2x_periodic_start(struct bnx2x_softc *sc) -{ - atomic_store_rel_long(&sc->periodic_flags, PERIODIC_GO); -} - -static void bnx2x_periodic_stop(struct bnx2x_softc *sc) -{ - atomic_store_rel_long(&sc->periodic_flags, PERIODIC_STOP); -} - static int bnx2x_initial_phy_init(struct bnx2x_softc *sc, int load_mode) { int rc, cfg_idx = bnx2x_get_link_cfg_idx(sc); @@ -7043,10 +7031,6 @@ static int bnx2x_initial_phy_init(struct bnx2x_softc *sc, int load_mode) bnx2x_link_report(sc); } - if (!CHIP_REV_IS_SLOW(sc)) { - bnx2x_periodic_start(sc); - } - sc->link_params.req_line_speed[cfg_idx] = req_line_speed; return rc; } @@ -7078,7 +7062,7 @@ void bnx2x_periodic_callout(struct bnx2x_softc *sc) { if ((sc->state != BNX2X_STATE_OPEN) || (atomic_load_acq_long(&sc->periodic_flags) == PERIODIC_STOP)) { - PMD_DRV_LOG(WARNING, "periodic callout exit (state=0x%x)", + PMD_DRV_LOG(INFO, "periodic callout exit (state=0x%x)", sc->state); return; } diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 17075d38..c93f148b 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1930,6 +1930,7 @@ void bnx2x_link_status_update(struct bnx2x_softc *sc); int bnx2x_complete_sp(struct bnx2x_softc *sc); int bnx2x_set_storm_rx_mode(struct bnx2x_softc *sc); void bnx2x_periodic_callout(struct bnx2x_softc *sc); +void bnx2x_periodic_stop(void *param); int bnx2x_vf_get_resources(struct bnx2x_softc *sc, uint8_t tx_count, uint8_t rx_count); void bnx2x_vf_close(struct bnx2x_softc *sc); diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c index 95861a06..650d6ce6 100644 --- a/drivers/net/bnx2x/bnx2x_ethdev.c +++ b/drivers/net/bnx2x/bnx2x_ethdev.c @@ -13,6 +13,8 @@ #include <rte_dev.h> #include <rte_ethdev_pci.h> +#include <rte_alarm.h> +#include <rte_atomic.h> /* * The set of PCI devices this driver supports @@ -78,26 +80,87 @@ static const struct rte_bnx2x_xstats_name_off bnx2x_xstats_strings[] = { offsetof(struct bnx2x_eth_stats, pfc_frames_received_lo)} }; -static void +/** + * Atomically reads the link status information from global + * structure rte_eth_dev. + * + * @param dev + * - Pointer to the structure rte_eth_dev to read from. + * - Pointer to the buffer to be saved with the link status. + * + * @return + * - On success, zero. + * - On failure, negative value. + */ +static inline int +bnx2x_dev_atomic_read_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link) +{ + struct rte_eth_link *dst = link; + struct rte_eth_link *src = &dev->data->dev_link; + + if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, + *(uint64_t *)src) == 0) + return -1; + + return 0; +} + +/** + * Atomically writes the link status information into global + * structure rte_eth_dev. + * + * @param dev + * - Pointer to the structure rte_eth_dev to read from. + * - Pointer to the buffer to be saved with the link status. + * + * @return + * - On success, zero. + * - On failure, negative value. + */ +static inline int +bnx2x_dev_atomic_write_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link) +{ + struct rte_eth_link *dst = &dev->data->dev_link; + struct rte_eth_link *src = link; + + if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, + *(uint64_t *)src) == 0) + return -1; + + return 0; +} + +static int bnx2x_link_update(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; + struct rte_eth_link orig; + struct rte_eth_link link; PMD_INIT_FUNC_TRACE(); + bnx2x_link_status_update(sc); + memset(&orig, 0, sizeof(orig)); + memset(&link, 0, sizeof(link)); + bnx2x_dev_atomic_read_link_status(dev, &orig); mb(); - dev->data->dev_link.link_speed = sc->link_vars.line_speed; + link.link_speed = sc->link_vars.line_speed; switch (sc->link_vars.duplex) { case DUPLEX_FULL: - dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; + link.link_duplex = ETH_LINK_FULL_DUPLEX; break; case DUPLEX_HALF: - dev->data->dev_link.link_duplex = ETH_LINK_HALF_DUPLEX; + link.link_duplex = ETH_LINK_HALF_DUPLEX; break; } - dev->data->dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & + link.link_autoneg = !(dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED); - dev->data->dev_link.link_status = sc->link_vars.link_up; + link.link_status = sc->link_vars.link_up; + bnx2x_dev_atomic_write_link_status(dev, &link); + + return (link.link_status == orig.link_status) ? -1 : 0; } static void @@ -106,8 +169,6 @@ bnx2x_interrupt_action(struct rte_eth_dev *dev) struct bnx2x_softc *sc = dev->data->dev_private; uint32_t link_status; - PMD_DEBUG_PERIODIC_LOG(INFO, "Interrupt handled"); - bnx2x_intr_legacy(sc, 0); if (sc->periodic_flags & PERIODIC_GO) @@ -125,15 +186,74 @@ bnx2x_interrupt_handler(void *param) struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct bnx2x_softc *sc = dev->data->dev_private; + PMD_DEBUG_PERIODIC_LOG(INFO, "Interrupt handled"); + bnx2x_interrupt_action(dev); rte_intr_enable(&sc->pci_dev->intr_handle); } +static void bnx2x_periodic_start(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct bnx2x_softc *sc = dev->data->dev_private; + int ret = 0; + + atomic_store_rel_long(&sc->periodic_flags, PERIODIC_GO); + bnx2x_interrupt_action(dev); + if (IS_PF(sc)) { + ret = rte_eal_alarm_set(BNX2X_SP_TIMER_PERIOD, + bnx2x_periodic_start, (void *)dev); + if (ret) { + PMD_DRV_LOG(ERR, "Unable to start periodic" + " timer rc %d", ret); + assert(false && "Unable to start periodic timer"); + } + } +} + +void bnx2x_periodic_stop(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct bnx2x_softc *sc = dev->data->dev_private; + + atomic_store_rel_long(&sc->periodic_flags, PERIODIC_STOP); + + rte_eal_alarm_cancel(bnx2x_periodic_start, (void *)dev); +} + /* * Devops - helper functions can be called from user application */ static int +bnx2x_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete) +{ + PMD_INIT_FUNC_TRACE(); + + return bnx2x_link_update(dev); +} + +static int +bnx2xvf_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete) +{ + struct bnx2x_softc *sc = dev->data->dev_private; + int ret = 0; + + ret = bnx2x_link_update(dev); + + bnx2x_check_bull(sc); + if (sc->old_bulletin.valid_bitmap & (1 << CHANNEL_DOWN)) { + PMD_DRV_LOG(ERR, "PF indicated channel is down." + "VF device is no longer operational"); + dev->data->dev_link.link_status = ETH_LINK_DOWN; + } + + return ret; +} + +static int bnx2x_dev_configure(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; @@ -182,6 +302,10 @@ bnx2x_dev_start(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + /* start the periodic callout */ + if (sc->periodic_flags & PERIODIC_STOP) + bnx2x_periodic_start(dev); + ret = bnx2x_init(sc); if (ret) { PMD_DRV_LOG(DEBUG, "bnx2x_init failed (%d)", ret); @@ -222,12 +346,21 @@ bnx2x_dev_stop(struct rte_eth_dev *dev) bnx2x_interrupt_handler, (void *)dev); } + /* stop the periodic callout */ + bnx2x_periodic_stop(dev); + ret = bnx2x_nic_unload(sc, UNLOAD_NORMAL, FALSE); if (ret) { PMD_DRV_LOG(DEBUG, "bnx2x_nic_unload failed (%d)", ret); return; } + /* Update device link status */ + if (IS_PF(sc)) + bnx2x_dev_link_update(dev, 0); + else + bnx2xvf_dev_link_update(dev, 0); + return; } @@ -300,36 +433,6 @@ bnx2x_dev_allmulticast_disable(struct rte_eth_dev *dev) } static int -bnx2x_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) -{ - PMD_INIT_FUNC_TRACE(); - - int old_link_status = dev->data->dev_link.link_status; - - bnx2x_link_update(dev); - - return old_link_status == dev->data->dev_link.link_status ? -1 : 0; -} - -static int -bnx2xvf_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) -{ - int old_link_status = dev->data->dev_link.link_status; - struct bnx2x_softc *sc = dev->data->dev_private; - - bnx2x_link_update(dev); - - bnx2x_check_bull(sc); - if (sc->old_bulletin.valid_bitmap & (1 << CHANNEL_DOWN)) { - PMD_DRV_LOG(ERR, "PF indicated channel is down." - "VF device is no longer operational"); - dev->data->dev_link.link_status = ETH_LINK_DOWN; - } - - return old_link_status == dev->data->dev_link.link_status ? -1 : 0; -} - -static int bnx2x_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct bnx2x_softc *sc = dev->data->dev_private; @@ -580,6 +683,17 @@ bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf) return ret; } + /* schedule periodic poll for slowpath link events */ + if (IS_PF(sc)) { + ret = rte_eal_alarm_set(BNX2X_SP_TIMER_PERIOD, + bnx2x_periodic_start, (void *)eth_dev); + if (ret) { + PMD_DRV_LOG(ERR, "Unable to start periodic" + " timer rc %d", ret); + return -EINVAL; + } + } + eth_dev->data->mac_addrs = (struct ether_addr *)sc->link_params.mac_addr; PMD_DRV_LOG(INFO, "pcie_bus=%d, pcie_device=%d", @@ -594,18 +708,20 @@ bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf) if (IS_VF(sc)) { rte_spinlock_init(&sc->vf2pf_lock); - if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_mbx_msg), - &sc->vf2pf_mbox_mapping, "vf2pf_mbox", - RTE_CACHE_LINE_SIZE) != 0) - return -ENOMEM; + ret = bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_mbx_msg), + &sc->vf2pf_mbox_mapping, "vf2pf_mbox", + RTE_CACHE_LINE_SIZE); + if (ret) + goto out; sc->vf2pf_mbox = (struct bnx2x_vf_mbx_msg *) sc->vf2pf_mbox_mapping.vaddr; - if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_bulletin), - &sc->pf2vf_bulletin_mapping, "vf2pf_bull", - RTE_CACHE_LINE_SIZE) != 0) - return -ENOMEM; + ret = bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_bulletin), + &sc->pf2vf_bulletin_mapping, "vf2pf_bull", + RTE_CACHE_LINE_SIZE); + if (ret) + goto out; sc->pf2vf_bulletin = (struct bnx2x_vf_bulletin *) sc->pf2vf_bulletin_mapping.vaddr; @@ -613,10 +729,14 @@ bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf) ret = bnx2x_vf_get_resources(sc, sc->max_tx_queues, sc->max_rx_queues); if (ret) - return ret; + goto out; } return 0; + +out: + bnx2x_periodic_stop(eth_dev); + return ret; } static int diff --git a/drivers/net/bnx2x/bnx2x_ethdev.h b/drivers/net/bnx2x/bnx2x_ethdev.h index 967d6dc5..a53d437d 100644 --- a/drivers/net/bnx2x/bnx2x_ethdev.h +++ b/drivers/net/bnx2x/bnx2x_ethdev.h @@ -58,7 +58,6 @@ #define wmb() rte_wmb() #define rmb() rte_rmb() - #define MAX_QUEUES sysconf(_SC_NPROCESSORS_CONF) #define BNX2X_MIN_RX_BUF_SIZE 1024 @@ -72,6 +71,8 @@ /* Maximum number of Rx packets to process at a time */ #define BNX2X_RX_BUDGET 0xffffffff +#define BNX2X_SP_TIMER_PERIOD US_PER_S /* 1 second */ + #endif /* MAC address operations */ |