Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d6f0d0c authored by James Bottomley's avatar James Bottomley
Browse files

[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: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 3de2403e
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -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;