Commit 9775a991 authored by Easwar Hariharan's avatar Easwar Hariharan Committed by Doug Ledford

IB/hfi1: Wait for QSFP modules to initialize

The function level reset in init_chip() and subsequent write of all 1s
to the ASIC_QSFP registers effectively resets attached active and
optical QSFP modules that pay attention to the RESET_N pin.

We subsequently try to access the QSFP management interface to qualify
and tune the channel and fabric SerDes before enough time (2 seconds
per SFF 8679 spec for QSFP28 modules) has elapsed for the module to
finish initialization. This fails and causes the failure of the channel
tuning algorithm, preventing us from bringing the link up.

This patch checks the port type prior to beginning channel and SerDes
tuning, and if found to be QSFP, watches for the QSFP initialization
complete interrupt, with a maximum timeout of 2 seconds, to allow the
initialization to complete.
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 0c7f77af
......@@ -9485,7 +9485,15 @@ int bringup_serdes(struct hfi1_pportdata *ppd)
return ret;
}
/* tune the SERDES to a ballpark setting for
get_port_type(ppd);
if (ppd->port_type == PORT_TYPE_QSFP) {
set_qsfp_int_n(ppd, 0);
wait_for_qsfp_init(ppd);
set_qsfp_int_n(ppd, 1);
}
/*
* Tune the SerDes to a ballpark setting for
* optimal signal and bit error rate
* Needs to be done before starting the link
*/
......
......@@ -87,6 +87,17 @@ void free_platform_config(struct hfi1_devdata *dd)
*/
}
void get_port_type(struct hfi1_pportdata *ppd)
{
int ret;
ret = get_platform_config_field(ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
PORT_TABLE_PORT_TYPE, &ppd->port_type,
4);
if (ret)
ppd->port_type = PORT_TYPE_UNKNOWN;
}
int set_qsfp_tx(struct hfi1_pportdata *ppd, int on)
{
u8 tx_ctrl_byte = on ? 0x0 : 0xF;
......@@ -784,12 +795,6 @@ void tune_serdes(struct hfi1_pportdata *ppd)
return;
}
ret = get_platform_config_field(ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
PORT_TABLE_PORT_TYPE, &ppd->port_type,
4);
if (ret)
ppd->port_type = PORT_TYPE_UNKNOWN;
switch (ppd->port_type) {
case PORT_TYPE_DISCONNECTED:
ppd->offline_disabled_reason =
......
......@@ -298,6 +298,7 @@ enum link_tuning_encoding {
/* platform.c */
void get_platform_config(struct hfi1_devdata *dd);
void free_platform_config(struct hfi1_devdata *dd);
void get_port_type(struct hfi1_pportdata *ppd);
int set_qsfp_tx(struct hfi1_pportdata *ppd, int on);
void tune_serdes(struct hfi1_pportdata *ppd);
......
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