Skip to content

Commit

Permalink
[SCSI] gdth: fix timer handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Bottomley authored and James Bottomley committed May 8, 2008
1 parent 3de2403 commit 2d6f0d0
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions drivers/scsi/gdth.c
Original file line number Diff line number Diff line change
Expand Up @@ -3724,14 +3724,19 @@ 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;
Scsi_Cmnd *nscp;
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);
Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 2d6f0d0

Please sign in to comment.