Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: Validate config for SW DCB map

Validate the inputs for SW DCB config received either via lldptool or pcap
file. And don't apply DCB for bad bandwidth inputs. Without this patch, any
config having bad inputs will cause the loss of link making PF unusable
even after driver reload. Recoverable only via system reboot.

Signed-off-by: Avinash Dayanand <avinash.dayanand@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>

authored by

Avinash Dayanand and committed by
Jeff Kirsher
a29a912d 7d51a015

+47
+40
drivers/net/ethernet/intel/ice/ice_dcb_lib.c
··· 149 149 } 150 150 151 151 /** 152 + * ice_dcb_bwchk - check if ETS bandwidth input parameters are correct 153 + * @pf: pointer to the PF struct 154 + * @dcbcfg: pointer to DCB config structure 155 + */ 156 + int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg) 157 + { 158 + struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg; 159 + u8 num_tc, total_bw = 0; 160 + int i; 161 + 162 + /* returns number of contigous TCs and 1 TC for non-contigous TCs, 163 + * since at least 1 TC has to be configured 164 + */ 165 + num_tc = ice_dcb_get_num_tc(dcbcfg); 166 + 167 + /* no bandwidth checks required if there's only one TC, so assign 168 + * all bandwidth to TC0 and return 169 + */ 170 + if (num_tc == 1) { 171 + etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 172 + return 0; 173 + } 174 + 175 + for (i = 0; i < num_tc; i++) 176 + total_bw += etscfg->tcbwtable[i]; 177 + 178 + if (!total_bw) { 179 + etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 180 + } else if (total_bw != ICE_TC_MAX_BW) { 181 + dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n"); 182 + return -EINVAL; 183 + } 184 + 185 + return 0; 186 + } 187 + 188 + /** 152 189 * ice_pf_dcb_cfg - Apply new DCB configuration 153 190 * @pf: pointer to the PF struct 154 191 * @new_cfg: DCBX config to apply ··· 218 181 dev_dbg(dev, "No change in DCB config required\n"); 219 182 return ret; 220 183 } 184 + 185 + if (ice_dcb_bwchk(pf, new_cfg)) 186 + return -EINVAL; 221 187 222 188 /* Store old config in case FW config fails */ 223 189 old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
+1
drivers/net/ethernet/intel/ice/ice_dcb_lib.h
··· 20 20 u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index); 21 21 int 22 22 ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked); 23 + int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg); 23 24 void ice_pf_dcb_recfg(struct ice_pf *pf); 24 25 void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi); 25 26 int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
+6
drivers/net/ethernet/intel/ice/ice_dcb_nl.c
··· 95 95 new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i]; 96 96 } 97 97 98 + if (ice_dcb_bwchk(pf, new_cfg)) { 99 + err = -EINVAL; 100 + goto ets_out; 101 + } 102 + 98 103 /* max_tc is a 1-8 value count of number of TC's, not a 0-7 value 99 104 * for the TC's index number. Add one to value if not zero, and 100 105 * for zero set it to the FW's default value ··· 124 119 if (err == ICE_DCB_NO_HW_CHG) 125 120 err = ICE_DCB_HW_CHG_RST; 126 121 122 + ets_out: 127 123 mutex_unlock(&pf->tc_mutex); 128 124 return err; 129 125 }