Commit a2ad031d authored by James Bottomley's avatar James Bottomley

Merge hch/andmike changes

parents f6842023 154173a0
...@@ -3079,7 +3079,6 @@ static struct ecard_driver acornscsi_driver = { ...@@ -3079,7 +3079,6 @@ static struct ecard_driver acornscsi_driver = {
.remove = __devexit_p(acornscsi_remove), .remove = __devexit_p(acornscsi_remove),
.id_table = acornscsi_cids, .id_table = acornscsi_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "acornscsi", .name = "acornscsi",
}, },
}; };
......
...@@ -397,7 +397,6 @@ static struct ecard_driver arxescsi_driver = { ...@@ -397,7 +397,6 @@ static struct ecard_driver arxescsi_driver = {
.remove = __devexit_p(arxescsi_remove), .remove = __devexit_p(arxescsi_remove),
.id_table = arxescsi_cids, .id_table = arxescsi_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "arxescsi", .name = "arxescsi",
}, },
}; };
......
...@@ -334,7 +334,6 @@ static struct ecard_driver cumanascsi1_driver = { ...@@ -334,7 +334,6 @@ static struct ecard_driver cumanascsi1_driver = {
.remove = __devexit_p(cumanascsi1_remove), .remove = __devexit_p(cumanascsi1_remove),
.id_table = cumanascsi1_cids, .id_table = cumanascsi1_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "cumanascsi1", .name = "cumanascsi1",
}, },
}; };
......
...@@ -552,7 +552,6 @@ static struct ecard_driver cumanascsi2_driver = { ...@@ -552,7 +552,6 @@ static struct ecard_driver cumanascsi2_driver = {
.remove = __devexit_p(cumanascsi2_remove), .remove = __devexit_p(cumanascsi2_remove),
.id_table = cumanascsi2_cids, .id_table = cumanascsi2_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "cumanascsi2", .name = "cumanascsi2",
}, },
}; };
......
...@@ -660,7 +660,6 @@ static struct ecard_driver eesoxscsi_driver = { ...@@ -660,7 +660,6 @@ static struct ecard_driver eesoxscsi_driver = {
.remove = __devexit_p(eesoxscsi_remove), .remove = __devexit_p(eesoxscsi_remove),
.id_table = eesoxscsi_cids, .id_table = eesoxscsi_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "eesoxscsi", .name = "eesoxscsi",
}, },
}; };
......
...@@ -192,7 +192,6 @@ static struct ecard_driver oakscsi_driver = { ...@@ -192,7 +192,6 @@ static struct ecard_driver oakscsi_driver = {
.remove = __devexit_p(oakscsi_remove), .remove = __devexit_p(oakscsi_remove),
.id_table = oakscsi_cids, .id_table = oakscsi_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "oakscsi", .name = "oakscsi",
}, },
}; };
......
...@@ -475,7 +475,6 @@ static struct ecard_driver powertecscsi_driver = { ...@@ -475,7 +475,6 @@ static struct ecard_driver powertecscsi_driver = {
.remove = __devexit_p(powertecscsi_remove), .remove = __devexit_p(powertecscsi_remove),
.id_table = powertecscsi_cids, .id_table = powertecscsi_cids,
.drv = { .drv = {
.devclass = &shost_devclass,
.name = "powertecscsi", .name = "powertecscsi",
}, },
}; };
......
...@@ -193,16 +193,6 @@ static int scsi_host_legacy_release(struct Scsi_Host *shost) ...@@ -193,16 +193,6 @@ static int scsi_host_legacy_release(struct Scsi_Host *shost)
return 0; return 0;
} }
static int scsi_remove_legacy_host(struct Scsi_Host *shost)
{
int error;
error = scsi_remove_host(shost);
if (!error)
(*shost->hostt->release)(shost);
return 0;
}
static int scsi_check_device_busy(struct scsi_device *sdev) static int scsi_check_device_busy(struct scsi_device *sdev)
{ {
struct Scsi_Host *shost = sdev->host; struct Scsi_Host *shost = sdev->host;
...@@ -268,11 +258,8 @@ int scsi_remove_host(struct Scsi_Host *shost) ...@@ -268,11 +258,8 @@ int scsi_remove_host(struct Scsi_Host *shost)
list_for_each_entry(sdev, &shost->my_devices, siblings) list_for_each_entry(sdev, &shost->my_devices, siblings)
sdev->online = FALSE; sdev->online = FALSE;
list_for_each_entry(sdev, &shost->my_devices, siblings)
if (scsi_check_device_busy(sdev))
return 1;
scsi_forget_host(shost); scsi_forget_host(shost);
scsi_sysfs_remove_host(shost);
return 0; return 0;
} }
...@@ -293,9 +280,9 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -293,9 +280,9 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
printk(KERN_INFO "scsi%d : %s\n", shost->host_no, printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
sht->info ? sht->info(shost) : sht->name); sht->info ? sht->info(shost) : sht->name);
if (dev) { error = scsi_sysfs_add_host(shost, dev);
shost->host_gendev = dev; if (error)
} return error;
scsi_scan_host(shost); scsi_scan_host(shost);
...@@ -531,7 +518,7 @@ int scsi_register_host(Scsi_Host_Template *shost_tp) ...@@ -531,7 +518,7 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
**/ **/
int scsi_unregister_host(Scsi_Host_Template *shost_tp) int scsi_unregister_host(Scsi_Host_Template *shost_tp)
{ {
scsi_tp_for_each_host(shost_tp, scsi_remove_legacy_host); scsi_tp_for_each_host(shost_tp, scsi_remove_host);
return 0; return 0;
} }
......
...@@ -482,9 +482,10 @@ struct Scsi_Host ...@@ -482,9 +482,10 @@ struct Scsi_Host
unsigned int max_host_blocked; unsigned int max_host_blocked;
/* /*
* Support for driverfs filesystem * Support for sysfs
*/ */
struct device *host_gendev; struct device host_gendev;
struct class_device class_dev;
/* /*
* We should ensure that this is aligned, both for better performance * We should ensure that this is aligned, both for better performance
...@@ -495,7 +496,10 @@ struct Scsi_Host ...@@ -495,7 +496,10 @@ struct Scsi_Host
__attribute__ ((aligned (sizeof(unsigned long)))); __attribute__ ((aligned (sizeof(unsigned long))));
}; };
#define to_scsi_host(d) d->driver_data /* Major logical breakage, but we compile again... */ #define dev_to_shost(d) \
container_of(d, struct Scsi_Host, host_gendev)
#define class_to_shost(d) \
container_of(d, struct Scsi_Host, class_dev)
/* /*
* These two functions are used to allocate and free a pseudo device * These two functions are used to allocate and free a pseudo device
...@@ -519,12 +523,12 @@ static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) ...@@ -519,12 +523,12 @@ static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
static inline void scsi_set_device(struct Scsi_Host *shost, static inline void scsi_set_device(struct Scsi_Host *shost,
struct device *dev) struct device *dev)
{ {
shost->host_gendev = dev; shost->host_gendev.parent = dev;
} }
static inline struct device *scsi_get_device(struct Scsi_Host *shost) static inline struct device *scsi_get_device(struct Scsi_Host *shost)
{ {
return shost->host_gendev; return shost->host_gendev.parent;
} }
struct Scsi_Device_Template struct Scsi_Device_Template
...@@ -591,6 +595,10 @@ static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost, ...@@ -591,6 +595,10 @@ static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost,
*/ */
extern int scsi_upper_driver_register(struct Scsi_Device_Template *); extern int scsi_upper_driver_register(struct Scsi_Device_Template *);
extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *); extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *);
extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *);
extern void scsi_sysfs_remove_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *);
extern struct class shost_class; extern struct class shost_class;
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
#include "scsi_logging.h" #include "scsi_logging.h"
#include "scsi_debug.h" #include "scsi_debug.h"
static const char * scsi_debug_version_str = "Version: 1.69 (20030329)"; static const char * scsi_debug_version_str = "Version: 1.70 (20030416)";
/* Additional Sense Code (ASC) used */ /* Additional Sense Code (ASC) used */
#define NO_ADDED_SENSE 0x0 #define NO_ADDED_SENSE 0x0
...@@ -145,10 +145,13 @@ struct sdebug_dev_info { ...@@ -145,10 +145,13 @@ struct sdebug_dev_info {
struct sdebug_host_info { struct sdebug_host_info {
struct list_head host_list; struct list_head host_list;
struct Scsi_Host *shost; struct Scsi_Host *shost;
struct device *dev; struct device dev;
struct list_head dev_info_list; struct list_head dev_info_list;
}; };
#define to_sdebug_host(d) \
container_of(d, struct sdebug_host_info, dev)
static LIST_HEAD(sdebug_host_list); static LIST_HEAD(sdebug_host_list);
static spinlock_t sdebug_host_list_lock = SPIN_LOCK_UNLOCKED; static spinlock_t sdebug_host_list_lock = SPIN_LOCK_UNLOCKED;
...@@ -249,22 +252,6 @@ static struct bus_type pseudo_lld_bus; ...@@ -249,22 +252,6 @@ static struct bus_type pseudo_lld_bus;
static int scsi_debug_register_driver(struct device_driver *); static int scsi_debug_register_driver(struct device_driver *);
static int scsi_debug_unregister_driver(struct device_driver *); static int scsi_debug_unregister_driver(struct device_driver *);
static struct sdebug_host_info *
sdebug_shost_to_host_info(struct Scsi_Host *shost)
{
struct sdebug_host_info * sdbg_host, * found = NULL;
spin_lock(&sdebug_host_list_lock);
list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
if (sdbg_host->shost == shost) {
found = sdbg_host;
break;
}
}
spin_unlock(&sdebug_host_list_lock);
return found;
}
static unsigned char * scatg2virt(const struct scatterlist * sclp) static unsigned char * scatg2virt(const struct scatterlist * sclp)
{ {
if (NULL == sclp) if (NULL == sclp)
...@@ -668,6 +655,15 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) ...@@ -668,6 +655,15 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
return sizeof(ctrl_m_pg); return sizeof(ctrl_m_pg);
} }
static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
{ /* Informational Exceptions control mode page for mode_sense */
unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
0, 0, 0x0, 0x0};
memcpy(p, iec_m_pg, sizeof(iec_m_pg));
if (1 == pcontrol)
memset(p + 2, 0, sizeof(iec_m_pg) - 2);
return sizeof(iec_m_pg);
}
#define SDEBUG_MAX_MSENSE_SZ 256 #define SDEBUG_MAX_MSENSE_SZ 256
...@@ -734,12 +730,17 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -734,12 +730,17 @@ static int resp_mode_sense(unsigned char * cmd, int target,
len = resp_ctrl_m_pg(ap, pcontrol, target); len = resp_ctrl_m_pg(ap, pcontrol, target);
offset += len; offset += len;
break; break;
case 0x1c: /* Informational Exceptions Mode page, all devices */
len = resp_iec_m_pg(ap, pcontrol, target);
offset += len;
break;
case 0x3f: /* Read all Mode pages */ case 0x3f: /* Read all Mode pages */
len = resp_err_recov_pg(ap, pcontrol, target); len = resp_err_recov_pg(ap, pcontrol, target);
len += resp_disconnect_pg(ap + len, pcontrol, target); len += resp_disconnect_pg(ap + len, pcontrol, target);
len += resp_format_pg(ap + len, pcontrol, target); len += resp_format_pg(ap + len, pcontrol, target);
len += resp_caching_pg(ap + len, pcontrol, target); len += resp_caching_pg(ap + len, pcontrol, target);
len += resp_ctrl_m_pg(ap + len, pcontrol, target); len += resp_ctrl_m_pg(ap + len, pcontrol, target);
len += resp_iec_m_pg(ap + len, pcontrol, target);
offset += len; offset += len;
break; break;
default: default:
...@@ -963,9 +964,9 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) ...@@ -963,9 +964,9 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
if (devip) if (devip)
return devip; return devip;
sdbg_host = sdebug_shost_to_host_info(sdev->host); sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata;
if(! sdbg_host) { if(! sdbg_host) {
printk(KERN_ERR "Unable to locate host info\n"); printk(KERN_ERR "Host info NULL\n");
return NULL; return NULL;
} }
list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
...@@ -1065,7 +1066,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) ...@@ -1065,7 +1066,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
printk(KERN_INFO "scsi_debug: bus_reset\n"); printk(KERN_INFO "scsi_debug: bus_reset\n");
++num_bus_resets; ++num_bus_resets;
if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
sdbg_host = sdebug_shost_to_host_info(hp); sdbg_host = *(struct sdebug_host_info **) hp->hostdata;
if (sdbg_host) { if (sdbg_host) {
list_for_each_entry(dev_info, list_for_each_entry(dev_info,
&sdbg_host->dev_info_list, &sdbg_host->dev_info_list,
...@@ -1546,8 +1547,11 @@ static int __init scsi_debug_init(void) ...@@ -1546,8 +1547,11 @@ static int __init scsi_debug_init(void)
static void __exit scsi_debug_exit(void) static void __exit scsi_debug_exit(void)
{ {
/* free up adapters here ?? */ int k = scsi_debug_add_host;
stop_all_queued(); stop_all_queued();
for (; k; k--)
sdebug_remove_adapter();
do_remove_driverfs_files(); do_remove_driverfs_files();
scsi_debug_unregister_driver(&sdebug_driverfs_driver); scsi_debug_unregister_driver(&sdebug_driverfs_driver);
bus_unregister(&pseudo_lld_bus); bus_unregister(&pseudo_lld_bus);
...@@ -1591,35 +1595,74 @@ static int scsi_debug_unregister_driver(struct device_driver *dev_driver) ...@@ -1591,35 +1595,74 @@ static int scsi_debug_unregister_driver(struct device_driver *dev_driver)
static void sdebug_release_adapter(struct device * dev) static void sdebug_release_adapter(struct device * dev)
{ {
kfree(dev); struct sdebug_host_info *sdbg_host;
sdbg_host = to_sdebug_host(dev);
kfree(sdbg_host);
} }
static int sdebug_add_adapter() static int sdebug_add_adapter()
{ {
struct device * dev; int k, devs_per_host;
int error; int error = 0;
struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo;
struct list_head *lh, *lh_sf;
dev = kmalloc(sizeof(*dev),GFP_KERNEL); sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL);
if (NULL == dev) {
if (NULL == sdbg_host) {
printk(KERN_ERR "%s: out of memory at line %d\n", printk(KERN_ERR "%s: out of memory at line %d\n",
__FUNCTION__, __LINE__); __FUNCTION__, __LINE__);
return -ENOMEM; return -ENOMEM;
} }
memset(dev, 0, sizeof(*dev));
dev->bus = &pseudo_lld_bus; memset(sdbg_host, 0, sizeof(*sdbg_host));
dev->parent = &pseudo_primary; INIT_LIST_HEAD(&sdbg_host->dev_info_list);
dev->release = &sdebug_release_adapter;
sprintf(dev->name, "scsi debug adapter");
sprintf(dev->bus_id, "adapter%d", scsi_debug_add_host);
error = device_register(dev); devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
for (k = 0; k < devs_per_host; k++) {
sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
if (NULL == sdbg_devinfo) {
printk(KERN_ERR "%s: out of memory at line %d\n",
__FUNCTION__, __LINE__);
error = -ENOMEM;
goto clean1;
}
memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo));
sdbg_devinfo->sdbg_host = sdbg_host;
list_add_tail(&sdbg_devinfo->dev_list,
&sdbg_host->dev_info_list);
}
spin_lock(&sdebug_host_list_lock);
list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
spin_unlock(&sdebug_host_list_lock);
sdbg_host->dev.bus = &pseudo_lld_bus;
sdbg_host->dev.parent = &pseudo_primary;
sdbg_host->dev.release = &sdebug_release_adapter;
sprintf(sdbg_host->dev.name, "scsi debug adapter");
sprintf(sdbg_host->dev.bus_id, "adapter%d", scsi_debug_add_host);
error = device_register(&sdbg_host->dev);
if (error) if (error)
kfree(dev); goto clean2;
else
++scsi_debug_add_host; ++scsi_debug_add_host;
return error;
clean2:
list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
dev_list);
list_del(&sdbg_devinfo->dev_list);
kfree(sdbg_devinfo);
}
clean1:
kfree(sdbg_host);
return error; return error;
} }
...@@ -1628,51 +1671,29 @@ static void sdebug_remove_adapter() ...@@ -1628,51 +1671,29 @@ static void sdebug_remove_adapter()
struct sdebug_host_info * sdbg_host = NULL; struct sdebug_host_info * sdbg_host = NULL;
spin_lock(&sdebug_host_list_lock); spin_lock(&sdebug_host_list_lock);
if (!list_empty(&sdebug_host_list)) if (!list_empty(&sdebug_host_list)) {
sdbg_host = list_entry(sdebug_host_list.prev, sdbg_host = list_entry(sdebug_host_list.prev,
struct sdebug_host_info, host_list); struct sdebug_host_info, host_list);
list_del(&sdbg_host->host_list);
}
spin_unlock(&sdebug_host_list_lock); spin_unlock(&sdebug_host_list_lock);
device_unregister(sdbg_host->dev); if (!sdbg_host)
return;
device_unregister(&sdbg_host->dev);
--scsi_debug_add_host; --scsi_debug_add_host;
} }
static int sdebug_driver_probe(struct device * dev) static int sdebug_driver_probe(struct device * dev)
{ {
int k, devs_per_host;
int error = 0; int error = 0;
struct sdebug_host_info *sdbg_host; struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo;
struct list_head *lh, *lh_sf;
struct Scsi_Host *hpnt; struct Scsi_Host *hpnt;
sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); sdbg_host = to_sdebug_host(dev);
if (NULL == sdbg_host) {
printk(KERN_ERR "%s: out of memory at line %d\n",
__FUNCTION__, __LINE__);
return -ENOMEM;
}
memset(sdbg_host, 0, sizeof(*sdbg_host));
INIT_LIST_HEAD(&sdbg_host->dev_info_list);
devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
for (k = 0; k < devs_per_host; k++) {
sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
if (NULL == sdbg_devinfo) {
printk(KERN_ERR "%s: out of memory at line %d\n",
__FUNCTION__, __LINE__);
error = -ENOMEM;
}
memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo));
sdbg_devinfo->sdbg_host = sdbg_host;
list_add_tail(&sdbg_devinfo->dev_list,
&sdbg_host->dev_info_list);
}
list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
hpnt = scsi_register(&sdebug_driver_template, 0); hpnt = scsi_register(&sdebug_driver_template, sizeof(sdbg_host));
if (NULL == hpnt) { if (NULL == hpnt) {
printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__);
error = -ENODEV; error = -ENODEV;
...@@ -1680,14 +1701,14 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1680,14 +1701,14 @@ static int sdebug_driver_probe(struct device * dev)
} }
sdbg_host->shost = hpnt; sdbg_host->shost = hpnt;
sdbg_host->dev = dev; *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
hpnt->max_id = scsi_debug_num_tgts + 1; hpnt->max_id = scsi_debug_num_tgts + 1;
else else
hpnt->max_id = scsi_debug_num_tgts; hpnt->max_id = scsi_debug_num_tgts;
hpnt->max_lun = scsi_debug_max_luns; hpnt->max_lun = scsi_debug_max_luns;
error = scsi_add_host(hpnt, sdbg_host->dev); error = scsi_add_host(hpnt, &sdbg_host->dev);
if (error) { if (error) {
printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__);
error = -ENODEV; error = -ENODEV;
...@@ -1700,48 +1721,25 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1700,48 +1721,25 @@ static int sdebug_driver_probe(struct device * dev)
clean2: clean2:
scsi_unregister(hpnt); scsi_unregister(hpnt);
clean1: clean1:
list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
dev_list);
list_del(&sdbg_devinfo->dev_list);
kfree(sdbg_devinfo);
}
kfree(sdbg_host); kfree(sdbg_host);
return error; return error;
} }
static int sdebug_driver_remove(struct device * dev) static int scsi_debug_release(struct Scsi_Host * shost)
{ {
struct list_head *lh, *lh_sf; struct list_head *lh, *lh_sf;
struct sdebug_dev_info *sdbg_devinfo; struct sdebug_dev_info *sdbg_devinfo;
struct sdebug_host_info *sdbg_host, *found = NULL; struct sdebug_host_info *sdbg_host;
spin_lock(&sdebug_host_list_lock);
list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
if (sdbg_host->dev == dev) {
list_del(&sdbg_host->host_list);
found = sdbg_host;
break;
}
}
spin_unlock(&sdebug_host_list_lock);
if (!found) {
printk(KERN_ERR "%s: sdebug_host_info not found\n",
__FUNCTION__);
return -ENODEV;
}
sdbg_host = *(struct sdebug_host_info **)shost->hostdata;
scsi_unregister(shost);
if (scsi_remove_host(sdbg_host->shost)) { if (!sdbg_host) {
printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__); printk(KERN_ERR "Unable to locate host info\n");
return -EBUSY; return 0;
} }
scsi_unregister(sdbg_host->shost);
list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
dev_list); dev_list);
...@@ -1749,7 +1747,20 @@ static int sdebug_driver_remove(struct device * dev) ...@@ -1749,7 +1747,20 @@ static int sdebug_driver_remove(struct device * dev)
kfree(sdbg_devinfo); kfree(sdbg_devinfo);
} }
kfree(sdbg_host); return 0;
}
static int sdebug_driver_remove(struct device * dev)
{
struct sdebug_host_info *sdbg_host;
sdbg_host = to_sdebug_host(dev);
if (sdbg_host && scsi_remove_host(sdbg_host->shost)) {
printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__);
return -EBUSY;
}
return 0; return 0;
} }
...@@ -16,6 +16,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd *); ...@@ -16,6 +16,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd *);
static int scsi_debug_host_reset(struct scsi_cmnd *); static int scsi_debug_host_reset(struct scsi_cmnd *);
static int scsi_debug_proc_info(char *, char **, off_t, int, int, int); static int scsi_debug_proc_info(char *, char **, off_t, int, int, int);
static const char * scsi_debug_info(struct Scsi_Host *); static const char * scsi_debug_info(struct Scsi_Host *);
static int scsi_debug_release(struct Scsi_Host *);
/* /*
* This driver is written for the lk 2.5 series * This driver is written for the lk 2.5 series
......
...@@ -480,7 +480,7 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, ...@@ -480,7 +480,7 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
* Undo the actions in scsi_alloc_sdev, including removing @sdev from * Undo the actions in scsi_alloc_sdev, including removing @sdev from
* the list, and freeing @sdev. * the list, and freeing @sdev.
**/ **/
static void scsi_free_sdev(struct scsi_device *sdev) void scsi_free_sdev(struct scsi_device *sdev)
{ {
unsigned long flags; unsigned long flags;
...@@ -1273,8 +1273,6 @@ int scsi_remove_device(struct scsi_device *sdev) ...@@ -1273,8 +1273,6 @@ int scsi_remove_device(struct scsi_device *sdev)
return -EINVAL; return -EINVAL;
scsi_device_unregister(sdev); scsi_device_unregister(sdev);
scsi_free_sdev(sdev);
return 0; return 0;
} }
......
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
*/ */
#define shost_show_function(field, format_string) \ #define shost_show_function(field, format_string) \
static ssize_t \ 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); \ return snprintf (buf, 20, format_string, shost->field); \
} }
...@@ -34,7 +34,7 @@ show_##field (struct device *dev, char *buf) \ ...@@ -34,7 +34,7 @@ show_##field (struct device *dev, char *buf) \
*/ */
#define shost_rd_attr(field, format_string) \ #define shost_rd_attr(field, format_string) \
shost_show_function(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. * Create the actual show/store functions and data structures.
...@@ -45,39 +45,16 @@ shost_rd_attr(cmd_per_lun, "%hd\n"); ...@@ -45,39 +45,16 @@ shost_rd_attr(cmd_per_lun, "%hd\n");
shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(sg_tablesize, "%hu\n");
shost_rd_attr(unchecked_isa_dma, "%d\n"); shost_rd_attr(unchecked_isa_dma, "%d\n");
static struct device_attribute *const shost_attrs[] = { static struct class_device_attribute *const shost_attrs[] = {
&dev_attr_unique_id, &class_device_attr_unique_id,
&dev_attr_host_busy, &class_device_attr_host_busy,
&dev_attr_cmd_per_lun, &class_device_attr_cmd_per_lun,
&dev_attr_sg_tablesize, &class_device_attr_sg_tablesize,
&dev_attr_unchecked_isa_dma, &class_device_attr_unchecked_isa_dma,
}; };
/**
* scsi_host_class_name_show - copy out the SCSI host name
* @dev: device to check
* @page: copy data into this area
* @count: number of bytes to copy
* @off: start at this offset in page
* Return:
* number of bytes written into page.
**/
static ssize_t scsi_host_class_name_show(struct device *dev, char *page)
{
struct Scsi_Host *shost;
shost = to_scsi_host(dev);
if (!shost)
return 0;
return snprintf(page, 20, "scsi%d\n", shost->host_no);
}
DEVICE_ATTR(class_name, S_IRUGO, scsi_host_class_name_show, NULL);
struct class shost_class = { struct class shost_class = {
.name = "scsi-host", .name = "scsi_host",
}; };
/** /**
...@@ -114,10 +91,16 @@ static struct bus_type scsi_bus_type = { ...@@ -114,10 +91,16 @@ static struct bus_type scsi_bus_type = {
int scsi_sysfs_register(void) int scsi_sysfs_register(void)
{ {
bus_register(&scsi_bus_type); int error;
class_register(&shost_class);
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) void scsi_sysfs_unregister(void)
...@@ -273,6 +256,16 @@ static struct device_attribute * const sdev_attrs[] = { ...@@ -273,6 +256,16 @@ static struct device_attribute * const sdev_attrs[] = {
&dev_attr_rescan, &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 * scsi_device_register - register a scsi device with the scsi bus
* @sdev: scsi_device to register * @sdev: scsi_device to register
...@@ -286,8 +279,9 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -286,8 +279,9 @@ int scsi_device_register(struct scsi_device *sdev)
sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d", sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); 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.bus = &scsi_bus_type;
sdev->sdev_driverfs_dev.release = scsi_device_release;
error = device_register(&sdev->sdev_driverfs_dev); error = device_register(&sdev->sdev_driverfs_dev);
if (error) if (error)
...@@ -315,3 +309,67 @@ void scsi_device_unregister(struct scsi_device *sdev) ...@@ -315,3 +309,67 @@ void scsi_device_unregister(struct scsi_device *sdev)
device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]); device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]);
device_unregister(&sdev->sdev_driverfs_dev); 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