OSDN Git Service

ice: handle DCBx non-contiguous TC request
authorPaul Greenwalt <paul.greenwalt@intel.com>
Wed, 9 Oct 2019 14:09:43 +0000 (07:09 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 7 Nov 2019 00:41:45 +0000 (16:41 -0800)
If DCBx request non-contiguous TCs, then the driver will configure default
traffic class (TC0). This is done to prevent Tx hang since the driver
currently does not support non-contiguous TC.

Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice_dcb_lib.c

index dd47869..13da89e 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "ice_dcb_lib.h"
 
+static void ice_pf_dcb_recfg(struct ice_pf *pf);
+
 /**
  * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
  * @vsi: the VSI being configured
@@ -138,42 +140,6 @@ void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
 }
 
 /**
- * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
- * @pf: pointer to the PF struct
- *
- * Assumed caller has already disabled all VSIs before
- * calling this function. Reconfiguring DCB based on
- * local_dcbx_cfg.
- */
-static void ice_pf_dcb_recfg(struct ice_pf *pf)
-{
-       struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
-       u8 tc_map = 0;
-       int v, ret;
-
-       /* Update each VSI */
-       ice_for_each_vsi(pf, v) {
-               if (!pf->vsi[v])
-                       continue;
-
-               if (pf->vsi[v]->type == ICE_VSI_PF)
-                       tc_map = ice_dcb_get_ena_tc(dcbcfg);
-               else
-                       tc_map = ICE_DFLT_TRAFFIC_CLASS;
-
-               ret = ice_vsi_cfg_tc(pf->vsi[v], tc_map);
-               if (ret) {
-                       dev_err(&pf->pdev->dev,
-                               "Failed to config TC for VSI index: %d\n",
-                               pf->vsi[v]->idx);
-                       continue;
-               }
-
-               ice_vsi_map_rings_to_vectors(pf->vsi[v]);
-       }
-}
-
-/**
  * ice_pf_dcb_cfg - Apply new DCB configuration
  * @pf: pointer to the PF struct
  * @new_cfg: DCBX config to apply
@@ -437,9 +403,10 @@ static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
 /**
  * ice_dcb_sw_default_config - Apply a default DCB config
  * @pf: PF to apply config to
+ * @ets_willing: configure ets willing
  * @locked: was this function called with RTNL held
  */
-static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool locked)
+static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
 {
        struct ice_aqc_port_ets_elem buf = { 0 };
        struct ice_dcbx_cfg *dcbcfg;
@@ -454,7 +421,7 @@ static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool locked)
        memset(dcbcfg, 0, sizeof(*dcbcfg));
        memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
 
-       dcbcfg->etscfg.willing = 1;
+       dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
        dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
        dcbcfg->etscfg.tcbwtable[0] = 100;
        dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
@@ -480,6 +447,102 @@ static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool locked)
 }
 
 /**
+ * ice_dcb_tc_contig - Check that TCs are contiguous
+ * @prio_table: pointer to priority table
+ *
+ * Check if TCs begin with TC0 and are contiguous
+ */
+static bool ice_dcb_tc_contig(u8 *prio_table)
+{
+       u8 max_tc = 0;
+       int i;
+
+       for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
+               u8 cur_tc = prio_table[i];
+
+               if (cur_tc > max_tc)
+                       return false;
+               else if (cur_tc == max_tc)
+                       max_tc++;
+       }
+
+       return true;
+}
+
+/**
+ * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
+ * @pf: pointer to the PF struct
+ *
+ * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
+ */
+static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
+{
+       struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
+       int ret;
+
+       /* Configure SW DCB default with ETS non-willing */
+       ret = ice_dcb_sw_dflt_cfg(pf, false, true);
+       if (ret) {
+               dev_err(&pf->pdev->dev,
+                       "Failed to set local DCB config %d\n", ret);
+               return ret;
+       }
+
+       /* Reconfigure with ETS willing so that FW will send LLDP MIB event */
+       dcbcfg->etscfg.willing = 1;
+       ret = ice_set_dcb_cfg(pf->hw.port_info);
+       if (ret)
+               dev_err(&pf->pdev->dev, "Failed to set DCB to unwilling\n");
+
+       return ret;
+}
+
+/**
+ * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
+ * @pf: pointer to the PF struct
+ *
+ * Assumed caller has already disabled all VSIs before
+ * calling this function. Reconfiguring DCB based on
+ * local_dcbx_cfg.
+ */
+static void ice_pf_dcb_recfg(struct ice_pf *pf)
+{
+       struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
+       u8 tc_map = 0;
+       int v, ret;
+
+       /* Update each VSI */
+       ice_for_each_vsi(pf, v) {
+               if (!pf->vsi[v])
+                       continue;
+
+               if (pf->vsi[v]->type == ICE_VSI_PF) {
+                       tc_map = ice_dcb_get_ena_tc(dcbcfg);
+
+                       /* If DCBX request non-contiguous TC, then configure
+                        * default TC
+                        */
+                       if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
+                               tc_map = ICE_DFLT_TRAFFIC_CLASS;
+                               ice_dcb_noncontig_cfg(pf);
+                       }
+               } else {
+                       tc_map = ICE_DFLT_TRAFFIC_CLASS;
+               }
+
+               ret = ice_vsi_cfg_tc(pf->vsi[v], tc_map);
+               if (ret) {
+                       dev_err(&pf->pdev->dev,
+                               "Failed to config TC for VSI index: %d\n",
+                               pf->vsi[v]->idx);
+                       continue;
+               }
+
+               ice_vsi_map_rings_to_vectors(pf->vsi[v]);
+       }
+}
+
+/**
  * ice_init_pf_dcb - initialize DCB for a PF
  * @pf: PF to initialize DCB for
  * @locked: Was function called with RTNL held
@@ -507,7 +570,7 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
                dev_info(&pf->pdev->dev,
                         "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
                clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
-               err = ice_dcb_sw_dflt_cfg(pf, locked);
+               err = ice_dcb_sw_dflt_cfg(pf, true, locked);
                if (err) {
                        dev_err(&pf->pdev->dev,
                                "Failed to set local DCB config %d\n", err);