diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-05-04 23:34:49 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-05-08 11:01:39 -0400 |
commit | 2d6f0d0cd94f9b8b24102300d8dd9cbbd1688826 (patch) | |
tree | e3149988098d59586e6170bbef7d9a140dfdb655 /drivers/scsi/gdth.c | |
parent | 3de2403e6659d71b36ec820dc9b942762ddfe6eb (diff) |
[SCSI] gdth: fix timer handling
The global timer handling is problematic in that if someone unbinds a
PCI gdth instance, the BUG_ON() in the timer will cause a panic.
Fix this by making the timer start and stop depending on whether there
are instances present. This should also permit binding and unbinding
to work.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/gdth.c')
-rw-r--r-- | drivers/scsi/gdth.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 8e2e964af668..16785a2ad035 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
@@ -3724,6 +3724,8 @@ static void gdth_log_event(gdth_evt_data *dvr, char *buffer) | |||
3724 | } | 3724 | } |
3725 | 3725 | ||
3726 | #ifdef GDTH_STATISTICS | 3726 | #ifdef GDTH_STATISTICS |
3727 | static unchar gdth_timer_running; | ||
3728 | |||
3727 | static void gdth_timeout(ulong data) | 3729 | static void gdth_timeout(ulong data) |
3728 | { | 3730 | { |
3729 | ulong32 i; | 3731 | ulong32 i; |
@@ -3731,7 +3733,10 @@ static void gdth_timeout(ulong data) | |||
3731 | gdth_ha_str *ha; | 3733 | gdth_ha_str *ha; |
3732 | ulong flags; | 3734 | ulong flags; |
3733 | 3735 | ||
3734 | BUG_ON(list_empty(&gdth_instances)); | 3736 | if(unlikely(list_empty(&gdth_instances))) { |
3737 | gdth_timer_running = 0; | ||
3738 | return; | ||
3739 | } | ||
3735 | 3740 | ||
3736 | ha = list_first_entry(&gdth_instances, gdth_ha_str, list); | 3741 | ha = list_first_entry(&gdth_instances, gdth_ha_str, list); |
3737 | spin_lock_irqsave(&ha->smp_lock, flags); | 3742 | spin_lock_irqsave(&ha->smp_lock, flags); |
@@ -3751,6 +3756,22 @@ static void gdth_timeout(ulong data) | |||
3751 | add_timer(&gdth_timer); | 3756 | add_timer(&gdth_timer); |
3752 | spin_unlock_irqrestore(&ha->smp_lock, flags); | 3757 | spin_unlock_irqrestore(&ha->smp_lock, flags); |
3753 | } | 3758 | } |
3759 | |||
3760 | static void gdth_timer_init(void) | ||
3761 | { | ||
3762 | if (gdth_timer_running) | ||
3763 | return; | ||
3764 | gdth_timer_running = 1; | ||
3765 | TRACE2(("gdth_detect(): Initializing timer !\n")); | ||
3766 | gdth_timer.expires = jiffies + HZ; | ||
3767 | gdth_timer.data = 0L; | ||
3768 | gdth_timer.function = gdth_timeout; | ||
3769 | add_timer(&gdth_timer); | ||
3770 | } | ||
3771 | #else | ||
3772 | static inline void gdth_timer_init(void) | ||
3773 | { | ||
3774 | } | ||
3754 | #endif | 3775 | #endif |
3755 | 3776 | ||
3756 | static void __init internal_setup(char *str,int *ints) | 3777 | static void __init internal_setup(char *str,int *ints) |
@@ -4735,6 +4756,7 @@ static int __init gdth_isa_probe_one(ulong32 isa_bios) | |||
4735 | if (error) | 4756 | if (error) |
4736 | goto out_free_coal_stat; | 4757 | goto out_free_coal_stat; |
4737 | list_add_tail(&ha->list, &gdth_instances); | 4758 | list_add_tail(&ha->list, &gdth_instances); |
4759 | gdth_timer_init(); | ||
4738 | 4760 | ||
4739 | scsi_scan_host(shp); | 4761 | scsi_scan_host(shp); |
4740 | 4762 | ||
@@ -4865,6 +4887,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot) | |||
4865 | if (error) | 4887 | if (error) |
4866 | goto out_free_coal_stat; | 4888 | goto out_free_coal_stat; |
4867 | list_add_tail(&ha->list, &gdth_instances); | 4889 | list_add_tail(&ha->list, &gdth_instances); |
4890 | gdth_timer_init(); | ||
4868 | 4891 | ||
4869 | scsi_scan_host(shp); | 4892 | scsi_scan_host(shp); |
4870 | 4893 | ||
@@ -5011,6 +5034,7 @@ static int gdth_pci_probe_one(gdth_pci_str *pcistr, | |||
5011 | list_add_tail(&ha->list, &gdth_instances); | 5034 | list_add_tail(&ha->list, &gdth_instances); |
5012 | 5035 | ||
5013 | pci_set_drvdata(ha->pdev, ha); | 5036 | pci_set_drvdata(ha->pdev, ha); |
5037 | gdth_timer_init(); | ||
5014 | 5038 | ||
5015 | scsi_scan_host(shp); | 5039 | scsi_scan_host(shp); |
5016 | 5040 | ||
@@ -5110,6 +5134,7 @@ static int __init gdth_init(void) | |||
5110 | /* initializations */ | 5134 | /* initializations */ |
5111 | gdth_polling = TRUE; | 5135 | gdth_polling = TRUE; |
5112 | gdth_clear_events(); | 5136 | gdth_clear_events(); |
5137 | init_timer(&gdth_timer); | ||
5113 | 5138 | ||
5114 | /* As default we do not probe for EISA or ISA controllers */ | 5139 | /* As default we do not probe for EISA or ISA controllers */ |
5115 | if (probe_eisa_isa) { | 5140 | if (probe_eisa_isa) { |
@@ -5138,17 +5163,6 @@ static int __init gdth_init(void) | |||
5138 | 5163 | ||
5139 | TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); | 5164 | TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); |
5140 | 5165 | ||
5141 | if (list_empty(&gdth_instances)) | ||
5142 | return -ENODEV; | ||
5143 | |||
5144 | #ifdef GDTH_STATISTICS | ||
5145 | TRACE2(("gdth_detect(): Initializing timer !\n")); | ||
5146 | init_timer(&gdth_timer); | ||
5147 | gdth_timer.expires = jiffies + HZ; | ||
5148 | gdth_timer.data = 0L; | ||
5149 | gdth_timer.function = gdth_timeout; | ||
5150 | add_timer(&gdth_timer); | ||
5151 | #endif | ||
5152 | major = register_chrdev(0,"gdth", &gdth_fops); | 5166 | major = register_chrdev(0,"gdth", &gdth_fops); |
5153 | register_reboot_notifier(&gdth_notifier); | 5167 | register_reboot_notifier(&gdth_notifier); |
5154 | gdth_polling = FALSE; | 5168 | gdth_polling = FALSE; |