diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 109 |
1 files changed, 79 insertions, 30 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c3e68e0d8f74..9a12d05e99e4 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2006 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -146,6 +146,10 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
146 | 146 | ||
147 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 147 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); |
148 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 148 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); |
149 | if (lpfc_cmd) { | ||
150 | lpfc_cmd->seg_cnt = 0; | ||
151 | lpfc_cmd->nonsg_phys = 0; | ||
152 | } | ||
149 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 153 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); |
150 | return lpfc_cmd; | 154 | return lpfc_cmd; |
151 | } | 155 | } |
@@ -288,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | |||
288 | } | 292 | } |
289 | 293 | ||
290 | static void | 294 | static void |
291 | lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | 295 | lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) |
292 | { | 296 | { |
293 | struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; | 297 | struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; |
294 | struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; | 298 | struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; |
295 | struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; | 299 | struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; |
296 | struct lpfc_hba *phba = lpfc_cmd->scsi_hba; | 300 | struct lpfc_hba *phba = lpfc_cmd->scsi_hba; |
297 | uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; | 301 | uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; |
298 | uint32_t resp_info = fcprsp->rspStatus2; | 302 | uint32_t resp_info = fcprsp->rspStatus2; |
299 | uint32_t scsi_status = fcprsp->rspStatus3; | 303 | uint32_t scsi_status = fcprsp->rspStatus3; |
300 | uint32_t *lp; | 304 | uint32_t *lp; |
@@ -356,6 +360,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
356 | fcpi_parm, cmnd->cmnd[0], cmnd->underflow); | 360 | fcpi_parm, cmnd->cmnd[0], cmnd->underflow); |
357 | 361 | ||
358 | /* | 362 | /* |
363 | * If there is an under run check if under run reported by | ||
364 | * storage array is same as the under run reported by HBA. | ||
365 | * If this is not same, there is a dropped frame. | ||
366 | */ | ||
367 | if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && | ||
368 | fcpi_parm && | ||
369 | (cmnd->resid != fcpi_parm)) { | ||
370 | lpfc_printf_log(phba, KERN_WARNING, | ||
371 | LOG_FCP | LOG_FCP_ERROR, | ||
372 | "%d:0735 FCP Read Check Error and Underrun " | ||
373 | "Data: x%x x%x x%x x%x\n", phba->brd_no, | ||
374 | be32_to_cpu(fcpcmd->fcpDl), | ||
375 | cmnd->resid, | ||
376 | fcpi_parm, cmnd->cmnd[0]); | ||
377 | cmnd->resid = cmnd->request_bufflen; | ||
378 | host_status = DID_ERROR; | ||
379 | } | ||
380 | /* | ||
359 | * The cmnd->underflow is the minimum number of bytes that must | 381 | * The cmnd->underflow is the minimum number of bytes that must |
360 | * be transfered for this command. Provided a sense condition | 382 | * be transfered for this command. Provided a sense condition |
361 | * is not present, make sure the actual amount transferred is at | 383 | * is not present, make sure the actual amount transferred is at |
@@ -435,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
435 | switch (lpfc_cmd->status) { | 457 | switch (lpfc_cmd->status) { |
436 | case IOSTAT_FCP_RSP_ERROR: | 458 | case IOSTAT_FCP_RSP_ERROR: |
437 | /* Call FCP RSP handler to determine result */ | 459 | /* Call FCP RSP handler to determine result */ |
438 | lpfc_handle_fcp_err(lpfc_cmd); | 460 | lpfc_handle_fcp_err(lpfc_cmd,pIocbOut); |
439 | break; | 461 | break; |
440 | case IOSTAT_NPORT_BSY: | 462 | case IOSTAT_NPORT_BSY: |
441 | case IOSTAT_FABRIC_BSY: | 463 | case IOSTAT_FABRIC_BSY: |
@@ -466,10 +488,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
466 | 488 | ||
467 | result = cmd->result; | 489 | result = cmd->result; |
468 | sdev = cmd->device; | 490 | sdev = cmd->device; |
491 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); | ||
469 | cmd->scsi_done(cmd); | 492 | cmd->scsi_done(cmd); |
470 | 493 | ||
471 | if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { | 494 | if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { |
472 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); | ||
473 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 495 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
474 | return; | 496 | return; |
475 | } | 497 | } |
@@ -527,7 +549,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
527 | } | 549 | } |
528 | } | 550 | } |
529 | 551 | ||
530 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); | ||
531 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 552 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
532 | } | 553 | } |
533 | 554 | ||
@@ -670,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, | |||
670 | return (1); | 691 | return (1); |
671 | } | 692 | } |
672 | 693 | ||
694 | static void | ||
695 | lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, | ||
696 | struct lpfc_iocbq *cmdiocbq, | ||
697 | struct lpfc_iocbq *rspiocbq) | ||
698 | { | ||
699 | struct lpfc_scsi_buf *lpfc_cmd = | ||
700 | (struct lpfc_scsi_buf *) cmdiocbq->context1; | ||
701 | if (lpfc_cmd) | ||
702 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
703 | return; | ||
704 | } | ||
705 | |||
673 | static int | 706 | static int |
674 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, | 707 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, |
675 | unsigned tgt_id, unsigned int lun, | 708 | unsigned tgt_id, unsigned int lun, |
@@ -706,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, | |||
706 | &phba->sli.ring[phba->sli.fcp_ring], | 739 | &phba->sli.ring[phba->sli.fcp_ring], |
707 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 740 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
708 | if (ret != IOCB_SUCCESS) { | 741 | if (ret != IOCB_SUCCESS) { |
742 | if (ret == IOCB_TIMEDOUT) | ||
743 | iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; | ||
709 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 744 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; |
710 | ret = FAILED; | ||
711 | } else { | 745 | } else { |
712 | ret = SUCCESS; | 746 | ret = SUCCESS; |
713 | lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; | 747 | lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; |
@@ -974,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
974 | } | 1008 | } |
975 | 1009 | ||
976 | static int | 1010 | static int |
977 | lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | 1011 | lpfc_device_reset_handler(struct scsi_cmnd *cmnd) |
978 | { | 1012 | { |
979 | struct Scsi_Host *shost = cmnd->device->host; | 1013 | struct Scsi_Host *shost = cmnd->device->host; |
980 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; | 1014 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; |
@@ -984,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
984 | struct lpfc_nodelist *pnode = rdata->pnode; | 1018 | struct lpfc_nodelist *pnode = rdata->pnode; |
985 | uint32_t cmd_result = 0, cmd_status = 0; | 1019 | uint32_t cmd_result = 0, cmd_status = 0; |
986 | int ret = FAILED; | 1020 | int ret = FAILED; |
1021 | int iocb_status = IOCB_SUCCESS; | ||
987 | int cnt, loopcnt; | 1022 | int cnt, loopcnt; |
988 | 1023 | ||
989 | lpfc_block_error_handler(cmnd); | 1024 | lpfc_block_error_handler(cmnd); |
@@ -995,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
995 | */ | 1030 | */ |
996 | while ( 1 ) { | 1031 | while ( 1 ) { |
997 | if (!pnode) | 1032 | if (!pnode) |
998 | return FAILED; | 1033 | goto out; |
999 | 1034 | ||
1000 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { | 1035 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { |
1001 | spin_unlock_irq(phba->host->host_lock); | 1036 | spin_unlock_irq(phba->host->host_lock); |
@@ -1013,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1013 | } | 1048 | } |
1014 | pnode = rdata->pnode; | 1049 | pnode = rdata->pnode; |
1015 | if (!pnode) | 1050 | if (!pnode) |
1016 | return FAILED; | 1051 | goto out; |
1017 | } | 1052 | } |
1018 | if (pnode->nlp_state == NLP_STE_MAPPED_NODE) | 1053 | if (pnode->nlp_state == NLP_STE_MAPPED_NODE) |
1019 | break; | 1054 | break; |
@@ -1028,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1028 | lpfc_cmd->rdata = rdata; | 1063 | lpfc_cmd->rdata = rdata; |
1029 | 1064 | ||
1030 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, | 1065 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, |
1031 | FCP_LUN_RESET); | 1066 | FCP_TARGET_RESET); |
1032 | if (!ret) | 1067 | if (!ret) |
1033 | goto out_free_scsi_buf; | 1068 | goto out_free_scsi_buf; |
1034 | 1069 | ||
@@ -1040,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1040 | goto out_free_scsi_buf; | 1075 | goto out_free_scsi_buf; |
1041 | 1076 | ||
1042 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | 1077 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, |
1043 | "%d:0703 Issue LUN Reset to TGT %d LUN %d " | 1078 | "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x " |
1044 | "Data: x%x x%x\n", phba->brd_no, cmnd->device->id, | 1079 | "nlp_flag x%x\n", phba->brd_no, cmnd->device->id, |
1045 | cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); | 1080 | cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); |
1046 | 1081 | ||
1047 | ret = lpfc_sli_issue_iocb_wait(phba, | 1082 | iocb_status = lpfc_sli_issue_iocb_wait(phba, |
1048 | &phba->sli.ring[phba->sli.fcp_ring], | 1083 | &phba->sli.ring[phba->sli.fcp_ring], |
1049 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 1084 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
1050 | if (ret == IOCB_SUCCESS) | ||
1051 | ret = SUCCESS; | ||
1052 | 1085 | ||
1086 | if (iocb_status == IOCB_TIMEDOUT) | ||
1087 | iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; | ||
1088 | |||
1089 | if (iocb_status == IOCB_SUCCESS) | ||
1090 | ret = SUCCESS; | ||
1091 | else | ||
1092 | ret = iocb_status; | ||
1053 | 1093 | ||
1054 | cmd_result = iocbqrsp->iocb.un.ulpWord[4]; | 1094 | cmd_result = iocbqrsp->iocb.un.ulpWord[4]; |
1055 | cmd_status = iocbqrsp->iocb.ulpStatus; | 1095 | cmd_status = iocbqrsp->iocb.ulpStatus; |
@@ -1087,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1087 | 1127 | ||
1088 | if (cnt) { | 1128 | if (cnt) { |
1089 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1129 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1090 | "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", | 1130 | "%d:0719 device reset I/O flush failure: cnt x%x\n", |
1091 | phba->brd_no, cnt); | 1131 | phba->brd_no, cnt); |
1092 | ret = FAILED; | 1132 | ret = FAILED; |
1093 | } | 1133 | } |
1094 | 1134 | ||
1095 | out_free_scsi_buf: | 1135 | out_free_scsi_buf: |
1096 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 1136 | if (iocb_status != IOCB_TIMEDOUT) { |
1097 | 1137 | lpfc_release_scsi_buf(phba, lpfc_cmd); | |
1138 | } | ||
1098 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1139 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1099 | "%d:0713 SCSI layer issued LUN reset (%d, %d) " | 1140 | "%d:0713 SCSI layer issued device reset (%d, %d) " |
1100 | "Data: x%x x%x x%x\n", | 1141 | "return x%x status x%x result x%x\n", |
1101 | phba->brd_no, cmnd->device->id,cmnd->device->lun, | 1142 | phba->brd_no, cmnd->device->id, cmnd->device->lun, |
1102 | ret, cmd_status, cmd_result); | 1143 | ret, cmd_status, cmd_result); |
1103 | 1144 | ||
1104 | out: | 1145 | out: |
@@ -1107,7 +1148,7 @@ out: | |||
1107 | } | 1148 | } |
1108 | 1149 | ||
1109 | static int | 1150 | static int |
1110 | lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | 1151 | lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) |
1111 | { | 1152 | { |
1112 | struct Scsi_Host *shost = cmnd->device->host; | 1153 | struct Scsi_Host *shost = cmnd->device->host; |
1113 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; | 1154 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; |
@@ -1134,10 +1175,12 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1134 | * fail, this routine returns failure to the midlayer. | 1175 | * fail, this routine returns failure to the midlayer. |
1135 | */ | 1176 | */ |
1136 | for (i = 0; i < LPFC_MAX_TARGET; i++) { | 1177 | for (i = 0; i < LPFC_MAX_TARGET; i++) { |
1137 | /* Search the mapped list for this target ID */ | 1178 | /* Search for mapped node by target ID */ |
1138 | match = 0; | 1179 | match = 0; |
1139 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | 1180 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
1140 | if ((i == ndlp->nlp_sid) && ndlp->rport) { | 1181 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && |
1182 | i == ndlp->nlp_sid && | ||
1183 | ndlp->rport) { | ||
1141 | match = 1; | 1184 | match = 1; |
1142 | break; | 1185 | break; |
1143 | } | 1186 | } |
@@ -1152,13 +1195,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1152 | "%d:0700 Bus Reset on target %d failed\n", | 1195 | "%d:0700 Bus Reset on target %d failed\n", |
1153 | phba->brd_no, i); | 1196 | phba->brd_no, i); |
1154 | err_count++; | 1197 | err_count++; |
1198 | break; | ||
1155 | } | 1199 | } |
1156 | } | 1200 | } |
1157 | 1201 | ||
1202 | if (ret != IOCB_TIMEDOUT) | ||
1203 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
1204 | |||
1158 | if (err_count == 0) | 1205 | if (err_count == 0) |
1159 | ret = SUCCESS; | 1206 | ret = SUCCESS; |
1160 | 1207 | else | |
1161 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 1208 | ret = FAILED; |
1162 | 1209 | ||
1163 | /* | 1210 | /* |
1164 | * All outstanding txcmplq I/Os should have been aborted by | 1211 | * All outstanding txcmplq I/Os should have been aborted by |
@@ -1299,11 +1346,13 @@ struct scsi_host_template lpfc_template = { | |||
1299 | .info = lpfc_info, | 1346 | .info = lpfc_info, |
1300 | .queuecommand = lpfc_queuecommand, | 1347 | .queuecommand = lpfc_queuecommand, |
1301 | .eh_abort_handler = lpfc_abort_handler, | 1348 | .eh_abort_handler = lpfc_abort_handler, |
1302 | .eh_device_reset_handler= lpfc_reset_lun_handler, | 1349 | .eh_device_reset_handler= lpfc_device_reset_handler, |
1303 | .eh_bus_reset_handler = lpfc_reset_bus_handler, | 1350 | .eh_bus_reset_handler = lpfc_bus_reset_handler, |
1304 | .slave_alloc = lpfc_slave_alloc, | 1351 | .slave_alloc = lpfc_slave_alloc, |
1305 | .slave_configure = lpfc_slave_configure, | 1352 | .slave_configure = lpfc_slave_configure, |
1306 | .slave_destroy = lpfc_slave_destroy, | 1353 | .slave_destroy = lpfc_slave_destroy, |
1354 | .scan_finished = lpfc_scan_finished, | ||
1355 | .scan_start = lpfc_scan_start, | ||
1307 | .this_id = -1, | 1356 | .this_id = -1, |
1308 | .sg_tablesize = LPFC_SG_SEG_CNT, | 1357 | .sg_tablesize = LPFC_SG_SEG_CNT, |
1309 | .cmd_per_lun = LPFC_CMD_PER_LUN, | 1358 | .cmd_per_lun = LPFC_CMD_PER_LUN, |