diff options
| author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-05-04 22:34:49 -0500 | 
|---|---|---|
| committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-05-08 10:01:39 -0500 | 
| commit | 2d6f0d0cd94f9b8b24102300d8dd9cbbd1688826 (patch) | |
| tree | e3149988098d59586e6170bbef7d9a140dfdb655 /drivers/scsi/gdth.c | |
| parent | 3de2403e6659d71b36ec820dc9b942762ddfe6eb (diff) | |
| download | linux-2d6f0d0cd94f9b8b24102300d8dd9cbbd1688826.tar.bz2 | |
[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)  }  #ifdef GDTH_STATISTICS +static unchar	gdth_timer_running; +  static void gdth_timeout(ulong data)  {      ulong32 i; @@ -3731,7 +3733,10 @@ static void gdth_timeout(ulong data)      gdth_ha_str *ha;      ulong flags; -    BUG_ON(list_empty(&gdth_instances)); +    if(unlikely(list_empty(&gdth_instances))) { +	    gdth_timer_running = 0; +	    return; +    }      ha = list_first_entry(&gdth_instances, gdth_ha_str, list);      spin_lock_irqsave(&ha->smp_lock, flags); @@ -3751,6 +3756,22 @@ static void gdth_timeout(ulong data)      add_timer(&gdth_timer);      spin_unlock_irqrestore(&ha->smp_lock, flags);  } + +static void gdth_timer_init(void) +{ +	if (gdth_timer_running) +		return; +	gdth_timer_running = 1; +	TRACE2(("gdth_detect(): Initializing timer !\n")); +	gdth_timer.expires = jiffies + HZ; +	gdth_timer.data = 0L; +	gdth_timer.function = gdth_timeout; +	add_timer(&gdth_timer); +} +#else +static inline void gdth_timer_init(void) +{ +}  #endif  static void __init internal_setup(char *str,int *ints) @@ -4735,6 +4756,7 @@ static int __init gdth_isa_probe_one(ulong32 isa_bios)  	if (error)  		goto out_free_coal_stat;  	list_add_tail(&ha->list, &gdth_instances); +	gdth_timer_init();  	scsi_scan_host(shp); @@ -4865,6 +4887,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)  	if (error)  		goto out_free_coal_stat;  	list_add_tail(&ha->list, &gdth_instances); +	gdth_timer_init();  	scsi_scan_host(shp); @@ -5011,6 +5034,7 @@ static int gdth_pci_probe_one(gdth_pci_str *pcistr,  	list_add_tail(&ha->list, &gdth_instances);  	pci_set_drvdata(ha->pdev, ha); +	gdth_timer_init();  	scsi_scan_host(shp); @@ -5110,6 +5134,7 @@ static int __init gdth_init(void)  	/* initializations */  	gdth_polling = TRUE;  	gdth_clear_events(); +	init_timer(&gdth_timer);  	/* As default we do not probe for EISA or ISA controllers */  	if (probe_eisa_isa) { @@ -5138,17 +5163,6 @@ static int __init gdth_init(void)  	TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); -	if (list_empty(&gdth_instances)) -		return -ENODEV; - -#ifdef GDTH_STATISTICS -	TRACE2(("gdth_detect(): Initializing timer !\n")); -	init_timer(&gdth_timer); -	gdth_timer.expires = jiffies + HZ; -	gdth_timer.data = 0L; -	gdth_timer.function = gdth_timeout; -	add_timer(&gdth_timer); -#endif  	major = register_chrdev(0,"gdth", &gdth_fops);  	register_reboot_notifier(&gdth_notifier);  	gdth_polling = FALSE; |