From patchwork Thu Jun 10 04:43:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311771 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45480C48BCD for ; Thu, 10 Jun 2021 04:43:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2C13D613B0 for ; Thu, 10 Jun 2021 04:43:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229715AbhFJEpy (ORCPT ); Thu, 10 Jun 2021 00:45:54 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:3851 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229529AbhFJEpx (ORCPT ); Thu, 10 Jun 2021 00:45:53 -0400 IronPort-SDR: a8F67ltK/+XEWU8BKVKFKJis06rS3DDtqYPL92K8ldd3tqzntH2OvibG67HsmDiNQRKUF75Sw+ /kXykNyUu8QwOb5sjVbaax/lsfNCwFtfXkUyceR5bJ3e4HeAOYKO7RlfY9epBO8y561VTv5otI Nk23w9OwpH0NSEsSZC3qU6tZEeKo6KCXbRTfVRr5K7mRZSxhITsHI6dD+meFAQdyPJ4U99n04U tF11a7kKeFAl2k6CtA1iGMBaIk2dp1I4Wy2iaiEjh7yG2Iy94xjiozaK6K4kqQ0fDD6k08ZZMO Rxs= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778426" Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:43:58 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg03-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:43:56 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id DFDFB21AF7; Wed, 9 Jun 2021 21:43:56 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , Adrian Hunter , Kiwoong Kim , Satya Tangirala , Bart Van Assche , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 1/9] scsi: ufs: Differentiate status between hba pm ops and wl pm ops Date: Wed, 9 Jun 2021 21:43:29 -0700 Message-Id: <1623300218-9454-2-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Put pm_op_in_progress and is_sys_suspend flags back to ufshcd hba pm ops, add two new flags, namely wl_pm_op_in_progress and is_wl_sys_suspended, to track the UFS device W-LU pm ops. This helps us differentiate the status of hba and wl pm ops when we need to do troubleshooting. Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 42 ++++++++++++++++++++++++++++-------------- drivers/scsi/ufs/ufshcd.h | 4 +++- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 25fe18a..47b2a9a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -549,7 +549,9 @@ static void ufshcd_print_host_state(struct ufs_hba *hba) hba->saved_err, hba->saved_uic_err); dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n", hba->curr_dev_pwr_mode, hba->uic_link_state); - dev_err(hba->dev, "PM in progress=%d, sys. suspended=%d\n", + dev_err(hba->dev, "wl_pm_op_in_progress=%d, is_wl_sys_suspended=%d\n", + hba->wl_pm_op_in_progress, hba->is_wl_sys_suspended); + dev_err(hba->dev, "pm_op_in_progress=%d, is_sys_suspended=%d\n", hba->pm_op_in_progress, hba->is_sys_suspended); dev_err(hba->dev, "Auto BKOPS=%d, Host self-block=%d\n", hba->auto_bkops_enabled, hba->host->host_self_blocked); @@ -1999,7 +2001,7 @@ static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba) if (!hba->clk_scaling.active_reqs++) queue_resume_work = true; - if (!hba->clk_scaling.is_enabled || hba->pm_op_in_progress) { + if (!hba->clk_scaling.is_enabled || hba->wl_pm_op_in_progress) { spin_unlock_irqrestore(hba->host->host_lock, flags); return; } @@ -2734,7 +2736,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) * err handler blocked for too long. So, just fail the scsi cmd * sent from PM ops, err handler can recover PM error anyways. */ - if (hba->pm_op_in_progress) { + if (hba->wl_pm_op_in_progress) { hba->force_reset = true; set_host_byte(cmd, DID_BAD_TARGET); cmd->scsi_done(cmd); @@ -2767,7 +2769,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) (hba->clk_gating.state != CLKS_ON)); if (unlikely(test_bit(tag, &hba->outstanding_reqs))) { - if (hba->pm_op_in_progress) + if (hba->wl_pm_op_in_progress) set_host_byte(cmd, DID_BAD_TARGET); else err = SCSI_MLQUEUE_HOST_BUSY; @@ -5116,7 +5118,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) * solution could be to abort the system suspend if * UFS device needs urgent BKOPs. */ - if (!hba->pm_op_in_progress && + if (!hba->wl_pm_op_in_progress && !ufshcd_eh_in_progress(hba) && ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) /* Flushed in suspend */ @@ -5916,7 +5918,7 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) { ufshcd_rpm_get_sync(hba); if (pm_runtime_status_suspended(&hba->sdev_ufs_device->sdev_gendev) || - hba->is_sys_suspended) { + hba->is_wl_sys_suspended) { enum ufs_pm_op pm_op; /* @@ -5933,7 +5935,7 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) if (!ufshcd_is_clkgating_allowed(hba)) ufshcd_setup_clocks(hba, true); ufshcd_release(hba); - pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; + pm_op = hba->is_wl_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; ufshcd_vops_resume(hba, pm_op); } else { ufshcd_hold(hba, false); @@ -5976,7 +5978,7 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba) struct request_queue *q; int ret; - hba->is_sys_suspended = false; + hba->is_wl_sys_suspended = false; /* * Set RPM status of wlun device to RPM_ACTIVE, * this also clears its runtime error. @@ -8784,7 +8786,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) enum ufs_dev_pwr_mode req_dev_pwr_mode; enum uic_link_state req_link_state; - hba->pm_op_in_progress = true; + hba->wl_pm_op_in_progress = true; if (pm_op != UFS_SHUTDOWN_PM) { pm_lvl = pm_op == UFS_RUNTIME_PM ? hba->rpm_lvl : hba->spm_lvl; @@ -8919,7 +8921,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) hba->clk_gating.is_suspended = false; ufshcd_release(hba); } - hba->pm_op_in_progress = false; + hba->wl_pm_op_in_progress = false; return ret; } @@ -8928,7 +8930,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) int ret; enum uic_link_state old_link_state = hba->uic_link_state; - hba->pm_op_in_progress = true; + hba->wl_pm_op_in_progress = true; /* * Call vendor specific resume callback. As these callbacks may access @@ -9006,7 +9008,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_update_evt_hist(hba, UFS_EVT_WL_RES_ERR, (u32)ret); hba->clk_gating.is_suspended = false; ufshcd_release(hba); - hba->pm_op_in_progress = false; + hba->wl_pm_op_in_progress = false; return ret; } @@ -9072,7 +9074,7 @@ static int ufshcd_wl_suspend(struct device *dev) out: if (!ret) - hba->is_sys_suspended = true; + hba->is_wl_sys_suspended = true; trace_ufshcd_wl_suspend(dev_name(dev), ret, ktime_to_us(ktime_sub(ktime_get(), start)), hba->curr_dev_pwr_mode, hba->uic_link_state); @@ -9100,7 +9102,7 @@ static int ufshcd_wl_resume(struct device *dev) ktime_to_us(ktime_sub(ktime_get(), start)), hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) - hba->is_sys_suspended = false; + hba->is_wl_sys_suspended = false; up(&hba->host_sem); return ret; } @@ -9141,6 +9143,8 @@ static int ufshcd_suspend(struct ufs_hba *hba) if (!hba->is_powered) return 0; + + hba->pm_op_in_progress = true; /* * Disable the host irq as host controller as there won't be any * host controller transaction expected till resume. @@ -9160,6 +9164,7 @@ static int ufshcd_suspend(struct ufs_hba *hba) ufshcd_vreg_set_lpm(hba); /* Put the host controller in low power mode if possible */ ufshcd_hba_vreg_set_lpm(hba); + hba->pm_op_in_progress = false; return ret; } @@ -9179,6 +9184,7 @@ static int ufshcd_resume(struct ufs_hba *hba) if (!hba->is_powered) return 0; + hba->pm_op_in_progress = true; ufshcd_hba_vreg_set_hpm(hba); ret = ufshcd_vreg_set_hpm(hba); if (ret) @@ -9198,6 +9204,7 @@ static int ufshcd_resume(struct ufs_hba *hba) out: if (ret) ufshcd_update_evt_hist(hba, UFS_EVT_RESUME_ERR, (u32)ret); + hba->pm_op_in_progress = false; return ret; } @@ -9222,6 +9229,10 @@ int ufshcd_system_suspend(struct ufs_hba *hba) trace_ufshcd_system_suspend(dev_name(hba->dev), ret, ktime_to_us(ktime_sub(ktime_get(), start)), hba->curr_dev_pwr_mode, hba->uic_link_state); + + if (!ret) + hba->is_sys_suspended = true; + return ret; } EXPORT_SYMBOL(ufshcd_system_suspend); @@ -9248,6 +9259,9 @@ int ufshcd_system_resume(struct ufs_hba *hba) ktime_to_us(ktime_sub(ktime_get(), start)), hba->curr_dev_pwr_mode, hba->uic_link_state); + if (!ret) + hba->is_sys_suspended = false; + return ret; } EXPORT_SYMBOL(ufshcd_system_resume); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index c98d540..eaebb4e 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -752,7 +752,8 @@ struct ufs_hba { enum ufs_pm_level spm_lvl; struct device_attribute rpm_lvl_attr; struct device_attribute spm_lvl_attr; - int pm_op_in_progress; + bool pm_op_in_progress; + bool wl_pm_op_in_progress; /* Auto-Hibernate Idle Timer register value */ u32 ahit; @@ -839,6 +840,7 @@ struct ufs_hba { struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; bool is_sys_suspended; + bool is_wl_sys_suspended; enum bkops_status urgent_bkops_lvl; bool is_urgent_bkops_lvl_checked; From patchwork Thu Jun 10 04:43:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311773 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BDE92C47094 for ; Thu, 10 Jun 2021 04:44:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9E542613B0 for ; Thu, 10 Jun 2021 04:44:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229802AbhFJEp5 (ORCPT ); Thu, 10 Jun 2021 00:45:57 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:5883 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229529AbhFJEp5 (ORCPT ); Thu, 10 Jun 2021 00:45:57 -0400 IronPort-SDR: Idqlk13gntzoO5ooMG8XCdA4OhhW0Oozbyfyg1ffQaNy5U+ASmeAtZ4B9vbh6LXdvHymyvOf3e EmPGdFsQ64+e0XZ9amUV4dWDKforkWMcvYgClPsHQVIdvPFTFifyHzgPFgobsLnfcs9zLuD5jU SH6fTEH3kT79YrbGHCSFqpD2dKdpQdIFUOzKR+04jlSmytCT0ZEqpfFC/PrmT45m3Xr4IZIRee Sh1AA0ibDwhL3pA1LKGyg8ARwLOsicDyaL1S17eWSpgchRtmsSSKqEb/MuBhmWhi7yOXGQiIjP TQE= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="47893346" Received: from unknown (HELO ironmsg05-sd.qualcomm.com) ([10.53.140.145]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:01 -0700 X-QCInternal: smtphost Received: from stor-presley.qualcomm.com ([192.168.140.85]) by ironmsg05-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:44:00 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id 1206E21AF7; Wed, 9 Jun 2021 21:44:01 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 2/9] scsi: ufs: Update the return value of supplier pm ops Date: Wed, 9 Jun 2021 21:43:30 -0700 Message-Id: <1623300218-9454-3-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org rpm_get_suppliers() is returning an error only if the error is negative. However, ufshcd_wl_resume() may return a positive error code, e.g., when hibern8 or SSU cmd fails. Make the positive return value a negative error code so that consumers are aware of any resume failure from their supplier. Make the same change to ufshcd_wl_suspend() just to keep symmetry. Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 47b2a9a..fed893e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8922,7 +8922,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_release(hba); } hba->wl_pm_op_in_progress = false; - return ret; + return ret <= 0 ? ret : -EINVAL; } static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) @@ -9009,7 +9009,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) hba->clk_gating.is_suspended = false; ufshcd_release(hba); hba->wl_pm_op_in_progress = false; - return ret; + return ret <= 0 ? ret : -EINVAL; } static int ufshcd_wl_runtime_suspend(struct device *dev) From patchwork Thu Jun 10 04:43:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311775 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C56C0C48BD1 for ; Thu, 10 Jun 2021 04:44:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A49D4613B0 for ; Thu, 10 Jun 2021 04:44:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229931AbhFJEqC (ORCPT ); Thu, 10 Jun 2021 00:46:02 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10993 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229925AbhFJEqC (ORCPT ); Thu, 10 Jun 2021 00:46:02 -0400 IronPort-SDR: 3sXAk0k9MJzrximd/juvH4shb43TTKhtGhw6v/732Q9Wvpt15eokixBnhu3t7i2BADKeir8uxf Apy7U51A5JVFyXFjT1Raois/9Ppk3V/SNi8foLXM27zPFSAAjcBOYSRJdGhSH2IvIsEdMUO0ef UwWtfanQmJSexEq6GXIBsrRcLNk75XbUvzzJ8zx0yq4bIv9luYxI3pZHxyeUmi3IgmC5zC+8DZ ucyOJcyzyyg6Q3QAa7jmNSGGSYyMC5hBp7/GoN1GfTDwn5nxQkZDR7E7JaBZxYLgOgDe3jBtLe fSg= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778427" Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:07 -0700 X-QCInternal: smtphost Received: from stor-presley.qualcomm.com ([192.168.140.85]) by ironmsg04-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:44:05 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id BE4E221AF7; Wed, 9 Jun 2021 21:44:05 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 3/9] scsi: ufs: Enable IRQ after enabling clocks in error handling preparation Date: Wed, 9 Jun 2021 21:43:31 -0700 Message-Id: <1623300218-9454-4-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org In error handling preparation, enable IRQ after enabling clocks in case unclocked register access happens. Fixes: c72e79c0ad2bd ("scsi: ufs: Recover HBA runtime PM error in error handler") Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index fed893e..0c9d2ee 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5927,13 +5927,14 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) * can be OFF or in LPM. */ ufshcd_setup_hba_vreg(hba, true); - ufshcd_enable_irq(hba); ufshcd_setup_vreg(hba, true); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); ufshcd_hold(hba, false); - if (!ufshcd_is_clkgating_allowed(hba)) + if (!ufshcd_is_clkgating_allowed(hba)) { ufshcd_setup_clocks(hba, true); + ufshcd_enable_irq(hba); + } ufshcd_release(hba); pm_op = hba->is_wl_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; ufshcd_vops_resume(hba, pm_op); From patchwork Thu Jun 10 04:43:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311777 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE8D5C48BD1 for ; Thu, 10 Jun 2021 04:44:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C2E32613F1 for ; Thu, 10 Jun 2021 04:44:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229980AbhFJEqH (ORCPT ); Thu, 10 Jun 2021 00:46:07 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10993 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229925AbhFJEqG (ORCPT ); Thu, 10 Jun 2021 00:46:06 -0400 IronPort-SDR: SoTOmHTj6kU1T0V3WelelP7bxzpFyL9/ldznSggmwmxqB2qGp1RfQOxDd1sw0lMgV6b6j0PK7e +kYc/0/DRQNycoECyUHPLeiLfaOYS2wNxygyQqjRhEF82LXPUWeVEhgPUDRSTxb27Ved2wzSXo bMsFzCtE033Zv4f8xSOq9ctmgRMSB8B4riKPTciyYxDq6xQAyUgKiPlNlhbPLKQGxGWeBSzfg3 DZJ8NjO4k0Ss4ohOKnVvRG+bPEJLHbghKThImJUaK9y04D8/VR9n7hBdJmShj+51P5NxTKKaIx Sv8= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778428" Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:11 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg-SD-alpha.qualcomm.com with ESMTP; 09 Jun 2021 21:44:10 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id 9637A21AF7; Wed, 9 Jun 2021 21:44:10 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 4/9] scsi: ufs: Complete the cmd before returning in queuecommand Date: Wed, 9 Jun 2021 21:43:32 -0700 Message-Id: <1623300218-9454-5-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Commit 7a7e66c65d4148fc3f23b058405bc9f102414fcb ("scsi: ufs: Fix a race condition between ufshcd_abort() and eh_work()") forgot to complete the cmd, which takes an occupied lrb, before returning in queuecommand. This change adds the missing codes. Fixes: 7a7e66c65d414 ("scsi: ufs: Fix a race condition between ufshcd_abort() and eh_work()") Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0c9d2ee..7dc0fda 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2758,6 +2758,16 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) goto out; } + if (unlikely(test_bit(tag, &hba->outstanding_reqs))) { + if (hba->wl_pm_op_in_progress) { + set_host_byte(cmd, DID_BAD_TARGET); + cmd->scsi_done(cmd); + } else { + err = SCSI_MLQUEUE_HOST_BUSY; + } + goto out; + } + hba->req_abort_count = 0; err = ufshcd_hold(hba, true); @@ -2768,15 +2778,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) WARN_ON(ufshcd_is_clkgating_allowed(hba) && (hba->clk_gating.state != CLKS_ON)); - if (unlikely(test_bit(tag, &hba->outstanding_reqs))) { - if (hba->wl_pm_op_in_progress) - set_host_byte(cmd, DID_BAD_TARGET); - else - err = SCSI_MLQUEUE_HOST_BUSY; - ufshcd_release(hba); - goto out; - } - lrbp = &hba->lrb[tag]; WARN_ON(lrbp->cmd); lrbp->cmd = cmd; From patchwork Thu Jun 10 04:43:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311779 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 284FDC48BD1 for ; Thu, 10 Jun 2021 04:44:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F29646141D for ; Thu, 10 Jun 2021 04:44:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230040AbhFJEqL (ORCPT ); Thu, 10 Jun 2021 00:46:11 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10993 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230028AbhFJEqK (ORCPT ); Thu, 10 Jun 2021 00:46:10 -0400 IronPort-SDR: k6MMqJoy2xjYYyGqs+Y3Vr0q5+HNFlJSHhYN8Z3Ek9ba+FVK0h+zIadBYoWgjmVRH8rac9rM14 +zB6KPX+Vej3b8rHqPk/cRo1k25WE9ISeyaN3T1X9TYBe/qlLBpW2Tru2L+09DNvUJFQjXJkbs H6ibR0cR3T5lKLE++wrjF4RNR6aWWTIAKWaoaKbe9Kgp2hzp+075Plx3Q7eYWDa1PkzI2mBCZC tETay8EUrPIuF0y2xH/LT31diLC1FFtYh/5qKIMS3ThazjLTq705ji6xGNZjSHsJm5xk1RcaHx 2zA= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778429" Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:15 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg03-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:44:14 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id A65A221AF7; Wed, 9 Jun 2021 21:44:14 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 5/9] scsi: ufs: Simplify error handling preparation Date: Wed, 9 Jun 2021 21:43:33 -0700 Message-Id: <1623300218-9454-6-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Commit cb7e6f05fce67c965194ac04467e1ba7bc70b069 ("scsi: ufs: core: Enable power management for wlun") moves UFS operations out of ufshcd_resume(), so in error handling preparation, if ufshcd hba has failed to resume, there is no point to re-enable IRQ/clk/pwr. Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 7dc0fda..0afad6b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2727,8 +2727,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) break; case UFSHCD_STATE_EH_SCHEDULED_FATAL: /* - * pm_runtime_get_sync() is used at error handling preparation - * stage. If a scsi cmd, e.g. the SSU cmd, is sent from hba's + * ufshcd_rpm_get_sync() is used at error handling preparation + * stage. If a scsi cmd, e.g., the SSU cmd, is sent from the * PM ops, it can never be finished if we let SCSI layer keep * retrying it, which gets err handler stuck forever. Neither * can we let the scsi cmd pass through, because UFS is in bad @@ -5915,29 +5915,26 @@ static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend) } } -static void ufshcd_err_handling_prepare(struct ufs_hba *hba) +static int ufshcd_err_handling_prepare(struct ufs_hba *hba) { + /* + * Exclusively call pm_runtime_get_sync(hba->dev) once, in case + * following ufshcd_rpm_get_sync() fails. + */ + pm_runtime_get_sync(hba->dev); + /* End of the world. */ + if (pm_runtime_suspended(hba->dev)) { + pm_runtime_put(hba->dev); + return -EINVAL; + } + + ufshcd_set_eh_in_progress(hba); ufshcd_rpm_get_sync(hba); - if (pm_runtime_status_suspended(&hba->sdev_ufs_device->sdev_gendev) || + if (pm_runtime_suspended(&hba->sdev_ufs_device->sdev_gendev) || hba->is_wl_sys_suspended) { - enum ufs_pm_op pm_op; + enum ufs_pm_op pm_op = hba->is_wl_sys_suspended ? + UFS_SYSTEM_PM : UFS_RUNTIME_PM; - /* - * Don't assume anything of resume, if - * resume fails, irq and clocks can be OFF, and powers - * can be OFF or in LPM. - */ - ufshcd_setup_hba_vreg(hba, true); - ufshcd_setup_vreg(hba, true); - ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); - ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); - ufshcd_hold(hba, false); - if (!ufshcd_is_clkgating_allowed(hba)) { - ufshcd_setup_clocks(hba, true); - ufshcd_enable_irq(hba); - } - ufshcd_release(hba); - pm_op = hba->is_wl_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; ufshcd_vops_resume(hba, pm_op); } else { ufshcd_hold(hba, false); @@ -5951,22 +5948,25 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) down_write(&hba->clk_scaling_lock); up_write(&hba->clk_scaling_lock); cancel_work_sync(&hba->eeh_work); + return 0; } static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) { + ufshcd_clear_eh_in_progress(hba); ufshcd_scsi_unblock_requests(hba); ufshcd_release(hba); if (ufshcd_is_clkscaling_supported(hba)) ufshcd_clk_scaling_suspend(hba, false); ufshcd_clear_ua_wluns(hba); ufshcd_rpm_put(hba); + pm_runtime_put(hba->dev); } static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba) { return (!hba->is_powered || hba->shutting_down || - !hba->sdev_ufs_device || + !hba->sdev_ufs_device || hba->is_sys_suspended || hba->ufshcd_state == UFSHCD_STATE_ERROR || (!(hba->saved_err || hba->saved_uic_err || hba->force_reset || ufshcd_is_link_broken(hba)))); @@ -6052,9 +6052,13 @@ static void ufshcd_err_handler(struct work_struct *work) up(&hba->host_sem); return; } - ufshcd_set_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); - ufshcd_err_handling_prepare(hba); + if (ufshcd_err_handling_prepare(hba)) { + dev_err(hba->dev, "%s: error handling preparation failed\n", + __func__); + up(&hba->host_sem); + return; + } /* Complete requests that have door-bell cleared by h/w */ ufshcd_complete_requests(hba); spin_lock_irqsave(hba->host->host_lock, flags); @@ -6198,7 +6202,6 @@ static void ufshcd_err_handler(struct work_struct *work) dev_err_ratelimited(hba->dev, "%s: exit: saved_err 0x%x saved_uic_err 0x%x", __func__, hba->saved_err, hba->saved_uic_err); } - ufshcd_clear_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_err_handling_unprepare(hba); up(&hba->host_sem); @@ -8999,6 +9002,9 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) /* Enable Auto-Hibernate if configured */ ufshcd_auto_hibern8_enable(hba); + + hba->clk_gating.is_suspended = false; + ufshcd_release(hba); goto out; set_old_link_state: @@ -9008,8 +9014,6 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) out: if (ret) ufshcd_update_evt_hist(hba, UFS_EVT_WL_RES_ERR, (u32)ret); - hba->clk_gating.is_suspended = false; - ufshcd_release(hba); hba->wl_pm_op_in_progress = false; return ret <= 0 ? ret : -EINVAL; } From patchwork Thu Jun 10 04:43:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311781 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBB1CC47094 for ; Thu, 10 Jun 2021 04:44:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D24A260FEF for ; Thu, 10 Jun 2021 04:44:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230113AbhFJEqP (ORCPT ); Thu, 10 Jun 2021 00:46:15 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10993 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230028AbhFJEqO (ORCPT ); Thu, 10 Jun 2021 00:46:14 -0400 IronPort-SDR: Vj+rtK7BokAmQ8EmYJ5TWOKGfZjBVOyZZ1pinm/RGEoe/ejUNIYv5+dGJzRlZ5P2L0RWGqqEY3 AP4VwsTshwOB2Mg0jUkqK6MIGcZv15gi2HDrVMPz6Bbtm6je36SQAoFaDcETjzCcsJye83W1S/ SSfY3/n+JPTeuGdzG14qLh5yc4Ufxri51zT8ouUE/effwICOWolCmmq90sT+nKazN33c8NmXku F3f99wijrgMDqXhFVaXsL/5fUdTzvjnfJrrWHoyfVJDUutwCBOPlOAj+75r1vV6XSghnVN6I9j xgk= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778430" Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:19 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg03-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:44:18 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id E25EF21AF7; Wed, 9 Jun 2021 21:44:18 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 6/9] scsi: ufs: Update ufshcd_recover_pm_error() Date: Wed, 9 Jun 2021 21:43:34 -0700 Message-Id: <1623300218-9454-7-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org After error handler performs a successful reset and restore, all the LUs become active, forcibly set the runtime PM status of the scsi devices (and their request queues) underneath hba to ACTIVE to reflect the change. By doing so, dev->power.runtime_error (if any) can also be cleared, such that runtime PM can get back to work on them, otherwise the device(s) may be left either runtime active or runtime suspended permanently. Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 49 ++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0afad6b..c418a19 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -243,6 +243,7 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba); static int ufshcd_change_power_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *pwr_mode); static void ufshcd_schedule_eh_work(struct ufs_hba *hba); +static void ufshcd_recover_pm_error(struct ufs_hba *hba); static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on); static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on); static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, @@ -5951,13 +5952,15 @@ static int ufshcd_err_handling_prepare(struct ufs_hba *hba) return 0; } -static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) +static void ufshcd_err_handling_unprepare(struct ufs_hba *hba, int reset_err) { ufshcd_clear_eh_in_progress(hba); ufshcd_scsi_unblock_requests(hba); ufshcd_release(hba); if (ufshcd_is_clkscaling_supported(hba)) ufshcd_clk_scaling_suspend(hba, false); + if (!reset_err) + ufshcd_recover_pm_error(hba); ufshcd_clear_ua_wluns(hba); ufshcd_rpm_put(hba); pm_runtime_put(hba->dev); @@ -5976,34 +5979,26 @@ static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba) static void ufshcd_recover_pm_error(struct ufs_hba *hba) { struct Scsi_Host *shost = hba->host; - struct scsi_device *sdev; - struct request_queue *q; + struct scsi_device *sdev = hba->sdev_ufs_device; + struct scsi_target *starget = sdev->sdev_target; int ret; hba->is_wl_sys_suspended = false; - /* - * Set RPM status of wlun device to RPM_ACTIVE, - * this also clears its runtime error. - */ - ret = pm_runtime_set_active(&hba->sdev_ufs_device->sdev_gendev); - /* hba device might have a runtime error otherwise */ - if (ret) - ret = pm_runtime_set_active(hba->dev); - /* - * If wlun device had runtime error, we also need to resume those - * consumer scsi devices in case any of them has failed to be - * resumed due to supplier runtime resume failure. This is to unblock - * blk_queue_enter in case there are bios waiting inside it. - */ - if (!ret) { - shost_for_each_device(sdev, shost) { - q = sdev->request_queue; - if (q->dev && (q->rpm_status == RPM_SUSPENDED || - q->rpm_status == RPM_SUSPENDING)) - pm_request_resume(q->dev); - } + /* Resume parent/target to clear path for pm_runtime_set_active() */ + pm_runtime_get_sync(&starget->dev); + shost_for_each_device(sdev, shost) { + struct device *dev = &sdev->sdev_gendev; + + pm_runtime_get_sync(dev); + /* Clear dev->power.runtime_error */ + ret = pm_runtime_set_active(dev); + if (!ret) + /* runtime_error cleared, kick blk_queue_enter() */ + blk_set_runtime_active(sdev->request_queue); + pm_runtime_put(dev); } + pm_runtime_put(&starget->dev); } #else static inline void ufshcd_recover_pm_error(struct ufs_hba *hba) @@ -6037,7 +6032,7 @@ static void ufshcd_err_handler(struct work_struct *work) unsigned long flags; bool err_xfer = false; bool err_tm = false; - int err = 0, pmc_err; + int err = -1, pmc_err; int tag; bool needs_reset = false, needs_restore = false; @@ -6189,8 +6184,6 @@ static void ufshcd_err_handler(struct work_struct *work) if (err) dev_err(hba->dev, "%s: reset and restore failed with err %d\n", __func__, err); - else - ufshcd_recover_pm_error(hba); spin_lock_irqsave(hba->host->host_lock, flags); } @@ -6203,7 +6196,7 @@ static void ufshcd_err_handler(struct work_struct *work) __func__, hba->saved_err, hba->saved_uic_err); } spin_unlock_irqrestore(hba->host->host_lock, flags); - ufshcd_err_handling_unprepare(hba); + ufshcd_err_handling_unprepare(hba, err); up(&hba->host_sem); } From patchwork Thu Jun 10 04:43:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311783 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17FE8C47094 for ; Thu, 10 Jun 2021 04:44:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 01AF160FEF for ; Thu, 10 Jun 2021 04:44:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230136AbhFJEqX (ORCPT ); Thu, 10 Jun 2021 00:46:23 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10071 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230120AbhFJEqW (ORCPT ); Thu, 10 Jun 2021 00:46:22 -0400 IronPort-SDR: jotiyUclQrVrtpwZwn2WtillfYGqVfOIO78rVhdw/eCjOS4N6HbAky4c/KrgKGFSTs9bTSX+aW EdCfJxiFQQuyNuJxR4t0sNRw8k6RlW0cslRBb+6+rAT+m7YOk7tlicH2hGPQPZ/NdAZb7qlCy/ fu1+7Y7V+fXXXu59R8erIui4jKxEYjcY9GduOfE/UFEKyKMoJzNzH8gXv1ElZocMPt3nOD7go1 npt/7KIKcuNL7ObbRHu7YTFAKAWgjviTMxE0uBl2/Rb1gEAp0RwqOfGtTQGsCRSKtqJf9TBUTG aW8= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778431" Received: from unknown (HELO ironmsg01-sd.qualcomm.com) ([10.53.140.141]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:26 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg01-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:44:25 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id AFCF921AF7; Wed, 9 Jun 2021 21:44:25 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , Adrian Hunter , Kiwoong Kim , Satya Tangirala , Bart Van Assche , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 7/9] scsi: ufs: Let host_sem cover the entire system suspend/resume Date: Wed, 9 Jun 2021 21:43:35 -0700 Message-Id: <1623300218-9454-8-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org UFS error handling now is doing more than just re-probing, but also sending scsi cmds, e.g., for clearing UACs, and recovering runtime PM error, which may change runtime status of scsi devices. To protect system suspend/resume from being disturbed by error handling, move the host_sem from wl pm ops to ufshcd_suspend_prepare() and ufshcd_resume_complete(). Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 8 +++----- drivers/scsi/ufs/ufshcd.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c418a19..861942b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -9060,16 +9060,13 @@ static int ufshcd_wl_suspend(struct device *dev) ktime_t start = ktime_get(); hba = shost_priv(sdev->host); - down(&hba->host_sem); if (pm_runtime_suspended(dev)) goto out; ret = __ufshcd_wl_suspend(hba, UFS_SYSTEM_PM); - if (ret) { + if (ret) dev_err(&sdev->sdev_gendev, "%s failed: %d\n", __func__, ret); - up(&hba->host_sem); - } out: if (!ret) @@ -9102,7 +9099,6 @@ static int ufshcd_wl_resume(struct device *dev) hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) hba->is_wl_sys_suspended = false; - up(&hba->host_sem); return ret; } #endif @@ -9665,6 +9661,7 @@ void ufshcd_resume_complete(struct device *dev) ufshcd_rpmb_rpm_put(hba); hba->rpmb_complete_put = false; } + up(&hba->host_sem); } EXPORT_SYMBOL_GPL(ufshcd_resume_complete); @@ -9691,6 +9688,7 @@ int ufshcd_suspend_prepare(struct device *dev) ufshcd_rpmb_rpm_get_sync(hba); hba->rpmb_complete_put = true; } + down(&hba->host_sem); return 0; } EXPORT_SYMBOL_GPL(ufshcd_suspend_prepare); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index eaebb4e..47da47c 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -693,7 +693,7 @@ struct ufs_hba_monitor { * @ee_ctrl_mask: Exception event control mask * @is_powered: flag to check if HBA is powered * @shutting_down: flag to check if shutdown has been invoked - * @host_sem: semaphore used to serialize concurrent contexts + * @host_sem: semaphore used to avoid concurrency of contexts * @eh_wq: Workqueue that eh_work works on * @eh_work: Worker to handle UFS errors that require s/w attention * @eeh_work: Worker to handle exception events From patchwork Thu Jun 10 04:43:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311785 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ADDB7C47094 for ; Thu, 10 Jun 2021 04:44:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E163613C0 for ; Thu, 10 Jun 2021 04:44:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230153AbhFJEqe (ORCPT ); Thu, 10 Jun 2021 00:46:34 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:10071 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230120AbhFJEq0 (ORCPT ); Thu, 10 Jun 2021 00:46:26 -0400 IronPort-SDR: 2gIJujVIYJSQw4eYn9kR8Wq5wR1nw6W01+zg/OC+002gLNKEVyuyQq7oQKxHWtA2xg37YbvDm0 Pm10nRbCjxt+SrQEuHlsprFd4FPQUnnXB66FQVPlNrfNbh7kTOBVeNxd0gzLzMm1DKOyQfzG/S AwM3+eSb/rV5ujqeJIUVH1WG5aJVGZwTF42qJXIAlHPrnvkk86rMDimuHsb07zGJmXj82XW+11 TPiPjcgzdC7THRddi5aFQ+EBG7eyrE8pJQ/Eis3A2zVAQvYT32G3UtMMpSe3MBrRkxNZfcdwsu HaA= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778432" Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:44:30 -0700 X-QCInternal: smtphost Received: from wsp769891wss.qualcomm.com (HELO stor-presley.qualcomm.com) ([192.168.140.85]) by ironmsg-SD-alpha.qualcomm.com with ESMTP; 09 Jun 2021 21:44:29 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id D86D021AF7; Wed, 9 Jun 2021 21:44:29 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Stanley Chu , Bean Huo , Jaegeuk Kim , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 8/9] scsi: ufs: Update the fast abort path in ufshcd_abort() for PM requests Date: Wed, 9 Jun 2021 21:43:36 -0700 Message-Id: <1623300218-9454-9-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org If PM requests fail during runtime suspend/resume, RPM framework saves the error to dev->power.runtime_error. Before the runtime_error gets cleared, runtime PM on this specific device won't work again, leaving the device either runtime active or runtime suspended permanently. When task abort happens to a PM request sent during runtime suspend/resume, even if it can be successfully aborted, RPM framework anyways saves the (TIMEOUT) error. In this situation, we can leverage error handling to recover and clear the runtime_error. So, let PM requests take the fast abort path in ufshcd_abort(). Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 861942b..cf24ec2 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2737,7 +2737,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) * err handler blocked for too long. So, just fail the scsi cmd * sent from PM ops, err handler can recover PM error anyways. */ - if (hba->wl_pm_op_in_progress) { + if (cmd->request->rq_flags & RQF_PM) { hba->force_reset = true; set_host_byte(cmd, DID_BAD_TARGET); cmd->scsi_done(cmd); @@ -2760,7 +2760,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) } if (unlikely(test_bit(tag, &hba->outstanding_reqs))) { - if (hba->wl_pm_op_in_progress) { + if (cmd->request->rq_flags & RQF_PM) { set_host_byte(cmd, DID_BAD_TARGET); cmd->scsi_done(cmd); } else { @@ -6985,11 +6985,14 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) int err = 0; struct ufshcd_lrb *lrbp; u32 reg; + bool need_eh = false; host = cmd->device->host; hba = shost_priv(host); tag = cmd->request->tag; lrbp = &hba->lrb[tag]; + + dev_info(hba->dev, "%s: Device abort task at tag %d\n", __func__, tag); if (!ufshcd_valid_tag(hba, tag)) { dev_err(hba->dev, "%s: invalid command tag %d: cmd=0x%p, cmd->request=0x%p", @@ -7007,9 +7010,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto out; } - /* Print Transfer Request of aborted task */ - dev_info(hba->dev, "%s: Device abort task at tag %d\n", __func__, tag); - /* * Print detailed info about aborted request. * As more than one request might get aborted at the same time, @@ -7037,21 +7037,21 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) } /* - * Task abort to the device W-LUN is illegal. When this command - * will fail, due to spec violation, scsi err handling next step - * will be to send LU reset which, again, is a spec violation. - * To avoid these unnecessary/illegal steps, first we clean up - * the lrb taken by this cmd and re-set it in outstanding_reqs, - * then queue the eh_work and bail. + * This fast path guarantees the cmd always gets aborted successfully, + * meanwhile it invokes the error handler. It allows contexts, which + * are blocked by this cmd, to fail fast. It serves multiple purposes: + * #1 To avoid unnecessary/illagal abort attempts to the W-LU. + * #2 To avoid live lock between eh_work and specific contexts, i.e., + * suspend/resume and eh_work itself. + * #3 To let eh_work recover runtime PM error in case abort happens + * to cmds sent from runtime suspend/resume ops. */ - if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { + if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN || + (cmd->request->rq_flags & RQF_PM)) { ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun); __ufshcd_transfer_req_compl(hba, (1UL << tag)); set_bit(tag, &hba->outstanding_reqs); - spin_lock_irqsave(host->host_lock, flags); - hba->force_reset = true; - ufshcd_schedule_eh_work(hba); - spin_unlock_irqrestore(host->host_lock, flags); + need_eh = true; goto out; } @@ -7065,6 +7065,12 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) cleanup: __ufshcd_transfer_req_compl(hba, (1UL << tag)); out: + if (cmd->request->rq_flags & RQF_PM || need_eh) { + spin_lock_irqsave(host->host_lock, flags); + hba->force_reset = true; + ufshcd_schedule_eh_work(hba); + spin_unlock_irqrestore(host->host_lock, flags); + } err = SUCCESS; } else { dev_err(hba->dev, "%s: failed with err %d\n", __func__, err); From patchwork Thu Jun 10 04:43:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Can Guo X-Patchwork-Id: 12311787 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7A115C47094 for ; Thu, 10 Jun 2021 04:45:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 533C9613B0 for ; Thu, 10 Jun 2021 04:45:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230166AbhFJErD (ORCPT ); Thu, 10 Jun 2021 00:47:03 -0400 Received: from labrats.qualcomm.com ([199.106.110.90]:17149 "EHLO labrats.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230083AbhFJErC (ORCPT ); Thu, 10 Jun 2021 00:47:02 -0400 IronPort-SDR: 9ZxkIA9BUeH8WF1atT1heVdvVZvMcfhcklU25BRDOH6cg0alSaGr58o4Sk30JLBrtL8xolty2R CrLga3xU5bruQ2ZxasIenK4pO6tIBSqi4F7860XpAEJgzXxPISPkMK6WeoF50+AoG1w9tz6Jip B5lsrelE5cPC3fyzLcTBYveS9uIGFOxp+vP1DjCrOkDE7mJOtTAxFln4YaQcZ9iIaONdEYgXib chdZ4VHKwC9GUHXUZOn+jKOLh3oZeWaHbCuF8G+4IwOc2kjfVy28lRjt51NeXFe7aKmOoLNmnP a9s= X-IronPort-AV: E=Sophos;i="5.83,262,1616482800"; d="scan'208";a="29778433" Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by labrats.qualcomm.com with ESMTP; 09 Jun 2021 21:45:07 -0700 X-QCInternal: smtphost Received: from stor-presley.qualcomm.com ([192.168.140.85]) by ironmsg02-sd.qualcomm.com with ESMTP; 09 Jun 2021 21:45:06 -0700 Received: by stor-presley.qualcomm.com (Postfix, from userid 359480) id 3DB5E21AF7; Wed, 9 Jun 2021 21:45:06 -0700 (PDT) From: Can Guo To: asutoshd@codeaurora.org, nguyenb@codeaurora.org, hongwus@codeaurora.org, ziqichen@codeaurora.org, linux-scsi@vger.kernel.org, kernel-team@android.com, cang@codeaurora.org Cc: Alim Akhtar , Avri Altman , "James E.J. Bottomley" , "Martin K. Petersen" , Adrian Hunter , Bean Huo , Stanley Chu , Keoseong Park , Jaegeuk Kim , Bart van Assche , Dinghao Liu , "Gustavo A. R. Silva" , Kiwoong Kim , Satya Tangirala , linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 9/9] scsi: ufs: Apply more limitations to user access Date: Wed, 9 Jun 2021 21:43:37 -0700 Message-Id: <1623300218-9454-10-git-send-email-cang@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623300218-9454-1-git-send-email-cang@codeaurora.org> References: <1623300218-9454-1-git-send-email-cang@codeaurora.org> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Do not let user access HW if hba resume fails or hba is not in good state, otherwise it may lead to various stability issues. Signed-off-by: Can Guo --- drivers/scsi/ufs/ufs-debugfs.c | 27 ++--------- drivers/scsi/ufs/ufs-sysfs.c | 105 ++++++++++++++--------------------------- drivers/scsi/ufs/ufs_bsg.c | 16 +++---- drivers/scsi/ufs/ufshcd.c | 63 +++++++++++++++---------- drivers/scsi/ufs/ufshcd.h | 17 ++++++- 5 files changed, 101 insertions(+), 127 deletions(-) diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c index 4e1ff20..42c1c8b 100644 --- a/drivers/scsi/ufs/ufs-debugfs.c +++ b/drivers/scsi/ufs/ufs-debugfs.c @@ -52,25 +52,6 @@ static int ee_usr_mask_get(void *data, u64 *val) return 0; } -static int ufs_debugfs_get_user_access(struct ufs_hba *hba) -__acquires(&hba->host_sem) -{ - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - up(&hba->host_sem); - return -EBUSY; - } - ufshcd_rpm_get_sync(hba); - return 0; -} - -static void ufs_debugfs_put_user_access(struct ufs_hba *hba) -__releases(&hba->host_sem) -{ - ufshcd_rpm_put_sync(hba); - up(&hba->host_sem); -} - static int ee_usr_mask_set(void *data, u64 val) { struct ufs_hba *hba = data; @@ -78,11 +59,11 @@ static int ee_usr_mask_set(void *data, u64 val) if (val & ~(u64)MASK_EE_STATUS) return -EINVAL; - err = ufs_debugfs_get_user_access(hba); + err = ufshcd_get_user_access(hba); if (err) return err; err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS); - ufs_debugfs_put_user_access(hba); + ufshcd_put_user_access(hba); return err; } @@ -120,10 +101,10 @@ static void ufs_debugfs_restart_ee(struct work_struct *work) struct ufs_hba *hba = container_of(work, struct ufs_hba, debugfs_ee_work.work); if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) || - ufs_debugfs_get_user_access(hba)) + ufshcd_get_user_access(hba)) return; ufshcd_write_ee_control(hba); - ufs_debugfs_put_user_access(hba); + ufshcd_put_user_access(hba); } void ufs_debugfs_hba_init(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 52bd807..b8732b9 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -160,22 +160,14 @@ static ssize_t auto_hibern8_show(struct device *dev, if (!ufshcd_is_auto_hibern8_supported(hba)) return -EOPNOTSUPP; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - ret = -EBUSY; - goto out; - } - - pm_runtime_get_sync(hba->dev); + ret = ufshcd_get_user_access(hba); + if (ret) + return ret; ufshcd_hold(hba, false); ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); - ret = sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit)); - -out: - up(&hba->host_sem); + ufshcd_put_user_access(hba); return ret; } @@ -202,7 +194,7 @@ static ssize_t auto_hibern8_store(struct device *dev, goto out; } - ufshcd_auto_hibern8_update(hba, ufshcd_us_to_ahit(timer)); + ret = ufshcd_auto_hibern8_update(hba, ufshcd_us_to_ahit(timer)); out: up(&hba->host_sem); @@ -239,17 +231,11 @@ static ssize_t wb_on_store(struct device *dev, struct device_attribute *attr, if (wb_enable != 0 && wb_enable != 1) return -EINVAL; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - res = -EBUSY; - goto out; - } - - ufshcd_rpm_get_sync(hba); + res = ufshcd_get_user_access(hba); + if (res) + return res; res = ufshcd_wb_toggle(hba, wb_enable); - ufshcd_rpm_put_sync(hba); -out: - up(&hba->host_sem); + ufshcd_put_user_access(hba); return res < 0 ? res : count; } @@ -527,16 +513,11 @@ static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, if (param_size > 8) return -EINVAL; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - ret = -EBUSY; - goto out; - } - - ufshcd_rpm_get_sync(hba); + ret = ufshcd_get_user_access(hba); + if (ret) + return ret; ret = ufshcd_read_desc_param(hba, desc_id, desc_index, param_offset, desc_buf, param_size); - ufshcd_rpm_put_sync(hba); if (ret) { ret = -EINVAL; goto out; @@ -561,7 +542,7 @@ static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, } out: - up(&hba->host_sem); + ufshcd_put_user_access(hba); return ret; } @@ -904,23 +885,20 @@ static ssize_t _name##_show(struct device *dev, \ int desc_len = QUERY_DESC_MAX_SIZE; \ u8 *desc_buf; \ \ - down(&hba->host_sem); \ - if (!ufshcd_is_user_access_allowed(hba)) { \ - up(&hba->host_sem); \ - return -EBUSY; \ - } \ + ret = ufshcd_get_user_access(hba); \ + if (ret) \ + return ret; \ desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \ if (!desc_buf) { \ - up(&hba->host_sem); \ - return -ENOMEM; \ + ret = -ENOMEM; \ + goto out; \ } \ - ufshcd_rpm_get_sync(hba); \ ret = ufshcd_query_descriptor_retry(hba, \ UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \ 0, 0, desc_buf, &desc_len); \ if (ret) { \ ret = -EINVAL; \ - goto out; \ + goto out_free; \ } \ index = desc_buf[DEVICE_DESC_PARAM##_pname]; \ kfree(desc_buf); \ @@ -928,12 +906,12 @@ static ssize_t _name##_show(struct device *dev, \ ret = ufshcd_read_string_desc(hba, index, &desc_buf, \ SD_ASCII_STD); \ if (ret < 0) \ - goto out; \ + goto out_free; \ ret = sysfs_emit(buf, "%s\n", desc_buf); \ -out: \ - ufshcd_rpm_put_sync(hba); \ +out_free: \ kfree(desc_buf); \ - up(&hba->host_sem); \ +out: \ + ufshcd_put_user_access(hba); \ return ret; \ } \ static DEVICE_ATTR_RO(_name) @@ -973,24 +951,20 @@ static ssize_t _name##_show(struct device *dev, \ int ret; \ struct ufs_hba *hba = dev_get_drvdata(dev); \ \ - down(&hba->host_sem); \ - if (!ufshcd_is_user_access_allowed(hba)) { \ - up(&hba->host_sem); \ - return -EBUSY; \ - } \ + ret = ufshcd_get_user_access(hba); \ + if (ret) \ + return ret; \ if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname)) \ index = ufshcd_wb_get_query_index(hba); \ - ufshcd_rpm_get_sync(hba); \ ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ QUERY_FLAG_IDN##_uname, index, &flag); \ - ufshcd_rpm_put_sync(hba); \ if (ret) { \ ret = -EINVAL; \ goto out; \ } \ ret = sysfs_emit(buf, "%s\n", flag ? "true" : "false"); \ out: \ - up(&hba->host_sem); \ + ufshcd_put_user_access(hba); \ return ret; \ } \ static DEVICE_ATTR_RO(_name) @@ -1042,24 +1016,20 @@ static ssize_t _name##_show(struct device *dev, \ int ret; \ u8 index = 0; \ \ - down(&hba->host_sem); \ - if (!ufshcd_is_user_access_allowed(hba)) { \ - up(&hba->host_sem); \ - return -EBUSY; \ - } \ + ret = ufshcd_get_user_access(hba); \ + if (ret) \ + return ret; \ if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname)) \ index = ufshcd_wb_get_query_index(hba); \ - ufshcd_rpm_get_sync(hba); \ ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \ QUERY_ATTR_IDN##_uname, index, 0, &value); \ - ufshcd_rpm_put_sync(hba); \ if (ret) { \ ret = -EINVAL; \ goto out; \ } \ ret = sysfs_emit(buf, "0x%08X\n", value); \ out: \ - up(&hba->host_sem); \ + ufshcd_put_user_access(hba); \ return ret; \ } \ static DEVICE_ATTR_RO(_name) @@ -1195,16 +1165,11 @@ static ssize_t dyn_cap_needed_attribute_show(struct device *dev, u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); int ret; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - ret = -EBUSY; - goto out; - } - - ufshcd_rpm_get_sync(hba); + ret = ufshcd_get_user_access(hba); + if (ret) + return ret; ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value); - ufshcd_rpm_put_sync(hba); if (ret) { ret = -EINVAL; goto out; @@ -1213,7 +1178,7 @@ static ssize_t dyn_cap_needed_attribute_show(struct device *dev, ret = sysfs_emit(buf, "0x%08X\n", value); out: - up(&hba->host_sem); + ufshcd_put_user_access(hba); return ret; } static DEVICE_ATTR_RO(dyn_cap_needed_attribute); diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index 39bf204..c5b3eb8 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -97,7 +97,9 @@ static int ufs_bsg_request(struct bsg_job *job) bsg_reply->reply_payload_rcv_len = 0; - ufshcd_rpm_get_sync(hba); + ret = ufshcd_get_user_access(hba); + if (ret) + goto out; msgcode = bsg_request->msgcode; switch (msgcode) { @@ -105,10 +107,8 @@ static int ufs_bsg_request(struct bsg_job *job) desc_op = bsg_request->upiu_req.qr.opcode; ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff, &desc_len, desc_op); - if (ret) { - ufshcd_rpm_put_sync(hba); - goto out; - } + if (ret) + goto out_put_access; fallthrough; case UPIU_TRANSACTION_NOP_OUT: @@ -138,10 +138,8 @@ static int ufs_bsg_request(struct bsg_job *job) break; } - ufshcd_rpm_put_sync(hba); - if (!desc_buff) - goto out; + goto out_put_access; if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) bsg_reply->reply_payload_rcv_len = @@ -151,6 +149,8 @@ static int ufs_bsg_request(struct bsg_job *job) kfree(desc_buff); +out_put_access: + ufshcd_put_user_access(hba); out: bsg_reply->result = ret; job->reply_len = sizeof(struct ufs_bsg_reply); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index cf24ec2..5ec829c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -128,15 +128,6 @@ enum { UFSHCD_CAN_QUEUE = 32, }; -/* UFSHCD states */ -enum { - UFSHCD_STATE_RESET, - UFSHCD_STATE_ERROR, - UFSHCD_STATE_OPERATIONAL, - UFSHCD_STATE_EH_SCHEDULED_FATAL, - UFSHCD_STATE_EH_SCHEDULED_NON_FATAL, -}; - /* UFSHCD error handling flags */ enum { UFSHCD_EH_IN_PROGRESS = (1 << 0), @@ -254,6 +245,31 @@ static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable); static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba); +int ufshcd_get_user_access(struct ufs_hba *hba) +__acquires(&hba->host_sem) +{ + down(&hba->host_sem); + if (!ufshcd_is_user_access_allowed(hba)) { + up(&hba->host_sem); + return -EBUSY; + } + if (ufshcd_rpm_get_sync(hba)) { + ufshcd_rpm_put_sync(hba); + up(&hba->host_sem); + return -EBUSY; + } + return 0; +} +EXPORT_SYMBOL_GPL(ufshcd_get_user_access); + +void ufshcd_put_user_access(struct ufs_hba *hba) +__releases(&hba->host_sem) +{ + ufshcd_rpm_put_sync(hba); + up(&hba->host_sem); +} +EXPORT_SYMBOL_GPL(ufshcd_put_user_access); + static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { return tag >= 0 && tag < hba->nutrs; @@ -1553,19 +1569,14 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, if (kstrtou32(buf, 0, &value)) return -EINVAL; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - err = -EBUSY; - goto out; - } + err = ufshcd_get_user_access(hba); + if (err) + return err; + ufshcd_hold(hba, false); value = !!value; if (value == hba->clk_scaling.is_enabled) goto out; - - ufshcd_rpm_get_sync(hba); - ufshcd_hold(hba, false); - hba->clk_scaling.is_enabled = value; if (value) { @@ -1578,10 +1589,9 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, __func__, err); } - ufshcd_release(hba); - ufshcd_rpm_put_sync(hba); out: - up(&hba->host_sem); + ufshcd_release(hba); + ufshcd_put_user_access(hba); return err ? err : count; } @@ -4180,13 +4190,13 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) } EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit); -void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) +int ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) { unsigned long flags; bool update = false; if (!ufshcd_is_auto_hibern8_supported(hba)) - return; + return 0; spin_lock_irqsave(hba->host->host_lock, flags); if (hba->ahit != ahit) { @@ -4197,12 +4207,17 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) if (update && !pm_runtime_suspended(&hba->sdev_ufs_device->sdev_gendev)) { - ufshcd_rpm_get_sync(hba); + if (ufshcd_rpm_get_sync(hba)) { + ufshcd_rpm_put_sync(hba); + return -EBUSY; + } ufshcd_hold(hba, false); ufshcd_auto_hibern8_enable(hba); ufshcd_release(hba); ufshcd_rpm_put_sync(hba); } + + return 0; } EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 47da47c..5cd1484 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -101,6 +101,15 @@ struct uic_command { struct completion done; }; +/* UFSHCD states */ +enum { + UFSHCD_STATE_RESET, + UFSHCD_STATE_ERROR, + UFSHCD_STATE_OPERATIONAL, + UFSHCD_STATE_EH_SCHEDULED_FATAL, + UFSHCD_STATE_EH_SCHEDULED_NON_FATAL, +}; + /* Used to differentiate the power management options */ enum ufs_pm_op { UFS_RUNTIME_PM, @@ -931,7 +940,9 @@ static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba) static inline bool ufshcd_is_user_access_allowed(struct ufs_hba *hba) { - return !hba->shutting_down; + return !hba->shutting_down && !hba->is_sys_suspended && + !hba->is_wl_sys_suspended && + hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL; } #define ufshcd_writel(hba, val, reg) \ @@ -1104,7 +1115,7 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res); void ufshcd_auto_hibern8_enable(struct ufs_hba *hba); -void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); +int ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups); #define SD_ASCII_STD true #define SD_RAW false @@ -1131,6 +1142,8 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable); int ufshcd_suspend_prepare(struct device *dev); void ufshcd_resume_complete(struct device *dev); +int ufshcd_get_user_access(struct ufs_hba *hba); +void ufshcd_put_user_access(struct ufs_hba *hba); /* Wrapper functions for safely calling variant operations */ static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)