[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>

authored by

Hannes Reinecke and committed by
James Bottomley
765cbc6d 6d49f63b

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