Commit 765cbc6d authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley

[SCSI] scsi_dh: Implement common device table handling

Instead of having each and every driver implement its own
device table scanning code we should rather implement a common
routine and scan the device tables there.
This allows us also to implement a general notifier chain
callback for all device handler instead for one per handler.

[sekharan: Fix rejections caused by conflicting bug fix]
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarChandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 6d49f63b
...@@ -33,7 +33,7 @@ static struct scsi_device_handler *get_device_handler(const char *name) ...@@ -33,7 +33,7 @@ static struct scsi_device_handler *get_device_handler(const char *name)
spin_lock(&list_lock); spin_lock(&list_lock);
list_for_each_entry(tmp, &scsi_dh_list, list) { list_for_each_entry(tmp, &scsi_dh_list, list) {
if (!strcmp(tmp->name, name)) { if (!strncmp(tmp->name, name, strlen(tmp->name))) {
found = tmp; found = tmp;
break; break;
} }
...@@ -42,50 +42,172 @@ static struct scsi_device_handler *get_device_handler(const char *name) ...@@ -42,50 +42,172 @@ static struct scsi_device_handler *get_device_handler(const char *name)
return found; return found;
} }
static int scsi_dh_notifier_add(struct device *dev, void *data) static int device_handler_match(struct scsi_device_handler *tmp,
struct scsi_device *sdev)
{ {
struct scsi_device_handler *scsi_dh = data; int i;
for(i = 0; tmp->devlist[i].vendor; i++) {
if (!strncmp(sdev->vendor, tmp->devlist[i].vendor,
strlen(tmp->devlist[i].vendor)) &&
!strncmp(sdev->model, tmp->devlist[i].model,
strlen(tmp->devlist[i].model))) {
return 1;
}
}
scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_ADD_DEVICE, dev);
return 0; return 0;
} }
/* /*
* scsi_register_device_handler - register a device handler personality * scsi_dh_handler_attach - Attach a device handler to a device
* module. * @sdev - SCSI device the device handler should attach to
* @scsi_dh - device handler to be registered. * @scsi_dh - The device handler to attach
*/
static int scsi_dh_handler_attach(struct scsi_device *sdev,
struct scsi_device_handler *scsi_dh)
{
int err = 0;
if (sdev->scsi_dh_data) {
if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
err = -EBUSY;
} else if (scsi_dh->attach)
err = scsi_dh->attach(sdev);
return err;
}
/*
* scsi_dh_handler_detach - Detach a device handler from a device
* @sdev - SCSI device the device handler should be detached from
* @scsi_dh - Device handler to be detached
* *
* Returns 0 on success, -EBUSY if handler already registered. * Detach from a device handler. If a device handler is specified,
* only detach if the currently attached handler is equal to it.
*/ */
int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) static void scsi_dh_handler_detach(struct scsi_device *sdev,
struct scsi_device_handler *scsi_dh)
{ {
int ret = -EBUSY; if (!sdev->scsi_dh_data)
struct scsi_device_handler *tmp; return;
tmp = get_device_handler(scsi_dh->name); if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
if (tmp) return;
goto done;
ret = bus_register_notifier(&scsi_bus_type, &scsi_dh->nb); if (!scsi_dh)
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (scsi_dh && scsi_dh->detach)
scsi_dh->detach(sdev);
}
/*
* scsi_dh_notifier - notifier chain callback
*/
static int scsi_dh_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
struct scsi_device *sdev;
int err = 0;
struct scsi_device_handler *tmp, *devinfo = NULL;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
spin_lock(&list_lock); spin_lock(&list_lock);
list_add(&scsi_dh->list, &scsi_dh_list); list_for_each_entry(tmp, &scsi_dh_list, list) {
if (device_handler_match(tmp, sdev)) {
devinfo = tmp;
break;
}
}
spin_unlock(&list_lock); spin_unlock(&list_lock);
done: if (!devinfo)
return ret; goto out;
if (action == BUS_NOTIFY_ADD_DEVICE) {
err = scsi_dh_handler_attach(sdev, devinfo);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
scsi_dh_handler_detach(sdev, NULL);
}
out:
return err;
} }
EXPORT_SYMBOL_GPL(scsi_register_device_handler);
/*
* scsi_dh_notifier_add - Callback for scsi_register_device_handler
*/
static int scsi_dh_notifier_add(struct device *dev, void *data)
{
struct scsi_device_handler *scsi_dh = data;
struct scsi_device *sdev;
if (!scsi_is_sdev_device(dev))
return 0;
if (!get_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (device_handler_match(scsi_dh, sdev))
scsi_dh_handler_attach(sdev, scsi_dh);
put_device(dev);
return 0;
}
/*
* scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
*/
static int scsi_dh_notifier_remove(struct device *dev, void *data) static int scsi_dh_notifier_remove(struct device *dev, void *data)
{ {
struct scsi_device_handler *scsi_dh = data; struct scsi_device_handler *scsi_dh = data;
struct scsi_device *sdev;
if (!scsi_is_sdev_device(dev))
return 0;
if (!get_device(dev))
return 0;
sdev = to_scsi_device(dev);
scsi_dh_handler_detach(sdev, scsi_dh);
put_device(dev);
scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_DEL_DEVICE, dev);
return 0; return 0;
} }
/*
* scsi_register_device_handler - register a device handler personality
* module.
* @scsi_dh - device handler to be registered.
*
* Returns 0 on success, -EBUSY if handler already registered.
*/
int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
{
if (get_device_handler(scsi_dh->name))
return -EBUSY;
spin_lock(&list_lock);
list_add(&scsi_dh->list, &scsi_dh_list);
spin_unlock(&list_lock);
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
return SCSI_DH_OK;
}
EXPORT_SYMBOL_GPL(scsi_register_device_handler);
/* /*
* scsi_unregister_device_handler - register a device handler personality * scsi_unregister_device_handler - register a device handler personality
* module. * module.
...@@ -95,23 +217,18 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data) ...@@ -95,23 +217,18 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
*/ */
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
{ {
int ret = -ENODEV; if (!get_device_handler(scsi_dh->name))
struct scsi_device_handler *tmp; return -ENODEV;
tmp = get_device_handler(scsi_dh->name);
if (!tmp)
goto done;
ret = bus_unregister_notifier(&scsi_bus_type, &scsi_dh->nb);
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
scsi_dh_notifier_remove); scsi_dh_notifier_remove);
spin_lock(&list_lock); spin_lock(&list_lock);
list_del(&scsi_dh->list); list_del(&scsi_dh->list);
spin_unlock(&list_lock); spin_unlock(&list_lock);
printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
done: return SCSI_DH_OK;
return ret;
} }
EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
...@@ -157,6 +274,27 @@ int scsi_dh_handler_exist(const char *name) ...@@ -157,6 +274,27 @@ int scsi_dh_handler_exist(const char *name)
} }
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist); EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
static struct notifier_block scsi_dh_nb = {
.notifier_call = scsi_dh_notifier
};
static int __init scsi_dh_init(void)
{
int r;
r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
return r;
}
static void __exit scsi_dh_exit(void)
{
bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
}
module_init(scsi_dh_init);
module_exit(scsi_dh_exit);
MODULE_DESCRIPTION("SCSI device handler"); MODULE_DESCRIPTION("SCSI device handler");
MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>"); MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -238,12 +238,12 @@ static int sp_info_endio(struct scsi_device *sdev, int result, ...@@ -238,12 +238,12 @@ static int sp_info_endio(struct scsi_device *sdev, int result,
} }
/* /*
* Get block request for REQ_BLOCK_PC command issued to path. Currently * Get block request for REQ_BLOCK_PC command issued to path. Currently
* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands. * limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
* *
* Uses data and sense buffers in hardware handler context structure and * Uses data and sense buffers in hardware handler context structure and
* assumes serial servicing of commands, both issuance and completion. * assumes serial servicing of commands, both issuance and completion.
*/ */
static struct request *get_req(struct scsi_device *sdev, int cmd) static struct request *get_req(struct scsi_device *sdev, int cmd)
{ {
struct clariion_dh_data *csdev = get_clariion_data(sdev); struct clariion_dh_data *csdev = get_clariion_data(sdev);
...@@ -390,21 +390,21 @@ static int clariion_check_sense(struct scsi_device *sdev, ...@@ -390,21 +390,21 @@ static int clariion_check_sense(struct scsi_device *sdev,
return SUCCESS; return SUCCESS;
} }
static const struct { const struct scsi_dh_devlist clariion_dev_list[] = {
char *vendor;
char *model;
} clariion_dev_list[] = {
{"DGC", "RAID"}, {"DGC", "RAID"},
{"DGC", "DISK"}, {"DGC", "DISK"},
{NULL, NULL}, {NULL, NULL},
}; };
static int clariion_bus_notify(struct notifier_block *, unsigned long, void *); static int clariion_bus_attach(struct scsi_device *sdev);
static void clariion_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler clariion_dh = { static struct scsi_device_handler clariion_dh = {
.name = CLARIION_NAME, .name = CLARIION_NAME,
.module = THIS_MODULE, .module = THIS_MODULE,
.nb.notifier_call = clariion_bus_notify, .devlist = clariion_dev_list,
.attach = clariion_bus_attach,
.detach = clariion_bus_detach,
.check_sense = clariion_check_sense, .check_sense = clariion_check_sense,
.activate = clariion_activate, .activate = clariion_activate,
}; };
...@@ -412,40 +412,18 @@ static struct scsi_device_handler clariion_dh = { ...@@ -412,40 +412,18 @@ static struct scsi_device_handler clariion_dh = {
/* /*
* TODO: need some interface so we can set trespass values * TODO: need some interface so we can set trespass values
*/ */
static int clariion_bus_notify(struct notifier_block *nb, static int clariion_bus_attach(struct scsi_device *sdev)
unsigned long action, void *data)
{ {
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data; struct scsi_dh_data *scsi_dh_data;
struct clariion_dh_data *h; struct clariion_dh_data *h;
int i, found = 0;
unsigned long flags; unsigned long flags;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; clariion_dev_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
strlen(clariion_dev_list[i].vendor)) &&
!strncmp(sdev->model, clariion_dev_list[i].model,
strlen(clariion_dev_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL); + sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) { if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n", sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
CLARIION_NAME); CLARIION_NAME);
goto out; return -ENOMEM;
} }
scsi_dh_data->scsi_dh = &clariion_dh; scsi_dh_data->scsi_dh = &clariion_dh;
...@@ -460,25 +438,24 @@ static int clariion_bus_notify(struct notifier_block *nb, ...@@ -460,25 +438,24 @@ static int clariion_bus_notify(struct notifier_block *nb,
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME); sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME);
try_module_get(THIS_MODULE); try_module_get(THIS_MODULE);
} else if (action == BUS_NOTIFY_DEL_DEVICE) { return 0;
if (sdev->scsi_dh_data == NULL || }
sdev->scsi_dh_data->scsi_dh != &clariion_dh)
goto out; static void clariion_bus_detach(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags); spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data; scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL; sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", sdev_printk(KERN_NOTICE, sdev, "Detached %s.\n",
CLARIION_NAME); CLARIION_NAME);
kfree(scsi_dh_data); kfree(scsi_dh_data);
module_put(THIS_MODULE); module_put(THIS_MODULE);
}
out:
return 0;
} }
static int __init clariion_init(void) static int __init clariion_init(void)
......
...@@ -108,58 +108,36 @@ static int hp_sw_activate(struct scsi_device *sdev) ...@@ -108,58 +108,36 @@ static int hp_sw_activate(struct scsi_device *sdev)
return ret; return ret;
} }
static const struct { const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
char *vendor;
char *model;
} hp_sw_dh_data_list[] = {
{"COMPAQ", "MSA"}, {"COMPAQ", "MSA"},
{"HP", "HSV"}, {"HP", "HSV"},
{"DEC", "HSG80"}, {"DEC", "HSG80"},
{NULL, NULL}, {NULL, NULL},
}; };
static int hp_sw_bus_notify(struct notifier_block *, unsigned long, void *); static int hp_sw_bus_attach(struct scsi_device *sdev);
static void hp_sw_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler hp_sw_dh = { static struct scsi_device_handler hp_sw_dh = {
.name = HP_SW_NAME, .name = HP_SW_NAME,
.module = THIS_MODULE, .module = THIS_MODULE,
.nb.notifier_call = hp_sw_bus_notify, .devlist = hp_sw_dh_data_list,
.attach = hp_sw_bus_attach,
.detach = hp_sw_bus_detach,
.activate = hp_sw_activate, .activate = hp_sw_activate,
}; };
static int hp_sw_bus_notify(struct notifier_block *nb, static int hp_sw_bus_attach(struct scsi_device *sdev)
unsigned long action, void *data)
{ {
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data; struct scsi_dh_data *scsi_dh_data;
int i, found = 0;
unsigned long flags; unsigned long flags;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
strlen(hp_sw_dh_data_list[i].vendor)) &&
!strncmp(sdev->model, hp_sw_dh_data_list[i].model,
strlen(hp_sw_dh_data_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(struct hp_sw_dh_data) , GFP_KERNEL); + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
if (!scsi_dh_data) { if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n", sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
HP_SW_NAME); HP_SW_NAME);
goto out; return 0;
} }
scsi_dh_data->scsi_dh = &hp_sw_dh; scsi_dh_data->scsi_dh = &hp_sw_dh;
...@@ -169,10 +147,14 @@ static int hp_sw_bus_notify(struct notifier_block *nb, ...@@ -169,10 +147,14 @@ static int hp_sw_bus_notify(struct notifier_block *nb,
try_module_get(THIS_MODULE); try_module_get(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME); sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
if (sdev->scsi_dh_data == NULL || return 0;
sdev->scsi_dh_data->scsi_dh != &hp_sw_dh) }
goto out;
static void hp_sw_bus_detach( struct scsi_device *sdev )
{
struct scsi_dh_data *scsi_dh_data;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags); spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data; scsi_dh_data = sdev->scsi_dh_data;
...@@ -180,13 +162,9 @@ static int hp_sw_bus_notify(struct notifier_block *nb, ...@@ -180,13 +162,9 @@ static int hp_sw_bus_notify(struct notifier_block *nb,
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
module_put(THIS_MODULE); module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", HP_SW_NAME); sdev_printk(KERN_NOTICE, sdev, "Detached %s\n", HP_SW_NAME);
kfree(scsi_dh_data); kfree(scsi_dh_data);
}
out:
return 0;
} }
static int __init hp_sw_init(void) static int __init hp_sw_init(void)
......
...@@ -569,10 +569,7 @@ static int rdac_check_sense(struct scsi_device *sdev, ...@@ -569,10 +569,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
return SCSI_RETURN_NOT_HANDLED; return SCSI_RETURN_NOT_HANDLED;
} }
static const struct { const struct scsi_dh_devlist rdac_dev_list[] = {
char *vendor;
char *model;
} rdac_dev_list[] = {
{"IBM", "1722"}, {"IBM", "1722"},
{"IBM", "1724"}, {"IBM", "1724"},
{"IBM", "1726"}, {"IBM", "1726"},
...@@ -590,54 +587,32 @@ static const struct { ...@@ -590,54 +587,32 @@ static const struct {
{NULL, NULL}, {NULL, NULL},
}; };
static int rdac_bus_notify(struct notifier_block *, unsigned long, void *); static int rdac_bus_attach(struct scsi_device *sdev);
static void rdac_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler rdac_dh = { static struct scsi_device_handler rdac_dh = {
.name = RDAC_NAME, .name = RDAC_NAME,
.module = THIS_MODULE, .module = THIS_MODULE,
.nb.notifier_call = rdac_bus_notify, .devlist = rdac_dev_list,
.prep_fn = rdac_prep_fn, .prep_fn = rdac_prep_fn,
.check_sense = rdac_check_sense, .check_sense = rdac_check_sense,
.attach = rdac_bus_attach,
.detach = rdac_bus_detach,
.activate = rdac_activate, .activate = rdac_activate,
}; };
/* static int rdac_bus_attach(struct scsi_device *sdev)
* TODO: need some interface so we can set trespass values
*/
static int rdac_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
{ {
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data; struct scsi_dh_data *scsi_dh_data;
struct rdac_dh_data *h; struct rdac_dh_data *h;
int i, found = 0;
unsigned long flags; unsigned long flags;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; rdac_dev_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor,
strlen(rdac_dev_list[i].vendor)) &&
!strncmp(sdev->model, rdac_dev_list[i].model,
strlen(rdac_dev_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL); + sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) { if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n", sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
RDAC_NAME); RDAC_NAME);
goto out; return 0;
} }
scsi_dh_data->scsi_dh = &rdac_dh; scsi_dh_data->scsi_dh = &rdac_dh;
...@@ -649,12 +624,16 @@ static int rdac_bus_notify(struct notifier_block *nb, ...@@ -649,12 +624,16 @@ static int rdac_bus_notify(struct notifier_block *nb,
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
try_module_get(THIS_MODULE); try_module_get(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", RDAC_NAME); sdev_printk(KERN_NOTICE, sdev, "Attached %s\n", RDAC_NAME);
return 0;
}
} else if (action == BUS_NOTIFY_DEL_DEVICE) { static void rdac_bus_detach( struct scsi_device *sdev )
if (sdev->scsi_dh_data == NULL || {
sdev->scsi_dh_data->scsi_dh != &rdac_dh) struct scsi_dh_data *scsi_dh_data;
goto out; struct rdac_dh_data *h;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags); spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data; scsi_dh_data = sdev->scsi_dh_data;
...@@ -666,13 +645,11 @@ static int rdac_bus_notify(struct notifier_block *nb, ...@@ -666,13 +645,11 @@ static int rdac_bus_notify(struct notifier_block *nb,
kref_put(&h->ctlr->kref, release_controller); kref_put(&h->ctlr->kref, release_controller);
kfree(scsi_dh_data); kfree(scsi_dh_data);
module_put(THIS_MODULE); module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", RDAC_NAME); sdev_printk(KERN_NOTICE, sdev, "Detached %s\n", RDAC_NAME);
}
out:
return 0;
} }
static int __init rdac_init(void) static int __init rdac_init(void)
{ {
int r; int r;
......
...@@ -167,15 +167,22 @@ struct scsi_device { ...@@ -167,15 +167,22 @@ struct scsi_device {
unsigned long sdev_data[0]; unsigned long sdev_data[0];
} __attribute__((aligned(sizeof(unsigned long)))); } __attribute__((aligned(sizeof(unsigned long))));
struct scsi_dh_devlist {
char *vendor;
char *model;
};
struct scsi_device_handler { struct scsi_device_handler {
/* Used by the infrastructure */ /* Used by the infrastructure */
struct list_head list; /* list of scsi_device_handlers */ struct list_head list; /* list of scsi_device_handlers */
struct notifier_block nb;
/* Filled by the hardware handler */ /* Filled by the hardware handler */
struct module *module; struct module *module;
const char *name; const char *name;
const struct scsi_dh_devlist *devlist;
int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
int (*attach)(struct scsi_device *);
void (*detach)(struct scsi_device *);
int (*activate)(struct scsi_device *); int (*activate)(struct scsi_device *);
int (*prep_fn)(struct scsi_device *, struct request *); int (*prep_fn)(struct scsi_device *, struct request *);
}; };
......
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