diff options
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 278 |
1 files changed, 222 insertions, 56 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5d4faa4dd4ea..e7aec3478a30 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -184,6 +184,7 @@ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); | |||
184 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); | 184 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); |
185 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | 185 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); |
186 | static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | 186 | static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); |
187 | static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); | ||
187 | 188 | ||
188 | /* module entry point */ | 189 | /* module entry point */ |
189 | static int __init fusion_init (void); | 190 | static int __init fusion_init (void); |
@@ -1815,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
1815 | * and we try GetLanConfigPages again... | 1816 | * and we try GetLanConfigPages again... |
1816 | */ | 1817 | */ |
1817 | if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { | 1818 | if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { |
1819 | |||
1820 | /* | ||
1821 | * Initalize link list for inactive raid volumes. | ||
1822 | */ | ||
1823 | init_MUTEX(&ioc->raid_data.inactive_list_mutex); | ||
1824 | INIT_LIST_HEAD(&ioc->raid_data.inactive_list); | ||
1825 | |||
1818 | if (ioc->bus_type == SAS) { | 1826 | if (ioc->bus_type == SAS) { |
1819 | 1827 | ||
1820 | /* clear persistency table */ | 1828 | /* clear persistency table */ |
@@ -2021,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
2021 | } | 2029 | } |
2022 | 2030 | ||
2023 | kfree(ioc->spi_data.nvram); | 2031 | kfree(ioc->spi_data.nvram); |
2032 | mpt_inactive_raid_list_free(ioc); | ||
2033 | kfree(ioc->raid_data.pIocPg2); | ||
2024 | kfree(ioc->raid_data.pIocPg3); | 2034 | kfree(ioc->raid_data.pIocPg3); |
2025 | ioc->spi_data.nvram = NULL; | 2035 | ioc->spi_data.nvram = NULL; |
2026 | ioc->raid_data.pIocPg3 = NULL; | 2036 | ioc->raid_data.pIocPg3 = NULL; |
@@ -2417,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2417 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); | 2427 | facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); |
2418 | 2428 | ||
2419 | facts->ProductID = le16_to_cpu(facts->ProductID); | 2429 | facts->ProductID = le16_to_cpu(facts->ProductID); |
2430 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | ||
2431 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | ||
2432 | ioc->ir_firmware = 1; | ||
2420 | facts->CurrentHostMfaHighAddr = | 2433 | facts->CurrentHostMfaHighAddr = |
2421 | le32_to_cpu(facts->CurrentHostMfaHighAddr); | 2434 | le32_to_cpu(facts->CurrentHostMfaHighAddr); |
2422 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); | 2435 | facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); |
@@ -2735,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) | |||
2735 | 2748 | ||
2736 | /* RAID FW may take a long time to enable | 2749 | /* RAID FW may take a long time to enable |
2737 | */ | 2750 | */ |
2738 | if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 2751 | if (ioc->ir_firmware || ioc->bus_type == SAS) { |
2739 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || | ||
2740 | (ioc->bus_type == SAS)) { | ||
2741 | rc = mpt_handshake_req_reply_wait(ioc, req_sz, | 2752 | rc = mpt_handshake_req_reply_wait(ioc, req_sz, |
2742 | (u32*)&port_enable, reply_sz, (u16*)&reply_buf, | 2753 | (u32*)&port_enable, reply_sz, (u16*)&reply_buf, |
2743 | 300 /*seconds*/, sleepFlag); | 2754 | 300 /*seconds*/, sleepFlag); |
@@ -4325,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc, | |||
4325 | if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && | 4336 | if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && |
4326 | reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || | 4337 | reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || |
4327 | (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { | 4338 | (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { |
4328 | printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", | 4339 | printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n", |
4329 | ioc->name, disk); | 4340 | ioc->name, disk, volume); |
4330 | } else { | 4341 | } else { |
4331 | printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", | 4342 | printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", |
4332 | ioc->name, volume); | 4343 | ioc->name, volume); |
@@ -4727,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) | |||
4727 | return 0; | 4738 | return 0; |
4728 | } | 4739 | } |
4729 | 4740 | ||
4730 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 4741 | /** |
4742 | * mpt_inactive_raid_list_free | ||
4743 | * | ||
4744 | * This clears this link list. | ||
4745 | * | ||
4746 | * @ioc - pointer to per adapter structure | ||
4747 | * | ||
4748 | **/ | ||
4749 | static void | ||
4750 | mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) | ||
4751 | { | ||
4752 | struct inactive_raid_component_info *component_info, *pNext; | ||
4753 | |||
4754 | if (list_empty(&ioc->raid_data.inactive_list)) | ||
4755 | return; | ||
4756 | |||
4757 | down(&ioc->raid_data.inactive_list_mutex); | ||
4758 | list_for_each_entry_safe(component_info, pNext, | ||
4759 | &ioc->raid_data.inactive_list, list) { | ||
4760 | list_del(&component_info->list); | ||
4761 | kfree(component_info); | ||
4762 | } | ||
4763 | up(&ioc->raid_data.inactive_list_mutex); | ||
4764 | } | ||
4765 | |||
4766 | /** | ||
4767 | * mpt_inactive_raid_volumes | ||
4768 | * | ||
4769 | * This sets up link list of phy_disk_nums for devices belonging in an inactive volume | ||
4770 | * | ||
4771 | * @ioc - pointer to per adapter structure | ||
4772 | * @channel - volume channel | ||
4773 | * @id - volume target id | ||
4774 | * | ||
4775 | * | ||
4776 | **/ | ||
4777 | static void | ||
4778 | mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
4779 | { | ||
4780 | CONFIGPARMS cfg; | ||
4781 | ConfigPageHeader_t hdr; | ||
4782 | dma_addr_t dma_handle; | ||
4783 | pRaidVolumePage0_t buffer = NULL; | ||
4784 | int i; | ||
4785 | RaidPhysDiskPage0_t phys_disk; | ||
4786 | struct inactive_raid_component_info *component_info; | ||
4787 | int handle_inactive_volumes; | ||
4788 | |||
4789 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
4790 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
4791 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; | ||
4792 | cfg.pageAddr = (channel << 8) + id; | ||
4793 | cfg.cfghdr.hdr = &hdr; | ||
4794 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
4795 | |||
4796 | if (mpt_config(ioc, &cfg) != 0) | ||
4797 | goto out; | ||
4798 | |||
4799 | if (!hdr.PageLength) | ||
4800 | goto out; | ||
4801 | |||
4802 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
4803 | &dma_handle); | ||
4804 | |||
4805 | if (!buffer) | ||
4806 | goto out; | ||
4807 | |||
4808 | cfg.physAddr = dma_handle; | ||
4809 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
4810 | |||
4811 | if (mpt_config(ioc, &cfg) != 0) | ||
4812 | goto out; | ||
4813 | |||
4814 | if (!buffer->NumPhysDisks) | ||
4815 | goto out; | ||
4816 | |||
4817 | handle_inactive_volumes = | ||
4818 | (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE || | ||
4819 | (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 || | ||
4820 | buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED || | ||
4821 | buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0; | ||
4822 | |||
4823 | if (!handle_inactive_volumes) | ||
4824 | goto out; | ||
4825 | |||
4826 | down(&ioc->raid_data.inactive_list_mutex); | ||
4827 | for (i = 0; i < buffer->NumPhysDisks; i++) { | ||
4828 | if(mpt_raid_phys_disk_pg0(ioc, | ||
4829 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||
4830 | continue; | ||
4831 | |||
4832 | if ((component_info = kmalloc(sizeof (*component_info), | ||
4833 | GFP_KERNEL)) == NULL) | ||
4834 | continue; | ||
4835 | |||
4836 | component_info->volumeID = id; | ||
4837 | component_info->volumeBus = channel; | ||
4838 | component_info->d.PhysDiskNum = phys_disk.PhysDiskNum; | ||
4839 | component_info->d.PhysDiskBus = phys_disk.PhysDiskBus; | ||
4840 | component_info->d.PhysDiskID = phys_disk.PhysDiskID; | ||
4841 | component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC; | ||
4842 | |||
4843 | list_add_tail(&component_info->list, | ||
4844 | &ioc->raid_data.inactive_list); | ||
4845 | } | ||
4846 | up(&ioc->raid_data.inactive_list_mutex); | ||
4847 | |||
4848 | out: | ||
4849 | if (buffer) | ||
4850 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
4851 | dma_handle); | ||
4852 | } | ||
4853 | |||
4854 | /** | ||
4855 | * mpt_raid_phys_disk_pg0 - returns phys disk page zero | ||
4856 | * @ioc: Pointer to a Adapter Structure | ||
4857 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
4858 | * @phys_disk: requested payload data returned | ||
4859 | * | ||
4860 | * Return: | ||
4861 | * 0 on success | ||
4862 | * -EFAULT if read of config page header fails or data pointer not NULL | ||
4863 | * -ENOMEM if pci_alloc failed | ||
4864 | **/ | ||
4865 | int | ||
4866 | mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) | ||
4867 | { | ||
4868 | CONFIGPARMS cfg; | ||
4869 | ConfigPageHeader_t hdr; | ||
4870 | dma_addr_t dma_handle; | ||
4871 | pRaidPhysDiskPage0_t buffer = NULL; | ||
4872 | int rc; | ||
4873 | |||
4874 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
4875 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
4876 | |||
4877 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
4878 | cfg.cfghdr.hdr = &hdr; | ||
4879 | cfg.physAddr = -1; | ||
4880 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
4881 | |||
4882 | if (mpt_config(ioc, &cfg) != 0) { | ||
4883 | rc = -EFAULT; | ||
4884 | goto out; | ||
4885 | } | ||
4886 | |||
4887 | if (!hdr.PageLength) { | ||
4888 | rc = -EFAULT; | ||
4889 | goto out; | ||
4890 | } | ||
4891 | |||
4892 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
4893 | &dma_handle); | ||
4894 | |||
4895 | if (!buffer) { | ||
4896 | rc = -ENOMEM; | ||
4897 | goto out; | ||
4898 | } | ||
4899 | |||
4900 | cfg.physAddr = dma_handle; | ||
4901 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
4902 | cfg.pageAddr = phys_disk_num; | ||
4903 | |||
4904 | if (mpt_config(ioc, &cfg) != 0) { | ||
4905 | rc = -EFAULT; | ||
4906 | goto out; | ||
4907 | } | ||
4908 | |||
4909 | rc = 0; | ||
4910 | memcpy(phys_disk, buffer, sizeof(*buffer)); | ||
4911 | phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA); | ||
4912 | |||
4913 | out: | ||
4914 | |||
4915 | if (buffer) | ||
4916 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
4917 | dma_handle); | ||
4918 | |||
4919 | return rc; | ||
4920 | } | ||
4921 | |||
4731 | /** | 4922 | /** |
4732 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes | 4923 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes |
4733 | * @ioc: Pointer to a Adapter Strucutre | 4924 | * @ioc: Pointer to a Adapter Strucutre |
@@ -4737,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) | |||
4737 | * 0 on success | 4928 | * 0 on success |
4738 | * -EFAULT if read of config page header fails or data pointer not NULL | 4929 | * -EFAULT if read of config page header fails or data pointer not NULL |
4739 | * -ENOMEM if pci_alloc failed | 4930 | * -ENOMEM if pci_alloc failed |
4740 | */ | 4931 | **/ |
4741 | int | 4932 | int |
4742 | mpt_findImVolumes(MPT_ADAPTER *ioc) | 4933 | mpt_findImVolumes(MPT_ADAPTER *ioc) |
4743 | { | 4934 | { |
4744 | IOCPage2_t *pIoc2; | 4935 | IOCPage2_t *pIoc2; |
4745 | u8 *mem; | 4936 | u8 *mem; |
4746 | ConfigPageIoc2RaidVol_t *pIocRv; | ||
4747 | dma_addr_t ioc2_dma; | 4937 | dma_addr_t ioc2_dma; |
4748 | CONFIGPARMS cfg; | 4938 | CONFIGPARMS cfg; |
4749 | ConfigPageHeader_t header; | 4939 | ConfigPageHeader_t header; |
4750 | int jj; | ||
4751 | int rc = 0; | 4940 | int rc = 0; |
4752 | int iocpage2sz; | 4941 | int iocpage2sz; |
4753 | u8 nVols, nPhys; | 4942 | int i; |
4754 | u8 vid, vbus, vioc; | 4943 | |
4944 | if (!ioc->ir_firmware) | ||
4945 | return 0; | ||
4946 | |||
4947 | /* Free the old page | ||
4948 | */ | ||
4949 | kfree(ioc->raid_data.pIocPg2); | ||
4950 | ioc->raid_data.pIocPg2 = NULL; | ||
4951 | mpt_inactive_raid_list_free(ioc); | ||
4755 | 4952 | ||
4756 | /* Read IOCP2 header then the page. | 4953 | /* Read IOCP2 header then the page. |
4757 | */ | 4954 | */ |
@@ -4779,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) | |||
4779 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 4976 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; |
4780 | cfg.physAddr = ioc2_dma; | 4977 | cfg.physAddr = ioc2_dma; |
4781 | if (mpt_config(ioc, &cfg) != 0) | 4978 | if (mpt_config(ioc, &cfg) != 0) |
4782 | goto done_and_free; | 4979 | goto out; |
4980 | |||
4981 | mem = kmalloc(iocpage2sz, GFP_KERNEL); | ||
4982 | if (!mem) | ||
4983 | goto out; | ||
4783 | 4984 | ||
4784 | if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { | ||
4785 | mem = kmalloc(iocpage2sz, GFP_ATOMIC); | ||
4786 | if (mem) { | ||
4787 | ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; | ||
4788 | } else { | ||
4789 | goto done_and_free; | ||
4790 | } | ||
4791 | } | ||
4792 | memcpy(mem, (u8 *)pIoc2, iocpage2sz); | 4985 | memcpy(mem, (u8 *)pIoc2, iocpage2sz); |
4986 | ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; | ||
4793 | 4987 | ||
4794 | /* Identify RAID Volume Id's */ | 4988 | mpt_read_ioc_pg_3(ioc); |
4795 | nVols = pIoc2->NumActiveVolumes; | ||
4796 | if ( nVols == 0) { | ||
4797 | /* No RAID Volume. | ||
4798 | */ | ||
4799 | goto done_and_free; | ||
4800 | } else { | ||
4801 | /* At least 1 RAID Volume | ||
4802 | */ | ||
4803 | pIocRv = pIoc2->RaidVolume; | ||
4804 | ioc->raid_data.isRaid = 0; | ||
4805 | for (jj = 0; jj < nVols; jj++, pIocRv++) { | ||
4806 | vid = pIocRv->VolumeID; | ||
4807 | vbus = pIocRv->VolumeBus; | ||
4808 | vioc = pIocRv->VolumeIOC; | ||
4809 | |||
4810 | /* find the match | ||
4811 | */ | ||
4812 | if (vbus == 0) { | ||
4813 | ioc->raid_data.isRaid |= (1 << vid); | ||
4814 | } else { | ||
4815 | /* Error! Always bus 0 | ||
4816 | */ | ||
4817 | } | ||
4818 | } | ||
4819 | } | ||
4820 | 4989 | ||
4821 | /* Identify Hidden Physical Disk Id's */ | 4990 | for (i = 0; i < pIoc2->NumActiveVolumes ; i++) |
4822 | nPhys = pIoc2->NumActivePhysDisks; | 4991 | mpt_inactive_raid_volumes(ioc, |
4823 | if (nPhys == 0) { | 4992 | pIoc2->RaidVolume[i].VolumeBus, |
4824 | /* No physical disks. | 4993 | pIoc2->RaidVolume[i].VolumeID); |
4825 | */ | ||
4826 | } else { | ||
4827 | mpt_read_ioc_pg_3(ioc); | ||
4828 | } | ||
4829 | 4994 | ||
4830 | done_and_free: | 4995 | out: |
4831 | pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); | 4996 | pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); |
4832 | 4997 | ||
4833 | return rc; | 4998 | return rc; |
@@ -4880,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) | |||
4880 | cfg.physAddr = ioc3_dma; | 5045 | cfg.physAddr = ioc3_dma; |
4881 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 5046 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; |
4882 | if (mpt_config(ioc, &cfg) == 0) { | 5047 | if (mpt_config(ioc, &cfg) == 0) { |
4883 | mem = kmalloc(iocpage3sz, GFP_ATOMIC); | 5048 | mem = kmalloc(iocpage3sz, GFP_KERNEL); |
4884 | if (mem) { | 5049 | if (mem) { |
4885 | memcpy(mem, (u8 *)pIoc3, iocpage3sz); | 5050 | memcpy(mem, (u8 *)pIoc3, iocpage3sz); |
4886 | ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; | 5051 | ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; |
@@ -6833,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); | |||
6833 | EXPORT_SYMBOL(mpt_alloc_fw_memory); | 6998 | EXPORT_SYMBOL(mpt_alloc_fw_memory); |
6834 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6999 | EXPORT_SYMBOL(mpt_free_fw_memory); |
6835 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | 7000 | EXPORT_SYMBOL(mptbase_sas_persist_operation); |
7001 | EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); | ||
6836 | 7002 | ||
6837 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 7003 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
6838 | /** | 7004 | /** |