ice: Refactor the LLDP MIB change event handling

This patch fixes the LLDP MIB change event handling code by removing
the workarounds in the current code. Added ice_dcb_need_recfg() to
print the DCB configuration changes detected via MIB change event.

Signed-off-by: Usha Ketineni <usha.k.ketineni@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@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:
Usha Ketineni 2019-04-16 10:24:31 -07:00 committed by Jeff Kirsher
parent 9ccb062c14
commit a17a5ff681
3 changed files with 141 additions and 23 deletions

View File

@ -624,7 +624,8 @@ ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
* *
* Parse DCB configuration from the LLDPDU * Parse DCB configuration from the LLDPDU
*/ */
enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg) static enum ice_status
ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
{ {
struct ice_lldp_org_tlv *tlv; struct ice_lldp_org_tlv *tlv;
enum ice_status ret = 0; enum ice_status ret = 0;
@ -674,7 +675,7 @@ enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
* *
* Query DCB configuration from the firmware * Query DCB configuration from the firmware
*/ */
static enum ice_status enum ice_status
ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype, ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
struct ice_dcbx_cfg *dcbcfg) struct ice_dcbx_cfg *dcbcfg)
{ {

View File

@ -120,7 +120,9 @@ struct ice_cee_app_prio {
u8 prio_map; u8 prio_map;
} __packed; } __packed;
enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg); enum ice_status
ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
struct ice_dcbx_cfg *dcbcfg);
enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi); enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi);
enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi); enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi);
enum ice_status ice_init_dcb(struct ice_hw *hw); enum ice_status ice_init_dcb(struct ice_hw *hw);

View File

@ -501,6 +501,55 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
return 0; return 0;
} }
/**
* ice_dcb_need_recfg - Check if DCB needs reconfig
* @pf: board private structure
* @old_cfg: current DCB config
* @new_cfg: new DCB config
*/
static bool ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
struct ice_dcbx_cfg *new_cfg)
{
bool need_reconfig = false;
/* Check if ETS configuration has changed */
if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
sizeof(new_cfg->etscfg))) {
/* If Priority Table has changed reconfig is needed */
if (memcmp(&new_cfg->etscfg.prio_table,
&old_cfg->etscfg.prio_table,
sizeof(new_cfg->etscfg.prio_table))) {
need_reconfig = true;
dev_dbg(&pf->pdev->dev, "ETS UP2TC changed.\n");
}
if (memcmp(&new_cfg->etscfg.tcbwtable,
&old_cfg->etscfg.tcbwtable,
sizeof(new_cfg->etscfg.tcbwtable)))
dev_dbg(&pf->pdev->dev, "ETS TC BW Table changed.\n");
if (memcmp(&new_cfg->etscfg.tsatable,
&old_cfg->etscfg.tsatable,
sizeof(new_cfg->etscfg.tsatable)))
dev_dbg(&pf->pdev->dev, "ETS TSA Table changed.\n");
}
/* Check if PFC configuration has changed */
if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
need_reconfig = true;
dev_dbg(&pf->pdev->dev, "PFC config change detected.\n");
}
/* Check if APP Table has changed */
if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) {
need_reconfig = true;
dev_dbg(&pf->pdev->dev, "APP Table change detected.\n");
}
dev_dbg(&pf->pdev->dev, "dcb need_reconfig=%d\n", need_reconfig);
return need_reconfig;
}
/** /**
* ice_dcb_process_lldp_set_mib_change - Process MIB change * ice_dcb_process_lldp_set_mib_change - Process MIB change
* @pf: ptr to ice_pf * @pf: ptr to ice_pf
@ -510,29 +559,95 @@ void
ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf, ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
struct ice_rq_event_info *event) struct ice_rq_event_info *event)
{ {
if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) { struct ice_aqc_port_ets_elem buf = { 0 };
struct ice_dcbx_cfg *dcbcfg, *prev_cfg; struct ice_aqc_lldp_get_mib *mib;
int err; struct ice_dcbx_cfg tmp_dcbx_cfg;
bool need_reconfig = false;
struct ice_port_info *pi;
u8 type;
int ret;
prev_cfg = &pf->hw.port_info->local_dcbx_cfg; /* Not DCB capable or capability disabled */
dcbcfg = devm_kmemdup(&pf->pdev->dev, prev_cfg, if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
sizeof(*dcbcfg), GFP_KERNEL); return;
if (!dcbcfg)
return;
err = ice_lldp_to_dcb_cfg(event->msg_buf, dcbcfg); if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
if (!err)
ice_pf_dcb_cfg(pf, dcbcfg, false);
devm_kfree(&pf->pdev->dev, dcbcfg);
/* Get updated DCBx data from firmware */
err = ice_get_dcb_cfg(pf->hw.port_info);
if (err)
dev_err(&pf->pdev->dev,
"Failed to get DCB config\n");
} else {
dev_dbg(&pf->pdev->dev, dev_dbg(&pf->pdev->dev,
"MIB Change Event in HOST mode\n"); "MIB Change Event in HOST mode\n");
return;
} }
pi = pf->hw.port_info;
mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
/* Ignore if event is not for Nearest Bridge */
type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
ICE_AQ_LLDP_BRID_TYPE_M);
dev_dbg(&pf->pdev->dev, "LLDP event MIB bridge type 0x%x\n", type);
if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
return;
/* Check MIB Type and return if event for Remote MIB update */
type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
dev_dbg(&pf->pdev->dev,
"LLDP event mib type %s\n", type ? "remote" : "local");
if (type == ICE_AQ_LLDP_MIB_REMOTE) {
/* Update the remote cached instance and return */
ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
&pi->remote_dcbx_cfg);
if (ret) {
dev_err(&pf->pdev->dev, "Failed to get remote DCB config\n");
return;
}
}
/* store the old configuration */
tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
/* Reset the old DCBx configuration data */
memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
/* Get updated DCBx data from firmware */
ret = ice_get_dcb_cfg(pf->hw.port_info);
if (ret) {
dev_err(&pf->pdev->dev, "Failed to get DCB config\n");
return;
}
/* No change detected in DCBX configs */
if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
dev_dbg(&pf->pdev->dev,
"No change detected in DCBX configuration.\n");
return;
}
need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
&pi->local_dcbx_cfg);
if (!need_reconfig)
return;
/* Enable DCB tagging only when more than one TC */
if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n");
set_bit(ICE_FLAG_DCB_ENA, pf->flags);
} else {
dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n");
clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
}
rtnl_lock();
ice_pf_dis_all_vsi(pf, true);
ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
if (ret) {
dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
rtnl_unlock();
return;
}
/* changes in configuration update VSI */
ice_pf_dcb_recfg(pf);
ice_pf_ena_all_vsi(pf, true);
rtnl_unlock();
} }