IB/hfi1: Harden state transition to Armed and Active
authorAlex Estrin <alex.estrin@intel.com>
Sat, 29 Jul 2017 15:43:20 +0000 (08:43 -0700)
committerDoug Ledford <dledford@redhat.com>
Mon, 31 Jul 2017 19:18:37 +0000 (15:18 -0400)
There is a window that allows other threads to read state of
'host_link_state' as a new, before the hardware actual state is set.
This patch closes the window by indicating a new state only after
hardware transition is complete.

Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Alex Estrin <alex.estrin@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/chip.c

index 8f7ce74..eca31dd 100644 (file)
@@ -10602,16 +10602,15 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state)
                        break;
                }
 
-               ppd->host_link_state = HLS_UP_ARMED;
                set_logical_state(dd, LSTATE_ARMED);
                ret = wait_logical_linkstate(ppd, IB_PORT_ARMED, 1000);
                if (ret) {
-                       /* logical state didn't change, stay at init */
-                       ppd->host_link_state = HLS_UP_INIT;
                        dd_dev_err(dd,
                                   "%s: logical state did not change to ARMED\n",
                                   __func__);
+                       break;
                }
+               ppd->host_link_state = HLS_UP_ARMED;
                /*
                 * The simulator does not currently implement SMA messages,
                 * so neighbor_normal is not set.  Set it here when we first
@@ -10624,18 +10623,16 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state)
                if (ppd->host_link_state != HLS_UP_ARMED)
                        goto unexpected;
 
-               ppd->host_link_state = HLS_UP_ACTIVE;
                set_logical_state(dd, LSTATE_ACTIVE);
                ret = wait_logical_linkstate(ppd, IB_PORT_ACTIVE, 1000);
                if (ret) {
-                       /* logical state didn't change, stay at armed */
-                       ppd->host_link_state = HLS_UP_ARMED;
                        dd_dev_err(dd,
                                   "%s: logical state did not change to ACTIVE\n",
                                   __func__);
                } else {
                        /* tell all engines to go running */
                        sdma_all_running(dd);
+                       ppd->host_link_state = HLS_UP_ACTIVE;
 
                        /* Signal the IB layer that the port has went active */
                        event.device = &dd->verbs_dev.rdi.ibdev;