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 @@ ...@@ -45,13 +45,9 @@
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
LIST_HEAD(scsi_host_tmpl_list); static LIST_HEAD(scsi_host_hn_list);
LIST_HEAD(scsi_host_hn_list); static LIST_HEAD(scsi_host_list);
static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(scsi_host_list);
spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
struct Scsi_Device_Template * scsi_devicelist;
static int scsi_host_next_hn; /* host_no for next new host */ static int scsi_host_next_hn; /* host_no for next new host */
static int scsi_hosts_registered; /* cnt of registered scsi hosts */ static int scsi_hosts_registered; /* cnt of registered scsi hosts */
...@@ -115,7 +111,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost) ...@@ -115,7 +111,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
{ {
int pcount; int pcount;
Scsi_Device *sdev; Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
Scsi_Cmnd *scmd; Scsi_Cmnd *scmd;
/* /*
...@@ -175,10 +170,7 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost) ...@@ -175,10 +170,7 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
* structures * structures
*/ */
for (sdev = shost->host_queue; sdev; sdev = sdev->next) { for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
for (sdev_tp = scsi_devicelist; sdev_tp; scsi_detach_device(sdev);
sdev_tp = sdev_tp->next)
if (sdev_tp->detach)
(*sdev_tp->detach) (sdev);
/* If something still attached, punt */ /* If something still attached, punt */
if (sdev->attached) { if (sdev->attached) {
...@@ -471,12 +463,9 @@ int scsi_register_host(Scsi_Host_Template *shost_tp) ...@@ -471,12 +463,9 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
{ {
int cur_cnt; int cur_cnt;
Scsi_Device *sdev; Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
struct list_head *lh; struct list_head *lh;
struct Scsi_Host *shost; struct Scsi_Host *shost;
INIT_LIST_HEAD(&shost_tp->shtp_list);
/* /*
* Check no detect routine. * Check no detect routine.
*/ */
...@@ -526,8 +515,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp) ...@@ -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 /* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries * Scsi_Devices entries
*/ */
...@@ -549,31 +536,15 @@ int scsi_register_host(Scsi_Host_Template *shost_tp) ...@@ -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 * Next we create the Scsi_Cmnd structures for this host
*/ */
list_for_each(lh, &scsi_host_list) { list_for_each(lh, &scsi_host_list) {
shost = list_entry(lh, struct Scsi_Host, sh_list); shost = list_entry(lh, struct Scsi_Host, sh_list);
for (sdev = shost->host_queue; sdev; sdev = sdev->next) for (sdev = shost->host_queue; sdev; sdev = sdev->next)
if (sdev->host->hostt == shost_tp) { if (sdev->host->hostt == shost_tp)
scsi_build_commandblocks(sdev); if (scsi_attach_device(sdev))
if (sdev->current_queue_depth == 0)
goto out_of_space; 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) ...@@ -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, printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
(scsi_hosts_registered == 1) ? "" : "s"); (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; MOD_DEC_USE_COUNT;
unlock_kernel(); unlock_kernel();
......
...@@ -57,9 +57,6 @@ typedef struct scsi_disk Disk; ...@@ -57,9 +57,6 @@ typedef struct scsi_disk Disk;
typedef struct SHT typedef struct SHT
{ {
struct list_head shtp_list;
/* Used with loadable modules so that we know when it is safe to unload */ /* Used with loadable modules so that we know when it is safe to unload */
struct module * module; struct module * module;
...@@ -513,8 +510,6 @@ typedef struct SHN ...@@ -513,8 +510,6 @@ typedef struct SHN
unsigned short host_registered; unsigned short host_registered;
} Scsi_Host_Name; } Scsi_Host_Name;
extern struct Scsi_Device_Template * scsi_devicelist;
extern void scsi_proc_host_mkdir(Scsi_Host_Template *); extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
extern void scsi_proc_host_add(struct Scsi_Host *); extern void scsi_proc_host_add(struct Scsi_Host *);
extern void scsi_proc_host_rm(struct Scsi_Host *); extern void scsi_proc_host_rm(struct Scsi_Host *);
......
...@@ -132,6 +132,12 @@ struct softscsi_data { ...@@ -132,6 +132,12 @@ struct softscsi_data {
static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned; 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. * 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. * 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) ...@@ -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, static int proc_scsi_gen_write(struct file * file, const char * buf,
unsigned long length, void *data) unsigned long length, void *data)
{ {
struct Scsi_Device_Template *SDTpnt;
Scsi_Device *scd; Scsi_Device *scd;
struct Scsi_Host *HBA_ptr; struct Scsi_Host *HBA_ptr;
char *p; char *p;
...@@ -1924,12 +1929,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, ...@@ -1924,12 +1929,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if (scd->access_count) if (scd->access_count)
goto out; goto out;
SDTpnt = scsi_devicelist; scsi_detach_device(scd);
while (SDTpnt != NULL) {
if (SDTpnt->detach)
(*SDTpnt->detach) (scd);
SDTpnt = SDTpnt->next;
}
if (scd->attached == 0) { if (scd->attached == 0) {
/* /*
...@@ -1969,6 +1969,56 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, ...@@ -1969,6 +1969,56 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
} }
#endif #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 * This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system. * add a high level scsi driver to the system.
...@@ -1987,8 +2037,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt) ...@@ -1987,8 +2037,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
if (tpnt->next) if (tpnt->next)
return 1; return 1;
down_write(&scsi_devicelist_mutex);
tpnt->next = scsi_devicelist; tpnt->next = scsi_devicelist;
scsi_devicelist = tpnt; scsi_devicelist = tpnt;
up_write(&scsi_devicelist_mutex);
tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag; tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
tpnt->scsi_driverfs_driver.bus = &scsi_driverfs_bus_type; tpnt->scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
...@@ -2094,6 +2146,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt) ...@@ -2094,6 +2146,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
/* /*
* Extract the template from the linked list. * Extract the template from the linked list.
*/ */
down_write(&scsi_devicelist_mutex);
spnt = scsi_devicelist; spnt = scsi_devicelist;
prev_spnt = NULL; prev_spnt = NULL;
while (spnt != tpnt) { while (spnt != tpnt) {
...@@ -2104,6 +2157,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt) ...@@ -2104,6 +2157,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
scsi_devicelist = tpnt->next; scsi_devicelist = tpnt->next;
else else
prev_spnt->next = spnt->next; prev_spnt->next = spnt->next;
up_write(&scsi_devicelist_mutex);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
unlock_kernel(); unlock_kernel();
......
...@@ -481,6 +481,9 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd, ...@@ -481,6 +481,9 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
int timeout, int retries); int timeout, int retries);
extern int scsi_dev_init(void); extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int); 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. * Newer request-based interfaces.
......
...@@ -1322,7 +1322,6 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew, ...@@ -1322,7 +1322,6 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
Scsi_Request *sreq, char *inq_result, int *bflags) Scsi_Request *sreq, char *inq_result, int *bflags)
{ {
Scsi_Device *sdev; Scsi_Device *sdev;
struct Scsi_Device_Template *sdt;
char devname[64]; char devname[64];
extern devfs_handle_t scsi_devfs_handle; extern devfs_handle_t scsi_devfs_handle;
...@@ -1479,9 +1478,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew, ...@@ -1479,9 +1478,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
* function */ * function */
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
for (sdt = scsi_devicelist; sdt; sdt = sdt->next) scsi_detect_device(sdev);
if (sdt->detect)
sdev->attached += (*sdt->detect) (sdev);
if (sdev->host->hostt->slave_attach != NULL) { if (sdev->host->hostt->slave_attach != NULL) {
if (sdev->host->hostt->slave_attach(sdev) != 0) { if (sdev->host->hostt->slave_attach(sdev) != 0) {
...@@ -2010,7 +2007,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel, ...@@ -2010,7 +2007,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
uint id, uint lun) uint id, uint lun)
{ {
Scsi_Device *sdevscan, *sdev = NULL; Scsi_Device *sdevscan, *sdev = NULL;
struct Scsi_Device_Template *sdt;
int res; int res;
if ((channel > shost->max_channel) || (id >= shost->max_id) || 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, ...@@ -2028,24 +2024,7 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
if (res != SCSI_SCAN_LUN_PRESENT) if (res != SCSI_SCAN_LUN_PRESENT)
return; return;
BUG_ON(sdev == NULL); scsi_attach_device(sdev);
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);
} }
/** /**
......
...@@ -92,7 +92,6 @@ EXPORT_SYMBOL(scsi_reset_provider); ...@@ -92,7 +92,6 @@ EXPORT_SYMBOL(scsi_reset_provider);
EXPORT_SYMBOL(scsi_host_get_next); EXPORT_SYMBOL(scsi_host_get_next);
EXPORT_SYMBOL(scsi_host_hn_get); EXPORT_SYMBOL(scsi_host_hn_get);
EXPORT_SYMBOL(scsi_host_put); EXPORT_SYMBOL(scsi_host_put);
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types); 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