Commit 154173a0 authored by Mike Anderson's avatar Mike Anderson Committed by James Bottomley

[PATCH] scsi host sysfs support again [4/4]

-andmike
--
Michael Anderson
andmike@us.ibm.com


DESC
Change scsi sysfs to support scsi host class device and call release
functions when ref count goes to zero.
EDESC


 drivers/scsi/scsi_sysfs.c |  111 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 96 insertions(+), 15 deletions(-)
parent 19e4ff96
......@@ -22,9 +22,9 @@
*/
#define shost_show_function(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf) \
show_##field (struct class_device *class_dev, char *buf) \
{ \
struct Scsi_Host *shost = to_scsi_host(dev); \
struct Scsi_Host *shost = class_to_shost(class_dev); \
return snprintf (buf, 20, format_string, shost->field); \
}
......@@ -34,7 +34,7 @@ show_##field (struct device *dev, char *buf) \
*/
#define shost_rd_attr(field, format_string) \
shost_show_function(field, format_string) \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
/*
* Create the actual show/store functions and data structures.
......@@ -45,16 +45,16 @@ shost_rd_attr(cmd_per_lun, "%hd\n");
shost_rd_attr(sg_tablesize, "%hu\n");
shost_rd_attr(unchecked_isa_dma, "%d\n");
static struct device_attribute *const shost_attrs[] = {
&dev_attr_unique_id,
&dev_attr_host_busy,
&dev_attr_cmd_per_lun,
&dev_attr_sg_tablesize,
&dev_attr_unchecked_isa_dma,
static struct class_device_attribute *const shost_attrs[] = {
&class_device_attr_unique_id,
&class_device_attr_host_busy,
&class_device_attr_cmd_per_lun,
&class_device_attr_sg_tablesize,
&class_device_attr_unchecked_isa_dma,
};
struct class shost_class = {
.name = "scsi-host",
.name = "scsi_host",
};
/**
......@@ -91,10 +91,16 @@ static struct bus_type scsi_bus_type = {
int scsi_sysfs_register(void)
{
bus_register(&scsi_bus_type);
class_register(&shost_class);
int error;
return 0;
error = bus_register(&scsi_bus_type);
if (error)
return error;
error = class_register(&shost_class);
if (error)
return error;
return error;
}
void scsi_sysfs_unregister(void)
......@@ -250,6 +256,16 @@ static struct device_attribute * const sdev_attrs[] = {
&dev_attr_rescan,
};
static void scsi_device_release(struct device *dev)
{
struct scsi_device *sdev;
sdev = to_scsi_device(dev);
if (!sdev)
return;
scsi_free_sdev(sdev);
}
/**
* scsi_device_register - register a scsi device with the scsi bus
* @sdev: scsi_device to register
......@@ -263,8 +279,9 @@ int scsi_device_register(struct scsi_device *sdev)
sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
sdev->sdev_driverfs_dev.parent = sdev->host->host_gendev;
sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev;
sdev->sdev_driverfs_dev.bus = &scsi_bus_type;
sdev->sdev_driverfs_dev.release = scsi_device_release;
error = device_register(&sdev->sdev_driverfs_dev);
if (error)
......@@ -292,3 +309,67 @@ void scsi_device_unregister(struct scsi_device *sdev)
device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]);
device_unregister(&sdev->sdev_driverfs_dev);
}
static void scsi_host_release(struct device *dev)
{
struct Scsi_Host *shost;
shost = dev_to_shost(dev);
if (!shost)
return;
shost->hostt->release(shost);
}
/**
* scsi_sysfs_add_host - add scsi host to subsystem
* @shost: scsi host struct to add to subsystem
* @dev: parent struct device pointer
**/
int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
{
int i, error;
sprintf(shost->host_gendev.bus_id,"host%d",
shost->host_no);
if (!shost->host_gendev.parent)
shost->host_gendev.parent = (dev) ? dev : &legacy_bus;
shost->host_gendev.release = scsi_host_release;
error = device_register(&shost->host_gendev);
if (error)
return error;
shost->class_dev.dev = &shost->host_gendev;
shost->class_dev.class = &shost_class;
snprintf(shost->class_dev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
error = class_device_register(&shost->class_dev);
if (error)
goto clean_device;
for (i = 0; !error && i < ARRAY_SIZE(shost_attrs); i++)
error = class_device_create_file(&shost->class_dev,
shost_attrs[i]);
if (error)
goto clean_class;
return error;
clean_class:
class_device_unregister(&shost->class_dev);
clean_device:
device_unregister(&shost->host_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)
{
class_device_unregister(&shost->class_dev);
device_unregister(&shost->host_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