aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c141
1 files changed, 87 insertions, 54 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 16c4232c37de..3efa728fc590 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -93,6 +93,7 @@ static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; 93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ 94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; 95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
96static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
96 97
97static void mptsas_hotplug_work(struct work_struct *work); 98static void mptsas_hotplug_work(struct work_struct *work);
98 99
@@ -523,10 +524,12 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
523 VirtTarget *vtarget = NULL; 524 VirtTarget *vtarget = NULL;
524 525
525 shost_for_each_device(sdev, ioc->sh) { 526 shost_for_each_device(sdev, ioc->sh) {
526 if ((vdevice = sdev->hostdata) == NULL) 527 vdevice = sdev->hostdata;
528 if ((vdevice == NULL) ||
529 (vdevice->vtarget == NULL))
527 continue; 530 continue;
528 if (vdevice->vtarget->id == id && 531 if (vdevice->vtarget->id == id &&
529 vdevice->vtarget->channel == channel) 532 vdevice->vtarget->channel == channel)
530 vtarget = vdevice->vtarget; 533 vtarget = vdevice->vtarget;
531 } 534 }
532 return vtarget; 535 return vtarget;
@@ -551,9 +554,11 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
551 MPT_FRAME_HDR *mf; 554 MPT_FRAME_HDR *mf;
552 SCSITaskMgmt_t *pScsiTm; 555 SCSITaskMgmt_t *pScsiTm;
553 556
554 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { 557 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
555 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", 558 if (mf == NULL) {
556 ioc->name,__func__, __LINE__)); 559 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
560 "%s, no msg frames @%d!!\n",
561 ioc->name, __func__, __LINE__));
557 return 0; 562 return 0;
558 } 563 }
559 564
@@ -569,7 +574,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
569 574
570 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); 575 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
571 576
572 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); 577 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
573 578
574 return 1; 579 return 1;
575} 580}
@@ -605,8 +610,9 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
605 target_reset_list = kzalloc(sizeof(*target_reset_list), 610 target_reset_list = kzalloc(sizeof(*target_reset_list),
606 GFP_ATOMIC); 611 GFP_ATOMIC);
607 if (!target_reset_list) { 612 if (!target_reset_list) {
608 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", 613 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
609 ioc->name,__func__, __LINE__)); 614 "%s, failed to allocate mem @%d..!!\n",
615 ioc->name, __func__, __LINE__));
610 return; 616 return;
611 } 617 }
612 618
@@ -614,55 +620,94 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
614 sizeof(*sas_event_data)); 620 sizeof(*sas_event_data));
615 list_add_tail(&target_reset_list->list, &hd->target_reset_list); 621 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
616 622
617 if (hd->resetPending) 623 target_reset_list->time_count = jiffies;
618 return;
619 624
620 if (mptsas_target_reset(ioc, channel, id)) { 625 if (mptsas_target_reset(ioc, channel, id)) {
621 target_reset_list->target_reset_issued = 1; 626 target_reset_list->target_reset_issued = 1;
622 hd->resetPending = 1;
623 } 627 }
624} 628}
625 629
626/** 630/**
627 * mptsas_dev_reset_complete 631 * mptsas_taskmgmt_complete - Completion for TARGET_RESET after
628 * 632 * NOT_RESPONDING_EVENT, enable work queue to finish off removing device
629 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, 633 * from upper layers. then send next TARGET_RESET in the queue.
630 * enable work queue to finish off removing device from upper layers. 634 * @ioc: Pointer to MPT_ADAPTER structure
631 * then send next TARGET_RESET in the queue.
632 *
633 * @ioc
634 * 635 *
635 **/ 636 **/
636static void 637static int
637mptsas_dev_reset_complete(MPT_ADAPTER *ioc) 638mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
638{ 639{
639 MPT_SCSI_HOST *hd = shost_priv(ioc->sh); 640 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
640 struct list_head *head = &hd->target_reset_list; 641 struct list_head *head = &hd->target_reset_list;
641 struct mptsas_target_reset_event *target_reset_list;
642 struct mptsas_hotplug_event *ev; 642 struct mptsas_hotplug_event *ev;
643 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; 643 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
644 u8 id, channel; 644 u8 id, channel;
645 __le64 sas_address; 645 __le64 sas_address;
646 struct mptsas_target_reset_event *target_reset_list;
647 SCSITaskMgmtReply_t *pScsiTmReply;
648
649 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
650 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
651
652 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
653 if (pScsiTmReply) {
654 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
655 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
656 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
657 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
658 "term_cmnds = %d\n", ioc->name,
659 pScsiTmReply->Bus, pScsiTmReply->TargetID,
660 pScsiTmReply->TaskType,
661 le16_to_cpu(pScsiTmReply->IOCStatus),
662 le32_to_cpu(pScsiTmReply->IOCLogInfo),
663 pScsiTmReply->ResponseCode,
664 le32_to_cpu(pScsiTmReply->TerminationCount)));
665
666 if (pScsiTmReply->ResponseCode)
667 mptscsih_taskmgmt_response_code(ioc,
668 pScsiTmReply->ResponseCode);
669 }
670
671 if (pScsiTmReply && (pScsiTmReply->TaskType ==
672 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
673 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
674 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
675 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
676 memcpy(ioc->taskmgmt_cmds.reply, mr,
677 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
678 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
679 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
680 complete(&ioc->taskmgmt_cmds.done);
681 return 1;
682 }
683 return 0;
684 }
685
686 mpt_clear_taskmgmt_in_progress_flag(ioc);
646 687
647 if (list_empty(head)) 688 if (list_empty(head))
648 return; 689 return 1;
690
691 target_reset_list = list_entry(head->next,
692 struct mptsas_target_reset_event, list);
649 693
650 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); 694 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
695 "TaskMgmt: completed (%d seconds)\n",
696 ioc->name, jiffies_to_msecs(jiffies -
697 target_reset_list->time_count)/1000));
651 698
652 sas_event_data = &target_reset_list->sas_event_data; 699 sas_event_data = &target_reset_list->sas_event_data;
653 id = sas_event_data->TargetID; 700 id = pScsiTmReply->TargetID;
654 channel = sas_event_data->Bus; 701 channel = pScsiTmReply->Bus;
655 hd->resetPending = 0; 702 target_reset_list->time_count = jiffies;
656 703
657 /* 704 /*
658 * retry target reset 705 * retry target reset
659 */ 706 */
660 if (!target_reset_list->target_reset_issued) { 707 if (!target_reset_list->target_reset_issued) {
661 if (mptsas_target_reset(ioc, channel, id)) { 708 if (mptsas_target_reset(ioc, channel, id))
662 target_reset_list->target_reset_issued = 1; 709 target_reset_list->target_reset_issued = 1;
663 hd->resetPending = 1; 710 return 1;
664 }
665 return;
666 } 711 }
667 712
668 /* 713 /*
@@ -674,7 +719,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
674 if (!ev) { 719 if (!ev) {
675 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", 720 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
676 ioc->name,__func__, __LINE__)); 721 ioc->name,__func__, __LINE__));
677 return; 722 return 0;
678 } 723 }
679 724
680 INIT_WORK(&ev->work, mptsas_hotplug_work); 725 INIT_WORK(&ev->work, mptsas_hotplug_work);
@@ -693,40 +738,26 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
693 schedule_work(&ev->work); 738 schedule_work(&ev->work);
694 kfree(target_reset_list); 739 kfree(target_reset_list);
695 740
741
696 /* 742 /*
697 * issue target reset to next device in the queue 743 * issue target reset to next device in the queue
698 */ 744 */
699 745
700 head = &hd->target_reset_list; 746 head = &hd->target_reset_list;
701 if (list_empty(head)) 747 if (list_empty(head))
702 return; 748 return 1;
703 749
704 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, 750 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
705 list); 751 list);
706 752
707 sas_event_data = &target_reset_list->sas_event_data; 753 id = target_reset_list->sas_event_data.TargetID;
708 id = sas_event_data->TargetID; 754 channel = target_reset_list->sas_event_data.Bus;
709 channel = sas_event_data->Bus; 755 target_reset_list->time_count = jiffies;
710 756
711 if (mptsas_target_reset(ioc, channel, id)) { 757 if (mptsas_target_reset(ioc, channel, id))
712 target_reset_list->target_reset_issued = 1; 758 target_reset_list->target_reset_issued = 1;
713 hd->resetPending = 1;
714 }
715}
716 759
717/** 760 return 1;
718 * mptsas_taskmgmt_complete
719 *
720 * @ioc
721 * @mf
722 * @mr
723 *
724 **/
725static int
726mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
727{
728 mptsas_dev_reset_complete(ioc);
729 return mptscsih_taskmgmt_complete(ioc, mf, mr);
730} 761}
731 762
732/** 763/**
@@ -3262,7 +3293,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3262 */ 3293 */
3263 hd->tmPending = 0; 3294 hd->tmPending = 0;
3264 hd->tmState = TM_STATE_NONE; 3295 hd->tmState = TM_STATE_NONE;
3265 hd->resetPending = 0;
3266 hd->abortSCpnt = NULL; 3296 hd->abortSCpnt = NULL;
3267 3297
3268 /* Clear the pointer used to store 3298 /* Clear the pointer used to store
@@ -3381,10 +3411,12 @@ mptsas_init(void)
3381 return -ENODEV; 3411 return -ENODEV;
3382 3412
3383 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); 3413 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
3384 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); 3414 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
3385 mptsasInternalCtx = 3415 mptsasInternalCtx =
3386 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); 3416 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
3387 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); 3417 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
3418 mptsasDeviceResetCtx =
3419 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
3388 3420
3389 mpt_event_register(mptsasDoneCtx, mptsas_event_process); 3421 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3390 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset); 3422 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
@@ -3409,6 +3441,7 @@ mptsas_exit(void)
3409 mpt_deregister(mptsasInternalCtx); 3441 mpt_deregister(mptsasInternalCtx);
3410 mpt_deregister(mptsasTaskCtx); 3442 mpt_deregister(mptsasTaskCtx);
3411 mpt_deregister(mptsasDoneCtx); 3443 mpt_deregister(mptsasDoneCtx);
3444 mpt_deregister(mptsasDeviceResetCtx);
3412} 3445}
3413 3446
3414module_init(mptsas_init); 3447module_init(mptsas_init);