IB/hfi1: Check xchg returned value for queuing link down entry
authorSebastian Sanchez <sebastian.sanchez@intel.com>
Sun, 13 Aug 2017 15:08:22 +0000 (08:08 -0700)
committerDoug Ledford <dledford@redhat.com>
Tue, 22 Aug 2017 18:22:37 +0000 (14:22 -0400)
Check xchg returned value for queuing link down entry
to guarantee proper atomic value reads.

Fixes: 626c077c025f ("IB/hfi1: Prevent link down request double queuing")
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@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

index cbda373..bfb50a4 100644 (file)
@@ -7810,16 +7810,22 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
        if (queue_link_down) {
                /*
                 * if the link is already going down or disabled, do not
-                * queue another
+                * queue another. If there's a link down entry already
+                * queued, don't queue another one.
                 */
                if ((ppd->host_link_state &
                    (HLS_GOING_OFFLINE | HLS_LINK_COOLDOWN)) ||
-                   ppd->link_enabled == 0 || ppd->is_link_down_queued) {
-                       dd_dev_info(dd, "%s: not queuing link down\n",
-                                   __func__);
+                   ppd->link_enabled == 0) {
+                       dd_dev_info(dd, "%s: not queuing link down. host_link_state %x, link_enabled %x\n",
+                                   __func__, ppd->host_link_state,
+                                   ppd->link_enabled);
                } else {
-                       xchg(&ppd->is_link_down_queued, 1);
-                       queue_work(ppd->link_wq, &ppd->link_down_work);
+                       if (xchg(&ppd->is_link_down_queued, 1) == 1)
+                               dd_dev_info(dd,
+                                           "%s: link down request already queued\n",
+                                           __func__);
+                       else
+                               queue_work(ppd->link_wq, &ppd->link_down_work);
                }
        }
 }