Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Kashyap, Desai and committed by
James Bottomley
a7938b0b 71278192

+527 -62
+167
drivers/message/fusion/mptbase.c
··· 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 5921 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes 5767 5922 * @ioc: Pointer to a Adapter Strucutre 5768 5923 * ··· 7322 7167 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: 7323 7168 snprintf(evStr, EVENT_DESCR_STR_SZ, 7324 7169 "IR2: Rebuild Medium Error: " 7170 + "id=%d channel=%d phys_num=%d", 7171 + id, channel, phys_num); 7172 + break; 7173 + case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: 7174 + snprintf(evStr, EVENT_DESCR_STR_SZ, 7175 + "IR2: Dual Port Added: " 7176 + "id=%d channel=%d phys_num=%d", 7177 + id, channel, phys_num); 7178 + break; 7179 + case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: 7180 + snprintf(evStr, EVENT_DESCR_STR_SZ, 7181 + "IR2: Dual Port Removed: " 7325 7182 "id=%d channel=%d phys_num=%d", 7326 7183 id, channel, phys_num); 7327 7184 break;
+4
drivers/message/fusion/mptbase.h
··· 958 958 extern int mpt_findImVolumes(MPT_ADAPTER *ioc); 959 959 extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 960 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 965 extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); 962 966 extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc); 963 967 extern void mpt_halt_firmware(MPT_ADAPTER *ioc);
+272 -60
drivers/message/fusion/mptsas.c
··· 121 121 static void mptsas_send_expander_event(struct fw_event_work *fw_event); 122 122 static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); 123 123 static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); 124 + static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id); 124 125 125 126 static void mptsas_print_phy_data(MPT_ADAPTER *ioc, 126 127 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) ··· 543 542 mutex_lock(&ioc->sas_device_info_mutex); 544 543 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, 545 544 list) { 546 - if ((sas_info->sas_address == sas_address || 547 - (sas_info->fw.channel == channel && 548 - sas_info->fw.id == id))) { 545 + if (!sas_info->is_logical_volume && 546 + (sas_info->sas_address == sas_address || 547 + (sas_info->fw.channel == channel && 548 + sas_info->fw.id == id))) { 549 549 list_del(&sas_info->list); 550 550 kfree(sas_info); 551 551 } ··· 616 614 mptsas_add_device_component(ioc, sas_device.channel, 617 615 sas_device.id, sas_device.sas_address, sas_device.device_info, 618 616 sas_device.slot, enclosure_info.enclosure_logical_id); 617 + } 618 + 619 + /** 620 + * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding 621 + * each individual device to list 622 + * @ioc: Pointer to MPT_ADAPTER structure 623 + * @channel: fw mapped id's 624 + * @id: 625 + * 626 + **/ 627 + static void 628 + mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc, 629 + struct scsi_target *starget) 630 + { 631 + CONFIGPARMS cfg; 632 + ConfigPageHeader_t hdr; 633 + dma_addr_t dma_handle; 634 + pRaidVolumePage0_t buffer = NULL; 635 + int i; 636 + RaidPhysDiskPage0_t phys_disk; 637 + struct mptsas_device_info *sas_info, *next; 638 + 639 + memset(&cfg, 0 , sizeof(CONFIGPARMS)); 640 + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 641 + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; 642 + /* assumption that all volumes on channel = 0 */ 643 + cfg.pageAddr = starget->id; 644 + cfg.cfghdr.hdr = &hdr; 645 + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 646 + cfg.timeout = 10; 647 + 648 + if (mpt_config(ioc, &cfg) != 0) 649 + goto out; 650 + 651 + if (!hdr.PageLength) 652 + goto out; 653 + 654 + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, 655 + &dma_handle); 656 + 657 + if (!buffer) 658 + goto out; 659 + 660 + cfg.physAddr = dma_handle; 661 + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 662 + 663 + if (mpt_config(ioc, &cfg) != 0) 664 + goto out; 665 + 666 + if (!buffer->NumPhysDisks) 667 + goto out; 668 + 669 + /* 670 + * Adding entry for hidden components 671 + */ 672 + for (i = 0; i < buffer->NumPhysDisks; i++) { 673 + 674 + if (mpt_raid_phys_disk_pg0(ioc, 675 + buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) 676 + continue; 677 + 678 + mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus, 679 + phys_disk.PhysDiskID); 680 + 681 + } 682 + 683 + /* 684 + * Delete all matching devices out of the list 685 + */ 686 + mutex_lock(&ioc->sas_device_info_mutex); 687 + list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, 688 + list) { 689 + if (sas_info->is_logical_volume && sas_info->fw.id == 690 + starget->id) { 691 + list_del(&sas_info->list); 692 + kfree(sas_info); 693 + } 694 + } 695 + 696 + sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL); 697 + if (sas_info) { 698 + sas_info->fw.id = starget->id; 699 + sas_info->os.id = starget->id; 700 + sas_info->os.channel = starget->channel; 701 + sas_info->is_logical_volume = 1; 702 + INIT_LIST_HEAD(&sas_info->list); 703 + list_add_tail(&sas_info->list, &ioc->sas_device_info_list); 704 + } 705 + mutex_unlock(&ioc->sas_device_info_mutex); 706 + 707 + out: 708 + if (buffer) 709 + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, 710 + dma_handle); 619 711 } 620 712 621 713 /** ··· 912 816 vdevice = sdev->hostdata; 913 817 if ((vdevice == NULL) || 914 818 (vdevice->vtarget == NULL)) 819 + continue; 820 + if ((vdevice->vtarget->tflags & 821 + MPT_TARGET_FLAGS_RAID_COMPONENT || 822 + vdevice->vtarget->raidVolume)) 915 823 continue; 916 824 if (vdevice->vtarget->id == id && 917 825 vdevice->vtarget->channel == channel) ··· 1587 1487 struct Scsi_Host *host = sdev->host; 1588 1488 MPT_SCSI_HOST *hd = shost_priv(host); 1589 1489 MPT_ADAPTER *ioc = hd->ioc; 1490 + VirtDevice *vdevice = sdev->hostdata; 1590 1491 1591 - if (sdev->channel == MPTSAS_RAID_CHANNEL) 1492 + if (vdevice->vtarget->deleted) { 1493 + sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n"); 1494 + vdevice->vtarget->deleted = 0; 1495 + } 1496 + 1497 + /* 1498 + * RAID volumes placed beyond the last expected port. 1499 + * Ignore sending sas mode pages in that case.. 1500 + */ 1501 + if (sdev->channel == MPTSAS_RAID_CHANNEL) { 1502 + mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev)); 1592 1503 goto out; 1504 + } 1593 1505 1594 1506 sas_read_port_mode_page(sdev); 1595 1507 ··· 1637 1525 * RAID volumes placed beyond the last expected port. 1638 1526 */ 1639 1527 if (starget->channel == MPTSAS_RAID_CHANNEL) { 1640 - for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) 1641 - if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) 1642 - channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; 1528 + if (!ioc->raid_data.pIocPg2) { 1529 + kfree(vtarget); 1530 + return -ENXIO; 1531 + } 1532 + for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { 1533 + if (id == ioc->raid_data.pIocPg2-> 1534 + RaidVolume[i].VolumeID) { 1535 + channel = ioc->raid_data.pIocPg2-> 1536 + RaidVolume[i].VolumeBus; 1537 + } 1538 + } 1539 + vtarget->raidVolume = 1; 1643 1540 goto out; 1644 1541 } 1645 1542 ··· 3398 3277 mutex_lock(&ioc->sas_device_info_mutex); 3399 3278 redo_device_scan: 3400 3279 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { 3401 - sas_device.handle = 0; 3402 - retry_count = 0; 3280 + if (!sas_info->is_logical_volume) { 3281 + sas_device.handle = 0; 3282 + retry_count = 0; 3403 3283 retry_page: 3404 - retval = mptsas_sas_device_pg0(ioc, &sas_device, 3284 + retval = mptsas_sas_device_pg0(ioc, &sas_device, 3405 3285 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID 3406 3286 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 3407 3287 (sas_info->fw.channel << 8) + 3408 3288 sas_info->fw.id); 3409 3289 3410 - if (sas_device.handle) 3411 - continue; 3412 - if (retval == -EBUSY) { 3413 - spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 3414 - if (ioc->ioc_reset_in_progress) { 3415 - dfailprintk(ioc, 3416 - printk(MYIOC_s_DEBUG_FMT 3417 - "%s: exiting due to reset\n", 3418 - ioc->name, __func__)); 3419 - spin_unlock_irqrestore 3420 - (&ioc->taskmgmt_lock, flags); 3421 - mutex_unlock(&ioc->sas_device_info_mutex); 3422 - return; 3290 + if (sas_device.handle) 3291 + continue; 3292 + if (retval == -EBUSY) { 3293 + spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 3294 + if (ioc->ioc_reset_in_progress) { 3295 + dfailprintk(ioc, 3296 + printk(MYIOC_s_DEBUG_FMT 3297 + "%s: exiting due to reset\n", 3298 + ioc->name, __func__)); 3299 + spin_unlock_irqrestore 3300 + (&ioc->taskmgmt_lock, flags); 3301 + mutex_unlock(&ioc-> 3302 + sas_device_info_mutex); 3303 + return; 3304 + } 3305 + spin_unlock_irqrestore(&ioc->taskmgmt_lock, 3306 + flags); 3423 3307 } 3424 - spin_unlock_irqrestore(&ioc->taskmgmt_lock, 3425 - flags); 3426 - } 3427 3308 3428 - if (retval && (retval != -ENODEV)) { 3429 - if (retry_count < 10) { 3430 - retry_count++; 3431 - goto retry_page; 3432 - } else { 3433 - devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 3434 - "%s: Config page retry exceeded retry " 3435 - "count deleting device 0x%llx\n", 3436 - ioc->name, __func__, 3437 - sas_info->sas_address)); 3309 + if (retval && (retval != -ENODEV)) { 3310 + if (retry_count < 10) { 3311 + retry_count++; 3312 + goto retry_page; 3313 + } else { 3314 + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 3315 + "%s: Config page retry exceeded retry " 3316 + "count deleting device 0x%llx\n", 3317 + ioc->name, __func__, 3318 + sas_info->sas_address)); 3319 + } 3438 3320 } 3439 - } 3440 3321 3441 - /* delete device */ 3442 - vtarget = mptsas_find_vtarget(ioc, 3322 + /* delete device */ 3323 + vtarget = mptsas_find_vtarget(ioc, 3443 3324 sas_info->fw.channel, sas_info->fw.id); 3444 - if (vtarget) 3445 - vtarget->deleted = 1; 3446 - phy_info = mptsas_find_phyinfo_by_sas_address(ioc, 3447 - sas_info->sas_address); 3448 - if (phy_info) { 3449 - mptsas_del_end_device(ioc, phy_info); 3450 - goto redo_device_scan; 3451 - } 3325 + 3326 + if (vtarget) 3327 + vtarget->deleted = 1; 3328 + 3329 + phy_info = mptsas_find_phyinfo_by_sas_address(ioc, 3330 + sas_info->sas_address); 3331 + 3332 + if (phy_info) { 3333 + mptsas_del_end_device(ioc, phy_info); 3334 + goto redo_device_scan; 3335 + } 3336 + } else 3337 + mptsas_volume_delete(ioc, sas_info->fw.id); 3452 3338 } 3453 - mutex_unlock(&ioc->sas_device_info_mutex); 3339 + mutex_lock(&ioc->sas_device_info_mutex); 3454 3340 3455 3341 /* expanders */ 3456 3342 mutex_lock(&ioc->sas_topology_mutex); ··· 3636 3508 return phy_info; 3637 3509 } 3638 3510 3639 - 3511 + /** 3512 + * mptsas_find_phyinfo_by_phys_disk_num - 3513 + * @ioc: Pointer to MPT_ADAPTER structure 3514 + * @phys_disk_num: 3515 + * @channel: 3516 + * @id: 3517 + * 3518 + **/ 3640 3519 static struct mptsas_phyinfo * 3641 - mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 3520 + mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num, 3521 + u8 channel, u8 id) 3642 3522 { 3643 - struct mptsas_portinfo *port_info; 3644 3523 struct mptsas_phyinfo *phy_info = NULL; 3524 + struct mptsas_portinfo *port_info; 3525 + RaidPhysDiskPage1_t *phys_disk = NULL; 3526 + int num_paths; 3527 + u64 sas_address = 0; 3645 3528 int i; 3646 3529 3530 + phy_info = NULL; 3531 + if (!ioc->raid_data.pIocPg3) 3532 + return NULL; 3533 + /* dual port support */ 3534 + num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num); 3535 + if (!num_paths) 3536 + goto out; 3537 + phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 3538 + (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 3539 + if (!phys_disk) 3540 + goto out; 3541 + mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk); 3542 + for (i = 0; i < num_paths; i++) { 3543 + if ((phys_disk->Path[i].Flags & 1) != 0) 3544 + /* entry no longer valid */ 3545 + continue; 3546 + if ((id == phys_disk->Path[i].PhysDiskID) && 3547 + (channel == phys_disk->Path[i].PhysDiskBus)) { 3548 + memcpy(&sas_address, &phys_disk->Path[i].WWID, 3549 + sizeof(u64)); 3550 + phy_info = mptsas_find_phyinfo_by_sas_address(ioc, 3551 + sas_address); 3552 + goto out; 3553 + } 3554 + } 3555 + 3556 + out: 3557 + kfree(phys_disk); 3558 + if (phy_info) 3559 + return phy_info; 3560 + 3561 + /* 3562 + * Extra code to handle RAID0 case, where the sas_address is not updated 3563 + * in phys_disk_page_1 when hotswapped 3564 + */ 3647 3565 mutex_lock(&ioc->sas_topology_mutex); 3648 3566 list_for_each_entry(port_info, &ioc->sas_topology, list) { 3649 - for (i = 0; i < port_info->num_phys; i++) { 3567 + for (i = 0; i < port_info->num_phys && !phy_info; i++) { 3650 3568 if (!mptsas_is_end_device( 3651 3569 &port_info->phy_info[i].attached)) 3652 3570 continue; 3653 3571 if (port_info->phy_info[i].attached.phys_disk_num == ~0) 3654 3572 continue; 3655 - if (port_info->phy_info[i].attached.phys_disk_num != id) 3656 - continue; 3657 - if (port_info->phy_info[i].attached.channel != channel) 3658 - continue; 3659 - phy_info = &port_info->phy_info[i]; 3660 - break; 3573 + if ((port_info->phy_info[i].attached.phys_disk_num == 3574 + phys_disk_num) && 3575 + (port_info->phy_info[i].attached.id == id) && 3576 + (port_info->phy_info[i].attached.channel == 3577 + channel)) 3578 + phy_info = &port_info->phy_info[i]; 3661 3579 } 3662 3580 } 3663 3581 mutex_unlock(&ioc->sas_topology_mutex); ··· 3857 3683 mpt_findImVolumes(ioc); 3858 3684 3859 3685 phy_info = mptsas_find_phyinfo_by_phys_disk_num( 3860 - ioc, hot_plug_info->channel, 3861 - hot_plug_info->phys_disk_num); 3686 + ioc, hot_plug_info->phys_disk_num, 3687 + hot_plug_info->channel, 3688 + hot_plug_info->id); 3862 3689 mptsas_del_end_device(ioc, phy_info); 3863 3690 break; 3864 3691 ··· 4207 4032 struct mptsas_hotplug_event hot_plug_info; 4208 4033 MPI_EVENT_DATA_IR2 *ir2_data; 4209 4034 u8 reasonCode; 4035 + RaidPhysDiskPage0_t phys_disk; 4210 4036 4211 4037 ioc = fw_event->ioc; 4212 4038 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data; ··· 4222 4046 switch (reasonCode) { 4223 4047 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: 4224 4048 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME; 4049 + break; 4050 + case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: 4051 + hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; 4052 + hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK; 4053 + break; 4054 + case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: 4055 + hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum; 4056 + mpt_raid_phys_disk_pg0(ioc, 4057 + ir2_data->PhysDiskNum, &phys_disk); 4058 + hot_plug_info.id = phys_disk.PhysDiskID; 4059 + hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK; 4225 4060 break; 4226 4061 default: 4227 4062 mptsas_free_fw_event(ioc, fw_event); ··· 4317 4130 fw_event->ioc = ioc; 4318 4131 mptsas_add_fw_event(ioc, fw_event, delay); 4319 4132 return 0; 4133 + } 4134 + 4135 + /* Delete a volume when no longer listed in ioc pg2 4136 + */ 4137 + static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id) 4138 + { 4139 + struct scsi_device *sdev; 4140 + int i; 4141 + 4142 + sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0); 4143 + if (!sdev) 4144 + return; 4145 + if (!ioc->raid_data.pIocPg2) 4146 + goto out; 4147 + if (!ioc->raid_data.pIocPg2->NumActiveVolumes) 4148 + goto out; 4149 + for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) 4150 + if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) 4151 + goto release_sdev; 4152 + out: 4153 + printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, " 4154 + "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id); 4155 + scsi_remove_device(sdev); 4156 + release_sdev: 4157 + scsi_device_put(sdev); 4320 4158 } 4321 4159 4322 4160 static int
+1
drivers/message/fusion/mptsas.h
··· 82 82 u32 device_info; /* specific bits for devices */ 83 83 u16 slot; /* enclosure slot id */ 84 84 u64 enclosure_logical_id; /*enclosure address */ 85 + u8 is_logical_volume; /* is this logical volume */ 85 86 }; 86 87 87 88 struct mptsas_hotplug_event {
+83 -2
drivers/message/fusion/mptscsih.c
··· 2087 2087 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) 2088 2088 { 2089 2089 struct inactive_raid_component_info *component_info; 2090 - int i; 2090 + int i, j; 2091 + RaidPhysDiskPage1_t *phys_disk; 2091 2092 int rc = 0; 2093 + int num_paths; 2092 2094 2093 2095 if (!ioc->raid_data.pIocPg3) 2094 2096 goto out; ··· 2101 2099 goto out; 2102 2100 } 2103 2101 } 2102 + 2103 + if (ioc->bus_type != SAS) 2104 + goto out; 2105 + 2106 + /* 2107 + * Check if dual path 2108 + */ 2109 + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2110 + num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2111 + ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2112 + if (num_paths < 2) 2113 + continue; 2114 + phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2115 + (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2116 + if (!phys_disk) 2117 + continue; 2118 + if ((mpt_raid_phys_disk_pg1(ioc, 2119 + ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2120 + phys_disk))) { 2121 + kfree(phys_disk); 2122 + continue; 2123 + } 2124 + for (j = 0; j < num_paths; j++) { 2125 + if ((phys_disk->Path[j].Flags & 2126 + MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2127 + continue; 2128 + if ((phys_disk->Path[j].Flags & 2129 + MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2130 + continue; 2131 + if ((id == phys_disk->Path[j].PhysDiskID) && 2132 + (channel == phys_disk->Path[j].PhysDiskBus)) { 2133 + rc = 1; 2134 + kfree(phys_disk); 2135 + goto out; 2136 + } 2137 + } 2138 + kfree(phys_disk); 2139 + } 2140 + 2104 2141 2105 2142 /* 2106 2143 * Check inactive list for matching phys disks ··· 2165 2124 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 2166 2125 { 2167 2126 struct inactive_raid_component_info *component_info; 2168 - int i; 2127 + int i, j; 2128 + RaidPhysDiskPage1_t *phys_disk; 2169 2129 int rc = -ENXIO; 2130 + int num_paths; 2170 2131 2171 2132 if (!ioc->raid_data.pIocPg3) 2172 2133 goto out; ··· 2178 2135 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; 2179 2136 goto out; 2180 2137 } 2138 + } 2139 + 2140 + if (ioc->bus_type != SAS) 2141 + goto out; 2142 + 2143 + /* 2144 + * Check if dual path 2145 + */ 2146 + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2147 + num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2148 + ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2149 + if (num_paths < 2) 2150 + continue; 2151 + phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2152 + (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2153 + if (!phys_disk) 2154 + continue; 2155 + if ((mpt_raid_phys_disk_pg1(ioc, 2156 + ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2157 + phys_disk))) { 2158 + kfree(phys_disk); 2159 + continue; 2160 + } 2161 + for (j = 0; j < num_paths; j++) { 2162 + if ((phys_disk->Path[j].Flags & 2163 + MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2164 + continue; 2165 + if ((phys_disk->Path[j].Flags & 2166 + MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2167 + continue; 2168 + if ((id == phys_disk->Path[j].PhysDiskID) && 2169 + (channel == phys_disk->Path[j].PhysDiskBus)) { 2170 + rc = phys_disk->PhysDiskNum; 2171 + kfree(phys_disk); 2172 + goto out; 2173 + } 2174 + } 2175 + kfree(phys_disk); 2181 2176 } 2182 2177 2183 2178 /*