ncr5380: Introduce unbound workqueue
Allocate a work queue that will permit busy waiting and sleeping. This means NCR5380_init() can potentially fail, so add this error path. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Ondrej Zary <linux@rainbow-software.org> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
e52bbd5ccf
commit
0ad0eff98f
13 changed files with 96 additions and 41 deletions
|
@ -514,7 +514,7 @@ static int should_disconnect(unsigned char cmd)
|
|||
static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
|
||||
{
|
||||
hostdata->time_expires = jiffies + timeout;
|
||||
schedule_delayed_work(&hostdata->coroutine, timeout);
|
||||
queue_delayed_work(hostdata->work_q, &hostdata->coroutine, timeout);
|
||||
}
|
||||
|
||||
|
||||
|
@ -791,6 +791,11 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
|
|||
hostdata->disconnected_queue = NULL;
|
||||
|
||||
INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
|
||||
hostdata->work_q = alloc_workqueue("ncr5380_%d",
|
||||
WQ_UNBOUND | WQ_MEM_RECLAIM,
|
||||
1, instance->host_no);
|
||||
if (!hostdata->work_q)
|
||||
return -ENOMEM;
|
||||
|
||||
/* The CHECK code seems to break the 53C400. Will check it later maybe */
|
||||
if (flags & FLAG_NCR53C400)
|
||||
|
@ -872,6 +877,7 @@ static void NCR5380_exit(struct Scsi_Host *instance)
|
|||
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
|
||||
|
||||
cancel_delayed_work_sync(&hostdata->coroutine);
|
||||
destroy_workqueue(hostdata->work_q);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -932,7 +938,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct
|
|||
|
||||
/* Run the coroutine if it isn't already running. */
|
||||
/* Kick off command processing */
|
||||
schedule_delayed_work(&hostdata->coroutine, 0);
|
||||
queue_delayed_work(hostdata->work_q, &hostdata->coroutine, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1128,7 +1134,8 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id)
|
|||
} /* if BASR_IRQ */
|
||||
spin_unlock_irqrestore(instance->host_lock, flags);
|
||||
if(!done)
|
||||
schedule_delayed_work(&hostdata->coroutine, 0);
|
||||
queue_delayed_work(hostdata->work_q,
|
||||
&hostdata->coroutine, 0);
|
||||
} while (!done);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -284,6 +284,7 @@ struct NCR5380_hostdata {
|
|||
unsigned spin_max_r;
|
||||
unsigned spin_max_w;
|
||||
#endif
|
||||
struct workqueue_struct *work_q;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
|
|
@ -238,7 +238,9 @@ static int cumanascsi1_probe(struct expansion_card *ec,
|
|||
|
||||
host->irq = ec->irq;
|
||||
|
||||
NCR5380_init(host, 0);
|
||||
ret = NCR5380_init(host, 0);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
||||
NCR5380_maybe_reset_bus(host);
|
||||
|
||||
|
@ -250,7 +252,7 @@ static int cumanascsi1_probe(struct expansion_card *ec,
|
|||
if (ret) {
|
||||
printk("scsi%d: IRQ%d not free: %d\n",
|
||||
host->host_no, host->irq, ret);
|
||||
goto out_unmap;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
ret = scsi_add_host(host, &ec->dev);
|
||||
|
@ -262,6 +264,8 @@ static int cumanascsi1_probe(struct expansion_card *ec,
|
|||
|
||||
out_free_irq:
|
||||
free_irq(host->irq, host);
|
||||
out_exit:
|
||||
NCR5380_exit(host);
|
||||
out_unmap:
|
||||
iounmap(priv(host)->base);
|
||||
iounmap(priv(host)->dma);
|
||||
|
|
|
@ -143,17 +143,21 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
|
|||
host->irq = NO_IRQ;
|
||||
host->n_io_port = 255;
|
||||
|
||||
NCR5380_init(host, 0);
|
||||
ret = NCR5380_init(host, 0);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
||||
NCR5380_maybe_reset_bus(host);
|
||||
|
||||
ret = scsi_add_host(host, &ec->dev);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
goto out_exit;
|
||||
|
||||
scsi_scan_host(host);
|
||||
goto out;
|
||||
|
||||
out_exit:
|
||||
NCR5380_exit(host);
|
||||
out_unmap:
|
||||
iounmap(priv(host)->base);
|
||||
unreg:
|
||||
|
|
|
@ -643,7 +643,7 @@ static inline void queue_main(struct NCR5380_hostdata *hostdata)
|
|||
queue it on the 'immediate' task queue, to be processed
|
||||
immediately after the current interrupt processing has
|
||||
finished. */
|
||||
schedule_work(&hostdata->main_task);
|
||||
queue_work(hostdata->work_q, &hostdata->main_task);
|
||||
}
|
||||
/* else: nothing to do: the running NCR5380_main() will pick up
|
||||
any newly queued command. */
|
||||
|
@ -832,6 +832,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
|
|||
hostdata->flags = flags;
|
||||
|
||||
INIT_WORK(&hostdata->main_task, NCR5380_main);
|
||||
hostdata->work_q = alloc_workqueue("ncr5380_%d",
|
||||
WQ_UNBOUND | WQ_MEM_RECLAIM,
|
||||
1, instance->host_no);
|
||||
if (!hostdata->work_q)
|
||||
return -ENOMEM;
|
||||
|
||||
prepare_info(instance);
|
||||
|
||||
|
@ -907,6 +912,7 @@ static void NCR5380_exit(struct Scsi_Host *instance)
|
|||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
cancel_work_sync(&hostdata->main_task);
|
||||
destroy_workqueue(hostdata->work_q);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -885,7 +885,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
|
|||
#endif
|
||||
host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
|
||||
|
||||
NCR5380_init(instance, host_flags);
|
||||
error = NCR5380_init(instance, host_flags);
|
||||
if (error)
|
||||
goto fail_init;
|
||||
|
||||
if (IS_A_TT()) {
|
||||
error = request_irq(instance->irq, scsi_tt_intr, 0,
|
||||
|
@ -947,6 +949,7 @@ fail_host:
|
|||
free_irq(instance->irq, instance);
|
||||
fail_irq:
|
||||
NCR5380_exit(instance);
|
||||
fail_init:
|
||||
scsi_host_put(instance);
|
||||
fail_alloc:
|
||||
if (atari_dma_buffer)
|
||||
|
|
|
@ -95,7 +95,9 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
|
|||
*/
|
||||
shost->irq = NO_IRQ;
|
||||
|
||||
NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
|
||||
error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
|
||||
if (error)
|
||||
goto out_host_put;
|
||||
|
||||
NCR5380_maybe_reset_bus(shost);
|
||||
|
||||
|
@ -103,11 +105,15 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
|
|||
|
||||
error = scsi_add_host(shost, &pdev->dev);
|
||||
if (error)
|
||||
goto out_release_region;
|
||||
goto out_exit;
|
||||
|
||||
scsi_scan_host(shost);
|
||||
return 0;
|
||||
|
||||
out_exit:
|
||||
NCR5380_exit(shost);
|
||||
out_host_put:
|
||||
scsi_host_put(shost);
|
||||
out_release_region:
|
||||
release_region(io, DMX3191D_REGION_LEN);
|
||||
out_disable_device:
|
||||
|
@ -119,15 +125,14 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
|
|||
static void dmx3191d_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
unsigned long io = shost->io_port;
|
||||
|
||||
scsi_remove_host(shost);
|
||||
|
||||
NCR5380_exit(shost);
|
||||
|
||||
release_region(shost->io_port, DMX3191D_REGION_LEN);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
scsi_host_put(shost);
|
||||
release_region(io, DMX3191D_REGION_LEN);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static struct pci_device_id dmx3191d_pci_tbl[] = {
|
||||
|
|
|
@ -230,12 +230,13 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
|
|||
found:
|
||||
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if (instance == NULL)
|
||||
break;
|
||||
goto out_unmap;
|
||||
|
||||
instance->base = addr;
|
||||
((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
|
||||
|
||||
NCR5380_init(instance, 0);
|
||||
if (NCR5380_init(instance, 0))
|
||||
goto out_unregister;
|
||||
|
||||
NCR5380_maybe_reset_bus(instance);
|
||||
|
||||
|
@ -275,6 +276,12 @@ found:
|
|||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out_unmap:
|
||||
iounmap(base);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -239,9 +239,6 @@ static int __init do_DTC3181E_setup(char *str)
|
|||
* and DTC436(ISAPnP) controllers. If overrides have been set we use
|
||||
* them.
|
||||
*
|
||||
* The caller supplied NCR5380_init function is invoked from here, before
|
||||
* the interrupt line is taken.
|
||||
*
|
||||
* Locks: none
|
||||
*/
|
||||
|
||||
|
@ -402,15 +399,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
|
|||
}
|
||||
#endif
|
||||
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if (instance == NULL) {
|
||||
#ifndef SCSI_G_NCR5380_MEM
|
||||
release_region(overrides[current_override].NCR5380_map_name, region_size);
|
||||
#else
|
||||
iounmap(iomem);
|
||||
release_mem_region(base, NCR5380_region_size);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (instance == NULL)
|
||||
goto out_release;
|
||||
|
||||
#ifndef SCSI_G_NCR5380_MEM
|
||||
instance->io_port = overrides[current_override].NCR5380_map_name;
|
||||
|
@ -427,7 +417,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
|
|||
((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
|
||||
#endif
|
||||
|
||||
NCR5380_init(instance, flags);
|
||||
if (NCR5380_init(instance, flags))
|
||||
goto out_unregister;
|
||||
|
||||
if (overrides[current_override].board == BOARD_NCR53C400)
|
||||
NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
|
||||
|
@ -459,6 +450,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
|
|||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out_release:
|
||||
#ifndef SCSI_G_NCR5380_MEM
|
||||
release_region(overrides[current_override].NCR5380_map_name, region_size);
|
||||
#else
|
||||
iounmap(iomem);
|
||||
release_mem_region(base, NCR5380_region_size);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -475,15 +477,12 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
|
|||
if (instance->irq != NO_IRQ)
|
||||
free_irq(instance->irq, instance);
|
||||
NCR5380_exit(instance);
|
||||
|
||||
#ifndef SCSI_G_NCR5380_MEM
|
||||
release_region(instance->io_port, instance->n_io_port);
|
||||
#else
|
||||
iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem);
|
||||
release_mem_region(instance->base, NCR5380_region_size);
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -382,7 +382,9 @@ static int __init mac_scsi_probe(struct platform_device *pdev)
|
|||
#endif
|
||||
host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
|
||||
|
||||
NCR5380_init(instance, host_flags);
|
||||
error = NCR5380_init(instance, host_flags);
|
||||
if (error)
|
||||
goto fail_init;
|
||||
|
||||
if (instance->irq != NO_IRQ) {
|
||||
error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED,
|
||||
|
@ -407,6 +409,7 @@ fail_host:
|
|||
free_irq(instance->irq, instance);
|
||||
fail_irq:
|
||||
NCR5380_exit(instance);
|
||||
fail_init:
|
||||
scsi_host_put(instance);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -378,11 +378,12 @@ static int __init pas16_detect(struct scsi_host_template *tpnt)
|
|||
|
||||
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if(instance == NULL)
|
||||
break;
|
||||
goto out;
|
||||
|
||||
instance->io_port = io_port;
|
||||
|
||||
NCR5380_init(instance, 0);
|
||||
if (NCR5380_init(instance, 0))
|
||||
goto out_unregister;
|
||||
|
||||
NCR5380_maybe_reset_bus(instance);
|
||||
|
||||
|
@ -418,6 +419,11 @@ static int __init pas16_detect(struct scsi_host_template *tpnt)
|
|||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -557,7 +557,9 @@ static int __init sun3_scsi_probe(struct platform_device *pdev)
|
|||
host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
|
||||
#endif
|
||||
|
||||
NCR5380_init(instance, host_flags);
|
||||
error = NCR5380_init(instance, host_flags);
|
||||
if (error)
|
||||
goto fail_init;
|
||||
|
||||
error = request_irq(instance->irq, scsi_sun3_intr, 0,
|
||||
"NCR5380", instance);
|
||||
|
@ -604,6 +606,7 @@ fail_host:
|
|||
free_irq(instance->irq, instance);
|
||||
fail_irq:
|
||||
NCR5380_exit(instance);
|
||||
fail_init:
|
||||
scsi_host_put(instance);
|
||||
fail_alloc:
|
||||
if (udc_regs)
|
||||
|
|
|
@ -208,12 +208,13 @@ static int __init t128_detect(struct scsi_host_template *tpnt)
|
|||
found:
|
||||
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if(instance == NULL)
|
||||
break;
|
||||
goto out_unmap;
|
||||
|
||||
instance->base = base;
|
||||
((struct NCR5380_hostdata *)instance->hostdata)->base = p;
|
||||
|
||||
NCR5380_init(instance, 0);
|
||||
if (NCR5380_init(instance, 0))
|
||||
goto out_unregister;
|
||||
|
||||
NCR5380_maybe_reset_bus(instance);
|
||||
|
||||
|
@ -246,6 +247,12 @@ found:
|
|||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out_unmap:
|
||||
iounmap(p);
|
||||
return count;
|
||||
}
|
||||
|
||||
static int t128_release(struct Scsi_Host *shost)
|
||||
|
|
Loading…
Reference in a new issue