diff options
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh.c | 130 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 87 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_emc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_hp_sw.c | 7 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_rdac.c | 100 |
5 files changed, 177 insertions, 149 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 6fae3d285ae7..0119b8147797 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c | |||
@@ -25,16 +25,9 @@ | |||
25 | #include <scsi/scsi_dh.h> | 25 | #include <scsi/scsi_dh.h> |
26 | #include "../scsi_priv.h" | 26 | #include "../scsi_priv.h" |
27 | 27 | ||
28 | struct scsi_dh_devinfo_list { | ||
29 | struct list_head node; | ||
30 | char vendor[9]; | ||
31 | char model[17]; | ||
32 | struct scsi_device_handler *handler; | ||
33 | }; | ||
34 | |||
35 | static DEFINE_SPINLOCK(list_lock); | 28 | static DEFINE_SPINLOCK(list_lock); |
36 | static LIST_HEAD(scsi_dh_list); | 29 | static LIST_HEAD(scsi_dh_list); |
37 | static LIST_HEAD(scsi_dh_dev_list); | 30 | static int scsi_dh_list_idx = 1; |
38 | 31 | ||
39 | static struct scsi_device_handler *get_device_handler(const char *name) | 32 | static struct scsi_device_handler *get_device_handler(const char *name) |
40 | { | 33 | { |
@@ -51,40 +44,18 @@ static struct scsi_device_handler *get_device_handler(const char *name) | |||
51 | return found; | 44 | return found; |
52 | } | 45 | } |
53 | 46 | ||
54 | 47 | static struct scsi_device_handler *get_device_handler_by_idx(int idx) | |
55 | static struct scsi_device_handler * | ||
56 | scsi_dh_cache_lookup(struct scsi_device *sdev) | ||
57 | { | 48 | { |
58 | struct scsi_dh_devinfo_list *tmp; | 49 | struct scsi_device_handler *tmp, *found = NULL; |
59 | struct scsi_device_handler *found_dh = NULL; | ||
60 | 50 | ||
61 | spin_lock(&list_lock); | 51 | spin_lock(&list_lock); |
62 | list_for_each_entry(tmp, &scsi_dh_dev_list, node) { | 52 | list_for_each_entry(tmp, &scsi_dh_list, list) { |
63 | if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) && | 53 | if (tmp->idx == idx) { |
64 | !strncmp(sdev->model, tmp->model, strlen(tmp->model))) { | 54 | found = tmp; |
65 | found_dh = tmp->handler; | ||
66 | break; | 55 | break; |
67 | } | 56 | } |
68 | } | 57 | } |
69 | spin_unlock(&list_lock); | 58 | spin_unlock(&list_lock); |
70 | |||
71 | return found_dh; | ||
72 | } | ||
73 | |||
74 | static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh, | ||
75 | struct scsi_device *sdev) | ||
76 | { | ||
77 | int i, found = 0; | ||
78 | |||
79 | for(i = 0; scsi_dh->devlist[i].vendor; i++) { | ||
80 | if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor, | ||
81 | strlen(scsi_dh->devlist[i].vendor)) && | ||
82 | !strncmp(sdev->model, scsi_dh->devlist[i].model, | ||
83 | strlen(scsi_dh->devlist[i].model))) { | ||
84 | found = 1; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | return found; | 59 | return found; |
89 | } | 60 | } |
90 | 61 | ||
@@ -102,41 +73,14 @@ device_handler_match(struct scsi_device_handler *scsi_dh, | |||
102 | struct scsi_device *sdev) | 73 | struct scsi_device *sdev) |
103 | { | 74 | { |
104 | struct scsi_device_handler *found_dh = NULL; | 75 | struct scsi_device_handler *found_dh = NULL; |
105 | struct scsi_dh_devinfo_list *tmp; | 76 | int idx; |
106 | 77 | ||
107 | found_dh = scsi_dh_cache_lookup(sdev); | 78 | idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model, |
108 | if (found_dh) | 79 | SCSI_DEVINFO_DH); |
109 | return found_dh; | 80 | found_dh = get_device_handler_by_idx(idx); |
110 | 81 | ||
111 | if (scsi_dh) { | 82 | if (scsi_dh && found_dh != scsi_dh) |
112 | if (scsi_dh_handler_lookup(scsi_dh, sdev)) | 83 | found_dh = NULL; |
113 | found_dh = scsi_dh; | ||
114 | } else { | ||
115 | struct scsi_device_handler *tmp_dh; | ||
116 | |||
117 | spin_lock(&list_lock); | ||
118 | list_for_each_entry(tmp_dh, &scsi_dh_list, list) { | ||
119 | if (scsi_dh_handler_lookup(tmp_dh, sdev)) | ||
120 | found_dh = tmp_dh; | ||
121 | } | ||
122 | spin_unlock(&list_lock); | ||
123 | } | ||
124 | |||
125 | if (found_dh) { /* If device is found, add it to the cache */ | ||
126 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
127 | if (tmp) { | ||
128 | strncpy(tmp->vendor, sdev->vendor, 8); | ||
129 | strncpy(tmp->model, sdev->model, 16); | ||
130 | tmp->vendor[8] = '\0'; | ||
131 | tmp->model[16] = '\0'; | ||
132 | tmp->handler = found_dh; | ||
133 | spin_lock(&list_lock); | ||
134 | list_add(&tmp->node, &scsi_dh_dev_list); | ||
135 | spin_unlock(&list_lock); | ||
136 | } else { | ||
137 | found_dh = NULL; | ||
138 | } | ||
139 | } | ||
140 | 84 | ||
141 | return found_dh; | 85 | return found_dh; |
142 | } | 86 | } |
@@ -373,12 +317,25 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data) | |||
373 | */ | 317 | */ |
374 | int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) | 318 | int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) |
375 | { | 319 | { |
320 | int i; | ||
321 | |||
376 | if (get_device_handler(scsi_dh->name)) | 322 | if (get_device_handler(scsi_dh->name)) |
377 | return -EBUSY; | 323 | return -EBUSY; |
378 | 324 | ||
379 | spin_lock(&list_lock); | 325 | spin_lock(&list_lock); |
326 | scsi_dh->idx = scsi_dh_list_idx++; | ||
380 | list_add(&scsi_dh->list, &scsi_dh_list); | 327 | list_add(&scsi_dh->list, &scsi_dh_list); |
381 | spin_unlock(&list_lock); | 328 | spin_unlock(&list_lock); |
329 | |||
330 | for (i = 0; scsi_dh->devlist[i].vendor; i++) { | ||
331 | scsi_dev_info_list_add_keyed(0, | ||
332 | scsi_dh->devlist[i].vendor, | ||
333 | scsi_dh->devlist[i].model, | ||
334 | NULL, | ||
335 | scsi_dh->idx, | ||
336 | SCSI_DEVINFO_DH); | ||
337 | } | ||
338 | |||
382 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); | 339 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); |
383 | printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); | 340 | printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); |
384 | 341 | ||
@@ -395,7 +352,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler); | |||
395 | */ | 352 | */ |
396 | int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | 353 | int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) |
397 | { | 354 | { |
398 | struct scsi_dh_devinfo_list *tmp, *pos; | 355 | int i; |
399 | 356 | ||
400 | if (!get_device_handler(scsi_dh->name)) | 357 | if (!get_device_handler(scsi_dh->name)) |
401 | return -ENODEV; | 358 | return -ENODEV; |
@@ -403,14 +360,14 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | |||
403 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, | 360 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, |
404 | scsi_dh_notifier_remove); | 361 | scsi_dh_notifier_remove); |
405 | 362 | ||
363 | for (i = 0; scsi_dh->devlist[i].vendor; i++) { | ||
364 | scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor, | ||
365 | scsi_dh->devlist[i].model, | ||
366 | SCSI_DEVINFO_DH); | ||
367 | } | ||
368 | |||
406 | spin_lock(&list_lock); | 369 | spin_lock(&list_lock); |
407 | list_del(&scsi_dh->list); | 370 | list_del(&scsi_dh->list); |
408 | list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) { | ||
409 | if (pos->handler == scsi_dh) { | ||
410 | list_del(&pos->node); | ||
411 | kfree(pos); | ||
412 | } | ||
413 | } | ||
414 | spin_unlock(&list_lock); | 371 | spin_unlock(&list_lock); |
415 | printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name); | 372 | printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name); |
416 | 373 | ||
@@ -437,21 +394,31 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | |||
437 | unsigned long flags; | 394 | unsigned long flags; |
438 | struct scsi_device *sdev; | 395 | struct scsi_device *sdev; |
439 | struct scsi_device_handler *scsi_dh = NULL; | 396 | struct scsi_device_handler *scsi_dh = NULL; |
397 | struct device *dev = NULL; | ||
440 | 398 | ||
441 | spin_lock_irqsave(q->queue_lock, flags); | 399 | spin_lock_irqsave(q->queue_lock, flags); |
442 | sdev = q->queuedata; | 400 | sdev = q->queuedata; |
443 | if (sdev && sdev->scsi_dh_data) | 401 | if (sdev && sdev->scsi_dh_data) |
444 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | 402 | scsi_dh = sdev->scsi_dh_data->scsi_dh; |
445 | if (!scsi_dh || !get_device(&sdev->sdev_gendev)) | 403 | dev = get_device(&sdev->sdev_gendev); |
404 | if (!scsi_dh || !dev || | ||
405 | sdev->sdev_state == SDEV_CANCEL || | ||
406 | sdev->sdev_state == SDEV_DEL) | ||
446 | err = SCSI_DH_NOSYS; | 407 | err = SCSI_DH_NOSYS; |
408 | if (sdev->sdev_state == SDEV_OFFLINE) | ||
409 | err = SCSI_DH_DEV_OFFLINED; | ||
447 | spin_unlock_irqrestore(q->queue_lock, flags); | 410 | spin_unlock_irqrestore(q->queue_lock, flags); |
448 | 411 | ||
449 | if (err) | 412 | if (err) { |
450 | return err; | 413 | if (fn) |
414 | fn(data, err); | ||
415 | goto out; | ||
416 | } | ||
451 | 417 | ||
452 | if (scsi_dh->activate) | 418 | if (scsi_dh->activate) |
453 | err = scsi_dh->activate(sdev, fn, data); | 419 | err = scsi_dh->activate(sdev, fn, data); |
454 | put_device(&sdev->sdev_gendev); | 420 | out: |
421 | put_device(dev); | ||
455 | return err; | 422 | return err; |
456 | } | 423 | } |
457 | EXPORT_SYMBOL_GPL(scsi_dh_activate); | 424 | EXPORT_SYMBOL_GPL(scsi_dh_activate); |
@@ -569,6 +536,10 @@ static int __init scsi_dh_init(void) | |||
569 | { | 536 | { |
570 | int r; | 537 | int r; |
571 | 538 | ||
539 | r = scsi_dev_info_add_list(SCSI_DEVINFO_DH, "SCSI Device Handler"); | ||
540 | if (r) | ||
541 | return r; | ||
542 | |||
572 | r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); | 543 | r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); |
573 | 544 | ||
574 | if (!r) | 545 | if (!r) |
@@ -583,6 +554,7 @@ static void __exit scsi_dh_exit(void) | |||
583 | bus_for_each_dev(&scsi_bus_type, NULL, NULL, | 554 | bus_for_each_dev(&scsi_bus_type, NULL, NULL, |
584 | scsi_dh_sysfs_attr_remove); | 555 | scsi_dh_sysfs_attr_remove); |
585 | bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); | 556 | bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); |
557 | scsi_dev_info_remove_list(SCSI_DEVINFO_DH); | ||
586 | } | 558 | } |
587 | 559 | ||
588 | module_init(scsi_dh_init); | 560 | module_init(scsi_dh_init); |
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 1a970a76b1b9..6fec9fe5dc39 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic SCSI-3 ALUA SCSI Device Handler | 2 | * Generic SCSI-3 ALUA SCSI Device Handler |
3 | * | 3 | * |
4 | * Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH. | 4 | * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH. |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -20,17 +20,19 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/delay.h> | ||
23 | #include <scsi/scsi.h> | 24 | #include <scsi/scsi.h> |
24 | #include <scsi/scsi_eh.h> | 25 | #include <scsi/scsi_eh.h> |
25 | #include <scsi/scsi_dh.h> | 26 | #include <scsi/scsi_dh.h> |
26 | 27 | ||
27 | #define ALUA_DH_NAME "alua" | 28 | #define ALUA_DH_NAME "alua" |
28 | #define ALUA_DH_VER "1.2" | 29 | #define ALUA_DH_VER "1.3" |
29 | 30 | ||
30 | #define TPGS_STATE_OPTIMIZED 0x0 | 31 | #define TPGS_STATE_OPTIMIZED 0x0 |
31 | #define TPGS_STATE_NONOPTIMIZED 0x1 | 32 | #define TPGS_STATE_NONOPTIMIZED 0x1 |
32 | #define TPGS_STATE_STANDBY 0x2 | 33 | #define TPGS_STATE_STANDBY 0x2 |
33 | #define TPGS_STATE_UNAVAILABLE 0x3 | 34 | #define TPGS_STATE_UNAVAILABLE 0x3 |
35 | #define TPGS_STATE_LBA_DEPENDENT 0x4 | ||
34 | #define TPGS_STATE_OFFLINE 0xe | 36 | #define TPGS_STATE_OFFLINE 0xe |
35 | #define TPGS_STATE_TRANSITIONING 0xf | 37 | #define TPGS_STATE_TRANSITIONING 0xf |
36 | 38 | ||
@@ -39,6 +41,7 @@ | |||
39 | #define TPGS_SUPPORT_NONOPTIMIZED 0x02 | 41 | #define TPGS_SUPPORT_NONOPTIMIZED 0x02 |
40 | #define TPGS_SUPPORT_STANDBY 0x04 | 42 | #define TPGS_SUPPORT_STANDBY 0x04 |
41 | #define TPGS_SUPPORT_UNAVAILABLE 0x08 | 43 | #define TPGS_SUPPORT_UNAVAILABLE 0x08 |
44 | #define TPGS_SUPPORT_LBA_DEPENDENT 0x10 | ||
42 | #define TPGS_SUPPORT_OFFLINE 0x40 | 45 | #define TPGS_SUPPORT_OFFLINE 0x40 |
43 | #define TPGS_SUPPORT_TRANSITION 0x80 | 46 | #define TPGS_SUPPORT_TRANSITION 0x80 |
44 | 47 | ||
@@ -250,13 +253,15 @@ static void stpg_endio(struct request *req, int error) | |||
250 | { | 253 | { |
251 | struct alua_dh_data *h = req->end_io_data; | 254 | struct alua_dh_data *h = req->end_io_data; |
252 | struct scsi_sense_hdr sense_hdr; | 255 | struct scsi_sense_hdr sense_hdr; |
253 | unsigned err = SCSI_DH_IO; | 256 | unsigned err = SCSI_DH_OK; |
254 | 257 | ||
255 | if (error || host_byte(req->errors) != DID_OK || | 258 | if (error || host_byte(req->errors) != DID_OK || |
256 | msg_byte(req->errors) != COMMAND_COMPLETE) | 259 | msg_byte(req->errors) != COMMAND_COMPLETE) { |
260 | err = SCSI_DH_IO; | ||
257 | goto done; | 261 | goto done; |
262 | } | ||
258 | 263 | ||
259 | if (err == SCSI_DH_IO && h->senselen > 0) { | 264 | if (h->senselen > 0) { |
260 | err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, | 265 | err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, |
261 | &sense_hdr); | 266 | &sense_hdr); |
262 | if (!err) { | 267 | if (!err) { |
@@ -282,7 +287,8 @@ static void stpg_endio(struct request *req, int error) | |||
282 | print_alua_state(h->state)); | 287 | print_alua_state(h->state)); |
283 | } | 288 | } |
284 | done: | 289 | done: |
285 | blk_put_request(req); | 290 | req->end_io_data = NULL; |
291 | __blk_put_request(req->q, req); | ||
286 | if (h->callback_fn) { | 292 | if (h->callback_fn) { |
287 | h->callback_fn(h->callback_data, err); | 293 | h->callback_fn(h->callback_data, err); |
288 | h->callback_fn = h->callback_data = NULL; | 294 | h->callback_fn = h->callback_data = NULL; |
@@ -300,7 +306,6 @@ done: | |||
300 | static unsigned submit_stpg(struct alua_dh_data *h) | 306 | static unsigned submit_stpg(struct alua_dh_data *h) |
301 | { | 307 | { |
302 | struct request *rq; | 308 | struct request *rq; |
303 | int err = SCSI_DH_RES_TEMP_UNAVAIL; | ||
304 | int stpg_len = 8; | 309 | int stpg_len = 8; |
305 | struct scsi_device *sdev = h->sdev; | 310 | struct scsi_device *sdev = h->sdev; |
306 | 311 | ||
@@ -329,7 +334,7 @@ static unsigned submit_stpg(struct alua_dh_data *h) | |||
329 | rq->end_io_data = h; | 334 | rq->end_io_data = h; |
330 | 335 | ||
331 | blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio); | 336 | blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio); |
332 | return err; | 337 | return SCSI_DH_OK; |
333 | } | 338 | } |
334 | 339 | ||
335 | /* | 340 | /* |
@@ -460,6 +465,8 @@ static char print_alua_state(int state) | |||
460 | return 'S'; | 465 | return 'S'; |
461 | case TPGS_STATE_UNAVAILABLE: | 466 | case TPGS_STATE_UNAVAILABLE: |
462 | return 'U'; | 467 | return 'U'; |
468 | case TPGS_STATE_LBA_DEPENDENT: | ||
469 | return 'L'; | ||
463 | case TPGS_STATE_OFFLINE: | 470 | case TPGS_STATE_OFFLINE: |
464 | return 'O'; | 471 | return 'O'; |
465 | case TPGS_STATE_TRANSITIONING: | 472 | case TPGS_STATE_TRANSITIONING: |
@@ -534,7 +541,7 @@ static int alua_check_sense(struct scsi_device *sdev, | |||
534 | * | 541 | * |
535 | * Evaluate the Target Port Group State. | 542 | * Evaluate the Target Port Group State. |
536 | * Returns SCSI_DH_DEV_OFFLINED if the path is | 543 | * Returns SCSI_DH_DEV_OFFLINED if the path is |
537 | * found to be unuseable. | 544 | * found to be unusable. |
538 | */ | 545 | */ |
539 | static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | 546 | static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) |
540 | { | 547 | { |
@@ -542,7 +549,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | |||
542 | int len, k, off, valid_states = 0; | 549 | int len, k, off, valid_states = 0; |
543 | char *ucp; | 550 | char *ucp; |
544 | unsigned err; | 551 | unsigned err; |
552 | unsigned long expiry, interval = 10; | ||
545 | 553 | ||
554 | expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT); | ||
546 | retry: | 555 | retry: |
547 | err = submit_rtpg(sdev, h); | 556 | err = submit_rtpg(sdev, h); |
548 | 557 | ||
@@ -553,7 +562,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | |||
553 | return SCSI_DH_IO; | 562 | return SCSI_DH_IO; |
554 | 563 | ||
555 | err = alua_check_sense(sdev, &sense_hdr); | 564 | err = alua_check_sense(sdev, &sense_hdr); |
556 | if (err == ADD_TO_MLQUEUE) | 565 | if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) |
557 | goto retry; | 566 | goto retry; |
558 | sdev_printk(KERN_INFO, sdev, | 567 | sdev_printk(KERN_INFO, sdev, |
559 | "%s: rtpg sense code %02x/%02x/%02x\n", | 568 | "%s: rtpg sense code %02x/%02x/%02x\n", |
@@ -587,38 +596,37 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | |||
587 | } | 596 | } |
588 | 597 | ||
589 | sdev_printk(KERN_INFO, sdev, | 598 | sdev_printk(KERN_INFO, sdev, |
590 | "%s: port group %02x state %c supports %c%c%c%c%c%c\n", | 599 | "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n", |
591 | ALUA_DH_NAME, h->group_id, print_alua_state(h->state), | 600 | ALUA_DH_NAME, h->group_id, print_alua_state(h->state), |
592 | valid_states&TPGS_SUPPORT_TRANSITION?'T':'t', | 601 | valid_states&TPGS_SUPPORT_TRANSITION?'T':'t', |
593 | valid_states&TPGS_SUPPORT_OFFLINE?'O':'o', | 602 | valid_states&TPGS_SUPPORT_OFFLINE?'O':'o', |
603 | valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l', | ||
594 | valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u', | 604 | valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u', |
595 | valid_states&TPGS_SUPPORT_STANDBY?'S':'s', | 605 | valid_states&TPGS_SUPPORT_STANDBY?'S':'s', |
596 | valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n', | 606 | valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n', |
597 | valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a'); | 607 | valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a'); |
598 | 608 | ||
599 | if (h->tpgs & TPGS_MODE_EXPLICIT) { | 609 | switch (h->state) { |
600 | switch (h->state) { | 610 | case TPGS_STATE_TRANSITIONING: |
601 | case TPGS_STATE_TRANSITIONING: | 611 | if (time_before(jiffies, expiry)) { |
602 | /* State transition, retry */ | 612 | /* State transition, retry */ |
613 | interval *= 10; | ||
614 | msleep(interval); | ||
603 | goto retry; | 615 | goto retry; |
604 | break; | ||
605 | case TPGS_STATE_OFFLINE: | ||
606 | /* Path is offline, fail */ | ||
607 | err = SCSI_DH_DEV_OFFLINED; | ||
608 | break; | ||
609 | default: | ||
610 | break; | ||
611 | } | 616 | } |
612 | } else { | 617 | /* Transitioning time exceeded, set port to standby */ |
613 | /* Only Implicit ALUA support */ | 618 | err = SCSI_DH_RETRY; |
614 | if (h->state == TPGS_STATE_OPTIMIZED || | 619 | h->state = TPGS_STATE_STANDBY; |
615 | h->state == TPGS_STATE_NONOPTIMIZED || | 620 | break; |
616 | h->state == TPGS_STATE_STANDBY) | 621 | case TPGS_STATE_OFFLINE: |
617 | /* Useable path if active */ | 622 | case TPGS_STATE_UNAVAILABLE: |
618 | err = SCSI_DH_OK; | 623 | /* Path unusable for unavailable/offline */ |
619 | else | 624 | err = SCSI_DH_DEV_OFFLINED; |
620 | /* Path unuseable for unavailable/offline */ | 625 | break; |
621 | err = SCSI_DH_DEV_OFFLINED; | 626 | default: |
627 | /* Useable path if active */ | ||
628 | err = SCSI_DH_OK; | ||
629 | break; | ||
622 | } | 630 | } |
623 | return err; | 631 | return err; |
624 | } | 632 | } |
@@ -672,7 +680,9 @@ static int alua_activate(struct scsi_device *sdev, | |||
672 | goto out; | 680 | goto out; |
673 | } | 681 | } |
674 | 682 | ||
675 | if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) { | 683 | if (h->tpgs & TPGS_MODE_EXPLICIT && |
684 | h->state != TPGS_STATE_OPTIMIZED && | ||
685 | h->state != TPGS_STATE_LBA_DEPENDENT) { | ||
676 | h->callback_fn = fn; | 686 | h->callback_fn = fn; |
677 | h->callback_data = data; | 687 | h->callback_data = data; |
678 | err = submit_stpg(h); | 688 | err = submit_stpg(h); |
@@ -698,8 +708,11 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) | |||
698 | struct alua_dh_data *h = get_alua_data(sdev); | 708 | struct alua_dh_data *h = get_alua_data(sdev); |
699 | int ret = BLKPREP_OK; | 709 | int ret = BLKPREP_OK; |
700 | 710 | ||
701 | if (h->state != TPGS_STATE_OPTIMIZED && | 711 | if (h->state == TPGS_STATE_TRANSITIONING) |
702 | h->state != TPGS_STATE_NONOPTIMIZED) { | 712 | ret = BLKPREP_DEFER; |
713 | else if (h->state != TPGS_STATE_OPTIMIZED && | ||
714 | h->state != TPGS_STATE_NONOPTIMIZED && | ||
715 | h->state != TPGS_STATE_LBA_DEPENDENT) { | ||
703 | ret = BLKPREP_KILL; | 716 | ret = BLKPREP_KILL; |
704 | req->cmd_flags |= REQ_QUIET; | 717 | req->cmd_flags |= REQ_QUIET; |
705 | } | 718 | } |
@@ -719,7 +732,9 @@ static const struct scsi_dh_devlist alua_dev_list[] = { | |||
719 | {"Pillar", "Axiom" }, | 732 | {"Pillar", "Axiom" }, |
720 | {"Intel", "Multi-Flex"}, | 733 | {"Intel", "Multi-Flex"}, |
721 | {"NETAPP", "LUN"}, | 734 | {"NETAPP", "LUN"}, |
735 | {"NETAPP", "LUN C-Mode"}, | ||
722 | {"AIX", "NVDISK"}, | 736 | {"AIX", "NVDISK"}, |
737 | {"Promise", "VTrak"}, | ||
723 | {NULL, NULL} | 738 | {NULL, NULL} |
724 | }; | 739 | }; |
725 | 740 | ||
@@ -748,7 +763,7 @@ static int alua_bus_attach(struct scsi_device *sdev) | |||
748 | unsigned long flags; | 763 | unsigned long flags; |
749 | int err = SCSI_DH_OK; | 764 | int err = SCSI_DH_OK; |
750 | 765 | ||
751 | scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) | 766 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) |
752 | + sizeof(*h) , GFP_KERNEL); | 767 | + sizeof(*h) , GFP_KERNEL); |
753 | if (!scsi_dh_data) { | 768 | if (!scsi_dh_data) { |
754 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", | 769 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", |
@@ -767,7 +782,7 @@ static int alua_bus_attach(struct scsi_device *sdev) | |||
767 | h->sdev = sdev; | 782 | h->sdev = sdev; |
768 | 783 | ||
769 | err = alua_initialize(sdev, h); | 784 | err = alua_initialize(sdev, h); |
770 | if (err != SCSI_DH_OK) | 785 | if ((err != SCSI_DH_OK) && (err != SCSI_DH_DEV_OFFLINED)) |
771 | goto failed; | 786 | goto failed; |
772 | 787 | ||
773 | if (!try_module_get(THIS_MODULE)) | 788 | if (!try_module_get(THIS_MODULE)) |
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6faf472f7537..48441f6908a4 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |||
@@ -650,7 +650,7 @@ static int clariion_bus_attach(struct scsi_device *sdev) | |||
650 | unsigned long flags; | 650 | unsigned long flags; |
651 | int err; | 651 | int err; |
652 | 652 | ||
653 | scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) | 653 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) |
654 | + sizeof(*h) , GFP_KERNEL); | 654 | + sizeof(*h) , GFP_KERNEL); |
655 | if (!scsi_dh_data) { | 655 | if (!scsi_dh_data) { |
656 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", | 656 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", |
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index e3916641e627..b479f1eef968 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
@@ -225,7 +225,8 @@ static void start_stop_endio(struct request *req, int error) | |||
225 | } | 225 | } |
226 | } | 226 | } |
227 | done: | 227 | done: |
228 | blk_put_request(req); | 228 | req->end_io_data = NULL; |
229 | __blk_put_request(req->q, req); | ||
229 | if (h->callback_fn) { | 230 | if (h->callback_fn) { |
230 | h->callback_fn(h->callback_data, err); | 231 | h->callback_fn(h->callback_data, err); |
231 | h->callback_fn = h->callback_data = NULL; | 232 | h->callback_fn = h->callback_data = NULL; |
@@ -338,8 +339,8 @@ static int hp_sw_bus_attach(struct scsi_device *sdev) | |||
338 | unsigned long flags; | 339 | unsigned long flags; |
339 | int ret; | 340 | int ret; |
340 | 341 | ||
341 | scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) | 342 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) |
342 | + sizeof(struct hp_sw_dh_data) , GFP_KERNEL); | 343 | + sizeof(*h) , GFP_KERNEL); |
343 | if (!scsi_dh_data) { | 344 | if (!scsi_dh_data) { |
344 | sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n", | 345 | sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n", |
345 | HP_SW_NAME); | 346 | HP_SW_NAME); |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index b9bcfa4c7d26..e7fc70d6b478 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -182,14 +182,24 @@ struct rdac_dh_data { | |||
182 | struct rdac_controller *ctlr; | 182 | struct rdac_controller *ctlr; |
183 | #define UNINITIALIZED_LUN (1 << 8) | 183 | #define UNINITIALIZED_LUN (1 << 8) |
184 | unsigned lun; | 184 | unsigned lun; |
185 | |||
186 | #define RDAC_MODE 0 | ||
187 | #define RDAC_MODE_AVT 1 | ||
188 | #define RDAC_MODE_IOSHIP 2 | ||
189 | unsigned char mode; | ||
190 | |||
185 | #define RDAC_STATE_ACTIVE 0 | 191 | #define RDAC_STATE_ACTIVE 0 |
186 | #define RDAC_STATE_PASSIVE 1 | 192 | #define RDAC_STATE_PASSIVE 1 |
187 | unsigned char state; | 193 | unsigned char state; |
188 | 194 | ||
189 | #define RDAC_LUN_UNOWNED 0 | 195 | #define RDAC_LUN_UNOWNED 0 |
190 | #define RDAC_LUN_OWNED 1 | 196 | #define RDAC_LUN_OWNED 1 |
191 | #define RDAC_LUN_AVT 2 | ||
192 | char lun_state; | 197 | char lun_state; |
198 | |||
199 | #define RDAC_PREFERRED 0 | ||
200 | #define RDAC_NON_PREFERRED 1 | ||
201 | char preferred; | ||
202 | |||
193 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | 203 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; |
194 | union { | 204 | union { |
195 | struct c2_inquiry c2; | 205 | struct c2_inquiry c2; |
@@ -199,11 +209,15 @@ struct rdac_dh_data { | |||
199 | } inq; | 209 | } inq; |
200 | }; | 210 | }; |
201 | 211 | ||
212 | static const char *mode[] = { | ||
213 | "RDAC", | ||
214 | "AVT", | ||
215 | "IOSHIP", | ||
216 | }; | ||
202 | static const char *lun_state[] = | 217 | static const char *lun_state[] = |
203 | { | 218 | { |
204 | "unowned", | 219 | "unowned", |
205 | "owned", | 220 | "owned", |
206 | "owned (AVT mode)", | ||
207 | }; | 221 | }; |
208 | 222 | ||
209 | struct rdac_queue_data { | 223 | struct rdac_queue_data { |
@@ -281,11 +295,13 @@ static struct request *get_rdac_req(struct scsi_device *sdev, | |||
281 | } | 295 | } |
282 | 296 | ||
283 | static struct request *rdac_failover_get(struct scsi_device *sdev, | 297 | static struct request *rdac_failover_get(struct scsi_device *sdev, |
284 | struct rdac_dh_data *h) | 298 | struct rdac_dh_data *h, struct list_head *list) |
285 | { | 299 | { |
286 | struct request *rq; | 300 | struct request *rq; |
287 | struct rdac_mode_common *common; | 301 | struct rdac_mode_common *common; |
288 | unsigned data_size; | 302 | unsigned data_size; |
303 | struct rdac_queue_data *qdata; | ||
304 | u8 *lun_table; | ||
289 | 305 | ||
290 | if (h->ctlr->use_ms10) { | 306 | if (h->ctlr->use_ms10) { |
291 | struct rdac_pg_expanded *rdac_pg; | 307 | struct rdac_pg_expanded *rdac_pg; |
@@ -298,6 +314,7 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, | |||
298 | rdac_pg->subpage_code = 0x1; | 314 | rdac_pg->subpage_code = 0x1; |
299 | rdac_pg->page_len[0] = 0x01; | 315 | rdac_pg->page_len[0] = 0x01; |
300 | rdac_pg->page_len[1] = 0x28; | 316 | rdac_pg->page_len[1] = 0x28; |
317 | lun_table = rdac_pg->lun_table; | ||
301 | } else { | 318 | } else { |
302 | struct rdac_pg_legacy *rdac_pg; | 319 | struct rdac_pg_legacy *rdac_pg; |
303 | 320 | ||
@@ -307,11 +324,16 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, | |||
307 | common = &rdac_pg->common; | 324 | common = &rdac_pg->common; |
308 | rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; | 325 | rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; |
309 | rdac_pg->page_len = 0x68; | 326 | rdac_pg->page_len = 0x68; |
327 | lun_table = rdac_pg->lun_table; | ||
310 | } | 328 | } |
311 | common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; | 329 | common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; |
312 | common->quiescence_timeout = RDAC_QUIESCENCE_TIME; | 330 | common->quiescence_timeout = RDAC_QUIESCENCE_TIME; |
313 | common->rdac_options = RDAC_FORCED_QUIESENCE; | 331 | common->rdac_options = RDAC_FORCED_QUIESENCE; |
314 | 332 | ||
333 | list_for_each_entry(qdata, list, entry) { | ||
334 | lun_table[qdata->h->lun] = 0x81; | ||
335 | } | ||
336 | |||
315 | /* get request for block layer packet command */ | 337 | /* get request for block layer packet command */ |
316 | rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE); | 338 | rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE); |
317 | if (!rq) | 339 | if (!rq) |
@@ -450,25 +472,33 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) | |||
450 | int err; | 472 | int err; |
451 | struct c9_inquiry *inqp; | 473 | struct c9_inquiry *inqp; |
452 | 474 | ||
453 | h->lun_state = RDAC_LUN_UNOWNED; | ||
454 | h->state = RDAC_STATE_ACTIVE; | 475 | h->state = RDAC_STATE_ACTIVE; |
455 | err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h); | 476 | err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h); |
456 | if (err == SCSI_DH_OK) { | 477 | if (err == SCSI_DH_OK) { |
457 | inqp = &h->inq.c9; | 478 | inqp = &h->inq.c9; |
458 | if ((inqp->avte_cvp >> 7) == 0x1) { | 479 | /* detect the operating mode */ |
459 | /* LUN in AVT mode */ | 480 | if ((inqp->avte_cvp >> 5) & 0x1) |
460 | sdev_printk(KERN_NOTICE, sdev, | 481 | h->mode = RDAC_MODE_IOSHIP; /* LUN in IOSHIP mode */ |
461 | "%s: AVT mode detected\n", | 482 | else if (inqp->avte_cvp >> 7) |
462 | RDAC_NAME); | 483 | h->mode = RDAC_MODE_AVT; /* LUN in AVT mode */ |
463 | h->lun_state = RDAC_LUN_AVT; | 484 | else |
464 | } else if ((inqp->avte_cvp & 0x1) != 0) { | 485 | h->mode = RDAC_MODE; /* LUN in RDAC mode */ |
465 | /* LUN was owned by the controller */ | 486 | |
487 | /* Update ownership */ | ||
488 | if (inqp->avte_cvp & 0x1) | ||
466 | h->lun_state = RDAC_LUN_OWNED; | 489 | h->lun_state = RDAC_LUN_OWNED; |
490 | else { | ||
491 | h->lun_state = RDAC_LUN_UNOWNED; | ||
492 | if (h->mode == RDAC_MODE) | ||
493 | h->state = RDAC_STATE_PASSIVE; | ||
467 | } | 494 | } |
468 | } | ||
469 | 495 | ||
470 | if (h->lun_state == RDAC_LUN_UNOWNED) | 496 | /* Update path prio*/ |
471 | h->state = RDAC_STATE_PASSIVE; | 497 | if (inqp->path_prio & 0x1) |
498 | h->preferred = RDAC_PREFERRED; | ||
499 | else | ||
500 | h->preferred = RDAC_NON_PREFERRED; | ||
501 | } | ||
472 | 502 | ||
473 | return err; | 503 | return err; |
474 | } | 504 | } |
@@ -565,7 +595,6 @@ static void send_mode_select(struct work_struct *work) | |||
565 | int err, retry_cnt = RDAC_RETRY_COUNT; | 595 | int err, retry_cnt = RDAC_RETRY_COUNT; |
566 | struct rdac_queue_data *tmp, *qdata; | 596 | struct rdac_queue_data *tmp, *qdata; |
567 | LIST_HEAD(list); | 597 | LIST_HEAD(list); |
568 | u8 *lun_table; | ||
569 | 598 | ||
570 | spin_lock(&ctlr->ms_lock); | 599 | spin_lock(&ctlr->ms_lock); |
571 | list_splice_init(&ctlr->ms_head, &list); | 600 | list_splice_init(&ctlr->ms_head, &list); |
@@ -573,21 +602,12 @@ static void send_mode_select(struct work_struct *work) | |||
573 | ctlr->ms_sdev = NULL; | 602 | ctlr->ms_sdev = NULL; |
574 | spin_unlock(&ctlr->ms_lock); | 603 | spin_unlock(&ctlr->ms_lock); |
575 | 604 | ||
576 | if (ctlr->use_ms10) | ||
577 | lun_table = ctlr->mode_select.expanded.lun_table; | ||
578 | else | ||
579 | lun_table = ctlr->mode_select.legacy.lun_table; | ||
580 | |||
581 | retry: | 605 | retry: |
582 | err = SCSI_DH_RES_TEMP_UNAVAIL; | 606 | err = SCSI_DH_RES_TEMP_UNAVAIL; |
583 | rq = rdac_failover_get(sdev, h); | 607 | rq = rdac_failover_get(sdev, h, &list); |
584 | if (!rq) | 608 | if (!rq) |
585 | goto done; | 609 | goto done; |
586 | 610 | ||
587 | list_for_each_entry(qdata, &list, entry) { | ||
588 | lun_table[qdata->h->lun] = 0x81; | ||
589 | } | ||
590 | |||
591 | RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " | 611 | RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " |
592 | "%s MODE_SELECT command", | 612 | "%s MODE_SELECT command", |
593 | (char *) h->ctlr->array_name, h->ctlr->index, | 613 | (char *) h->ctlr->array_name, h->ctlr->index, |
@@ -650,12 +670,27 @@ static int rdac_activate(struct scsi_device *sdev, | |||
650 | { | 670 | { |
651 | struct rdac_dh_data *h = get_rdac_data(sdev); | 671 | struct rdac_dh_data *h = get_rdac_data(sdev); |
652 | int err = SCSI_DH_OK; | 672 | int err = SCSI_DH_OK; |
673 | int act = 0; | ||
653 | 674 | ||
654 | err = check_ownership(sdev, h); | 675 | err = check_ownership(sdev, h); |
655 | if (err != SCSI_DH_OK) | 676 | if (err != SCSI_DH_OK) |
656 | goto done; | 677 | goto done; |
657 | 678 | ||
658 | if (h->lun_state == RDAC_LUN_UNOWNED) { | 679 | switch (h->mode) { |
680 | case RDAC_MODE: | ||
681 | if (h->lun_state == RDAC_LUN_UNOWNED) | ||
682 | act = 1; | ||
683 | break; | ||
684 | case RDAC_MODE_IOSHIP: | ||
685 | if ((h->lun_state == RDAC_LUN_UNOWNED) && | ||
686 | (h->preferred == RDAC_PREFERRED)) | ||
687 | act = 1; | ||
688 | break; | ||
689 | default: | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | if (act) { | ||
659 | err = queue_mode_select(sdev, fn, data); | 694 | err = queue_mode_select(sdev, fn, data); |
660 | if (err == SCSI_DH_OK) | 695 | if (err == SCSI_DH_OK) |
661 | return 0; | 696 | return 0; |
@@ -769,10 +804,13 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { | |||
769 | {"DELL", "MD32xx"}, | 804 | {"DELL", "MD32xx"}, |
770 | {"DELL", "MD32xxi"}, | 805 | {"DELL", "MD32xxi"}, |
771 | {"DELL", "MD36xxi"}, | 806 | {"DELL", "MD36xxi"}, |
807 | {"DELL", "MD36xxf"}, | ||
772 | {"LSI", "INF-01-00"}, | 808 | {"LSI", "INF-01-00"}, |
773 | {"ENGENIO", "INF-01-00"}, | 809 | {"ENGENIO", "INF-01-00"}, |
774 | {"STK", "FLEXLINE 380"}, | 810 | {"STK", "FLEXLINE 380"}, |
775 | {"SUN", "CSM100_R_FC"}, | 811 | {"SUN", "CSM100_R_FC"}, |
812 | {"SUN", "STK6580_6780"}, | ||
813 | {"SUN", "SUN_6180"}, | ||
776 | {NULL, NULL}, | 814 | {NULL, NULL}, |
777 | }; | 815 | }; |
778 | 816 | ||
@@ -798,7 +836,7 @@ static int rdac_bus_attach(struct scsi_device *sdev) | |||
798 | int err; | 836 | int err; |
799 | char array_name[ARRAY_LABEL_LEN]; | 837 | char array_name[ARRAY_LABEL_LEN]; |
800 | 838 | ||
801 | scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) | 839 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) |
802 | + sizeof(*h) , GFP_KERNEL); | 840 | + sizeof(*h) , GFP_KERNEL); |
803 | if (!scsi_dh_data) { | 841 | if (!scsi_dh_data) { |
804 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", | 842 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", |
@@ -835,8 +873,9 @@ static int rdac_bus_attach(struct scsi_device *sdev) | |||
835 | spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); | 873 | spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); |
836 | 874 | ||
837 | sdev_printk(KERN_NOTICE, sdev, | 875 | sdev_printk(KERN_NOTICE, sdev, |
838 | "%s: LUN %d (%s)\n", | 876 | "%s: LUN %d (%s) (%s)\n", |
839 | RDAC_NAME, h->lun, lun_state[(int)h->lun_state]); | 877 | RDAC_NAME, h->lun, mode[(int)h->mode], |
878 | lun_state[(int)h->lun_state]); | ||
840 | 879 | ||
841 | return 0; | 880 | return 0; |
842 | 881 | ||
@@ -904,4 +943,5 @@ module_exit(rdac_exit); | |||
904 | 943 | ||
905 | MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver"); | 944 | MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver"); |
906 | MODULE_AUTHOR("Mike Christie, Chandra Seetharaman"); | 945 | MODULE_AUTHOR("Mike Christie, Chandra Seetharaman"); |
946 | MODULE_VERSION("01.00.0000.0000"); | ||
907 | MODULE_LICENSE("GPL"); | 947 | MODULE_LICENSE("GPL"); |