diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 278 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 19 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 272 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 32 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 3 |
5 files changed, 510 insertions, 94 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 | /** |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 3d613c4f93d9..07830d28e58d 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -485,10 +485,24 @@ typedef struct _SasCfgData { | |||
485 | */ | 485 | */ |
486 | }SasCfgData; | 486 | }SasCfgData; |
487 | 487 | ||
488 | /* | ||
489 | * Inactive volume link list of raid component data | ||
490 | * @inactive_list | ||
491 | */ | ||
492 | struct inactive_raid_component_info { | ||
493 | struct list_head list; | ||
494 | u8 volumeID; /* volume target id */ | ||
495 | u8 volumeBus; /* volume channel */ | ||
496 | IOC_3_PHYS_DISK d; /* phys disk info */ | ||
497 | }; | ||
498 | |||
488 | typedef struct _RaidCfgData { | 499 | typedef struct _RaidCfgData { |
489 | IOCPage2_t *pIocPg2; /* table of Raid Volumes */ | 500 | IOCPage2_t *pIocPg2; /* table of Raid Volumes */ |
490 | IOCPage3_t *pIocPg3; /* table of physical disks */ | 501 | IOCPage3_t *pIocPg3; /* table of physical disks */ |
491 | int isRaid; /* bit field, 1 if RAID */ | 502 | struct semaphore inactive_list_mutex; |
503 | struct list_head inactive_list; /* link list for physical | ||
504 | disk that belong in | ||
505 | inactive volumes */ | ||
492 | }RaidCfgData; | 506 | }RaidCfgData; |
493 | 507 | ||
494 | typedef struct _FcCfgData { | 508 | typedef struct _FcCfgData { |
@@ -611,6 +625,8 @@ typedef struct _MPT_ADAPTER | |||
611 | u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ | 625 | u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ |
612 | LANPage0_t lan_cnfg_page0; | 626 | LANPage0_t lan_cnfg_page0; |
613 | LANPage1_t lan_cnfg_page1; | 627 | LANPage1_t lan_cnfg_page1; |
628 | |||
629 | u8 ir_firmware; /* =1 if IR firmware detected */ | ||
614 | /* | 630 | /* |
615 | * Description: errata_flag_1064 | 631 | * Description: errata_flag_1064 |
616 | * If a PCIX read occurs within 1 or 2 cycles after the chip receives | 632 | * If a PCIX read occurs within 1 or 2 cycles after the chip receives |
@@ -1043,6 +1059,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); | |||
1043 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | 1059 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); |
1044 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 1060 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
1045 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 1061 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
1062 | extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); | ||
1046 | 1063 | ||
1047 | /* | 1064 | /* |
1048 | * Public data decl's... | 1065 | * Public data decl's... |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index f7c5e0d97890..a8df06c422bd 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -94,12 +94,14 @@ static int mptsasTaskCtx = -1; | |||
94 | static int mptsasInternalCtx = -1; /* Used only for internal commands */ | 94 | static int mptsasInternalCtx = -1; /* Used only for internal commands */ |
95 | static int mptsasMgmtCtx = -1; | 95 | static int mptsasMgmtCtx = -1; |
96 | 96 | ||
97 | static void mptsas_hotplug_work(struct work_struct *work); | ||
97 | 98 | ||
98 | enum mptsas_hotplug_action { | 99 | enum mptsas_hotplug_action { |
99 | MPTSAS_ADD_DEVICE, | 100 | MPTSAS_ADD_DEVICE, |
100 | MPTSAS_DEL_DEVICE, | 101 | MPTSAS_DEL_DEVICE, |
101 | MPTSAS_ADD_RAID, | 102 | MPTSAS_ADD_RAID, |
102 | MPTSAS_DEL_RAID, | 103 | MPTSAS_DEL_RAID, |
104 | MPTSAS_ADD_INACTIVE_VOLUME, | ||
103 | MPTSAS_IGNORE_EVENT, | 105 | MPTSAS_IGNORE_EVENT, |
104 | }; | 106 | }; |
105 | 107 | ||
@@ -108,14 +110,15 @@ struct mptsas_hotplug_event { | |||
108 | MPT_ADAPTER *ioc; | 110 | MPT_ADAPTER *ioc; |
109 | enum mptsas_hotplug_action event_type; | 111 | enum mptsas_hotplug_action event_type; |
110 | u64 sas_address; | 112 | u64 sas_address; |
111 | u32 channel; | 113 | u8 channel; |
112 | u32 id; | 114 | u8 id; |
113 | u32 device_info; | 115 | u32 device_info; |
114 | u16 handle; | 116 | u16 handle; |
115 | u16 parent_handle; | 117 | u16 parent_handle; |
116 | u8 phy_id; | 118 | u8 phy_id; |
117 | u8 phys_disk_num; | 119 | u8 phys_disk_num_valid; /* hrc (hidden raid component) */ |
118 | u8 phys_disk_num_valid; | 120 | u8 phys_disk_num; /* hrc - unique index*/ |
121 | u8 hidden_raid_component; /* hrc - don't expose*/ | ||
119 | }; | 122 | }; |
120 | 123 | ||
121 | struct mptsas_discovery_event { | 124 | struct mptsas_discovery_event { |
@@ -140,6 +143,7 @@ struct mptsas_devinfo { | |||
140 | u8 port_id; /* sas physical port this device | 143 | u8 port_id; /* sas physical port this device |
141 | is assoc'd with */ | 144 | is assoc'd with */ |
142 | u8 id; /* logical target id of this device */ | 145 | u8 id; /* logical target id of this device */ |
146 | u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ | ||
143 | u8 channel; /* logical bus number of this device */ | 147 | u8 channel; /* logical bus number of this device */ |
144 | u64 sas_address; /* WWN of this device, | 148 | u64 sas_address; /* WWN of this device, |
145 | SATA is assigned by HBA,expander */ | 149 | SATA is assigned by HBA,expander */ |
@@ -711,6 +715,7 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
711 | channel, id); | 715 | channel, id); |
712 | vtarget->tflags |= | 716 | vtarget->tflags |= |
713 | MPT_TARGET_FLAGS_RAID_COMPONENT; | 717 | MPT_TARGET_FLAGS_RAID_COMPONENT; |
718 | p->phy_info[i].attached.phys_disk_num = id; | ||
714 | } | 719 | } |
715 | mutex_unlock(&hd->ioc->sas_topology_mutex); | 720 | mutex_unlock(&hd->ioc->sas_topology_mutex); |
716 | goto out; | 721 | goto out; |
@@ -1272,6 +1277,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
1272 | device_info->phy_id = buffer->PhyNum; | 1277 | device_info->phy_id = buffer->PhyNum; |
1273 | device_info->port_id = buffer->PhysicalPort; | 1278 | device_info->port_id = buffer->PhysicalPort; |
1274 | device_info->id = buffer->TargetID; | 1279 | device_info->id = buffer->TargetID; |
1280 | device_info->phys_disk_num = ~0; | ||
1275 | device_info->channel = buffer->Bus; | 1281 | device_info->channel = buffer->Bus; |
1276 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | 1282 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); |
1277 | device_info->sas_address = le64_to_cpu(sas_address); | 1283 | device_info->sas_address = le64_to_cpu(sas_address); |
@@ -1983,6 +1989,8 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | |||
1983 | /* | 1989 | /* |
1984 | Reporting RAID volumes. | 1990 | Reporting RAID volumes. |
1985 | */ | 1991 | */ |
1992 | if (!ioc->ir_firmware) | ||
1993 | goto out; | ||
1986 | if (!ioc->raid_data.pIocPg2) | 1994 | if (!ioc->raid_data.pIocPg2) |
1987 | goto out; | 1995 | goto out; |
1988 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | 1996 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) |
@@ -2041,12 +2049,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
2041 | mutex_lock(&ioc->sas_topology_mutex); | 2049 | mutex_lock(&ioc->sas_topology_mutex); |
2042 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 2050 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
2043 | for (i = 0; i < port_info->num_phys; i++) { | 2051 | for (i = 0; i < port_info->num_phys; i++) { |
2052 | if (!mptsas_is_end_device( | ||
2053 | &port_info->phy_info[i].attached)) | ||
2054 | continue; | ||
2044 | if (port_info->phy_info[i].attached.sas_address | 2055 | if (port_info->phy_info[i].attached.sas_address |
2045 | != sas_address) | 2056 | != sas_address) |
2046 | continue; | 2057 | continue; |
2058 | phy_info = &port_info->phy_info[i]; | ||
2059 | break; | ||
2060 | } | ||
2061 | } | ||
2062 | mutex_unlock(&ioc->sas_topology_mutex); | ||
2063 | return phy_info; | ||
2064 | } | ||
2065 | |||
2066 | static struct mptsas_phyinfo * | ||
2067 | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
2068 | { | ||
2069 | struct mptsas_portinfo *port_info; | ||
2070 | struct mptsas_phyinfo *phy_info = NULL; | ||
2071 | int i; | ||
2072 | |||
2073 | mutex_lock(&ioc->sas_topology_mutex); | ||
2074 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||
2075 | for (i = 0; i < port_info->num_phys; i++) { | ||
2047 | if (!mptsas_is_end_device( | 2076 | if (!mptsas_is_end_device( |
2048 | &port_info->phy_info[i].attached)) | 2077 | &port_info->phy_info[i].attached)) |
2049 | continue; | 2078 | continue; |
2079 | if (port_info->phy_info[i].attached.id != id) | ||
2080 | continue; | ||
2081 | if (port_info->phy_info[i].attached.channel != channel) | ||
2082 | continue; | ||
2050 | phy_info = &port_info->phy_info[i]; | 2083 | phy_info = &port_info->phy_info[i]; |
2051 | break; | 2084 | break; |
2052 | } | 2085 | } |
@@ -2056,7 +2089,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
2056 | } | 2089 | } |
2057 | 2090 | ||
2058 | static struct mptsas_phyinfo * | 2091 | static struct mptsas_phyinfo * |
2059 | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | 2092 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2060 | { | 2093 | { |
2061 | struct mptsas_portinfo *port_info; | 2094 | struct mptsas_portinfo *port_info; |
2062 | struct mptsas_phyinfo *phy_info = NULL; | 2095 | struct mptsas_phyinfo *phy_info = NULL; |
@@ -2065,11 +2098,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | |||
2065 | mutex_lock(&ioc->sas_topology_mutex); | 2098 | mutex_lock(&ioc->sas_topology_mutex); |
2066 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 2099 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
2067 | for (i = 0; i < port_info->num_phys; i++) { | 2100 | for (i = 0; i < port_info->num_phys; i++) { |
2068 | if (port_info->phy_info[i].attached.id != id) | ||
2069 | continue; | ||
2070 | if (!mptsas_is_end_device( | 2101 | if (!mptsas_is_end_device( |
2071 | &port_info->phy_info[i].attached)) | 2102 | &port_info->phy_info[i].attached)) |
2072 | continue; | 2103 | continue; |
2104 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) | ||
2105 | continue; | ||
2106 | if (port_info->phy_info[i].attached.phys_disk_num != id) | ||
2107 | continue; | ||
2108 | if (port_info->phy_info[i].attached.channel != channel) | ||
2109 | continue; | ||
2073 | phy_info = &port_info->phy_info[i]; | 2110 | phy_info = &port_info->phy_info[i]; |
2074 | break; | 2111 | break; |
2075 | } | 2112 | } |
@@ -2105,6 +2142,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) | |||
2105 | mptsas_reprobe_lun); | 2142 | mptsas_reprobe_lun); |
2106 | } | 2143 | } |
2107 | 2144 | ||
2145 | static void | ||
2146 | mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
2147 | { | ||
2148 | CONFIGPARMS cfg; | ||
2149 | ConfigPageHeader_t hdr; | ||
2150 | dma_addr_t dma_handle; | ||
2151 | pRaidVolumePage0_t buffer = NULL; | ||
2152 | RaidPhysDiskPage0_t phys_disk; | ||
2153 | int i; | ||
2154 | struct mptsas_hotplug_event *ev; | ||
2155 | |||
2156 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
2157 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
2158 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; | ||
2159 | cfg.pageAddr = (channel << 8) + id; | ||
2160 | cfg.cfghdr.hdr = &hdr; | ||
2161 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
2162 | |||
2163 | if (mpt_config(ioc, &cfg) != 0) | ||
2164 | goto out; | ||
2165 | |||
2166 | if (!hdr.PageLength) | ||
2167 | goto out; | ||
2168 | |||
2169 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
2170 | &dma_handle); | ||
2171 | |||
2172 | if (!buffer) | ||
2173 | goto out; | ||
2174 | |||
2175 | cfg.physAddr = dma_handle; | ||
2176 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
2177 | |||
2178 | if (mpt_config(ioc, &cfg) != 0) | ||
2179 | goto out; | ||
2180 | |||
2181 | if (!(buffer->VolumeStatus.Flags & | ||
2182 | MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)) | ||
2183 | goto out; | ||
2184 | |||
2185 | if (!buffer->NumPhysDisks) | ||
2186 | goto out; | ||
2187 | |||
2188 | for (i = 0; i < buffer->NumPhysDisks; i++) { | ||
2189 | |||
2190 | if (mpt_raid_phys_disk_pg0(ioc, | ||
2191 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||
2192 | continue; | ||
2193 | |||
2194 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
2195 | if (!ev) { | ||
2196 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | ||
2197 | goto out; | ||
2198 | } | ||
2199 | |||
2200 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
2201 | ev->ioc = ioc; | ||
2202 | ev->id = phys_disk.PhysDiskID; | ||
2203 | ev->channel = phys_disk.PhysDiskBus; | ||
2204 | ev->phys_disk_num_valid = 1; | ||
2205 | ev->phys_disk_num = phys_disk.PhysDiskNum; | ||
2206 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
2207 | schedule_work(&ev->work); | ||
2208 | } | ||
2209 | |||
2210 | out: | ||
2211 | if (buffer) | ||
2212 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
2213 | dma_handle); | ||
2214 | } | ||
2108 | /* | 2215 | /* |
2109 | * Work queue thread to handle SAS hotplug events | 2216 | * Work queue thread to handle SAS hotplug events |
2110 | */ | 2217 | */ |
@@ -2113,6 +2220,7 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2113 | { | 2220 | { |
2114 | struct mptsas_hotplug_event *ev = | 2221 | struct mptsas_hotplug_event *ev = |
2115 | container_of(work, struct mptsas_hotplug_event, work); | 2222 | container_of(work, struct mptsas_hotplug_event, work); |
2223 | |||
2116 | MPT_ADAPTER *ioc = ev->ioc; | 2224 | MPT_ADAPTER *ioc = ev->ioc; |
2117 | struct mptsas_phyinfo *phy_info; | 2225 | struct mptsas_phyinfo *phy_info; |
2118 | struct sas_rphy *rphy; | 2226 | struct sas_rphy *rphy; |
@@ -2125,17 +2233,43 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2125 | VirtTarget *vtarget; | 2233 | VirtTarget *vtarget; |
2126 | VirtDevice *vdevice; | 2234 | VirtDevice *vdevice; |
2127 | 2235 | ||
2128 | |||
2129 | mutex_lock(&ioc->sas_discovery_mutex); | 2236 | mutex_lock(&ioc->sas_discovery_mutex); |
2130 | switch (ev->event_type) { | 2237 | switch (ev->event_type) { |
2131 | case MPTSAS_DEL_DEVICE: | 2238 | case MPTSAS_DEL_DEVICE: |
2132 | 2239 | ||
2133 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); | 2240 | phy_info = NULL; |
2241 | if (ev->phys_disk_num_valid) { | ||
2242 | if (ev->hidden_raid_component){ | ||
2243 | if (mptsas_sas_device_pg0(ioc, &sas_device, | ||
2244 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||
2245 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
2246 | (ev->channel << 8) + ev->id)) { | ||
2247 | dfailprintk((MYIOC_s_ERR_FMT | ||
2248 | "%s: exit at line=%d\n", ioc->name, | ||
2249 | __FUNCTION__, __LINE__)); | ||
2250 | break; | ||
2251 | } | ||
2252 | phy_info = mptsas_find_phyinfo_by_sas_address( | ||
2253 | ioc, sas_device.sas_address); | ||
2254 | }else | ||
2255 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( | ||
2256 | ioc, ev->channel, ev->phys_disk_num); | ||
2257 | } | ||
2258 | |||
2259 | if (!phy_info) | ||
2260 | phy_info = mptsas_find_phyinfo_by_target(ioc, | ||
2261 | ev->channel, ev->id); | ||
2134 | 2262 | ||
2135 | /* | 2263 | /* |
2136 | * Sanity checks, for non-existing phys and remote rphys. | 2264 | * Sanity checks, for non-existing phys and remote rphys. |
2137 | */ | 2265 | */ |
2138 | if (!phy_info || !phy_info->port_details) { | 2266 | if (!phy_info){ |
2267 | dfailprintk((MYIOC_s_ERR_FMT | ||
2268 | "%s: exit at line=%d\n", ioc->name, | ||
2269 | __FUNCTION__, __LINE__)); | ||
2270 | break; | ||
2271 | } | ||
2272 | if (!phy_info->port_details) { | ||
2139 | dfailprintk((MYIOC_s_ERR_FMT | 2273 | dfailprintk((MYIOC_s_ERR_FMT |
2140 | "%s: exit at line=%d\n", ioc->name, | 2274 | "%s: exit at line=%d\n", ioc->name, |
2141 | __FUNCTION__, __LINE__)); | 2275 | __FUNCTION__, __LINE__)); |
@@ -2148,6 +2282,7 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2148 | __FUNCTION__, __LINE__)); | 2282 | __FUNCTION__, __LINE__)); |
2149 | break; | 2283 | break; |
2150 | } | 2284 | } |
2285 | |||
2151 | port = mptsas_get_port(phy_info); | 2286 | port = mptsas_get_port(phy_info); |
2152 | if (!port) { | 2287 | if (!port) { |
2153 | dfailprintk((MYIOC_s_ERR_FMT | 2288 | dfailprintk((MYIOC_s_ERR_FMT |
@@ -2170,28 +2305,38 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2170 | /* | 2305 | /* |
2171 | * Handling RAID components | 2306 | * Handling RAID components |
2172 | */ | 2307 | */ |
2173 | if (ev->phys_disk_num_valid) { | 2308 | if (ev->phys_disk_num_valid && |
2309 | ev->hidden_raid_component) { | ||
2310 | printk(MYIOC_s_INFO_FMT | ||
2311 | "RAID Hidding: channel=%d, id=%d, " | ||
2312 | "physdsk %d \n", ioc->name, ev->channel, | ||
2313 | ev->id, ev->phys_disk_num); | ||
2174 | vtarget->id = ev->phys_disk_num; | 2314 | vtarget->id = ev->phys_disk_num; |
2175 | vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | 2315 | vtarget->tflags |= |
2316 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
2176 | mptsas_reprobe_target(starget, 1); | 2317 | mptsas_reprobe_target(starget, 1); |
2177 | break; | 2318 | phy_info->attached.phys_disk_num = |
2319 | ev->phys_disk_num; | ||
2320 | break; | ||
2178 | } | 2321 | } |
2179 | 2322 | ||
2180 | vtarget->deleted = 1; | 2323 | vtarget->deleted = 1; |
2181 | mptsas_target_reset(ioc, vtarget); | 2324 | mptsas_target_reset(ioc, vtarget); |
2182 | } | 2325 | } |
2183 | 2326 | ||
2184 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 2327 | if (phy_info->attached.device_info & |
2328 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
2185 | ds = "ssp"; | 2329 | ds = "ssp"; |
2186 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 2330 | if (phy_info->attached.device_info & |
2331 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
2187 | ds = "stp"; | 2332 | ds = "stp"; |
2188 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 2333 | if (phy_info->attached.device_info & |
2334 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
2189 | ds = "sata"; | 2335 | ds = "sata"; |
2190 | 2336 | ||
2191 | printk(MYIOC_s_INFO_FMT | 2337 | printk(MYIOC_s_INFO_FMT |
2192 | "removing %s device, channel %d, id %d, phy %d\n", | 2338 | "removing %s device, channel %d, id %d, phy %d\n", |
2193 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | 2339 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); |
2194 | |||
2195 | #ifdef MPT_DEBUG_SAS_WIDE | 2340 | #ifdef MPT_DEBUG_SAS_WIDE |
2196 | dev_printk(KERN_DEBUG, &port->dev, | 2341 | dev_printk(KERN_DEBUG, &port->dev, |
2197 | "delete port (%d)\n", port->port_identifier); | 2342 | "delete port (%d)\n", port->port_identifier); |
@@ -2209,14 +2354,14 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2209 | */ | 2354 | */ |
2210 | if (mptsas_sas_device_pg0(ioc, &sas_device, | 2355 | if (mptsas_sas_device_pg0(ioc, &sas_device, |
2211 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 2356 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << |
2212 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { | 2357 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
2358 | (ev->channel << 8) + ev->id)) { | ||
2213 | dfailprintk((MYIOC_s_ERR_FMT | 2359 | dfailprintk((MYIOC_s_ERR_FMT |
2214 | "%s: exit at line=%d\n", ioc->name, | 2360 | "%s: exit at line=%d\n", ioc->name, |
2215 | __FUNCTION__, __LINE__)); | 2361 | __FUNCTION__, __LINE__)); |
2216 | break; | 2362 | break; |
2217 | } | 2363 | } |
2218 | 2364 | ||
2219 | ssleep(2); | ||
2220 | __mptsas_discovery_work(ioc); | 2365 | __mptsas_discovery_work(ioc); |
2221 | 2366 | ||
2222 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | 2367 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
@@ -2230,7 +2375,8 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2230 | } | 2375 | } |
2231 | 2376 | ||
2232 | starget = mptsas_get_starget(phy_info); | 2377 | starget = mptsas_get_starget(phy_info); |
2233 | if (starget) { | 2378 | if (starget && (!ev->hidden_raid_component)){ |
2379 | |||
2234 | vtarget = starget->hostdata; | 2380 | vtarget = starget->hostdata; |
2235 | 2381 | ||
2236 | if (!vtarget) { | 2382 | if (!vtarget) { |
@@ -2243,9 +2389,15 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2243 | * Handling RAID components | 2389 | * Handling RAID components |
2244 | */ | 2390 | */ |
2245 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2391 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { |
2246 | vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; | 2392 | printk(MYIOC_s_INFO_FMT |
2393 | "RAID Exposing: channel=%d, id=%d, " | ||
2394 | "physdsk %d \n", ioc->name, ev->channel, | ||
2395 | ev->id, ev->phys_disk_num); | ||
2396 | vtarget->tflags &= | ||
2397 | ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
2247 | vtarget->id = ev->id; | 2398 | vtarget->id = ev->id; |
2248 | mptsas_reprobe_target(starget, 0); | 2399 | mptsas_reprobe_target(starget, 0); |
2400 | phy_info->attached.phys_disk_num = ~0; | ||
2249 | } | 2401 | } |
2250 | break; | 2402 | break; |
2251 | } | 2403 | } |
@@ -2254,8 +2406,10 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2254 | dfailprintk((MYIOC_s_ERR_FMT | 2406 | dfailprintk((MYIOC_s_ERR_FMT |
2255 | "%s: exit at line=%d\n", ioc->name, | 2407 | "%s: exit at line=%d\n", ioc->name, |
2256 | __FUNCTION__, __LINE__)); | 2408 | __FUNCTION__, __LINE__)); |
2409 | if (ev->channel) printk("%d\n", __LINE__); | ||
2257 | break; | 2410 | break; |
2258 | } | 2411 | } |
2412 | |||
2259 | port = mptsas_get_port(phy_info); | 2413 | port = mptsas_get_port(phy_info); |
2260 | if (!port) { | 2414 | if (!port) { |
2261 | dfailprintk((MYIOC_s_ERR_FMT | 2415 | dfailprintk((MYIOC_s_ERR_FMT |
@@ -2263,15 +2417,17 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2263 | __FUNCTION__, __LINE__)); | 2417 | __FUNCTION__, __LINE__)); |
2264 | break; | 2418 | break; |
2265 | } | 2419 | } |
2266 | |||
2267 | memcpy(&phy_info->attached, &sas_device, | 2420 | memcpy(&phy_info->attached, &sas_device, |
2268 | sizeof(struct mptsas_devinfo)); | 2421 | sizeof(struct mptsas_devinfo)); |
2269 | 2422 | ||
2270 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 2423 | if (phy_info->attached.device_info & |
2424 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
2271 | ds = "ssp"; | 2425 | ds = "ssp"; |
2272 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 2426 | if (phy_info->attached.device_info & |
2427 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
2273 | ds = "stp"; | 2428 | ds = "stp"; |
2274 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 2429 | if (phy_info->attached.device_info & |
2430 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
2275 | ds = "sata"; | 2431 | ds = "sata"; |
2276 | 2432 | ||
2277 | printk(MYIOC_s_INFO_FMT | 2433 | printk(MYIOC_s_INFO_FMT |
@@ -2312,19 +2468,23 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2312 | break; | 2468 | break; |
2313 | case MPTSAS_DEL_RAID: | 2469 | case MPTSAS_DEL_RAID: |
2314 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | 2470 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, |
2315 | ev->id, 0); | 2471 | ev->id, 0); |
2316 | if (!sdev) | 2472 | if (!sdev) |
2317 | break; | 2473 | break; |
2318 | printk(MYIOC_s_INFO_FMT | 2474 | printk(MYIOC_s_INFO_FMT |
2319 | "removing raid volume, channel %d, id %d\n", | 2475 | "removing raid volume, channel %d, id %d\n", |
2320 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | 2476 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); |
2321 | vdevice = sdev->hostdata; | ||
2322 | vdevice->vtarget->deleted = 1; | 2477 | vdevice->vtarget->deleted = 1; |
2323 | mptsas_target_reset(ioc, vdevice->vtarget); | 2478 | mptsas_target_reset(ioc, vdevice->vtarget); |
2479 | vdevice = sdev->hostdata; | ||
2324 | scsi_remove_device(sdev); | 2480 | scsi_remove_device(sdev); |
2325 | scsi_device_put(sdev); | 2481 | scsi_device_put(sdev); |
2326 | mpt_findImVolumes(ioc); | 2482 | mpt_findImVolumes(ioc); |
2327 | break; | 2483 | break; |
2484 | case MPTSAS_ADD_INACTIVE_VOLUME: | ||
2485 | mptsas_adding_inactive_raid_components(ioc, | ||
2486 | ev->channel, ev->id); | ||
2487 | break; | ||
2328 | case MPTSAS_IGNORE_EVENT: | 2488 | case MPTSAS_IGNORE_EVENT: |
2329 | default: | 2489 | default: |
2330 | break; | 2490 | break; |
@@ -2332,7 +2492,6 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2332 | 2492 | ||
2333 | mutex_unlock(&ioc->sas_discovery_mutex); | 2493 | mutex_unlock(&ioc->sas_discovery_mutex); |
2334 | kfree(ev); | 2494 | kfree(ev); |
2335 | |||
2336 | } | 2495 | } |
2337 | 2496 | ||
2338 | static void | 2497 | static void |
@@ -2386,15 +2545,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, | |||
2386 | mptsas_persist_clear_table); | 2545 | mptsas_persist_clear_table); |
2387 | schedule_work(&ioc->sas_persist_task); | 2546 | schedule_work(&ioc->sas_persist_task); |
2388 | break; | 2547 | break; |
2548 | /* | ||
2549 | * TODO, handle other events | ||
2550 | */ | ||
2389 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | 2551 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: |
2390 | /* TODO */ | 2552 | case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: |
2391 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | 2553 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: |
2392 | /* TODO */ | 2554 | case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: |
2555 | case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: | ||
2556 | case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: | ||
2557 | case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: | ||
2393 | default: | 2558 | default: |
2394 | break; | 2559 | break; |
2395 | } | 2560 | } |
2396 | } | 2561 | } |
2397 | |||
2398 | static void | 2562 | static void |
2399 | mptsas_send_raid_event(MPT_ADAPTER *ioc, | 2563 | mptsas_send_raid_event(MPT_ADAPTER *ioc, |
2400 | EVENT_DATA_RAID *raid_event_data) | 2564 | EVENT_DATA_RAID *raid_event_data) |
@@ -2415,31 +2579,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, | |||
2415 | INIT_WORK(&ev->work, mptsas_hotplug_work); | 2579 | INIT_WORK(&ev->work, mptsas_hotplug_work); |
2416 | ev->ioc = ioc; | 2580 | ev->ioc = ioc; |
2417 | ev->id = raid_event_data->VolumeID; | 2581 | ev->id = raid_event_data->VolumeID; |
2582 | ev->channel = raid_event_data->VolumeBus; | ||
2418 | ev->event_type = MPTSAS_IGNORE_EVENT; | 2583 | ev->event_type = MPTSAS_IGNORE_EVENT; |
2419 | 2584 | ||
2420 | switch (raid_event_data->ReasonCode) { | 2585 | switch (raid_event_data->ReasonCode) { |
2421 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: | 2586 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: |
2587 | ev->phys_disk_num_valid = 1; | ||
2588 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
2422 | ev->event_type = MPTSAS_ADD_DEVICE; | 2589 | ev->event_type = MPTSAS_ADD_DEVICE; |
2423 | break; | 2590 | break; |
2424 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 2591 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: |
2425 | ioc->raid_data.isRaid = 1; | ||
2426 | ev->phys_disk_num_valid = 1; | 2592 | ev->phys_disk_num_valid = 1; |
2427 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | 2593 | ev->phys_disk_num = raid_event_data->PhysDiskNum; |
2594 | ev->hidden_raid_component = 1; | ||
2428 | ev->event_type = MPTSAS_DEL_DEVICE; | 2595 | ev->event_type = MPTSAS_DEL_DEVICE; |
2429 | break; | 2596 | break; |
2430 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: | 2597 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: |
2431 | switch (state) { | 2598 | switch (state) { |
2432 | case MPI_PD_STATE_ONLINE: | 2599 | case MPI_PD_STATE_ONLINE: |
2433 | ioc->raid_data.isRaid = 1; | 2600 | case MPI_PD_STATE_NOT_COMPATIBLE: |
2434 | ev->phys_disk_num_valid = 1; | 2601 | ev->phys_disk_num_valid = 1; |
2435 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | 2602 | ev->phys_disk_num = raid_event_data->PhysDiskNum; |
2603 | ev->hidden_raid_component = 1; | ||
2436 | ev->event_type = MPTSAS_ADD_DEVICE; | 2604 | ev->event_type = MPTSAS_ADD_DEVICE; |
2437 | break; | 2605 | break; |
2438 | case MPI_PD_STATE_MISSING: | 2606 | case MPI_PD_STATE_MISSING: |
2439 | case MPI_PD_STATE_NOT_COMPATIBLE: | ||
2440 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: | 2607 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: |
2441 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: | 2608 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: |
2442 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: | 2609 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: |
2610 | ev->phys_disk_num_valid = 1; | ||
2611 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
2443 | ev->event_type = MPTSAS_DEL_DEVICE; | 2612 | ev->event_type = MPTSAS_DEL_DEVICE; |
2444 | break; | 2613 | break; |
2445 | default: | 2614 | default: |
@@ -2496,6 +2665,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, | |||
2496 | schedule_work(&ev->work); | 2665 | schedule_work(&ev->work); |
2497 | }; | 2666 | }; |
2498 | 2667 | ||
2668 | /* | ||
2669 | * mptsas_send_ir2_event - handle exposing hidden disk when | ||
2670 | * an inactive raid volume is added | ||
2671 | * | ||
2672 | * @ioc: Pointer to MPT_ADAPTER structure | ||
2673 | * @ir2_data | ||
2674 | * | ||
2675 | */ | ||
2676 | static void | ||
2677 | mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) | ||
2678 | { | ||
2679 | struct mptsas_hotplug_event *ev; | ||
2680 | |||
2681 | if (ir2_data->ReasonCode != | ||
2682 | MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) | ||
2683 | return; | ||
2684 | |||
2685 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
2686 | if (!ev) | ||
2687 | return; | ||
2688 | |||
2689 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
2690 | ev->ioc = ioc; | ||
2691 | ev->id = ir2_data->TargetID; | ||
2692 | ev->channel = ir2_data->Bus; | ||
2693 | ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; | ||
2694 | |||
2695 | schedule_work(&ev->work); | ||
2696 | }; | ||
2499 | 2697 | ||
2500 | static int | 2698 | static int |
2501 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | 2699 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) |
@@ -2535,6 +2733,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | |||
2535 | mptsas_send_discovery_event(ioc, | 2733 | mptsas_send_discovery_event(ioc, |
2536 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); | 2734 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); |
2537 | break; | 2735 | break; |
2736 | case MPI_EVENT_IR2: | ||
2737 | mptsas_send_ir2_event(ioc, | ||
2738 | (PTR_MPI_EVENT_DATA_IR2)reply->Data); | ||
2739 | break; | ||
2538 | default: | 2740 | default: |
2539 | rc = mptscsih_event_process(ioc, reply); | 2741 | rc = mptscsih_event_process(ioc, reply); |
2540 | break; | 2742 | break; |
@@ -2742,7 +2944,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | |||
2742 | struct mptsas_portinfo *p, *n; | 2944 | struct mptsas_portinfo *p, *n; |
2743 | int i; | 2945 | int i; |
2744 | 2946 | ||
2745 | ioc->sas_discovery_ignore_events=1; | 2947 | ioc->sas_discovery_ignore_events = 1; |
2746 | sas_remove_host(ioc->sh); | 2948 | sas_remove_host(ioc->sh); |
2747 | 2949 | ||
2748 | mutex_lock(&ioc->sas_topology_mutex); | 2950 | mutex_lock(&ioc->sas_topology_mutex); |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 507aa08611d5..f9e11c8db462 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -2244,6 +2244,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | |||
2244 | int | 2244 | int |
2245 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2245 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2246 | { | 2246 | { |
2247 | struct inactive_raid_component_info *component_info; | ||
2247 | int i; | 2248 | int i; |
2248 | int rc = 0; | 2249 | int rc = 0; |
2249 | 2250 | ||
@@ -2257,6 +2258,21 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
2257 | } | 2258 | } |
2258 | } | 2259 | } |
2259 | 2260 | ||
2261 | /* | ||
2262 | * Check inactive list for matching phys disks | ||
2263 | */ | ||
2264 | if (list_empty(&ioc->raid_data.inactive_list)) | ||
2265 | goto out; | ||
2266 | |||
2267 | down(&ioc->raid_data.inactive_list_mutex); | ||
2268 | list_for_each_entry(component_info, &ioc->raid_data.inactive_list, | ||
2269 | list) { | ||
2270 | if ((component_info->d.PhysDiskID == id) && | ||
2271 | (component_info->d.PhysDiskBus == channel)) | ||
2272 | rc = 1; | ||
2273 | } | ||
2274 | up(&ioc->raid_data.inactive_list_mutex); | ||
2275 | |||
2260 | out: | 2276 | out: |
2261 | return rc; | 2277 | return rc; |
2262 | } | 2278 | } |
@@ -2265,6 +2281,7 @@ EXPORT_SYMBOL(mptscsih_is_phys_disk); | |||
2265 | u8 | 2281 | u8 |
2266 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2282 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2267 | { | 2283 | { |
2284 | struct inactive_raid_component_info *component_info; | ||
2268 | int i; | 2285 | int i; |
2269 | int rc = -ENXIO; | 2286 | int rc = -ENXIO; |
2270 | 2287 | ||
@@ -2278,6 +2295,21 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
2278 | } | 2295 | } |
2279 | } | 2296 | } |
2280 | 2297 | ||
2298 | /* | ||
2299 | * Check inactive list for matching phys disks | ||
2300 | */ | ||
2301 | if (list_empty(&ioc->raid_data.inactive_list)) | ||
2302 | goto out; | ||
2303 | |||
2304 | down(&ioc->raid_data.inactive_list_mutex); | ||
2305 | list_for_each_entry(component_info, &ioc->raid_data.inactive_list, | ||
2306 | list) { | ||
2307 | if ((component_info->d.PhysDiskID == id) && | ||
2308 | (component_info->d.PhysDiskBus == channel)) | ||
2309 | rc = component_info->d.PhysDiskNum; | ||
2310 | } | ||
2311 | up(&ioc->raid_data.inactive_list_mutex); | ||
2312 | |||
2281 | out: | 2313 | out: |
2282 | return rc; | 2314 | return rc; |
2283 | } | 2315 | } |
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 06a7b86f5f23..5398aeab191d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
@@ -1363,8 +1363,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1363 | /* | 1363 | /* |
1364 | * If RAID Firmware Detected, setup virtual channel | 1364 | * If RAID Firmware Detected, setup virtual channel |
1365 | */ | 1365 | */ |
1366 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 1366 | if (ioc->ir_firmware) |
1367 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | ||
1368 | sh->max_channel = 1; | 1367 | sh->max_channel = 1; |
1369 | else | 1368 | else |
1370 | sh->max_channel = 0; | 1369 | sh->max_channel = 0; |