aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-05-29 07:23:56 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-09 18:44:11 -0400
commita7938b0bb3b458fe0723608be3db6c4ed8d79a8c (patch)
tree6654a67ee51d52e1447ed970801b2fb9106f3867
parent71278192a887d7da3e768809c6fe9979d172ff23 (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.c167
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptsas.c332
-rw-r--r--drivers/message/fusion/mptsas.h1
-rw-r--r--drivers/message/fusion/mptscsih.c85
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 **/
5773int
5774mpt_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}
5828EXPORT_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 **/
5841int
5842mpt_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}
5917EXPORT_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);
958extern int mpt_findImVolumes(MPT_ADAPTER *ioc); 958extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
959extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 959extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
960extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); 960extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
961extern int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
962 pRaidPhysDiskPage1_t phys_disk);
963extern int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc,
964 u8 phys_disk_num);
961extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); 965extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
962extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); 966extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
963extern void mpt_halt_firmware(MPT_ADAPTER *ioc); 967extern 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,
121static void mptsas_send_expander_event(struct fw_event_work *fw_event); 121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); 122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); 123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
124static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
124 125
125static void mptsas_print_phy_data(MPT_ADAPTER *ioc, 126static 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 **/
629static void
630mptsas_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;
3282retry_page: 3404retry_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 **/
3512static struct mptsas_phyinfo * 3647static struct mptsas_phyinfo *
3513mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 3648mptsas_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 */
4324static 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
4135static int 4347static int
4136mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) 4348mptsas_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
87struct mptsas_hotplug_event { 88struct 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
2087mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) 2087mptscsih_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
2124mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 2165mptscsih_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 */