aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler/scsi_dh_emc.c
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/device_handler/scsi_dh_emc.c
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/device_handler/scsi_dh_emc.c')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c109
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 */
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)