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 /drivers/message | |
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>
Diffstat (limited to 'drivers/message')
-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 | */ |