aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2008-07-17 19:52:51 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-26 15:14:51 -0400
commit765cbc6dad16b87724803e359d6be792ddf08614 (patch)
tree2cedfbe6b55c9f7a3e4cc3fb4f0d1f4d9d18f625 /drivers/scsi
parent6d49f63b415ca02223e01e187076cb69a5a38eaf (diff)
[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: Hannes Reinecke <hare@suse.de> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c202
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c109
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c86
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c109
4 files changed, 288 insertions, 218 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index ab6c21cd9689..3f798171ed69 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -33,7 +33,7 @@ static struct scsi_device_handler *get_device_handler(const char *name)
33 33
34 spin_lock(&list_lock); 34 spin_lock(&list_lock);
35 list_for_each_entry(tmp, &scsi_dh_list, list) { 35 list_for_each_entry(tmp, &scsi_dh_list, list) {
36 if (!strcmp(tmp->name, name)) { 36 if (!strncmp(tmp->name, name, strlen(tmp->name))) {
37 found = tmp; 37 found = tmp;
38 break; 38 break;
39 } 39 }
@@ -42,51 +42,173 @@ static struct scsi_device_handler *get_device_handler(const char *name)
42 return found; 42 return found;
43} 43}
44 44
45static int scsi_dh_notifier_add(struct device *dev, void *data) 45static int device_handler_match(struct scsi_device_handler *tmp,
46 struct scsi_device *sdev)
46{ 47{
47 struct scsi_device_handler *scsi_dh = data; 48 int i;
49
50 for(i = 0; tmp->devlist[i].vendor; i++) {
51 if (!strncmp(sdev->vendor, tmp->devlist[i].vendor,
52 strlen(tmp->devlist[i].vendor)) &&
53 !strncmp(sdev->model, tmp->devlist[i].model,
54 strlen(tmp->devlist[i].model))) {
55 return 1;
56 }
57 }
48 58
49 scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_ADD_DEVICE, dev);
50 return 0; 59 return 0;
51} 60}
52 61
53/* 62/*
54 * scsi_register_device_handler - register a device handler personality 63 * scsi_dh_handler_attach - Attach a device handler to a device
55 * module. 64 * @sdev - SCSI device the device handler should attach to
56 * @scsi_dh - device handler to be registered. 65 * @scsi_dh - The device handler to attach
66 */
67static int scsi_dh_handler_attach(struct scsi_device *sdev,
68 struct scsi_device_handler *scsi_dh)
69{
70 int err = 0;
71
72 if (sdev->scsi_dh_data) {
73 if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
74 err = -EBUSY;
75 } else if (scsi_dh->attach)
76 err = scsi_dh->attach(sdev);
77
78 return err;
79}
80
81/*
82 * scsi_dh_handler_detach - Detach a device handler from a device
83 * @sdev - SCSI device the device handler should be detached from
84 * @scsi_dh - Device handler to be detached
57 * 85 *
58 * Returns 0 on success, -EBUSY if handler already registered. 86 * Detach from a device handler. If a device handler is specified,
87 * only detach if the currently attached handler is equal to it.
59 */ 88 */
60int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) 89static void scsi_dh_handler_detach(struct scsi_device *sdev,
90 struct scsi_device_handler *scsi_dh)
61{ 91{
62 int ret = -EBUSY; 92 if (!sdev->scsi_dh_data)
63 struct scsi_device_handler *tmp; 93 return;
64 94
65 tmp = get_device_handler(scsi_dh->name); 95 if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
66 if (tmp) 96 return;
67 goto done;
68 97
69 ret = bus_register_notifier(&scsi_bus_type, &scsi_dh->nb); 98 if (!scsi_dh)
99 scsi_dh = sdev->scsi_dh_data->scsi_dh;
100
101 if (scsi_dh && scsi_dh->detach)
102 scsi_dh->detach(sdev);
103}
104
105/*
106 * scsi_dh_notifier - notifier chain callback
107 */
108static int scsi_dh_notifier(struct notifier_block *nb,
109 unsigned long action, void *data)
110{
111 struct device *dev = data;
112 struct scsi_device *sdev;
113 int err = 0;
114 struct scsi_device_handler *tmp, *devinfo = NULL;
115
116 if (!scsi_is_sdev_device(dev))
117 return 0;
118
119 sdev = to_scsi_device(dev);
70 120
71 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
72 spin_lock(&list_lock); 121 spin_lock(&list_lock);
73 list_add(&scsi_dh->list, &scsi_dh_list); 122 list_for_each_entry(tmp, &scsi_dh_list, list) {
123 if (device_handler_match(tmp, sdev)) {
124 devinfo = tmp;
125 break;
126 }
127 }
74 spin_unlock(&list_lock); 128 spin_unlock(&list_lock);
75 129
76done: 130 if (!devinfo)
77 return ret; 131 goto out;
132
133 if (action == BUS_NOTIFY_ADD_DEVICE) {
134 err = scsi_dh_handler_attach(sdev, devinfo);
135 } else if (action == BUS_NOTIFY_DEL_DEVICE) {
136 scsi_dh_handler_detach(sdev, NULL);
137 }
138out:
139 return err;
78} 140}
79EXPORT_SYMBOL_GPL(scsi_register_device_handler);
80 141
142/*
143 * scsi_dh_notifier_add - Callback for scsi_register_device_handler
144 */
145static int scsi_dh_notifier_add(struct device *dev, void *data)
146{
147 struct scsi_device_handler *scsi_dh = data;
148 struct scsi_device *sdev;
149
150 if (!scsi_is_sdev_device(dev))
151 return 0;
152
153 if (!get_device(dev))
154 return 0;
155
156 sdev = to_scsi_device(dev);
157
158 if (device_handler_match(scsi_dh, sdev))
159 scsi_dh_handler_attach(sdev, scsi_dh);
160
161 put_device(dev);
162
163 return 0;
164}
165
166/*
167 * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
168 */
81static int scsi_dh_notifier_remove(struct device *dev, void *data) 169static int scsi_dh_notifier_remove(struct device *dev, void *data)
82{ 170{
83 struct scsi_device_handler *scsi_dh = data; 171 struct scsi_device_handler *scsi_dh = data;
172 struct scsi_device *sdev;
173
174 if (!scsi_is_sdev_device(dev))
175 return 0;
176
177 if (!get_device(dev))
178 return 0;
179
180 sdev = to_scsi_device(dev);
181
182 scsi_dh_handler_detach(sdev, scsi_dh);
183
184 put_device(dev);
84 185
85 scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_DEL_DEVICE, dev);
86 return 0; 186 return 0;
87} 187}
88 188
89/* 189/*
190 * scsi_register_device_handler - register a device handler personality
191 * module.
192 * @scsi_dh - device handler to be registered.
193 *
194 * Returns 0 on success, -EBUSY if handler already registered.
195 */
196int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
197{
198 if (get_device_handler(scsi_dh->name))
199 return -EBUSY;
200
201 spin_lock(&list_lock);
202 list_add(&scsi_dh->list, &scsi_dh_list);
203 spin_unlock(&list_lock);
204 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
205 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
206
207 return SCSI_DH_OK;
208}
209EXPORT_SYMBOL_GPL(scsi_register_device_handler);
210
211/*
90 * scsi_unregister_device_handler - register a device handler personality 212 * scsi_unregister_device_handler - register a device handler personality
91 * module. 213 * module.
92 * @scsi_dh - device handler to be unregistered. 214 * @scsi_dh - device handler to be unregistered.
@@ -95,23 +217,18 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
95 */ 217 */
96int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) 218int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
97{ 219{
98 int ret = -ENODEV; 220 if (!get_device_handler(scsi_dh->name))
99 struct scsi_device_handler *tmp; 221 return -ENODEV;
100
101 tmp = get_device_handler(scsi_dh->name);
102 if (!tmp)
103 goto done;
104
105 ret = bus_unregister_notifier(&scsi_bus_type, &scsi_dh->nb);
106 222
107 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, 223 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
108 scsi_dh_notifier_remove); 224 scsi_dh_notifier_remove);
225
109 spin_lock(&list_lock); 226 spin_lock(&list_lock);
110 list_del(&scsi_dh->list); 227 list_del(&scsi_dh->list);
111 spin_unlock(&list_lock); 228 spin_unlock(&list_lock);
229 printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
112 230
113done: 231 return SCSI_DH_OK;
114 return ret;
115} 232}
116EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); 233EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
117 234
@@ -157,6 +274,27 @@ int scsi_dh_handler_exist(const char *name)
157} 274}
158EXPORT_SYMBOL_GPL(scsi_dh_handler_exist); 275EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
159 276
277static struct notifier_block scsi_dh_nb = {
278 .notifier_call = scsi_dh_notifier
279};
280
281static int __init scsi_dh_init(void)
282{
283 int r;
284
285 r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
286
287 return r;
288}
289
290static void __exit scsi_dh_exit(void)
291{
292 bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
293}
294
295module_init(scsi_dh_init);
296module_exit(scsi_dh_exit);
297
160MODULE_DESCRIPTION("SCSI device handler"); 298MODULE_DESCRIPTION("SCSI device handler");
161MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>"); 299MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
162MODULE_LICENSE("GPL"); 300MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index f2467e936e55..bf0a389c52d8 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -238,12 +238,12 @@ done:
238} 238}
239 239
240/* 240/*
241* Get block request for REQ_BLOCK_PC command issued to path. Currently 241 * Get block request for REQ_BLOCK_PC command issued to path. Currently
242* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands. 242 * limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
243* 243 *
244* Uses data and sense buffers in hardware handler context structure and 244 * Uses data and sense buffers in hardware handler context structure and
245* assumes serial servicing of commands, both issuance and completion. 245 * assumes serial servicing of commands, both issuance and completion.
246*/ 246 */
247static struct request *get_req(struct scsi_device *sdev, int cmd) 247static struct request *get_req(struct scsi_device *sdev, int cmd)
248{ 248{
249 struct clariion_dh_data *csdev = get_clariion_data(sdev); 249 struct clariion_dh_data *csdev = get_clariion_data(sdev);
@@ -390,21 +390,21 @@ static int clariion_check_sense(struct scsi_device *sdev,
390 return SUCCESS; 390 return SUCCESS;
391} 391}
392 392
393static const struct { 393const struct scsi_dh_devlist clariion_dev_list[] = {
394 char *vendor;
395 char *model;
396} clariion_dev_list[] = {
397 {"DGC", "RAID"}, 394 {"DGC", "RAID"},
398 {"DGC", "DISK"}, 395 {"DGC", "DISK"},
399 {NULL, NULL}, 396 {NULL, NULL},
400}; 397};
401 398
402static int clariion_bus_notify(struct notifier_block *, unsigned long, void *); 399static int clariion_bus_attach(struct scsi_device *sdev);
400static void clariion_bus_detach(struct scsi_device *sdev);
403 401
404static struct scsi_device_handler clariion_dh = { 402static struct scsi_device_handler clariion_dh = {
405 .name = CLARIION_NAME, 403 .name = CLARIION_NAME,
406 .module = THIS_MODULE, 404 .module = THIS_MODULE,
407 .nb.notifier_call = clariion_bus_notify, 405 .devlist = clariion_dev_list,
406 .attach = clariion_bus_attach,
407 .detach = clariion_bus_detach,
408 .check_sense = clariion_check_sense, 408 .check_sense = clariion_check_sense,
409 .activate = clariion_activate, 409 .activate = clariion_activate,
410}; 410};
@@ -412,73 +412,50 @@ static struct scsi_device_handler clariion_dh = {
412/* 412/*
413 * TODO: need some interface so we can set trespass values 413 * TODO: need some interface so we can set trespass values
414 */ 414 */
415static int clariion_bus_notify(struct notifier_block *nb, 415static int clariion_bus_attach(struct scsi_device *sdev)
416 unsigned long action, void *data)
417{ 416{
418 struct device *dev = data;
419 struct scsi_device *sdev;
420 struct scsi_dh_data *scsi_dh_data; 417 struct scsi_dh_data *scsi_dh_data;
421 struct clariion_dh_data *h; 418 struct clariion_dh_data *h;
422 int i, found = 0;
423 unsigned long flags; 419 unsigned long flags;
424 420
425 if (!scsi_is_sdev_device(dev)) 421 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
426 return 0; 422 + sizeof(*h) , GFP_KERNEL);
427 423 if (!scsi_dh_data) {
428 sdev = to_scsi_device(dev); 424 sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
429 425 CLARIION_NAME);
430 if (action == BUS_NOTIFY_ADD_DEVICE) { 426 return -ENOMEM;
431 for (i = 0; clariion_dev_list[i].vendor; i++) { 427 }
432 if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
433 strlen(clariion_dev_list[i].vendor)) &&
434 !strncmp(sdev->model, clariion_dev_list[i].model,
435 strlen(clariion_dev_list[i].model))) {
436 found = 1;
437 break;
438 }
439 }
440 if (!found)
441 goto out;
442
443 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
444 + sizeof(*h) , GFP_KERNEL);
445 if (!scsi_dh_data) {
446 sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
447 CLARIION_NAME);
448 goto out;
449 }
450 428
451 scsi_dh_data->scsi_dh = &clariion_dh; 429 scsi_dh_data->scsi_dh = &clariion_dh;
452 h = (struct clariion_dh_data *) scsi_dh_data->buf; 430 h = (struct clariion_dh_data *) scsi_dh_data->buf;
453 h->default_sp = CLARIION_UNBOUND_LU; 431 h->default_sp = CLARIION_UNBOUND_LU;
454 h->current_sp = CLARIION_UNBOUND_LU; 432 h->current_sp = CLARIION_UNBOUND_LU;
455 433
456 spin_lock_irqsave(sdev->request_queue->queue_lock, flags); 434 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
457 sdev->scsi_dh_data = scsi_dh_data; 435 sdev->scsi_dh_data = scsi_dh_data;
458 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 436 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
459 437
460 sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME); 438 sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME);
461 try_module_get(THIS_MODULE); 439 try_module_get(THIS_MODULE);
462 440
463 } else if (action == BUS_NOTIFY_DEL_DEVICE) { 441 return 0;
464 if (sdev->scsi_dh_data == NULL || 442}
465 sdev->scsi_dh_data->scsi_dh != &clariion_dh)
466 goto out;
467 443
468 spin_lock_irqsave(sdev->request_queue->queue_lock, flags); 444static void clariion_bus_detach(struct scsi_device *sdev)
469 scsi_dh_data = sdev->scsi_dh_data; 445{
470 sdev->scsi_dh_data = NULL; 446 struct scsi_dh_data *scsi_dh_data;
471 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 447 unsigned long flags;
472 448
473 sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", 449 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
474 CLARIION_NAME); 450 scsi_dh_data = sdev->scsi_dh_data;
451 sdev->scsi_dh_data = NULL;
452 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
475 453
476 kfree(scsi_dh_data); 454 sdev_printk(KERN_NOTICE, sdev, "Detached %s.\n",
477 module_put(THIS_MODULE); 455 CLARIION_NAME);
478 }
479 456
480out: 457 kfree(scsi_dh_data);
481 return 0; 458 module_put(THIS_MODULE);
482} 459}
483 460
484static int __init clariion_init(void) 461static int __init clariion_init(void)
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index ae6be87d6a83..78259bc5dfc9 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -108,85 +108,63 @@ done:
108 return ret; 108 return ret;
109} 109}
110 110
111static const struct { 111const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
112 char *vendor;
113 char *model;
114} hp_sw_dh_data_list[] = {
115 {"COMPAQ", "MSA"}, 112 {"COMPAQ", "MSA"},
116 {"HP", "HSV"}, 113 {"HP", "HSV"},
117 {"DEC", "HSG80"}, 114 {"DEC", "HSG80"},
118 {NULL, NULL}, 115 {NULL, NULL},
119}; 116};
120 117
121static int hp_sw_bus_notify(struct notifier_block *, unsigned long, void *); 118static int hp_sw_bus_attach(struct scsi_device *sdev);
119static void hp_sw_bus_detach(struct scsi_device *sdev);
122 120
123static struct scsi_device_handler hp_sw_dh = { 121static struct scsi_device_handler hp_sw_dh = {
124 .name = HP_SW_NAME, 122 .name = HP_SW_NAME,
125 .module = THIS_MODULE, 123 .module = THIS_MODULE,
126 .nb.notifier_call = hp_sw_bus_notify, 124 .devlist = hp_sw_dh_data_list,
125 .attach = hp_sw_bus_attach,
126 .detach = hp_sw_bus_detach,
127 .activate = hp_sw_activate, 127 .activate = hp_sw_activate,
128}; 128};
129 129
130static int hp_sw_bus_notify(struct notifier_block *nb, 130static int hp_sw_bus_attach(struct scsi_device *sdev)
131 unsigned long action, void *data)
132{ 131{
133 struct device *dev = data;
134 struct scsi_device *sdev;
135 struct scsi_dh_data *scsi_dh_data; 132 struct scsi_dh_data *scsi_dh_data;
136 int i, found = 0;
137 unsigned long flags; 133 unsigned long flags;
138 134
139 if (!scsi_is_sdev_device(dev)) 135 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
136 + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
137 if (!scsi_dh_data) {
138 sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
139 HP_SW_NAME);
140 return 0; 140 return 0;
141 }
141 142
142 sdev = to_scsi_device(dev); 143 scsi_dh_data->scsi_dh = &hp_sw_dh;
143 144 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
144 if (action == BUS_NOTIFY_ADD_DEVICE) { 145 sdev->scsi_dh_data = scsi_dh_data;
145 for (i = 0; hp_sw_dh_data_list[i].vendor; i++) { 146 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
146 if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor, 147 try_module_get(THIS_MODULE);
147 strlen(hp_sw_dh_data_list[i].vendor)) &&
148 !strncmp(sdev->model, hp_sw_dh_data_list[i].model,
149 strlen(hp_sw_dh_data_list[i].model))) {
150 found = 1;
151 break;
152 }
153 }
154 if (!found)
155 goto out;
156
157 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
158 + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
159 if (!scsi_dh_data) {
160 sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
161 HP_SW_NAME);
162 goto out;
163 }
164 148
165 scsi_dh_data->scsi_dh = &hp_sw_dh; 149 sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME);
166 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
167 sdev->scsi_dh_data = scsi_dh_data;
168 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
169 try_module_get(THIS_MODULE);
170 150
171 sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME); 151 return 0;
172 } else if (action == BUS_NOTIFY_DEL_DEVICE) { 152}
173 if (sdev->scsi_dh_data == NULL ||
174 sdev->scsi_dh_data->scsi_dh != &hp_sw_dh)
175 goto out;
176 153
177 spin_lock_irqsave(sdev->request_queue->queue_lock, flags); 154static void hp_sw_bus_detach( struct scsi_device *sdev )
178 scsi_dh_data = sdev->scsi_dh_data; 155{
179 sdev->scsi_dh_data = NULL; 156 struct scsi_dh_data *scsi_dh_data;
180 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 157 unsigned long flags;
181 module_put(THIS_MODULE);
182 158
183 sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", HP_SW_NAME); 159 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
160 scsi_dh_data = sdev->scsi_dh_data;
161 sdev->scsi_dh_data = NULL;
162 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
163 module_put(THIS_MODULE);
184 164
185 kfree(scsi_dh_data); 165 sdev_printk(KERN_NOTICE, sdev, "Detached %s\n", HP_SW_NAME);
186 }
187 166
188out: 167 kfree(scsi_dh_data);
189 return 0;
190} 168}
191 169
192static int __init hp_sw_init(void) 170static int __init hp_sw_init(void)
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index fdf34b0ec6e1..0e25a6e9c82d 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -569,10 +569,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
569 return SCSI_RETURN_NOT_HANDLED; 569 return SCSI_RETURN_NOT_HANDLED;
570} 570}
571 571
572static const struct { 572const struct scsi_dh_devlist rdac_dev_list[] = {
573 char *vendor;
574 char *model;
575} rdac_dev_list[] = {
576 {"IBM", "1722"}, 573 {"IBM", "1722"},
577 {"IBM", "1724"}, 574 {"IBM", "1724"},
578 {"IBM", "1726"}, 575 {"IBM", "1726"},
@@ -590,89 +587,69 @@ static const struct {
590 {NULL, NULL}, 587 {NULL, NULL},
591}; 588};
592 589
593static int rdac_bus_notify(struct notifier_block *, unsigned long, void *); 590static int rdac_bus_attach(struct scsi_device *sdev);
591static void rdac_bus_detach(struct scsi_device *sdev);
594 592
595static struct scsi_device_handler rdac_dh = { 593static struct scsi_device_handler rdac_dh = {
596 .name = RDAC_NAME, 594 .name = RDAC_NAME,
597 .module = THIS_MODULE, 595 .module = THIS_MODULE,
598 .nb.notifier_call = rdac_bus_notify, 596 .devlist = rdac_dev_list,
599 .prep_fn = rdac_prep_fn, 597 .prep_fn = rdac_prep_fn,
600 .check_sense = rdac_check_sense, 598 .check_sense = rdac_check_sense,
599 .attach = rdac_bus_attach,
600 .detach = rdac_bus_detach,
601 .activate = rdac_activate, 601 .activate = rdac_activate,
602}; 602};
603 603
604/* 604static int rdac_bus_attach(struct scsi_device *sdev)
605 * TODO: need some interface so we can set trespass values
606 */
607static int rdac_bus_notify(struct notifier_block *nb,
608 unsigned long action, void *data)
609{ 605{
610 struct device *dev = data;
611 struct scsi_device *sdev;
612 struct scsi_dh_data *scsi_dh_data; 606 struct scsi_dh_data *scsi_dh_data;
613 struct rdac_dh_data *h; 607 struct rdac_dh_data *h;
614 int i, found = 0;
615 unsigned long flags; 608 unsigned long flags;
616 609
617 if (!scsi_is_sdev_device(dev)) 610 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
611 + sizeof(*h) , GFP_KERNEL);
612 if (!scsi_dh_data) {
613 sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
614 RDAC_NAME);
618 return 0; 615 return 0;
616 }
619 617
620 sdev = to_scsi_device(dev); 618 scsi_dh_data->scsi_dh = &rdac_dh;
621 619 h = (struct rdac_dh_data *) scsi_dh_data->buf;
622 if (action == BUS_NOTIFY_ADD_DEVICE) { 620 h->lun = UNINITIALIZED_LUN;
623 for (i = 0; rdac_dev_list[i].vendor; i++) { 621 h->state = RDAC_STATE_ACTIVE;
624 if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor, 622 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
625 strlen(rdac_dev_list[i].vendor)) && 623 sdev->scsi_dh_data = scsi_dh_data;
626 !strncmp(sdev->model, rdac_dev_list[i].model, 624 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
627 strlen(rdac_dev_list[i].model))) { 625 try_module_get(THIS_MODULE);
628 found = 1;
629 break;
630 }
631 }
632 if (!found)
633 goto out;
634
635 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
636 + sizeof(*h) , GFP_KERNEL);
637 if (!scsi_dh_data) {
638 sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
639 RDAC_NAME);
640 goto out;
641 }
642 626
643 scsi_dh_data->scsi_dh = &rdac_dh; 627 sdev_printk(KERN_NOTICE, sdev, "Attached %s\n", RDAC_NAME);
644 h = (struct rdac_dh_data *) scsi_dh_data->buf;
645 h->lun = UNINITIALIZED_LUN;
646 h->state = RDAC_STATE_ACTIVE;
647 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
648 sdev->scsi_dh_data = scsi_dh_data;
649 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
650 try_module_get(THIS_MODULE);
651
652 sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", RDAC_NAME);
653
654 } else if (action == BUS_NOTIFY_DEL_DEVICE) {
655 if (sdev->scsi_dh_data == NULL ||
656 sdev->scsi_dh_data->scsi_dh != &rdac_dh)
657 goto out;
658
659 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
660 scsi_dh_data = sdev->scsi_dh_data;
661 sdev->scsi_dh_data = NULL;
662 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
663
664 h = (struct rdac_dh_data *) scsi_dh_data->buf;
665 if (h->ctlr)
666 kref_put(&h->ctlr->kref, release_controller);
667 kfree(scsi_dh_data);
668 module_put(THIS_MODULE);
669 sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", RDAC_NAME);
670 }
671 628
672out:
673 return 0; 629 return 0;
674} 630}
675 631
632static void rdac_bus_detach( struct scsi_device *sdev )
633{
634 struct scsi_dh_data *scsi_dh_data;
635 struct rdac_dh_data *h;
636 unsigned long flags;
637
638 spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
639 scsi_dh_data = sdev->scsi_dh_data;
640 sdev->scsi_dh_data = NULL;
641 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
642
643 h = (struct rdac_dh_data *) scsi_dh_data->buf;
644 if (h->ctlr)
645 kref_put(&h->ctlr->kref, release_controller);
646 kfree(scsi_dh_data);
647 module_put(THIS_MODULE);
648 sdev_printk(KERN_NOTICE, sdev, "Detached %s\n", RDAC_NAME);
649}
650
651
652
676static int __init rdac_init(void) 653static int __init rdac_init(void)
677{ 654{
678 int r; 655 int r;