diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 484 |
1 files changed, 324 insertions, 160 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 275ca9a1719e..c34e39009a8f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 10 +#define DRV_VERSION_BUILD 21 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN @@ -278,7 +278,7 @@ static void i40e_tx_timeout(struct net_device *netdev) pf->tx_timeout_count++; if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20))) - pf->tx_timeout_recovery_level = 0; + pf->tx_timeout_recovery_level = 1; pf->tx_timeout_last_recovery = jiffies; netdev_info(netdev, "tx_timeout recovery level %d\n", pf->tx_timeout_recovery_level); @@ -304,8 +304,8 @@ static void i40e_tx_timeout(struct net_device *netdev) break; default: netdev_err(netdev, "tx_timeout recovery unsuccessful\n"); - set_bit(__I40E_DOWN, &vsi->state); - i40e_down(vsi); + set_bit(__I40E_DOWN_REQUESTED, &pf->state); + set_bit(__I40E_DOWN_REQUESTED, &vsi->state); break; } i40e_service_event_schedule(pf); @@ -444,9 +444,21 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi) **/ void i40e_pf_reset_stats(struct i40e_pf *pf) { + int i; + memset(&pf->stats, 0, sizeof(pf->stats)); memset(&pf->stats_offsets, 0, sizeof(pf->stats_offsets)); pf->stat_offsets_loaded = false; + + for (i = 0; i < I40E_MAX_VEB; i++) { + if (pf->veb[i]) { + memset(&pf->veb[i]->stats, 0, + sizeof(pf->veb[i]->stats)); + memset(&pf->veb[i]->stats_offsets, 0, + sizeof(pf->veb[i]->stats_offsets)); + pf->veb[i]->stat_offsets_loaded = false; + } + } } /** @@ -1315,9 +1327,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p) netdev_info(netdev, "set mac address=%pM\n", addr->sa_data); - if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) - return 0; - if (test_bit(__I40E_DOWN, &vsi->back->state) || test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return -EADDRNOTAVAIL; @@ -1325,7 +1334,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) if (vsi->type == I40E_VSI_MAIN) { i40e_status ret; ret = i40e_aq_mac_address_write(&vsi->back->hw, - I40E_AQC_WRITE_TYPE_LAA_ONLY, + I40E_AQC_WRITE_TYPE_LAA_WOL, addr->sa_data, NULL); if (ret) { netdev_info(netdev, @@ -1333,22 +1342,27 @@ static int i40e_set_mac(struct net_device *netdev, void *p) ret); return -EADDRNOTAVAIL; } - - ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data); } - /* In order to be sure to not drop any packets, add the new address - * then delete the old one. - */ - f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false); - if (!f) - return -ENOMEM; + f = i40e_find_mac(vsi, addr->sa_data, false, true); + if (!f) { + /* In order to be sure to not drop any packets, add the + * new address first then delete the old one. + */ + f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, + false, false); + if (!f) + return -ENOMEM; - i40e_sync_vsi_filters(vsi); - i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false); - i40e_sync_vsi_filters(vsi); + i40e_sync_vsi_filters(vsi); + i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, + false, false); + i40e_sync_vsi_filters(vsi); + } - ether_addr_copy(netdev->dev_addr, addr->sa_data); + f->is_laa = true; + if (!ether_addr_equal(netdev->dev_addr, addr->sa_data)) + ether_addr_copy(netdev->dev_addr, addr->sa_data); return 0; } @@ -2387,10 +2401,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) rx_ctx.rxmax = min_t(u16, vsi->max_frame, (chain_len * ring->rx_buf_len)); - rx_ctx.tphrdesc_ena = 1; - rx_ctx.tphwdesc_ena = 1; - rx_ctx.tphdata_ena = 1; - rx_ctx.tphhead_ena = 1; if (hw->revision_id == 0) rx_ctx.lrxqthresh = 0; else @@ -2756,6 +2766,22 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) } /** + * i40e_irq_dynamic_disable - Disable default interrupt generation settings + * @vsi: pointer to a vsi + * @vector: enable a particular Hw Interrupt vector + **/ +void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + u32 val; + + val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT; + wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val); + i40e_flush(hw); +} + +/** * i40e_msix_clean_rings - MSIX mode Interrupt Handler * @irq: interrupt number * @data: pointer to a q_vector @@ -3057,16 +3083,33 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) /* clear next_to_watch to prevent false hangs */ tx_buf->next_to_watch = NULL; + tx_desc->buffer_addr = 0; + tx_desc->cmd_type_offset_bsz = 0; + /* move past filter desc */ + tx_buf++; + tx_desc++; + i++; + if (unlikely(!i)) { + i -= tx_ring->count; + tx_buf = tx_ring->tx_bi; + tx_desc = I40E_TX_DESC(tx_ring, 0); + } /* unmap skb header data */ dma_unmap_single(tx_ring->dev, dma_unmap_addr(tx_buf, dma), dma_unmap_len(tx_buf, len), DMA_TO_DEVICE); + if (tx_buf->tx_flags & I40E_TX_FLAGS_FD_SB) + kfree(tx_buf->raw_buf); + tx_buf->raw_buf = NULL; + tx_buf->tx_flags = 0; + tx_buf->next_to_watch = NULL; dma_unmap_len_set(tx_buf, len, 0); + tx_desc->buffer_addr = 0; + tx_desc->cmd_type_offset_bsz = 0; - - /* move to the next desc and buffer to clean */ + /* move us past the eop_desc for start of next FD desc */ tx_buf++; tx_desc++; i++; @@ -3151,8 +3194,12 @@ static void i40e_vsi_map_rings_to_vectors(struct i40e_vsi *vsi) /* If we don't have enough vectors for a 1-to-1 mapping, we'll have to * group them so there are multiple queues per vector. + * It is also important to go through all the vectors available to be + * sure that if we don't use all the vectors, that the remaining vectors + * are cleared. This is especially important when decreasing the + * number of queues in use. */ - for (; v_start < q_vectors && qp_remaining; v_start++) { + for (; v_start < q_vectors; v_start++) { struct i40e_q_vector *q_vector = vsi->q_vectors[v_start]; num_ringpairs = DIV_ROUND_UP(qp_remaining, q_vectors - v_start); @@ -3228,6 +3275,35 @@ static void i40e_netpoll(struct net_device *netdev) #endif /** + * i40e_pf_txq_wait - Wait for a PF's Tx queue to be enabled or disabled + * @pf: the PF being configured + * @pf_q: the PF queue + * @enable: enable or disable state of the queue + * + * This routine will wait for the given Tx queue of the PF to reach the + * enabled or disabled state. + * Returns -ETIMEDOUT in case of failing to reach the requested state after + * multiple retries; else will return 0 in case of success. + **/ +static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable) +{ + int i; + u32 tx_reg; + + for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) { + tx_reg = rd32(&pf->hw, I40E_QTX_ENA(pf_q)); + if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) + break; + + udelay(10); + } + if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT) + return -ETIMEDOUT; + + return 0; +} + +/** * i40e_vsi_control_tx - Start or stop a VSI's rings * @vsi: the VSI being configured * @enable: start or stop the rings @@ -3236,7 +3312,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) { struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; - int i, j, pf_q; + int i, j, pf_q, ret = 0; u32 tx_reg; pf_q = vsi->base_queue; @@ -3269,22 +3345,46 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) wr32(hw, I40E_QTX_ENA(pf_q), tx_reg); /* wait for the change to finish */ - for (j = 0; j < 10; j++) { - tx_reg = rd32(hw, I40E_QTX_ENA(pf_q)); - if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) - break; - - udelay(10); - } - if (j >= 10) { - dev_info(&pf->pdev->dev, "Tx ring %d %sable timeout\n", - pf_q, (enable ? "en" : "dis")); - return -ETIMEDOUT; + ret = i40e_pf_txq_wait(pf, pf_q, enable); + if (ret) { + dev_info(&pf->pdev->dev, + "%s: VSI seid %d Tx ring %d %sable timeout\n", + __func__, vsi->seid, pf_q, + (enable ? "en" : "dis")); + break; } } if (hw->revision_id == 0) mdelay(50); + return ret; +} + +/** + * i40e_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled + * @pf: the PF being configured + * @pf_q: the PF queue + * @enable: enable or disable state of the queue + * + * This routine will wait for the given Rx queue of the PF to reach the + * enabled or disabled state. + * Returns -ETIMEDOUT in case of failing to reach the requested state after + * multiple retries; else will return 0 in case of success. + **/ +static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable) +{ + int i; + u32 rx_reg; + + for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) { + rx_reg = rd32(&pf->hw, I40E_QRX_ENA(pf_q)); + if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) + break; + + udelay(10); + } + if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT) + return -ETIMEDOUT; return 0; } @@ -3298,7 +3398,7 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) { struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; - int i, j, pf_q; + int i, j, pf_q, ret = 0; u32 rx_reg; pf_q = vsi->base_queue; @@ -3323,22 +3423,17 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) wr32(hw, I40E_QRX_ENA(pf_q), rx_reg); /* wait for the change to finish */ - for (j = 0; j < 10; j++) { - rx_reg = rd32(hw, I40E_QRX_ENA(pf_q)); - - if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) - break; - - udelay(10); - } - if (j >= 10) { - dev_info(&pf->pdev->dev, "Rx ring %d %sable timeout\n", - pf_q, (enable ? "en" : "dis")); - return -ETIMEDOUT; + ret = i40e_pf_rxq_wait(pf, pf_q, enable); + if (ret) { + dev_info(&pf->pdev->dev, + "%s: VSI seid %d Rx ring %d %sable timeout\n", + __func__, vsi->seid, pf_q, + (enable ? "en" : "dis")); + break; } } - return 0; + return ret; } /** @@ -4231,8 +4326,12 @@ 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 @@ -4640,6 +4739,23 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) /* no further action needed, so return now */ return; + } else if (reset_flags & (1 << __I40E_DOWN_REQUESTED)) { + int v; + + /* Find the VSI(s) that needs to be brought down */ + dev_info(&pf->pdev->dev, "VSI down requested\n"); + for (v = 0; v < pf->num_alloc_vsi; v++) { + struct i40e_vsi *vsi = pf->vsi[v]; + if (vsi != NULL && + test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) { + set_bit(__I40E_DOWN, &vsi->state); + i40e_down(vsi); + clear_bit(__I40E_DOWN_REQUESTED, &vsi->state); + } + } + + /* no further action needed, so return now */ + return; } else { dev_info(&pf->pdev->dev, "bad reset request 0x%08x\n", reset_flags); @@ -4845,7 +4961,20 @@ static void i40e_service_event_complete(struct i40e_pf *pf) } /** - * i40e_get_current_fd_count - Get the count of FD filters programmed in the HW + * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters + * @pf: board private structure + **/ +int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf) +{ + int val, fcnt_prog; + + val = rd32(&pf->hw, I40E_PFQF_FDSTAT); + fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK); + return fcnt_prog; +} + +/** + * i40e_get_current_fd_count - Get the count of total FD filters programmed * @pf: board private structure **/ int i40e_get_current_fd_count(struct i40e_pf *pf) @@ -4857,7 +4986,6 @@ int i40e_get_current_fd_count(struct i40e_pf *pf) I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); return fcnt_prog; } - /** * i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled * @pf: board private structure @@ -4872,8 +5000,8 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf) if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && (pf->flags & I40E_FLAG_FD_SB_ENABLED)) return; - fcnt_prog = i40e_get_current_fd_count(pf); - fcnt_avail = i40e_get_fd_cnt_all(pf); + fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf); + fcnt_avail = pf->fdir_pf_filter_count; if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) { if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) && (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) { @@ -5110,6 +5238,10 @@ static void i40e_reset_subtask(struct i40e_pf *pf) reset_flags |= (1 << __I40E_GLOBAL_RESET_REQUESTED); clear_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state); } + if (test_bit(__I40E_DOWN_REQUESTED, &pf->state)) { + reset_flags |= (1 << __I40E_DOWN_REQUESTED); + clear_bit(__I40E_DOWN_REQUESTED, &pf->state); + } /* If there's a recovery already waiting, it takes * precedence before starting a new reset sequence. @@ -5164,7 +5296,7 @@ static void i40e_handle_link_event(struct i40e_pf *pf, * then see if the status changed while processing the * initial event. */ - i40e_aq_get_link_info(&pf->hw, true, NULL, NULL); + i40e_update_link_info(&pf->hw, true); i40e_link_event(pf); } @@ -5182,9 +5314,6 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) u32 oldval; u32 val; - if (!test_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state)) - return; - /* check for error indications */ val = rd32(&pf->hw, pf->hw.aq.arq.len); oldval = val; @@ -5228,10 +5357,9 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) do { event.msg_size = I40E_MAX_AQ_BUF_SIZE; /* reinit each time */ ret = i40e_clean_arq_element(hw, &event, &pending); - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) { - dev_info(&pf->pdev->dev, "No ARQ event found\n"); + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) break; - } else if (ret) { + else if (ret) { dev_info(&pf->pdev->dev, "ARQ event error %d\n", ret); break; } @@ -5463,6 +5591,20 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf) struct i40e_vsi *vsi; int i; + /* quick workaround for an NVM issue that leaves a critical register + * uninitialized + */ + if (!rd32(&pf->hw, I40E_GLQF_HKEY(0))) { + static const u32 hkey[] = { + 0xe640d33f, 0xcdfe98ab, 0x73fa7161, 0x0d7a7d36, + 0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb, + 0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21, + 0x95b3a76d}; + + for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++) + wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]); + } + if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED)) return; @@ -5512,7 +5654,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) * * Close up the VFs and other things in prep for pf Reset. **/ -static int i40e_prep_for_reset(struct i40e_pf *pf) +static void i40e_prep_for_reset(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; i40e_status ret = 0; @@ -5520,7 +5662,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) - return 0; + return; dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n"); @@ -5537,13 +5679,10 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) /* call shutdown HMC */ if (hw->hmc.hmc_obj) { ret = i40e_shutdown_lan_hmc(hw); - if (ret) { + if (ret) dev_warn(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); - clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); - } } - return ret; } /** @@ -5679,7 +5818,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } if (pf->vsi[pf->lan_vsi]->uplink_seid == pf->mac_seid) { - dev_info(&pf->pdev->dev, "attempting to rebuild PF VSI\n"); + dev_dbg(&pf->pdev->dev, "attempting to rebuild PF VSI\n"); /* no VEB, so rebuild only the Main VSI */ ret = i40e_add_vsi(pf->vsi[pf->lan_vsi]); if (ret) { @@ -5717,11 +5856,8 @@ end_core_reset: **/ static void i40e_handle_reset_warning(struct i40e_pf *pf) { - i40e_status ret; - - ret = i40e_prep_for_reset(pf); - if (!ret) - i40e_reset_and_rebuild(pf, false); + i40e_prep_for_reset(pf); + i40e_reset_and_rebuild(pf, false); } /** @@ -5734,6 +5870,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; bool mdd_detected = false; + bool pf_mdd_detected = false; struct i40e_vf *vf; u32 reg; int i; @@ -5744,26 +5881,28 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) /* find what triggered the MDD event */ reg = rd32(hw, I40E_GL_MDET_TX); if (reg & I40E_GL_MDET_TX_VALID_MASK) { - u8 func = (reg & I40E_GL_MDET_TX_FUNCTION_MASK) - >> I40E_GL_MDET_TX_FUNCTION_SHIFT; - u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) - >> I40E_GL_MDET_TX_EVENT_SHIFT; - u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) - >> I40E_GL_MDET_TX_QUEUE_SHIFT; + 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) >> + I40E_GL_MDET_TX_VF_NUM_SHIFT; + u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) >> + I40E_GL_MDET_TX_EVENT_SHIFT; + u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >> + I40E_GL_MDET_TX_QUEUE_SHIFT; dev_info(&pf->pdev->dev, - "Malicious Driver Detection event 0x%02x on TX queue %d of function 0x%02x\n", - event, queue, func); + "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); wr32(hw, I40E_GL_MDET_TX, 0xffffffff); mdd_detected = true; } reg = rd32(hw, I40E_GL_MDET_RX); 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) - >> I40E_GL_MDET_RX_EVENT_SHIFT; - u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) - >> I40E_GL_MDET_RX_QUEUE_SHIFT; + u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >> + I40E_GL_MDET_RX_FUNCTION_SHIFT; + u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT) >> + I40E_GL_MDET_RX_EVENT_SHIFT; + u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >> + I40E_GL_MDET_RX_QUEUE_SHIFT; dev_info(&pf->pdev->dev, "Malicious Driver Detection event 0x%02x on RX queue %d of function 0x%02x\n", event, queue, func); @@ -5771,6 +5910,30 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) mdd_detected = true; } + if (mdd_detected) { + reg = rd32(hw, I40E_PF_MDET_TX); + if (reg & I40E_PF_MDET_TX_VALID_MASK) { + wr32(hw, I40E_PF_MDET_TX, 0xFFFF); + dev_info(&pf->pdev->dev, + "MDD TX event is for this function 0x%08x, requesting PF reset.\n", + reg); + pf_mdd_detected = true; + } + reg = rd32(hw, I40E_PF_MDET_RX); + if (reg & I40E_PF_MDET_RX_VALID_MASK) { + wr32(hw, I40E_PF_MDET_RX, 0xFFFF); + dev_info(&pf->pdev->dev, + "MDD RX event is for this function 0x%08x, requesting PF reset.\n", + reg); + pf_mdd_detected = true; + } + /* Queue belongs to the PF, initiate a reset */ + if (pf_mdd_detected) { + set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); + i40e_service_event_schedule(pf); + } + } + /* see if one of the VFs needs its hand slapped */ for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) { vf = &(pf->vf[i]); @@ -5860,6 +6023,12 @@ static void i40e_service_task(struct work_struct *work) service_task); unsigned long start_time = jiffies; + /* don't bother with service tasks if a reset is in progress */ + if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) { + i40e_service_event_complete(pf); + return; + } + i40e_reset_subtask(pf); i40e_handle_mdd_event(pf); i40e_vc_process_vflr_event(pf); @@ -6492,6 +6661,7 @@ static int i40e_config_rss(struct i40e_pf *pf) u32 lut = 0; int i, j; u64 hena; + u32 reg_val; /* Fill out hash function seed */ for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) @@ -6504,8 +6674,19 @@ static int i40e_config_rss(struct i40e_pf *pf) wr32(hw, I40E_PFQF_HENA(0), (u32)hena); wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32)); + /* Check capability and Set table size and register per hw expectation*/ + reg_val = rd32(hw, I40E_PFQF_CTL_0); + if (hw->func_caps.rss_table_size == 512) { + reg_val |= I40E_PFQF_CTL_0_HASHLUTSIZE_512; + pf->rss_table_size = 512; + } else { + pf->rss_table_size = 128; + reg_val &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_512; + } + wr32(hw, I40E_PFQF_CTL_0, reg_val); + /* Populate the LUT with max no. of queues in round robin fashion */ - for (i = 0, j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) { + for (i = 0, j = 0; i < pf->rss_table_size; i++, j++) { /* The assumption is that lan qp count will be the highest * qp count for any PF VSI that needs RSS. @@ -6592,13 +6773,12 @@ static int i40e_sw_init(struct i40e_pf *pf) * maximum might end up larger than the available queues */ pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width; + pf->rss_size = 1; pf->rss_size_max = min_t(int, pf->rss_size_max, pf->hw.func_caps.num_tx_qp); if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus()); - } else { - pf->rss_size = 1; } /* MFP mode enabled */ @@ -6670,6 +6850,8 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->irq_pile->num_entries = pf->hw.func_caps.num_msix_vectors; pf->irq_pile->search_hint = 0; + pf->tx_timeout_recovery_level = 1; + mutex_init(&pf->switch_mutex); sw_init_done: @@ -6702,9 +6884,11 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features) i40e_fdir_filter_exit(pf); } pf->flags &= ~I40E_FLAG_FD_SB_ENABLED; - /* if ATR was disabled it can be re-enabled. */ - if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) - pf->flags |= I40E_FLAG_FD_ATR_ENABLED; + pf->auto_disable_flags &= ~I40E_FLAG_FD_SB_ENABLED; + /* if ATR was auto disabled it can be re-enabled. */ + if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && + (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED)) + pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED; } return need_reset; } @@ -6833,6 +7017,22 @@ static void i40e_del_vxlan_port(struct net_device *netdev, } #endif +static int i40e_get_phys_port_id(struct net_device *netdev, + struct netdev_phys_port_id *ppid) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + struct i40e_hw *hw = &pf->hw; + + if (!(pf->flags & I40E_FLAG_PORT_ID_VALID)) + return -EOPNOTSUPP; + + ppid->id_len = min_t(int, sizeof(hw->mac.port_addr), sizeof(ppid->id)); + memcpy(ppid->id, hw->mac.port_addr, ppid->id_len); + + return 0; +} + #ifdef HAVE_FDB_OPS #ifdef USE_CONST_DEV_UC_CHAR static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], @@ -6910,13 +7110,14 @@ static int i40e_ndo_fdb_del(struct ndmsg *ndm, static int i40e_ndo_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, + struct net_device *filter_dev, int idx) { struct i40e_netdev_priv *np = netdev_priv(dev); struct i40e_pf *pf = np->vsi->back; if (pf->flags & I40E_FLAG_SRIOV_ENABLED) - idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); + idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx); return idx; } @@ -6951,6 +7152,7 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_add_vxlan_port = i40e_add_vxlan_port, .ndo_del_vxlan_port = i40e_del_vxlan_port, #endif + .ndo_get_phys_port_id = i40e_get_phys_port_id, #ifdef HAVE_FDB_OPS .ndo_fdb_add = i40e_ndo_fdb_add, #ifndef USE_DEFAULT_FDB_DEL_DUMP @@ -7223,6 +7425,12 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { f->changed = true; f_count++; + + if (f->is_laa && vsi->type == I40E_VSI_MAIN) { + i40e_aq_mac_address_write(&vsi->back->hw, + I40E_AQC_WRITE_TYPE_LAA_WOL, + f->macaddr, NULL); + } } if (f_count) { vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; @@ -8090,7 +8298,6 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) **/ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) { - u32 rxfc = 0, txfc = 0, rxfc_reg; int ret; /* find out what's out there already */ @@ -8150,68 +8357,13 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) i40e_config_rss(pf); /* fill in link information and enable LSE reporting */ - i40e_aq_get_link_info(&pf->hw, true, NULL, NULL); + 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); - /* requested_mode is set in probe or by ethtool */ - if (!pf->fc_autoneg_status) - goto no_autoneg; - - if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) && - (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)) - pf->hw.fc.current_mode = I40E_FC_FULL; - else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) - pf->hw.fc.current_mode = I40E_FC_TX_PAUSE; - else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) - pf->hw.fc.current_mode = I40E_FC_RX_PAUSE; - else - pf->hw.fc.current_mode = I40E_FC_NONE; - /* sync the flow control settings with the auto-neg values */ - switch (pf->hw.fc.current_mode) { - case I40E_FC_FULL: - txfc = 1; - rxfc = 1; - break; - case I40E_FC_TX_PAUSE: - txfc = 1; - rxfc = 0; - break; - case I40E_FC_RX_PAUSE: - txfc = 0; - rxfc = 1; - break; - case I40E_FC_NONE: - case I40E_FC_DEFAULT: - txfc = 0; - rxfc = 0; - break; - case I40E_FC_PFC: - /* TBD */ - break; - /* no default case, we have to handle all possibilities here */ - } - - wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT); - - rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) & - ~I40E_PRTDCB_MFLCN_RFCE_MASK; - rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT); - - wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg); - - goto fc_complete; - -no_autoneg: - /* disable L2 flow control, user can turn it on if they wish */ - wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0); - wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) & - ~I40E_PRTDCB_MFLCN_RFCE_MASK); - -fc_complete: i40e_ptp_init(pf); return ret; @@ -8460,6 +8612,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Reset here to make sure all is clean and to define PF 'n' */ + i40e_clear_hw(hw); err = i40e_pf_reset(hw); if (err) { dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err); @@ -8495,6 +8648,20 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_pf_reset; } + if (hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) + dev_info(&pdev->dev, + "Note: FW API version %02x.%02x newer than expected %02x.%02x, recommend driver update.\n", + hw->aq.api_maj_ver, hw->aq.api_min_ver, + I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR); + + if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR || + hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR-1)) + dev_info(&pdev->dev, + "Note: FW API version %02x.%02x older than expected %02x.%02x, recommend nvm update.\n", + hw->aq.api_maj_ver, hw->aq.api_min_ver, + I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR); + + i40e_verify_eeprom(pf); /* Rev 0 hardware was never productized */ @@ -8535,6 +8702,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } dev_info(&pdev->dev, "MAC address: %pM\n", hw->mac.addr); ether_addr_copy(hw->mac.perm_addr, hw->mac.addr); + i40e_get_port_mac_addr(hw, hw->mac.port_addr); + if (is_valid_ether_addr(hw->mac.port_addr)) + pf->flags |= I40E_FLAG_PORT_ID_VALID; pci_set_drvdata(pdev, pf); pci_save_state(pdev); @@ -8722,7 +8892,6 @@ static void i40e_remove(struct pci_dev *pdev) { struct i40e_pf *pf = pci_get_drvdata(pdev); i40e_status ret_code; - u32 reg; int i; i40e_dbg_pf_exit(pf); @@ -8800,11 +8969,6 @@ static void i40e_remove(struct pci_dev *pdev) kfree(pf->irq_pile); kfree(pf->vsi); - /* force a PF reset to clean anything leftover */ - reg = rd32(&pf->hw, I40E_PFGEN_CTRL); - wr32(&pf->hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); - i40e_flush(&pf->hw); - iounmap(pf->hw.hw_addr); kfree(pf); pci_release_selected_regions(pdev, |