diff options
| -rw-r--r-- | drivers/scsi/hpsa.c | 103 | ||||
| -rw-r--r-- | drivers/scsi/hpsa.h | 3 |
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 | ||
| 169 | static int number_of_controllers; | 169 | static int number_of_controllers; |
| 170 | 170 | ||
| 171 | static struct list_head hpsa_ctlr_list = LIST_HEAD_INIT(hpsa_ctlr_list); | ||
| 172 | static spinlock_t lockup_detector_lock; | ||
| 173 | static struct task_struct *hpsa_lockup_detector; | ||
| 174 | |||
| 175 | static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); | 171 | static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); |
| 176 | static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); | 172 | static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); |
| 177 | static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg); | 173 | static 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 | ||
| 4719 | static 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. */ |
| 4730 | static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list) | 4716 | static 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 | ||
| 4798 | static int detect_controller_lockup_thread(void *notused) | 4781 | static 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 | |||
| 4819 | static 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) { | |
| 4829 | static 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); | |
| 4846 | static 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 | ||
| 4862 | static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 4799 | static 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 | ||
| 5010 | clean4: | 4952 | clean4: |
| @@ -5079,13 +5021,20 @@ static void hpsa_free_device_info(struct ctlr_info *h) | |||
| 5079 | static void hpsa_remove_one(struct pci_dev *pdev) | 5021 | static 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]; |
