diff options
author | James.Smart@Emulex.Com <James.Smart@Emulex.Com> | 2005-10-28 20:30:02 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 11:31:48 -0400 |
commit | 0bd4ca25ad2ace4aa717c83dbd4ed21c53c953cb (patch) | |
tree | 10ae769505f9f306ea7a312663011e95019c34ef /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 4a0dfcdefb1cc81c0920dc98fbb82bb57326b16d (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.c | 103 |
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 | ||
68 | struct lpfc_iocbq * | ||
69 | lpfc_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 | |||
68 | void | 78 | void |
69 | lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) | 79 | lpfc_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 | ||
2456 | static int | 2462 | static int |
2457 | lpfc_sli_validate_iocb_cmd(struct lpfc_scsi_buf *lpfc_cmd, uint16_t tgt_id, | 2463 | lpfc_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 | |||
2492 | lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 2507 | lpfc_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; |