aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2013-12-04 18:10:07 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-12-19 23:56:29 -0500
commit8a98db7386b5fed82dc1df25c904b6d0ae32a2cb (patch)
tree420021744c5931fd0a6b66a60582f16b0077f761 /drivers
parent95d8a25b52d551f631595ae4b5883d22a8d85a52 (diff)
[SCSI] hpsa: use workqueue instead of kernel thread for lockup detection
Much simpler and avoids races starting/stopping the thread. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/hpsa.c103
-rw-r--r--drivers/scsi/hpsa.h3
2 files changed, 28 insertions, 78 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 91e2d8398969..f929875a9187 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -168,10 +168,6 @@ static struct board_type products[] = {
168 168
169static int number_of_controllers; 169static int number_of_controllers;
170 170
171static struct list_head hpsa_ctlr_list = LIST_HEAD_INIT(hpsa_ctlr_list);
172static spinlock_t lockup_detector_lock;
173static struct task_struct *hpsa_lockup_detector;
174
175static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); 171static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
176static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); 172static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
177static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg); 173static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
@@ -4716,16 +4712,6 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
4716 kfree(h); 4712 kfree(h);
4717} 4713}
4718 4714
4719static void remove_ctlr_from_lockup_detector_list(struct ctlr_info *h)
4720{
4721 assert_spin_locked(&lockup_detector_lock);
4722 if (!hpsa_lockup_detector)
4723 return;
4724 if (h->lockup_detected)
4725 return; /* already stopped the lockup detector */
4726 list_del(&h->lockup_list);
4727}
4728
4729/* Called when controller lockup detected. */ 4715/* Called when controller lockup detected. */
4730static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list) 4716static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list)
4731{ 4717{
@@ -4744,8 +4730,6 @@ static void controller_lockup_detected(struct ctlr_info *h)
4744{ 4730{
4745 unsigned long flags; 4731 unsigned long flags;
4746 4732
4747 assert_spin_locked(&lockup_detector_lock);
4748 remove_ctlr_from_lockup_detector_list(h);
4749 h->access.set_intr_mask(h, HPSA_INTR_OFF); 4733 h->access.set_intr_mask(h, HPSA_INTR_OFF);
4750 spin_lock_irqsave(&h->lock, flags); 4734 spin_lock_irqsave(&h->lock, flags);
4751 h->lockup_detected = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); 4735 h->lockup_detected = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
@@ -4765,7 +4749,6 @@ static void detect_controller_lockup(struct ctlr_info *h)
4765 u32 heartbeat; 4749 u32 heartbeat;
4766 unsigned long flags; 4750 unsigned long flags;
4767 4751
4768 assert_spin_locked(&lockup_detector_lock);
4769 now = get_jiffies_64(); 4752 now = get_jiffies_64();
4770 /* If we've received an interrupt recently, we're ok. */ 4753 /* If we've received an interrupt recently, we're ok. */
4771 if (time_after64(h->last_intr_timestamp + 4754 if (time_after64(h->last_intr_timestamp +
@@ -4795,68 +4778,22 @@ static void detect_controller_lockup(struct ctlr_info *h)
4795 h->last_heartbeat_timestamp = now; 4778 h->last_heartbeat_timestamp = now;
4796} 4779}
4797 4780
4798static int detect_controller_lockup_thread(void *notused) 4781static void hpsa_monitor_ctlr_worker(struct work_struct *work)
4799{
4800 struct ctlr_info *h;
4801 unsigned long flags;
4802
4803 while (1) {
4804 struct list_head *this, *tmp;
4805
4806 schedule_timeout_interruptible(HEARTBEAT_SAMPLE_INTERVAL);
4807 if (kthread_should_stop())
4808 break;
4809 spin_lock_irqsave(&lockup_detector_lock, flags);
4810 list_for_each_safe(this, tmp, &hpsa_ctlr_list) {
4811 h = list_entry(this, struct ctlr_info, lockup_list);
4812 detect_controller_lockup(h);
4813 }
4814 spin_unlock_irqrestore(&lockup_detector_lock, flags);
4815 }
4816 return 0;
4817}
4818
4819static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h)
4820{ 4782{
4821 unsigned long flags; 4783 unsigned long flags;
4822 4784 struct ctlr_info *h = container_of(to_delayed_work(work),
4823 h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; 4785 struct ctlr_info, monitor_ctlr_work);
4824 spin_lock_irqsave(&lockup_detector_lock, flags); 4786 detect_controller_lockup(h);
4825 list_add_tail(&h->lockup_list, &hpsa_ctlr_list); 4787 if (h->lockup_detected)
4826 spin_unlock_irqrestore(&lockup_detector_lock, flags); 4788 return;
4827} 4789 spin_lock_irqsave(&h->lock, flags);
4828 4790 if (h->remove_in_progress) {
4829static void start_controller_lockup_detector(struct ctlr_info *h) 4791 spin_unlock_irqrestore(&h->lock, flags);
4830{
4831 /* Start the lockup detector thread if not already started */
4832 if (!hpsa_lockup_detector) {
4833 spin_lock_init(&lockup_detector_lock);
4834 hpsa_lockup_detector =
4835 kthread_run(detect_controller_lockup_thread,
4836 NULL, HPSA);
4837 }
4838 if (!hpsa_lockup_detector) {
4839 dev_warn(&h->pdev->dev,
4840 "Could not start lockup detector thread\n");
4841 return; 4792 return;
4842 } 4793 }
4843 add_ctlr_to_lockup_detector_list(h); 4794 schedule_delayed_work(&h->monitor_ctlr_work,
4844} 4795 h->heartbeat_sample_interval);
4845 4796 spin_unlock_irqrestore(&h->lock, flags);
4846static void stop_controller_lockup_detector(struct ctlr_info *h)
4847{
4848 unsigned long flags;
4849
4850 spin_lock_irqsave(&lockup_detector_lock, flags);
4851 remove_ctlr_from_lockup_detector_list(h);
4852 /* If the list of ctlr's to monitor is empty, stop the thread */
4853 if (list_empty(&hpsa_ctlr_list)) {
4854 spin_unlock_irqrestore(&lockup_detector_lock, flags);
4855 kthread_stop(hpsa_lockup_detector);
4856 spin_lock_irqsave(&lockup_detector_lock, flags);
4857 hpsa_lockup_detector = NULL;
4858 }
4859 spin_unlock_irqrestore(&lockup_detector_lock, flags);
4860} 4797}
4861 4798
4862static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 4799static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -5004,7 +4941,12 @@ reinit_after_soft_reset:
5004 4941
5005 hpsa_hba_inquiry(h); 4942 hpsa_hba_inquiry(h);
5006 hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ 4943 hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */
5007 start_controller_lockup_detector(h); 4944
4945 /* Monitor the controller for firmware lockups */
4946 h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
4947 INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
4948 schedule_delayed_work(&h->monitor_ctlr_work,
4949 h->heartbeat_sample_interval);
5008 return 0; 4950 return 0;
5009 4951
5010clean4: 4952clean4:
@@ -5079,13 +5021,20 @@ static void hpsa_free_device_info(struct ctlr_info *h)
5079static void hpsa_remove_one(struct pci_dev *pdev) 5021static void hpsa_remove_one(struct pci_dev *pdev)
5080{ 5022{
5081 struct ctlr_info *h; 5023 struct ctlr_info *h;
5024 unsigned long flags;
5082 5025
5083 if (pci_get_drvdata(pdev) == NULL) { 5026 if (pci_get_drvdata(pdev) == NULL) {
5084 dev_err(&pdev->dev, "unable to remove device\n"); 5027 dev_err(&pdev->dev, "unable to remove device\n");
5085 return; 5028 return;
5086 } 5029 }
5087 h = pci_get_drvdata(pdev); 5030 h = pci_get_drvdata(pdev);
5088 stop_controller_lockup_detector(h); 5031
5032 /* Get rid of any controller monitoring work items */
5033 spin_lock_irqsave(&h->lock, flags);
5034 h->remove_in_progress = 1;
5035 cancel_delayed_work(&h->monitor_ctlr_work);
5036 spin_unlock_irqrestore(&h->lock, flags);
5037
5089 hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ 5038 hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */
5090 hpsa_shutdown(pdev); 5039 hpsa_shutdown(pdev);
5091 iounmap(h->vaddr); 5040 iounmap(h->vaddr);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 5f3f72f90bc9..01c328349c83 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -135,7 +135,8 @@ struct ctlr_info {
135 u32 heartbeat_sample_interval; 135 u32 heartbeat_sample_interval;
136 atomic_t firmware_flash_in_progress; 136 atomic_t firmware_flash_in_progress;
137 u32 lockup_detected; 137 u32 lockup_detected;
138 struct list_head lockup_list; 138 struct delayed_work monitor_ctlr_work;
139 int remove_in_progress;
139 u32 fifo_recently_full; 140 u32 fifo_recently_full;
140 /* Address of h->q[x] is passed to intr handler to know which queue */ 141 /* Address of h->q[x] is passed to intr handler to know which queue */
141 u8 q[MAX_REPLY_QUEUES]; 142 u8 q[MAX_REPLY_QUEUES];