aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/hpsa.c68
-rw-r--r--drivers/scsi/hpsa.h2
2 files changed, 56 insertions, 14 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 15ef65c25d64..95d581c45413 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6787,14 +6787,14 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
6787 return 0; 6787 return 0;
6788} 6788}
6789 6789
6790 6790static void hpsa_rescan_ctlr_worker(struct work_struct *work)
6791static void hpsa_monitor_ctlr_worker(struct work_struct *work)
6792{ 6791{
6793 unsigned long flags; 6792 unsigned long flags;
6794 struct ctlr_info *h = container_of(to_delayed_work(work), 6793 struct ctlr_info *h = container_of(to_delayed_work(work),
6795 struct ctlr_info, monitor_ctlr_work); 6794 struct ctlr_info, rescan_ctlr_work);
6796 detect_controller_lockup(h); 6795
6797 if (lockup_detected(h)) 6796
6797 if (h->remove_in_progress)
6798 return; 6798 return;
6799 6799
6800 if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) { 6800 if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) {
@@ -6803,17 +6803,44 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
6803 hpsa_scan_start(h->scsi_host); 6803 hpsa_scan_start(h->scsi_host);
6804 scsi_host_put(h->scsi_host); 6804 scsi_host_put(h->scsi_host);
6805 } 6805 }
6806
6807 spin_lock_irqsave(&h->lock, flags); 6806 spin_lock_irqsave(&h->lock, flags);
6808 if (h->remove_in_progress) { 6807 if (!h->remove_in_progress)
6809 spin_unlock_irqrestore(&h->lock, flags); 6808 queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
6809 h->heartbeat_sample_interval);
6810 spin_unlock_irqrestore(&h->lock, flags);
6811}
6812
6813static void hpsa_monitor_ctlr_worker(struct work_struct *work)
6814{
6815 unsigned long flags;
6816 struct ctlr_info *h = container_of(to_delayed_work(work),
6817 struct ctlr_info, monitor_ctlr_work);
6818
6819 detect_controller_lockup(h);
6820 if (lockup_detected(h))
6810 return; 6821 return;
6811 } 6822
6812 schedule_delayed_work(&h->monitor_ctlr_work, 6823 spin_lock_irqsave(&h->lock, flags);
6824 if (!h->remove_in_progress)
6825 schedule_delayed_work(&h->monitor_ctlr_work,
6813 h->heartbeat_sample_interval); 6826 h->heartbeat_sample_interval);
6814 spin_unlock_irqrestore(&h->lock, flags); 6827 spin_unlock_irqrestore(&h->lock, flags);
6815} 6828}
6816 6829
6830static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
6831 char *name)
6832{
6833 struct workqueue_struct *wq = NULL;
6834 char wq_name[20];
6835
6836 snprintf(wq_name, sizeof(wq_name), "%s_%d_hpsa", name, h->ctlr);
6837 wq = alloc_ordered_workqueue(wq_name, 0);
6838 if (!wq)
6839 dev_err(&h->pdev->dev, "failed to create %s workqueue\n", name);
6840
6841 return wq;
6842}
6843
6817static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 6844static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6818{ 6845{
6819 int dac, rc; 6846 int dac, rc;
@@ -6856,12 +6883,18 @@ reinit_after_soft_reset:
6856 spin_lock_init(&h->scan_lock); 6883 spin_lock_init(&h->scan_lock);
6857 atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS); 6884 atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
6858 6885
6859 h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0); 6886 h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan");
6887 if (!h->rescan_ctlr_wq) {
6888 rc = -ENOMEM;
6889 goto clean1;
6890 }
6891
6892 h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit");
6860 if (!h->resubmit_wq) { 6893 if (!h->resubmit_wq) {
6861 dev_err(&h->pdev->dev, "Failed to allocate work queue\n");
6862 rc = -ENOMEM; 6894 rc = -ENOMEM;
6863 goto clean1; 6895 goto clean1;
6864 } 6896 }
6897
6865 /* Allocate and clear per-cpu variable lockup_detected */ 6898 /* Allocate and clear per-cpu variable lockup_detected */
6866 h->lockup_detected = alloc_percpu(u32); 6899 h->lockup_detected = alloc_percpu(u32);
6867 if (!h->lockup_detected) { 6900 if (!h->lockup_detected) {
@@ -6985,6 +7018,9 @@ reinit_after_soft_reset:
6985 INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker); 7018 INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
6986 schedule_delayed_work(&h->monitor_ctlr_work, 7019 schedule_delayed_work(&h->monitor_ctlr_work,
6987 h->heartbeat_sample_interval); 7020 h->heartbeat_sample_interval);
7021 INIT_DELAYED_WORK(&h->rescan_ctlr_work, hpsa_rescan_ctlr_worker);
7022 queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
7023 h->heartbeat_sample_interval);
6988 return 0; 7024 return 0;
6989 7025
6990clean4: 7026clean4:
@@ -6996,6 +7032,8 @@ clean2:
6996clean1: 7032clean1:
6997 if (h->resubmit_wq) 7033 if (h->resubmit_wq)
6998 destroy_workqueue(h->resubmit_wq); 7034 destroy_workqueue(h->resubmit_wq);
7035 if (h->rescan_ctlr_wq)
7036 destroy_workqueue(h->rescan_ctlr_wq);
6999 if (h->lockup_detected) 7037 if (h->lockup_detected)
7000 free_percpu(h->lockup_detected); 7038 free_percpu(h->lockup_detected);
7001 kfree(h); 7039 kfree(h);
@@ -7069,11 +7107,13 @@ static void hpsa_remove_one(struct pci_dev *pdev)
7069 /* Get rid of any controller monitoring work items */ 7107 /* Get rid of any controller monitoring work items */
7070 spin_lock_irqsave(&h->lock, flags); 7108 spin_lock_irqsave(&h->lock, flags);
7071 h->remove_in_progress = 1; 7109 h->remove_in_progress = 1;
7072 cancel_delayed_work(&h->monitor_ctlr_work);
7073 spin_unlock_irqrestore(&h->lock, flags); 7110 spin_unlock_irqrestore(&h->lock, flags);
7111 cancel_delayed_work_sync(&h->monitor_ctlr_work);
7112 cancel_delayed_work_sync(&h->rescan_ctlr_work);
7113 destroy_workqueue(h->rescan_ctlr_wq);
7114 destroy_workqueue(h->resubmit_wq);
7074 hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ 7115 hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */
7075 hpsa_shutdown(pdev); 7116 hpsa_shutdown(pdev);
7076 destroy_workqueue(h->resubmit_wq);
7077 iounmap(h->vaddr); 7117 iounmap(h->vaddr);
7078 iounmap(h->transtable); 7118 iounmap(h->transtable);
7079 iounmap(h->cfgtable); 7119 iounmap(h->cfgtable);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 62c50c32070e..657713050349 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -207,6 +207,7 @@ struct ctlr_info {
207 atomic_t firmware_flash_in_progress; 207 atomic_t firmware_flash_in_progress;
208 u32 __percpu *lockup_detected; 208 u32 __percpu *lockup_detected;
209 struct delayed_work monitor_ctlr_work; 209 struct delayed_work monitor_ctlr_work;
210 struct delayed_work rescan_ctlr_work;
210 int remove_in_progress; 211 int remove_in_progress;
211 /* Address of h->q[x] is passed to intr handler to know which queue */ 212 /* Address of h->q[x] is passed to intr handler to know which queue */
212 u8 q[MAX_REPLY_QUEUES]; 213 u8 q[MAX_REPLY_QUEUES];
@@ -251,6 +252,7 @@ struct ctlr_info {
251 int acciopath_status; 252 int acciopath_status;
252 int raid_offload_debug; 253 int raid_offload_debug;
253 struct workqueue_struct *resubmit_wq; 254 struct workqueue_struct *resubmit_wq;
255 struct workqueue_struct *rescan_ctlr_wq;
254}; 256};
255 257
256struct offline_device_entry { 258struct offline_device_entry {