aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-04 19:30:12 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-04 19:30:12 -0500
commitf61ea1b0c825a20a1826bb43a226387091934586 (patch)
treefdedf0a2368f707e3fd5205db05bfcbac79606ec /drivers/scsi/lpfc/lpfc_sli.c
parentd347da0deffa1d8f88f0d270eab040e4707c9916 (diff)
parent7b32b8e018d8f8cc94c808a5fa84a3f889441b91 (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.c217
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
889static 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
918void 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