diff options
| author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-05-29 07:23:56 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-09 18:44:11 -0400 |
| commit | a7938b0bb3b458fe0723608be3db6c4ed8d79a8c (patch) | |
| tree | 6654a67ee51d52e1447ed970801b2fb9106f3867 | |
| parent | 71278192a887d7da3e768809c6fe9979d172ff23 (diff) | |
[SCSI] mpt fusion: RAID device handling and Dual port Raid support is added
1. Handle integrated Raid device(Add/Delete) and error condition and check
related to Raid device. is_logical_volume will represent logical volume
device.
2. Raid device dual port support is added. Main functions to support this
feature are mpt_raid_phys_disk_get_num_paths and mpt_raid_phys_disk_pg1.
Signed-off-by: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
| -rw-r--r-- | drivers/message/fusion/mptbase.c | 167 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.h | 4 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 332 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.h | 1 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 85 |
5 files changed, 527 insertions, 62 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 9f6b315624aa..44b931504457 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -5763,6 +5763,161 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, | |||
| 5763 | } | 5763 | } |
| 5764 | 5764 | ||
| 5765 | /** | 5765 | /** |
| 5766 | * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num | ||
| 5767 | * @ioc: Pointer to a Adapter Structure | ||
| 5768 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
| 5769 | * | ||
| 5770 | * Return: | ||
| 5771 | * returns number paths | ||
| 5772 | **/ | ||
| 5773 | int | ||
| 5774 | mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num) | ||
| 5775 | { | ||
| 5776 | CONFIGPARMS cfg; | ||
| 5777 | ConfigPageHeader_t hdr; | ||
| 5778 | dma_addr_t dma_handle; | ||
| 5779 | pRaidPhysDiskPage1_t buffer = NULL; | ||
| 5780 | int rc; | ||
| 5781 | |||
| 5782 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 5783 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 5784 | |||
| 5785 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
| 5786 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
| 5787 | hdr.PageNumber = 1; | ||
| 5788 | cfg.cfghdr.hdr = &hdr; | ||
| 5789 | cfg.physAddr = -1; | ||
| 5790 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 5791 | |||
| 5792 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5793 | rc = 0; | ||
| 5794 | goto out; | ||
| 5795 | } | ||
| 5796 | |||
| 5797 | if (!hdr.PageLength) { | ||
| 5798 | rc = 0; | ||
| 5799 | goto out; | ||
| 5800 | } | ||
| 5801 | |||
| 5802 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 5803 | &dma_handle); | ||
| 5804 | |||
| 5805 | if (!buffer) { | ||
| 5806 | rc = 0; | ||
| 5807 | goto out; | ||
| 5808 | } | ||
| 5809 | |||
| 5810 | cfg.physAddr = dma_handle; | ||
| 5811 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 5812 | cfg.pageAddr = phys_disk_num; | ||
| 5813 | |||
| 5814 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5815 | rc = 0; | ||
| 5816 | goto out; | ||
| 5817 | } | ||
| 5818 | |||
| 5819 | rc = buffer->NumPhysDiskPaths; | ||
| 5820 | out: | ||
| 5821 | |||
| 5822 | if (buffer) | ||
| 5823 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 5824 | dma_handle); | ||
| 5825 | |||
| 5826 | return rc; | ||
| 5827 | } | ||
| 5828 | EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths); | ||
| 5829 | |||
| 5830 | /** | ||
| 5831 | * mpt_raid_phys_disk_pg1 - returns phys disk page 1 | ||
| 5832 | * @ioc: Pointer to a Adapter Structure | ||
| 5833 | * @phys_disk_num: io unit unique phys disk num generated by the ioc | ||
| 5834 | * @phys_disk: requested payload data returned | ||
| 5835 | * | ||
| 5836 | * Return: | ||
| 5837 | * 0 on success | ||
| 5838 | * -EFAULT if read of config page header fails or data pointer not NULL | ||
| 5839 | * -ENOMEM if pci_alloc failed | ||
| 5840 | **/ | ||
| 5841 | int | ||
| 5842 | mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, | ||
| 5843 | RaidPhysDiskPage1_t *phys_disk) | ||
| 5844 | { | ||
| 5845 | CONFIGPARMS cfg; | ||
| 5846 | ConfigPageHeader_t hdr; | ||
| 5847 | dma_addr_t dma_handle; | ||
| 5848 | pRaidPhysDiskPage1_t buffer = NULL; | ||
| 5849 | int rc; | ||
| 5850 | int i; | ||
| 5851 | __le64 sas_address; | ||
| 5852 | |||
| 5853 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 5854 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 5855 | rc = 0; | ||
| 5856 | |||
| 5857 | hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; | ||
| 5858 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
| 5859 | hdr.PageNumber = 1; | ||
| 5860 | cfg.cfghdr.hdr = &hdr; | ||
| 5861 | cfg.physAddr = -1; | ||
| 5862 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 5863 | |||
| 5864 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5865 | rc = -EFAULT; | ||
| 5866 | goto out; | ||
| 5867 | } | ||
| 5868 | |||
| 5869 | if (!hdr.PageLength) { | ||
| 5870 | rc = -EFAULT; | ||
| 5871 | goto out; | ||
| 5872 | } | ||
| 5873 | |||
| 5874 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 5875 | &dma_handle); | ||
| 5876 | |||
| 5877 | if (!buffer) { | ||
| 5878 | rc = -ENOMEM; | ||
| 5879 | goto out; | ||
| 5880 | } | ||
| 5881 | |||
| 5882 | cfg.physAddr = dma_handle; | ||
| 5883 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 5884 | cfg.pageAddr = phys_disk_num; | ||
| 5885 | |||
| 5886 | if (mpt_config(ioc, &cfg) != 0) { | ||
| 5887 | rc = -EFAULT; | ||
| 5888 | goto out; | ||
| 5889 | } | ||
| 5890 | |||
| 5891 | phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths; | ||
| 5892 | phys_disk->PhysDiskNum = phys_disk_num; | ||
| 5893 | for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) { | ||
| 5894 | phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID; | ||
| 5895 | phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus; | ||
| 5896 | phys_disk->Path[i].OwnerIdentifier = | ||
| 5897 | buffer->Path[i].OwnerIdentifier; | ||
| 5898 | phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags); | ||
| 5899 | memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64)); | ||
| 5900 | sas_address = le64_to_cpu(sas_address); | ||
| 5901 | memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64)); | ||
| 5902 | memcpy(&sas_address, | ||
| 5903 | &buffer->Path[i].OwnerWWID, sizeof(__le64)); | ||
| 5904 | sas_address = le64_to_cpu(sas_address); | ||
| 5905 | memcpy(&phys_disk->Path[i].OwnerWWID, | ||
| 5906 | &sas_address, sizeof(__le64)); | ||
| 5907 | } | ||
| 5908 | |||
| 5909 | out: | ||
| 5910 | |||
| 5911 | if (buffer) | ||
| 5912 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 5913 | dma_handle); | ||
| 5914 | |||
| 5915 | return rc; | ||
| 5916 | } | ||
| 5917 | EXPORT_SYMBOL(mpt_raid_phys_disk_pg1); | ||
| 5918 | |||
| 5919 | |||
| 5920 | /** | ||
| 5766 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes | 5921 | * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes |
| 5767 | * @ioc: Pointer to a Adapter Strucutre | 5922 | * @ioc: Pointer to a Adapter Strucutre |
| 5768 | * | 5923 | * |
| @@ -7170,6 +7325,18 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) | |||
| 7170 | "id=%d channel=%d phys_num=%d", | 7325 | "id=%d channel=%d phys_num=%d", |
| 7171 | id, channel, phys_num); | 7326 | id, channel, phys_num); |
| 7172 | break; | 7327 | break; |
| 7328 | case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: | ||
| 7329 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
| 7330 | "IR2: Dual Port Added: " | ||
| 7331 | "id=%d channel=%d phys_num=%d", | ||
| 7332 | id, channel, phys_num); | ||
| 7333 | break; | ||
| 7334 | case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: | ||
| 7335 | snprintf(evStr, EVENT_DESCR_STR_SZ, | ||
| 7336 | "IR2: Dual Port Removed: " | ||
| 7337 | "id=%d channel=%d phys_num=%d", | ||
| 7338 | id, channel, phys_num); | ||
| 7339 | break; | ||
| 7173 | default: | 7340 | default: |
| 7174 | ds = "IR2"; | 7341 | ds = "IR2"; |
| 7175 | break; | 7342 | break; |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 91499d1275c4..4f3d4c34bcd8 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
| @@ -958,6 +958,10 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | |||
| 958 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 958 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
| 959 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 959 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
| 960 | extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); | 960 | extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); |
| 961 | extern int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, | ||
| 962 | pRaidPhysDiskPage1_t phys_disk); | ||
| 963 | extern int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, | ||
| 964 | u8 phys_disk_num); | ||
| 961 | extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); | 965 | extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); |
| 962 | extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); | 966 | extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); |
| 963 | extern void mpt_halt_firmware(MPT_ADAPTER *ioc); | 967 | extern void mpt_halt_firmware(MPT_ADAPTER *ioc); |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index da22141152d7..72158237f5e8 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -121,6 +121,7 @@ static void mptsas_expander_delete(MPT_ADAPTER *ioc, | |||
| 121 | static void mptsas_send_expander_event(struct fw_event_work *fw_event); | 121 | static void mptsas_send_expander_event(struct fw_event_work *fw_event); |
| 122 | static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); | 122 | static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); |
| 123 | static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); | 123 | static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); |
| 124 | static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id); | ||
| 124 | 125 | ||
| 125 | static void mptsas_print_phy_data(MPT_ADAPTER *ioc, | 126 | static void mptsas_print_phy_data(MPT_ADAPTER *ioc, |
| 126 | MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) | 127 | MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) |
| @@ -542,9 +543,10 @@ mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id, | |||
| 542 | mutex_lock(&ioc->sas_device_info_mutex); | 543 | mutex_lock(&ioc->sas_device_info_mutex); |
| 543 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | 544 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, |
| 544 | list) { | 545 | list) { |
| 545 | if ((sas_info->sas_address == sas_address || | 546 | if (!sas_info->is_logical_volume && |
| 546 | (sas_info->fw.channel == channel && | 547 | (sas_info->sas_address == sas_address || |
| 547 | sas_info->fw.id == id))) { | 548 | (sas_info->fw.channel == channel && |
| 549 | sas_info->fw.id == id))) { | ||
| 548 | list_del(&sas_info->list); | 550 | list_del(&sas_info->list); |
| 549 | kfree(sas_info); | 551 | kfree(sas_info); |
| 550 | } | 552 | } |
| @@ -617,6 +619,100 @@ mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 617 | } | 619 | } |
| 618 | 620 | ||
| 619 | /** | 621 | /** |
| 622 | * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding | ||
| 623 | * each individual device to list | ||
| 624 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 625 | * @channel: fw mapped id's | ||
| 626 | * @id: | ||
| 627 | * | ||
| 628 | **/ | ||
| 629 | static void | ||
| 630 | mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc, | ||
| 631 | struct scsi_target *starget) | ||
| 632 | { | ||
| 633 | CONFIGPARMS cfg; | ||
| 634 | ConfigPageHeader_t hdr; | ||
| 635 | dma_addr_t dma_handle; | ||
| 636 | pRaidVolumePage0_t buffer = NULL; | ||
| 637 | int i; | ||
| 638 | RaidPhysDiskPage0_t phys_disk; | ||
| 639 | struct mptsas_device_info *sas_info, *next; | ||
| 640 | |||
| 641 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
| 642 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
| 643 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; | ||
| 644 | /* assumption that all volumes on channel = 0 */ | ||
| 645 | cfg.pageAddr = starget->id; | ||
| 646 | cfg.cfghdr.hdr = &hdr; | ||
| 647 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 648 | cfg.timeout = 10; | ||
| 649 | |||
| 650 | if (mpt_config(ioc, &cfg) != 0) | ||
| 651 | goto out; | ||
| 652 | |||
| 653 | if (!hdr.PageLength) | ||
| 654 | goto out; | ||
| 655 | |||
| 656 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
| 657 | &dma_handle); | ||
| 658 | |||
| 659 | if (!buffer) | ||
| 660 | goto out; | ||
| 661 | |||
| 662 | cfg.physAddr = dma_handle; | ||
| 663 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 664 | |||
| 665 | if (mpt_config(ioc, &cfg) != 0) | ||
| 666 | goto out; | ||
| 667 | |||
| 668 | if (!buffer->NumPhysDisks) | ||
| 669 | goto out; | ||
| 670 | |||
| 671 | /* | ||
| 672 | * Adding entry for hidden components | ||
| 673 | */ | ||
| 674 | for (i = 0; i < buffer->NumPhysDisks; i++) { | ||
| 675 | |||
| 676 | if (mpt_raid_phys_disk_pg0(ioc, | ||
| 677 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||
| 678 | continue; | ||
| 679 | |||
| 680 | mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus, | ||
| 681 | phys_disk.PhysDiskID); | ||
| 682 | |||
| 683 | } | ||
| 684 | |||
| 685 | /* | ||
| 686 | * Delete all matching devices out of the list | ||
| 687 | */ | ||
| 688 | mutex_lock(&ioc->sas_device_info_mutex); | ||
| 689 | list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, | ||
| 690 | list) { | ||
| 691 | if (sas_info->is_logical_volume && sas_info->fw.id == | ||
| 692 | starget->id) { | ||
| 693 | list_del(&sas_info->list); | ||
| 694 | kfree(sas_info); | ||
| 695 | } | ||
| 696 | } | ||
| 697 | |||
| 698 | sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL); | ||
| 699 | if (sas_info) { | ||
| 700 | sas_info->fw.id = starget->id; | ||
| 701 | sas_info->os.id = starget->id; | ||
| 702 | sas_info->os.channel = starget->channel; | ||
| 703 | sas_info->is_logical_volume = 1; | ||
| 704 | INIT_LIST_HEAD(&sas_info->list); | ||
| 705 | list_add_tail(&sas_info->list, &ioc->sas_device_info_list); | ||
| 706 | } | ||
| 707 | mutex_unlock(&ioc->sas_device_info_mutex); | ||
| 708 | |||
| 709 | out: | ||
| 710 | if (buffer) | ||
| 711 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
| 712 | dma_handle); | ||
| 713 | } | ||
| 714 | |||
| 715 | /** | ||
| 620 | * mptsas_add_device_component_starget - | 716 | * mptsas_add_device_component_starget - |
| 621 | * @ioc: Pointer to MPT_ADAPTER structure | 717 | * @ioc: Pointer to MPT_ADAPTER structure |
| 622 | * @starget: | 718 | * @starget: |
| @@ -817,6 +913,10 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 817 | if ((vdevice == NULL) || | 913 | if ((vdevice == NULL) || |
| 818 | (vdevice->vtarget == NULL)) | 914 | (vdevice->vtarget == NULL)) |
| 819 | continue; | 915 | continue; |
| 916 | if ((vdevice->vtarget->tflags & | ||
| 917 | MPT_TARGET_FLAGS_RAID_COMPONENT || | ||
| 918 | vdevice->vtarget->raidVolume)) | ||
| 919 | continue; | ||
| 820 | if (vdevice->vtarget->id == id && | 920 | if (vdevice->vtarget->id == id && |
| 821 | vdevice->vtarget->channel == channel) | 921 | vdevice->vtarget->channel == channel) |
| 822 | vtarget = vdevice->vtarget; | 922 | vtarget = vdevice->vtarget; |
| @@ -1487,9 +1587,21 @@ mptsas_slave_configure(struct scsi_device *sdev) | |||
| 1487 | struct Scsi_Host *host = sdev->host; | 1587 | struct Scsi_Host *host = sdev->host; |
| 1488 | MPT_SCSI_HOST *hd = shost_priv(host); | 1588 | MPT_SCSI_HOST *hd = shost_priv(host); |
| 1489 | MPT_ADAPTER *ioc = hd->ioc; | 1589 | MPT_ADAPTER *ioc = hd->ioc; |
| 1590 | VirtDevice *vdevice = sdev->hostdata; | ||
| 1490 | 1591 | ||
| 1491 | if (sdev->channel == MPTSAS_RAID_CHANNEL) | 1592 | if (vdevice->vtarget->deleted) { |
| 1593 | sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n"); | ||
| 1594 | vdevice->vtarget->deleted = 0; | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | /* | ||
| 1598 | * RAID volumes placed beyond the last expected port. | ||
| 1599 | * Ignore sending sas mode pages in that case.. | ||
| 1600 | */ | ||
| 1601 | if (sdev->channel == MPTSAS_RAID_CHANNEL) { | ||
| 1602 | mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev)); | ||
| 1492 | goto out; | 1603 | goto out; |
| 1604 | } | ||
| 1493 | 1605 | ||
| 1494 | sas_read_port_mode_page(sdev); | 1606 | sas_read_port_mode_page(sdev); |
| 1495 | 1607 | ||
| @@ -1525,9 +1637,18 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
| 1525 | * RAID volumes placed beyond the last expected port. | 1637 | * RAID volumes placed beyond the last expected port. |
| 1526 | */ | 1638 | */ |
| 1527 | if (starget->channel == MPTSAS_RAID_CHANNEL) { | 1639 | if (starget->channel == MPTSAS_RAID_CHANNEL) { |
| 1528 | for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) | 1640 | if (!ioc->raid_data.pIocPg2) { |
| 1529 | if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) | 1641 | kfree(vtarget); |
| 1530 | channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; | 1642 | return -ENXIO; |
| 1643 | } | ||
| 1644 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | ||
| 1645 | if (id == ioc->raid_data.pIocPg2-> | ||
| 1646 | RaidVolume[i].VolumeID) { | ||
| 1647 | channel = ioc->raid_data.pIocPg2-> | ||
| 1648 | RaidVolume[i].VolumeBus; | ||
| 1649 | } | ||
| 1650 | } | ||
| 1651 | vtarget->raidVolume = 1; | ||
| 1531 | goto out; | 1652 | goto out; |
| 1532 | } | 1653 | } |
| 1533 | 1654 | ||
| @@ -3277,59 +3398,66 @@ mptsas_not_responding_devices(MPT_ADAPTER *ioc) | |||
| 3277 | mutex_lock(&ioc->sas_device_info_mutex); | 3398 | mutex_lock(&ioc->sas_device_info_mutex); |
| 3278 | redo_device_scan: | 3399 | redo_device_scan: |
| 3279 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { | 3400 | list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { |
| 3280 | sas_device.handle = 0; | 3401 | if (!sas_info->is_logical_volume) { |
| 3281 | retry_count = 0; | 3402 | sas_device.handle = 0; |
| 3403 | retry_count = 0; | ||
| 3282 | retry_page: | 3404 | retry_page: |
| 3283 | retval = mptsas_sas_device_pg0(ioc, &sas_device, | 3405 | retval = mptsas_sas_device_pg0(ioc, &sas_device, |
| 3284 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID | 3406 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID |
| 3285 | << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 3407 | << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
| 3286 | (sas_info->fw.channel << 8) + | 3408 | (sas_info->fw.channel << 8) + |
| 3287 | sas_info->fw.id); | 3409 | sas_info->fw.id); |
| 3288 | 3410 | ||
| 3289 | if (sas_device.handle) | 3411 | if (sas_device.handle) |
| 3290 | continue; | 3412 | continue; |
| 3291 | if (retval == -EBUSY) { | 3413 | if (retval == -EBUSY) { |
| 3292 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | 3414 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
| 3293 | if (ioc->ioc_reset_in_progress) { | 3415 | if (ioc->ioc_reset_in_progress) { |
| 3294 | dfailprintk(ioc, | 3416 | dfailprintk(ioc, |
| 3295 | printk(MYIOC_s_DEBUG_FMT | 3417 | printk(MYIOC_s_DEBUG_FMT |
| 3296 | "%s: exiting due to reset\n", | 3418 | "%s: exiting due to reset\n", |
| 3297 | ioc->name, __func__)); | 3419 | ioc->name, __func__)); |
| 3298 | spin_unlock_irqrestore | 3420 | spin_unlock_irqrestore |
| 3299 | (&ioc->taskmgmt_lock, flags); | 3421 | (&ioc->taskmgmt_lock, flags); |
| 3300 | mutex_unlock(&ioc->sas_device_info_mutex); | 3422 | mutex_unlock(&ioc-> |
| 3301 | return; | 3423 | sas_device_info_mutex); |
| 3424 | return; | ||
| 3425 | } | ||
| 3426 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, | ||
| 3427 | flags); | ||
| 3302 | } | 3428 | } |
| 3303 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, | ||
| 3304 | flags); | ||
| 3305 | } | ||
| 3306 | 3429 | ||
| 3307 | if (retval && (retval != -ENODEV)) { | 3430 | if (retval && (retval != -ENODEV)) { |
| 3308 | if (retry_count < 10) { | 3431 | if (retry_count < 10) { |
| 3309 | retry_count++; | 3432 | retry_count++; |
| 3310 | goto retry_page; | 3433 | goto retry_page; |
| 3311 | } else { | 3434 | } else { |
| 3312 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 3435 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
| 3313 | "%s: Config page retry exceeded retry " | 3436 | "%s: Config page retry exceeded retry " |
| 3314 | "count deleting device 0x%llx\n", | 3437 | "count deleting device 0x%llx\n", |
| 3315 | ioc->name, __func__, | 3438 | ioc->name, __func__, |
| 3316 | sas_info->sas_address)); | 3439 | sas_info->sas_address)); |
| 3440 | } | ||
| 3317 | } | 3441 | } |
| 3318 | } | ||
| 3319 | 3442 | ||
| 3320 | /* delete device */ | 3443 | /* delete device */ |
| 3321 | vtarget = mptsas_find_vtarget(ioc, | 3444 | vtarget = mptsas_find_vtarget(ioc, |
| 3322 | sas_info->fw.channel, sas_info->fw.id); | 3445 | sas_info->fw.channel, sas_info->fw.id); |
| 3323 | if (vtarget) | 3446 | |
| 3324 | vtarget->deleted = 1; | 3447 | if (vtarget) |
| 3325 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | 3448 | vtarget->deleted = 1; |
| 3326 | sas_info->sas_address); | 3449 | |
| 3327 | if (phy_info) { | 3450 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
| 3328 | mptsas_del_end_device(ioc, phy_info); | 3451 | sas_info->sas_address); |
| 3329 | goto redo_device_scan; | 3452 | |
| 3330 | } | 3453 | if (phy_info) { |
| 3454 | mptsas_del_end_device(ioc, phy_info); | ||
| 3455 | goto redo_device_scan; | ||
| 3456 | } | ||
| 3457 | } else | ||
| 3458 | mptsas_volume_delete(ioc, sas_info->fw.id); | ||
| 3331 | } | 3459 | } |
| 3332 | mutex_unlock(&ioc->sas_device_info_mutex); | 3460 | mutex_lock(&ioc->sas_device_info_mutex); |
| 3333 | 3461 | ||
| 3334 | /* expanders */ | 3462 | /* expanders */ |
| 3335 | mutex_lock(&ioc->sas_topology_mutex); | 3463 | mutex_lock(&ioc->sas_topology_mutex); |
| @@ -3508,28 +3636,74 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
| 3508 | return phy_info; | 3636 | return phy_info; |
| 3509 | } | 3637 | } |
| 3510 | 3638 | ||
| 3511 | 3639 | /** | |
| 3640 | * mptsas_find_phyinfo_by_phys_disk_num - | ||
| 3641 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 3642 | * @phys_disk_num: | ||
| 3643 | * @channel: | ||
| 3644 | * @id: | ||
| 3645 | * | ||
| 3646 | **/ | ||
| 3512 | static struct mptsas_phyinfo * | 3647 | static struct mptsas_phyinfo * |
| 3513 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 3648 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num, |
| 3649 | u8 channel, u8 id) | ||
| 3514 | { | 3650 | { |
| 3515 | struct mptsas_portinfo *port_info; | ||
| 3516 | struct mptsas_phyinfo *phy_info = NULL; | 3651 | struct mptsas_phyinfo *phy_info = NULL; |
| 3652 | struct mptsas_portinfo *port_info; | ||
| 3653 | RaidPhysDiskPage1_t *phys_disk = NULL; | ||
| 3654 | int num_paths; | ||
| 3655 | u64 sas_address = 0; | ||
| 3517 | int i; | 3656 | int i; |
| 3518 | 3657 | ||
| 3658 | phy_info = NULL; | ||
| 3659 | if (!ioc->raid_data.pIocPg3) | ||
| 3660 | return NULL; | ||
| 3661 | /* dual port support */ | ||
| 3662 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num); | ||
| 3663 | if (!num_paths) | ||
| 3664 | goto out; | ||
| 3665 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
| 3666 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
| 3667 | if (!phys_disk) | ||
| 3668 | goto out; | ||
| 3669 | mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk); | ||
| 3670 | for (i = 0; i < num_paths; i++) { | ||
| 3671 | if ((phys_disk->Path[i].Flags & 1) != 0) | ||
| 3672 | /* entry no longer valid */ | ||
| 3673 | continue; | ||
| 3674 | if ((id == phys_disk->Path[i].PhysDiskID) && | ||
| 3675 | (channel == phys_disk->Path[i].PhysDiskBus)) { | ||
| 3676 | memcpy(&sas_address, &phys_disk->Path[i].WWID, | ||
| 3677 | sizeof(u64)); | ||
| 3678 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||
| 3679 | sas_address); | ||
| 3680 | goto out; | ||
| 3681 | } | ||
| 3682 | } | ||
| 3683 | |||
| 3684 | out: | ||
| 3685 | kfree(phys_disk); | ||
| 3686 | if (phy_info) | ||
| 3687 | return phy_info; | ||
| 3688 | |||
| 3689 | /* | ||
| 3690 | * Extra code to handle RAID0 case, where the sas_address is not updated | ||
| 3691 | * in phys_disk_page_1 when hotswapped | ||
| 3692 | */ | ||
| 3519 | mutex_lock(&ioc->sas_topology_mutex); | 3693 | mutex_lock(&ioc->sas_topology_mutex); |
| 3520 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 3694 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
| 3521 | for (i = 0; i < port_info->num_phys; i++) { | 3695 | for (i = 0; i < port_info->num_phys && !phy_info; i++) { |
| 3522 | if (!mptsas_is_end_device( | 3696 | if (!mptsas_is_end_device( |
| 3523 | &port_info->phy_info[i].attached)) | 3697 | &port_info->phy_info[i].attached)) |
| 3524 | continue; | 3698 | continue; |
| 3525 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) | 3699 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) |
| 3526 | continue; | 3700 | continue; |
| 3527 | if (port_info->phy_info[i].attached.phys_disk_num != id) | 3701 | if ((port_info->phy_info[i].attached.phys_disk_num == |
| 3528 | continue; | 3702 | phys_disk_num) && |
| 3529 | if (port_info->phy_info[i].attached.channel != channel) | 3703 | (port_info->phy_info[i].attached.id == id) && |
| 3530 | continue; | 3704 | (port_info->phy_info[i].attached.channel == |
| 3531 | phy_info = &port_info->phy_info[i]; | 3705 | channel)) |
| 3532 | break; | 3706 | phy_info = &port_info->phy_info[i]; |
| 3533 | } | 3707 | } |
| 3534 | } | 3708 | } |
| 3535 | mutex_unlock(&ioc->sas_topology_mutex); | 3709 | mutex_unlock(&ioc->sas_topology_mutex); |
| @@ -3683,8 +3857,9 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, | |||
| 3683 | mpt_findImVolumes(ioc); | 3857 | mpt_findImVolumes(ioc); |
| 3684 | 3858 | ||
| 3685 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( | 3859 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( |
| 3686 | ioc, hot_plug_info->channel, | 3860 | ioc, hot_plug_info->phys_disk_num, |
| 3687 | hot_plug_info->phys_disk_num); | 3861 | hot_plug_info->channel, |
| 3862 | hot_plug_info->id); | ||
| 3688 | mptsas_del_end_device(ioc, phy_info); | 3863 | mptsas_del_end_device(ioc, phy_info); |
| 3689 | break; | 3864 | break; |
| 3690 | 3865 | ||
| @@ -4032,6 +4207,7 @@ mptsas_send_ir2_event(struct fw_event_work *fw_event) | |||
| 4032 | struct mptsas_hotplug_event hot_plug_info; | 4207 | struct mptsas_hotplug_event hot_plug_info; |
| 4033 | MPI_EVENT_DATA_IR2 *ir2_data; | 4208 | MPI_EVENT_DATA_IR2 *ir2_data; |
| 4034 | u8 reasonCode; | 4209 | u8 reasonCode; |
| 4210 | RaidPhysDiskPage0_t phys_disk; | ||
| 4035 | 4211 | ||
| 4036 | ioc = fw_event->ioc; | 4212 | ioc = fw_event->ioc; |
| 4037 | ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data; | 4213 | ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data; |
| @@ -4047,6 +4223,17 @@ mptsas_send_ir2_event(struct fw_event_work *fw_event) | |||
| 4047 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: | 4223 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: |
| 4048 | hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME; | 4224 | hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME; |
| 4049 | break; | 4225 | break; |
| 4226 | case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: | ||
| 4227 | hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; | ||
| 4228 | hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK; | ||
| 4229 | break; | ||
| 4230 | case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: | ||
| 4231 | hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; | ||
| 4232 | mpt_raid_phys_disk_pg0(ioc, | ||
| 4233 | ir2_data->PhysDiskNum, &phys_disk); | ||
| 4234 | hot_plug_info.id = phys_disk.PhysDiskID; | ||
| 4235 | hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK; | ||
| 4236 | break; | ||
| 4050 | default: | 4237 | default: |
| 4051 | mptsas_free_fw_event(ioc, fw_event); | 4238 | mptsas_free_fw_event(ioc, fw_event); |
| 4052 | return; | 4239 | return; |
| @@ -4132,6 +4319,31 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | |||
| 4132 | return 0; | 4319 | return 0; |
| 4133 | } | 4320 | } |
| 4134 | 4321 | ||
| 4322 | /* Delete a volume when no longer listed in ioc pg2 | ||
| 4323 | */ | ||
| 4324 | static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id) | ||
| 4325 | { | ||
| 4326 | struct scsi_device *sdev; | ||
| 4327 | int i; | ||
| 4328 | |||
| 4329 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0); | ||
| 4330 | if (!sdev) | ||
| 4331 | return; | ||
| 4332 | if (!ioc->raid_data.pIocPg2) | ||
| 4333 | goto out; | ||
| 4334 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
| 4335 | goto out; | ||
| 4336 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) | ||
| 4337 | if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) | ||
| 4338 | goto release_sdev; | ||
| 4339 | out: | ||
| 4340 | printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, " | ||
| 4341 | "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id); | ||
| 4342 | scsi_remove_device(sdev); | ||
| 4343 | release_sdev: | ||
| 4344 | scsi_device_put(sdev); | ||
| 4345 | } | ||
| 4346 | |||
| 4135 | static int | 4347 | static int |
| 4136 | mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 4348 | mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 4137 | { | 4349 | { |
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 9e0885a86d23..57258b60369e 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h | |||
| @@ -82,6 +82,7 @@ struct mptsas_device_info { | |||
| 82 | u32 device_info; /* specific bits for devices */ | 82 | u32 device_info; /* specific bits for devices */ |
| 83 | u16 slot; /* enclosure slot id */ | 83 | u16 slot; /* enclosure slot id */ |
| 84 | u64 enclosure_logical_id; /*enclosure address */ | 84 | u64 enclosure_logical_id; /*enclosure address */ |
| 85 | u8 is_logical_volume; /* is this logical volume */ | ||
| 85 | }; | 86 | }; |
| 86 | 87 | ||
| 87 | struct mptsas_hotplug_event { | 88 | struct mptsas_hotplug_event { |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 6424dcbd5908..cf1aba18a09f 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
| @@ -2087,8 +2087,10 @@ int | |||
| 2087 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2087 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) |
| 2088 | { | 2088 | { |
| 2089 | struct inactive_raid_component_info *component_info; | 2089 | struct inactive_raid_component_info *component_info; |
| 2090 | int i; | 2090 | int i, j; |
| 2091 | RaidPhysDiskPage1_t *phys_disk; | ||
| 2091 | int rc = 0; | 2092 | int rc = 0; |
| 2093 | int num_paths; | ||
| 2092 | 2094 | ||
| 2093 | if (!ioc->raid_data.pIocPg3) | 2095 | if (!ioc->raid_data.pIocPg3) |
| 2094 | goto out; | 2096 | goto out; |
| @@ -2100,6 +2102,45 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2100 | } | 2102 | } |
| 2101 | } | 2103 | } |
| 2102 | 2104 | ||
| 2105 | if (ioc->bus_type != SAS) | ||
| 2106 | goto out; | ||
| 2107 | |||
| 2108 | /* | ||
| 2109 | * Check if dual path | ||
| 2110 | */ | ||
| 2111 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2112 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
| 2113 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
| 2114 | if (num_paths < 2) | ||
| 2115 | continue; | ||
| 2116 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
| 2117 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
| 2118 | if (!phys_disk) | ||
| 2119 | continue; | ||
| 2120 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
| 2121 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
| 2122 | phys_disk))) { | ||
| 2123 | kfree(phys_disk); | ||
| 2124 | continue; | ||
| 2125 | } | ||
| 2126 | for (j = 0; j < num_paths; j++) { | ||
| 2127 | if ((phys_disk->Path[j].Flags & | ||
| 2128 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
| 2129 | continue; | ||
| 2130 | if ((phys_disk->Path[j].Flags & | ||
| 2131 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
| 2132 | continue; | ||
| 2133 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
| 2134 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
| 2135 | rc = 1; | ||
| 2136 | kfree(phys_disk); | ||
| 2137 | goto out; | ||
| 2138 | } | ||
| 2139 | } | ||
| 2140 | kfree(phys_disk); | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | |||
| 2103 | /* | 2144 | /* |
| 2104 | * Check inactive list for matching phys disks | 2145 | * Check inactive list for matching phys disks |
| 2105 | */ | 2146 | */ |
| @@ -2124,8 +2165,10 @@ u8 | |||
| 2124 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2165 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
| 2125 | { | 2166 | { |
| 2126 | struct inactive_raid_component_info *component_info; | 2167 | struct inactive_raid_component_info *component_info; |
| 2127 | int i; | 2168 | int i, j; |
| 2169 | RaidPhysDiskPage1_t *phys_disk; | ||
| 2128 | int rc = -ENXIO; | 2170 | int rc = -ENXIO; |
| 2171 | int num_paths; | ||
| 2129 | 2172 | ||
| 2130 | if (!ioc->raid_data.pIocPg3) | 2173 | if (!ioc->raid_data.pIocPg3) |
| 2131 | goto out; | 2174 | goto out; |
| @@ -2137,6 +2180,44 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
| 2137 | } | 2180 | } |
| 2138 | } | 2181 | } |
| 2139 | 2182 | ||
| 2183 | if (ioc->bus_type != SAS) | ||
| 2184 | goto out; | ||
| 2185 | |||
| 2186 | /* | ||
| 2187 | * Check if dual path | ||
| 2188 | */ | ||
| 2189 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
| 2190 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
| 2191 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
| 2192 | if (num_paths < 2) | ||
| 2193 | continue; | ||
| 2194 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
| 2195 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
| 2196 | if (!phys_disk) | ||
| 2197 | continue; | ||
| 2198 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
| 2199 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
| 2200 | phys_disk))) { | ||
| 2201 | kfree(phys_disk); | ||
| 2202 | continue; | ||
| 2203 | } | ||
| 2204 | for (j = 0; j < num_paths; j++) { | ||
| 2205 | if ((phys_disk->Path[j].Flags & | ||
| 2206 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
| 2207 | continue; | ||
| 2208 | if ((phys_disk->Path[j].Flags & | ||
| 2209 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
| 2210 | continue; | ||
| 2211 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
| 2212 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
| 2213 | rc = phys_disk->PhysDiskNum; | ||
| 2214 | kfree(phys_disk); | ||
| 2215 | goto out; | ||
| 2216 | } | ||
| 2217 | } | ||
| 2218 | kfree(phys_disk); | ||
| 2219 | } | ||
| 2220 | |||
| 2140 | /* | 2221 | /* |
| 2141 | * Check inactive list for matching phys disks | 2222 | * Check inactive list for matching phys disks |
| 2142 | */ | 2223 | */ |
