diff options
author | Chandra Seetharaman <sekharan@us.ibm.com> | 2011-07-20 17:18:56 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 06:29:44 -0400 |
commit | a53becc9a9dbe4f2961b2bba129b3b2624401021 (patch) | |
tree | 67351ddb63c352d8529f708cb3eb83a726b84f36 /drivers/scsi/device_handler | |
parent | e466e1c6e14e211e0ece86bdb0810b1b9c1a59a8 (diff) |
[SCSI] dh_rdac: Use WWID from C8 page instead of Subsystem id from C4 page to identify storage
rdac hardware handler uses "Subsystem Identifier" from C4 inquiry page
to uniquely identify a storage. The problem with that is that if any
any of the bytes are non-ascii, subsys_id will all be spaces (hex
0x20). This creates lot of problems especially when there are multiple
rdac storages are connected to the server.
Use "Storage Array Unique Identifier" from C8 inquiry page, which is the
world wide unique identifier for the storage array, to uniquely identify
the storage.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_rdac.c | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 2e7c136bb805..f57009b348d6 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -128,25 +128,7 @@ struct c4_inquiry { | |||
128 | u8 reserved[2]; | 128 | u8 reserved[2]; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | struct rdac_controller { | 131 | #define UNIQUE_ID_LEN 16 |
132 | u8 subsys_id[SUBSYS_ID_LEN]; | ||
133 | u8 slot_id[SLOT_ID_LEN]; | ||
134 | int use_ms10; | ||
135 | struct kref kref; | ||
136 | struct list_head node; /* list of all controllers */ | ||
137 | union { | ||
138 | struct rdac_pg_legacy legacy; | ||
139 | struct rdac_pg_expanded expanded; | ||
140 | } mode_select; | ||
141 | u8 index; | ||
142 | u8 array_name[ARRAY_LABEL_LEN]; | ||
143 | spinlock_t ms_lock; | ||
144 | int ms_queued; | ||
145 | struct work_struct ms_work; | ||
146 | struct scsi_device *ms_sdev; | ||
147 | struct list_head ms_head; | ||
148 | }; | ||
149 | |||
150 | struct c8_inquiry { | 132 | struct c8_inquiry { |
151 | u8 peripheral_info; | 133 | u8 peripheral_info; |
152 | u8 page_code; /* 0xC8 */ | 134 | u8 page_code; /* 0xC8 */ |
@@ -159,12 +141,30 @@ struct c8_inquiry { | |||
159 | u8 vol_user_label_len; | 141 | u8 vol_user_label_len; |
160 | u8 vol_user_label[60]; | 142 | u8 vol_user_label[60]; |
161 | u8 array_uniq_id_len; | 143 | u8 array_uniq_id_len; |
162 | u8 array_unique_id[16]; | 144 | u8 array_unique_id[UNIQUE_ID_LEN]; |
163 | u8 array_user_label_len; | 145 | u8 array_user_label_len; |
164 | u8 array_user_label[60]; | 146 | u8 array_user_label[60]; |
165 | u8 lun[8]; | 147 | u8 lun[8]; |
166 | }; | 148 | }; |
167 | 149 | ||
150 | struct rdac_controller { | ||
151 | u8 array_id[UNIQUE_ID_LEN]; | ||
152 | int use_ms10; | ||
153 | struct kref kref; | ||
154 | struct list_head node; /* list of all controllers */ | ||
155 | union { | ||
156 | struct rdac_pg_legacy legacy; | ||
157 | struct rdac_pg_expanded expanded; | ||
158 | } mode_select; | ||
159 | u8 index; | ||
160 | u8 array_name[ARRAY_LABEL_LEN]; | ||
161 | spinlock_t ms_lock; | ||
162 | int ms_queued; | ||
163 | struct work_struct ms_work; | ||
164 | struct scsi_device *ms_sdev; | ||
165 | struct list_head ms_head; | ||
166 | }; | ||
167 | |||
168 | struct c2_inquiry { | 168 | struct c2_inquiry { |
169 | u8 peripheral_info; | 169 | u8 peripheral_info; |
170 | u8 page_code; /* 0xC2 */ | 170 | u8 page_code; /* 0xC2 */ |
@@ -369,16 +369,16 @@ static void release_controller(struct kref *kref) | |||
369 | kfree(ctlr); | 369 | kfree(ctlr); |
370 | } | 370 | } |
371 | 371 | ||
372 | static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id, | 372 | static struct rdac_controller *get_controller(int index, char *array_name, |
373 | char *array_name) | 373 | u8 *array_id) |
374 | { | 374 | { |
375 | struct rdac_controller *ctlr, *tmp; | 375 | struct rdac_controller *ctlr, *tmp; |
376 | 376 | ||
377 | spin_lock(&list_lock); | 377 | spin_lock(&list_lock); |
378 | 378 | ||
379 | list_for_each_entry(tmp, &ctlr_list, node) { | 379 | list_for_each_entry(tmp, &ctlr_list, node) { |
380 | if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) && | 380 | if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) && |
381 | (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) { | 381 | (tmp->index == index)) { |
382 | kref_get(&tmp->kref); | 382 | kref_get(&tmp->kref); |
383 | spin_unlock(&list_lock); | 383 | spin_unlock(&list_lock); |
384 | return tmp; | 384 | return tmp; |
@@ -389,16 +389,10 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id, | |||
389 | goto done; | 389 | goto done; |
390 | 390 | ||
391 | /* initialize fields of controller */ | 391 | /* initialize fields of controller */ |
392 | memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN); | 392 | memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN); |
393 | memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN); | 393 | ctlr->index = index; |
394 | memcpy(ctlr->array_name, array_name, ARRAY_LABEL_LEN); | 394 | memcpy(ctlr->array_name, array_name, ARRAY_LABEL_LEN); |
395 | 395 | ||
396 | /* update the controller index */ | ||
397 | if (slot_id[1] == 0x31) | ||
398 | ctlr->index = 0; | ||
399 | else | ||
400 | ctlr->index = 1; | ||
401 | |||
402 | kref_init(&ctlr->kref); | 396 | kref_init(&ctlr->kref); |
403 | ctlr->use_ms10 = -1; | 397 | ctlr->use_ms10 = -1; |
404 | ctlr->ms_queued = 0; | 398 | ctlr->ms_queued = 0; |
@@ -444,7 +438,7 @@ done: | |||
444 | } | 438 | } |
445 | 439 | ||
446 | static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h, | 440 | static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h, |
447 | char *array_name) | 441 | char *array_name, u8 *array_id) |
448 | { | 442 | { |
449 | int err, i; | 443 | int err, i; |
450 | struct c8_inquiry *inqp; | 444 | struct c8_inquiry *inqp; |
@@ -463,6 +457,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h, | |||
463 | *(array_name+i) = inqp->array_user_label[(2*i)+1]; | 457 | *(array_name+i) = inqp->array_user_label[(2*i)+1]; |
464 | 458 | ||
465 | *(array_name+ARRAY_LABEL_LEN-1) = '\0'; | 459 | *(array_name+ARRAY_LABEL_LEN-1) = '\0'; |
460 | memset(array_id, 0, UNIQUE_ID_LEN); | ||
461 | memcpy(array_id, inqp->array_unique_id, inqp->array_uniq_id_len); | ||
466 | } | 462 | } |
467 | return err; | 463 | return err; |
468 | } | 464 | } |
@@ -504,16 +500,20 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) | |||
504 | } | 500 | } |
505 | 501 | ||
506 | static int initialize_controller(struct scsi_device *sdev, | 502 | static int initialize_controller(struct scsi_device *sdev, |
507 | struct rdac_dh_data *h, char *array_name) | 503 | struct rdac_dh_data *h, char *array_name, u8 *array_id) |
508 | { | 504 | { |
509 | int err; | 505 | int err, index; |
510 | struct c4_inquiry *inqp; | 506 | struct c4_inquiry *inqp; |
511 | 507 | ||
512 | err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h); | 508 | err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h); |
513 | if (err == SCSI_DH_OK) { | 509 | if (err == SCSI_DH_OK) { |
514 | inqp = &h->inq.c4; | 510 | inqp = &h->inq.c4; |
515 | h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id, | 511 | /* get the controller index */ |
516 | array_name); | 512 | if (inqp->slot_id[1] == 0x31) |
513 | index = 0; | ||
514 | else | ||
515 | index = 1; | ||
516 | h->ctlr = get_controller(index, array_name, array_id); | ||
517 | if (!h->ctlr) | 517 | if (!h->ctlr) |
518 | err = SCSI_DH_RES_TEMP_UNAVAIL; | 518 | err = SCSI_DH_RES_TEMP_UNAVAIL; |
519 | } | 519 | } |
@@ -835,6 +835,7 @@ static int rdac_bus_attach(struct scsi_device *sdev) | |||
835 | unsigned long flags; | 835 | unsigned long flags; |
836 | int err; | 836 | int err; |
837 | char array_name[ARRAY_LABEL_LEN]; | 837 | char array_name[ARRAY_LABEL_LEN]; |
838 | char array_id[UNIQUE_ID_LEN]; | ||
838 | 839 | ||
839 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) | 840 | scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) |
840 | + sizeof(*h) , GFP_KERNEL); | 841 | + sizeof(*h) , GFP_KERNEL); |
@@ -849,11 +850,11 @@ static int rdac_bus_attach(struct scsi_device *sdev) | |||
849 | h->lun = UNINITIALIZED_LUN; | 850 | h->lun = UNINITIALIZED_LUN; |
850 | h->state = RDAC_STATE_ACTIVE; | 851 | h->state = RDAC_STATE_ACTIVE; |
851 | 852 | ||
852 | err = get_lun_info(sdev, h, array_name); | 853 | err = get_lun_info(sdev, h, array_name, array_id); |
853 | if (err != SCSI_DH_OK) | 854 | if (err != SCSI_DH_OK) |
854 | goto failed; | 855 | goto failed; |
855 | 856 | ||
856 | err = initialize_controller(sdev, h, array_name); | 857 | err = initialize_controller(sdev, h, array_name, array_id); |
857 | if (err != SCSI_DH_OK) | 858 | if (err != SCSI_DH_OK) |
858 | goto failed; | 859 | goto failed; |
859 | 860 | ||