Commit 242b5e06 authored by Dave Ertman's avatar Dave Ertman Committed by Jeff Kirsher

ice: Fix DCB rebuild after reset

The function ice_dcb_rebuild had some logic
flaws in it, and also didn't differentiate
between FW and SW modes needs.

For FW flow, the willing setting was being
forced to OFF and left that way.  Unwilling
in DCB FW mode is not a supported model.

Leave the config alone and use the return value
from the set command to determine if setting the
config was successful.

The SW DCB flow does not need to need to register
for MIB change events (as they are not used in
SW mode).

Use !is_sw_lldp checks to only perform FW specific
task while in FW mode.

Also adding a reapplication of the current DCB
config after a link event.  Some NVMs are not
maintaining their DCB configs across link events.
Signed-off-by: default avatarDave Ertman <david.m.ertman@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b9287f2a
......@@ -315,9 +315,9 @@ ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
*/
void ice_dcb_rebuild(struct ice_pf *pf)
{
struct ice_dcbx_cfg *local_dcbx_cfg, *desired_dcbx_cfg, *prev_cfg;
struct ice_aqc_port_ets_elem buf = { 0 };
struct device *dev = ice_pf_to_dev(pf);
struct ice_dcbx_cfg *err_cfg;
enum ice_status ret;
ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
......@@ -330,53 +330,25 @@ void ice_dcb_rebuild(struct ice_pf *pf)
if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
return;
local_dcbx_cfg = &pf->hw.port_info->local_dcbx_cfg;
desired_dcbx_cfg = &pf->hw.port_info->desired_dcbx_cfg;
/* Save current willing state and force FW to unwilling */
local_dcbx_cfg->etscfg.willing = 0x0;
local_dcbx_cfg->pfc.willing = 0x0;
local_dcbx_cfg->app_mode = ICE_DCBX_APPS_NON_WILLING;
mutex_lock(&pf->tc_mutex);
if (!pf->hw.port_info->is_sw_lldp)
ice_cfg_etsrec_defaults(pf->hw.port_info);
ret = ice_set_dcb_cfg(pf->hw.port_info);
if (ret) {
dev_err(dev, "Failed to set DCB to unwilling\n");
dev_err(dev, "Failed to set DCB config in rebuild\n");
goto dcb_error;
}
/* Retrieve DCB config and ensure same as current in SW */
prev_cfg = kmemdup(local_dcbx_cfg, sizeof(*prev_cfg), GFP_KERNEL);
if (!prev_cfg)
goto dcb_error;
ice_init_dcb(&pf->hw, true);
if (pf->hw.port_info->dcbx_status == ICE_DCBX_STATUS_DIS)
pf->hw.port_info->is_sw_lldp = true;
else
pf->hw.port_info->is_sw_lldp = false;
if (ice_dcb_need_recfg(pf, prev_cfg, local_dcbx_cfg)) {
/* difference in cfg detected - disable DCB till next MIB */
dev_err(dev, "Set local MIB not accurate\n");
kfree(prev_cfg);
if (!pf->hw.port_info->is_sw_lldp) {
ret = ice_cfg_lldp_mib_change(&pf->hw, true);
if (ret && !pf->hw.port_info->is_sw_lldp) {
dev_err(dev, "Failed to register for MIB changes\n");
goto dcb_error;
}
/* fetched config congruent to previous configuration */
kfree(prev_cfg);
/* Set the local desired config */
if (local_dcbx_cfg->dcbx_mode == ICE_DCBX_MODE_CEE)
memcpy(local_dcbx_cfg, desired_dcbx_cfg,
sizeof(*local_dcbx_cfg));
ice_cfg_etsrec_defaults(pf->hw.port_info);
ret = ice_set_dcb_cfg(pf->hw.port_info);
if (ret) {
dev_err(dev, "Failed to set desired config\n");
goto dcb_error;
}
dev_info(dev, "DCB restored after reset\n");
ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
if (ret) {
......@@ -384,26 +356,32 @@ void ice_dcb_rebuild(struct ice_pf *pf)
goto dcb_error;
}
mutex_unlock(&pf->tc_mutex);
return;
dcb_error:
dev_err(dev, "Disabling DCB until new settings occur\n");
prev_cfg = kzalloc(sizeof(*prev_cfg), GFP_KERNEL);
if (!prev_cfg)
err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL);
if (!err_cfg) {
mutex_unlock(&pf->tc_mutex);
return;
}
prev_cfg->etscfg.willing = true;
prev_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
prev_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
memcpy(&prev_cfg->etsrec, &prev_cfg->etscfg, sizeof(prev_cfg->etsrec));
err_cfg->etscfg.willing = true;
err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec));
/* Coverity warns the return code of ice_pf_dcb_cfg() is not checked
* here as is done for other calls to that function. That check is
* not necessary since this is in this function's error cleanup path.
* Suppress the Coverity warning with the following comment...
*/
/* coverity[check_return] */
ice_pf_dcb_cfg(pf, prev_cfg, false);
kfree(prev_cfg);
ice_pf_dcb_cfg(pf, err_cfg, false);
kfree(err_cfg);
mutex_unlock(&pf->tc_mutex);
}
/**
......@@ -777,6 +755,8 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
}
}
mutex_lock(&pf->tc_mutex);
/* store the old configuration */
tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
......@@ -787,20 +767,20 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
ret = ice_get_dcb_cfg(pf->hw.port_info);
if (ret) {
dev_err(dev, "Failed to get DCB config\n");
return;
goto out;
}
/* No change detected in DCBX configs */
if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
dev_dbg(dev, "No change detected in DCBX configuration.\n");
return;
goto out;
}
need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
&pi->local_dcbx_cfg);
ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
if (!need_reconfig)
return;
goto out;
/* Enable DCB tagging only when more than one TC */
if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
......@@ -814,7 +794,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
pf_vsi = ice_get_main_vsi(pf);
if (!pf_vsi) {
dev_dbg(dev, "PF VSI doesn't exist\n");
return;
goto out;
}
rtnl_lock();
......@@ -823,13 +803,15 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
if (ret) {
dev_err(dev, "Query Port ETS failed\n");
rtnl_unlock();
return;
goto unlock_rtnl;
}
/* changes in configuration update VSI */
ice_pf_dcb_recfg(pf);
ice_ena_vsi(pf_vsi, true);
unlock_rtnl:
rtnl_unlock();
out:
mutex_unlock(&pf->tc_mutex);
}
......@@ -841,6 +841,7 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
}
}
ice_dcb_rebuild(pf);
ice_vsi_link_event(vsi, link_up);
ice_print_link_msg(vsi, link_up);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment