diff options
author | Hannes Reinecke <hare@suse.de> | 2008-07-17 19:52:51 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-26 15:14:51 -0400 |
commit | 765cbc6dad16b87724803e359d6be792ddf08614 (patch) | |
tree | 2cedfbe6b55c9f7a3e4cc3fb4f0d1f4d9d18f625 /drivers/scsi/device_handler/scsi_dh_emc.c | |
parent | 6d49f63b415ca02223e01e187076cb69a5a38eaf (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/device_handler/scsi_dh_emc.c')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_emc.c | 109 |
1 files changed, 43 insertions, 66 deletions
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 | */ |
247 | static struct request *get_req(struct scsi_device *sdev, int cmd) | 247 | static 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 | ||
393 | static const struct { | 393 | const 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 | ||
402 | static int clariion_bus_notify(struct notifier_block *, unsigned long, void *); | 399 | static int clariion_bus_attach(struct scsi_device *sdev); |
400 | static void clariion_bus_detach(struct scsi_device *sdev); | ||
403 | 401 | ||
404 | static struct scsi_device_handler clariion_dh = { | 402 | static 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 | */ |
415 | static int clariion_bus_notify(struct notifier_block *nb, | 415 | static 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); | 444 | static 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 | ||
480 | out: | 457 | kfree(scsi_dh_data); |
481 | return 0; | 458 | module_put(THIS_MODULE); |
482 | } | 459 | } |
483 | 460 | ||
484 | static int __init clariion_init(void) | 461 | static int __init clariion_init(void) |