ice: Implement LFC workaround
There is a bug where the LFC settings are not being preserved through a link event. The registers in question are the ones that are touched (and restored) when a set_local_mib AQ command is performed. On a link-up event, make sure that a set_local_mib is being performed. Move the function ice_aq_set_lldp_mib() from the DCB specific ice_dcb.c to ice_common.c so that the driver always has access to this AQ command. Signed-off-by: Dave Ertman <david.m.ertman@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
490ed0b908
commit
7d9c9b791f
@ -4357,3 +4357,36 @@ bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_aq_set_lldp_mib - Set the LLDP MIB
|
||||
* @hw: pointer to the HW struct
|
||||
* @mib_type: Local, Remote or both Local and Remote MIBs
|
||||
* @buf: pointer to the caller-supplied buffer to store the MIB block
|
||||
* @buf_size: size of the buffer (in bytes)
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* Set the LLDP MIB. (0x0A08)
|
||||
*/
|
||||
enum ice_status
|
||||
ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
|
||||
struct ice_sq_cd *cd)
|
||||
{
|
||||
struct ice_aqc_lldp_set_local_mib *cmd;
|
||||
struct ice_aq_desc desc;
|
||||
|
||||
cmd = &desc.params.lldp_set_mib;
|
||||
|
||||
if (buf_size == 0 || !buf)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
|
||||
|
||||
desc.flags |= cpu_to_le16((u16)ICE_AQ_FLAG_RD);
|
||||
desc.datalen = cpu_to_le16(buf_size);
|
||||
|
||||
cmd->type = mib_type;
|
||||
cmd->length = cpu_to_le16(buf_size);
|
||||
|
||||
return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
|
||||
}
|
||||
|
@ -172,4 +172,7 @@ ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
|
||||
enum ice_status
|
||||
ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
|
||||
struct ice_aqc_txsched_elem_data *buf);
|
||||
enum ice_status
|
||||
ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
|
||||
struct ice_sq_cd *cd);
|
||||
#endif /* _ICE_COMMON_H_ */
|
||||
|
@ -134,39 +134,6 @@ ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd)
|
||||
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_aq_set_lldp_mib - Set the LLDP MIB
|
||||
* @hw: pointer to the HW struct
|
||||
* @mib_type: Local, Remote or both Local and Remote MIBs
|
||||
* @buf: pointer to the caller-supplied buffer to store the MIB block
|
||||
* @buf_size: size of the buffer (in bytes)
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* Set the LLDP MIB. (0x0A08)
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
|
||||
struct ice_sq_cd *cd)
|
||||
{
|
||||
struct ice_aqc_lldp_set_local_mib *cmd;
|
||||
struct ice_aq_desc desc;
|
||||
|
||||
cmd = &desc.params.lldp_set_mib;
|
||||
|
||||
if (buf_size == 0 || !buf)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
|
||||
|
||||
desc.flags |= cpu_to_le16((u16)ICE_AQ_FLAG_RD);
|
||||
desc.datalen = cpu_to_le16(buf_size);
|
||||
|
||||
cmd->type = mib_type;
|
||||
cmd->length = cpu_to_le16(buf_size);
|
||||
|
||||
return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_dcbx_status
|
||||
* @hw: pointer to the HW struct
|
||||
|
@ -444,10 +444,6 @@ void ice_dcb_rebuild(struct ice_pf *pf)
|
||||
goto dcb_error;
|
||||
}
|
||||
|
||||
/* If DCB was not enabled previously, we are done */
|
||||
if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
|
||||
return;
|
||||
|
||||
mutex_lock(&pf->tc_mutex);
|
||||
|
||||
if (!pf->hw.port_info->is_sw_lldp)
|
||||
|
@ -53,6 +53,12 @@ ice_set_cgd_num(struct ice_tlan_ctx *tlan_ctx, struct ice_ring *ring)
|
||||
{
|
||||
tlan_ctx->cgd_num = ring->dcb_tc;
|
||||
}
|
||||
|
||||
static inline bool ice_is_dcb_active(struct ice_pf *pf)
|
||||
{
|
||||
return (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags) ||
|
||||
test_bit(ICE_FLAG_DCB_ENA, pf->flags));
|
||||
}
|
||||
#else
|
||||
#define ice_dcb_rebuild(pf) do {} while (0)
|
||||
|
||||
@ -95,6 +101,11 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring __always_unused *tx_ring,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool ice_is_dcb_active(struct ice_pf __always_unused *pf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ice_is_pfc_causing_hung_q(struct ice_pf __always_unused *pf,
|
||||
unsigned int __always_unused txqueue)
|
||||
|
@ -766,6 +766,100 @@ static void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_dflt_mib - send a default config MIB to the FW
|
||||
* @pf: private PF struct
|
||||
*
|
||||
* This function sends a default configuration MIB to the FW.
|
||||
*
|
||||
* If this function errors out at any point, the driver is still able to
|
||||
* function. The main impact is that LFC may not operate as expected.
|
||||
* Therefore an error state in this function should be treated with a DBG
|
||||
* message and continue on with driver rebuild/reenable.
|
||||
*/
|
||||
static void ice_set_dflt_mib(struct ice_pf *pf)
|
||||
{
|
||||
struct device *dev = ice_pf_to_dev(pf);
|
||||
u8 mib_type, *buf, *lldpmib = NULL;
|
||||
u16 len, typelen, offset = 0;
|
||||
struct ice_lldp_org_tlv *tlv;
|
||||
struct ice_hw *hw;
|
||||
u32 ouisubtype;
|
||||
|
||||
if (!pf) {
|
||||
dev_dbg(dev, "%s NULL pf pointer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
hw = &pf->hw;
|
||||
mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB;
|
||||
lldpmib = kzalloc(ICE_LLDPDU_SIZE, GFP_KERNEL);
|
||||
if (!lldpmib) {
|
||||
dev_dbg(dev, "%s Failed to allocate MIB memory\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add ETS CFG TLV */
|
||||
tlv = (struct ice_lldp_org_tlv *)lldpmib;
|
||||
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
|
||||
ICE_IEEE_ETS_TLV_LEN);
|
||||
tlv->typelen = htons(typelen);
|
||||
ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
|
||||
ICE_IEEE_SUBTYPE_ETS_CFG);
|
||||
tlv->ouisubtype = htonl(ouisubtype);
|
||||
|
||||
buf = tlv->tlvinfo;
|
||||
buf[0] = 0;
|
||||
|
||||
/* ETS CFG all UPs map to TC 0. Next 4 (1 - 4) Octets = 0.
|
||||
* Octets 5 - 12 are BW values, set octet 5 to 100% BW.
|
||||
* Octets 13 - 20 are TSA values - leave as zeros
|
||||
*/
|
||||
buf[5] = 0x64;
|
||||
len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
|
||||
offset += len + 2;
|
||||
tlv = (struct ice_lldp_org_tlv *)
|
||||
((char *)tlv + sizeof(tlv->typelen) + len);
|
||||
|
||||
/* Add ETS REC TLV */
|
||||
buf = tlv->tlvinfo;
|
||||
tlv->typelen = htons(typelen);
|
||||
|
||||
ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
|
||||
ICE_IEEE_SUBTYPE_ETS_REC);
|
||||
tlv->ouisubtype = htonl(ouisubtype);
|
||||
|
||||
/* First octet of buf is reserved
|
||||
* Octets 1 - 4 map UP to TC - all UPs map to zero
|
||||
* Octets 5 - 12 are BW values - set TC 0 to 100%.
|
||||
* Octets 13 - 20 are TSA value - leave as zeros
|
||||
*/
|
||||
buf[5] = 0x64;
|
||||
offset += len + 2;
|
||||
tlv = (struct ice_lldp_org_tlv *)
|
||||
((char *)tlv + sizeof(tlv->typelen) + len);
|
||||
|
||||
/* Add PFC CFG TLV */
|
||||
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
|
||||
ICE_IEEE_PFC_TLV_LEN);
|
||||
tlv->typelen = htons(typelen);
|
||||
|
||||
ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
|
||||
ICE_IEEE_SUBTYPE_PFC_CFG);
|
||||
tlv->ouisubtype = htonl(ouisubtype);
|
||||
|
||||
/* Octet 1 left as all zeros - PFC disabled */
|
||||
buf[0] = 0x08;
|
||||
len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
|
||||
offset += len + 2;
|
||||
|
||||
if (ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, offset, NULL))
|
||||
dev_dbg(dev, "%s Failed to set default LLDP MIB\n", __func__);
|
||||
|
||||
kfree(lldpmib);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_link_event - process the link event
|
||||
* @pf: PF that the link event is associated with
|
||||
@ -821,7 +915,13 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
|
||||
if (link_up == old_link && link_speed == old_link_speed)
|
||||
return result;
|
||||
|
||||
ice_dcb_rebuild(pf);
|
||||
if (ice_is_dcb_active(pf)) {
|
||||
if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
|
||||
ice_dcb_rebuild(pf);
|
||||
} else {
|
||||
if (link_up)
|
||||
ice_set_dflt_mib(pf);
|
||||
}
|
||||
ice_vsi_link_event(vsi, link_up);
|
||||
ice_print_link_msg(vsi, link_up);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user