diff options
Diffstat (limited to 'drivers/message/fusion/mptfc.c')
-rw-r--r-- | drivers/message/fusion/mptfc.c | 171 |
1 files changed, 162 insertions, 9 deletions
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 | */ | ||
179 | static void | 172 | static void |
180 | mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) | 173 | mptfc_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 | ||
696 | static int | ||
697 | mptfc_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 | |||
739 | static int | ||
740 | mptfc_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 | |||
770 | start_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 | |||
814 | static void | ||
815 | mptfc_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 | |||
703 | static void | 843 | static void |
704 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | 844 | mptfc_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 | ||