diff options
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; |