summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/hfi1/intr.c
diff options
context:
space:
mode:
authorMichael J. Ruhl <michael.j.ruhl@intel.com>2017-10-23 15:05:45 +0200
committerDoug Ledford <dledford@redhat.com>2017-10-30 19:51:36 +0100
commit4061f3a4da4574b8c9f11a82c767aaaed3ef2aa9 (patch)
tree08394267eb7dc05cc03535d6bcdc8dfbe65720d8 /drivers/infiniband/hw/hfi1/intr.c
parentbnxt_re: Implement the shutdown hook of the L2-RoCE driver interface (diff)
downloadlinux-4061f3a4da4574b8c9f11a82c767aaaed3ef2aa9.tar.xz
linux-4061f3a4da4574b8c9f11a82c767aaaed3ef2aa9.zip
IB/hfi1: Race condition between user notification and driver state
The handler for link init state (HLS_UP_INIT) notifies userspace (update_statusp()) before enabling the device (RCV_CTRL_RCV_PORT_ENABLE_SMASK) or setting the device state (ppd->host_link_state). This causes a race condition where the userspace thinks the interface is in the INIT state before the driver has set that state. Rework the code path to eliminate the race. Delay setting the init state until after a HW settling period. Reviewed-by: Sebastian Sanchez <sebastian.sanchez@intel.com> Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to '')
-rw-r--r--drivers/infiniband/hw/hfi1/intr.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c
index 96845dfed5c5..3e3184ddab5b 100644
--- a/drivers/infiniband/hw/hfi1/intr.c
+++ b/drivers/infiniband/hw/hfi1/intr.c
@@ -53,6 +53,8 @@
#include "common.h"
#include "sdma.h"
+#define LINK_UP_DELAY 500 /* in microseconds */
+
/**
* format_hwmsg - format a single hwerror message
* @msg message buffer
@@ -102,9 +104,16 @@ static void signal_ib_event(struct hfi1_pportdata *ppd, enum ib_event_type ev)
ib_dispatch_event(&event);
}
-/*
+/**
+ * handle_linkup_change - finish linkup/down state changes
+ * @dd: valid device
+ * @linkup: link state information
+ *
* Handle a linkup or link down notification.
+ * The HW needs time to finish its link up state change. Give it that chance.
+ *
* This is called outside an interrupt.
+ *
*/
void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup)
{
@@ -151,6 +160,9 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup)
ppd->neighbor_guid, ppd->neighbor_type,
ppd->neighbor_port_number);
+ /* HW needs LINK_UP_DELAY to settle, give it that chance */
+ udelay(LINK_UP_DELAY);
+
/* physical link went up */
ppd->linkup = 1;
ppd->offline_disabled_reason =