aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Reed <mdr@sgi.com>2006-05-24 16:07:24 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-10 16:59:19 -0400
commitca2f938efe71ca48cbc689db4df8d4f04b5d8f07 (patch)
tree044df117f00aa7838d83a78aa40ed41c1f0baf31
parent80d3ac77a84987d5132726f3d7cef342a280f7d9 (diff)
[SCSI] mptfc: set fibre channel fw target missing timers to one second
The fibre channel firmware provides a timer which is similar in purpose to the fibre channel transport's device loss timer. The effect of this timer is to extend the total time that a target will be missing beyond the value associated with the transport's timer. This patch changes the firmware timer to a default of one second which significantly reduces the lag between when a target goes missing and the notification of the fibre channel transport. Signed-off-by: Michael Reed <mdr@sgi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/message/fusion/mptbase.h10
-rw-r--r--drivers/message/fusion/mptfc.c171
2 files changed, 172 insertions, 9 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 693c95c9034a..29f6b986946f 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -487,6 +487,15 @@ typedef struct _RaidCfgData {
487 int isRaid; /* bit field, 1 if RAID */ 487 int isRaid; /* bit field, 1 if RAID */
488}RaidCfgData; 488}RaidCfgData;
489 489
490typedef struct _FcCfgData {
491 /* will ultimately hold fc_port_page0 also */
492 struct {
493 FCPortPage1_t *data;
494 dma_addr_t dma;
495 int pg_sz;
496 } fc_port_page1[2];
497} FcCfgData;
498
490#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ 499#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
491#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ 500#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
492 501
@@ -565,6 +574,7 @@ typedef struct _MPT_ADAPTER
565 SpiCfgData spi_data; /* Scsi config. data */ 574 SpiCfgData spi_data; /* Scsi config. data */
566 RaidCfgData raid_data; /* Raid config. data */ 575 RaidCfgData raid_data; /* Raid config. data */
567 SasCfgData sas_data; /* Sas config. data */ 576 SasCfgData sas_data; /* Sas config. data */
577 FcCfgData fc_data; /* Fc config. data */
568 MPT_IOCTL *ioctl; /* ioctl data pointer */ 578 MPT_IOCTL *ioctl; /* ioctl data pointer */
569 struct proc_dir_entry *ioc_dentry; 579 struct proc_dir_entry *ioc_dentry;
570 struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ 580 struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index e518bc97f8ce..918aca0146ff 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -169,13 +169,6 @@ static struct fc_function_template mptfc_transport_functions = {
169 169
170}; 170};
171 171
172/* FIXME! values controlling firmware RESCAN event
173 * need to be set low to allow dev_loss_tmo to
174 * work as expected. Currently, firmware doesn't
175 * notify driver of RESCAN event until some number
176 * of seconds elapse. This value can be set via
177 * lsiutil.
178 */
179static void 172static void
180mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 173mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
181{ 174{
@@ -700,6 +693,153 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
700 return rc; 693 return rc;
701} 694}
702 695
696static int
697mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
698{
699 ConfigPageHeader_t hdr;
700 CONFIGPARMS cfg;
701 int rc;
702
703 if (portnum > 1)
704 return -EINVAL;
705
706 if (!(ioc->fc_data.fc_port_page1[portnum].data))
707 return -EINVAL;
708
709 /* get fcport page 1 header */
710 hdr.PageVersion = 0;
711 hdr.PageLength = 0;
712 hdr.PageNumber = 1;
713 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
714 cfg.cfghdr.hdr = &hdr;
715 cfg.physAddr = -1;
716 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
717 cfg.dir = 0;
718 cfg.pageAddr = portnum;
719 cfg.timeout = 0;
720
721 if ((rc = mpt_config(ioc, &cfg)) != 0)
722 return rc;
723
724 if (hdr.PageLength == 0)
725 return -ENODEV;
726
727 if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
728 return -EINVAL;
729
730 cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
731 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
732 cfg.dir = 1;
733
734 rc = mpt_config(ioc, &cfg);
735
736 return rc;
737}
738
739static int
740mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
741{
742 ConfigPageHeader_t hdr;
743 CONFIGPARMS cfg;
744 FCPortPage1_t *page1_alloc;
745 dma_addr_t page1_dma;
746 int data_sz;
747 int rc;
748
749 if (portnum > 1)
750 return -EINVAL;
751
752 /* get fcport page 1 header */
753 hdr.PageVersion = 0;
754 hdr.PageLength = 0;
755 hdr.PageNumber = 1;
756 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
757 cfg.cfghdr.hdr = &hdr;
758 cfg.physAddr = -1;
759 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
760 cfg.dir = 0;
761 cfg.pageAddr = portnum;
762 cfg.timeout = 0;
763
764 if ((rc = mpt_config(ioc, &cfg)) != 0)
765 return rc;
766
767 if (hdr.PageLength == 0)
768 return -ENODEV;
769
770start_over:
771
772 if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
773 data_sz = hdr.PageLength * 4;
774 if (data_sz < sizeof(FCPortPage1_t))
775 data_sz = sizeof(FCPortPage1_t);
776
777 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
778 data_sz,
779 &page1_dma);
780 if (!page1_alloc)
781 return -ENOMEM;
782 }
783 else {
784 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
785 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
786 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
787 if (hdr.PageLength * 4 > data_sz) {
788 ioc->fc_data.fc_port_page1[portnum].data = NULL;
789 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
790 page1_alloc, page1_dma);
791 goto start_over;
792 }
793 }
794
795 memset(page1_alloc,0,data_sz);
796
797 cfg.physAddr = page1_dma;
798 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
799
800 if ((rc = mpt_config(ioc, &cfg)) == 0) {
801 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
802 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
803 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
804 }
805 else {
806 ioc->fc_data.fc_port_page1[portnum].data = NULL;
807 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
808 page1_alloc, page1_dma);
809 }
810
811 return rc;
812}
813
814static void
815mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
816{
817 int ii;
818 FCPortPage1_t *pp1;
819
820 #define MPTFC_FW_DEVICE_TIMEOUT (1)
821 #define MPTFC_FW_IO_PEND_TIMEOUT (1)
822 #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
823 #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
824
825 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
826 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
827 continue;
828 pp1 = ioc->fc_data.fc_port_page1[ii].data;
829 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
830 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
831 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
832 && ((pp1->Flags & OFF_FLAGS) == 0))
833 continue;
834 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
835 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
836 pp1->Flags &= ~OFF_FLAGS;
837 pp1->Flags |= ON_FLAGS;
838 mptfc_WriteFcPortPage1(ioc, ii);
839 }
840}
841
842
703static void 843static void
704mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) 844mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
705{ 845{
@@ -1000,6 +1140,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1000 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 1140 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1001 (void) mptfc_GetFcPortPage0(ioc, ii); 1141 (void) mptfc_GetFcPortPage0(ioc, ii);
1002 } 1142 }
1143 mptfc_SetFcPortPage1_defaults(ioc);
1003 1144
1004 /* 1145 /*
1005 * scan for rports - 1146 * scan for rports -
@@ -1086,6 +1227,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1086 } 1227 }
1087 1228
1088 else { /* MPT_IOC_POST_RESET */ 1229 else { /* MPT_IOC_POST_RESET */
1230 mptfc_SetFcPortPage1_defaults(ioc);
1089 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); 1231 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1090 if (ioc->fc_rescan_work_q) { 1232 if (ioc->fc_rescan_work_q) {
1091 if (ioc->fc_rescan_work_count++ == 0) { 1233 if (ioc->fc_rescan_work_count++ == 0) {
@@ -1112,8 +1254,8 @@ mptfc_init(void)
1112 1254
1113 show_mptmod_ver(my_NAME, my_VERSION); 1255 show_mptmod_ver(my_NAME, my_VERSION);
1114 1256
1115 /* sanity check module parameter */ 1257 /* sanity check module parameters */
1116 if (mptfc_dev_loss_tmo == 0) 1258 if (mptfc_dev_loss_tmo <= 0)
1117 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; 1259 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1118 1260
1119 mptfc_transport_template = 1261 mptfc_transport_template =
@@ -1156,6 +1298,7 @@ mptfc_remove(struct pci_dev *pdev)
1156 struct mptfc_rport_info *p, *n; 1298 struct mptfc_rport_info *p, *n;
1157 struct workqueue_struct *work_q; 1299 struct workqueue_struct *work_q;
1158 unsigned long flags; 1300 unsigned long flags;
1301 int ii;
1159 1302
1160 /* destroy workqueue */ 1303 /* destroy workqueue */
1161 if ((work_q=ioc->fc_rescan_work_q)) { 1304 if ((work_q=ioc->fc_rescan_work_q)) {
@@ -1172,6 +1315,16 @@ mptfc_remove(struct pci_dev *pdev)
1172 kfree(p); 1315 kfree(p);
1173 } 1316 }
1174 1317
1318 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1319 if (ioc->fc_data.fc_port_page1[ii].data) {
1320 pci_free_consistent(ioc->pcidev,
1321 ioc->fc_data.fc_port_page1[ii].pg_sz,
1322 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1323 ioc->fc_data.fc_port_page1[ii].dma);
1324 ioc->fc_data.fc_port_page1[ii].data = NULL;
1325 }
1326 }
1327
1175 mptscsih_remove(pdev); 1328 mptscsih_remove(pdev);
1176} 1329}
1177 1330