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>
This commit is contained in:
Avinash Dayanand 2020-02-13 13:30:59 -08:00 committed by Jeff Kirsher
parent 7d51a01599
commit a29a912d44
3 changed files with 47 additions and 0 deletions

View File

@ -148,6 +148,43 @@ void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
}
}
/**
* ice_dcb_bwchk - check if ETS bandwidth input parameters are correct
* @pf: pointer to the PF struct
* @dcbcfg: pointer to DCB config structure
*/
int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg)
{
struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg;
u8 num_tc, total_bw = 0;
int i;
/* returns number of contigous TCs and 1 TC for non-contigous TCs,
* since at least 1 TC has to be configured
*/
num_tc = ice_dcb_get_num_tc(dcbcfg);
/* no bandwidth checks required if there's only one TC, so assign
* all bandwidth to TC0 and return
*/
if (num_tc == 1) {
etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
return 0;
}
for (i = 0; i < num_tc; i++)
total_bw += etscfg->tcbwtable[i];
if (!total_bw) {
etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
} else if (total_bw != ICE_TC_MAX_BW) {
dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n");
return -EINVAL;
}
return 0;
}
/**
* ice_pf_dcb_cfg - Apply new DCB configuration
* @pf: pointer to the PF struct
@ -182,6 +219,9 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
return ret;
}
if (ice_dcb_bwchk(pf, new_cfg))
return -EINVAL;
/* Store old config in case FW config fails */
old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
if (!old_cfg)

View File

@ -20,6 +20,7 @@ u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg);
u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
int
ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg);
void ice_pf_dcb_recfg(struct ice_pf *pf);
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);

View File

@ -95,6 +95,11 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];
}
if (ice_dcb_bwchk(pf, new_cfg)) {
err = -EINVAL;
goto ets_out;
}
/* max_tc is a 1-8 value count of number of TC's, not a 0-7 value
* for the TC's index number. Add one to value if not zero, and
* for zero set it to the FW's default value
@ -119,6 +124,7 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
if (err == ICE_DCB_NO_HW_CHG)
err = ICE_DCB_HW_CHG_RST;
ets_out:
mutex_unlock(&pf->tc_mutex);
return err;
}