aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2007-01-29 11:45:37 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-02 22:01:28 -0500
commitb506ade9f3c309ac2ce3ffc4039f731097506038 (patch)
tree26ffb22dd5859977e92ca57f01033da69a6265f5 /drivers/message/fusion/mptbase.c
parentc6c727a1a0ff90c80425b7226557b2354e00cf7b (diff)
[SCSI] fusion - inactive raid support, and raid event bug fix's
inactive raid support, e.g. exposing hidden raid components belonging to a volume that are inactive. Also misc bug fix's for various raid asyn events. Signed-off-by: Eric Moore <Eric.Moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c278
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);
184static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); 184static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
185static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); 185static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
186static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); 186static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
187static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
187 188
188/* module entry point */ 189/* module entry point */
189static int __init fusion_init (void); 190static 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 **/
4749static void
4750mpt_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 **/
4777static void
4778mpt_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 **/
4865int
4866mpt_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 **/
4741int 4932int
4742mpt_findImVolumes(MPT_ADAPTER *ioc) 4933mpt_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
4830done_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);
6833EXPORT_SYMBOL(mpt_alloc_fw_memory); 6998EXPORT_SYMBOL(mpt_alloc_fw_memory);
6834EXPORT_SYMBOL(mpt_free_fw_memory); 6999EXPORT_SYMBOL(mpt_free_fw_memory);
6835EXPORT_SYMBOL(mptbase_sas_persist_operation); 7000EXPORT_SYMBOL(mptbase_sas_persist_operation);
7001EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
6836 7002
6837/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7003/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6838/** 7004/**