diff options
| author | Moger, Babu <Babu.Moger@lsi.com> | 2011-02-11 17:14:08 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-12 15:05:08 -0500 |
| commit | 04b6e153b64471ff43dde82b0122e67cf491f2f5 (patch) | |
| tree | f58379ad7189750122033f71f7e4b8a6c0c6db5a /drivers/scsi/device_handler | |
| parent | 3487735aa54407565278a5a1288119c45210b86c (diff) | |
[SCSI] scsi_dh_rdac: fix for lun_table update for rdac device handler
During one of our testing, we noticed that mode select command sent
from the host did not have the lun_table updated.
Problem is root caused to the way lun table is updated. Lun table
update was done after the call to blk_rq_map_kern is made. This was
causing problem because kernel uses bounce buffer(bio_copy_kern) if
the address is not aligned. The command buffer updated after the
call(blk_rq_map_kern) was not going on the wire. Moved the code to
update the lun_table before the call to fix the problem.
Signed-off-by: Babu Moger <babu.moger@lsi.com>
Signed-off-by: Somasundaram Krishnasamy <Somasundaram.Krishnasamy@lsi.com>
Signed-off-by: Yanling Qi <Yanling.Qi@lsi.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.c | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 5be3ae15cb71..7d83a84442a7 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
| @@ -281,11 +281,13 @@ static struct request *get_rdac_req(struct scsi_device *sdev, | |||
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static struct request *rdac_failover_get(struct scsi_device *sdev, | 283 | static struct request *rdac_failover_get(struct scsi_device *sdev, |
| 284 | struct rdac_dh_data *h) | 284 | struct rdac_dh_data *h, struct list_head *list) |
| 285 | { | 285 | { |
| 286 | struct request *rq; | 286 | struct request *rq; |
| 287 | struct rdac_mode_common *common; | 287 | struct rdac_mode_common *common; |
| 288 | unsigned data_size; | 288 | unsigned data_size; |
| 289 | struct rdac_queue_data *qdata; | ||
| 290 | u8 *lun_table; | ||
| 289 | 291 | ||
| 290 | if (h->ctlr->use_ms10) { | 292 | if (h->ctlr->use_ms10) { |
| 291 | struct rdac_pg_expanded *rdac_pg; | 293 | struct rdac_pg_expanded *rdac_pg; |
| @@ -298,6 +300,7 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, | |||
| 298 | rdac_pg->subpage_code = 0x1; | 300 | rdac_pg->subpage_code = 0x1; |
| 299 | rdac_pg->page_len[0] = 0x01; | 301 | rdac_pg->page_len[0] = 0x01; |
| 300 | rdac_pg->page_len[1] = 0x28; | 302 | rdac_pg->page_len[1] = 0x28; |
| 303 | lun_table = rdac_pg->lun_table; | ||
| 301 | } else { | 304 | } else { |
| 302 | struct rdac_pg_legacy *rdac_pg; | 305 | struct rdac_pg_legacy *rdac_pg; |
| 303 | 306 | ||
| @@ -307,11 +310,16 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, | |||
| 307 | common = &rdac_pg->common; | 310 | common = &rdac_pg->common; |
| 308 | rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; | 311 | rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; |
| 309 | rdac_pg->page_len = 0x68; | 312 | rdac_pg->page_len = 0x68; |
| 313 | lun_table = rdac_pg->lun_table; | ||
| 310 | } | 314 | } |
| 311 | common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; | 315 | common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; |
| 312 | common->quiescence_timeout = RDAC_QUIESCENCE_TIME; | 316 | common->quiescence_timeout = RDAC_QUIESCENCE_TIME; |
| 313 | common->rdac_options = RDAC_FORCED_QUIESENCE; | 317 | common->rdac_options = RDAC_FORCED_QUIESENCE; |
| 314 | 318 | ||
| 319 | list_for_each_entry(qdata, list, entry) { | ||
| 320 | lun_table[qdata->h->lun] = 0x81; | ||
| 321 | } | ||
| 322 | |||
| 315 | /* get request for block layer packet command */ | 323 | /* get request for block layer packet command */ |
| 316 | rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE); | 324 | rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE); |
| 317 | if (!rq) | 325 | if (!rq) |
| @@ -565,7 +573,6 @@ static void send_mode_select(struct work_struct *work) | |||
| 565 | int err, retry_cnt = RDAC_RETRY_COUNT; | 573 | int err, retry_cnt = RDAC_RETRY_COUNT; |
| 566 | struct rdac_queue_data *tmp, *qdata; | 574 | struct rdac_queue_data *tmp, *qdata; |
| 567 | LIST_HEAD(list); | 575 | LIST_HEAD(list); |
| 568 | u8 *lun_table; | ||
| 569 | 576 | ||
| 570 | spin_lock(&ctlr->ms_lock); | 577 | spin_lock(&ctlr->ms_lock); |
| 571 | list_splice_init(&ctlr->ms_head, &list); | 578 | list_splice_init(&ctlr->ms_head, &list); |
| @@ -573,21 +580,12 @@ static void send_mode_select(struct work_struct *work) | |||
| 573 | ctlr->ms_sdev = NULL; | 580 | ctlr->ms_sdev = NULL; |
| 574 | spin_unlock(&ctlr->ms_lock); | 581 | spin_unlock(&ctlr->ms_lock); |
| 575 | 582 | ||
| 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: | 583 | retry: |
| 582 | err = SCSI_DH_RES_TEMP_UNAVAIL; | 584 | err = SCSI_DH_RES_TEMP_UNAVAIL; |
| 583 | rq = rdac_failover_get(sdev, h); | 585 | rq = rdac_failover_get(sdev, h, &list); |
| 584 | if (!rq) | 586 | if (!rq) |
| 585 | goto done; | 587 | goto done; |
| 586 | 588 | ||
| 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, " | 589 | RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " |
| 592 | "%s MODE_SELECT command", | 590 | "%s MODE_SELECT command", |
| 593 | (char *) h->ctlr->array_name, h->ctlr->index, | 591 | (char *) h->ctlr->array_name, h->ctlr->index, |
