diff options
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r-- | drivers/message/fusion/mptsas.c | 141 |
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; | |||
93 | static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; | 93 | static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; |
94 | static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ | 94 | static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ |
95 | static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; | 95 | static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; |
96 | static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS; | ||
96 | 97 | ||
97 | static void mptsas_hotplug_work(struct work_struct *work); | 98 | static 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 | **/ |
636 | static void | 637 | static int |
637 | mptsas_dev_reset_complete(MPT_ADAPTER *ioc) | 638 | mptsas_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 | **/ | ||
725 | static int | ||
726 | mptsas_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 | ||
3414 | module_init(mptsas_init); | 3447 | module_init(mptsas_init); |