IB/hfi1: Create workqueue for link events
authorSebastian Sanchez <sebastian.sanchez@intel.com>
Sat, 29 Jul 2017 15:43:49 +0000 (08:43 -0700)
committerDoug Ledford <dledford@redhat.com>
Mon, 31 Jul 2017 19:18:38 +0000 (15:18 -0400)
Currently, link down interrupts queue link entries
on a workqueue intended for sending events only.
Create a workqueue for queuing link events.

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>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/driver.c
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/pio.c
drivers/infiniband/hw/hfi1/sdma.c

index bd594e7b0078f89bd3826dfc0709f990ea2f087d..8443d41c6e35a086807be1ef3f12ffd20bd9c15d 100644 (file)
@@ -5545,7 +5545,7 @@ static void update_rcverr_timer(unsigned long opaque)
                set_link_down_reason(
                ppd, OPA_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN, 0,
                OPA_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN);
-               queue_work(ppd->hfi1_wq, &ppd->link_bounce_work);
+               queue_work(ppd->link_wq, &ppd->link_bounce_work);
        }
        dd->rcv_ovfl_cnt = (u32)cur_ovfl_cnt;
 
@@ -6100,7 +6100,7 @@ static void handle_qsfp_int(struct hfi1_devdata *dd, u32 src_ctx, u64 reg)
                                 * will not happen. We have to do it here
                                 * before turning the DC off.
                                 */
-                               queue_work(ppd->hfi1_wq, &ppd->link_down_work);
+                               queue_work(ppd->link_wq, &ppd->link_down_work);
                        }
                } else {
                        dd_dev_info(dd, "%s: QSFP module inserted\n",
@@ -6135,7 +6135,7 @@ static void handle_qsfp_int(struct hfi1_devdata *dd, u32 src_ctx, u64 reg)
 
        /* Schedule the QSFP work only if there is a cable attached. */
        if (qsfp_mod_present(ppd))
-               queue_work(ppd->hfi1_wq, &ppd->qsfp_info.qsfp_work);
+               queue_work(ppd->link_wq, &ppd->qsfp_info.qsfp_work);
 }
 
 static int request_host_lcb_access(struct hfi1_devdata *dd)
@@ -7738,12 +7738,12 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
                        host_msg &= ~(u64)HOST_REQ_DONE;
                }
                if (host_msg & BC_SMA_MSG) {
-                       queue_work(ppd->hfi1_wq, &ppd->sma_message_work);
+                       queue_work(ppd->link_wq, &ppd->sma_message_work);
                        host_msg &= ~(u64)BC_SMA_MSG;
                }
                if (host_msg & LINKUP_ACHIEVED) {
                        dd_dev_info(dd, "8051: Link up\n");
-                       queue_work(ppd->hfi1_wq, &ppd->link_up_work);
+                       queue_work(ppd->link_wq, &ppd->link_up_work);
                        host_msg &= ~(u64)LINKUP_ACHIEVED;
                }
                if (host_msg & EXT_DEVICE_CFG_REQ) {
@@ -7751,7 +7751,7 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
                        host_msg &= ~(u64)EXT_DEVICE_CFG_REQ;
                }
                if (host_msg & VERIFY_CAP_FRAME) {
-                       queue_work(ppd->hfi1_wq, &ppd->link_vc_work);
+                       queue_work(ppd->link_wq, &ppd->link_vc_work);
                        host_msg &= ~(u64)VERIFY_CAP_FRAME;
                }
                if (host_msg & LINK_GOING_DOWN) {
@@ -7766,7 +7766,7 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
                        host_msg &= ~(u64)LINK_GOING_DOWN;
                }
                if (host_msg & LINK_WIDTH_DOWNGRADED) {
-                       queue_work(ppd->hfi1_wq, &ppd->link_downgrade_work);
+                       queue_work(ppd->link_wq, &ppd->link_downgrade_work);
                        host_msg &= ~(u64)LINK_WIDTH_DOWNGRADED;
                }
                if (host_msg) {
@@ -7809,7 +7809,7 @@ static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg)
                        dd_dev_info(dd, "%s: not queuing link down\n",
                                    __func__);
                } else {
-                       queue_work(ppd->hfi1_wq, &ppd->link_down_work);
+                       queue_work(ppd->link_wq, &ppd->link_down_work);
                }
        }
 }
@@ -8017,7 +8017,7 @@ static void handle_dcc_err(struct hfi1_devdata *dd, u32 unused, u64 reg)
                dd_dev_info_ratelimited(dd, "%s: PortErrorAction bounce\n",
                                        __func__);
                set_link_down_reason(ppd, lcl_reason, 0, lcl_reason);
-               queue_work(ppd->hfi1_wq, &ppd->link_bounce_work);
+               queue_work(ppd->link_wq, &ppd->link_bounce_work);
        }
 }
 
@@ -9685,7 +9685,7 @@ static void try_start_link(struct hfi1_pportdata *ppd)
                            "QSFP not responding, waiting and retrying %d\n",
                            (int)ppd->qsfp_retry_count);
                ppd->qsfp_retry_count++;
-               queue_delayed_work(ppd->hfi1_wq, &ppd->start_link_work,
+               queue_delayed_work(ppd->link_wq, &ppd->start_link_work,
                                   msecs_to_jiffies(QSFP_RETRY_WAIT));
                return;
        }
index 01235d4757a593f747901b08c3119905f4c2ff03..0b7ca0e05320f73d857976b2d06f521fdd51ce86 100644 (file)
@@ -914,7 +914,7 @@ static inline int set_armed_to_active(struct hfi1_ctxtdata *rcd,
                        return 0;
                }
 
-               queue_work(rcd->ppd->hfi1_wq, lsaw);
+               queue_work(rcd->ppd->link_wq, lsaw);
                return 1;
        }
        return 0;
index 2d32c5c314a3cafef04686fb20a21c00c90a26c8..ee6c389f951530e50c8064867989aea8786fe16d 100644 (file)
@@ -576,6 +576,7 @@ struct hfi1_pportdata {
        /* SendDMA related entries */
 
        struct workqueue_struct *hfi1_wq;
+       struct workqueue_struct *link_wq;
 
        /* move out of interrupt context */
        struct work_struct link_vc_work;
index 7f5e4c7dca896b5bc65c972273efe9cf0d9d6351..be027c9c880ee9f0f84b101f6c115294f91dc8d0 100644 (file)
@@ -660,6 +660,20 @@ static int create_workqueues(struct hfi1_devdata *dd)
                        if (!ppd->hfi1_wq)
                                goto wq_error;
                }
+               if (!ppd->link_wq) {
+                       /*
+                        * Make the link workqueue single-threaded to enforce
+                        * serialization.
+                        */
+                       ppd->link_wq =
+                               alloc_workqueue(
+                                   "hfi_link_%d_%d",
+                                   WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND,
+                                   1, /* max_active */
+                                   dd->unit, pidx);
+                       if (!ppd->link_wq)
+                               goto wq_error;
+               }
        }
        return 0;
 wq_error:
@@ -670,6 +684,10 @@ wq_error:
                        destroy_workqueue(ppd->hfi1_wq);
                        ppd->hfi1_wq = NULL;
                }
+               if (ppd->link_wq) {
+                       destroy_workqueue(ppd->link_wq);
+                       ppd->link_wq = NULL;
+               }
        }
        return -ENOMEM;
 }
@@ -954,6 +972,10 @@ static void shutdown_device(struct hfi1_devdata *dd)
                        destroy_workqueue(ppd->hfi1_wq);
                        ppd->hfi1_wq = NULL;
                }
+               if (ppd->link_wq) {
+                       destroy_workqueue(ppd->link_wq);
+                       ppd->link_wq = NULL;
+               }
        }
        sdma_exit(dd);
 }
@@ -1575,6 +1597,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                destroy_workqueue(ppd->hfi1_wq);
                                ppd->hfi1_wq = NULL;
                        }
+                       if (ppd->link_wq) {
+                               destroy_workqueue(ppd->link_wq);
+                               ppd->link_wq = NULL;
+                       }
                }
                if (!j)
                        hfi1_device_remove(dd);
index adb6a4da6107091017ea7c15ef220cd8c50d72d3..7108a4b5e94cdef45f27722847065388a36a6f85 100644 (file)
@@ -1012,7 +1012,7 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
                                   "%s: context %u(%u) timeout waiting for packets to egress, remaining count %u, bouncing link\n",
                                   __func__, sc->sw_index,
                                   sc->hw_context, (u32)reg);
-                       queue_work(dd->pport->hfi1_wq,
+                       queue_work(dd->pport->link_wq,
                                   &dd->pport->link_bounce_work);
                        break;
                }
index 71b4258545c4ac6ff49aee563bee99455add1436..6781bcdb10b3153246d1f3e7b0f8bc056657dde3 100644 (file)
@@ -325,7 +325,7 @@ static void sdma_wait_for_packet_egress(struct sdma_engine *sde,
                        /* timed out - bounce the link */
                        dd_dev_err(dd, "%s: engine %u timeout waiting for packets to egress, remaining count %u, bouncing link\n",
                                   __func__, sde->this_idx, (u32)reg);
-                       queue_work(dd->pport->hfi1_wq,
+                       queue_work(dd->pport->link_wq,
                                   &dd->pport->link_bounce_work);
                        break;
                }