aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler
diff options
context:
space:
mode:
authorChandra Seetharaman <sekharan@us.ibm.com>2009-10-21 12:22:51 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:00:47 -0500
commit970f3f47e7c97c0bfe9f91356943b55ac389cb1d (patch)
treedab9946544c452937d165239df74d667d16bddf9 /drivers/scsi/device_handler
parent3ae31f6a7b6e442fc6a92f29330fbad230dc3992 (diff)
[SCSI] scsi_dh: Make rdac hardware handler's activate() async
Batch up MODE_SELECT in rdac device handler. LSI RDAC storage has the capability of handling mode selects for multiple luns in a same command. Make use of that ability to send as few MODE SELECTs as possible to the storage controller as possible. This patch creates a work queue and queues up activate requests when a MODE SELECT is sent down the wire. When that MODE SELECT completes, it compiles queued up activate requests for multiple luns into a single MODE SELECT. This reduces the time to do failover/failback of large number of LUNS. Signed-off-by: Babu Moger <babu.moger@lsi.com> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c108
1 files changed, 100 insertions, 8 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index be362adbd8e7..47cfe1c49c3e 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -22,6 +22,7 @@
22#include <scsi/scsi.h> 22#include <scsi/scsi.h>
23#include <scsi/scsi_eh.h> 23#include <scsi/scsi_eh.h>
24#include <scsi/scsi_dh.h> 24#include <scsi/scsi_dh.h>
25#include <linux/workqueue.h>
25 26
26#define RDAC_NAME "rdac" 27#define RDAC_NAME "rdac"
27#define RDAC_RETRY_COUNT 5 28#define RDAC_RETRY_COUNT 5
@@ -138,7 +139,13 @@ struct rdac_controller {
138 } mode_select; 139 } mode_select;
139 u8 index; 140 u8 index;
140 u8 array_name[ARRAY_LABEL_LEN]; 141 u8 array_name[ARRAY_LABEL_LEN];
142 spinlock_t ms_lock;
143 int ms_queued;
144 struct work_struct ms_work;
145 struct scsi_device *ms_sdev;
146 struct list_head ms_head;
141}; 147};
148
142struct c8_inquiry { 149struct c8_inquiry {
143 u8 peripheral_info; 150 u8 peripheral_info;
144 u8 page_code; /* 0xC8 */ 151 u8 page_code; /* 0xC8 */
@@ -198,8 +205,17 @@ static const char *lun_state[] =
198 "owned (AVT mode)", 205 "owned (AVT mode)",
199}; 206};
200 207
208struct rdac_queue_data {
209 struct list_head entry;
210 struct rdac_dh_data *h;
211 activate_complete callback_fn;
212 void *callback_data;
213};
214
201static LIST_HEAD(ctlr_list); 215static LIST_HEAD(ctlr_list);
202static DEFINE_SPINLOCK(list_lock); 216static DEFINE_SPINLOCK(list_lock);
217static struct workqueue_struct *kmpath_rdacd;
218static void send_mode_select(struct work_struct *work);
203 219
204/* 220/*
205 * module parameter to enable rdac debug logging. 221 * module parameter to enable rdac debug logging.
@@ -281,7 +297,6 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
281 rdac_pg->subpage_code = 0x1; 297 rdac_pg->subpage_code = 0x1;
282 rdac_pg->page_len[0] = 0x01; 298 rdac_pg->page_len[0] = 0x01;
283 rdac_pg->page_len[1] = 0x28; 299 rdac_pg->page_len[1] = 0x28;
284 rdac_pg->lun_table[h->lun] = 0x81;
285 } else { 300 } else {
286 struct rdac_pg_legacy *rdac_pg; 301 struct rdac_pg_legacy *rdac_pg;
287 302
@@ -291,7 +306,6 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
291 common = &rdac_pg->common; 306 common = &rdac_pg->common;
292 rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; 307 rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
293 rdac_pg->page_len = 0x68; 308 rdac_pg->page_len = 0x68;
294 rdac_pg->lun_table[h->lun] = 0x81;
295 } 309 }
296 common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; 310 common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
297 common->quiescence_timeout = RDAC_QUIESCENCE_TIME; 311 common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
@@ -325,6 +339,7 @@ static void release_controller(struct kref *kref)
325 struct rdac_controller *ctlr; 339 struct rdac_controller *ctlr;
326 ctlr = container_of(kref, struct rdac_controller, kref); 340 ctlr = container_of(kref, struct rdac_controller, kref);
327 341
342 flush_workqueue(kmpath_rdacd);
328 spin_lock(&list_lock); 343 spin_lock(&list_lock);
329 list_del(&ctlr->node); 344 list_del(&ctlr->node);
330 spin_unlock(&list_lock); 345 spin_unlock(&list_lock);
@@ -363,6 +378,11 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
363 378
364 kref_init(&ctlr->kref); 379 kref_init(&ctlr->kref);
365 ctlr->use_ms10 = -1; 380 ctlr->use_ms10 = -1;
381 ctlr->ms_queued = 0;
382 ctlr->ms_sdev = NULL;
383 spin_lock_init(&ctlr->ms_lock);
384 INIT_WORK(&ctlr->ms_work, send_mode_select);
385 INIT_LIST_HEAD(&ctlr->ms_head);
366 list_add(&ctlr->node, &ctlr_list); 386 list_add(&ctlr->node, &ctlr_list);
367done: 387done:
368 spin_unlock(&list_lock); 388 spin_unlock(&list_lock);
@@ -490,7 +510,7 @@ static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
490} 510}
491 511
492static int mode_select_handle_sense(struct scsi_device *sdev, 512static int mode_select_handle_sense(struct scsi_device *sdev,
493 unsigned char *sensebuf) 513 unsigned char *sensebuf)
494{ 514{
495 struct scsi_sense_hdr sense_hdr; 515 struct scsi_sense_hdr sense_hdr;
496 int err = SCSI_DH_IO, ret; 516 int err = SCSI_DH_IO, ret;
@@ -533,11 +553,29 @@ done:
533 return err; 553 return err;
534} 554}
535 555
536static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h) 556static void send_mode_select(struct work_struct *work)
537{ 557{
558 struct rdac_controller *ctlr =
559 container_of(work, struct rdac_controller, ms_work);
538 struct request *rq; 560 struct request *rq;
561 struct scsi_device *sdev = ctlr->ms_sdev;
562 struct rdac_dh_data *h = get_rdac_data(sdev);
539 struct request_queue *q = sdev->request_queue; 563 struct request_queue *q = sdev->request_queue;
540 int err, retry_cnt = RDAC_RETRY_COUNT; 564 int err, retry_cnt = RDAC_RETRY_COUNT;
565 struct rdac_queue_data *tmp, *qdata;
566 LIST_HEAD(list);
567 u8 *lun_table;
568
569 spin_lock(&ctlr->ms_lock);
570 list_splice_init(&ctlr->ms_head, &list);
571 ctlr->ms_queued = 0;
572 ctlr->ms_sdev = NULL;
573 spin_unlock(&ctlr->ms_lock);
574
575 if (ctlr->use_ms10)
576 lun_table = ctlr->mode_select.expanded.lun_table;
577 else
578 lun_table = ctlr->mode_select.legacy.lun_table;
541 579
542retry: 580retry:
543 err = SCSI_DH_RES_TEMP_UNAVAIL; 581 err = SCSI_DH_RES_TEMP_UNAVAIL;
@@ -545,6 +583,10 @@ retry:
545 if (!rq) 583 if (!rq)
546 goto done; 584 goto done;
547 585
586 list_for_each_entry(qdata, &list, entry) {
587 lun_table[qdata->h->lun] = 0x81;
588 }
589
548 RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " 590 RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
549 "%s MODE_SELECT command", 591 "%s MODE_SELECT command",
550 (char *) h->ctlr->array_name, h->ctlr->index, 592 (char *) h->ctlr->array_name, h->ctlr->index,
@@ -565,7 +607,41 @@ retry:
565 } 607 }
566 608
567done: 609done:
568 return err; 610 list_for_each_entry_safe(qdata, tmp, &list, entry) {
611 list_del(&qdata->entry);
612 if (err == SCSI_DH_OK)
613 qdata->h->state = RDAC_STATE_ACTIVE;
614 if (qdata->callback_fn)
615 qdata->callback_fn(qdata->callback_data, err);
616 kfree(qdata);
617 }
618 return;
619}
620
621static int queue_mode_select(struct scsi_device *sdev,
622 activate_complete fn, void *data)
623{
624 struct rdac_queue_data *qdata;
625 struct rdac_controller *ctlr;
626
627 qdata = kzalloc(sizeof(*qdata), GFP_KERNEL);
628 if (!qdata)
629 return SCSI_DH_RETRY;
630
631 qdata->h = get_rdac_data(sdev);
632 qdata->callback_fn = fn;
633 qdata->callback_data = data;
634
635 ctlr = qdata->h->ctlr;
636 spin_lock(&ctlr->ms_lock);
637 list_add_tail(&qdata->entry, &ctlr->ms_head);
638 if (!ctlr->ms_queued) {
639 ctlr->ms_queued = 1;
640 ctlr->ms_sdev = sdev;
641 queue_work(kmpath_rdacd, &ctlr->ms_work);
642 }
643 spin_unlock(&ctlr->ms_lock);
644 return SCSI_DH_OK;
569} 645}
570 646
571static int rdac_activate(struct scsi_device *sdev, 647static int rdac_activate(struct scsi_device *sdev,
@@ -578,8 +654,11 @@ static int rdac_activate(struct scsi_device *sdev,
578 if (err != SCSI_DH_OK) 654 if (err != SCSI_DH_OK)
579 goto done; 655 goto done;
580 656
581 if (h->lun_state == RDAC_LUN_UNOWNED) 657 if (h->lun_state == RDAC_LUN_UNOWNED) {
582 err = send_mode_select(sdev, h); 658 err = queue_mode_select(sdev, fn, data);
659 if (err == SCSI_DH_OK)
660 return 0;
661 }
583done: 662done:
584 if (fn) 663 if (fn)
585 fn(data, err); 664 fn(data, err);
@@ -793,13 +872,26 @@ static int __init rdac_init(void)
793 int r; 872 int r;
794 873
795 r = scsi_register_device_handler(&rdac_dh); 874 r = scsi_register_device_handler(&rdac_dh);
796 if (r != 0) 875 if (r != 0) {
797 printk(KERN_ERR "Failed to register scsi device handler."); 876 printk(KERN_ERR "Failed to register scsi device handler.");
877 goto done;
878 }
879
880 /*
881 * Create workqueue to handle mode selects for rdac
882 */
883 kmpath_rdacd = create_singlethread_workqueue("kmpath_rdacd");
884 if (!kmpath_rdacd) {
885 scsi_unregister_device_handler(&rdac_dh);
886 printk(KERN_ERR "kmpath_rdacd creation failed.\n");
887 }
888done:
798 return r; 889 return r;
799} 890}
800 891
801static void __exit rdac_exit(void) 892static void __exit rdac_exit(void)
802{ 893{
894 destroy_workqueue(kmpath_rdacd);
803 scsi_unregister_device_handler(&rdac_dh); 895 scsi_unregister_device_handler(&rdac_dh);
804} 896}
805 897