diff options
| author | David S. Miller <davem@davemloft.net> | 2020-01-04 17:02:19 -0800 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2020-01-04 17:02:19 -0800 |
| commit | 4460985fac06f8e0e5bd4b86dcef49ada451583c (patch) | |
| tree | 47a857e32bf3c0601853068d6eaea9194166b3f3 /drivers/net/ethernet/intel/ice/ice_lib.c | |
| parent | 3c85efb8f15ffa5bd165881b9fd1f9e5dd1d705f (diff) | |
| parent | 5d9e618cbb54f5cbaef7f6f44ceb919978f0e5bc (diff) | |
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue
Jeff Kirsher says:
====================
100GbE Intel Wired LAN Driver Updates 2020-01-03
This series contains updates to the ice driver only.
Brett adds support for UDP segmentation offload (USO) based on the work
Alex Duyck did for other Intel drivers. Refactored how the VF sets
spoof checking to resolve a couple of issues found in
ice_set_vf_spoofchk(). Adds the ability to track of the dflt_vsI
(default VSI), since we cannot have more than one default VSI. Add a
macro for commonly used "for loop" used repeatedly in the code. Cleaned
up and made the VF link flows all similar. Refactor the flows of adding
and deleting MAC addresses in order to simplify the logic for error
conditions and setting/clearing the VF's default MAC address field.
Michal moves the setting of the default ITR value from ice_cfg_itr() to
the function we allocate queue vectors. Adds support for saving and
restoring the ITR value for each queue. Adds a check for all invalid
or unused parameters to log the information and return an error.
Vignesh cleans up the driver where we were trying to write to read-only
registers for the receive flex descriptors.
Tony changes a netdev_info() to netdev_dbg() when the MTU value is
changed.
Bruce suppresses a coverity reported error that was not really an error
by adding a code comment.
Mitch adds a check for a NULL receive descriptor to resolve a coverity
reported issue.
Krzysztof prevents a potential general protection fault by adding a
boundary check to see if the queue id is greater than the size of a UMEM
array. Adds additional code comments to assist coverity in its scans to
prevent false positives.
Jake adds support for E822 devices to the driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_lib.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.c | 254 |
1 files changed, 238 insertions, 16 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index e7449248fab4..4cfad81ba496 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -817,12 +817,23 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi) ctxt->info.valid_sections |= cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); - /* Enable MAC Antispoof with new VSI being initialized or updated */ - if (vsi->type == ICE_VSI_VF && pf->vf[vsi->vf_id].spoofchk) { + /* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off + * respectively + */ + if (vsi->type == ICE_VSI_VF) { ctxt->info.valid_sections |= cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); - ctxt->info.sec_flags |= - ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; + if (pf->vf[vsi->vf_id].spoofchk) { + ctxt->info.sec_flags |= + ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | + (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << + ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); + } else { + ctxt->info.sec_flags &= + ~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | + (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << + ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S)); + } } /* Allow control frames out of main VSI */ @@ -1636,22 +1647,14 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) ctxt->info = vsi->info; - if (ena) { - ctxt->info.sec_flags |= - ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << - ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; + if (ena) ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; - } else { - ctxt->info.sec_flags &= - ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << - ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); + else ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; - } if (!vlan_promisc) ctxt->info.valid_sections = - cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | - ICE_AQ_VSI_PROP_SW_VALID); + cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); if (status) { @@ -1661,7 +1664,6 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) goto err_out; } - vsi->info.sec_flags = ctxt->info.sec_flags; vsi->info.sw_flags2 = ctxt->info.sw_flags2; kfree(ctxt); @@ -2402,6 +2404,97 @@ int ice_vsi_release(struct ice_vsi *vsi) } /** + * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector + * @q_vector: pointer to q_vector which is being updated + * @coalesce: pointer to array of struct with stored coalesce + * + * Set coalesce param in q_vector and update these parameters in HW. + */ +static void +ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector, + struct ice_coalesce_stored *coalesce) +{ + struct ice_ring_container *rx_rc = &q_vector->rx; + struct ice_ring_container *tx_rc = &q_vector->tx; + struct ice_hw *hw = &q_vector->vsi->back->hw; + + tx_rc->itr_setting = coalesce->itr_tx; + rx_rc->itr_setting = coalesce->itr_rx; + + /* dynamic ITR values will be updated during Tx/Rx */ + if (!ITR_IS_DYNAMIC(tx_rc->itr_setting)) + wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx), + ITR_REG_ALIGN(tx_rc->itr_setting) >> + ICE_ITR_GRAN_S); + if (!ITR_IS_DYNAMIC(rx_rc->itr_setting)) + wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx), + ITR_REG_ALIGN(rx_rc->itr_setting) >> + ICE_ITR_GRAN_S); + + q_vector->intrl = coalesce->intrl; + wr32(hw, GLINT_RATE(q_vector->reg_idx), + ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); +} + +/** + * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors + * @vsi: VSI connected with q_vectors + * @coalesce: array of struct with stored coalesce + * + * Returns array size. + */ +static int +ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, + struct ice_coalesce_stored *coalesce) +{ + int i; + + ice_for_each_q_vector(vsi, i) { + struct ice_q_vector *q_vector = vsi->q_vectors[i]; + + coalesce[i].itr_tx = q_vector->tx.itr_setting; + coalesce[i].itr_rx = q_vector->rx.itr_setting; + coalesce[i].intrl = q_vector->intrl; + } + + return vsi->num_q_vectors; +} + +/** + * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays + * @vsi: VSI connected with q_vectors + * @coalesce: pointer to array of struct with stored coalesce + * @size: size of coalesce array + * + * Before this function, ice_vsi_rebuild_get_coalesce should be called to save + * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce + * to default value. + */ +static void +ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, + struct ice_coalesce_stored *coalesce, int size) +{ + int i; + + if ((size && !coalesce) || !vsi) + return; + + for (i = 0; i < size && i < vsi->num_q_vectors; i++) + ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], + &coalesce[i]); + + for (; i < vsi->num_q_vectors; i++) { + struct ice_coalesce_stored coalesce_dflt = { + .itr_tx = ICE_DFLT_TX_ITR, + .itr_rx = ICE_DFLT_RX_ITR, + .intrl = 0 + }; + ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], + &coalesce_dflt); + } +} + +/** * ice_vsi_rebuild - Rebuild VSI after reset * @vsi: VSI to be rebuild * @init_vsi: is this an initialization or a reconfigure of the VSI @@ -2411,6 +2504,8 @@ int ice_vsi_release(struct ice_vsi *vsi) int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) { u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; + struct ice_coalesce_stored *coalesce; + int prev_num_q_vectors = 0; struct ice_vf *vf = NULL; enum ice_status status; struct ice_pf *pf; @@ -2423,6 +2518,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) if (vsi->type == ICE_VSI_VF) vf = &pf->vf[vsi->vf_id]; + coalesce = kcalloc(vsi->num_q_vectors, + sizeof(struct ice_coalesce_stored), GFP_KERNEL); + if (coalesce) + prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, + coalesce); ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); ice_vsi_free_q_vectors(vsi); @@ -2535,6 +2635,9 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) return ice_schedule_reset(pf, ICE_RESET_PFR); } } + ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors); + kfree(coalesce); + return 0; err_vectors: @@ -2549,6 +2652,7 @@ err_rings: err_vsi: ice_vsi_clear(vsi); set_bit(__ICE_RESET_FAILED, pf->state); + kfree(coalesce); return ret; } @@ -2740,3 +2844,121 @@ cfg_mac_fltr_exit: ice_free_fltr_list(&vsi->back->pdev->dev, &tmp_add_list); return status; } + +/** + * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used + * @sw: switch to check if its default forwarding VSI is free + * + * Return true if the default forwarding VSI is already being used, else returns + * false signalling that it's available to use. + */ +bool ice_is_dflt_vsi_in_use(struct ice_sw *sw) +{ + return (sw->dflt_vsi && sw->dflt_vsi_ena); +} + +/** + * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI + * @sw: switch for the default forwarding VSI to compare against + * @vsi: VSI to compare against default forwarding VSI + * + * If this VSI passed in is the default forwarding VSI then return true, else + * return false + */ +bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) +{ + return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena); +} + +/** + * ice_set_dflt_vsi - set the default forwarding VSI + * @sw: switch used to assign the default forwarding VSI + * @vsi: VSI getting set as the default forwarding VSI on the switch + * + * If the VSI passed in is already the default VSI and it's enabled just return + * success. + * + * If there is already a default VSI on the switch and it's enabled then return + * -EEXIST since there can only be one default VSI per switch. + * + * Otherwise try to set the VSI passed in as the switch's default VSI and + * return the result. + */ +int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) +{ + enum ice_status status; + struct device *dev; + + if (!sw || !vsi) + return -EINVAL; + + dev = ice_pf_to_dev(vsi->back); + + /* the VSI passed in is already the default VSI */ + if (ice_is_vsi_dflt_vsi(sw, vsi)) { + dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n", + vsi->vsi_num); + return 0; + } + + /* another VSI is already the default VSI for this switch */ + if (ice_is_dflt_vsi_in_use(sw)) { + dev_err(dev, + "Default forwarding VSI %d already in use, disable it and try again\n", + sw->dflt_vsi->vsi_num); + return -EEXIST; + } + + status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX); + if (status) { + dev_err(dev, + "Failed to set VSI %d as the default forwarding VSI, error %d\n", + vsi->vsi_num, status); + return -EIO; + } + + sw->dflt_vsi = vsi; + sw->dflt_vsi_ena = true; + + return 0; +} + +/** + * ice_clear_dflt_vsi - clear the default forwarding VSI + * @sw: switch used to clear the default VSI + * + * If the switch has no default VSI or it's not enabled then return error. + * + * Otherwise try to clear the default VSI and return the result. + */ +int ice_clear_dflt_vsi(struct ice_sw *sw) +{ + struct ice_vsi *dflt_vsi; + enum ice_status status; + struct device *dev; + + if (!sw) + return -EINVAL; + + dev = ice_pf_to_dev(sw->pf); + + dflt_vsi = sw->dflt_vsi; + + /* there is no default VSI configured */ + if (!ice_is_dflt_vsi_in_use(sw)) + return -ENODEV; + + status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false, + ICE_FLTR_RX); + if (status) { + dev_err(dev, + "Failed to clear the default forwarding VSI %d, error %d\n", + dflt_vsi->vsi_num, status); + return -EIO; + } + + sw->dflt_vsi = NULL; + sw->dflt_vsi_ena = false; + + return 0; +} |
