aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message')
-rw-r--r--drivers/message/fusion/mptbase.h1
-rw-r--r--drivers/message/fusion/mptsas.c325
2 files changed, 281 insertions, 45 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 07830d28e58d..7176944e201c 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -994,6 +994,7 @@ typedef struct _MPT_SCSI_HOST {
994 int scandv_wait_done; 994 int scandv_wait_done;
995 long last_queue_full; 995 long last_queue_full;
996 u16 tm_iocstatus; 996 u16 tm_iocstatus;
997 struct list_head target_reset_list;
997} MPT_SCSI_HOST; 998} MPT_SCSI_HOST;
998 999
999/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1000/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index a8df06c422bd..3dbb5659f615 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -96,6 +96,12 @@ static int mptsasMgmtCtx = -1;
96 96
97static void mptsas_hotplug_work(struct work_struct *work); 97static void mptsas_hotplug_work(struct work_struct *work);
98 98
99struct 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};
104
99enum mptsas_hotplug_action { 105enum mptsas_hotplug_action {
100 MPTSAS_ADD_DEVICE, 106 MPTSAS_ADD_DEVICE,
101 MPTSAS_DEL_DEVICE, 107 MPTSAS_DEL_DEVICE,
@@ -571,20 +577,271 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
571 mutex_unlock(&ioc->sas_topology_mutex); 577 mutex_unlock(&ioc->sas_topology_mutex);
572} 578}
573 579
580/**
581 * csmisas_find_vtarget
582 *
583 * @ioc
584 * @volume_id
585 * @volume_bus
586 *
587 **/
588static VirtTarget *
589mptsas_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 **/
618static int
619mptsas_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 **/
574static void 664static void
575mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) 665mptsas_target_reset_queue(MPT_ADAPTER *ioc,
666 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
576{ 667{
577 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;
578 672
579 if (mptscsih_TMHandler(hd, 673 id = sas_event_data->TargetID;
580 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 674 channel = sas_event_data->Bus;
581 vtarget->channel, vtarget->id, 0, 0, 5) < 0) { 675
582 hd->tmPending = 0; 676 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
583 hd->tmState = TM_STATE_NONE; 677 return;
584 printk(MYIOC_s_WARN_FMT 678
585 "Error processing TaskMgmt id=%d TARGET_RESET\n", 679 vtarget->deleted = 1; /* block IO */
586 ioc->name, vtarget->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;
699 }
700}
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 **/
712static void
713mptsas_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 **/
801static int
802mptsas_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 **/
815static int
816mptsas_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);
587 } 841 }
842
843 out:
844 return rc;
588} 845}
589 846
590static int 847static int
@@ -1885,8 +2142,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1885 struct mptsas_portinfo buffer; 2142 struct mptsas_portinfo buffer;
1886 struct mptsas_portinfo *port_info, *n, *parent; 2143 struct mptsas_portinfo *port_info, *n, *parent;
1887 struct mptsas_phyinfo *phy_info; 2144 struct mptsas_phyinfo *phy_info;
1888 struct scsi_target * starget;
1889 VirtTarget * vtarget;
1890 struct sas_port * port; 2145 struct sas_port * port;
1891 int i; 2146 int i;
1892 u64 expander_sas_address; 2147 u64 expander_sas_address;
@@ -1904,25 +2159,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1904 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { 2159 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1905 2160
1906 /* 2161 /*
1907 * Issue target reset to all child end devices
1908 * then mark them deleted to prevent further
1909 * IO going to them.
1910 */
1911 phy_info = port_info->phy_info;
1912 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1913 starget = mptsas_get_starget(phy_info);
1914 if (!starget)
1915 continue;
1916 vtarget = starget->hostdata;
1917 if(vtarget->deleted)
1918 continue;
1919 vtarget->deleted = 1;
1920 mptsas_target_reset(ioc, vtarget);
1921 sas_port_delete(mptsas_get_port(phy_info));
1922 mptsas_port_delete(phy_info->port_details);
1923 }
1924
1925 /*
1926 * Obtain the port_info instance to the parent port 2162 * Obtain the port_info instance to the parent port
1927 */ 2163 */
1928 parent = mptsas_find_portinfo_by_handle(ioc, 2164 parent = mptsas_find_portinfo_by_handle(ioc,
@@ -2319,9 +2555,6 @@ mptsas_hotplug_work(struct work_struct *work)
2319 ev->phys_disk_num; 2555 ev->phys_disk_num;
2320 break; 2556 break;
2321 } 2557 }
2322
2323 vtarget->deleted = 1;
2324 mptsas_target_reset(ioc, vtarget);
2325 } 2558 }
2326 2559
2327 if (phy_info->attached.device_info & 2560 if (phy_info->attached.device_info &
@@ -2474,8 +2707,6 @@ mptsas_hotplug_work(struct work_struct *work)
2474 printk(MYIOC_s_INFO_FMT 2707 printk(MYIOC_s_INFO_FMT
2475 "removing raid volume, channel %d, id %d\n", 2708 "removing raid volume, channel %d, id %d\n",
2476 ioc->name, MPTSAS_RAID_CHANNEL, ev->id); 2709 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2477 vdevice->vtarget->deleted = 1;
2478 mptsas_target_reset(ioc, vdevice->vtarget);
2479 vdevice = sdev->hostdata; 2710 vdevice = sdev->hostdata;
2480 scsi_remove_device(sdev); 2711 scsi_remove_device(sdev);
2481 scsi_device_put(sdev); 2712 scsi_device_put(sdev);
@@ -2509,8 +2740,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
2509 return; 2740 return;
2510 2741
2511 switch (sas_event_data->ReasonCode) { 2742 switch (sas_event_data->ReasonCode) {
2512 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2513 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: 2743 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
2744
2745 mptsas_target_reset_queue(ioc, sas_event_data);
2746 break;
2747
2748 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2514 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 2749 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2515 if (!ev) { 2750 if (!ev) {
2516 printk(KERN_WARNING "mptsas: lost hotplug event\n"); 2751 printk(KERN_WARNING "mptsas: lost hotplug event\n");
@@ -2871,8 +3106,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2871 sh->sg_tablesize = numSGE; 3106 sh->sg_tablesize = numSGE;
2872 } 3107 }
2873 3108
2874 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2875
2876 hd = (MPT_SCSI_HOST *) sh->hostdata; 3109 hd = (MPT_SCSI_HOST *) sh->hostdata;
2877 hd->ioc = ioc; 3110 hd->ioc = ioc;
2878 3111
@@ -2912,15 +3145,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2912 3145
2913 ioc->sas_data.ptClear = mpt_pt_clear; 3146 ioc->sas_data.ptClear = mpt_pt_clear;
2914 3147
3148 init_waitqueue_head(&hd->scandv_waitq);
3149 hd->scandv_wait_done = 0;
3150 hd->last_queue_full = 0;
3151 INIT_LIST_HEAD(&hd->target_reset_list);
3152 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3153
2915 if (ioc->sas_data.ptClear==1) { 3154 if (ioc->sas_data.ptClear==1) {
2916 mptbase_sas_persist_operation( 3155 mptbase_sas_persist_operation(
2917 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); 3156 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2918 } 3157 }
2919 3158
2920 init_waitqueue_head(&hd->scandv_waitq);
2921 hd->scandv_wait_done = 0;
2922 hd->last_queue_full = 0;
2923
2924 error = scsi_add_host(sh, &ioc->pcidev->dev); 3159 error = scsi_add_host(sh, &ioc->pcidev->dev);
2925 if (error) { 3160 if (error) {
2926 dprintk((KERN_ERR MYNAM 3161 dprintk((KERN_ERR MYNAM
@@ -2999,7 +3234,7 @@ mptsas_init(void)
2999 return -ENODEV; 3234 return -ENODEV;
3000 3235
3001 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); 3236 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
3002 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); 3237 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
3003 mptsasInternalCtx = 3238 mptsasInternalCtx =
3004 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); 3239 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
3005 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); 3240 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
@@ -3009,7 +3244,7 @@ mptsas_init(void)
3009 ": Registered for IOC event notifications\n")); 3244 ": Registered for IOC event notifications\n"));
3010 } 3245 }
3011 3246
3012 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { 3247 if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
3013 dprintk((KERN_INFO MYNAM 3248 dprintk((KERN_INFO MYNAM
3014 ": Registered for IOC reset notifications\n")); 3249 ": Registered for IOC reset notifications\n"));
3015 } 3250 }