- avoid system stalls by switching to local workqueue Reviewed-by: Justin Lindley <justin.lindley@xxxxxxxxxxxxx> Reviewed-by: David Carroll <david.carroll@xxxxxxxxxxxxx> Reviewed-by: Scott Teel <scott.teel@xxxxxxxxxxxxx> Signed-off-by: Don Brace <don.brace@xxxxxxxxxxxxx> --- drivers/scsi/hpsa.c | 22 +++++++++++++++++++--- drivers/scsi/hpsa.h | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 410941afcb7e..ade0d505a32c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8113,6 +8113,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 */ } @@ -8448,8 +8453,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); } @@ -8494,7 +8499,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); } @@ -8662,6 +8667,12 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 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 @@ -8791,6 +8802,10 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 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; } @@ -8938,6 +8953,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); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 59e023696fff..7aa7378f70dd 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -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;