aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-06-20 17:09:16 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:04:50 -0400
commit77c852f312243192b1f2ce7fc56d678784786692 (patch)
treebb0f8a9694f1f2cf4d7985ef3dc40af79963c4f7
parentf53a3a32c1e799e27f63bff7b42b4c36749e5e6f (diff)
isci: Handle timed-out request terminations correctly
In the situation where a termination of an I/O times-out, make sure that the linkage from the request to the task is severed completely. Also make sure that the selection of tasks to terminate occurs under scic_lock. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/scsi/isci/request.c9
-rw-r--r--drivers/scsi/isci/task.c358
2 files changed, 181 insertions, 186 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 5879e5f308e6..433565c2b343 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2741,6 +2741,15 @@ static void isci_request_io_request_complete(struct isci_host *isci_host,
2741 spin_unlock(&request->state_lock); 2741 spin_unlock(&request->state_lock);
2742 break; 2742 break;
2743 2743
2744 case dead:
2745 /* This was a terminated request that timed-out during the
2746 * termination process. There is no task to complete to
2747 * libsas.
2748 */
2749 complete_to_host = isci_perform_normal_io_completion;
2750 spin_unlock(&request->state_lock);
2751 break;
2752
2744 default: 2753 default:
2745 2754
2746 /* The request is done from an SCU HW perspective. */ 2755 /* The request is done from an SCU HW perspective. */
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 709c08171743..573cf1c9e81d 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -567,31 +567,33 @@ static enum isci_request_status isci_task_validate_request_to_abort(
567 return old_state; 567 return old_state;
568} 568}
569 569
570/**
571* isci_request_cleanup_completed_loiterer() - This function will take care of
572* the final cleanup on any request which has been explicitly terminated.
573* @isci_host: This parameter specifies the ISCI host object
574* @isci_device: This is the device to which the request is pending.
575* @isci_request: This parameter specifies the terminated request object.
576* @task: This parameter is the libsas I/O request.
577*/
570static void isci_request_cleanup_completed_loiterer( 578static void isci_request_cleanup_completed_loiterer(
571 struct isci_host *isci_host, 579 struct isci_host *isci_host,
572 struct isci_remote_device *isci_device, 580 struct isci_remote_device *isci_device,
573 struct isci_request *isci_request) 581 struct isci_request *isci_request,
582 struct sas_task *task)
574{ 583{
575 struct sas_task *task; 584 unsigned long flags;
576 unsigned long flags;
577
578 task = (isci_request->ttype == io_task)
579 ? isci_request_access_task(isci_request)
580 : NULL;
581 585
582 dev_dbg(&isci_host->pdev->dev, 586 dev_dbg(&isci_host->pdev->dev,
583 "%s: isci_device=%p, request=%p, task=%p\n", 587 "%s: isci_device=%p, request=%p, task=%p\n",
584 __func__, isci_device, isci_request, task); 588 __func__, isci_device, isci_request, task);
585 589
586 spin_lock_irqsave(&isci_host->scic_lock, flags);
587 list_del_init(&isci_request->dev_node);
588 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
589
590 if (task != NULL) { 590 if (task != NULL) {
591 591
592 spin_lock_irqsave(&task->task_state_lock, flags); 592 spin_lock_irqsave(&task->task_state_lock, flags);
593 task->lldd_task = NULL; 593 task->lldd_task = NULL;
594 594
595 task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
596
595 isci_set_task_doneflags(task); 597 isci_set_task_doneflags(task);
596 598
597 /* If this task is not in the abort path, call task_done. */ 599 /* If this task is not in the abort path, call task_done. */
@@ -602,61 +604,16 @@ static void isci_request_cleanup_completed_loiterer(
602 } else 604 } else
603 spin_unlock_irqrestore(&task->task_state_lock, flags); 605 spin_unlock_irqrestore(&task->task_state_lock, flags);
604 } 606 }
605 isci_request_free(isci_host, isci_request);
606}
607
608/**
609* @isci_termination_timed_out(): this function will deal with a request for
610* which the wait for termination has timed-out.
611*
612* @isci_host This SCU.
613* @isci_request The I/O request being terminated.
614*/
615static void
616isci_termination_timed_out(
617 struct isci_host * host,
618 struct isci_request * request
619 )
620{
621 unsigned long state_flags;
622
623 dev_warn(&host->pdev->dev,
624 "%s: host = %p; request = %p\n",
625 __func__, host, request);
626 607
627 /* At this point, the request to terminate 608 if (isci_request != NULL) {
628 * has timed out. The best we can do is to 609 spin_lock_irqsave(&isci_host->scic_lock, flags);
629 * have the request die a silent death 610 list_del_init(&isci_request->dev_node);
630 * if it ever completes. 611 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
631 */
632 spin_lock_irqsave(&request->state_lock, state_flags);
633
634 if (request->status == started) {
635
636 /* Set the request state to "dead",
637 * and clear the task pointer so that an actual
638 * completion event callback doesn't do
639 * anything.
640 */
641 request->status = dead;
642
643 /* Clear the timeout completion event pointer.*/
644 request->io_request_completion = NULL;
645
646 if (request->ttype == io_task) {
647
648 /* Break links with the sas_task. */
649 if (request->ttype_ptr.io_task_ptr != NULL) {
650 612
651 request->ttype_ptr.io_task_ptr->lldd_task = NULL; 613 isci_request_free(isci_host, isci_request);
652 request->ttype_ptr.io_task_ptr = NULL;
653 }
654 }
655 } 614 }
656 spin_unlock_irqrestore(&request->state_lock, state_flags);
657} 615}
658 616
659
660/** 617/**
661 * isci_terminate_request_core() - This function will terminate the given 618 * isci_terminate_request_core() - This function will terminate the given
662 * request, and wait for it to complete. This function must only be called 619 * request, and wait for it to complete. This function must only be called
@@ -666,7 +623,6 @@ isci_termination_timed_out(
666 * @isci_device: The target. 623 * @isci_device: The target.
667 * @isci_request: The I/O request to be terminated. 624 * @isci_request: The I/O request to be terminated.
668 * 625 *
669 *
670 */ 626 */
671static void isci_terminate_request_core( 627static void isci_terminate_request_core(
672 struct isci_host *isci_host, 628 struct isci_host *isci_host,
@@ -677,9 +633,10 @@ static void isci_terminate_request_core(
677 bool was_terminated = false; 633 bool was_terminated = false;
678 bool needs_cleanup_handling = false; 634 bool needs_cleanup_handling = false;
679 enum isci_request_status request_status; 635 enum isci_request_status request_status;
680 unsigned long flags; 636 unsigned long flags;
681 unsigned long timeout_remaining; 637 unsigned long termination_completed = 1;
682 638 struct completion *io_request_completion;
639 struct sas_task *task;
683 640
684 dev_dbg(&isci_host->pdev->dev, 641 dev_dbg(&isci_host->pdev->dev,
685 "%s: device = %p; request = %p\n", 642 "%s: device = %p; request = %p\n",
@@ -687,6 +644,12 @@ static void isci_terminate_request_core(
687 644
688 spin_lock_irqsave(&isci_host->scic_lock, flags); 645 spin_lock_irqsave(&isci_host->scic_lock, flags);
689 646
647 io_request_completion = isci_request->io_request_completion;
648
649 task = (isci_request->ttype == io_task)
650 ? isci_request_access_task(isci_request)
651 : NULL;
652
690 /* Note that we are not going to control 653 /* Note that we are not going to control
691 * the target to abort the request. 654 * the target to abort the request.
692 */ 655 */
@@ -715,119 +678,112 @@ static void isci_terminate_request_core(
715 dev_err(&isci_host->pdev->dev, 678 dev_err(&isci_host->pdev->dev,
716 "%s: scic_controller_terminate_request" 679 "%s: scic_controller_terminate_request"
717 " returned = 0x%x\n", 680 " returned = 0x%x\n",
718 __func__, 681 __func__, status);
719 status); 682
720 /* Clear the completion pointer from the request. */
721 isci_request->io_request_completion = NULL; 683 isci_request->io_request_completion = NULL;
722 684
723 } else { 685 } else {
724 if (was_terminated) { 686 if (was_terminated) {
725 dev_dbg(&isci_host->pdev->dev, 687 dev_dbg(&isci_host->pdev->dev,
726 "%s: before completion wait (%p)\n", 688 "%s: before completion wait (%p/%p)\n",
727 __func__, 689 __func__, isci_request, io_request_completion);
728 isci_request->io_request_completion);
729 690
730 /* Wait here for the request to complete. */ 691 /* Wait here for the request to complete. */
731 #define TERMINATION_TIMEOUT_MSEC 50 692 #define TERMINATION_TIMEOUT_MSEC 500
732 timeout_remaining 693 termination_completed
733 = wait_for_completion_timeout( 694 = wait_for_completion_timeout(
734 isci_request->io_request_completion, 695 io_request_completion,
735 msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC)); 696 msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
736 697
737 if (!timeout_remaining) { 698 if (!termination_completed) {
699
700 /* The request to terminate has timed out. */
701 spin_lock_irqsave(&isci_host->scic_lock,
702 flags);
703
704 /* Check for state changes. */
705 if (!isci_request->terminated) {
706
707 /* The best we can do is to have the
708 * request die a silent death if it
709 * ever really completes.
710 *
711 * Set the request state to "dead",
712 * and clear the task pointer so that
713 * an actual completion event callback
714 * doesn't do anything.
715 */
716 isci_request->status = dead;
717 isci_request->io_request_completion
718 = NULL;
719
720 if (isci_request->ttype == io_task) {
721
722 /* Break links with the
723 * sas_task.
724 */
725 isci_request->ttype_ptr.io_task_ptr
726 = NULL;
727 }
728 } else
729 termination_completed = 1;
730
731 spin_unlock_irqrestore(&isci_host->scic_lock,
732 flags);
738 733
739 isci_termination_timed_out(isci_host, 734 if (!termination_completed) {
740 isci_request);
741 735
742 dev_err(&isci_host->pdev->dev, 736 dev_err(&isci_host->pdev->dev,
743 "%s: *** Timeout waiting for " 737 "%s: *** Timeout waiting for "
744 "termination(%p/%p)\n", 738 "termination(%p/%p)\n",
745 __func__, 739 __func__, io_request_completion,
746 isci_request->io_request_completion, 740 isci_request);
747 isci_request);
748 741
749 } else 742 /* The request can no longer be referenced
743 * safely since it may go away if the
744 * termination every really does complete.
745 */
746 isci_request = NULL;
747 }
748 }
749 if (termination_completed)
750 dev_dbg(&isci_host->pdev->dev, 750 dev_dbg(&isci_host->pdev->dev,
751 "%s: after completion wait (%p)\n", 751 "%s: after completion wait (%p/%p)\n",
752 __func__, 752 __func__, isci_request, io_request_completion);
753 isci_request->io_request_completion);
754 } 753 }
755 /* Clear the completion pointer from the request. */
756 isci_request->io_request_completion = NULL;
757 754
758 /* Peek at the status of the request. This will tell 755 if (termination_completed) {
759 * us if there was special handling on the request such that it
760 * needs to be detached and freed here.
761 */
762 spin_lock_irqsave(&isci_request->state_lock, flags);
763 request_status = isci_request_get_state(isci_request);
764
765 if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
766 && ((request_status == aborted)
767 || (request_status == aborting)
768 || (request_status == terminating)
769 || (request_status == completed)
770 || (request_status == dead)
771 )
772 ) {
773
774 /* The completion routine won't free a request in
775 * the aborted/aborting/etc. states, so we do
776 * it here.
777 */
778 needs_cleanup_handling = true;
779 }
780 spin_unlock_irqrestore(&isci_request->state_lock, flags);
781
782 if (needs_cleanup_handling)
783 isci_request_cleanup_completed_loiterer(
784 isci_host, isci_device, isci_request
785 );
786 }
787}
788 756
789static void isci_terminate_request( 757 isci_request->io_request_completion = NULL;
790 struct isci_host *isci_host,
791 struct isci_remote_device *isci_device,
792 struct isci_request *isci_request,
793 enum isci_request_status new_request_state)
794{
795 enum isci_request_status old_state;
796 DECLARE_COMPLETION_ONSTACK(request_completion);
797 758
798 /* Change state to "new_request_state" if it is currently "started" */ 759 /* Peek at the status of the request. This will tell
799 old_state = isci_request_change_started_to_newstate( 760 * us if there was special handling on the request such that it
800 isci_request, 761 * needs to be detached and freed here.
801 &request_completion, 762 */
802 new_request_state 763 spin_lock_irqsave(&isci_request->state_lock, flags);
803 ); 764 request_status = isci_request_get_state(isci_request);
765
766 if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
767 && ((request_status == aborted)
768 || (request_status == aborting)
769 || (request_status == terminating)
770 || (request_status == completed)
771 || (request_status == dead)
772 )
773 ) {
774
775 /* The completion routine won't free a request in
776 * the aborted/aborting/etc. states, so we do
777 * it here.
778 */
779 needs_cleanup_handling = true;
780 }
781 spin_unlock_irqrestore(&isci_request->state_lock, flags);
804 782
805 if ((old_state == started) || 783 }
806 (old_state == completed) || 784 if (needs_cleanup_handling)
807 (old_state == aborting)) { 785 isci_request_cleanup_completed_loiterer(
808 786 isci_host, isci_device, isci_request, task);
809 /* If the old_state is started:
810 * This request was not already being aborted. If it had been,
811 * then the aborting I/O (ie. the TMF request) would not be in
812 * the aborting state, and thus would be terminated here. Note
813 * that since the TMF completion's call to the kernel function
814 * "complete()" does not happen until the pending I/O request
815 * terminate fully completes, we do not have to implement a
816 * special wait here for already aborting requests - the
817 * termination of the TMF request will force the request
818 * to finish it's already started terminate.
819 *
820 * If old_state == completed:
821 * This request completed from the SCU hardware perspective
822 * and now just needs cleaning up in terms of freeing the
823 * request and potentially calling up to libsas.
824 *
825 * If old_state == aborting:
826 * This request has already gone through a TMF timeout, but may
827 * not have been terminated; needs cleaning up at least.
828 */
829 isci_terminate_request_core(isci_host, isci_device,
830 isci_request);
831 } 787 }
832} 788}
833 789
@@ -850,9 +806,8 @@ void isci_terminate_pending_requests(
850 struct isci_request *request; 806 struct isci_request *request;
851 struct isci_request *next_request; 807 struct isci_request *next_request;
852 unsigned long flags; 808 unsigned long flags;
853 struct list_head aborted_request_list; 809 enum isci_request_status old_state;
854 810 DECLARE_COMPLETION_ONSTACK(request_completion);
855 INIT_LIST_HEAD(&aborted_request_list);
856 811
857 dev_dbg(&isci_host->pdev->dev, 812 dev_dbg(&isci_host->pdev->dev,
858 "%s: isci_device = %p (new request state = %d)\n", 813 "%s: isci_device = %p (new request state = %d)\n",
@@ -860,31 +815,62 @@ void isci_terminate_pending_requests(
860 815
861 spin_lock_irqsave(&isci_host->scic_lock, flags); 816 spin_lock_irqsave(&isci_host->scic_lock, flags);
862 817
863 /* Move all of the pending requests off of the device list. */ 818 /* Iterate through the list. */
864 list_splice_init(&isci_device->reqs_in_process,
865 &aborted_request_list);
866
867 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
868
869 /* Iterate through the now-local list. */
870 list_for_each_entry_safe(request, next_request, 819 list_for_each_entry_safe(request, next_request,
871 &aborted_request_list, dev_node) { 820 &isci_device->reqs_in_process, dev_node) {
872 821
873 dev_warn(&isci_host->pdev->dev, 822 init_completion(&request_completion);
874 "%s: isci_device=%p request=%p; task=%p\n",
875 __func__,
876 isci_device, request,
877 ((request->ttype == io_task)
878 ? isci_request_access_task(request)
879 : NULL));
880 823
881 /* Mark all still pending I/O with the selected next 824 /* Change state to "new_request_state" if it is currently
882 * state, terminate and free it. 825 * "started".
883 */ 826 */
884 isci_terminate_request(isci_host, isci_device, 827 old_state = isci_request_change_started_to_newstate(
885 request, new_request_state 828 request,
886 ); 829 &request_completion,
830 new_request_state);
831
832 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
833
834 if ((old_state == started) ||
835 (old_state == completed) ||
836 (old_state == aborting)) {
837
838 dev_warn(&isci_host->pdev->dev,
839 "%s: isci_device=%p request=%p; task=%p "
840 "old_state=%d\n",
841 __func__,
842 isci_device, request,
843 ((request->ttype == io_task)
844 ? isci_request_access_task(request)
845 : NULL),
846 old_state);
847
848 /* If the old_state is started:
849 * This request was not already being aborted. If it had been,
850 * then the aborting I/O (ie. the TMF request) would not be in
851 * the aborting state, and thus would be terminated here. Note
852 * that since the TMF completion's call to the kernel function
853 * "complete()" does not happen until the pending I/O request
854 * terminate fully completes, we do not have to implement a
855 * special wait here for already aborting requests - the
856 * termination of the TMF request will force the request
857 * to finish it's already started terminate.
858 *
859 * If old_state == completed:
860 * This request completed from the SCU hardware perspective
861 * and now just needs cleaning up in terms of freeing the
862 * request and potentially calling up to libsas.
863 *
864 * If old_state == aborting:
865 * This request has already gone through a TMF timeout, but may
866 * not have been terminated; needs cleaning up at least.
867 */
868 isci_terminate_request_core(isci_host, isci_device,
869 request);
870 }
871 spin_lock_irqsave(&isci_host->scic_lock, flags);
887 } 872 }
873 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
888} 874}
889 875
890/** 876/**
@@ -1257,9 +1243,9 @@ int isci_task_abort_task(struct sas_task *task)
1257 if (ret == TMF_RESP_FUNC_COMPLETE) { 1243 if (ret == TMF_RESP_FUNC_COMPLETE) {
1258 old_request->complete_in_target = true; 1244 old_request->complete_in_target = true;
1259 1245
1260 /* Clean up the request on our side, and wait for the aborted I/O to 1246 /* Clean up the request on our side, and wait for the aborted
1261 * complete. 1247 * I/O to complete.
1262 */ 1248 */
1263 isci_terminate_request_core(isci_host, isci_device, old_request); 1249 isci_terminate_request_core(isci_host, isci_device, old_request);
1264 } 1250 }
1265 1251