Commit 710471f0 authored by James Bottomley's avatar James Bottomley

Merge in patmans changes by hand

parents bb7b9e76 024772d3
...@@ -45,12 +45,101 @@ ...@@ -45,12 +45,101 @@
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
static LIST_HEAD(scsi_host_hn_list);
static LIST_HEAD(scsi_host_list); static LIST_HEAD(scsi_host_list);
static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED; 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_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 */
static char *scsihosts;
MODULE_PARM(scsihosts, "s");
MODULE_PARM_DESC(scsihosts, "scsihosts=driver1,driver2,driver3");
#ifndef MODULE
int __init scsi_setup(char *str)
{
scsihosts = str;
return 1;
}
__setup("scsihosts=", scsi_setup);
#endif
/**
* scsi_find_host_by_num - get a Scsi_Host by host no
*
* @host_no: host number to locate
*
* Return value:
* A pointer to located Scsi_Host or NULL.
**/
static struct Scsi_Host *scsi_find_host_by_num(unsigned short host_no)
{
struct Scsi_Host *shost, *shost_found = NULL;
spin_lock(&scsi_host_list_lock);
list_for_each_entry(shost, &scsi_host_list, sh_list) {
if (shost->host_no > host_no) {
/*
* The list is sorted.
*/
break;
} else if (shost->host_no == host_no) {
shost_found = shost;
break;
}
}
spin_unlock(&scsi_host_list_lock);
return shost_found;
}
/**
* scsi_alloc_hostnum - choose new SCSI host number based on host name.
* @name: String to store in name field
*
* Return value:
* Pointer to a new Scsi_Host_Name
**/
static int scsi_alloc_host_num(const char *name)
{
int hostnum;
int namelen;
const char *start, *end;
if (name) {
hostnum = 0;
namelen = strlen(name);
start = scsihosts;
while (1) {
int hostlen;
if (start && start[0] != '\0') {
end = strpbrk(start, ",:");
if (end) {
hostlen = (end - start);
end++;
} else
hostlen = strlen(start);
/*
* Look for a match on the scsihosts list.
*/
if ((hostlen == namelen) &&
(strncmp(name, start, hostlen) == 0) &&
(!scsi_find_host_by_num(hostnum)))
return hostnum;
start = end;
} else {
/*
* Look for any unused numbers.
*/
if (!scsi_find_host_by_num(hostnum))
return hostnum;
}
hostnum++;
}
} else
return scsi_host_next_hn++;
}
/** /**
* scsi_tp_for_each_host - call function for each scsi host off a template * scsi_tp_for_each_host - call function for each scsi host off a template
...@@ -243,21 +332,11 @@ int scsi_add_host(struct Scsi_Host *shost) ...@@ -243,21 +332,11 @@ int scsi_add_host(struct Scsi_Host *shost)
**/ **/
void scsi_unregister(struct Scsi_Host *shost) void scsi_unregister(struct Scsi_Host *shost)
{ {
struct list_head *lh;
Scsi_Host_Name *shost_name;
/* Remove shost from scsi_host_list */ /* Remove shost from scsi_host_list */
spin_lock(&scsi_host_list_lock); spin_lock(&scsi_host_list_lock);
list_del(&shost->sh_list); list_del(&shost->sh_list);
spin_unlock(&scsi_host_list_lock); spin_unlock(&scsi_host_list_lock);
/* Unregister from scsi_host_hn_list */
list_for_each(lh, &scsi_host_hn_list) {
shost_name = list_entry(lh, Scsi_Host_Name, shn_list);
if (shost->host_no == shost_name->host_no)
shost_name->host_registered = 0;
}
/* /*
* Next, kill the kernel error recovery thread for this host. * Next, kill the kernel error recovery thread for this host.
*/ */
...@@ -283,43 +362,6 @@ void scsi_unregister(struct Scsi_Host *shost) ...@@ -283,43 +362,6 @@ void scsi_unregister(struct Scsi_Host *shost)
kfree(shost); kfree(shost);
} }
/**
* scsi_host_hn_add - allocate and add new Scsi_Host_Name
* @name: String to store in name field
*
* Return value:
* Pointer to a new Scsi_Host_Name
**/
Scsi_Host_Name *scsi_host_hn_add(char *name)
{
Scsi_Host_Name *shost_name;
int len;
len = strlen(name);
shost_name = kmalloc(sizeof(*shost_name), GFP_KERNEL);
if (!shost_name) {
printk(KERN_ERR "%s: out of memory at line %d.\n",
__FUNCTION__, __LINE__);
return NULL;
}
shost_name->name = kmalloc(len + 1, GFP_KERNEL);
if (!shost_name->name) {
kfree(shost_name);
printk(KERN_ERR "%s: out of memory at line %d.\n",
__FUNCTION__, __LINE__);
return NULL;
}
if (len)
strncpy(shost_name->name, name, len);
shost_name->name[len] = 0;
shost_name->host_no = scsi_host_next_hn++;
shost_name->host_registered = 0;
list_add_tail(&shost_name->shn_list, &scsi_host_hn_list);
return shost_name;
}
/** /**
* scsi_register - register a scsi host adapter instance. * scsi_register - register a scsi host adapter instance.
* @shost_tp: pointer to scsi host template * @shost_tp: pointer to scsi host template
...@@ -337,28 +379,17 @@ extern int blk_nohighio; ...@@ -337,28 +379,17 @@ extern int blk_nohighio;
struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes) struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
{ {
struct Scsi_Host *shost, *shost_scr; struct Scsi_Host *shost, *shost_scr;
Scsi_Host_Name *shost_name = NULL;
Scsi_Host_Name *shn = NULL;
char *hname;
size_t hname_len;
struct list_head *lh; struct list_head *lh;
int gfp_mask; int gfp_mask;
DECLARE_MUTEX_LOCKED(sem); DECLARE_MUTEX_LOCKED(sem);
/*
* Determine host number. Check reserved first before allocating
* new one
*/
hname = (shost_tp->proc_name) ? shost_tp->proc_name : "";
hname_len = strlen(hname);
/* Check to see if this host has any error handling facilities */ /* Check to see if this host has any error handling facilities */
if(shost_tp->eh_strategy_handler == NULL && if(shost_tp->eh_strategy_handler == NULL &&
shost_tp->eh_abort_handler == NULL && shost_tp->eh_abort_handler == NULL &&
shost_tp->eh_device_reset_handler == NULL && shost_tp->eh_device_reset_handler == NULL &&
shost_tp->eh_bus_reset_handler == NULL && shost_tp->eh_bus_reset_handler == NULL &&
shost_tp->eh_host_reset_handler == NULL) { shost_tp->eh_host_reset_handler == NULL) {
printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\nERROR: This is not a safe way to run your SCSI host\nERROR: The error handling must be added to this driver\n", hname); printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\nERROR: This is not a safe way to run your SCSI host\nERROR: The error handling must be added to this driver\n", shost_tp->proc_name);
dump_stack(); dump_stack();
} }
gfp_mask = GFP_KERNEL; gfp_mask = GFP_KERNEL;
...@@ -373,26 +404,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes) ...@@ -373,26 +404,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes); memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes);
if (hname_len) shost->host_no = scsi_alloc_host_num(shost_tp->proc_name);
list_for_each(lh, &scsi_host_hn_list) {
shn = list_entry(lh, Scsi_Host_Name, shn_list);
if (!(shn->host_registered) &&
!strncmp(hname, shn->name, hname_len)) {
shost_name = shn;
break;
}
}
if (!shost_name) {
shost_name = scsi_host_hn_add(hname);
if (!shost_name) {
kfree(shost);
return NULL;
}
}
shost->host_no = shost_name->host_no;
shost_name->host_registered = 1;
scsi_hosts_registered++; scsi_hosts_registered++;
spin_lock_init(&shost->default_lock); spin_lock_init(&shost->default_lock);
...@@ -641,22 +653,8 @@ struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *shost) ...@@ -641,22 +653,8 @@ struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *shost)
**/ **/
struct Scsi_Host *scsi_host_hn_get(unsigned short host_no) struct Scsi_Host *scsi_host_hn_get(unsigned short host_no)
{ {
struct list_head *lh; /* XXX Inc ref count */
struct Scsi_Host *shost; return scsi_find_host_by_num(host_no);
spin_lock(&scsi_host_list_lock);
list_for_each(lh, &scsi_host_list) {
shost = list_entry(lh, struct Scsi_Host, sh_list);
if (shost->host_no == host_no) {
/* XXX Inc ref count */
goto done;
}
}
shost = (struct Scsi_Host *)NULL;
done:
spin_unlock(&scsi_host_list_lock);
return shost;
} }
/** /**
...@@ -673,38 +671,19 @@ void scsi_host_put(struct Scsi_Host *shost) ...@@ -673,38 +671,19 @@ void scsi_host_put(struct Scsi_Host *shost)
} }
/** /**
* scsi_host_hn_init - init scsi host number list from string * scsi_host_init - set up the scsi host number list based on any entries
* @shost_hn: string of scsi host driver names. * scsihosts.
**/
void __init scsi_host_hn_init(char *shost_hn)
{
char *temp = shost_hn;
while (temp) {
while (*temp && (*temp != ':') && (*temp != ','))
temp++;
if (!*temp)
temp = NULL;
else
*temp++ = 0;
(void)scsi_host_hn_add(shost_hn);
shost_hn = temp;
}
}
/**
* scsi_host_no_release - free all entries in scsi host number list
**/ **/
void __exit scsi_host_hn_release() void __init scsi_host_init(void)
{ {
struct list_head *lh, *next; char *shost_hn;
Scsi_Host_Name *shn;
shost_hn = scsihosts;
list_for_each_safe(lh, next, &scsi_host_hn_list) { while (shost_hn) {
shn = list_entry(lh, Scsi_Host_Name, shn_list); scsi_host_next_hn++;
if (shn->name) shost_hn = strpbrk(shost_hn, ":,");
kfree(shn->name); if (shost_hn)
kfree(shn); shost_hn++;
} }
} }
......
...@@ -578,8 +578,7 @@ extern int scsi_unregister_host(Scsi_Host_Template *); ...@@ -578,8 +578,7 @@ extern int scsi_unregister_host(Scsi_Host_Template *);
extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *);
extern struct Scsi_Host *scsi_host_hn_get(unsigned short); extern struct Scsi_Host *scsi_host_hn_get(unsigned short);
extern void scsi_host_put(struct Scsi_Host *); extern void scsi_host_put(struct Scsi_Host *);
extern void scsi_host_hn_init(char *); extern void scsi_host_init(void);
extern void scsi_host_hn_release(void);
/* /*
* host_busy inc/dec/test functions * host_busy inc/dec/test functions
......
...@@ -2550,10 +2550,7 @@ static void scsi_dump_status(int level) ...@@ -2550,10 +2550,7 @@ static void scsi_dump_status(int level)
} }
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
static char *scsihosts;
static char *scsi_dev_flags; static char *scsi_dev_flags;
MODULE_PARM(scsihosts, "s");
MODULE_PARM(scsi_dev_flags, "s"); MODULE_PARM(scsi_dev_flags, "s");
MODULE_PARM_DESC(scsi_dev_flags, MODULE_PARM_DESC(scsi_dev_flags,
"Given scsi_dev_flags=vendor:model:flags, add a black/white list" "Given scsi_dev_flags=vendor:model:flags, add a black/white list"
...@@ -2566,13 +2563,6 @@ MODULE_DESCRIPTION("SCSI core"); ...@@ -2566,13 +2563,6 @@ MODULE_DESCRIPTION("SCSI core");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifndef MODULE #ifndef MODULE
int __init scsi_setup(char *str)
{
scsihosts = str;
return 1;
}
__setup("scsihosts=", scsi_setup);
int __init setup_scsi_dev_flags(char *str) int __init setup_scsi_dev_flags(char *str)
{ {
...@@ -2598,7 +2588,6 @@ static int __init setup_scsi_default_dev_flags(char *str) ...@@ -2598,7 +2588,6 @@ static int __init setup_scsi_default_dev_flags(char *str)
__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); __setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
#endif #endif
static void *scsi_pool_alloc(int gfp_mask, void *data) static void *scsi_pool_alloc(int gfp_mask, void *data)
{ {
return kmem_cache_alloc(data, gfp_mask); return kmem_cache_alloc(data, gfp_mask);
...@@ -2733,8 +2722,7 @@ static int __init init_scsi(void) ...@@ -2733,8 +2722,7 @@ static int __init init_scsi(void)
scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL); scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
scsi_host_hn_init(scsihosts); scsi_host_init();
scsi_dev_info_list_init(scsi_dev_flags); scsi_dev_info_list_init(scsi_dev_flags);
bus_register(&scsi_driverfs_bus_type); bus_register(&scsi_driverfs_bus_type);
...@@ -2750,10 +2738,8 @@ static void __exit exit_scsi(void) ...@@ -2750,10 +2738,8 @@ static void __exit exit_scsi(void)
int i; int i;
devfs_unregister (scsi_devfs_handle); devfs_unregister (scsi_devfs_handle);
scsi_dev_info_list_delete(); scsi_dev_info_list_delete();
scsi_host_hn_release();
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
/* No, we're not here anymore. Don't show the /proc/scsi files. */ /* No, we're not here anymore. Don't show the /proc/scsi files. */
......
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