aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/task.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-03-04 17:06:52 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:30 -0400
commit4dc043c41037fc6e369270daaa626465a8766565 (patch)
tree9021ca328112a5a171da0392df43c05a2d63fa52 /drivers/scsi/isci/task.c
parentcbb65c665b341e560b7a3b37cc616376031b3ee5 (diff)
isci: Termination handling cleanup, added termination timeouts.
Added a request "dead" state for use when a termination wait times-out. isci_terminate_pending_requests now detaches the device's pending list and terminates each entry on the detached list. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r--drivers/scsi/isci/task.c233
1 files changed, 141 insertions, 92 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 5e80e8449223..c781a4ab4a50 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -663,6 +663,59 @@ static void isci_request_cleanup_completed_loiterer(
663 } 663 }
664 isci_request_free(isci_host, isci_request); 664 isci_request_free(isci_host, isci_request);
665} 665}
666
667/**
668* @isci_termination_timed_out(): this function will deal with a request for
669* which the wait for termination has timed-out.
670*
671* @isci_host This SCU.
672* @isci_request The I/O request being terminated.
673*/
674static void
675isci_termination_timed_out(
676 struct isci_host * host,
677 struct isci_request * request
678 )
679{
680 unsigned long state_flags;
681
682 dev_warn(&host->pdev->dev,
683 "%s: host = %p; request = %p\n",
684 __func__, host, request);
685
686 /* At this point, the request to terminate
687 * has timed out. The best we can do is to
688 * have the request die a silent death
689 * if it ever completes.
690 */
691 spin_lock_irqsave(&request->state_lock, state_flags);
692
693 if (request->status == started) {
694
695 /* Set the request state to "dead",
696 * and clear the task pointer so that an actual
697 * completion event callback doesn't do
698 * anything.
699 */
700 request->status = dead;
701
702 /* Clear the timeout completion event pointer.*/
703 request->io_request_completion = NULL;
704
705 if (request->ttype == io_task) {
706
707 /* Break links with the sas_task. */
708 if (request->ttype_ptr.io_task_ptr != NULL) {
709
710 request->ttype_ptr.io_task_ptr->lldd_task = NULL;
711 request->ttype_ptr.io_task_ptr = NULL;
712 }
713 }
714 }
715 spin_unlock_irqrestore(&request->state_lock, state_flags);
716}
717
718
666/** 719/**
667 * isci_terminate_request_core() - This function will terminate the given 720 * isci_terminate_request_core() - This function will terminate the given
668 * request, and wait for it to complete. This function must only be called 721 * request, and wait for it to complete. This function must only be called
@@ -684,35 +737,20 @@ static void isci_terminate_request_core(
684 bool needs_cleanup_handling = false; 737 bool needs_cleanup_handling = false;
685 enum isci_request_status request_status; 738 enum isci_request_status request_status;
686 unsigned long flags; 739 unsigned long flags;
740 unsigned long timeout_remaining;
741
687 742
688 dev_dbg(&isci_host->pdev->dev, 743 dev_dbg(&isci_host->pdev->dev,
689 "%s: device = %p; request = %p\n", 744 "%s: device = %p; request = %p\n",
690 __func__, isci_device, isci_request); 745 __func__, isci_device, isci_request);
691 746
692 /* Peek at the current status of the request. This will tell 747 spin_lock_irqsave(&isci_host->scic_lock, flags);
693 * us if there was special handling on the request such that it
694 * needs to be detached and freed here.
695 */
696 spin_lock_irqsave(&isci_request->state_lock, flags);
697 request_status = isci_request_get_state(isci_request);
698
699 if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
700 && ((request_status == aborted)
701 || (request_status == aborting)
702 || (request_status == terminating)
703 || (request_status == completed)
704 )
705 ) {
706 748
707 /* The completion routine won't free a request in 749 /* Note that we are not going to control
708 * the aborted/aborting/terminating state, so we do 750 * the target to abort the request.
709 * it here. 751 */
710 */ 752 isci_request->complete_in_target = true;
711 needs_cleanup_handling = true;
712 }
713 spin_unlock_irqrestore(&isci_request->state_lock, flags);
714 753
715 spin_lock_irqsave(&isci_host->scic_lock, flags);
716 /* Make sure the request wasn't just sitting around signalling 754 /* Make sure the request wasn't just sitting around signalling
717 * device condition (if the request handle is NULL, then the 755 * device condition (if the request handle is NULL, then the
718 * request completed but needed additional handling here). 756 * request completed but needed additional handling here).
@@ -733,13 +771,16 @@ static void isci_terminate_request_core(
733 * fail is when the io request is completed and 771 * fail is when the io request is completed and
734 * being aborted. 772 * being aborted.
735 */ 773 */
736 if (status != SCI_SUCCESS) 774 if (status != SCI_SUCCESS) {
737 dev_err(&isci_host->pdev->dev, 775 dev_err(&isci_host->pdev->dev,
738 "%s: scic_controller_terminate_request" 776 "%s: scic_controller_terminate_request"
739 " returned = 0x%x\n", 777 " returned = 0x%x\n",
740 __func__, 778 __func__,
741 status); 779 status);
742 else { 780 /* Clear the completion pointer from the request. */
781 isci_request->io_request_completion = NULL;
782
783 } else {
743 if (was_terminated) { 784 if (was_terminated) {
744 dev_dbg(&isci_host->pdev->dev, 785 dev_dbg(&isci_host->pdev->dev,
745 "%s: before completion wait (%p)\n", 786 "%s: before completion wait (%p)\n",
@@ -747,21 +788,62 @@ static void isci_terminate_request_core(
747 isci_request->io_request_completion); 788 isci_request->io_request_completion);
748 789
749 /* Wait here for the request to complete. */ 790 /* Wait here for the request to complete. */
750 wait_for_completion(isci_request->io_request_completion); 791 #define TERMINATION_TIMEOUT_MSEC 50
792 timeout_remaining
793 = wait_for_completion_timeout(
794 isci_request->io_request_completion,
795 msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
796
797 if (!timeout_remaining) {
798
799 isci_termination_timed_out(isci_host,
800 isci_request);
801
802 dev_err(&isci_host->pdev->dev,
803 "%s: *** Timeout waiting for "
804 "termination(%p/%p)\n",
805 __func__,
806 isci_request->io_request_completion,
807 isci_request);
808
809 } else
810 dev_dbg(&isci_host->pdev->dev,
811 "%s: after completion wait (%p)\n",
812 __func__,
813 isci_request->io_request_completion);
814 }
815 /* Clear the completion pointer from the request. */
816 isci_request->io_request_completion = NULL;
751 817
752 dev_dbg(&isci_host->pdev->dev, 818 /* Peek at the status of the request. This will tell
753 "%s: after completion wait (%p)\n", 819 * us if there was special handling on the request such that it
754 __func__, 820 * needs to be detached and freed here.
755 isci_request->io_request_completion); 821 */
822 spin_lock_irqsave(&isci_request->state_lock, flags);
823 request_status = isci_request_get_state(isci_request);
824
825 if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
826 && ((request_status == aborted)
827 || (request_status == aborting)
828 || (request_status == terminating)
829 || (request_status == completed)
830 || (request_status == dead)
831 )
832 ) {
833
834 /* The completion routine won't free a request in
835 * the aborted/aborting/etc. states, so we do
836 * it here.
837 */
838 needs_cleanup_handling = true;
756 } 839 }
840 spin_unlock_irqrestore(&isci_request->state_lock, flags);
757 841
758 if (needs_cleanup_handling) 842 if (needs_cleanup_handling)
759 isci_request_cleanup_completed_loiterer( 843 isci_request_cleanup_completed_loiterer(
760 isci_host, isci_device, isci_request 844 isci_host, isci_device, isci_request
761 ); 845 );
762 } 846 }
763 /* Clear the completion pointer from the request. */
764 isci_request->io_request_completion = NULL;
765} 847}
766 848
767static void isci_terminate_request( 849static void isci_terminate_request(
@@ -771,11 +853,7 @@ static void isci_terminate_request(
771 enum isci_request_status new_request_state) 853 enum isci_request_status new_request_state)
772{ 854{
773 enum isci_request_status old_state; 855 enum isci_request_status old_state;
774
775 DECLARE_COMPLETION_ONSTACK(request_completion); 856 DECLARE_COMPLETION_ONSTACK(request_completion);
776 unsigned long flags;
777
778 spin_lock_irqsave(&isci_host->scic_lock, flags);
779 857
780 /* Change state to "new_request_state" if it is currently "started" */ 858 /* Change state to "new_request_state" if it is currently "started" */
781 old_state = isci_request_change_started_to_newstate( 859 old_state = isci_request_change_started_to_newstate(
@@ -823,73 +901,44 @@ void isci_terminate_pending_requests(
823 struct isci_remote_device *isci_device, 901 struct isci_remote_device *isci_device,
824 enum isci_request_status new_request_state) 902 enum isci_request_status new_request_state)
825{ 903{
826 struct isci_request *isci_request; 904 struct isci_request *request;
827 struct sas_task *task; 905 struct isci_request *next_request;
828 bool done = false; 906 unsigned long flags;
829 unsigned long flags; 907 struct list_head aborted_request_list;
908
909 INIT_LIST_HEAD(&aborted_request_list);
830 910
831 dev_dbg(&isci_host->pdev->dev, 911 dev_dbg(&isci_host->pdev->dev,
832 "%s: isci_device = %p (new request state = %d)\n", 912 "%s: isci_device = %p (new request state = %d)\n",
833 __func__, isci_device, new_request_state); 913 __func__, isci_device, new_request_state);
834 914
835 #define ISCI_TERMINATE_SHOW_PENDING_REQUESTS 915 spin_lock_irqsave(&isci_host->scic_lock, flags);
836 #ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS
837 {
838 struct isci_request *request;
839
840 /* Only abort the task if it's in the
841 * device's request_in_process list
842 */
843 list_for_each_entry(request,
844 &isci_device->reqs_in_process,
845 dev_node)
846 dev_dbg(&isci_host->pdev->dev,
847 "%s: isci_device = %p; request is on "
848 "reqs_in_process list: %p\n",
849 __func__, isci_device, request);
850 }
851 #endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */
852
853 /* Clean up all pending requests. */
854 do {
855 spin_lock_irqsave(&isci_host->scic_lock, flags);
856
857 if (list_empty(&isci_device->reqs_in_process)) {
858
859 done = true;
860 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
861 916
862 dev_dbg(&isci_host->pdev->dev, 917 /* Move all of the pending requests off of the device list. */
863 "%s: isci_device = %p; done.\n", 918 list_splice_init(&isci_device->reqs_in_process,
864 __func__, isci_device); 919 &aborted_request_list);
865 } else {
866 /* The list was not empty - grab the first request. */
867 isci_request = list_first_entry(
868 &isci_device->reqs_in_process,
869 struct isci_request, dev_node
870 );
871 /* Note that we are not expecting to have to control
872 * the target to abort the request.
873 */
874 isci_request->complete_in_target = true;
875 920
876 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 921 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
877 922
878 /* Get the libsas task reference. */ 923 /* Iterate through the now-local list. */
879 task = isci_request_access_task(isci_request); 924 list_for_each_entry_safe(request, next_request,
925 &aborted_request_list, dev_node) {
880 926
881 dev_dbg(&isci_host->pdev->dev, 927 dev_warn(&isci_host->pdev->dev,
882 "%s: isci_device=%p request=%p; task=%p\n", 928 "%s: isci_device=%p request=%p; task=%p\n",
883 __func__, isci_device, isci_request, task); 929 __func__,
930 isci_device, request,
931 ((request->ttype == io_task)
932 ? isci_request_access_task(request)
933 : NULL));
884 934
885 /* Mark all still pending I/O with the selected next 935 /* Mark all still pending I/O with the selected next
886 * state. 936 * state, terminate and free it.
887 */ 937 */
888 isci_terminate_request(isci_host, isci_device, 938 isci_terminate_request(isci_host, isci_device,
889 isci_request, new_request_state 939 request, new_request_state
890 ); 940 );
891 } 941 }
892 } while (!done);
893} 942}
894 943
895/** 944/**