summaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorEaswar Hariharan <easwar.hariharan@intel.com>2016-05-12 10:22:39 -0700
committerDoug Ledford <dledford@redhat.com>2016-05-13 19:39:14 -0400
commit9775a991f9bdbdde3cc38e553326755af5b2b2a9 (patch)
treea0101d0215a599c762af30592d2ab7fae7f2ff11 /drivers/staging
parent0c7f77afb7f6e74af899584ac672c8d9e63058b0 (diff)
downloadlinux-9775a991f9bdbdde3cc38e553326755af5b2b2a9.tar.bz2
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: Dean Luick <dean.luick@intel.com> Signed-off-by: Easwar Hariharan <easwar.hariharan@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/rdma/hfi1/chip.c10
-rw-r--r--drivers/staging/rdma/hfi1/platform.c17
-rw-r--r--drivers/staging/rdma/hfi1/platform.h1
3 files changed, 21 insertions, 7 deletions
diff --git a/drivers/staging/rdma/hfi1/chip.c b/drivers/staging/rdma/hfi1/chip.c
index f6ae0ba3a3b8..ce4c275b60f2 100644
--- a/drivers/staging/rdma/hfi1/chip.c
+++ b/drivers/staging/rdma/hfi1/chip.c
@@ -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
*/
diff --git a/drivers/staging/rdma/hfi1/platform.c b/drivers/staging/rdma/hfi1/platform.c
index 8fe8a205b5bb..dfa413cfa351 100644
--- a/drivers/staging/rdma/hfi1/platform.c
+++ b/drivers/staging/rdma/hfi1/platform.c
@@ -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 =
diff --git a/drivers/staging/rdma/hfi1/platform.h b/drivers/staging/rdma/hfi1/platform.h
index 19620cf546d5..e2c21613c326 100644
--- a/drivers/staging/rdma/hfi1/platform.h
+++ b/drivers/staging/rdma/hfi1/platform.h
@@ -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);