Commit ad82a127 authored by Doug Ledford's avatar Doug Ledford

Update high level scsi drivers to use struct list_head in templates

Update scsi.c for struct list_head in upper layer templates
Update scsi.c for new module loader semantics
parent ae3c7c33
......@@ -549,7 +549,7 @@ extern void scsi_mark_host_reset(struct Scsi_Host *);
struct Scsi_Device_Template
{
struct Scsi_Device_Template * next;
struct list_head list;
const char * name;
const char * tag;
struct module * module; /* Used for loadable modules */
......
......@@ -163,6 +163,7 @@ static int osst_dev_max;
struct Scsi_Device_Template osst_template =
{
module: THIS_MODULE,
list: LIST_HEAD_INIT(osst_template.list),
name: "OnStream tape",
tag: "osst",
scsi_type: TYPE_TAPE,
......@@ -4174,15 +4175,13 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
#endif
return (-EBUSY);
}
if (!try_module_get(STp->device->host->hostt->module))
return (-ENXIO);
STp->device->access_count++;
STp->in_use = 1;
STp->rew_at_close = (minor(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
if (osst_template.module)
__MOD_INC_USE_COUNT(osst_template.module);
STp->device->access_count++;
if (mode != STp->current_mode) {
#if DEBUG
if (debugging)
......@@ -4521,10 +4520,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
STp->header_ok = 0;
STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
if (osst_template.module)
__MOD_DEC_USE_COUNT(osst_template.module);
module_put(STp->device->host->hostt->module);
return retval;
}
......@@ -4652,10 +4648,7 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
STp->in_use = 0;
STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
if(osst_template.module)
__MOD_DEC_USE_COUNT(osst_template.module);
module_put(STp->device->host->hostt->module);
return result;
}
......
......@@ -135,7 +135,7 @@ static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned;
/*
* List of all highlevel drivers.
*/
static struct Scsi_Device_Template *scsi_devicelist;
LIST_HEAD(scsi_devicelist);
static DECLARE_RWSEM(scsi_devicelist_mutex);
/*
......@@ -1963,9 +1963,15 @@ void scsi_detect_device(struct scsi_device *sdev)
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detect)
(*sdt->detect)(sdev);
list_for_each_entry(sdt, &scsi_devicelist, list)
if (sdt->detect) {
if(try_module_get(sdt->module)) {
(*sdt->detect)(sdev);
module_put(sdt->module);
} else {
printk(KERN_WARNING "SCSI module %s not ready, skipping detection.\n", sdt->name);
}
}
up_read(&scsi_devicelist_mutex);
}
......@@ -1974,14 +1980,20 @@ int scsi_attach_device(struct scsi_device *sdev)
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->attach)
list_for_each_entry(sdt, &scsi_devicelist, list)
if (sdt->attach) {
/*
* XXX check result when the upper level attach
* return values are fixed, and on failure goto
* fail.
*/
(*sdt->attach) (sdev);
if(try_module_get(sdt->module)) {
(*sdt->attach)(sdev);
module_put(sdt->module);
} else {
printk(KERN_WARNING "SCSI module %s not ready, skipping attach.\n", sdt->name);
}
}
up_read(&scsi_devicelist_mutex);
return 0;
......@@ -1997,9 +2009,15 @@ void scsi_detach_device(struct scsi_device *sdev)
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detach)
(*sdt->detach)(sdev);
list_for_each_entry(sdt, &scsi_devicelist, list)
if (sdt->detach) {
if(try_module_get(sdt->module)) {
(*sdt->detach)(sdev);
module_put(sdt->module);
} else {
printk(KERN_WARNING "SCSI module %s not ready, skipping detach.\n", sdt->name);
}
}
up_read(&scsi_devicelist_mutex);
}
......@@ -2064,24 +2082,34 @@ void scsi_slave_detach(struct scsi_device *sdev)
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
*
* This entry point is called from the upper level module's module_init()
* routine. That implies that when this function is called, the
* scsi_mod module is locked down because of upper module layering and
* that the high level driver module is locked down by being in it's
* init routine. So, the *only* thing we have to do to protect adds
* we perform in this function is to make sure that all call's
* to the high level driver's attach() and detach() call in points, other
* than via scsi_register_device and scsi_unregister_device which are in
* the module_init and module_exit code respectively and therefore already
* locked down by the kernel module loader, are wrapped by try_module_get()
* and module_put() to avoid races on device adds and removes.
*/
int scsi_register_device(struct Scsi_Device_Template *tpnt)
{
Scsi_Device *SDpnt;
struct Scsi_Host *shpnt;
int out_of_space = 0;
#ifdef CONFIG_KMOD
if (scsi_host_get_next(NULL) == NULL)
request_module("scsi_hostadapter");
#endif
if (tpnt->next)
if (!list_empty(&tpnt->list))
return 1;
down_write(&scsi_devicelist_mutex);
tpnt->next = scsi_devicelist;
scsi_devicelist = tpnt;
list_add_tail(&tpnt->list, &scsi_devicelist);
up_write(&scsi_devicelist_mutex);
tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
......@@ -2120,13 +2148,6 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
}
}
MOD_INC_USE_COUNT;
if (out_of_space) {
scsi_unregister_device(tpnt); /* easiest way to clean up?? */
return 1;
}
return 0;
}
......@@ -2134,16 +2155,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
{
Scsi_Device *SDpnt;
struct Scsi_Host *shpnt;
struct Scsi_Device_Template *spnt;
struct Scsi_Device_Template *prev_spnt;
lock_kernel();
/*
* If we are busy, this is not going to fly.
if (GET_USE_COUNT(tpnt->module) != 0)
goto error_out;
*/
driver_unregister(&tpnt->scsi_driverfs_driver);
/*
......@@ -2162,28 +2174,14 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
* Extract the template from the linked list.
*/
down_write(&scsi_devicelist_mutex);
spnt = scsi_devicelist;
prev_spnt = NULL;
while (spnt != tpnt) {
prev_spnt = spnt;
spnt = spnt->next;
}
if (prev_spnt == NULL)
scsi_devicelist = tpnt->next;
else
prev_spnt->next = spnt->next;
list_del(&tpnt->list);
up_write(&scsi_devicelist_mutex);
MOD_DEC_USE_COUNT;
unlock_kernel();
/*
* Final cleanup for the driver is done in the driver sources in the
* cleanup function.
*/
return 0;
error_out:
unlock_kernel();
return -1;
}
#ifdef CONFIG_PROC_FS
......
......@@ -104,6 +104,7 @@ static struct notifier_block sd_notifier_block = {sd_notifier, NULL, 0};
static struct Scsi_Device_Template sd_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(sd_template.list),
.name = "disk",
.tag = "sd",
.scsi_type = TYPE_DISK,
......@@ -453,10 +454,8 @@ static int sd_open(struct inode *inode, struct file *filp)
* The following code can sleep.
* Module unloading must be prevented
*/
if (sdp->host->hostt->module)
__MOD_INC_USE_COUNT(sdp->host->hostt->module);
if (sd_template.module)
__MOD_INC_USE_COUNT(sd_template.module);
if(!try_module_get(sdp->host->hostt->module))
return -ENOMEM;
sdp->access_count++;
if (sdp->removable) {
......@@ -498,10 +497,7 @@ static int sd_open(struct inode *inode, struct file *filp)
error_out:
sdp->access_count--;
if (sdp->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->host->hostt->module);
if (sd_template.module)
__MOD_DEC_USE_COUNT(sd_template.module);
module_put(sdp->host->hostt->module);
return retval;
}
......@@ -536,10 +532,7 @@ static int sd_release(struct inode *inode, struct file *filp)
if (scsi_block_when_processing_errors(sdp))
scsi_set_medium_removal(sdp, SCSI_REMOVAL_ALLOW);
}
if (sdp->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->host->hostt->module);
if (sd_template.module)
__MOD_DEC_USE_COUNT(sd_template.module);
module_put(sdp->host->hostt->module);
return 0;
}
......@@ -1241,6 +1234,7 @@ static int sd_attach(struct scsi_device * sdp)
gd->de = sdp->de;
gd->major = SD_MAJOR(dsk_nr>>4);
gd->first_minor = (dsk_nr & 15)<<4;
gd->minors = 16;
gd->fops = &sd_fops;
if (dsk_nr > 26)
sprintf(gd->disk_name, "sd%c%c",'a'+dsk_nr/26-1,'a'+dsk_nr%26);
......
......@@ -121,6 +121,7 @@ static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; /* Also used to lock
static struct Scsi_Device_Template sg_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(sg_template.list),
.name = "generic",
.tag = "sg",
.scsi_type = 0xff,
......@@ -261,8 +262,8 @@ sg_open(struct inode *inode, struct file *filp)
/* This driver's module count bumped by fops_get in <linux/fs.h> */
/* Prevent the device driver from vanishing while we sleep */
if (sdp->device->host->hostt->module)
__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
if (!try_module_get(sdp->device->host->hostt->module))
return -ENXIO;
sdp->device->access_count++;
if (!((flags & O_NONBLOCK) ||
......@@ -317,8 +318,7 @@ sg_open(struct inode *inode, struct file *filp)
error_out:
sdp->device->access_count--;
if ((!sdp->detached) && sdp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
module_put(sdp->device->host->hostt->module);
return retval;
}
......@@ -336,9 +336,7 @@ sg_release(struct inode *inode, struct file *filp)
if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
if (!sdp->detached) {
sdp->device->access_count--;
if (sdp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->device->host->hostt->
module);
module_put(sdp->device->host->hostt->module);
}
sdp->exclude = 0;
wake_up_interruptible(&sdp->o_excl_wait);
......@@ -1304,11 +1302,8 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n"));
if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
sdp->device->access_count--;
if (sdp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
module_put(sdp->device->host->hostt->module);
}
if (sg_template.module)
__MOD_DEC_USE_COUNT(sg_template.module);
sfp = NULL;
}
} else if (srp && srp->orphan) {
......@@ -1539,12 +1534,7 @@ sg_detach(Scsi_Device * scsidp)
}
if (sfp->closed) {
sdp->device->access_count--;
if (sg_template.module)
__MOD_DEC_USE_COUNT(sg_template.module);
if (sdp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(
sdp->device->host->
hostt->module);
module_put(sdp->device->host->hostt->module);
__sg_remove_sfp(sdp, sfp);
} else {
delay = 1;
......@@ -2530,13 +2520,12 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
}
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
} else {
sfp->closed = 1; /* flag dirty state on this fd */
sdp->device->access_count++;
/* MOD_INC's to inhibit unloading sg and associated adapter driver */
if (sg_template.module)
__MOD_INC_USE_COUNT(sg_template.module);
if (sdp->device->host->hostt->module)
__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
/* only bump the access_count if we actually succeeded in
* throwing another counter on the host module */
if(try_module_get(sdp->device->host->hostt->module))
sdp->device->access_count++;
sfp->closed = 1; /* flag dirty state on this fd */
SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
dirty));
}
......
......@@ -72,6 +72,7 @@ static int sr_init_command(struct scsi_cmnd *);
static struct Scsi_Device_Template sr_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(sr_template.list),
.name = "cdrom",
.tag = "sr",
.scsi_type = TYPE_ROM,
......@@ -130,10 +131,7 @@ static void sr_release(struct cdrom_device_info *cdi)
if (cd->device->sector_size > 2048)
sr_set_blocklength(cd, 2048);
cd->device->access_count--;
if (cd->device->host->hostt->module)
__MOD_DEC_USE_COUNT(cd->device->host->hostt->module);
if (sr_template.module)
__MOD_DEC_USE_COUNT(sr_template.module);
module_put(cd->device->host->hostt->module);
}
static struct cdrom_device_ops sr_dops = {
......@@ -472,11 +470,9 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
if (!scsi_block_when_processing_errors(cd->device)) {
return -ENXIO;
}
if(!try_module_get(cd->device->host->hostt->module))
return -ENXIO;
cd->device->access_count++;
if (cd->device->host->hostt->module)
__MOD_INC_USE_COUNT(cd->device->host->hostt->module);
if (sr_template.module)
__MOD_INC_USE_COUNT(sr_template.module);
/* If this device did not have media in the drive at boot time, then
* we would have been unable to get the sector size. Check to see if
......
......@@ -175,6 +175,7 @@ static void st_detach(Scsi_Device *);
static struct Scsi_Device_Template st_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(st_template.list),
.name = "tape",
.tag = "st",
.scsi_type = TYPE_TAPE,
......@@ -992,13 +993,13 @@ static int st_open(struct inode *inode, struct file *filp)
DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
return (-EBUSY);
}
if(!try_module_get(STp->device->host->hostt->module))
return (-ENXIO);
STp->device->access_count++;
STp->in_use = 1;
write_unlock(&st_dev_arr_lock);
STp->rew_at_close = STp->autorew_dev = (minor(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
STp->device->access_count++;
if (!scsi_block_when_processing_errors(STp->device)) {
retval = (-ENXIO);
......@@ -1040,8 +1041,7 @@ static int st_open(struct inode *inode, struct file *filp)
normalize_buffer(STp->buffer);
STp->in_use = 0;
STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
module_put(STp->device->host->hostt->module);
return retval;
}
......@@ -1175,8 +1175,7 @@ static int st_release(struct inode *inode, struct file *filp)
STp->in_use = 0;
write_unlock(&st_dev_arr_lock);
STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
module_put(STp->device->host->hostt->module);
return result;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment