.. | .. |
---|
731 | 731 | } |
---|
732 | 732 | |
---|
733 | 733 | /** |
---|
734 | | - * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field |
---|
735 | | - * @hba: per adapter instance |
---|
736 | | - * @tag: position of the bit to be cleared |
---|
737 | | - */ |
---|
738 | | -static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag) |
---|
739 | | -{ |
---|
740 | | - clear_bit(tag, &hba->outstanding_reqs); |
---|
741 | | -} |
---|
742 | | - |
---|
743 | | -/** |
---|
744 | 734 | * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY |
---|
745 | 735 | * @reg: Register value of host controller status |
---|
746 | 736 | * |
---|
.. | .. |
---|
2882 | 2872 | static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, |
---|
2883 | 2873 | struct ufshcd_lrb *lrbp, int max_timeout) |
---|
2884 | 2874 | { |
---|
2885 | | - int err = 0; |
---|
2886 | | - unsigned long time_left; |
---|
| 2875 | + unsigned long time_left = msecs_to_jiffies(max_timeout); |
---|
2887 | 2876 | unsigned long flags; |
---|
| 2877 | + bool pending; |
---|
| 2878 | + int err; |
---|
2888 | 2879 | |
---|
| 2880 | +retry: |
---|
2889 | 2881 | time_left = wait_for_completion_timeout(hba->dev_cmd.complete, |
---|
2890 | | - msecs_to_jiffies(max_timeout)); |
---|
| 2882 | + time_left); |
---|
2891 | 2883 | |
---|
2892 | 2884 | /* Make sure descriptors are ready before ringing the doorbell */ |
---|
2893 | 2885 | wmb(); |
---|
2894 | | - spin_lock_irqsave(hba->host->host_lock, flags); |
---|
2895 | | - hba->dev_cmd.complete = NULL; |
---|
2896 | 2886 | if (likely(time_left)) { |
---|
| 2887 | + /* |
---|
| 2888 | + * The completion handler called complete() and the caller of |
---|
| 2889 | + * this function still owns the @lrbp tag so the code below does |
---|
| 2890 | + * not trigger any race conditions. |
---|
| 2891 | + */ |
---|
| 2892 | + hba->dev_cmd.complete = NULL; |
---|
2897 | 2893 | err = ufshcd_get_tr_ocs(lrbp); |
---|
2898 | 2894 | if (!err) |
---|
2899 | 2895 | err = ufshcd_dev_cmd_completion(hba, lrbp); |
---|
2900 | | - } |
---|
2901 | | - spin_unlock_irqrestore(hba->host->host_lock, flags); |
---|
2902 | | - |
---|
2903 | | - if (!time_left) { |
---|
| 2896 | + } else { |
---|
2904 | 2897 | err = -ETIMEDOUT; |
---|
2905 | 2898 | dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n", |
---|
2906 | 2899 | __func__, lrbp->task_tag); |
---|
2907 | | - if (!ufshcd_clear_cmd(hba, lrbp->task_tag)) |
---|
| 2900 | + if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) { |
---|
2908 | 2901 | /* successfully cleared the command, retry if needed */ |
---|
2909 | 2902 | err = -EAGAIN; |
---|
2910 | | - /* |
---|
2911 | | - * in case of an error, after clearing the doorbell, |
---|
2912 | | - * we also need to clear the outstanding_request |
---|
2913 | | - * field in hba |
---|
2914 | | - */ |
---|
2915 | | - ufshcd_outstanding_req_clear(hba, lrbp->task_tag); |
---|
| 2903 | + /* |
---|
| 2904 | + * Since clearing the command succeeded we also need to |
---|
| 2905 | + * clear the task tag bit from the outstanding_reqs |
---|
| 2906 | + * variable. |
---|
| 2907 | + */ |
---|
| 2908 | + spin_lock_irqsave(hba->host->host_lock, flags); |
---|
| 2909 | + pending = test_bit(lrbp->task_tag, |
---|
| 2910 | + &hba->outstanding_reqs); |
---|
| 2911 | + if (pending) { |
---|
| 2912 | + hba->dev_cmd.complete = NULL; |
---|
| 2913 | + __clear_bit(lrbp->task_tag, |
---|
| 2914 | + &hba->outstanding_reqs); |
---|
| 2915 | + } |
---|
| 2916 | + spin_unlock_irqrestore(hba->host->host_lock, flags); |
---|
| 2917 | + |
---|
| 2918 | + if (!pending) { |
---|
| 2919 | + /* |
---|
| 2920 | + * The completion handler ran while we tried to |
---|
| 2921 | + * clear the command. |
---|
| 2922 | + */ |
---|
| 2923 | + time_left = 1; |
---|
| 2924 | + goto retry; |
---|
| 2925 | + } |
---|
| 2926 | + } else { |
---|
| 2927 | + dev_err(hba->dev, "%s: failed to clear tag %d\n", |
---|
| 2928 | + __func__, lrbp->task_tag); |
---|
| 2929 | + spin_lock_irqsave(hba->host->host_lock, flags); |
---|
| 2930 | + pending = test_bit(lrbp->task_tag, |
---|
| 2931 | + &hba->outstanding_reqs); |
---|
| 2932 | + if (pending) |
---|
| 2933 | + hba->dev_cmd.complete = NULL; |
---|
| 2934 | + spin_unlock_irqrestore(hba->host->host_lock, flags); |
---|
| 2935 | + |
---|
| 2936 | + if (!pending) { |
---|
| 2937 | + /* |
---|
| 2938 | + * The completion handler ran while we tried to |
---|
| 2939 | + * clear the command. |
---|
| 2940 | + */ |
---|
| 2941 | + time_left = 1; |
---|
| 2942 | + goto retry; |
---|
| 2943 | + } |
---|
| 2944 | + } |
---|
2916 | 2945 | } |
---|
2917 | 2946 | |
---|
2918 | 2947 | return err; |
---|
.. | .. |
---|
9485 | 9514 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); |
---|
9486 | 9515 | MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); |
---|
9487 | 9516 | MODULE_DESCRIPTION("Generic UFS host controller driver Core"); |
---|
| 9517 | +MODULE_SOFTDEP("pre: governor_simpleondemand"); |
---|
9488 | 9518 | MODULE_LICENSE("GPL"); |
---|
9489 | 9519 | MODULE_VERSION(UFSHCD_DRIVER_VERSION); |
---|