net/bnxt: fix speed autonegotiation
[dpdk.git] / drivers / net / ngbe / ngbe_ethdev.c
index a0b7dd9..4a2a9dd 100644 (file)
@@ -89,7 +89,6 @@ static int ngbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
 static int ngbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev);
 static int ngbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static void ngbe_dev_interrupt_handler(void *param);
-static void ngbe_dev_interrupt_delayed_handler(void *param);
 static void ngbe_configure_msix(struct rte_eth_dev *dev);
 
 #define NGBE_SET_HWSTRIP(h, q) do {\
@@ -315,6 +314,7 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
        const struct rte_memzone *mz;
        uint32_t ctrl_ext;
+       u32 led_conf = 0;
        int err, ret;
 
        PMD_INIT_FUNC_TRACE();
@@ -402,6 +402,12 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
                return -EIO;
        }
 
+       err = hw->phy.led_oem_chk(hw, &led_conf);
+       if (err == 0)
+               hw->led_conf = led_conf;
+       else
+               hw->led_conf = 0xFFFF;
+
        err = hw->mac.init_hw(hw);
        if (err != 0) {
                PMD_INIT_LOG(ERR, "Hardware Initialization Failure: %d", err);
@@ -943,12 +949,14 @@ ngbe_dev_start(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
+       /* Stop the link setup handler before resetting the HW. */
+       rte_eal_alarm_cancel(ngbe_dev_setup_link_alarm_handler, dev);
+
        /* disable uio/vfio intr/eventfd mapping */
        rte_intr_disable(intr_handle);
 
        /* stop adapter */
        hw->adapter_stopped = 0;
-       ngbe_stop_hw(hw);
 
        /* reinitialize adapter, this calls reset and start */
        hw->nb_rx_queues = dev->data->nb_rx_queues;
@@ -959,6 +967,8 @@ ngbe_dev_start(struct rte_eth_dev *dev)
        hw->mac.start_hw(hw);
        hw->mac.get_link_status = true;
 
+       ngbe_set_pcie_master(hw, true);
+
        /* configure PF module if SRIOV enabled */
        ngbe_pf_host_configure(dev);
 
@@ -983,7 +993,7 @@ ngbe_dev_start(struct rte_eth_dev *dev)
                }
        }
 
-       /* confiugre MSI-X for sleep until Rx interrupt */
+       /* configure MSI-X for sleep until Rx interrupt */
        ngbe_configure_msix(dev);
 
        /* initialize transmission unit */
@@ -1004,6 +1014,7 @@ ngbe_dev_start(struct rte_eth_dev *dev)
                goto error;
        }
 
+       hw->mac.setup_pba(hw);
        ngbe_configure_port(dev);
 
        err = ngbe_dev_rxtx_start(dev);
@@ -1054,7 +1065,11 @@ ngbe_dev_start(struct rte_eth_dev *dev)
                        speed |= NGBE_LINK_SPEED_10M_FULL;
        }
 
-       hw->phy.init_hw(hw);
+       err = hw->phy.init_hw(hw);
+       if (err != 0) {
+               PMD_INIT_LOG(ERR, "PHY init failed");
+               goto error;
+       }
        err = hw->mac.setup_link(hw, speed, link_up);
        if (err != 0)
                goto error;
@@ -1089,8 +1104,7 @@ skip_link_setup:
        /* resume enabled intr since HW reset */
        ngbe_enable_intr(dev);
 
-       if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-               (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+       if (hw->gpio_ctl) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODATA, 0);
        }
@@ -1131,8 +1145,9 @@ ngbe_dev_stop(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
-       if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-               (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+       rte_eal_alarm_cancel(ngbe_dev_setup_link_alarm_handler, dev);
+
+       if (hw->gpio_ctl) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
        }
@@ -1169,6 +1184,8 @@ ngbe_dev_stop(struct rte_eth_dev *dev)
        rte_intr_efd_disable(intr_handle);
        rte_intr_vec_list_free(intr_handle);
 
+       ngbe_set_pcie_master(hw, true);
+
        adapter->rss_reta_updated = 0;
 
        hw->adapter_stopped = true;
@@ -1197,6 +1214,8 @@ ngbe_dev_close(struct rte_eth_dev *dev)
 
        ngbe_dev_free_queues(dev);
 
+       ngbe_set_pcie_master(hw, false);
+
        /* reprogram the RAR[0] in case user changed it. */
        ngbe_set_rar(hw, 0, hw->mac.addr, 0, true);
 
@@ -1800,6 +1819,24 @@ ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
        return NULL;
 }
 
+void
+ngbe_dev_setup_link_alarm_handler(void *param)
+{
+       struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+       struct ngbe_hw *hw = ngbe_dev_hw(dev);
+       struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
+       u32 speed;
+       bool autoneg = false;
+
+       speed = hw->phy.autoneg_advertised;
+       if (!speed)
+               hw->mac.get_link_capabilities(hw, &speed, &autoneg);
+
+       hw->mac.setup_link(hw, speed, true);
+
+       intr->flags &= ~NGBE_FLAG_NEED_LINK_CONFIG;
+}
+
 /* return 0 means link status changed, -1 means not changed */
 int
 ngbe_dev_link_update_share(struct rte_eth_dev *dev,
@@ -1837,8 +1874,16 @@ ngbe_dev_link_update_share(struct rte_eth_dev *dev,
                return rte_eth_linkstatus_set(dev, &link);
        }
 
-       if (!link_up)
+       if (!link_up) {
+               if (hw->phy.media_type == ngbe_media_type_fiber &&
+                       hw->phy.type != ngbe_phy_mvl_sfi) {
+                       intr->flags |= NGBE_FLAG_NEED_LINK_CONFIG;
+                       rte_eal_alarm_set(10,
+                               ngbe_dev_setup_link_alarm_handler, dev);
+               }
+
                return rte_eth_linkstatus_set(dev, &link);
+       }
 
        intr->flags &= ~NGBE_FLAG_NEED_LINK_CONFIG;
        link.link_status = RTE_ETH_LINK_UP;
@@ -2061,9 +2106,6 @@ ngbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
        struct ngbe_hw *hw = ngbe_dev_hw(dev);
        struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
 
-       /* clear all cause mask */
-       ngbe_disable_intr(hw);
-
        /* read-on-clear nic registers here */
        eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC];
        PMD_DRV_LOG(DEBUG, "eicr %x", eicr);
@@ -2083,6 +2125,8 @@ ngbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
        if (eicr & NGBE_ICRMISC_GPIO)
                intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE;
 
+       ((u32 *)hw->isb_mem)[NGBE_ISB_MISC] = 0;
+
        return 0;
 }
 
@@ -2135,7 +2179,6 @@ static int
 ngbe_dev_interrupt_action(struct rte_eth_dev *dev)
 {
        struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
-       int64_t timeout;
 
        PMD_DRV_LOG(DEBUG, "intr action type %d", intr->flags);
 
@@ -2151,31 +2194,11 @@ ngbe_dev_interrupt_action(struct rte_eth_dev *dev)
                rte_eth_linkstatus_get(dev, &link);
 
                ngbe_dev_link_update(dev, 0);
-
-               /* likely to up */
-               if (link.link_status != RTE_ETH_LINK_UP)
-                       /* handle it 1 sec later, wait it being stable */
-                       timeout = NGBE_LINK_UP_CHECK_TIMEOUT;
-               /* likely to down */
-               else
-                       /* handle it 4 sec later, wait it being stable */
-                       timeout = NGBE_LINK_DOWN_CHECK_TIMEOUT;
-
+               intr->flags &= ~NGBE_FLAG_NEED_LINK_UPDATE;
                ngbe_dev_link_status_print(dev);
-               if (rte_eal_alarm_set(timeout * 1000,
-                                     ngbe_dev_interrupt_delayed_handler,
-                                     (void *)dev) < 0) {
-                       PMD_DRV_LOG(ERR, "Error setting alarm");
-               } else {
-                       /* remember original mask */
-                       intr->mask_misc_orig = intr->mask_misc;
-                       /* only disable lsc interrupt */
-                       intr->mask_misc &= ~NGBE_ICRMISC_PHY;
-
-                       intr->mask_orig = intr->mask;
-                       /* only disable all misc interrupts */
-                       intr->mask &= ~(1ULL << NGBE_MISC_VEC_ID);
-               }
+               if (dev->data->dev_link.link_speed != link.link_speed)
+                       rte_eth_dev_callback_process(dev,
+                               RTE_ETH_EVENT_INTR_LSC, NULL);
        }
 
        PMD_DRV_LOG(DEBUG, "enable intr immediately");
@@ -2184,53 +2207,6 @@ ngbe_dev_interrupt_action(struct rte_eth_dev *dev)
        return 0;
 }
 
-/**
- * Interrupt handler which shall be registered for alarm callback for delayed
- * handling specific interrupt to wait for the stable nic state. As the
- * NIC interrupt state is not stable for ngbe after link is just down,
- * it needs to wait 4 seconds to get the stable status.
- *
- * @param param
- *  The address of parameter (struct rte_eth_dev *) registered before.
- */
-static void
-ngbe_dev_interrupt_delayed_handler(void *param)
-{
-       struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-       struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
-       struct ngbe_hw *hw = ngbe_dev_hw(dev);
-       uint32_t eicr;
-
-       ngbe_disable_intr(hw);
-
-       eicr = ((u32 *)hw->isb_mem)[NGBE_ISB_MISC];
-       if (eicr & NGBE_ICRMISC_VFMBX)
-               ngbe_pf_mbx_process(dev);
-
-       if (intr->flags & NGBE_FLAG_NEED_LINK_UPDATE) {
-               ngbe_dev_link_update(dev, 0);
-               intr->flags &= ~NGBE_FLAG_NEED_LINK_UPDATE;
-               ngbe_dev_link_status_print(dev);
-               rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
-                                             NULL);
-       }
-
-       if (intr->flags & NGBE_FLAG_MACSEC) {
-               rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_MACSEC,
-                                             NULL);
-               intr->flags &= ~NGBE_FLAG_MACSEC;
-       }
-
-       /* restore original mask */
-       intr->mask_misc = intr->mask_misc_orig;
-       intr->mask_misc_orig = 0;
-       intr->mask = intr->mask_orig;
-       intr->mask_orig = 0;
-
-       PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
-       ngbe_enable_intr(dev);
-}
-
 /**
  * Interrupt handler triggered by NIC  for handling
  * specific interrupt.
@@ -2488,7 +2464,7 @@ ngbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
         * scattered packets when this feature has not been enabled before.
         */
        if (dev_data->dev_started && !dev_data->scattered_rx &&
-           (frame_size + 2 * NGBE_VLAN_TAG_SIZE >
+           (frame_size + 2 * RTE_VLAN_HLEN >
             dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)) {
                PMD_INIT_LOG(ERR, "Stop port first.");
                return -EINVAL;
@@ -2641,7 +2617,7 @@ ngbe_set_ivar_map(struct ngbe_hw *hw, int8_t direction,
                wr32(hw, NGBE_IVARMISC, tmp);
        } else {
                /* rx or tx causes */
-               /* Workround for ICR lost */
+               /* Workaround for ICR lost */
                idx = ((16 * (queue & 1)) + (8 * direction));
                tmp = rd32(hw, NGBE_IVAR(queue >> 1));
                tmp &= ~(0xFF << idx);
@@ -2893,7 +2869,7 @@ ngbe_timesync_disable(struct rte_eth_dev *dev)
        /* Disable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */
        wr32(hw, NGBE_ETFLT(NGBE_ETF_ID_1588), 0);
 
-       /* Stop incrementating the System Time registers. */
+       /* Stop incrementing the System Time registers. */
        wr32(hw, NGBE_TSTIMEINC, 0);
 
        return 0;
@@ -3100,6 +3076,7 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = {
        .timesync_adjust_time       = ngbe_timesync_adjust_time,
        .timesync_read_time         = ngbe_timesync_read_time,
        .timesync_write_time        = ngbe_timesync_write_time,
+       .tx_done_cleanup            = ngbe_dev_tx_done_cleanup,
 };
 
 RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd);