aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptfc.c')
-rw-r--r--drivers/message/fusion/mptfc.c394
1 files changed, 380 insertions, 14 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 856487741ef4..74714e5bcf03 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{
@@ -587,15 +580,266 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
587#ifdef DMPT_DEBUG_FC 580#ifdef DMPT_DEBUG_FC
588 if (unlikely(err)) { 581 if (unlikely(err)) {
589 dfcprintk ((MYIOC_s_INFO_FMT 582 dfcprintk ((MYIOC_s_INFO_FMT
590 "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n", 583 "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
591 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, 584 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
592 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, 585 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
593 SCpnt->device->id,SCpnt->device->lun)); 586 SCpnt->device->id,SCpnt->device->lun,err));
594 } 587 }
595#endif 588#endif
596 return err; 589 return err;
597} 590}
598 591
592/*
593 * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
594 * @ioc: Pointer to MPT_ADAPTER structure
595 * @portnum: IOC Port number
596 *
597 * Return: 0 for success
598 * -ENOMEM if no memory available
599 * -EPERM if not allowed due to ISR context
600 * -EAGAIN if no msg frames currently available
601 * -EFAULT for non-successful reply or no reply (timeout)
602 * -EINVAL portnum arg out of range (hardwired to two elements)
603 */
604static int
605mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
606{
607 ConfigPageHeader_t hdr;
608 CONFIGPARMS cfg;
609 FCPortPage0_t *ppage0_alloc;
610 FCPortPage0_t *pp0dest;
611 dma_addr_t page0_dma;
612 int data_sz;
613 int copy_sz;
614 int rc;
615 int count = 400;
616
617 if (portnum > 1)
618 return -EINVAL;
619
620 /* Get FCPort Page 0 header */
621 hdr.PageVersion = 0;
622 hdr.PageLength = 0;
623 hdr.PageNumber = 0;
624 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
625 cfg.cfghdr.hdr = &hdr;
626 cfg.physAddr = -1;
627 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
628 cfg.dir = 0;
629 cfg.pageAddr = portnum;
630 cfg.timeout = 0;
631
632 if ((rc = mpt_config(ioc, &cfg)) != 0)
633 return rc;
634
635 if (hdr.PageLength == 0)
636 return 0;
637
638 data_sz = hdr.PageLength * 4;
639 rc = -ENOMEM;
640 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
641 if (ppage0_alloc) {
642
643 try_again:
644 memset((u8 *)ppage0_alloc, 0, data_sz);
645 cfg.physAddr = page0_dma;
646 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
647
648 if ((rc = mpt_config(ioc, &cfg)) == 0) {
649 /* save the data */
650 pp0dest = &ioc->fc_port_page0[portnum];
651 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
652 memcpy(pp0dest, ppage0_alloc, copy_sz);
653
654 /*
655 * Normalize endianness of structure data,
656 * by byte-swapping all > 1 byte fields!
657 */
658 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
659 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
660 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
661 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
662 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
663 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
664 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
665 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
666 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
667 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
668 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
669 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
670 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
671 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
672 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
673 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
674
675 /*
676 * if still doing discovery,
677 * hang loose a while until finished
678 */
679 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
680 if (count-- > 0) {
681 msleep(100);
682 goto try_again;
683 }
684 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
685 " complete.\n",
686 ioc->name);
687 }
688 }
689
690 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
691 }
692
693 return rc;
694}
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
599static void 843static void
600mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) 844mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
601{ 845{
@@ -629,6 +873,31 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
629} 873}
630 874
631static void 875static void
876mptfc_setup_reset(void *arg)
877{
878 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
879 u64 pn;
880 struct mptfc_rport_info *ri;
881
882 /* reset about to happen, delete (block) all rports */
883 list_for_each_entry(ri, &ioc->fc_rports, list) {
884 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
885 ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
886 fc_remote_port_delete(ri->rport); /* won't sleep */
887 ri->rport = NULL;
888
889 pn = (u64)ri->pg0.WWPN.High << 32 |
890 (u64)ri->pg0.WWPN.Low;
891 dfcprintk ((MYIOC_s_INFO_FMT
892 "mptfc_setup_reset.%d: %llx deleted\n",
893 ioc->name,
894 ioc->sh->host_no,
895 (unsigned long long)pn));
896 }
897 }
898}
899
900static void
632mptfc_rescan_devices(void *arg) 901mptfc_rescan_devices(void *arg)
633{ 902{
634 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; 903 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
@@ -651,7 +920,7 @@ mptfc_rescan_devices(void *arg)
651 * will reregister existing rports 920 * will reregister existing rports
652 */ 921 */
653 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 922 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
654 (void) mptbase_GetFcPortPage0(ioc, ii); 923 (void) mptfc_GetFcPortPage0(ioc, ii);
655 mptfc_init_host_attr(ioc,ii); /* refresh */ 924 mptfc_init_host_attr(ioc,ii); /* refresh */
656 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); 925 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
657 } 926 }
@@ -753,7 +1022,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
753 goto out_mptfc_probe; 1022 goto out_mptfc_probe;
754 } 1023 }
755 1024
1025 spin_lock_init(&ioc->fc_rescan_work_lock);
756 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); 1026 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
1027 INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
757 1028
758 spin_lock_irqsave(&ioc->FreeQlock, flags); 1029 spin_lock_irqsave(&ioc->FreeQlock, flags);
759 1030
@@ -889,6 +1160,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
889 goto out_mptfc_probe; 1160 goto out_mptfc_probe;
890 1161
891 /* 1162 /*
1163 * Pre-fetch FC port WWN and stuff...
1164 * (FCPortPage0_t stuff)
1165 */
1166 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1167 (void) mptfc_GetFcPortPage0(ioc, ii);
1168 }
1169 mptfc_SetFcPortPage1_defaults(ioc);
1170
1171 /*
892 * scan for rports - 1172 * scan for rports -
893 * by doing it via the workqueue, some locking is eliminated 1173 * by doing it via the workqueue, some locking is eliminated
894 */ 1174 */
@@ -917,6 +1197,81 @@ static struct pci_driver mptfc_driver = {
917#endif 1197#endif
918}; 1198};
919 1199
1200static int
1201mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1202{
1203 MPT_SCSI_HOST *hd;
1204 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1205 unsigned long flags;
1206 int rc=1;
1207
1208 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1209 ioc->name, event));
1210
1211 if (ioc->sh == NULL ||
1212 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1213 return 1;
1214
1215 switch (event) {
1216 case MPI_EVENT_RESCAN:
1217 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1218 if (ioc->fc_rescan_work_q) {
1219 if (ioc->fc_rescan_work_count++ == 0) {
1220 queue_work(ioc->fc_rescan_work_q,
1221 &ioc->fc_rescan_work);
1222 }
1223 }
1224 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1225 break;
1226 default:
1227 rc = mptscsih_event_process(ioc,pEvReply);
1228 break;
1229 }
1230 return rc;
1231}
1232
1233static int
1234mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1235{
1236 int rc;
1237 unsigned long flags;
1238
1239 rc = mptscsih_ioc_reset(ioc,reset_phase);
1240 if (rc == 0)
1241 return rc;
1242
1243
1244 dtmprintk((KERN_WARNING MYNAM
1245 ": IOC %s_reset routed to FC host driver!\n",
1246 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1247 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1248
1249 if (reset_phase == MPT_IOC_SETUP_RESET) {
1250 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1251 if (ioc->fc_rescan_work_q) {
1252 queue_work(ioc->fc_rescan_work_q,
1253 &ioc->fc_setup_reset_work);
1254 }
1255 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1256 }
1257
1258 else if (reset_phase == MPT_IOC_PRE_RESET) {
1259 }
1260
1261 else { /* MPT_IOC_POST_RESET */
1262 mptfc_SetFcPortPage1_defaults(ioc);
1263 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1264 if (ioc->fc_rescan_work_q) {
1265 if (ioc->fc_rescan_work_count++ == 0) {
1266 queue_work(ioc->fc_rescan_work_q,
1267 &ioc->fc_rescan_work);
1268 }
1269 }
1270 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1271 }
1272 return 1;
1273}
1274
920/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1275/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
921/** 1276/**
922 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with 1277 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
@@ -931,8 +1286,8 @@ mptfc_init(void)
931 1286
932 show_mptmod_ver(my_NAME, my_VERSION); 1287 show_mptmod_ver(my_NAME, my_VERSION);
933 1288
934 /* sanity check module parameter */ 1289 /* sanity check module parameters */
935 if (mptfc_dev_loss_tmo == 0) 1290 if (mptfc_dev_loss_tmo <= 0)
936 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; 1291 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
937 1292
938 mptfc_transport_template = 1293 mptfc_transport_template =
@@ -945,12 +1300,12 @@ mptfc_init(void)
945 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); 1300 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
946 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); 1301 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
947 1302
948 if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { 1303 if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
949 devtverboseprintk((KERN_INFO MYNAM 1304 devtverboseprintk((KERN_INFO MYNAM
950 ": Registered for IOC event notifications\n")); 1305 ": Registered for IOC event notifications\n"));
951 } 1306 }
952 1307
953 if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { 1308 if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
954 dprintk((KERN_INFO MYNAM 1309 dprintk((KERN_INFO MYNAM
955 ": Registered for IOC reset notifications\n")); 1310 ": Registered for IOC reset notifications\n"));
956 } 1311 }
@@ -975,6 +1330,7 @@ mptfc_remove(struct pci_dev *pdev)
975 struct mptfc_rport_info *p, *n; 1330 struct mptfc_rport_info *p, *n;
976 struct workqueue_struct *work_q; 1331 struct workqueue_struct *work_q;
977 unsigned long flags; 1332 unsigned long flags;
1333 int ii;
978 1334
979 /* destroy workqueue */ 1335 /* destroy workqueue */
980 if ((work_q=ioc->fc_rescan_work_q)) { 1336 if ((work_q=ioc->fc_rescan_work_q)) {
@@ -991,6 +1347,16 @@ mptfc_remove(struct pci_dev *pdev)
991 kfree(p); 1347 kfree(p);
992 } 1348 }
993 1349
1350 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1351 if (ioc->fc_data.fc_port_page1[ii].data) {
1352 pci_free_consistent(ioc->pcidev,
1353 ioc->fc_data.fc_port_page1[ii].pg_sz,
1354 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1355 ioc->fc_data.fc_port_page1[ii].dma);
1356 ioc->fc_data.fc_port_page1[ii].data = NULL;
1357 }
1358 }
1359
994 mptscsih_remove(pdev); 1360 mptscsih_remove(pdev);
995} 1361}
996 1362