Commit 4365d624 authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] proper scsi_devicelist handling

Factor out code calling methods of all device template on a scsi_device
out to three helper functions in scsi.c, make scsi_devicelist static to
it and add a r/w semaphore to protect it.

Make scsi_host_list and scsi_host_hn_list static to hosts.c and remove
the never used scsi_host_tmpl_list (we only add to it and remove from
it but never traverse it)
parent c6b82347
......@@ -45,13 +45,9 @@
#include "scsi.h"
#include "hosts.h"
LIST_HEAD(scsi_host_tmpl_list);
LIST_HEAD(scsi_host_hn_list);
LIST_HEAD(scsi_host_list);
spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
struct Scsi_Device_Template * scsi_devicelist;
static LIST_HEAD(scsi_host_hn_list);
static LIST_HEAD(scsi_host_list);
static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
static int scsi_host_next_hn; /* host_no for next new host */
static int scsi_hosts_registered; /* cnt of registered scsi hosts */
......@@ -115,7 +111,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
{
int pcount;
Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
Scsi_Cmnd *scmd;
/*
......@@ -175,10 +170,7 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
* structures
*/
for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
for (sdev_tp = scsi_devicelist; sdev_tp;
sdev_tp = sdev_tp->next)
if (sdev_tp->detach)
(*sdev_tp->detach) (sdev);
scsi_detach_device(sdev);
/* If something still attached, punt */
if (sdev->attached) {
......@@ -471,12 +463,9 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
{
int cur_cnt;
Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
struct list_head *lh;
struct Scsi_Host *shost;
INIT_LIST_HEAD(&shost_tp->shtp_list);
/*
* Check no detect routine.
*/
......@@ -526,8 +515,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
list_add_tail(&shost_tp->shtp_list, &scsi_host_tmpl_list);
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
......@@ -549,31 +536,15 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
for (sdev_tp = scsi_devicelist; sdev_tp;
sdev_tp = sdev_tp->next) {
if (sdev_tp->init && sdev_tp->dev_noticed)
(*sdev_tp->init) ();
}
/*
* Next we create the Scsi_Cmnd structures for this host
*/
list_for_each(lh, &scsi_host_list) {
shost = list_entry(lh, struct Scsi_Host, sh_list);
for (sdev = shost->host_queue; sdev; sdev = sdev->next)
if (sdev->host->hostt == shost_tp) {
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
if (sdev->host->hostt == shost_tp)
if (scsi_attach_device(sdev))
goto out_of_space;
for (sdev_tp = scsi_devicelist;
sdev_tp;
sdev_tp = sdev_tp->next)
if (sdev_tp->attach)
(*sdev_tp->attach) (sdev);
if (!sdev->attached) {
scsi_release_commandblocks(sdev);
}
}
}
}
......@@ -614,14 +585,6 @@ int scsi_unregister_host(Scsi_Host_Template *shost_tp)
printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
(scsi_hosts_registered == 1) ? "" : "s");
/*
* Remove it from the list if all
* hosts were successfully removed (ie preset == 0)
*/
if (!shost_tp->present) {
list_del(&shost_tp->shtp_list);
}
MOD_DEC_USE_COUNT;
unlock_kernel();
......
......@@ -57,9 +57,6 @@ typedef struct scsi_disk Disk;
typedef struct SHT
{
struct list_head shtp_list;
/* Used with loadable modules so that we know when it is safe to unload */
struct module * module;
......@@ -513,8 +510,6 @@ typedef struct SHN
unsigned short host_registered;
} Scsi_Host_Name;
extern struct Scsi_Device_Template * scsi_devicelist;
extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
extern void scsi_proc_host_add(struct Scsi_Host *);
extern void scsi_proc_host_rm(struct Scsi_Host *);
......
......@@ -132,6 +132,12 @@ struct softscsi_data {
static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned;
/*
* List of all highlevel drivers.
*/
static struct Scsi_Device_Template *scsi_devicelist;
static DECLARE_RWSEM(scsi_devicelist_mutex);
/*
* Note - the initial logging level can be set here to log events at boot time.
* After the system is up, you may enable logging via the /proc interface.
......@@ -1718,7 +1724,6 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
static int proc_scsi_gen_write(struct file * file, const char * buf,
unsigned long length, void *data)
{
struct Scsi_Device_Template *SDTpnt;
Scsi_Device *scd;
struct Scsi_Host *HBA_ptr;
char *p;
......@@ -1924,12 +1929,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if (scd->access_count)
goto out;
SDTpnt = scsi_devicelist;
while (SDTpnt != NULL) {
if (SDTpnt->detach)
(*SDTpnt->detach) (scd);
SDTpnt = SDTpnt->next;
}
scsi_detach_device(scd);
if (scd->attached == 0) {
/*
......@@ -1969,6 +1969,56 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
}
#endif
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)
sdev->attached += (*sdt->detect)(sdev);
up_read(&scsi_devicelist_mutex);
}
int scsi_attach_device(struct scsi_device *sdev)
{
struct Scsi_Device_Template *sdt;
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->init && sdt->dev_noticed)
(*sdt->init) ();
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->attach)
(*sdt->attach) (sdev);
up_read(&scsi_devicelist_mutex);
if (!sdev->attached)
scsi_release_commandblocks(sdev);
return 0;
fail:
printk(KERN_ERR "%s: Allocation failure during SCSI scanning, "
"some SCSI devices might not be configured\n",
__FUNCTION__);
return -ENOMEM;
}
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);
up_read(&scsi_devicelist_mutex);
}
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
......@@ -1987,8 +2037,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
if (tpnt->next)
return 1;
down_write(&scsi_devicelist_mutex);
tpnt->next = scsi_devicelist;
scsi_devicelist = tpnt;
up_write(&scsi_devicelist_mutex);
tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
tpnt->scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
......@@ -2094,6 +2146,7 @@ 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) {
......@@ -2104,6 +2157,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
scsi_devicelist = tpnt->next;
else
prev_spnt->next = spnt->next;
up_write(&scsi_devicelist_mutex);
MOD_DEC_USE_COUNT;
unlock_kernel();
......
......@@ -481,6 +481,9 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
int timeout, int retries);
extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern void scsi_detect_device(struct scsi_device *);
extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *);
/*
* Newer request-based interfaces.
......
......@@ -1322,7 +1322,6 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
Scsi_Request *sreq, char *inq_result, int *bflags)
{
Scsi_Device *sdev;
struct Scsi_Device_Template *sdt;
char devname[64];
extern devfs_handle_t scsi_devfs_handle;
......@@ -1479,9 +1478,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
* function */
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detect)
sdev->attached += (*sdt->detect) (sdev);
scsi_detect_device(sdev);
if (sdev->host->hostt->slave_attach != NULL) {
if (sdev->host->hostt->slave_attach(sdev) != 0) {
......@@ -2010,7 +2007,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
uint id, uint lun)
{
Scsi_Device *sdevscan, *sdev = NULL;
struct Scsi_Device_Template *sdt;
int res;
if ((channel > shost->max_channel) || (id >= shost->max_id) ||
......@@ -2028,24 +2024,7 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
if (res != SCSI_SCAN_LUN_PRESENT)
return;
BUG_ON(sdev == NULL);
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0) {
printk(ALLOC_FAILURE_MSG, __FUNCTION__);
return;
}
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->init && sdt->dev_noticed)
(*sdt->init) ();
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->attach)
(*sdt->attach) (sdev);
if (!sdev->attached)
scsi_release_commandblocks(sdev);
scsi_attach_device(sdev);
}
/**
......
......@@ -92,7 +92,6 @@ EXPORT_SYMBOL(scsi_reset_provider);
EXPORT_SYMBOL(scsi_host_get_next);
EXPORT_SYMBOL(scsi_host_hn_get);
EXPORT_SYMBOL(scsi_host_put);
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types);
/*
......
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