aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
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;