scsi: hpsa: use local workqueues instead of system workqueues
authorDon Brace <don.brace@microsemi.com>
Tue, 7 May 2019 18:32:07 +0000 (13:32 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 18 Jun 2019 23:46:18 +0000 (19:46 -0400)
Avoid system stalls by switching to local workqueue.

Reviewed-by: Justin Lindley <justin.lindley@microsemi.com>
Reviewed-by: David Carroll <david.carroll@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h

index 54b0e3d..61365fc 100644 (file)
@@ -8128,6 +8128,11 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
                destroy_workqueue(h->rescan_ctlr_wq);
                h->rescan_ctlr_wq = NULL;
        }
+       if (h->monitor_ctlr_wq) {
+               destroy_workqueue(h->monitor_ctlr_wq);
+               h->monitor_ctlr_wq = NULL;
+       }
+
        kfree(h);                               /* init_one 1 */
 }
 
@@ -8463,8 +8468,8 @@ static void hpsa_event_monitor_worker(struct work_struct *work)
 
        spin_lock_irqsave(&h->lock, flags);
        if (!h->remove_in_progress)
-               schedule_delayed_work(&h->event_monitor_work,
-                                       HPSA_EVENT_MONITOR_INTERVAL);
+               queue_delayed_work(h->monitor_ctlr_wq, &h->event_monitor_work,
+                               HPSA_EVENT_MONITOR_INTERVAL);
        spin_unlock_irqrestore(&h->lock, flags);
 }
 
@@ -8509,7 +8514,7 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
 
        spin_lock_irqsave(&h->lock, flags);
        if (!h->remove_in_progress)
-               schedule_delayed_work(&h->monitor_ctlr_work,
+               queue_delayed_work(h->monitor_ctlr_wq, &h->monitor_ctlr_work,
                                h->heartbeat_sample_interval);
        spin_unlock_irqrestore(&h->lock, flags);
 }
@@ -8677,6 +8682,12 @@ reinit_after_soft_reset:
                goto clean7;    /* aer/h */
        }
 
+       h->monitor_ctlr_wq = hpsa_create_controller_wq(h, "monitor");
+       if (!h->monitor_ctlr_wq) {
+               rc = -ENOMEM;
+               goto clean7;
+       }
+
        /*
         * At this point, the controller is ready to take commands.
         * Now, if reset_devices and the hard reset didn't work, try
@@ -8806,6 +8817,10 @@ clean1:  /* wq/aer/h */
                destroy_workqueue(h->rescan_ctlr_wq);
                h->rescan_ctlr_wq = NULL;
        }
+       if (h->monitor_ctlr_wq) {
+               destroy_workqueue(h->monitor_ctlr_wq);
+               h->monitor_ctlr_wq = NULL;
+       }
        kfree(h);
        return rc;
 }
@@ -8953,6 +8968,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
        cancel_delayed_work_sync(&h->event_monitor_work);
        destroy_workqueue(h->rescan_ctlr_wq);
        destroy_workqueue(h->resubmit_wq);
+       destroy_workqueue(h->monitor_ctlr_wq);
 
        hpsa_delete_sas_host(h);
 
index 59e0236..7aa7378 100644 (file)
@@ -300,6 +300,7 @@ struct ctlr_info {
        int     needs_abort_tags_swizzled;
        struct workqueue_struct *resubmit_wq;
        struct workqueue_struct *rescan_ctlr_wq;
+       struct workqueue_struct *monitor_ctlr_wq;
        atomic_t abort_cmds_available;
        wait_queue_head_t event_sync_wait_queue;
        struct mutex reset_mutex;