i40e: properly parse MDET registers
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / intel / i40e / i40e_main.c
index ed5f1c15fb0f4cd5fe7ce797920fd3b6cd21f7df..1a98e2384b3b4c85bfff613452b1e2edd659174b 100644 (file)
@@ -39,7 +39,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 0
-#define DRV_VERSION_BUILD 11
+#define DRV_VERSION_BUILD 21
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -74,6 +74,7 @@ static const struct pci_device_id i40e_pci_tbl[] = {
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_A), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0},
+       {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0},
        /* required last entry */
        {0, }
 };
@@ -812,7 +813,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        struct i40e_eth_stats *oes;
        struct i40e_eth_stats *es;     /* device's eth stats */
        u32 tx_restart, tx_busy;
+       struct i40e_ring *p;
        u32 rx_page, rx_buf;
+       u64 bytes, packets;
+       unsigned int start;
        u64 rx_p, rx_b;
        u64 tx_p, tx_b;
        u16 q;
@@ -836,10 +840,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        rx_buf = 0;
        rcu_read_lock();
        for (q = 0; q < vsi->num_queue_pairs; q++) {
-               struct i40e_ring *p;
-               u64 bytes, packets;
-               unsigned int start;
-
                /* locate Tx ring */
                p = ACCESS_ONCE(vsi->tx_rings[q]);
 
@@ -2462,10 +2462,14 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
        }
 
        /* Now associate this queue with this PCI function */
-       if (vsi->type == I40E_VSI_VMDQ2)
+       if (vsi->type == I40E_VSI_VMDQ2) {
                qtx_ctl = I40E_QTX_CTL_VM_QUEUE;
-       else
+               qtx_ctl |= ((vsi->id) << I40E_QTX_CTL_VFVM_INDX_SHIFT) &
+                          I40E_QTX_CTL_VFVM_INDX_MASK;
+       } else {
                qtx_ctl = I40E_QTX_CTL_PF_QUEUE;
+       }
+
        qtx_ctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) &
                    I40E_QTX_CTL_PF_INDX_MASK);
        wr32(hw, I40E_QTX_CTL(pf_q), qtx_ctl);
@@ -3440,7 +3444,7 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
                if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
                        break;
 
-               udelay(10);
+               usleep_range(10, 20);
        }
        if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
                return -ETIMEDOUT;
@@ -3466,7 +3470,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
                /* warn the TX unit of coming changes */
                i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable);
                if (!enable)
-                       udelay(10);
+                       usleep_range(10, 20);
 
                for (j = 0; j < 50; j++) {
                        tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
@@ -3526,7 +3530,7 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
                if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
                        break;
 
-               udelay(10);
+               usleep_range(10, 20);
        }
        if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
                return -ETIMEDOUT;
@@ -4449,6 +4453,9 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
        case I40E_LINK_SPEED_1GB:
                strlcpy(speed, "1000 Mbps", SPEED_SIZE);
                break;
+       case I40E_LINK_SPEED_100MB:
+               strncpy(speed, "100 Mbps", SPEED_SIZE);
+               break;
        default:
                break;
        }
@@ -4479,12 +4486,8 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
 static int i40e_up_complete(struct i40e_vsi *vsi)
 {
        struct i40e_pf *pf = vsi->back;
-       u8 set_fc_aq_fail = 0;
        int err;
 
-       /* force flow control off */
-       i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
-
        if (pf->flags & I40E_FLAG_MSIX_ENABLED)
                i40e_vsi_configure_msix(vsi);
        else
@@ -5212,6 +5215,9 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
        int flush_wait_retry = 50;
        int reg;
 
+       if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
+               return;
+
        if (time_after(jiffies, pf->fd_flush_timestamp +
                                (I40E_MIN_FD_FLUSH_INTERVAL * HZ))) {
                set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
@@ -5273,6 +5279,9 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
        if (test_bit(__I40E_DOWN, &pf->state))
                return;
 
+       if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
+               return;
+
        if ((pf->fd_add_err >= I40E_MAX_FD_PROGRAM_ERROR) &&
            (i40e_get_current_atr_cnt(pf) >= pf->fd_atr_cnt) &&
            (i40e_get_current_atr_cnt(pf) > pf->fdir_pf_filter_count))
@@ -5353,14 +5362,21 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up)
 static void i40e_link_event(struct i40e_pf *pf)
 {
        bool new_link, old_link;
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+
+       /* set this to force the get_link_status call to refresh state */
+       pf->hw.phy.get_link_info = true;
 
-       new_link = (pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP);
        old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP);
+       new_link = i40e_get_link_status(&pf->hw);
 
-       if (new_link == old_link)
+       if (new_link == old_link &&
+           (test_bit(__I40E_DOWN, &vsi->state) ||
+            new_link == netif_carrier_ok(vsi->netdev)))
                return;
-       if (!test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state))
-               i40e_print_link_message(pf->vsi[pf->lan_vsi], new_link);
+
+       if (!test_bit(__I40E_DOWN, &vsi->state))
+               i40e_print_link_message(vsi, new_link);
 
        /* Notify the base of the switch tree connected to
         * the link.  Floating VEBs are not notified.
@@ -5368,7 +5384,7 @@ static void i40e_link_event(struct i40e_pf *pf)
        if (pf->lan_veb != I40E_NO_VEB && pf->veb[pf->lan_veb])
                i40e_veb_link_event(pf->veb[pf->lan_veb], new_link);
        else
-               i40e_vsi_link_event(pf->vsi[pf->lan_vsi], new_link);
+               i40e_vsi_link_event(vsi, new_link);
 
        if (pf->vf)
                i40e_vc_notify_link_state(pf);
@@ -5525,33 +5541,20 @@ static void i40e_handle_link_event(struct i40e_pf *pf,
        memcpy(&pf->hw.phy.link_info_old, hw_link_info,
               sizeof(pf->hw.phy.link_info_old));
 
+       /* Do a new status request to re-enable LSE reporting
+        * and load new status information into the hw struct
+        * This completely ignores any state information
+        * in the ARQ event info, instead choosing to always
+        * issue the AQ update link status command.
+        */
+       i40e_link_event(pf);
+
        /* check for unqualified module, if link is down */
        if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
            (!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
            (!(status->link_info & I40E_AQ_LINK_UP)))
                dev_err(&pf->pdev->dev,
                        "The driver failed to link because an unqualified module was detected.\n");
-
-       /* update link status */
-       hw_link_info->phy_type = (enum i40e_aq_phy_type)status->phy_type;
-       hw_link_info->link_speed = (enum i40e_aq_link_speed)status->link_speed;
-       hw_link_info->link_info = status->link_info;
-       hw_link_info->an_info = status->an_info;
-       hw_link_info->ext_info = status->ext_info;
-       hw_link_info->lse_enable =
-               le16_to_cpu(status->command_flags) &
-                           I40E_AQ_LSE_ENABLE;
-
-       /* process the event */
-       i40e_link_event(pf);
-
-       /* Do a new status request to re-enable LSE reporting
-        * and load new status information into the hw struct,
-        * then see if the status changed while processing the
-        * initial event.
-        */
-       i40e_update_link_info(&pf->hw, true);
-       i40e_link_event(pf);
 }
 
 /**
@@ -5967,6 +5970,7 @@ static void i40e_send_version(struct i40e_pf *pf)
 static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
 {
        struct i40e_hw *hw = &pf->hw;
+       u8 set_fc_aq_fail = 0;
        i40e_status ret;
        u32 v;
 
@@ -6038,6 +6042,20 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
        if (ret)
                goto end_core_reset;
 
+       /* driver is only interested in link up/down and module qualification
+        * reports from firmware
+        */
+       ret = i40e_aq_set_phy_int_mask(&pf->hw,
+                                      I40E_AQ_EVENT_LINK_UPDOWN |
+                                      I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
+       if (ret)
+               dev_info(&pf->pdev->dev, "set phy mask fail, aq_err %d\n", ret);
+
+       /* make sure our flow control settings are restored */
+       ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
+       if (ret)
+               dev_info(&pf->pdev->dev, "set fc fail, aq_err %d\n", ret);
+
        /* Rebuild the VSIs and VEBs that existed before reset.
         * They are still in our local switch element arrays, so only
         * need to rebuild the switch model in the HW.
@@ -6092,6 +6110,13 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                }
        }
 
+       msleep(75);
+       ret = i40e_aq_set_link_restart_an(&pf->hw, true, NULL);
+       if (ret) {
+               dev_info(&pf->pdev->dev, "link restart failed, aq_err=%d\n",
+                        pf->hw.aq.asq_last_status);
+       }
+
        /* reinit the misc interrupt */
        if (pf->flags & I40E_FLAG_MSIX_ENABLED)
                ret = i40e_setup_misc_vector(pf);
@@ -6149,12 +6174,13 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
        if (reg & I40E_GL_MDET_TX_VALID_MASK) {
                u8 pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >>
                                I40E_GL_MDET_TX_PF_NUM_SHIFT;
-               u8 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
+               u16 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
                                I40E_GL_MDET_TX_VF_NUM_SHIFT;
-               u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) >>
+               u8 event = (reg & I40E_GL_MDET_TX_EVENT_MASK) >>
                                I40E_GL_MDET_TX_EVENT_SHIFT;
-               u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
-                               I40E_GL_MDET_TX_QUEUE_SHIFT;
+               u16 queue = ((reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
+                               I40E_GL_MDET_TX_QUEUE_SHIFT) -
+                               pf->hw.func_caps.base_queue;
                if (netif_msg_tx_err(pf))
                        dev_info(&pf->pdev->dev, "Malicious Driver Detection event 0x%02x on TX queue %d pf number 0x%02x vf number 0x%02x\n",
                                 event, queue, pf_num, vf_num);
@@ -6165,10 +6191,11 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
        if (reg & I40E_GL_MDET_RX_VALID_MASK) {
                u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >>
                                I40E_GL_MDET_RX_FUNCTION_SHIFT;
-               u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT) >>
+               u8 event = (reg & I40E_GL_MDET_RX_EVENT_MASK) >>
                                I40E_GL_MDET_RX_EVENT_SHIFT;
-               u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
-                               I40E_GL_MDET_RX_QUEUE_SHIFT;
+               u16 queue = ((reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
+                               I40E_GL_MDET_RX_QUEUE_SHIFT) -
+                               pf->hw.func_caps.base_queue;
                if (netif_msg_rx_err(pf))
                        dev_info(&pf->pdev->dev, "Malicious Driver Detection event 0x%02x on RX queue %d of function 0x%02x\n",
                                 event, queue, func);
@@ -6305,6 +6332,8 @@ static void i40e_service_task(struct work_struct *work)
 #endif
        i40e_clean_adminq_subtask(pf);
 
+       i40e_link_event(pf);
+
        i40e_service_event_complete(pf);
 
        /* If the tasks have taken longer than one timer cycle or there
@@ -6676,6 +6705,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
 {
        i40e_status err = 0;
        struct i40e_hw *hw = &pf->hw;
+       int other_vecs = 0;
        int v_budget, i;
        int vec;
 
@@ -6701,10 +6731,10 @@ static int i40e_init_msix(struct i40e_pf *pf)
         */
        pf->num_lan_msix = pf->num_lan_qps - (pf->rss_size_max - pf->rss_size);
        pf->num_vmdq_msix = pf->num_vmdq_qps;
-       v_budget = 1 + pf->num_lan_msix;
-       v_budget += (pf->num_vmdq_vsis * pf->num_vmdq_msix);
+       other_vecs = 1;
+       other_vecs += (pf->num_vmdq_vsis * pf->num_vmdq_msix);
        if (pf->flags & I40E_FLAG_FD_SB_ENABLED)
-               v_budget++;
+               other_vecs++;
 
 #ifdef I40E_FCOE
        if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
@@ -6714,7 +6744,9 @@ static int i40e_init_msix(struct i40e_pf *pf)
 
 #endif
        /* Scale down if necessary, and the rings will share vectors */
-       v_budget = min_t(int, v_budget, hw->func_caps.num_msix_vectors);
+       pf->num_lan_msix = min_t(int, pf->num_lan_msix,
+                       (hw->func_caps.num_msix_vectors - other_vecs));
+       v_budget = pf->num_lan_msix + other_vecs;
 
        pf->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry),
                                   GFP_KERNEL);
@@ -7931,8 +7963,8 @@ static int i40e_vsi_setup_vectors(struct i40e_vsi *vsi)
                                                 vsi->num_q_vectors, vsi->idx);
        if (vsi->base_vector < 0) {
                dev_info(&pf->pdev->dev,
-                        "failed to get queue tracking for VSI %d, err=%d\n",
-                        vsi->seid, vsi->base_vector);
+                        "failed to get tracking for %d vectors for VSI %d, err=%d\n",
+                        vsi->num_q_vectors, vsi->seid, vsi->base_vector);
                i40e_vsi_free_q_vectors(vsi);
                ret = -ENOENT;
                goto vector_setup_out;
@@ -7968,8 +8000,9 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
 
        ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs, vsi->idx);
        if (ret < 0) {
-               dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n",
-                        vsi->seid, ret);
+               dev_info(&pf->pdev->dev,
+                        "failed to get tracking for %d queues for VSI %d err=%d\n",
+                        vsi->alloc_queue_pairs, vsi->seid, ret);
                goto err_vsi;
        }
        vsi->base_queue = ret;
@@ -8098,8 +8131,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
        ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs,
                                vsi->idx);
        if (ret < 0) {
-               dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n",
-                        vsi->seid, ret);
+               dev_info(&pf->pdev->dev,
+                        "failed to get tracking for %d queues for VSI %d err=%d\n",
+                        vsi->alloc_queue_pairs, vsi->seid, ret);
                goto err_vsi;
        }
        vsi->base_queue = ret;
@@ -8715,6 +8749,14 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
        i40e_update_link_info(&pf->hw, true);
        i40e_link_event(pf);
 
+       /* Initialize user-specific link properties */
+       pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
+                                 I40E_AQ_AN_COMPLETED) ? true : false);
+
+       /* fill in link information and enable LSE reporting */
+       i40e_update_link_info(&pf->hw, true);
+       i40e_link_event(pf);
+
        /* Initialize user-specific link properties */
        pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
                                  I40E_AQ_AN_COMPLETED) ? true : false);
@@ -8987,6 +9029,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->bus.func = PCI_FUNC(pdev->devfn);
        pf->instance = pfs_found;
 
+       if (debug != -1) {
+               pf->msg_enable = pf->hw.debug_mask;
+               pf->msg_enable = debug;
+       }
+
        /* do a special CORER for clearing PXE mode once at init */
        if (hw->revision_id == 0 &&
            (rd32(hw, I40E_GLLAN_RCTL_0) & I40E_GLLAN_RCTL_0_PXE_MODE_MASK)) {
@@ -9158,6 +9205,22 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       /* driver is only interested in link up/down and module qualification
+        * reports from firmware
+        */
+       err = i40e_aq_set_phy_int_mask(&pf->hw,
+                                      I40E_AQ_EVENT_LINK_UPDOWN |
+                                      I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
+       if (err)
+               dev_info(&pf->pdev->dev, "set phy mask fail, aq_err %d\n", err);
+
+       msleep(75);
+       err = i40e_aq_set_link_restart_an(&pf->hw, true, NULL);
+       if (err) {
+               dev_info(&pf->pdev->dev, "link restart failed, aq_err=%d\n",
+                        pf->hw.aq.asq_last_status);
+       }
+
        /* The main driver is (mostly) up and happy. We need to set this state
         * before setting up the misc vector or we get a race and the vector
         * ends up disabled forever.