aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames.Smart@Emulex.Com <James.Smart@Emulex.Com>2005-10-28 20:30:02 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-29 11:31:48 -0400
commit0bd4ca25ad2ace4aa717c83dbd4ed21c53c953cb (patch)
tree10ae769505f9f306ea7a312663011e95019c34ef /drivers/scsi/lpfc/lpfc_sli.c
parent4a0dfcdefb1cc81c0920dc98fbb82bb57326b16d (diff)
[SCSI] lpfc: Fix eh_ return codes for commands
Return FAILED from eh_ routines if command(s) is(are) not completed There were scenarios where we may have returned from the error handlers prior to all affected commands being flushed to the midlayer. Add changes to ensure this doesn't happen. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c103
1 files changed, 47 insertions, 56 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index b53ed3abc6c9..508710001ed6 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -65,6 +65,16 @@ typedef enum _lpfc_iocb_type {
65 LPFC_ABORT_IOCB 65 LPFC_ABORT_IOCB
66} lpfc_iocb_type; 66} lpfc_iocb_type;
67 67
68struct lpfc_iocbq *
69lpfc_sli_get_iocbq(struct lpfc_hba * phba)
70{
71 struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
72 struct lpfc_iocbq * iocbq = NULL;
73
74 list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list);
75 return iocbq;
76}
77
68void 78void
69lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) 79lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
70{ 80{
@@ -1055,7 +1065,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
1055 struct lpfc_iocbq *next_iocb; 1065 struct lpfc_iocbq *next_iocb;
1056 struct lpfc_iocbq *cmdiocbp; 1066 struct lpfc_iocbq *cmdiocbp;
1057 struct lpfc_iocbq *saveq; 1067 struct lpfc_iocbq *saveq;
1058 struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
1059 struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; 1068 struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
1060 uint8_t iocb_cmd_type; 1069 uint8_t iocb_cmd_type;
1061 lpfc_iocb_type type; 1070 lpfc_iocb_type type;
@@ -1097,7 +1106,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
1097 } 1106 }
1098 1107
1099 rmb(); 1108 rmb();
1100 lpfc_iocb_list = &phba->lpfc_iocb_list;
1101 while (pring->rspidx != portRspPut) { 1109 while (pring->rspidx != portRspPut) {
1102 /* 1110 /*
1103 * Build a completion list and call the appropriate handler. 1111 * Build a completion list and call the appropriate handler.
@@ -1113,8 +1121,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
1113 * received. 1121 * received.
1114 */ 1122 */
1115 entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); 1123 entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
1116 list_remove_head(lpfc_iocb_list, rspiocbp, struct lpfc_iocbq, 1124 rspiocbp = lpfc_sli_get_iocbq(phba);
1117 list);
1118 if (rspiocbp == NULL) { 1125 if (rspiocbp == NULL) {
1119 printk(KERN_ERR "%s: out of buffers! Failing " 1126 printk(KERN_ERR "%s: out of buffers! Failing "
1120 "completion.\n", __FUNCTION__); 1127 "completion.\n", __FUNCTION__);
@@ -2407,13 +2414,12 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
2407 struct lpfc_sli_ring * pring, 2414 struct lpfc_sli_ring * pring,
2408 struct lpfc_iocbq * cmdiocb) 2415 struct lpfc_iocbq * cmdiocb)
2409{ 2416{
2410 struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; 2417 struct lpfc_iocbq *abtsiocbp;
2411 struct lpfc_iocbq *abtsiocbp = NULL;
2412 IOCB_t *icmd = NULL; 2418 IOCB_t *icmd = NULL;
2413 IOCB_t *iabt = NULL; 2419 IOCB_t *iabt = NULL;
2414 2420
2415 /* issue ABTS for this IOCB based on iotag */ 2421 /* issue ABTS for this IOCB based on iotag */
2416 list_remove_head(lpfc_iocb_list, abtsiocbp, struct lpfc_iocbq, list); 2422 abtsiocbp = lpfc_sli_get_iocbq(phba);
2417 if (abtsiocbp == NULL) 2423 if (abtsiocbp == NULL)
2418 return 0; 2424 return 0;
2419 2425
@@ -2454,28 +2460,37 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
2454} 2460}
2455 2461
2456static int 2462static int
2457lpfc_sli_validate_iocb_cmd(struct lpfc_scsi_buf *lpfc_cmd, uint16_t tgt_id, 2463lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
2458 uint64_t lun_id, struct lpfc_iocbq *iocb, 2464 uint64_t lun_id, uint32_t ctx,
2459 uint32_t ctx, lpfc_ctx_cmd ctx_cmd) 2465 lpfc_ctx_cmd ctx_cmd)
2460{ 2466{
2467 struct lpfc_scsi_buf *lpfc_cmd;
2468 struct scsi_cmnd *cmnd;
2461 int rc = 1; 2469 int rc = 1;
2462 2470
2463 if (lpfc_cmd == NULL) 2471 if (!(iocbq->iocb_flag & LPFC_IO_FCP))
2472 return rc;
2473
2474 lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
2475 cmnd = lpfc_cmd->pCmd;
2476
2477 if (cmnd == NULL)
2464 return rc; 2478 return rc;
2465 2479
2466 switch (ctx_cmd) { 2480 switch (ctx_cmd) {
2467 case LPFC_CTX_LUN: 2481 case LPFC_CTX_LUN:
2468 if ((lpfc_cmd->pCmd->device->id == tgt_id) && 2482 if ((cmnd->device->id == tgt_id) &&
2469 (lpfc_cmd->pCmd->device->lun == lun_id)) 2483 (cmnd->device->lun == lun_id))
2470 rc = 0; 2484 rc = 0;
2471 break; 2485 break;
2472 case LPFC_CTX_TGT: 2486 case LPFC_CTX_TGT:
2473 if (lpfc_cmd->pCmd->device->id == tgt_id) 2487 if (cmnd->device->id == tgt_id)
2474 rc = 0; 2488 rc = 0;
2475 break; 2489 break;
2476 case LPFC_CTX_CTX: 2490 case LPFC_CTX_CTX:
2477 if (iocb->iocb.ulpContext == ctx) 2491 if (iocbq->iocb.ulpContext == ctx)
2478 rc = 0; 2492 rc = 0;
2493 break;
2479 case LPFC_CTX_HOST: 2494 case LPFC_CTX_HOST:
2480 rc = 0; 2495 rc = 0;
2481 break; 2496 break;
@@ -2492,30 +2507,17 @@ int
2492lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 2507lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
2493 uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) 2508 uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
2494{ 2509{
2495 struct lpfc_iocbq *iocb, *next_iocb; 2510 struct lpfc_iocbq *iocbq;
2496 IOCB_t *cmd = NULL; 2511 int sum, i;
2497 struct lpfc_scsi_buf *lpfc_cmd;
2498 int sum = 0, ret_val = 0;
2499 2512
2500 /* Next check the txcmplq */ 2513 for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) {
2501 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { 2514 iocbq = phba->sli.iocbq_lookup[i];
2502 cmd = &iocb->iocb;
2503
2504 /* Must be a FCP command */
2505 if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) &&
2506 (cmd->ulpCommand != CMD_FCP_IWRITE64_CR) &&
2507 (cmd->ulpCommand != CMD_FCP_IREAD64_CR)) {
2508 continue;
2509 }
2510 2515
2511 /* context1 MUST be a struct lpfc_scsi_buf */ 2516 if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
2512 lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1); 2517 0, ctx_cmd) == 0)
2513 ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id, 2518 sum++;
2514 NULL, 0, ctx_cmd);
2515 if (ret_val != 0)
2516 continue;
2517 sum++;
2518 } 2519 }
2520
2519 return sum; 2521 return sum;
2520} 2522}
2521 2523
@@ -2534,38 +2536,27 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
2534 uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, 2536 uint16_t tgt_id, uint64_t lun_id, uint32_t ctx,
2535 lpfc_ctx_cmd abort_cmd) 2537 lpfc_ctx_cmd abort_cmd)
2536{ 2538{
2537 struct lpfc_iocbq *iocb, *next_iocb; 2539 struct lpfc_iocbq *iocbq;
2538 struct lpfc_iocbq *abtsiocb = NULL; 2540 struct lpfc_iocbq *abtsiocb;
2539 struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
2540 IOCB_t *cmd = NULL; 2541 IOCB_t *cmd = NULL;
2541 struct lpfc_scsi_buf *lpfc_cmd;
2542 int errcnt = 0, ret_val = 0; 2542 int errcnt = 0, ret_val = 0;
2543 int i;
2543 2544
2544 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { 2545 for (i = 1; i <= phba->sli.last_iotag; i++) {
2545 cmd = &iocb->iocb; 2546 iocbq = phba->sli.iocbq_lookup[i];
2546
2547 /* Must be a FCP command */
2548 if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) &&
2549 (cmd->ulpCommand != CMD_FCP_IWRITE64_CR) &&
2550 (cmd->ulpCommand != CMD_FCP_IREAD64_CR)) {
2551 continue;
2552 }
2553 2547
2554 /* context1 MUST be a struct lpfc_scsi_buf */ 2548 if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
2555 lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1); 2549 0, abort_cmd) != 0)
2556 ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id,
2557 iocb, ctx, abort_cmd);
2558 if (ret_val != 0)
2559 continue; 2550 continue;
2560 2551
2561 /* issue ABTS for this IOCB based on iotag */ 2552 /* issue ABTS for this IOCB based on iotag */
2562 list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq, 2553 abtsiocb = lpfc_sli_get_iocbq(phba);
2563 list);
2564 if (abtsiocb == NULL) { 2554 if (abtsiocb == NULL) {
2565 errcnt++; 2555 errcnt++;
2566 continue; 2556 continue;
2567 } 2557 }
2568 2558
2559 cmd = &iocbq->iocb;
2569 abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; 2560 abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS;
2570 abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; 2561 abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext;
2571 abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag; 2562 abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;