aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames.Smart@Emulex.Com <James.Smart@Emulex.Com>2005-11-29 16:32:13 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-13 20:34:14 -0500
commit875fbdfe9b1b4c8f12622a8d8d81428ff0984875 (patch)
tree63c787cb9a7d4a92eaedcc9f8a89a00d5d8f6603 /drivers/scsi/lpfc/lpfc_sli.c
parent5cc36b3cd0e3610ad7c7e2514160998276798fc0 (diff)
[SCSI] lpfc 8.1.1 : Add polled-mode support
- Add functionality to run in polled mode only. Includes run time attribute to enable mode. - Enable runtime writable hba settings for coallescing and delay parameters Customers have requested a mode in the driver to run strictly polled. This is generally to support an environment where the server is extremely loaded and is looking to reclaim some cpu cycles from adapter interrupt handling. This patch adds a new "poll" attribute, and the following behavior: if value is 0 (default): The driver uses the normal method for i/o completion. It uses the firmware feature of interrupt coalesing. The firmware allows a minimum number of i/o completions before an interrupt, or a maximum time delay between interrupts. By default, the driver sets these to no delay (disabled) or 1 i/o - meaning coalescing is disabled. Attributes were provided to change the coalescing values, but it was a module-load time only and global across all adapters. This patch allows them to be writable on a per-adapter basis. if value is 1 : Interrupts are left enabled, expecting that the user has tuned the interrupt coalescing values. When this setting is enabled, the driver will attempt to service completed i/o whenever new i/o is submitted to the adapter. If the coalescing values are large, and the i/o generation rate steady, an interrupt will be avoided by servicing completed i/o prior to the coalescing thresholds kicking in. However, if the i/o completion load is high enough or i/o generation slow, the coalescion values will ensure that completed i/o is serviced in a timely fashion. if value is 3 : Turns off FCP i/o interrupts altogether. The coalescing values now have no effect. A new attribute "poll_tmo" (default 10ms) exists to set the polling interval for i/o completion. When this setting is enabled, the driver will attempt to service completed i/o and restart the interval timer whenever new i/o is submitted. This behavior allows for servicing of completed i/o sooner than the interval timer, but ensures that if no i/o is being issued, then the interval timer will kick in to service the outstanding i/o. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
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