On 3/30/2023 8:16 AM, Andrew Rybchenko wrote:
> On 3/28/23 19:51, Ivan Malov wrote:
>> FW should send link status change events in either v1 or
>> v2 format depending on the preference which the driver
>> can express during CMD_DRV_ATTACH stage. At the moment,
>> libefx does not request v2, so v1 events must arrive.
>> However, FW does not honour this choice and always
>> sends v2 events. So teach libefx to parse such and
>> add v2 request to CMD_DRV_ATTACH, correspondingly.
>>
>> Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>
>
Applied to dpdk-next-net/main, thanks.
@@ -868,6 +868,7 @@ ef10_ev_mcdi(
efx_nic_t *enp = eep->ee_enp;
unsigned int code;
boolean_t should_abort = B_FALSE;
+ boolean_t ev_is_v2 = B_FALSE;
EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE);
@@ -905,10 +906,13 @@ ef10_ev_mcdi(
break;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+ case MCDI_EVENT_CODE_LINKCHANGE_V2:
+ ev_is_v2 = B_TRUE;
+ /* Fallthrough */
case MCDI_EVENT_CODE_LINKCHANGE: {
efx_link_mode_t link_mode;
- ef10_phy_link_ev(enp, eqp, &link_mode);
+ ef10_phy_link_ev(enp, eqp, ev_is_v2, &link_mode);
should_abort = eecp->eec_link_change(arg, link_mode);
break;
}
@@ -753,6 +753,7 @@ extern void
ef10_phy_link_ev(
__in efx_nic_t *enp,
__in efx_qword_t *eqp,
+ __in boolean_t ev_is_v2,
__out efx_link_mode_t *link_modep);
LIBEFX_INTERNAL
@@ -166,6 +166,7 @@ mcdi_phy_decode_link_mode(
ef10_phy_link_ev(
__in efx_nic_t *enp,
__in efx_qword_t *eqp,
+ __in boolean_t ev_is_v2,
__out efx_link_mode_t *link_modep)
{
efx_port_t *epp = &(enp->en_port);
@@ -174,13 +175,31 @@ ef10_phy_link_ev(
unsigned int fcntl;
efx_phy_fec_type_t fec = MC_CMD_FEC_NONE;
efx_link_mode_t link_mode;
+ unsigned int ev_lp_cap;
+ unsigned int ev_fcntl;
+ unsigned int ev_speed;
uint32_t lp_cap_mask;
+ if (ev_is_v2) {
+ link_flags = (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN);
+ if (MCDI_EV_FIELD(eqp, LINKCHANGE_V2_FLAGS_LINK_UP))
+ link_flags |= (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN);
+
+ ev_lp_cap = MCDI_EV_FIELD(eqp, LINKCHANGE_V2_LP_CAP);
+ ev_fcntl = MCDI_EV_FIELD(eqp, LINKCHANGE_V2_FCNTL);
+ ev_speed = MCDI_EV_FIELD(eqp, LINKCHANGE_V2_SPEED);
+ } else {
+ link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
+ ev_lp_cap = MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP);
+ ev_fcntl = MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL);
+ ev_speed = MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED);
+ }
+
/*
* Convert the LINKCHANGE speed enumeration into mbit/s, in the
* same way as GET_LINK encodes the speed
*/
- switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) {
+ switch (ev_speed) {
case MCDI_EVENT_LINKCHANGE_SPEED_100M:
speed = 100;
break;
@@ -207,13 +226,10 @@ ef10_phy_link_ev(
break;
}
- link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
- mcdi_phy_decode_link_mode(enp, link_flags, speed,
- MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL),
+ mcdi_phy_decode_link_mode(enp, link_flags, speed, ev_fcntl,
MC_CMD_FEC_NONE, &link_mode,
&fcntl, &fec);
- mcdi_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
- &lp_cap_mask);
+ mcdi_phy_decode_cap(ev_lp_cap, &lp_cap_mask);
/*
* It's safe to update ep_lp_cap_mask without the driver's port lock
@@ -1620,10 +1620,16 @@ efx_mcdi_drv_attach(
* such example is the ESXi native driver that attempts attaching with
* FULL_FEATURED datapath firmware type first and fall backs to
* DONT_CARE datapath firmware type if MC_CMD_DRV_ATTACH fails.
+ *
+ * Always set WANT_V2_LINKCHANGES to 1. Old firmware that only supports
+ * v1 will ignore it, and for newer firmware it ensures that it always
+ * sends v2 if possible. While EF100 always uses v2, there are some
+ * older EF10 firmwares that only send v2 if it is requested.
*/
- MCDI_IN_POPULATE_DWORD_2(req, DRV_ATTACH_IN_NEW_STATE,
+ MCDI_IN_POPULATE_DWORD_3(req, DRV_ATTACH_IN_NEW_STATE,
DRV_ATTACH_IN_ATTACH, attach ? 1 : 0,
- DRV_ATTACH_IN_SUBVARIANT_AWARE, EFSYS_OPT_FW_SUBVARIANT_AWARE);
+ DRV_ATTACH_IN_SUBVARIANT_AWARE, EFSYS_OPT_FW_SUBVARIANT_AWARE,
+ DRV_ATTACH_IN_WANT_V2_LINKCHANGES, 1);
MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_FIRMWARE_ID, enp->efv);