diff options
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r-- | drivers/message/fusion/mptsas.c | 718 |
1 files changed, 580 insertions, 138 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 09e9a9d96410..84b8b485e95b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * running LSI Logic Fusion MPT (Message Passing Technology) firmware. | 4 | * running LSI Logic Fusion MPT (Message Passing Technology) firmware. |
5 | * | 5 | * |
6 | * Copyright (c) 1999-2007 LSI Logic Corporation | 6 | * Copyright (c) 1999-2007 LSI Logic Corporation |
7 | * (mailto:mpt_linux_developer@lsil.com) | 7 | * (mailto:mpt_linux_developer@lsi.com) |
8 | * Copyright (c) 2005-2007 Dell | 8 | * Copyright (c) 2005-2007 Dell |
9 | */ | 9 | */ |
10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -83,17 +83,31 @@ MODULE_PARM_DESC(mpt_pt_clear, | |||
83 | " Clear persistency table: enable=1 " | 83 | " Clear persistency table: enable=1 " |
84 | "(default=MPTSCSIH_PT_CLEAR=0)"); | 84 | "(default=MPTSCSIH_PT_CLEAR=0)"); |
85 | 85 | ||
86 | /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ | ||
87 | #define MPTSAS_MAX_LUN (16895) | ||
88 | static int max_lun = MPTSAS_MAX_LUN; | ||
89 | module_param(max_lun, int, 0); | ||
90 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); | ||
91 | |||
86 | static int mptsasDoneCtx = -1; | 92 | static int mptsasDoneCtx = -1; |
87 | static int mptsasTaskCtx = -1; | 93 | static int mptsasTaskCtx = -1; |
88 | static int mptsasInternalCtx = -1; /* Used only for internal commands */ | 94 | static int mptsasInternalCtx = -1; /* Used only for internal commands */ |
89 | static int mptsasMgmtCtx = -1; | 95 | static int mptsasMgmtCtx = -1; |
90 | 96 | ||
97 | static void mptsas_hotplug_work(struct work_struct *work); | ||
98 | |||
99 | struct mptsas_target_reset_event { | ||
100 | struct list_head list; | ||
101 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; | ||
102 | u8 target_reset_issued; | ||
103 | }; | ||
91 | 104 | ||
92 | enum mptsas_hotplug_action { | 105 | enum mptsas_hotplug_action { |
93 | MPTSAS_ADD_DEVICE, | 106 | MPTSAS_ADD_DEVICE, |
94 | MPTSAS_DEL_DEVICE, | 107 | MPTSAS_DEL_DEVICE, |
95 | MPTSAS_ADD_RAID, | 108 | MPTSAS_ADD_RAID, |
96 | MPTSAS_DEL_RAID, | 109 | MPTSAS_DEL_RAID, |
110 | MPTSAS_ADD_INACTIVE_VOLUME, | ||
97 | MPTSAS_IGNORE_EVENT, | 111 | MPTSAS_IGNORE_EVENT, |
98 | }; | 112 | }; |
99 | 113 | ||
@@ -102,14 +116,15 @@ struct mptsas_hotplug_event { | |||
102 | MPT_ADAPTER *ioc; | 116 | MPT_ADAPTER *ioc; |
103 | enum mptsas_hotplug_action event_type; | 117 | enum mptsas_hotplug_action event_type; |
104 | u64 sas_address; | 118 | u64 sas_address; |
105 | u32 channel; | 119 | u8 channel; |
106 | u32 id; | 120 | u8 id; |
107 | u32 device_info; | 121 | u32 device_info; |
108 | u16 handle; | 122 | u16 handle; |
109 | u16 parent_handle; | 123 | u16 parent_handle; |
110 | u8 phy_id; | 124 | u8 phy_id; |
111 | u8 phys_disk_num; | 125 | u8 phys_disk_num_valid; /* hrc (hidden raid component) */ |
112 | u8 phys_disk_num_valid; | 126 | u8 phys_disk_num; /* hrc - unique index*/ |
127 | u8 hidden_raid_component; /* hrc - don't expose*/ | ||
113 | }; | 128 | }; |
114 | 129 | ||
115 | struct mptsas_discovery_event { | 130 | struct mptsas_discovery_event { |
@@ -134,6 +149,7 @@ struct mptsas_devinfo { | |||
134 | u8 port_id; /* sas physical port this device | 149 | u8 port_id; /* sas physical port this device |
135 | is assoc'd with */ | 150 | is assoc'd with */ |
136 | u8 id; /* logical target id of this device */ | 151 | u8 id; /* logical target id of this device */ |
152 | u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ | ||
137 | u8 channel; /* logical bus number of this device */ | 153 | u8 channel; /* logical bus number of this device */ |
138 | u64 sas_address; /* WWN of this device, | 154 | u64 sas_address; /* WWN of this device, |
139 | SATA is assigned by HBA,expander */ | 155 | SATA is assigned by HBA,expander */ |
@@ -153,6 +169,7 @@ struct mptsas_portinfo_details{ | |||
153 | }; | 169 | }; |
154 | 170 | ||
155 | struct mptsas_phyinfo { | 171 | struct mptsas_phyinfo { |
172 | u16 handle; /* unique id to address this */ | ||
156 | u8 phy_id; /* phy index */ | 173 | u8 phy_id; /* phy index */ |
157 | u8 port_id; /* firmware port identifier */ | 174 | u8 port_id; /* firmware port identifier */ |
158 | u8 negotiated_link_rate; /* nego'd link rate for this phy */ | 175 | u8 negotiated_link_rate; /* nego'd link rate for this phy */ |
@@ -168,7 +185,6 @@ struct mptsas_phyinfo { | |||
168 | 185 | ||
169 | struct mptsas_portinfo { | 186 | struct mptsas_portinfo { |
170 | struct list_head list; | 187 | struct list_head list; |
171 | u16 handle; /* unique id to address this */ | ||
172 | u16 num_phys; /* number of phys */ | 188 | u16 num_phys; /* number of phys */ |
173 | struct mptsas_phyinfo *phy_info; | 189 | struct mptsas_phyinfo *phy_info; |
174 | }; | 190 | }; |
@@ -561,22 +577,273 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
561 | mutex_unlock(&ioc->sas_topology_mutex); | 577 | mutex_unlock(&ioc->sas_topology_mutex); |
562 | } | 578 | } |
563 | 579 | ||
580 | /** | ||
581 | * csmisas_find_vtarget | ||
582 | * | ||
583 | * @ioc | ||
584 | * @volume_id | ||
585 | * @volume_bus | ||
586 | * | ||
587 | **/ | ||
588 | static VirtTarget * | ||
589 | mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
590 | { | ||
591 | struct scsi_device *sdev; | ||
592 | VirtDevice *vdev; | ||
593 | VirtTarget *vtarget = NULL; | ||
594 | |||
595 | shost_for_each_device(sdev, ioc->sh) { | ||
596 | if ((vdev = sdev->hostdata) == NULL) | ||
597 | continue; | ||
598 | if (vdev->vtarget->id == id && | ||
599 | vdev->vtarget->channel == channel) | ||
600 | vtarget = vdev->vtarget; | ||
601 | } | ||
602 | return vtarget; | ||
603 | } | ||
604 | |||
605 | /** | ||
606 | * mptsas_target_reset | ||
607 | * | ||
608 | * Issues TARGET_RESET to end device using handshaking method | ||
609 | * | ||
610 | * @ioc | ||
611 | * @channel | ||
612 | * @id | ||
613 | * | ||
614 | * Returns (1) success | ||
615 | * (0) failure | ||
616 | * | ||
617 | **/ | ||
618 | static int | ||
619 | mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
620 | { | ||
621 | MPT_FRAME_HDR *mf; | ||
622 | SCSITaskMgmt_t *pScsiTm; | ||
623 | |||
624 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { | ||
625 | dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", | ||
626 | ioc->name,__FUNCTION__, __LINE__)); | ||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | /* Format the Request | ||
631 | */ | ||
632 | pScsiTm = (SCSITaskMgmt_t *) mf; | ||
633 | memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t)); | ||
634 | pScsiTm->TargetID = id; | ||
635 | pScsiTm->Bus = channel; | ||
636 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; | ||
637 | pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
638 | pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; | ||
639 | |||
640 | DBG_DUMP_TM_REQUEST_FRAME(mf); | ||
641 | |||
642 | if (mpt_send_handshake_request(ioc->TaskCtx, ioc, | ||
643 | sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) { | ||
644 | mpt_free_msg_frame(ioc, mf); | ||
645 | dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", | ||
646 | ioc->name,__FUNCTION__, __LINE__)); | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | return 1; | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * mptsas_target_reset_queue | ||
655 | * | ||
656 | * Receive request for TARGET_RESET after recieving an firmware | ||
657 | * event NOT_RESPONDING_EVENT, then put command in link list | ||
658 | * and queue if task_queue already in use. | ||
659 | * | ||
660 | * @ioc | ||
661 | * @sas_event_data | ||
662 | * | ||
663 | **/ | ||
564 | static void | 664 | static void |
565 | mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) | 665 | mptsas_target_reset_queue(MPT_ADAPTER *ioc, |
666 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) | ||
566 | { | 667 | { |
567 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; | 668 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; |
669 | VirtTarget *vtarget = NULL; | ||
670 | struct mptsas_target_reset_event *target_reset_list; | ||
671 | u8 id, channel; | ||
568 | 672 | ||
569 | if (mptscsih_TMHandler(hd, | 673 | id = sas_event_data->TargetID; |
570 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 674 | channel = sas_event_data->Bus; |
571 | vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) { | 675 | |
572 | hd->tmPending = 0; | 676 | if (!(vtarget = mptsas_find_vtarget(ioc, channel, id))) |
573 | hd->tmState = TM_STATE_NONE; | 677 | return; |
574 | printk(MYIOC_s_WARN_FMT | 678 | |
575 | "Error processing TaskMgmt id=%d TARGET_RESET\n", | 679 | vtarget->deleted = 1; /* block IO */ |
576 | ioc->name, vtarget->target_id); | 680 | |
681 | target_reset_list = kzalloc(sizeof(*target_reset_list), | ||
682 | GFP_ATOMIC); | ||
683 | if (!target_reset_list) { | ||
684 | dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", | ||
685 | ioc->name,__FUNCTION__, __LINE__)); | ||
686 | return; | ||
687 | } | ||
688 | |||
689 | memcpy(&target_reset_list->sas_event_data, sas_event_data, | ||
690 | sizeof(*sas_event_data)); | ||
691 | list_add_tail(&target_reset_list->list, &hd->target_reset_list); | ||
692 | |||
693 | if (hd->resetPending) | ||
694 | return; | ||
695 | |||
696 | if (mptsas_target_reset(ioc, channel, id)) { | ||
697 | target_reset_list->target_reset_issued = 1; | ||
698 | hd->resetPending = 1; | ||
577 | } | 699 | } |
578 | } | 700 | } |
579 | 701 | ||
702 | /** | ||
703 | * mptsas_dev_reset_complete | ||
704 | * | ||
705 | * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, | ||
706 | * enable work queue to finish off removing device from upper layers. | ||
707 | * then send next TARGET_RESET in the queue. | ||
708 | * | ||
709 | * @ioc | ||
710 | * | ||
711 | **/ | ||
712 | static void | ||
713 | mptsas_dev_reset_complete(MPT_ADAPTER *ioc) | ||
714 | { | ||
715 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
716 | struct list_head *head = &hd->target_reset_list; | ||
717 | struct mptsas_target_reset_event *target_reset_list; | ||
718 | struct mptsas_hotplug_event *ev; | ||
719 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; | ||
720 | u8 id, channel; | ||
721 | __le64 sas_address; | ||
722 | |||
723 | if (list_empty(head)) | ||
724 | return; | ||
725 | |||
726 | target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); | ||
727 | |||
728 | sas_event_data = &target_reset_list->sas_event_data; | ||
729 | id = sas_event_data->TargetID; | ||
730 | channel = sas_event_data->Bus; | ||
731 | hd->resetPending = 0; | ||
732 | |||
733 | /* | ||
734 | * retry target reset | ||
735 | */ | ||
736 | if (!target_reset_list->target_reset_issued) { | ||
737 | if (mptsas_target_reset(ioc, channel, id)) { | ||
738 | target_reset_list->target_reset_issued = 1; | ||
739 | hd->resetPending = 1; | ||
740 | } | ||
741 | return; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * enable work queue to remove device from upper layers | ||
746 | */ | ||
747 | list_del(&target_reset_list->list); | ||
748 | |||
749 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
750 | if (!ev) { | ||
751 | dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", | ||
752 | ioc->name,__FUNCTION__, __LINE__)); | ||
753 | return; | ||
754 | } | ||
755 | |||
756 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
757 | ev->ioc = ioc; | ||
758 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); | ||
759 | ev->parent_handle = | ||
760 | le16_to_cpu(sas_event_data->ParentDevHandle); | ||
761 | ev->channel = channel; | ||
762 | ev->id =id; | ||
763 | ev->phy_id = sas_event_data->PhyNum; | ||
764 | memcpy(&sas_address, &sas_event_data->SASAddress, | ||
765 | sizeof(__le64)); | ||
766 | ev->sas_address = le64_to_cpu(sas_address); | ||
767 | ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); | ||
768 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
769 | schedule_work(&ev->work); | ||
770 | kfree(target_reset_list); | ||
771 | |||
772 | /* | ||
773 | * issue target reset to next device in the queue | ||
774 | */ | ||
775 | |||
776 | head = &hd->target_reset_list; | ||
777 | if (list_empty(head)) | ||
778 | return; | ||
779 | |||
780 | target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, | ||
781 | list); | ||
782 | |||
783 | sas_event_data = &target_reset_list->sas_event_data; | ||
784 | id = sas_event_data->TargetID; | ||
785 | channel = sas_event_data->Bus; | ||
786 | |||
787 | if (mptsas_target_reset(ioc, channel, id)) { | ||
788 | target_reset_list->target_reset_issued = 1; | ||
789 | hd->resetPending = 1; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | /** | ||
794 | * mptsas_taskmgmt_complete | ||
795 | * | ||
796 | * @ioc | ||
797 | * @mf | ||
798 | * @mr | ||
799 | * | ||
800 | **/ | ||
801 | static int | ||
802 | mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | ||
803 | { | ||
804 | mptsas_dev_reset_complete(ioc); | ||
805 | return mptscsih_taskmgmt_complete(ioc, mf, mr); | ||
806 | } | ||
807 | |||
808 | /** | ||
809 | * mptscsih_ioc_reset | ||
810 | * | ||
811 | * @ioc | ||
812 | * @reset_phase | ||
813 | * | ||
814 | **/ | ||
815 | static int | ||
816 | mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | ||
817 | { | ||
818 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
819 | struct mptsas_target_reset_event *target_reset_list, *n; | ||
820 | int rc; | ||
821 | |||
822 | rc = mptscsih_ioc_reset(ioc, reset_phase); | ||
823 | |||
824 | if (ioc->bus_type != SAS) | ||
825 | goto out; | ||
826 | |||
827 | if (reset_phase != MPT_IOC_POST_RESET) | ||
828 | goto out; | ||
829 | |||
830 | if (!hd || !hd->ioc) | ||
831 | goto out; | ||
832 | |||
833 | if (list_empty(&hd->target_reset_list)) | ||
834 | goto out; | ||
835 | |||
836 | /* flush the target_reset_list */ | ||
837 | list_for_each_entry_safe(target_reset_list, n, | ||
838 | &hd->target_reset_list, list) { | ||
839 | list_del(&target_reset_list->list); | ||
840 | kfree(target_reset_list); | ||
841 | } | ||
842 | |||
843 | out: | ||
844 | return rc; | ||
845 | } | ||
846 | |||
580 | static int | 847 | static int |
581 | mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, | 848 | mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, |
582 | u32 form, u32 form_specific) | 849 | u32 form, u32 form_specific) |
@@ -661,8 +928,7 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
661 | struct Scsi_Host *host = dev_to_shost(&starget->dev); | 928 | struct Scsi_Host *host = dev_to_shost(&starget->dev); |
662 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | 929 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; |
663 | VirtTarget *vtarget; | 930 | VirtTarget *vtarget; |
664 | u32 target_id; | 931 | u8 id, channel; |
665 | u32 channel; | ||
666 | struct sas_rphy *rphy; | 932 | struct sas_rphy *rphy; |
667 | struct mptsas_portinfo *p; | 933 | struct mptsas_portinfo *p; |
668 | int i; | 934 | int i; |
@@ -673,15 +939,19 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
673 | 939 | ||
674 | vtarget->starget = starget; | 940 | vtarget->starget = starget; |
675 | vtarget->ioc_id = hd->ioc->id; | 941 | vtarget->ioc_id = hd->ioc->id; |
676 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; | 942 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; |
677 | 943 | id = starget->id; | |
678 | target_id = starget->id; | ||
679 | channel = 0; | 944 | channel = 0; |
680 | 945 | ||
681 | hd->Targets[target_id] = vtarget; | 946 | /* |
682 | 947 | * RAID volumes placed beyond the last expected port. | |
683 | if (starget->channel == MPTSAS_RAID_CHANNEL) | 948 | */ |
949 | if (starget->channel == MPTSAS_RAID_CHANNEL) { | ||
950 | for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) | ||
951 | if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) | ||
952 | channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; | ||
684 | goto out; | 953 | goto out; |
954 | } | ||
685 | 955 | ||
686 | rphy = dev_to_rphy(starget->dev.parent); | 956 | rphy = dev_to_rphy(starget->dev.parent); |
687 | mutex_lock(&hd->ioc->sas_topology_mutex); | 957 | mutex_lock(&hd->ioc->sas_topology_mutex); |
@@ -690,18 +960,19 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
690 | if (p->phy_info[i].attached.sas_address != | 960 | if (p->phy_info[i].attached.sas_address != |
691 | rphy->identify.sas_address) | 961 | rphy->identify.sas_address) |
692 | continue; | 962 | continue; |
693 | target_id = p->phy_info[i].attached.id; | 963 | id = p->phy_info[i].attached.id; |
694 | channel = p->phy_info[i].attached.channel; | 964 | channel = p->phy_info[i].attached.channel; |
695 | mptsas_set_starget(&p->phy_info[i], starget); | 965 | mptsas_set_starget(&p->phy_info[i], starget); |
696 | 966 | ||
697 | /* | 967 | /* |
698 | * Exposing hidden raid components | 968 | * Exposing hidden raid components |
699 | */ | 969 | */ |
700 | if (mptscsih_is_phys_disk(hd->ioc, target_id)) { | 970 | if (mptscsih_is_phys_disk(hd->ioc, channel, id)) { |
701 | target_id = mptscsih_raid_id_to_num(hd, | 971 | id = mptscsih_raid_id_to_num(hd->ioc, |
702 | target_id); | 972 | channel, id); |
703 | vtarget->tflags |= | 973 | vtarget->tflags |= |
704 | MPT_TARGET_FLAGS_RAID_COMPONENT; | 974 | MPT_TARGET_FLAGS_RAID_COMPONENT; |
975 | p->phy_info[i].attached.phys_disk_num = id; | ||
705 | } | 976 | } |
706 | mutex_unlock(&hd->ioc->sas_topology_mutex); | 977 | mutex_unlock(&hd->ioc->sas_topology_mutex); |
707 | goto out; | 978 | goto out; |
@@ -713,8 +984,8 @@ mptsas_target_alloc(struct scsi_target *starget) | |||
713 | return -ENXIO; | 984 | return -ENXIO; |
714 | 985 | ||
715 | out: | 986 | out: |
716 | vtarget->target_id = target_id; | 987 | vtarget->id = id; |
717 | vtarget->bus_id = channel; | 988 | vtarget->channel = channel; |
718 | starget->hostdata = vtarget; | 989 | starget->hostdata = vtarget; |
719 | return 0; | 990 | return 0; |
720 | } | 991 | } |
@@ -786,7 +1057,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
786 | * Exposing hidden raid components | 1057 | * Exposing hidden raid components |
787 | */ | 1058 | */ |
788 | if (mptscsih_is_phys_disk(hd->ioc, | 1059 | if (mptscsih_is_phys_disk(hd->ioc, |
789 | p->phy_info[i].attached.id)) | 1060 | p->phy_info[i].attached.channel, |
1061 | p->phy_info[i].attached.id)) | ||
790 | sdev->no_uld_attach = 1; | 1062 | sdev->no_uld_attach = 1; |
791 | mutex_unlock(&hd->ioc->sas_topology_mutex); | 1063 | mutex_unlock(&hd->ioc->sas_topology_mutex); |
792 | goto out; | 1064 | goto out; |
@@ -808,13 +1080,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
808 | { | 1080 | { |
809 | VirtDevice *vdev = SCpnt->device->hostdata; | 1081 | VirtDevice *vdev = SCpnt->device->hostdata; |
810 | 1082 | ||
811 | // scsi_print_command(SCpnt); | 1083 | if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) { |
812 | if (vdev->vtarget->deleted) { | ||
813 | SCpnt->result = DID_NO_CONNECT << 16; | 1084 | SCpnt->result = DID_NO_CONNECT << 16; |
814 | done(SCpnt); | 1085 | done(SCpnt); |
815 | return 0; | 1086 | return 0; |
816 | } | 1087 | } |
817 | 1088 | ||
1089 | // scsi_print_command(SCpnt); | ||
1090 | |||
818 | return mptscsih_qcmd(SCpnt,done); | 1091 | return mptscsih_qcmd(SCpnt,done); |
819 | } | 1092 | } |
820 | 1093 | ||
@@ -1114,9 +1387,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
1114 | goto out_free_consistent; | 1387 | goto out_free_consistent; |
1115 | } | 1388 | } |
1116 | 1389 | ||
1117 | if (port_info->num_phys) | ||
1118 | port_info->handle = | ||
1119 | le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); | ||
1120 | for (i = 0; i < port_info->num_phys; i++) { | 1390 | for (i = 0; i < port_info->num_phys; i++) { |
1121 | mptsas_print_phy_data(&buffer->PhyData[i]); | 1391 | mptsas_print_phy_data(&buffer->PhyData[i]); |
1122 | port_info->phy_info[i].phy_id = i; | 1392 | port_info->phy_info[i].phy_id = i; |
@@ -1125,6 +1395,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
1125 | port_info->phy_info[i].negotiated_link_rate = | 1395 | port_info->phy_info[i].negotiated_link_rate = |
1126 | buffer->PhyData[i].NegotiatedLinkRate; | 1396 | buffer->PhyData[i].NegotiatedLinkRate; |
1127 | port_info->phy_info[i].portinfo = port_info; | 1397 | port_info->phy_info[i].portinfo = port_info; |
1398 | port_info->phy_info[i].handle = | ||
1399 | le16_to_cpu(buffer->PhyData[i].ControllerDevHandle); | ||
1128 | } | 1400 | } |
1129 | 1401 | ||
1130 | out_free_consistent: | 1402 | out_free_consistent: |
@@ -1261,6 +1533,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
1261 | device_info->phy_id = buffer->PhyNum; | 1533 | device_info->phy_id = buffer->PhyNum; |
1262 | device_info->port_id = buffer->PhysicalPort; | 1534 | device_info->port_id = buffer->PhysicalPort; |
1263 | device_info->id = buffer->TargetID; | 1535 | device_info->id = buffer->TargetID; |
1536 | device_info->phys_disk_num = ~0; | ||
1264 | device_info->channel = buffer->Bus; | 1537 | device_info->channel = buffer->Bus; |
1265 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | 1538 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); |
1266 | device_info->sas_address = le64_to_cpu(sas_address); | 1539 | device_info->sas_address = le64_to_cpu(sas_address); |
@@ -1325,7 +1598,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | |||
1325 | 1598 | ||
1326 | /* save config data */ | 1599 | /* save config data */ |
1327 | port_info->num_phys = buffer->NumPhys; | 1600 | port_info->num_phys = buffer->NumPhys; |
1328 | port_info->handle = le16_to_cpu(buffer->DevHandle); | ||
1329 | port_info->phy_info = kcalloc(port_info->num_phys, | 1601 | port_info->phy_info = kcalloc(port_info->num_phys, |
1330 | sizeof(*port_info->phy_info),GFP_KERNEL); | 1602 | sizeof(*port_info->phy_info),GFP_KERNEL); |
1331 | if (!port_info->phy_info) { | 1603 | if (!port_info->phy_info) { |
@@ -1333,8 +1605,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | |||
1333 | goto out_free_consistent; | 1605 | goto out_free_consistent; |
1334 | } | 1606 | } |
1335 | 1607 | ||
1336 | for (i = 0; i < port_info->num_phys; i++) | 1608 | for (i = 0; i < port_info->num_phys; i++) { |
1337 | port_info->phy_info[i].portinfo = port_info; | 1609 | port_info->phy_info[i].portinfo = port_info; |
1610 | port_info->phy_info[i].handle = | ||
1611 | le16_to_cpu(buffer->DevHandle); | ||
1612 | } | ||
1338 | 1613 | ||
1339 | out_free_consistent: | 1614 | out_free_consistent: |
1340 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | 1615 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, |
@@ -1702,7 +1977,6 @@ static int | |||
1702 | mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | 1977 | mptsas_probe_hba_phys(MPT_ADAPTER *ioc) |
1703 | { | 1978 | { |
1704 | struct mptsas_portinfo *port_info, *hba; | 1979 | struct mptsas_portinfo *port_info, *hba; |
1705 | u32 handle = 0xFFFF; | ||
1706 | int error = -ENOMEM, i; | 1980 | int error = -ENOMEM, i; |
1707 | 1981 | ||
1708 | hba = kzalloc(sizeof(*port_info), GFP_KERNEL); | 1982 | hba = kzalloc(sizeof(*port_info), GFP_KERNEL); |
@@ -1714,34 +1988,36 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) | |||
1714 | goto out_free_port_info; | 1988 | goto out_free_port_info; |
1715 | 1989 | ||
1716 | mutex_lock(&ioc->sas_topology_mutex); | 1990 | mutex_lock(&ioc->sas_topology_mutex); |
1717 | ioc->handle = hba->handle; | 1991 | ioc->handle = hba->phy_info[0].handle; |
1718 | port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); | 1992 | port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); |
1719 | if (!port_info) { | 1993 | if (!port_info) { |
1720 | port_info = hba; | 1994 | port_info = hba; |
1721 | list_add_tail(&port_info->list, &ioc->sas_topology); | 1995 | list_add_tail(&port_info->list, &ioc->sas_topology); |
1722 | } else { | 1996 | } else { |
1723 | port_info->handle = hba->handle; | 1997 | for (i = 0; i < hba->num_phys; i++) { |
1724 | for (i = 0; i < hba->num_phys; i++) | ||
1725 | port_info->phy_info[i].negotiated_link_rate = | 1998 | port_info->phy_info[i].negotiated_link_rate = |
1726 | hba->phy_info[i].negotiated_link_rate; | 1999 | hba->phy_info[i].negotiated_link_rate; |
2000 | port_info->phy_info[i].handle = | ||
2001 | hba->phy_info[i].handle; | ||
2002 | port_info->phy_info[i].port_id = | ||
2003 | hba->phy_info[i].port_id; | ||
2004 | } | ||
1727 | kfree(hba->phy_info); | 2005 | kfree(hba->phy_info); |
1728 | kfree(hba); | 2006 | kfree(hba); |
1729 | hba = NULL; | 2007 | hba = NULL; |
1730 | } | 2008 | } |
1731 | mutex_unlock(&ioc->sas_topology_mutex); | 2009 | mutex_unlock(&ioc->sas_topology_mutex); |
1732 | |||
1733 | for (i = 0; i < port_info->num_phys; i++) { | 2010 | for (i = 0; i < port_info->num_phys; i++) { |
1734 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], | 2011 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], |
1735 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << | 2012 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << |
1736 | MPI_SAS_PHY_PGAD_FORM_SHIFT), i); | 2013 | MPI_SAS_PHY_PGAD_FORM_SHIFT), i); |
1737 | 2014 | ||
1738 | mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, | 2015 | mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, |
1739 | (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE << | 2016 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
1740 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle); | 2017 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
2018 | port_info->phy_info[i].handle); | ||
1741 | port_info->phy_info[i].identify.phy_id = | 2019 | port_info->phy_info[i].identify.phy_id = |
1742 | port_info->phy_info[i].phy_id; | 2020 | port_info->phy_info[i].phy_id = i; |
1743 | handle = port_info->phy_info[i].identify.handle; | ||
1744 | |||
1745 | if (port_info->phy_info[i].attached.handle) | 2021 | if (port_info->phy_info[i].attached.handle) |
1746 | mptsas_sas_device_pg0(ioc, | 2022 | mptsas_sas_device_pg0(ioc, |
1747 | &port_info->phy_info[i].attached, | 2023 | &port_info->phy_info[i].attached, |
@@ -1777,12 +2053,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) | |||
1777 | goto out; | 2053 | goto out; |
1778 | 2054 | ||
1779 | error = mptsas_sas_expander_pg0(ioc, ex, | 2055 | error = mptsas_sas_expander_pg0(ioc, ex, |
1780 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | 2056 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << |
1781 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); | 2057 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); |
1782 | if (error) | 2058 | if (error) |
1783 | goto out_free_port_info; | 2059 | goto out_free_port_info; |
1784 | 2060 | ||
1785 | *handle = ex->handle; | 2061 | *handle = ex->phy_info[0].handle; |
1786 | 2062 | ||
1787 | mutex_lock(&ioc->sas_topology_mutex); | 2063 | mutex_lock(&ioc->sas_topology_mutex); |
1788 | port_info = mptsas_find_portinfo_by_handle(ioc, *handle); | 2064 | port_info = mptsas_find_portinfo_by_handle(ioc, *handle); |
@@ -1790,7 +2066,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) | |||
1790 | port_info = ex; | 2066 | port_info = ex; |
1791 | list_add_tail(&port_info->list, &ioc->sas_topology); | 2067 | list_add_tail(&port_info->list, &ioc->sas_topology); |
1792 | } else { | 2068 | } else { |
1793 | port_info->handle = ex->handle; | 2069 | for (i = 0; i < ex->num_phys; i++) { |
2070 | port_info->phy_info[i].handle = | ||
2071 | ex->phy_info[i].handle; | ||
2072 | port_info->phy_info[i].port_id = | ||
2073 | ex->phy_info[i].port_id; | ||
2074 | } | ||
1794 | kfree(ex->phy_info); | 2075 | kfree(ex->phy_info); |
1795 | kfree(ex); | 2076 | kfree(ex); |
1796 | ex = NULL; | 2077 | ex = NULL; |
@@ -1868,8 +2149,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) | |||
1868 | struct mptsas_portinfo buffer; | 2149 | struct mptsas_portinfo buffer; |
1869 | struct mptsas_portinfo *port_info, *n, *parent; | 2150 | struct mptsas_portinfo *port_info, *n, *parent; |
1870 | struct mptsas_phyinfo *phy_info; | 2151 | struct mptsas_phyinfo *phy_info; |
1871 | struct scsi_target * starget; | ||
1872 | VirtTarget * vtarget; | ||
1873 | struct sas_port * port; | 2152 | struct sas_port * port; |
1874 | int i; | 2153 | int i; |
1875 | u64 expander_sas_address; | 2154 | u64 expander_sas_address; |
@@ -1884,26 +2163,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) | |||
1884 | 2163 | ||
1885 | if (mptsas_sas_expander_pg0(ioc, &buffer, | 2164 | if (mptsas_sas_expander_pg0(ioc, &buffer, |
1886 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << | 2165 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << |
1887 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { | 2166 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), |
1888 | 2167 | port_info->phy_info[0].handle)) { | |
1889 | /* | ||
1890 | * Issue target reset to all child end devices | ||
1891 | * then mark them deleted to prevent further | ||
1892 | * IO going to them. | ||
1893 | */ | ||
1894 | phy_info = port_info->phy_info; | ||
1895 | for (i = 0; i < port_info->num_phys; i++, phy_info++) { | ||
1896 | starget = mptsas_get_starget(phy_info); | ||
1897 | if (!starget) | ||
1898 | continue; | ||
1899 | vtarget = starget->hostdata; | ||
1900 | if(vtarget->deleted) | ||
1901 | continue; | ||
1902 | vtarget->deleted = 1; | ||
1903 | mptsas_target_reset(ioc, vtarget); | ||
1904 | sas_port_delete(mptsas_get_port(phy_info)); | ||
1905 | mptsas_port_delete(phy_info->port_details); | ||
1906 | } | ||
1907 | 2168 | ||
1908 | /* | 2169 | /* |
1909 | * Obtain the port_info instance to the parent port | 2170 | * Obtain the port_info instance to the parent port |
@@ -1972,11 +2233,13 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | |||
1972 | /* | 2233 | /* |
1973 | Reporting RAID volumes. | 2234 | Reporting RAID volumes. |
1974 | */ | 2235 | */ |
2236 | if (!ioc->ir_firmware) | ||
2237 | goto out; | ||
1975 | if (!ioc->raid_data.pIocPg2) | 2238 | if (!ioc->raid_data.pIocPg2) |
1976 | goto out; | 2239 | goto out; |
1977 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | 2240 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) |
1978 | goto out; | 2241 | goto out; |
1979 | for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | 2242 | for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { |
1980 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, | 2243 | scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, |
1981 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); | 2244 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); |
1982 | } | 2245 | } |
@@ -2030,12 +2293,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
2030 | mutex_lock(&ioc->sas_topology_mutex); | 2293 | mutex_lock(&ioc->sas_topology_mutex); |
2031 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 2294 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
2032 | for (i = 0; i < port_info->num_phys; i++) { | 2295 | for (i = 0; i < port_info->num_phys; i++) { |
2296 | if (!mptsas_is_end_device( | ||
2297 | &port_info->phy_info[i].attached)) | ||
2298 | continue; | ||
2033 | if (port_info->phy_info[i].attached.sas_address | 2299 | if (port_info->phy_info[i].attached.sas_address |
2034 | != sas_address) | 2300 | != sas_address) |
2035 | continue; | 2301 | continue; |
2302 | phy_info = &port_info->phy_info[i]; | ||
2303 | break; | ||
2304 | } | ||
2305 | } | ||
2306 | mutex_unlock(&ioc->sas_topology_mutex); | ||
2307 | return phy_info; | ||
2308 | } | ||
2309 | |||
2310 | static struct mptsas_phyinfo * | ||
2311 | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
2312 | { | ||
2313 | struct mptsas_portinfo *port_info; | ||
2314 | struct mptsas_phyinfo *phy_info = NULL; | ||
2315 | int i; | ||
2316 | |||
2317 | mutex_lock(&ioc->sas_topology_mutex); | ||
2318 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||
2319 | for (i = 0; i < port_info->num_phys; i++) { | ||
2036 | if (!mptsas_is_end_device( | 2320 | if (!mptsas_is_end_device( |
2037 | &port_info->phy_info[i].attached)) | 2321 | &port_info->phy_info[i].attached)) |
2038 | continue; | 2322 | continue; |
2323 | if (port_info->phy_info[i].attached.id != id) | ||
2324 | continue; | ||
2325 | if (port_info->phy_info[i].attached.channel != channel) | ||
2326 | continue; | ||
2039 | phy_info = &port_info->phy_info[i]; | 2327 | phy_info = &port_info->phy_info[i]; |
2040 | break; | 2328 | break; |
2041 | } | 2329 | } |
@@ -2045,7 +2333,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | |||
2045 | } | 2333 | } |
2046 | 2334 | ||
2047 | static struct mptsas_phyinfo * | 2335 | static struct mptsas_phyinfo * |
2048 | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | 2336 | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2049 | { | 2337 | { |
2050 | struct mptsas_portinfo *port_info; | 2338 | struct mptsas_portinfo *port_info; |
2051 | struct mptsas_phyinfo *phy_info = NULL; | 2339 | struct mptsas_phyinfo *phy_info = NULL; |
@@ -2054,11 +2342,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | |||
2054 | mutex_lock(&ioc->sas_topology_mutex); | 2342 | mutex_lock(&ioc->sas_topology_mutex); |
2055 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | 2343 | list_for_each_entry(port_info, &ioc->sas_topology, list) { |
2056 | for (i = 0; i < port_info->num_phys; i++) { | 2344 | for (i = 0; i < port_info->num_phys; i++) { |
2057 | if (port_info->phy_info[i].attached.id != id) | ||
2058 | continue; | ||
2059 | if (!mptsas_is_end_device( | 2345 | if (!mptsas_is_end_device( |
2060 | &port_info->phy_info[i].attached)) | 2346 | &port_info->phy_info[i].attached)) |
2061 | continue; | 2347 | continue; |
2348 | if (port_info->phy_info[i].attached.phys_disk_num == ~0) | ||
2349 | continue; | ||
2350 | if (port_info->phy_info[i].attached.phys_disk_num != id) | ||
2351 | continue; | ||
2352 | if (port_info->phy_info[i].attached.channel != channel) | ||
2353 | continue; | ||
2062 | phy_info = &port_info->phy_info[i]; | 2354 | phy_info = &port_info->phy_info[i]; |
2063 | break; | 2355 | break; |
2064 | } | 2356 | } |
@@ -2094,6 +2386,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) | |||
2094 | mptsas_reprobe_lun); | 2386 | mptsas_reprobe_lun); |
2095 | } | 2387 | } |
2096 | 2388 | ||
2389 | static void | ||
2390 | mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||
2391 | { | ||
2392 | CONFIGPARMS cfg; | ||
2393 | ConfigPageHeader_t hdr; | ||
2394 | dma_addr_t dma_handle; | ||
2395 | pRaidVolumePage0_t buffer = NULL; | ||
2396 | RaidPhysDiskPage0_t phys_disk; | ||
2397 | int i; | ||
2398 | struct mptsas_hotplug_event *ev; | ||
2399 | |||
2400 | memset(&cfg, 0 , sizeof(CONFIGPARMS)); | ||
2401 | memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); | ||
2402 | hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; | ||
2403 | cfg.pageAddr = (channel << 8) + id; | ||
2404 | cfg.cfghdr.hdr = &hdr; | ||
2405 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
2406 | |||
2407 | if (mpt_config(ioc, &cfg) != 0) | ||
2408 | goto out; | ||
2409 | |||
2410 | if (!hdr.PageLength) | ||
2411 | goto out; | ||
2412 | |||
2413 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, | ||
2414 | &dma_handle); | ||
2415 | |||
2416 | if (!buffer) | ||
2417 | goto out; | ||
2418 | |||
2419 | cfg.physAddr = dma_handle; | ||
2420 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
2421 | |||
2422 | if (mpt_config(ioc, &cfg) != 0) | ||
2423 | goto out; | ||
2424 | |||
2425 | if (!(buffer->VolumeStatus.Flags & | ||
2426 | MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)) | ||
2427 | goto out; | ||
2428 | |||
2429 | if (!buffer->NumPhysDisks) | ||
2430 | goto out; | ||
2431 | |||
2432 | for (i = 0; i < buffer->NumPhysDisks; i++) { | ||
2433 | |||
2434 | if (mpt_raid_phys_disk_pg0(ioc, | ||
2435 | buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||
2436 | continue; | ||
2437 | |||
2438 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
2439 | if (!ev) { | ||
2440 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | ||
2441 | goto out; | ||
2442 | } | ||
2443 | |||
2444 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
2445 | ev->ioc = ioc; | ||
2446 | ev->id = phys_disk.PhysDiskID; | ||
2447 | ev->channel = phys_disk.PhysDiskBus; | ||
2448 | ev->phys_disk_num_valid = 1; | ||
2449 | ev->phys_disk_num = phys_disk.PhysDiskNum; | ||
2450 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
2451 | schedule_work(&ev->work); | ||
2452 | } | ||
2453 | |||
2454 | out: | ||
2455 | if (buffer) | ||
2456 | pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||
2457 | dma_handle); | ||
2458 | } | ||
2097 | /* | 2459 | /* |
2098 | * Work queue thread to handle SAS hotplug events | 2460 | * Work queue thread to handle SAS hotplug events |
2099 | */ | 2461 | */ |
@@ -2102,6 +2464,7 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2102 | { | 2464 | { |
2103 | struct mptsas_hotplug_event *ev = | 2465 | struct mptsas_hotplug_event *ev = |
2104 | container_of(work, struct mptsas_hotplug_event, work); | 2466 | container_of(work, struct mptsas_hotplug_event, work); |
2467 | |||
2105 | MPT_ADAPTER *ioc = ev->ioc; | 2468 | MPT_ADAPTER *ioc = ev->ioc; |
2106 | struct mptsas_phyinfo *phy_info; | 2469 | struct mptsas_phyinfo *phy_info; |
2107 | struct sas_rphy *rphy; | 2470 | struct sas_rphy *rphy; |
@@ -2114,17 +2477,43 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2114 | VirtTarget *vtarget; | 2477 | VirtTarget *vtarget; |
2115 | VirtDevice *vdevice; | 2478 | VirtDevice *vdevice; |
2116 | 2479 | ||
2117 | |||
2118 | mutex_lock(&ioc->sas_discovery_mutex); | 2480 | mutex_lock(&ioc->sas_discovery_mutex); |
2119 | switch (ev->event_type) { | 2481 | switch (ev->event_type) { |
2120 | case MPTSAS_DEL_DEVICE: | 2482 | case MPTSAS_DEL_DEVICE: |
2121 | 2483 | ||
2122 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); | 2484 | phy_info = NULL; |
2485 | if (ev->phys_disk_num_valid) { | ||
2486 | if (ev->hidden_raid_component){ | ||
2487 | if (mptsas_sas_device_pg0(ioc, &sas_device, | ||
2488 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||
2489 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
2490 | (ev->channel << 8) + ev->id)) { | ||
2491 | dfailprintk((MYIOC_s_ERR_FMT | ||
2492 | "%s: exit at line=%d\n", ioc->name, | ||
2493 | __FUNCTION__, __LINE__)); | ||
2494 | break; | ||
2495 | } | ||
2496 | phy_info = mptsas_find_phyinfo_by_sas_address( | ||
2497 | ioc, sas_device.sas_address); | ||
2498 | }else | ||
2499 | phy_info = mptsas_find_phyinfo_by_phys_disk_num( | ||
2500 | ioc, ev->channel, ev->phys_disk_num); | ||
2501 | } | ||
2502 | |||
2503 | if (!phy_info) | ||
2504 | phy_info = mptsas_find_phyinfo_by_target(ioc, | ||
2505 | ev->channel, ev->id); | ||
2123 | 2506 | ||
2124 | /* | 2507 | /* |
2125 | * Sanity checks, for non-existing phys and remote rphys. | 2508 | * Sanity checks, for non-existing phys and remote rphys. |
2126 | */ | 2509 | */ |
2127 | if (!phy_info || !phy_info->port_details) { | 2510 | if (!phy_info){ |
2511 | dfailprintk((MYIOC_s_ERR_FMT | ||
2512 | "%s: exit at line=%d\n", ioc->name, | ||
2513 | __FUNCTION__, __LINE__)); | ||
2514 | break; | ||
2515 | } | ||
2516 | if (!phy_info->port_details) { | ||
2128 | dfailprintk((MYIOC_s_ERR_FMT | 2517 | dfailprintk((MYIOC_s_ERR_FMT |
2129 | "%s: exit at line=%d\n", ioc->name, | 2518 | "%s: exit at line=%d\n", ioc->name, |
2130 | __FUNCTION__, __LINE__)); | 2519 | __FUNCTION__, __LINE__)); |
@@ -2137,6 +2526,7 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2137 | __FUNCTION__, __LINE__)); | 2526 | __FUNCTION__, __LINE__)); |
2138 | break; | 2527 | break; |
2139 | } | 2528 | } |
2529 | |||
2140 | port = mptsas_get_port(phy_info); | 2530 | port = mptsas_get_port(phy_info); |
2141 | if (!port) { | 2531 | if (!port) { |
2142 | dfailprintk((MYIOC_s_ERR_FMT | 2532 | dfailprintk((MYIOC_s_ERR_FMT |
@@ -2159,28 +2549,35 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2159 | /* | 2549 | /* |
2160 | * Handling RAID components | 2550 | * Handling RAID components |
2161 | */ | 2551 | */ |
2162 | if (ev->phys_disk_num_valid) { | 2552 | if (ev->phys_disk_num_valid && |
2163 | vtarget->target_id = ev->phys_disk_num; | 2553 | ev->hidden_raid_component) { |
2164 | vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | 2554 | printk(MYIOC_s_INFO_FMT |
2555 | "RAID Hidding: channel=%d, id=%d, " | ||
2556 | "physdsk %d \n", ioc->name, ev->channel, | ||
2557 | ev->id, ev->phys_disk_num); | ||
2558 | vtarget->id = ev->phys_disk_num; | ||
2559 | vtarget->tflags |= | ||
2560 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
2165 | mptsas_reprobe_target(starget, 1); | 2561 | mptsas_reprobe_target(starget, 1); |
2166 | break; | 2562 | phy_info->attached.phys_disk_num = |
2563 | ev->phys_disk_num; | ||
2564 | break; | ||
2167 | } | 2565 | } |
2168 | |||
2169 | vtarget->deleted = 1; | ||
2170 | mptsas_target_reset(ioc, vtarget); | ||
2171 | } | 2566 | } |
2172 | 2567 | ||
2173 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 2568 | if (phy_info->attached.device_info & |
2569 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
2174 | ds = "ssp"; | 2570 | ds = "ssp"; |
2175 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 2571 | if (phy_info->attached.device_info & |
2572 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
2176 | ds = "stp"; | 2573 | ds = "stp"; |
2177 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 2574 | if (phy_info->attached.device_info & |
2575 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
2178 | ds = "sata"; | 2576 | ds = "sata"; |
2179 | 2577 | ||
2180 | printk(MYIOC_s_INFO_FMT | 2578 | printk(MYIOC_s_INFO_FMT |
2181 | "removing %s device, channel %d, id %d, phy %d\n", | 2579 | "removing %s device, channel %d, id %d, phy %d\n", |
2182 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | 2580 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); |
2183 | |||
2184 | #ifdef MPT_DEBUG_SAS_WIDE | 2581 | #ifdef MPT_DEBUG_SAS_WIDE |
2185 | dev_printk(KERN_DEBUG, &port->dev, | 2582 | dev_printk(KERN_DEBUG, &port->dev, |
2186 | "delete port (%d)\n", port->port_identifier); | 2583 | "delete port (%d)\n", port->port_identifier); |
@@ -2198,14 +2595,14 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2198 | */ | 2595 | */ |
2199 | if (mptsas_sas_device_pg0(ioc, &sas_device, | 2596 | if (mptsas_sas_device_pg0(ioc, &sas_device, |
2200 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 2597 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << |
2201 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { | 2598 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
2599 | (ev->channel << 8) + ev->id)) { | ||
2202 | dfailprintk((MYIOC_s_ERR_FMT | 2600 | dfailprintk((MYIOC_s_ERR_FMT |
2203 | "%s: exit at line=%d\n", ioc->name, | 2601 | "%s: exit at line=%d\n", ioc->name, |
2204 | __FUNCTION__, __LINE__)); | 2602 | __FUNCTION__, __LINE__)); |
2205 | break; | 2603 | break; |
2206 | } | 2604 | } |
2207 | 2605 | ||
2208 | ssleep(2); | ||
2209 | __mptsas_discovery_work(ioc); | 2606 | __mptsas_discovery_work(ioc); |
2210 | 2607 | ||
2211 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | 2608 | phy_info = mptsas_find_phyinfo_by_sas_address(ioc, |
@@ -2219,7 +2616,8 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2219 | } | 2616 | } |
2220 | 2617 | ||
2221 | starget = mptsas_get_starget(phy_info); | 2618 | starget = mptsas_get_starget(phy_info); |
2222 | if (starget) { | 2619 | if (starget && (!ev->hidden_raid_component)){ |
2620 | |||
2223 | vtarget = starget->hostdata; | 2621 | vtarget = starget->hostdata; |
2224 | 2622 | ||
2225 | if (!vtarget) { | 2623 | if (!vtarget) { |
@@ -2232,9 +2630,15 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2232 | * Handling RAID components | 2630 | * Handling RAID components |
2233 | */ | 2631 | */ |
2234 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2632 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { |
2235 | vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; | 2633 | printk(MYIOC_s_INFO_FMT |
2236 | vtarget->target_id = ev->id; | 2634 | "RAID Exposing: channel=%d, id=%d, " |
2635 | "physdsk %d \n", ioc->name, ev->channel, | ||
2636 | ev->id, ev->phys_disk_num); | ||
2637 | vtarget->tflags &= | ||
2638 | ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
2639 | vtarget->id = ev->id; | ||
2237 | mptsas_reprobe_target(starget, 0); | 2640 | mptsas_reprobe_target(starget, 0); |
2641 | phy_info->attached.phys_disk_num = ~0; | ||
2238 | } | 2642 | } |
2239 | break; | 2643 | break; |
2240 | } | 2644 | } |
@@ -2243,8 +2647,10 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2243 | dfailprintk((MYIOC_s_ERR_FMT | 2647 | dfailprintk((MYIOC_s_ERR_FMT |
2244 | "%s: exit at line=%d\n", ioc->name, | 2648 | "%s: exit at line=%d\n", ioc->name, |
2245 | __FUNCTION__, __LINE__)); | 2649 | __FUNCTION__, __LINE__)); |
2650 | if (ev->channel) printk("%d\n", __LINE__); | ||
2246 | break; | 2651 | break; |
2247 | } | 2652 | } |
2653 | |||
2248 | port = mptsas_get_port(phy_info); | 2654 | port = mptsas_get_port(phy_info); |
2249 | if (!port) { | 2655 | if (!port) { |
2250 | dfailprintk((MYIOC_s_ERR_FMT | 2656 | dfailprintk((MYIOC_s_ERR_FMT |
@@ -2252,15 +2658,17 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2252 | __FUNCTION__, __LINE__)); | 2658 | __FUNCTION__, __LINE__)); |
2253 | break; | 2659 | break; |
2254 | } | 2660 | } |
2255 | |||
2256 | memcpy(&phy_info->attached, &sas_device, | 2661 | memcpy(&phy_info->attached, &sas_device, |
2257 | sizeof(struct mptsas_devinfo)); | 2662 | sizeof(struct mptsas_devinfo)); |
2258 | 2663 | ||
2259 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 2664 | if (phy_info->attached.device_info & |
2665 | MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
2260 | ds = "ssp"; | 2666 | ds = "ssp"; |
2261 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 2667 | if (phy_info->attached.device_info & |
2668 | MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
2262 | ds = "stp"; | 2669 | ds = "stp"; |
2263 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 2670 | if (phy_info->attached.device_info & |
2671 | MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
2264 | ds = "sata"; | 2672 | ds = "sata"; |
2265 | 2673 | ||
2266 | printk(MYIOC_s_INFO_FMT | 2674 | printk(MYIOC_s_INFO_FMT |
@@ -2301,19 +2709,21 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2301 | break; | 2709 | break; |
2302 | case MPTSAS_DEL_RAID: | 2710 | case MPTSAS_DEL_RAID: |
2303 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | 2711 | sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, |
2304 | ev->id, 0); | 2712 | ev->id, 0); |
2305 | if (!sdev) | 2713 | if (!sdev) |
2306 | break; | 2714 | break; |
2307 | printk(MYIOC_s_INFO_FMT | 2715 | printk(MYIOC_s_INFO_FMT |
2308 | "removing raid volume, channel %d, id %d\n", | 2716 | "removing raid volume, channel %d, id %d\n", |
2309 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | 2717 | ioc->name, MPTSAS_RAID_CHANNEL, ev->id); |
2310 | vdevice = sdev->hostdata; | 2718 | vdevice = sdev->hostdata; |
2311 | vdevice->vtarget->deleted = 1; | ||
2312 | mptsas_target_reset(ioc, vdevice->vtarget); | ||
2313 | scsi_remove_device(sdev); | 2719 | scsi_remove_device(sdev); |
2314 | scsi_device_put(sdev); | 2720 | scsi_device_put(sdev); |
2315 | mpt_findImVolumes(ioc); | 2721 | mpt_findImVolumes(ioc); |
2316 | break; | 2722 | break; |
2723 | case MPTSAS_ADD_INACTIVE_VOLUME: | ||
2724 | mptsas_adding_inactive_raid_components(ioc, | ||
2725 | ev->channel, ev->id); | ||
2726 | break; | ||
2317 | case MPTSAS_IGNORE_EVENT: | 2727 | case MPTSAS_IGNORE_EVENT: |
2318 | default: | 2728 | default: |
2319 | break; | 2729 | break; |
@@ -2321,7 +2731,6 @@ mptsas_hotplug_work(struct work_struct *work) | |||
2321 | 2731 | ||
2322 | mutex_unlock(&ioc->sas_discovery_mutex); | 2732 | mutex_unlock(&ioc->sas_discovery_mutex); |
2323 | kfree(ev); | 2733 | kfree(ev); |
2324 | |||
2325 | } | 2734 | } |
2326 | 2735 | ||
2327 | static void | 2736 | static void |
@@ -2339,8 +2748,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, | |||
2339 | return; | 2748 | return; |
2340 | 2749 | ||
2341 | switch (sas_event_data->ReasonCode) { | 2750 | switch (sas_event_data->ReasonCode) { |
2342 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: | ||
2343 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: | 2751 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: |
2752 | |||
2753 | mptsas_target_reset_queue(ioc, sas_event_data); | ||
2754 | break; | ||
2755 | |||
2756 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: | ||
2344 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | 2757 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); |
2345 | if (!ev) { | 2758 | if (!ev) { |
2346 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | 2759 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); |
@@ -2375,15 +2788,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, | |||
2375 | mptsas_persist_clear_table); | 2788 | mptsas_persist_clear_table); |
2376 | schedule_work(&ioc->sas_persist_task); | 2789 | schedule_work(&ioc->sas_persist_task); |
2377 | break; | 2790 | break; |
2791 | /* | ||
2792 | * TODO, handle other events | ||
2793 | */ | ||
2378 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | 2794 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: |
2379 | /* TODO */ | 2795 | case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: |
2380 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | 2796 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: |
2381 | /* TODO */ | 2797 | case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: |
2798 | case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: | ||
2799 | case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: | ||
2800 | case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: | ||
2382 | default: | 2801 | default: |
2383 | break; | 2802 | break; |
2384 | } | 2803 | } |
2385 | } | 2804 | } |
2386 | |||
2387 | static void | 2805 | static void |
2388 | mptsas_send_raid_event(MPT_ADAPTER *ioc, | 2806 | mptsas_send_raid_event(MPT_ADAPTER *ioc, |
2389 | EVENT_DATA_RAID *raid_event_data) | 2807 | EVENT_DATA_RAID *raid_event_data) |
@@ -2404,31 +2822,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, | |||
2404 | INIT_WORK(&ev->work, mptsas_hotplug_work); | 2822 | INIT_WORK(&ev->work, mptsas_hotplug_work); |
2405 | ev->ioc = ioc; | 2823 | ev->ioc = ioc; |
2406 | ev->id = raid_event_data->VolumeID; | 2824 | ev->id = raid_event_data->VolumeID; |
2825 | ev->channel = raid_event_data->VolumeBus; | ||
2407 | ev->event_type = MPTSAS_IGNORE_EVENT; | 2826 | ev->event_type = MPTSAS_IGNORE_EVENT; |
2408 | 2827 | ||
2409 | switch (raid_event_data->ReasonCode) { | 2828 | switch (raid_event_data->ReasonCode) { |
2410 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: | 2829 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: |
2830 | ev->phys_disk_num_valid = 1; | ||
2831 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
2411 | ev->event_type = MPTSAS_ADD_DEVICE; | 2832 | ev->event_type = MPTSAS_ADD_DEVICE; |
2412 | break; | 2833 | break; |
2413 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 2834 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: |
2414 | ioc->raid_data.isRaid = 1; | ||
2415 | ev->phys_disk_num_valid = 1; | 2835 | ev->phys_disk_num_valid = 1; |
2416 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | 2836 | ev->phys_disk_num = raid_event_data->PhysDiskNum; |
2837 | ev->hidden_raid_component = 1; | ||
2417 | ev->event_type = MPTSAS_DEL_DEVICE; | 2838 | ev->event_type = MPTSAS_DEL_DEVICE; |
2418 | break; | 2839 | break; |
2419 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: | 2840 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: |
2420 | switch (state) { | 2841 | switch (state) { |
2421 | case MPI_PD_STATE_ONLINE: | 2842 | case MPI_PD_STATE_ONLINE: |
2422 | ioc->raid_data.isRaid = 1; | 2843 | case MPI_PD_STATE_NOT_COMPATIBLE: |
2423 | ev->phys_disk_num_valid = 1; | 2844 | ev->phys_disk_num_valid = 1; |
2424 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | 2845 | ev->phys_disk_num = raid_event_data->PhysDiskNum; |
2846 | ev->hidden_raid_component = 1; | ||
2425 | ev->event_type = MPTSAS_ADD_DEVICE; | 2847 | ev->event_type = MPTSAS_ADD_DEVICE; |
2426 | break; | 2848 | break; |
2427 | case MPI_PD_STATE_MISSING: | 2849 | case MPI_PD_STATE_MISSING: |
2428 | case MPI_PD_STATE_NOT_COMPATIBLE: | ||
2429 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: | 2850 | case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: |
2430 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: | 2851 | case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: |
2431 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: | 2852 | case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: |
2853 | ev->phys_disk_num_valid = 1; | ||
2854 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
2432 | ev->event_type = MPTSAS_DEL_DEVICE; | 2855 | ev->event_type = MPTSAS_DEL_DEVICE; |
2433 | break; | 2856 | break; |
2434 | default: | 2857 | default: |
@@ -2485,6 +2908,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, | |||
2485 | schedule_work(&ev->work); | 2908 | schedule_work(&ev->work); |
2486 | }; | 2909 | }; |
2487 | 2910 | ||
2911 | /* | ||
2912 | * mptsas_send_ir2_event - handle exposing hidden disk when | ||
2913 | * an inactive raid volume is added | ||
2914 | * | ||
2915 | * @ioc: Pointer to MPT_ADAPTER structure | ||
2916 | * @ir2_data | ||
2917 | * | ||
2918 | */ | ||
2919 | static void | ||
2920 | mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) | ||
2921 | { | ||
2922 | struct mptsas_hotplug_event *ev; | ||
2923 | |||
2924 | if (ir2_data->ReasonCode != | ||
2925 | MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) | ||
2926 | return; | ||
2927 | |||
2928 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
2929 | if (!ev) | ||
2930 | return; | ||
2931 | |||
2932 | INIT_WORK(&ev->work, mptsas_hotplug_work); | ||
2933 | ev->ioc = ioc; | ||
2934 | ev->id = ir2_data->TargetID; | ||
2935 | ev->channel = ir2_data->Bus; | ||
2936 | ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; | ||
2937 | |||
2938 | schedule_work(&ev->work); | ||
2939 | }; | ||
2488 | 2940 | ||
2489 | static int | 2941 | static int |
2490 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | 2942 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) |
@@ -2524,6 +2976,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | |||
2524 | mptsas_send_discovery_event(ioc, | 2976 | mptsas_send_discovery_event(ioc, |
2525 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); | 2977 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); |
2526 | break; | 2978 | break; |
2979 | case MPI_EVENT_IR2: | ||
2980 | mptsas_send_ir2_event(ioc, | ||
2981 | (PTR_MPI_EVENT_DATA_IR2)reply->Data); | ||
2982 | break; | ||
2527 | default: | 2983 | default: |
2528 | rc = mptscsih_event_process(ioc, reply); | 2984 | rc = mptscsih_event_process(ioc, reply); |
2529 | break; | 2985 | break; |
@@ -2611,12 +3067,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2611 | /* set 16 byte cdb's */ | 3067 | /* set 16 byte cdb's */ |
2612 | sh->max_cmd_len = 16; | 3068 | sh->max_cmd_len = 16; |
2613 | 3069 | ||
2614 | sh->max_id = ioc->pfacts->MaxDevices + 1; | 3070 | sh->max_id = ioc->pfacts[0].PortSCSIID; |
3071 | sh->max_lun = max_lun; | ||
2615 | 3072 | ||
2616 | sh->transportt = mptsas_transport_template; | 3073 | sh->transportt = mptsas_transport_template; |
2617 | 3074 | ||
2618 | sh->max_lun = MPT_LAST_LUN + 1; | ||
2619 | sh->max_channel = 0; | ||
2620 | sh->this_id = ioc->pfacts[0].PortSCSIID; | 3075 | sh->this_id = ioc->pfacts[0].PortSCSIID; |
2621 | 3076 | ||
2622 | /* Required entry. | 3077 | /* Required entry. |
@@ -2659,8 +3114,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2659 | sh->sg_tablesize = numSGE; | 3114 | sh->sg_tablesize = numSGE; |
2660 | } | 3115 | } |
2661 | 3116 | ||
2662 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2663 | |||
2664 | hd = (MPT_SCSI_HOST *) sh->hostdata; | 3117 | hd = (MPT_SCSI_HOST *) sh->hostdata; |
2665 | hd->ioc = ioc; | 3118 | hd->ioc = ioc; |
2666 | 3119 | ||
@@ -2676,19 +3129,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2676 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", | 3129 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", |
2677 | ioc->name, hd->ScsiLookup)); | 3130 | ioc->name, hd->ScsiLookup)); |
2678 | 3131 | ||
2679 | /* Allocate memory for the device structures. | ||
2680 | * A non-Null pointer at an offset | ||
2681 | * indicates a device exists. | ||
2682 | * max_id = 1 + maximum id (hosts.h) | ||
2683 | */ | ||
2684 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); | ||
2685 | if (!hd->Targets) { | ||
2686 | error = -ENOMEM; | ||
2687 | goto out_mptsas_probe; | ||
2688 | } | ||
2689 | |||
2690 | dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); | ||
2691 | |||
2692 | /* Clear the TM flags | 3132 | /* Clear the TM flags |
2693 | */ | 3133 | */ |
2694 | hd->tmPending = 0; | 3134 | hd->tmPending = 0; |
@@ -2713,15 +3153,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2713 | 3153 | ||
2714 | ioc->sas_data.ptClear = mpt_pt_clear; | 3154 | ioc->sas_data.ptClear = mpt_pt_clear; |
2715 | 3155 | ||
3156 | init_waitqueue_head(&hd->scandv_waitq); | ||
3157 | hd->scandv_wait_done = 0; | ||
3158 | hd->last_queue_full = 0; | ||
3159 | INIT_LIST_HEAD(&hd->target_reset_list); | ||
3160 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
3161 | |||
2716 | if (ioc->sas_data.ptClear==1) { | 3162 | if (ioc->sas_data.ptClear==1) { |
2717 | mptbase_sas_persist_operation( | 3163 | mptbase_sas_persist_operation( |
2718 | ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); | 3164 | ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); |
2719 | } | 3165 | } |
2720 | 3166 | ||
2721 | init_waitqueue_head(&hd->scandv_waitq); | ||
2722 | hd->scandv_wait_done = 0; | ||
2723 | hd->last_queue_full = 0; | ||
2724 | |||
2725 | error = scsi_add_host(sh, &ioc->pcidev->dev); | 3167 | error = scsi_add_host(sh, &ioc->pcidev->dev); |
2726 | if (error) { | 3168 | if (error) { |
2727 | dprintk((KERN_ERR MYNAM | 3169 | dprintk((KERN_ERR MYNAM |
@@ -2745,7 +3187,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | |||
2745 | struct mptsas_portinfo *p, *n; | 3187 | struct mptsas_portinfo *p, *n; |
2746 | int i; | 3188 | int i; |
2747 | 3189 | ||
2748 | ioc->sas_discovery_ignore_events=1; | 3190 | ioc->sas_discovery_ignore_events = 1; |
2749 | sas_remove_host(ioc->sh); | 3191 | sas_remove_host(ioc->sh); |
2750 | 3192 | ||
2751 | mutex_lock(&ioc->sas_topology_mutex); | 3193 | mutex_lock(&ioc->sas_topology_mutex); |
@@ -2800,7 +3242,7 @@ mptsas_init(void) | |||
2800 | return -ENODEV; | 3242 | return -ENODEV; |
2801 | 3243 | ||
2802 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); | 3244 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); |
2803 | mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); | 3245 | mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); |
2804 | mptsasInternalCtx = | 3246 | mptsasInternalCtx = |
2805 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); | 3247 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); |
2806 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); | 3248 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); |
@@ -2810,7 +3252,7 @@ mptsas_init(void) | |||
2810 | ": Registered for IOC event notifications\n")); | 3252 | ": Registered for IOC event notifications\n")); |
2811 | } | 3253 | } |
2812 | 3254 | ||
2813 | if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { | 3255 | if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) { |
2814 | dprintk((KERN_INFO MYNAM | 3256 | dprintk((KERN_INFO MYNAM |
2815 | ": Registered for IOC reset notifications\n")); | 3257 | ": Registered for IOC reset notifications\n")); |
2816 | } | 3258 | } |