diff options
Diffstat (limited to 'drivers/scsi')
-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 | ||