Commit 8e47b96b authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley

[PATCH] place host-related LDM code directly in hosts.c

This was in scsi_sysfs.c previously but given that it's not
sysfs-related and the whole scsi code is built around the driver
model now it's better to have it where it belongs.  Also allows
us to reduce the scsi_mod-wide globals.
parent 976c09eb
...@@ -40,6 +40,16 @@ ...@@ -40,6 +40,16 @@
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 void scsi_host_cls_release(struct class_device *class_dev)
{
put_device(&class_to_shost(class_dev)->shost_gendev);
}
static struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
/** /**
* scsi_host_cancel - cancel outstanding IO to this host * scsi_host_cancel - cancel outstanding IO to this host
* @shost: pointer to struct Scsi_Host * @shost: pointer to struct Scsi_Host
...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery) ...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/ **/
void scsi_remove_host(struct Scsi_Host *shost) void scsi_remove_host(struct Scsi_Host *shost)
{ {
unsigned long flags;
scsi_host_cancel(shost, 0); scsi_host_cancel(shost, 0);
scsi_proc_host_rm(shost); scsi_proc_host_rm(shost);
scsi_forget_host(shost); scsi_forget_host(shost);
scsi_sysfs_remove_host(shost);
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
/** /**
...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (!shost->can_queue) { if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name); sht->name);
error = -EINVAL; return -EINVAL;
} }
error = scsi_sysfs_add_host(shost, dev); if (!shost->shost_gendev.parent)
if (!error) shost->shost_gendev.parent = dev ? dev : &legacy_bus;
scsi_proc_host_add(shost);
error = device_add(&shost->shost_gendev);
if (error)
goto out;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto out_del_gendev;
get_device(&shost->shost_gendev);
error = scsi_sysfs_add_host(shost);
if (error)
goto out_del_classdev;
scsi_proc_host_add(shost);
return error;
out_del_classdev:
class_device_del(&shost->shost_classdev);
out_del_gendev:
device_del(&shost->shost_gendev);
out:
return error; return error;
} }
/** static void scsi_host_dev_release(struct device *dev)
* scsi_free_sdev - free a scsi hosts resources
* @shost: scsi host to free
**/
void scsi_free_shost(struct Scsi_Host *shost)
{ {
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
if (shost->ehandler) { if (shost->ehandler) {
DECLARE_COMPLETION(sem); DECLARE_COMPLETION(sem);
shost->eh_notify = &sem; shost->eh_notify = &sem;
...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost) ...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost)
scsi_proc_hostdir_rm(shost->hostt); scsi_proc_hostdir_rm(shost->hostt);
scsi_destroy_command_freelist(shost); scsi_destroy_command_freelist(shost);
put_device(parent);
kfree(shost); kfree(shost);
} }
...@@ -214,7 +258,18 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) ...@@ -214,7 +258,18 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (rval) if (rval)
goto fail; goto fail;
scsi_sysfs_init_host(shost); device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s",
shost->hostt->proc_name);
shost->shost_gendev.release = scsi_host_dev_release;
class_device_initialize(&shost->shost_classdev);
shost->shost_classdev.dev = &shost->shost_gendev;
shost->shost_classdev.class = &shost_class;
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->eh_notify = &complete; shost->eh_notify = &complete;
/* XXX(hch): handle error return */ /* XXX(hch): handle error return */
...@@ -299,3 +354,13 @@ void scsi_host_put(struct Scsi_Host *shost) ...@@ -299,3 +354,13 @@ void scsi_host_put(struct Scsi_Host *shost)
{ {
put_device(&shost->shost_gendev); put_device(&shost->shost_gendev);
} }
int scsi_init_hosts(void)
{
return class_register(&shost_class);
}
void scsi_exit_hosts(void)
{
class_unregister(&shost_class);
}
...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void) ...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void)
error = scsi_init_devinfo(); error = scsi_init_devinfo();
if (error) if (error)
goto cleanup_procfs; goto cleanup_procfs;
error = scsi_sysfs_register(); error = scsi_init_hosts();
if (error) if (error)
goto cleanup_devlist; goto cleanup_devlist;
error = scsi_sysfs_register();
if (error)
goto cleanup_hosts;
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
INIT_LIST_HEAD(&done_q[i]); INIT_LIST_HEAD(&done_q[i]);
...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void) ...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void)
printk(KERN_NOTICE "SCSI subsystem initialized\n"); printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0; return 0;
cleanup_hosts:
scsi_exit_hosts();
cleanup_devlist: cleanup_devlist:
scsi_exit_devinfo(); scsi_exit_devinfo();
cleanup_procfs: cleanup_procfs:
...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void) ...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void) static void __exit exit_scsi(void)
{ {
scsi_sysfs_unregister(); scsi_sysfs_unregister();
scsi_exit_hosts();
scsi_exit_devinfo(); scsi_exit_devinfo();
devfs_remove("scsi"); devfs_remove("scsi");
scsi_exit_procfs(); scsi_exit_procfs();
......
...@@ -51,6 +51,9 @@ struct scsi_target { ...@@ -51,6 +51,9 @@ struct scsi_target {
unsigned int starget_refcnt; unsigned int starget_refcnt;
}; };
/* hosts.c */
extern int scsi_init_hosts(void);
extern void scsi_exit_hosts(void);
/* scsi.c */ /* scsi.c */
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
...@@ -108,18 +111,14 @@ extern void scsi_exit_procfs(void); ...@@ -108,18 +111,14 @@ extern void scsi_exit_procfs(void);
/* scsi_scan.c */ /* scsi_scan.c */
extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *); extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_free_shost(struct Scsi_Host *);
extern void scsi_rescan_device(struct device *); extern void scsi_rescan_device(struct device *);
/* scsi_sysfs.c */ /* scsi_sysfs.c */
extern int scsi_device_register(struct scsi_device *); extern int scsi_device_register(struct scsi_device *);
extern void scsi_sysfs_init_host(struct Scsi_Host *); extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *);
extern void scsi_sysfs_remove_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void); extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void); extern void scsi_sysfs_unregister(void);
extern struct class shost_class;
extern struct class sdev_class; extern struct class sdev_class;
extern struct bus_type scsi_bus_type; extern struct bus_type scsi_bus_type;
......
...@@ -54,30 +54,6 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { ...@@ -54,30 +54,6 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
NULL NULL
}; };
static void scsi_host_cls_release(struct class_device *class_dev)
{
struct Scsi_Host *shost;
shost = class_to_shost(class_dev);
put_device(&shost->shost_gendev);
}
static void scsi_host_dev_release(struct device *dev)
{
struct Scsi_Host *shost;
struct device *parent;
parent = dev->parent;
shost = dev_to_shost(dev);
scsi_free_shost(shost);
put_device(parent);
}
struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
static void scsi_device_cls_release(struct class_device *class_dev) static void scsi_device_cls_release(struct class_device *class_dev)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
...@@ -119,27 +95,18 @@ int scsi_sysfs_register(void) ...@@ -119,27 +95,18 @@ int scsi_sysfs_register(void)
int error; int error;
error = bus_register(&scsi_bus_type); error = bus_register(&scsi_bus_type);
if (error) if (!error) {
return error; error = class_register(&sdev_class);
error = class_register(&shost_class); if (error)
if (error) bus_unregister(&scsi_bus_type);
goto bus_unregister; }
error = class_register(&sdev_class);
if (error)
goto class_unregister;
return 0;
class_unregister:
class_unregister(&shost_class);
bus_unregister:
bus_unregister(&scsi_bus_type);
return error; return error;
} }
void scsi_sysfs_unregister(void) void scsi_sysfs_unregister(void)
{ {
class_unregister(&sdev_class); class_unregister(&sdev_class);
class_unregister(&shost_class);
bus_unregister(&scsi_bus_type); bus_unregister(&scsi_bus_type);
} }
...@@ -403,22 +370,6 @@ int scsi_register_interface(struct class_interface *intf) ...@@ -403,22 +370,6 @@ int scsi_register_interface(struct class_interface *intf)
} }
void scsi_sysfs_init_host(struct Scsi_Host *shost)
{
device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s",
shost->hostt->proc_name);
shost->shost_gendev.release = scsi_host_dev_release;
class_device_initialize(&shost->shost_classdev);
shost->shost_classdev.dev = &shost->shost_gendev;
shost->shost_classdev.class = &shost_class;
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
}
static struct class_device_attribute *class_attr_overridden( static struct class_device_attribute *class_attr_overridden(
struct class_device_attribute **attrs, struct class_device_attribute **attrs,
struct class_device_attribute *attr) struct class_device_attribute *attr)
...@@ -461,31 +412,16 @@ static int class_attr_add(struct class_device *classdev, ...@@ -461,31 +412,16 @@ static int class_attr_add(struct class_device *classdev,
* @shost: scsi host struct to add to subsystem * @shost: scsi host struct to add to subsystem
* @dev: parent struct device pointer * @dev: parent struct device pointer
**/ **/
int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) int scsi_sysfs_add_host(struct Scsi_Host *shost)
{ {
int error, i; int error, i;
if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &legacy_bus;
error = device_add(&shost->shost_gendev);
if (error)
return error;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto clean_device;
get_device(&shost->shost_gendev);
if (shost->hostt->shost_attrs) { if (shost->hostt->shost_attrs) {
for (i = 0; shost->hostt->shost_attrs[i]; i++) { for (i = 0; shost->hostt->shost_attrs[i]; i++) {
error = class_attr_add(&shost->shost_classdev, error = class_attr_add(&shost->shost_classdev,
shost->hostt->shost_attrs[i]); shost->hostt->shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
...@@ -495,31 +431,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -495,31 +431,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
error = class_device_create_file(&shost->shost_classdev, error = class_device_create_file(&shost->shost_classdev,
scsi_sysfs_shost_attrs[i]); scsi_sysfs_shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
return error; return 0;
clean_class:
class_device_del(&shost->shost_classdev);
clean_device:
device_del(&shost->shost_gendev);
return error;
}
/**
* scsi_sysfs_remove_host - remove scsi host from subsystem
* @shost: scsi host to remove from subsystem
**/
void scsi_sysfs_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
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