aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptfc.c
diff options
context:
space:
mode:
authorMichael Reed <mdr@sgi.com>2006-05-24 16:07:09 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-10 16:58:37 -0400
commit80d3ac77a84987d5132726f3d7cef342a280f7d9 (patch)
treecb126b63a06eed078cd7daa95a998d01f3df015e /drivers/message/fusion/mptfc.c
parentf0cd91a68acdc9b49d7f6738b514a426da627649 (diff)
[SCSI] mptfusion: move fc event/reset handling to mptfc
Move fibre channel event and reset handling to mptfc. This will result in fewer changes over time that need to be applied to either mptbase.c or mptscsih.c. Signed-off-by: Michael Reed <mdr@sgi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion/mptfc.c')
-rw-r--r--drivers/message/fusion/mptfc.c187
1 files changed, 184 insertions, 3 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 856487741ef4..e518bc97f8ce 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -596,6 +596,110 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
596 return err; 596 return err;
597} 597}
598 598
599/*
600 * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
601 * @ioc: Pointer to MPT_ADAPTER structure
602 * @portnum: IOC Port number
603 *
604 * Return: 0 for success
605 * -ENOMEM if no memory available
606 * -EPERM if not allowed due to ISR context
607 * -EAGAIN if no msg frames currently available
608 * -EFAULT for non-successful reply or no reply (timeout)
609 * -EINVAL portnum arg out of range (hardwired to two elements)
610 */
611static int
612mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
613{
614 ConfigPageHeader_t hdr;
615 CONFIGPARMS cfg;
616 FCPortPage0_t *ppage0_alloc;
617 FCPortPage0_t *pp0dest;
618 dma_addr_t page0_dma;
619 int data_sz;
620 int copy_sz;
621 int rc;
622 int count = 400;
623
624 if (portnum > 1)
625 return -EINVAL;
626
627 /* Get FCPort Page 0 header */
628 hdr.PageVersion = 0;
629 hdr.PageLength = 0;
630 hdr.PageNumber = 0;
631 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
632 cfg.cfghdr.hdr = &hdr;
633 cfg.physAddr = -1;
634 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
635 cfg.dir = 0;
636 cfg.pageAddr = portnum;
637 cfg.timeout = 0;
638
639 if ((rc = mpt_config(ioc, &cfg)) != 0)
640 return rc;
641
642 if (hdr.PageLength == 0)
643 return 0;
644
645 data_sz = hdr.PageLength * 4;
646 rc = -ENOMEM;
647 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
648 if (ppage0_alloc) {
649
650 try_again:
651 memset((u8 *)ppage0_alloc, 0, data_sz);
652 cfg.physAddr = page0_dma;
653 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
654
655 if ((rc = mpt_config(ioc, &cfg)) == 0) {
656 /* save the data */
657 pp0dest = &ioc->fc_port_page0[portnum];
658 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
659 memcpy(pp0dest, ppage0_alloc, copy_sz);
660
661 /*
662 * Normalize endianness of structure data,
663 * by byte-swapping all > 1 byte fields!
664 */
665 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
666 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
667 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
668 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
669 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
670 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
671 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
672 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
673 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
674 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
675 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
676 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
677 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
678 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
679 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
680 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
681
682 /*
683 * if still doing discovery,
684 * hang loose a while until finished
685 */
686 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
687 if (count-- > 0) {
688 msleep_interruptible(100);
689 goto try_again;
690 }
691 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
692 " complete.\n",
693 ioc->name);
694 }
695 }
696
697 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
698 }
699
700 return rc;
701}
702
599static void 703static void
600mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) 704mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
601{ 705{
@@ -651,7 +755,7 @@ mptfc_rescan_devices(void *arg)
651 * will reregister existing rports 755 * will reregister existing rports
652 */ 756 */
653 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 757 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
654 (void) mptbase_GetFcPortPage0(ioc, ii); 758 (void) mptfc_GetFcPortPage0(ioc, ii);
655 mptfc_init_host_attr(ioc,ii); /* refresh */ 759 mptfc_init_host_attr(ioc,ii); /* refresh */
656 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); 760 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
657 } 761 }
@@ -753,6 +857,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
753 goto out_mptfc_probe; 857 goto out_mptfc_probe;
754 } 858 }
755 859
860 spin_lock_init(&ioc->fc_rescan_work_lock);
756 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); 861 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
757 862
758 spin_lock_irqsave(&ioc->FreeQlock, flags); 863 spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -889,6 +994,14 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
889 goto out_mptfc_probe; 994 goto out_mptfc_probe;
890 995
891 /* 996 /*
997 * Pre-fetch FC port WWN and stuff...
998 * (FCPortPage0_t stuff)
999 */
1000 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1001 (void) mptfc_GetFcPortPage0(ioc, ii);
1002 }
1003
1004 /*
892 * scan for rports - 1005 * scan for rports -
893 * by doing it via the workqueue, some locking is eliminated 1006 * by doing it via the workqueue, some locking is eliminated
894 */ 1007 */
@@ -917,6 +1030,74 @@ static struct pci_driver mptfc_driver = {
917#endif 1030#endif
918}; 1031};
919 1032
1033static int
1034mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1035{
1036 MPT_SCSI_HOST *hd;
1037 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1038 unsigned long flags;
1039 int rc=1;
1040
1041 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1042 ioc->name, event));
1043
1044 if (ioc->sh == NULL ||
1045 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1046 return 1;
1047
1048 switch (event) {
1049 case MPI_EVENT_RESCAN:
1050 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1051 if (ioc->fc_rescan_work_q) {
1052 if (ioc->fc_rescan_work_count++ == 0) {
1053 queue_work(ioc->fc_rescan_work_q,
1054 &ioc->fc_rescan_work);
1055 }
1056 }
1057 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1058 break;
1059 default:
1060 rc = mptscsih_event_process(ioc,pEvReply);
1061 break;
1062 }
1063 return rc;
1064}
1065
1066static int
1067mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1068{
1069 int rc;
1070 unsigned long flags;
1071
1072 rc = mptscsih_ioc_reset(ioc,reset_phase);
1073 if (rc == 0)
1074 return rc;
1075
1076
1077 dtmprintk((KERN_WARNING MYNAM
1078 ": IOC %s_reset routed to FC host driver!\n",
1079 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1080 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1081
1082 if (reset_phase == MPT_IOC_SETUP_RESET) {
1083 }
1084
1085 else if (reset_phase == MPT_IOC_PRE_RESET) {
1086 }
1087
1088 else { /* MPT_IOC_POST_RESET */
1089 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1090 if (ioc->fc_rescan_work_q) {
1091 if (ioc->fc_rescan_work_count++ == 0) {
1092 queue_work(ioc->fc_rescan_work_q,
1093 &ioc->fc_rescan_work);
1094 }
1095 }
1096 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1097 }
1098 return 1;
1099}
1100
920/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1101/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
921/** 1102/**
922 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with 1103 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
@@ -945,12 +1126,12 @@ mptfc_init(void)
945 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); 1126 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
946 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); 1127 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
947 1128
948 if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { 1129 if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
949 devtverboseprintk((KERN_INFO MYNAM 1130 devtverboseprintk((KERN_INFO MYNAM
950 ": Registered for IOC event notifications\n")); 1131 ": Registered for IOC event notifications\n"));
951 } 1132 }
952 1133
953 if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { 1134 if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
954 dprintk((KERN_INFO MYNAM 1135 dprintk((KERN_INFO MYNAM
955 ": Registered for IOC reset notifications\n")); 1136 ": Registered for IOC reset notifications\n"));
956 } 1137 }