diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-04 19:30:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-04 19:30:12 -0500 |
commit | f61ea1b0c825a20a1826bb43a226387091934586 (patch) | |
tree | fdedf0a2368f707e3fd5205db05bfcbac79606ec /drivers/scsi/lpfc/lpfc_sli.c | |
parent | d347da0deffa1d8f88f0d270eab040e4707c9916 (diff) | |
parent | 7b32b8e018d8f8cc94c808a5fa84a3f889441b91 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 217 |
1 files changed, 196 insertions, 21 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e2c08c5d83fb..7b785ade8b07 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -886,6 +886,182 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, | |||
886 | return rc; | 886 | return rc; |
887 | } | 887 | } |
888 | 888 | ||
889 | static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba, | ||
890 | struct lpfc_sli_ring * pring) | ||
891 | { | ||
892 | struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; | ||
893 | /* | ||
894 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger then | ||
895 | * rsp ring <portRspMax> | ||
896 | */ | ||
897 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
898 | "%d:0312 Ring %d handler: portRspPut %d " | ||
899 | "is bigger then rsp ring %d\n", | ||
900 | phba->brd_no, pring->ringno, | ||
901 | le32_to_cpu(pgp->rspPutInx), | ||
902 | pring->numRiocb); | ||
903 | |||
904 | phba->hba_state = LPFC_HBA_ERROR; | ||
905 | |||
906 | /* | ||
907 | * All error attention handlers are posted to | ||
908 | * worker thread | ||
909 | */ | ||
910 | phba->work_ha |= HA_ERATT; | ||
911 | phba->work_hs = HS_FFER3; | ||
912 | if (phba->work_wait) | ||
913 | wake_up(phba->work_wait); | ||
914 | |||
915 | return; | ||
916 | } | ||
917 | |||
918 | void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba) | ||
919 | { | ||
920 | struct lpfc_sli * psli = &phba->sli; | ||
921 | struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING]; | ||
922 | IOCB_t *irsp = NULL; | ||
923 | IOCB_t *entry = NULL; | ||
924 | struct lpfc_iocbq *cmdiocbq = NULL; | ||
925 | struct lpfc_iocbq rspiocbq; | ||
926 | struct lpfc_pgp *pgp; | ||
927 | uint32_t status; | ||
928 | uint32_t portRspPut, portRspMax; | ||
929 | int type; | ||
930 | uint32_t rsp_cmpl = 0; | ||
931 | void __iomem *to_slim; | ||
932 | uint32_t ha_copy; | ||
933 | |||
934 | pring->stats.iocb_event++; | ||
935 | |||
936 | /* The driver assumes SLI-2 mode */ | ||
937 | pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; | ||
938 | |||
939 | /* | ||
940 | * The next available response entry should never exceed the maximum | ||
941 | * entries. If it does, treat it as an adapter hardware error. | ||
942 | */ | ||
943 | portRspMax = pring->numRiocb; | ||
944 | portRspPut = le32_to_cpu(pgp->rspPutInx); | ||
945 | if (unlikely(portRspPut >= portRspMax)) { | ||
946 | lpfc_sli_rsp_pointers_error(phba, pring); | ||
947 | return; | ||
948 | } | ||
949 | |||
950 | rmb(); | ||
951 | while (pring->rspidx != portRspPut) { | ||
952 | |||
953 | entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); | ||
954 | |||
955 | if (++pring->rspidx >= portRspMax) | ||
956 | pring->rspidx = 0; | ||
957 | |||
958 | lpfc_sli_pcimem_bcopy((uint32_t *) entry, | ||
959 | (uint32_t *) &rspiocbq.iocb, | ||
960 | sizeof (IOCB_t)); | ||
961 | irsp = &rspiocbq.iocb; | ||
962 | type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK); | ||
963 | pring->stats.iocb_rsp++; | ||
964 | rsp_cmpl++; | ||
965 | |||
966 | if (unlikely(irsp->ulpStatus)) { | ||
967 | /* Rsp ring <ringno> error: IOCB */ | ||
968 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
969 | "%d:0326 Rsp Ring %d error: IOCB Data: " | ||
970 | "x%x x%x x%x x%x x%x x%x x%x x%x\n", | ||
971 | phba->brd_no, pring->ringno, | ||
972 | irsp->un.ulpWord[0], | ||
973 | irsp->un.ulpWord[1], | ||
974 | irsp->un.ulpWord[2], | ||
975 | irsp->un.ulpWord[3], | ||
976 | irsp->un.ulpWord[4], | ||
977 | irsp->un.ulpWord[5], | ||
978 | *(((uint32_t *) irsp) + 6), | ||
979 | *(((uint32_t *) irsp) + 7)); | ||
980 | } | ||
981 | |||
982 | switch (type) { | ||
983 | case LPFC_ABORT_IOCB: | ||
984 | case LPFC_SOL_IOCB: | ||
985 | /* | ||
986 | * Idle exchange closed via ABTS from port. No iocb | ||
987 | * resources need to be recovered. | ||
988 | */ | ||
989 | if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) { | ||
990 | printk(KERN_INFO "%s: IOCB cmd 0x%x processed." | ||
991 | " Skipping completion\n", __FUNCTION__, | ||
992 | irsp->ulpCommand); | ||
993 | break; | ||
994 | } | ||
995 | |||
996 | cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, | ||
997 | &rspiocbq); | ||
998 | if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { | ||
999 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, | ||
1000 | &rspiocbq); | ||
1001 | } | ||
1002 | break; | ||
1003 | default: | ||
1004 | if (irsp->ulpCommand == CMD_ADAPTER_MSG) { | ||
1005 | char adaptermsg[LPFC_MAX_ADPTMSG]; | ||
1006 | memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); | ||
1007 | memcpy(&adaptermsg[0], (uint8_t *) irsp, | ||
1008 | MAX_MSG_DATA); | ||
1009 | dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s", | ||
1010 | phba->brd_no, adaptermsg); | ||
1011 | } else { | ||
1012 | /* Unknown IOCB command */ | ||
1013 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
1014 | "%d:0321 Unknown IOCB command " | ||
1015 | "Data: x%x, x%x x%x x%x x%x\n", | ||
1016 | phba->brd_no, type, | ||
1017 | irsp->ulpCommand, | ||
1018 | irsp->ulpStatus, | ||
1019 | irsp->ulpIoTag, | ||
1020 | irsp->ulpContext); | ||
1021 | } | ||
1022 | break; | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | * The response IOCB has been processed. Update the ring | ||
1027 | * pointer in SLIM. If the port response put pointer has not | ||
1028 | * been updated, sync the pgp->rspPutInx and fetch the new port | ||
1029 | * response put pointer. | ||
1030 | */ | ||
1031 | to_slim = phba->MBslimaddr + | ||
1032 | (SLIMOFF + (pring->ringno * 2) + 1) * 4; | ||
1033 | writeb(pring->rspidx, to_slim); | ||
1034 | |||
1035 | if (pring->rspidx == portRspPut) | ||
1036 | portRspPut = le32_to_cpu(pgp->rspPutInx); | ||
1037 | } | ||
1038 | |||
1039 | ha_copy = readl(phba->HAregaddr); | ||
1040 | ha_copy >>= (LPFC_FCP_RING * 4); | ||
1041 | |||
1042 | if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) { | ||
1043 | pring->stats.iocb_rsp_full++; | ||
1044 | status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4)); | ||
1045 | writel(status, phba->CAregaddr); | ||
1046 | readl(phba->CAregaddr); | ||
1047 | } | ||
1048 | if ((ha_copy & HA_R0CE_RSP) && | ||
1049 | (pring->flag & LPFC_CALL_RING_AVAILABLE)) { | ||
1050 | pring->flag &= ~LPFC_CALL_RING_AVAILABLE; | ||
1051 | pring->stats.iocb_cmd_empty++; | ||
1052 | |||
1053 | /* Force update of the local copy of cmdGetInx */ | ||
1054 | pring->local_getidx = le32_to_cpu(pgp->cmdGetInx); | ||
1055 | lpfc_sli_resume_iocb(phba, pring); | ||
1056 | |||
1057 | if ((pring->lpfc_sli_cmd_available)) | ||
1058 | (pring->lpfc_sli_cmd_available) (phba, pring); | ||
1059 | |||
1060 | } | ||
1061 | |||
1062 | return; | ||
1063 | } | ||
1064 | |||
889 | /* | 1065 | /* |
890 | * This routine presumes LPFC_FCP_RING handling and doesn't bother | 1066 | * This routine presumes LPFC_FCP_RING handling and doesn't bother |
891 | * to check it explicitly. | 1067 | * to check it explicitly. |
@@ -917,24 +1093,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
917 | portRspMax = pring->numRiocb; | 1093 | portRspMax = pring->numRiocb; |
918 | portRspPut = le32_to_cpu(pgp->rspPutInx); | 1094 | portRspPut = le32_to_cpu(pgp->rspPutInx); |
919 | if (unlikely(portRspPut >= portRspMax)) { | 1095 | if (unlikely(portRspPut >= portRspMax)) { |
920 | /* | 1096 | lpfc_sli_rsp_pointers_error(phba, pring); |
921 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger then | ||
922 | * rsp ring <portRspMax> | ||
923 | */ | ||
924 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
925 | "%d:0312 Ring %d handler: portRspPut %d " | ||
926 | "is bigger then rsp ring %d\n", | ||
927 | phba->brd_no, pring->ringno, portRspPut, | ||
928 | portRspMax); | ||
929 | |||
930 | phba->hba_state = LPFC_HBA_ERROR; | ||
931 | |||
932 | /* All error attention handlers are posted to worker thread */ | ||
933 | phba->work_ha |= HA_ERATT; | ||
934 | phba->work_hs = HS_FFER3; | ||
935 | if (phba->work_wait) | ||
936 | wake_up(phba->work_wait); | ||
937 | |||
938 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 1097 | spin_unlock_irqrestore(phba->host->host_lock, iflag); |
939 | return 1; | 1098 | return 1; |
940 | } | 1099 | } |
@@ -947,6 +1106,10 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
947 | * network byte order and pci byte orders are different. | 1106 | * network byte order and pci byte orders are different. |
948 | */ | 1107 | */ |
949 | entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); | 1108 | entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); |
1109 | |||
1110 | if (++pring->rspidx >= portRspMax) | ||
1111 | pring->rspidx = 0; | ||
1112 | |||
950 | lpfc_sli_pcimem_bcopy((uint32_t *) entry, | 1113 | lpfc_sli_pcimem_bcopy((uint32_t *) entry, |
951 | (uint32_t *) &rspiocbq.iocb, | 1114 | (uint32_t *) &rspiocbq.iocb, |
952 | sizeof (IOCB_t)); | 1115 | sizeof (IOCB_t)); |
@@ -1020,9 +1183,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
1020 | * been updated, sync the pgp->rspPutInx and fetch the new port | 1183 | * been updated, sync the pgp->rspPutInx and fetch the new port |
1021 | * response put pointer. | 1184 | * response put pointer. |
1022 | */ | 1185 | */ |
1023 | if (++pring->rspidx >= portRspMax) | ||
1024 | pring->rspidx = 0; | ||
1025 | |||
1026 | to_slim = phba->MBslimaddr + | 1186 | to_slim = phba->MBslimaddr + |
1027 | (SLIMOFF + (pring->ringno * 2) + 1) * 4; | 1187 | (SLIMOFF + (pring->ringno * 2) + 1) * 4; |
1028 | writel(pring->rspidx, to_slim); | 1188 | writel(pring->rspidx, to_slim); |
@@ -2615,6 +2775,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, | |||
2615 | DECLARE_WAIT_QUEUE_HEAD(done_q); | 2775 | DECLARE_WAIT_QUEUE_HEAD(done_q); |
2616 | long timeleft, timeout_req = 0; | 2776 | long timeleft, timeout_req = 0; |
2617 | int retval = IOCB_SUCCESS; | 2777 | int retval = IOCB_SUCCESS; |
2778 | uint32_t creg_val; | ||
2618 | 2779 | ||
2619 | /* | 2780 | /* |
2620 | * If the caller has provided a response iocbq buffer, then context2 | 2781 | * If the caller has provided a response iocbq buffer, then context2 |
@@ -2630,6 +2791,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, | |||
2630 | piocb->context_un.wait_queue = &done_q; | 2791 | piocb->context_un.wait_queue = &done_q; |
2631 | piocb->iocb_flag &= ~LPFC_IO_WAKE; | 2792 | piocb->iocb_flag &= ~LPFC_IO_WAKE; |
2632 | 2793 | ||
2794 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | ||
2795 | creg_val = readl(phba->HCregaddr); | ||
2796 | creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING); | ||
2797 | writel(creg_val, phba->HCregaddr); | ||
2798 | readl(phba->HCregaddr); /* flush */ | ||
2799 | } | ||
2800 | |||
2633 | retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0); | 2801 | retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0); |
2634 | if (retval == IOCB_SUCCESS) { | 2802 | if (retval == IOCB_SUCCESS) { |
2635 | timeout_req = timeout * HZ; | 2803 | timeout_req = timeout * HZ; |
@@ -2663,6 +2831,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, | |||
2663 | retval = IOCB_ERROR; | 2831 | retval = IOCB_ERROR; |
2664 | } | 2832 | } |
2665 | 2833 | ||
2834 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | ||
2835 | creg_val = readl(phba->HCregaddr); | ||
2836 | creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING); | ||
2837 | writel(creg_val, phba->HCregaddr); | ||
2838 | readl(phba->HCregaddr); /* flush */ | ||
2839 | } | ||
2840 | |||
2666 | if (prspiocbq) | 2841 | if (prspiocbq) |
2667 | piocb->context2 = NULL; | 2842 | piocb->context2 = NULL; |
2668 | 2843 | ||