diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 109 |
1 files changed, 56 insertions, 53 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5a2cb484e13..584c5451641 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -955,6 +955,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
955 | match = 0; | 955 | match = 0; |
956 | irsp = &(saveq->iocb); | 956 | irsp = &(saveq->iocb); |
957 | 957 | ||
958 | if (irsp->ulpStatus == IOSTAT_NEED_BUFFER) | ||
959 | return 1; | ||
958 | if (irsp->ulpCommand == CMD_ASYNC_STATUS) { | 960 | if (irsp->ulpCommand == CMD_ASYNC_STATUS) { |
959 | if (pring->lpfc_sli_rcv_async_status) | 961 | if (pring->lpfc_sli_rcv_async_status) |
960 | pring->lpfc_sli_rcv_async_status(phba, pring, saveq); | 962 | pring->lpfc_sli_rcv_async_status(phba, pring, saveq); |
@@ -970,36 +972,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
970 | return 1; | 972 | return 1; |
971 | } | 973 | } |
972 | 974 | ||
973 | if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) | ||
974 | || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) | ||
975 | || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX) | ||
976 | || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) { | ||
977 | Rctl = FC_ELS_REQ; | ||
978 | Type = FC_ELS_DATA; | ||
979 | } else { | ||
980 | w5p = | ||
981 | (WORD5 *) & (saveq->iocb.un. | ||
982 | ulpWord[5]); | ||
983 | Rctl = w5p->hcsw.Rctl; | ||
984 | Type = w5p->hcsw.Type; | ||
985 | |||
986 | /* Firmware Workaround */ | ||
987 | if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) && | ||
988 | (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX || | ||
989 | irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { | ||
990 | Rctl = FC_ELS_REQ; | ||
991 | Type = FC_ELS_DATA; | ||
992 | w5p->hcsw.Rctl = Rctl; | ||
993 | w5p->hcsw.Type = Type; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 975 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
998 | struct lpfc_hbq_entry *hbqe_1, *hbqe_2; | ||
999 | hbqe_1 = (struct lpfc_hbq_entry *) &saveq->iocb.un.ulpWord[0]; | ||
1000 | hbqe_2 = (struct lpfc_hbq_entry *) &saveq->iocb. | ||
1001 | unsli3.sli3Words[4]; | ||
1002 | |||
1003 | if (irsp->ulpBdeCount != 0) { | 976 | if (irsp->ulpBdeCount != 0) { |
1004 | saveq->context2 = lpfc_sli_get_buff(phba, pring, | 977 | saveq->context2 = lpfc_sli_get_buff(phba, pring, |
1005 | irsp->un.ulpWord[3]); | 978 | irsp->un.ulpWord[3]); |
@@ -1011,7 +984,6 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1011 | "an unsolicited iocb. tag 0x%x\n", | 984 | "an unsolicited iocb. tag 0x%x\n", |
1012 | pring->ringno, | 985 | pring->ringno, |
1013 | irsp->un.ulpWord[3]); | 986 | irsp->un.ulpWord[3]); |
1014 | |||
1015 | } | 987 | } |
1016 | if (irsp->ulpBdeCount == 2) { | 988 | if (irsp->ulpBdeCount == 2) { |
1017 | saveq->context3 = lpfc_sli_get_buff(phba, pring, | 989 | saveq->context3 = lpfc_sli_get_buff(phba, pring, |
@@ -1026,16 +998,11 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1026 | irsp->unsli3.sli3Words[7]); | 998 | irsp->unsli3.sli3Words[7]); |
1027 | } | 999 | } |
1028 | list_for_each_entry(iocbq, &saveq->list, list) { | 1000 | list_for_each_entry(iocbq, &saveq->list, list) { |
1029 | hbqe_1 = (struct lpfc_hbq_entry *) &iocbq->iocb. | ||
1030 | un.ulpWord[0]; | ||
1031 | hbqe_2 = (struct lpfc_hbq_entry *) &iocbq->iocb. | ||
1032 | unsli3.sli3Words[4]; | ||
1033 | irsp = &(iocbq->iocb); | 1001 | irsp = &(iocbq->iocb); |
1034 | |||
1035 | if (irsp->ulpBdeCount != 0) { | 1002 | if (irsp->ulpBdeCount != 0) { |
1036 | iocbq->context2 = lpfc_sli_get_buff(phba, pring, | 1003 | iocbq->context2 = lpfc_sli_get_buff(phba, pring, |
1037 | irsp->un.ulpWord[3]); | 1004 | irsp->un.ulpWord[3]); |
1038 | if (!saveq->context2) | 1005 | if (!iocbq->context2) |
1039 | lpfc_printf_log(phba, | 1006 | lpfc_printf_log(phba, |
1040 | KERN_ERR, | 1007 | KERN_ERR, |
1041 | LOG_SLI, | 1008 | LOG_SLI, |
@@ -1047,7 +1014,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1047 | if (irsp->ulpBdeCount == 2) { | 1014 | if (irsp->ulpBdeCount == 2) { |
1048 | iocbq->context3 = lpfc_sli_get_buff(phba, pring, | 1015 | iocbq->context3 = lpfc_sli_get_buff(phba, pring, |
1049 | irsp->unsli3.sli3Words[7]); | 1016 | irsp->unsli3.sli3Words[7]); |
1050 | if (!saveq->context3) | 1017 | if (!iocbq->context3) |
1051 | lpfc_printf_log(phba, | 1018 | lpfc_printf_log(phba, |
1052 | KERN_ERR, | 1019 | KERN_ERR, |
1053 | LOG_SLI, | 1020 | LOG_SLI, |
@@ -1059,6 +1026,49 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1059 | } | 1026 | } |
1060 | } | 1027 | } |
1061 | } | 1028 | } |
1029 | if (irsp->ulpBdeCount != 0 && | ||
1030 | (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX || | ||
1031 | irsp->ulpStatus == IOSTAT_INTERMED_RSP)) { | ||
1032 | int found = 0; | ||
1033 | |||
1034 | /* search continue save q for same XRI */ | ||
1035 | list_for_each_entry(iocbq, &pring->iocb_continue_saveq, clist) { | ||
1036 | if (iocbq->iocb.ulpContext == saveq->iocb.ulpContext) { | ||
1037 | list_add_tail(&saveq->list, &iocbq->list); | ||
1038 | found = 1; | ||
1039 | break; | ||
1040 | } | ||
1041 | } | ||
1042 | if (!found) | ||
1043 | list_add_tail(&saveq->clist, | ||
1044 | &pring->iocb_continue_saveq); | ||
1045 | if (saveq->iocb.ulpStatus != IOSTAT_INTERMED_RSP) { | ||
1046 | list_del_init(&iocbq->clist); | ||
1047 | saveq = iocbq; | ||
1048 | irsp = &(saveq->iocb); | ||
1049 | } else | ||
1050 | return 0; | ||
1051 | } | ||
1052 | if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) || | ||
1053 | (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) || | ||
1054 | (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)) { | ||
1055 | Rctl = FC_ELS_REQ; | ||
1056 | Type = FC_ELS_DATA; | ||
1057 | } else { | ||
1058 | w5p = (WORD5 *)&(saveq->iocb.un.ulpWord[5]); | ||
1059 | Rctl = w5p->hcsw.Rctl; | ||
1060 | Type = w5p->hcsw.Type; | ||
1061 | |||
1062 | /* Firmware Workaround */ | ||
1063 | if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) && | ||
1064 | (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX || | ||
1065 | irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) { | ||
1066 | Rctl = FC_ELS_REQ; | ||
1067 | Type = FC_ELS_DATA; | ||
1068 | w5p->hcsw.Rctl = Rctl; | ||
1069 | w5p->hcsw.Type = Type; | ||
1070 | } | ||
1071 | } | ||
1062 | 1072 | ||
1063 | /* unSolicited Responses */ | 1073 | /* unSolicited Responses */ |
1064 | if (pring->prt[0].profile) { | 1074 | if (pring->prt[0].profile) { |
@@ -1069,12 +1079,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1069 | } else { | 1079 | } else { |
1070 | /* We must search, based on rctl / type | 1080 | /* We must search, based on rctl / type |
1071 | for the right routine */ | 1081 | for the right routine */ |
1072 | for (i = 0; i < pring->num_mask; | 1082 | for (i = 0; i < pring->num_mask; i++) { |
1073 | i++) { | 1083 | if ((pring->prt[i].rctl == Rctl) |
1074 | if ((pring->prt[i].rctl == | 1084 | && (pring->prt[i].type == Type)) { |
1075 | Rctl) | ||
1076 | && (pring->prt[i]. | ||
1077 | type == Type)) { | ||
1078 | if (pring->prt[i].lpfc_sli_rcv_unsol_event) | 1085 | if (pring->prt[i].lpfc_sli_rcv_unsol_event) |
1079 | (pring->prt[i].lpfc_sli_rcv_unsol_event) | 1086 | (pring->prt[i].lpfc_sli_rcv_unsol_event) |
1080 | (phba, pring, saveq); | 1087 | (phba, pring, saveq); |
@@ -1641,12 +1648,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, | |||
1641 | 1648 | ||
1642 | writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx); | 1649 | writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx); |
1643 | 1650 | ||
1644 | if (list_empty(&(pring->iocb_continueq))) { | 1651 | list_add_tail(&rspiocbp->list, &(pring->iocb_continueq)); |
1645 | list_add(&rspiocbp->list, &(pring->iocb_continueq)); | ||
1646 | } else { | ||
1647 | list_add_tail(&rspiocbp->list, | ||
1648 | &(pring->iocb_continueq)); | ||
1649 | } | ||
1650 | 1652 | ||
1651 | pring->iocb_continueq_cnt++; | 1653 | pring->iocb_continueq_cnt++; |
1652 | if (irsp->ulpLe) { | 1654 | if (irsp->ulpLe) { |
@@ -1711,17 +1713,17 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, | |||
1711 | iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; | 1713 | iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; |
1712 | type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); | 1714 | type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); |
1713 | if (type == LPFC_SOL_IOCB) { | 1715 | if (type == LPFC_SOL_IOCB) { |
1714 | spin_unlock_irqrestore(&phba->hbalock, | 1716 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
1715 | iflag); | ||
1716 | rc = lpfc_sli_process_sol_iocb(phba, pring, | 1717 | rc = lpfc_sli_process_sol_iocb(phba, pring, |
1717 | saveq); | 1718 | saveq); |
1718 | spin_lock_irqsave(&phba->hbalock, iflag); | 1719 | spin_lock_irqsave(&phba->hbalock, iflag); |
1719 | } else if (type == LPFC_UNSOL_IOCB) { | 1720 | } else if (type == LPFC_UNSOL_IOCB) { |
1720 | spin_unlock_irqrestore(&phba->hbalock, | 1721 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
1721 | iflag); | ||
1722 | rc = lpfc_sli_process_unsol_iocb(phba, pring, | 1722 | rc = lpfc_sli_process_unsol_iocb(phba, pring, |
1723 | saveq); | 1723 | saveq); |
1724 | spin_lock_irqsave(&phba->hbalock, iflag); | 1724 | spin_lock_irqsave(&phba->hbalock, iflag); |
1725 | if (!rc) | ||
1726 | free_saveq = 0; | ||
1725 | } else if (type == LPFC_ABORT_IOCB) { | 1727 | } else if (type == LPFC_ABORT_IOCB) { |
1726 | if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) && | 1728 | if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) && |
1727 | ((cmdiocbp = | 1729 | ((cmdiocbp = |
@@ -3238,6 +3240,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba) | |||
3238 | INIT_LIST_HEAD(&pring->txq); | 3240 | INIT_LIST_HEAD(&pring->txq); |
3239 | INIT_LIST_HEAD(&pring->txcmplq); | 3241 | INIT_LIST_HEAD(&pring->txcmplq); |
3240 | INIT_LIST_HEAD(&pring->iocb_continueq); | 3242 | INIT_LIST_HEAD(&pring->iocb_continueq); |
3243 | INIT_LIST_HEAD(&pring->iocb_continue_saveq); | ||
3241 | INIT_LIST_HEAD(&pring->postbufq); | 3244 | INIT_LIST_HEAD(&pring->postbufq); |
3242 | } | 3245 | } |
3243 | spin_unlock_irq(&phba->hbalock); | 3246 | spin_unlock_irq(&phba->hbalock); |