IB/hfi1: Prevent link down request double queuing
authorSebastian Sanchez <sebastian.sanchez@intel.com>
Sat, 29 Jul 2017 15:43:55 +0000 (08:43 -0700)
committerDoug Ledford <dledford@redhat.com>
Mon, 31 Jul 2017 19:18:38 +0000 (15:18 -0400)
When link interrupts occur, multiple link down requests
could be queued up when only one is needed. This could get
the hfi1 out of sync with its link partner during LNI.

Only allow one link down request to be queued at any one time.

Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Sebastian Sanchez <sebastian.sanchez@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
drivers/infiniband/hw/hfi1/hfi.h

index 8443d41c6e35a086807be1ef3f12ffd20bd9c15d..a3af46cbbf8d45f9ee3421f26555d9c5c9d60ab5 100644 (file)
@@ -7045,6 +7045,7 @@ void handle_link_down(struct work_struct *work)
        /* Go offline first, then deal with reading/writing through 8051 */
        was_up = !!(ppd->host_link_state & HLS_UP);
        set_link_state(ppd, HLS_DN_OFFLINE);
+       xchg(&ppd->is_link_down_queued, 0);
 
        if (was_up) {
                lcl_reason = 0;
@@ -7805,10 +7806,11 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
                 */
                if ((ppd->host_link_state &
                    (HLS_GOING_OFFLINE | HLS_LINK_COOLDOWN)) ||
-                   ppd->link_enabled == 0) {
+                   ppd->link_enabled == 0 || ppd->is_link_down_queued) {
                        dd_dev_info(dd, "%s: not queuing link down\n",
                                    __func__);
                } else {
+                       xchg(&ppd->is_link_down_queued, 1);
                        queue_work(ppd->link_wq, &ppd->link_down_work);
                }
        }
index ee6c389f951530e50c8064867989aea8786fe16d..fb5f8394fbed24d66ce6c1ab5bf9c68a0a5dee1e 100644 (file)
@@ -644,6 +644,7 @@ struct hfi1_pportdata {
        /* placeholders for IB MAD packet settings */
        u8 overrun_threshold;
        u8 phy_error_threshold;
+       unsigned int is_link_down_queued;
 
        /* Used to override LED behavior for things like maintenance beaconing*/
        /*