RE: [PATCH] scsi: ufs: Fix Runtime PM
On 2017-11-21 20:45, Subhash Jadavani wrote: > On 2017-11-13 01:14, Michal Potomski wrote: > > From: Michał Potomski > > > > Recent testing of Runtime PM for UFS has shown it's not working as > > intended. To acheive fully working Runtime PM, first we have to put > > back scsi_device autopm reference counter. > > > > Existing implementation was prone to races and not working for > > tranfsers to sleeping devices. This commit aims to fix this to acheive > > fully working environment. Due to runtime PM being previously disabled > > by not putting scsi_device autopm counter, the Runtime PM is set to be > > forbidden as default, to not cause problems with hosts and devices, > > which do not fully support different Device and Link states. > > > > It can be still enabled through sysFS power/control attribute. > > > > Changes since v1: > > - Fix compilation error for certain kernel configs, > > - Move pm_mark_last_busy(), only to relevant context. > > > > Signed-off-by: Michał Potomski > > --- > > drivers/scsi/ufs/ufshcd-pci.c | 4 ++- > > drivers/scsi/ufs/ufshcd.c | 64 > > +++ > > 2 files changed, 56 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/scsi/ufs/ufshcd-pci.c > > b/drivers/scsi/ufs/ufshcd-pci.c index 925b0ec7ec54..4fffb1123876 > > 100644 > > --- a/drivers/scsi/ufs/ufshcd-pci.c > > +++ b/drivers/scsi/ufs/ufshcd-pci.c > > @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const > > struct pci_device_id *id) > > } > > > > pci_set_drvdata(pdev, hba); > > + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); > > + pm_runtime_use_autosuspend(&pdev->dev); > > pm_runtime_put_noidle(&pdev->dev); > > - pm_runtime_allow(&pdev->dev); > > + pm_runtime_forbid(&pdev->dev); > > > > return 0; > > } > > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c > > index 011c3369082c..7ff7f51afe26 100644 > > --- a/drivers/scsi/ufs/ufshcd.c > > +++ b/drivers/scsi/ufs/ufshcd.c > > @@ -240,6 +240,37 @@ static inline bool ufshcd_valid_tag(struct > > ufs_hba *hba, int tag) > > return tag >= 0 && tag < hba->nutrs; } > > > > +#ifdef CONFIG_PM > > +static void ufshcd_pm_runtime_get(struct device *dev) { > > + // Don't trigger PM events while in transition states > > + if (dev->power.runtime_status == RPM_RESUMING || > > + dev->power.runtime_status == RPM_SUSPENDING) > > Why do we need to check this? Isn't this check race condition prone? We need to check this, because we might end up in triggering resume, while suspending or resuming, which will cause deadlock. This is especially important in ufshcd_queuecommand directive, through which we pass e.g. START/STOP Unit SCSI command, when resuming or suspending. > > + pm_runtime_get_noresume(dev); > > + else > > + pm_runtime_get_sync(dev); > > +} > > + > > +static void ufshcd_pm_runtime_put(struct device *dev) { > > + // Don't trigger PM events while in transition states > > + if (dev->power.runtime_status == RPM_RESUMING || > > + dev->power.runtime_status == RPM_SUSPENDING) > > + pm_runtime_put_noidle(dev); > > + else { > > + pm_runtime_mark_last_busy(dev); > > + pm_runtime_put_autosuspend(dev); > > + } > > +} > > +#else > > +static void ufshcd_pm_runtime_get(struct device *dev) { } static void > > +ufshcd_pm_runtime_put(struct device *dev) { } #endif > > + > > static inline int ufshcd_enable_irq(struct ufs_hba *hba) { > > int ret = 0; > > @@ -1345,7 +1376,7 @@ static ssize_t > > ufshcd_clkscale_enable_store(struct device *dev, > > if (value == hba->clk_scaling.is_allowed) > > goto out; > > > > - pm_runtime_get_sync(hba->dev); > > + ufshcd_pm_runtime_get(hba->dev); > > ufshcd_hold(hba, false); > > > > cancel_work_sync(&hba->clk_scaling.suspend_work); > > @@ -1364,7 +1395,7 @@ static ssize_t > > ufshcd_clkscale_enable_store(struct device *dev, > > } > > > > ufshcd_release(hba); > > - pm_runtime_put_sync(hba->dev); > > + ufshcd_pm_runtime_put(hba->dev); > > out: > > return count; > > } > > @@ -1948,6 +1979,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct > > uic_command *uic_cmd) > > unsigned long flags; > > > > ufshcd_hold(hba, false); > > + ufshcd_pm_runtime_get(hba->dev); > > mutex_lock(&hba->uic_cmd_mutex); > > ufshcd_add_delay_before_dme_cmd(hba); > > > > @@ -1959,6 +1991,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct > > uic_command *uic_cmd) > > > > mutex_unlock(&hba->uic_cmd_mutex); > > > > + ufshcd_pm_runtime_put(hba->dev); > > ufshcd_release(hba); > > return ret; > > } > > @@ -2345,6 +2378,7 @@ static int ufshcd_queuecommand(struct Scsi_Host > > *host, struct scsi_cmnd *cmd) > > clear_bit_unlock(tag, &hba->lrb_in_use); > > goto out; > > } > > + ufshcd_pm_runtime_get(hba->dev); > > > why do we need to hold PM reference count here? I thought as ufs host is > parent of
Re: [PATCH] scsi: ufs: Fix Runtime PM
On 2017-11-13 01:14, Michal Potomski wrote: From: Michał Potomski Recent testing of Runtime PM for UFS has shown it's not working as intended. To acheive fully working Runtime PM, first we have to put back scsi_device autopm reference counter. Existing implementation was prone to races and not working for tranfsers to sleeping devices. This commit aims to fix this to acheive fully working environment. Due to runtime PM being previously disabled by not putting scsi_device autopm counter, the Runtime PM is set to be forbidden as default, to not cause problems with hosts and devices, which do not fully support different Device and Link states. It can be still enabled through sysFS power/control attribute. Changes since v1: - Fix compilation error for certain kernel configs, - Move pm_mark_last_busy(), only to relevant context. Signed-off-by: Michał Potomski --- drivers/scsi/ufs/ufshcd-pci.c | 4 ++- drivers/scsi/ufs/ufshcd.c | 64 +++ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 925b0ec7ec54..4fffb1123876 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_drvdata(pdev, hba); + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - pm_runtime_allow(&pdev->dev); + pm_runtime_forbid(&pdev->dev); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 011c3369082c..7ff7f51afe26 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -240,6 +240,37 @@ static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) return tag >= 0 && tag < hba->nutrs; } +#ifdef CONFIG_PM +static void ufshcd_pm_runtime_get(struct device *dev) +{ + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) Why do we need to check this? Isn't this check race condition prone? + pm_runtime_get_noresume(dev); + else + pm_runtime_get_sync(dev); +} + +static void ufshcd_pm_runtime_put(struct device *dev) +{ + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) + pm_runtime_put_noidle(dev); + else { + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + } +} +#else +static void ufshcd_pm_runtime_get(struct device *dev) +{ +} +static void ufshcd_pm_runtime_put(struct device *dev) +{ +} +#endif + static inline int ufshcd_enable_irq(struct ufs_hba *hba) { int ret = 0; @@ -1345,7 +1376,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, if (value == hba->clk_scaling.is_allowed) goto out; - pm_runtime_get_sync(hba->dev); + ufshcd_pm_runtime_get(hba->dev); ufshcd_hold(hba, false); cancel_work_sync(&hba->clk_scaling.suspend_work); @@ -1364,7 +1395,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, } ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); + ufshcd_pm_runtime_put(hba->dev); out: return count; } @@ -1948,6 +1979,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) unsigned long flags; ufshcd_hold(hba, false); + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); @@ -1959,6 +1991,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) mutex_unlock(&hba->uic_cmd_mutex); + ufshcd_pm_runtime_put(hba->dev); ufshcd_release(hba); return ret; } @@ -2345,6 +2378,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) clear_bit_unlock(tag, &hba->lrb_in_use); goto out; } + ufshcd_pm_runtime_get(hba->dev); why do we need to hold PM reference count here? I thought as ufs host is parent of scsi_host/scsi_device, scsi would make sure that UFS host is runtime resumed before any access to it. WARN_ON(hba->clk_gating.state != CLKS_ON); lrbp = &hba->lrb[tag]; @@ -3555,6 +3589,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) int ret; bool reenable_intr = false; + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); init_completion(&uic_async_done); ufshcd_add_delay_before_dme_cmd(hba); @@ -3609,6 +3644,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct u
[PATCH] scsi: ufs: Fix Runtime PM
From: Michał Potomski Recent testing of Runtime PM for UFS has shown it's not working as intended. To acheive fully working Runtime PM, first we have to put back scsi_device autopm reference counter. Existing implementation was prone to races and not working for tranfsers to sleeping devices. This commit aims to fix this to acheive fully working environment. Due to runtime PM being previously disabled by not putting scsi_device autopm counter, the Runtime PM is set to be forbidden as default, to not cause problems with hosts and devices, which do not fully support different Device and Link states. It can be still enabled through sysFS power/control attribute. Changes since v1: - Fix compilation error for certain kernel configs, - Move pm_mark_last_busy(), only to relevant context. Signed-off-by: Michał Potomski --- drivers/scsi/ufs/ufshcd-pci.c | 4 ++- drivers/scsi/ufs/ufshcd.c | 64 +++ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 925b0ec7ec54..4fffb1123876 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_drvdata(pdev, hba); + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - pm_runtime_allow(&pdev->dev); + pm_runtime_forbid(&pdev->dev); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 011c3369082c..7ff7f51afe26 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -240,6 +240,37 @@ static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) return tag >= 0 && tag < hba->nutrs; } +#ifdef CONFIG_PM +static void ufshcd_pm_runtime_get(struct device *dev) +{ + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) + pm_runtime_get_noresume(dev); + else + pm_runtime_get_sync(dev); +} + +static void ufshcd_pm_runtime_put(struct device *dev) +{ + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) + pm_runtime_put_noidle(dev); + else { + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + } +} +#else +static void ufshcd_pm_runtime_get(struct device *dev) +{ +} +static void ufshcd_pm_runtime_put(struct device *dev) +{ +} +#endif + static inline int ufshcd_enable_irq(struct ufs_hba *hba) { int ret = 0; @@ -1345,7 +1376,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, if (value == hba->clk_scaling.is_allowed) goto out; - pm_runtime_get_sync(hba->dev); + ufshcd_pm_runtime_get(hba->dev); ufshcd_hold(hba, false); cancel_work_sync(&hba->clk_scaling.suspend_work); @@ -1364,7 +1395,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, } ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); + ufshcd_pm_runtime_put(hba->dev); out: return count; } @@ -1948,6 +1979,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) unsigned long flags; ufshcd_hold(hba, false); + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); @@ -1959,6 +1991,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) mutex_unlock(&hba->uic_cmd_mutex); + ufshcd_pm_runtime_put(hba->dev); ufshcd_release(hba); return ret; } @@ -2345,6 +2378,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) clear_bit_unlock(tag, &hba->lrb_in_use); goto out; } + ufshcd_pm_runtime_get(hba->dev); WARN_ON(hba->clk_gating.state != CLKS_ON); lrbp = &hba->lrb[tag]; @@ -3555,6 +3589,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) int ret; bool reenable_intr = false; + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); init_completion(&uic_async_done); ufshcd_add_delay_before_dme_cmd(hba); @@ -3609,6 +3644,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); spin_unlock_irqrestore(hba->host->host_lock, flags); mutex_unlock(&hba->uic_cmd_mutex); + ufshcd_pm_runtime_put(hba->dev); return ret; } @@ -4386,6 +4422,7 @@ static int ufshcd_slave_con
RE: [PATCH] scsi: ufs: Fix Runtime PM
> -Original Message- > From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi- > ow...@vger.kernel.org] On Behalf Of Michal Potomski > Sent: Thursday, November 09, 2017 11:17 AM > To: linux-scsi@vger.kernel.org > Cc: vinholika...@gmail.com; martin.peter...@oracle.com; > j...@linux.vnet.ibm.com; subha...@codeaurora.org; > szymonx.mielcza...@intel.com > Subject: [PATCH] scsi: ufs: Fix Runtime PM > > From: Michał Potomski > > Recent testing of Runtime PM for UFS has shown it's not working as intended. > To acheive fully working Runtime PM, first we have to put back scsi_device > autopm reference counter. > > Existing implementation was prone to races and not working for tranfsers to > sleeping devices. Wouldn't calling pm_runtime_mark_last_busy() just before pm_runtime_put_autosuspend() suffice? This commit aims to fix this to acheive fully working > environment. Due to runtime PM being previously disabled by not putting > scsi_device autopm counter, the Runtime PM is set to be forbidden as > default, to not cause problems with hosts and devices, which do not fully > support different Device and Link states. > > It can be still enabled through sysFS power/control attribute. > > Signed-off-by: Michał Potomski > --- > drivers/scsi/ufs/ufshcd-pci.c | 4 +++- > drivers/scsi/ufs/ufshcd.c | 55 ++--- > -- > 2 files changed, 47 insertions(+), 12 deletions(-) > > diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c > index > 925b0ec7ec54..4fffb1123876 100644 > --- a/drivers/scsi/ufs/ufshcd-pci.c > +++ b/drivers/scsi/ufs/ufshcd-pci.c > @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct > pci_device_id *id) > } > > pci_set_drvdata(pdev, hba); > + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); > + pm_runtime_use_autosuspend(&pdev->dev); > pm_runtime_put_noidle(&pdev->dev); > - pm_runtime_allow(&pdev->dev); > + pm_runtime_forbid(&pdev->dev); > > return 0; > } > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index > 011c3369082c..e7c7ed9bf8a5 100644 > --- a/drivers/scsi/ufs/ufshcd.c > +++ b/drivers/scsi/ufs/ufshcd.c > @@ -240,6 +240,28 @@ static inline bool ufshcd_valid_tag(struct ufs_hba > *hba, int tag) > return tag >= 0 && tag < hba->nutrs; > } > > +static void ufshcd_pm_runtime_get(struct device *dev) { > + // Don't trigger PM events while in transition states > + if (dev->power.runtime_status == RPM_RESUMING || > + dev->power.runtime_status == RPM_SUSPENDING) > + pm_runtime_get_noresume(dev); > + else > + pm_runtime_get_sync(dev); > +} > + > +static void ufshcd_pm_runtime_put(struct device *dev) { > + pm_runtime_mark_last_busy(dev); > + > + // Don't trigger PM events while in transition states > + if (dev->power.runtime_status == RPM_RESUMING || > + dev->power.runtime_status == RPM_SUSPENDING) > + pm_runtime_put_noidle(dev); > + else > + pm_runtime_put_autosuspend(dev); > +} > + > static inline int ufshcd_enable_irq(struct ufs_hba *hba) { > int ret = 0; > @@ -1345,7 +1367,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct > device *dev, > if (value == hba->clk_scaling.is_allowed) > goto out; > > - pm_runtime_get_sync(hba->dev); > + ufshcd_pm_runtime_get(hba->dev); > ufshcd_hold(hba, false); > > cancel_work_sync(&hba->clk_scaling.suspend_work); > @@ -1364,7 +1386,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct > device *dev, > } > > ufshcd_release(hba); > - pm_runtime_put_sync(hba->dev); > + ufshcd_pm_runtime_put(hba->dev); > out: > return count; > } > @@ -1948,6 +1970,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct > uic_command *uic_cmd) > unsigned long flags; > > ufshcd_hold(hba, false); > + ufshcd_pm_runtime_get(hba->dev); > mutex_lock(&hba->uic_cmd_mutex); > ufshcd_add_delay_before_dme_cmd(hba); > > @@ -1959,6 +1982,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct > uic_command *uic_cmd) > > mutex_unlock(&hba->uic_cmd_mutex); > > + ufshcd_pm_runtime_put(hba->dev); > ufshcd_release(hba); > return ret; > } > @@ -2345,6 +2369,7 @@ static int ufshcd_queuecommand(struct Scsi_Host > *host, struct scsi_cmnd *cmd) > clear_bit_unlock(tag, &hba->lrb_in_use); > goto ou
Re: [PATCH] scsi: ufs: Fix Runtime PM
Hi Michał, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on scsi/for-next] [also build test WARNING on v4.14-rc8 next-20171109] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Michal-Potomski/scsi-ufs-Fix-Runtime-PM/20171110-191314 base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next config: x86_64-randconfig-v0-11102116 (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): In file included from include/uapi/linux/stddef.h:1:0, from include/linux/stddef.h:4, from include/uapi/linux/posix_types.h:4, from include/uapi/linux/types.h:13, from include/linux/types.h:5, from include/linux/async.h:15, from drivers/scsi/ufs/ufshcd.c:40: drivers/scsi/ufs/ufshcd.c: In function 'ufshcd_pm_runtime_get': drivers/scsi/ufs/ufshcd.c:246:16: error: 'struct dev_pm_info' has no member named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:247:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:246:16: error: 'struct dev_pm_info' has no member named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ include/linux/compiler.h:156:42: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:247:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ include/linux/compiler.h:156:42: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:246:16: error: 'struct dev_pm_info' has no member named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ include/linux/compiler.h:167:16: note: in definition of macro '__trace_if' __r = !!(cond); \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:247:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ include/linux/compiler.h:167:16: note: in definition of macro '__trace_if' __r = !!(cond); \ ^~~~ >> drivers/scsi/ufs/ufshcd.c:246:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c: In function 'ufshcd_pm_runtime_put': drivers/scsi/ufs/ufshcd.c:258:16: error: 'struct dev_pm_info' has no member named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ drivers/scsi/ufs/ufshcd.c:258:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING || ^~ drivers/scsi/ufs/ufshcd.c:259:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ drivers/scsi/ufs/ufshcd.c:258:2: note: in expansion of macro 'if' if (dev->power.runtime_status == RPM_RESUMING
Re: [PATCH] scsi: ufs: Fix Runtime PM
Hi Michał, Thank you for the patch! Yet something to improve: [auto build test ERROR on scsi/for-next] [also build test ERROR on v4.14-rc8 next-20171109] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Michal-Potomski/scsi-ufs-Fix-Runtime-PM/20171110-191314 base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next config: m68k-allyesconfig (attached as .config) compiler: m68k-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=m68k All errors (new ones prefixed by >>): drivers/scsi/ufs/ufshcd.c: In function 'ufshcd_pm_runtime_get': >> drivers/scsi/ufs/ufshcd.c:246:16: error: 'struct dev_pm_info' has no member >> named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ drivers/scsi/ufs/ufshcd.c:247:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ drivers/scsi/ufs/ufshcd.c: In function 'ufshcd_pm_runtime_put': drivers/scsi/ufs/ufshcd.c:258:16: error: 'struct dev_pm_info' has no member named 'runtime_status' if (dev->power.runtime_status == RPM_RESUMING || ^ drivers/scsi/ufs/ufshcd.c:259:16: error: 'struct dev_pm_info' has no member named 'runtime_status' dev->power.runtime_status == RPM_SUSPENDING) ^ vim +246 drivers/scsi/ufs/ufshcd.c 242 243 static void ufshcd_pm_runtime_get(struct device *dev) 244 { 245 // Don't trigger PM events while in transition states > 246 if (dev->power.runtime_status == RPM_RESUMING || 247 dev->power.runtime_status == RPM_SUSPENDING) 248 pm_runtime_get_noresume(dev); 249 else 250 pm_runtime_get_sync(dev); 251 } 252 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
[PATCH] scsi: ufs: Fix Runtime PM
From: Michał Potomski Recent testing of Runtime PM for UFS has shown it's not working as intended. To acheive fully working Runtime PM, first we have to put back scsi_device autopm reference counter. Existing implementation was prone to races and not working for tranfsers to sleeping devices. This commit aims to fix this to acheive fully working environment. Due to runtime PM being previously disabled by not putting scsi_device autopm counter, the Runtime PM is set to be forbidden as default, to not cause problems with hosts and devices, which do not fully support different Device and Link states. It can be still enabled through sysFS power/control attribute. Signed-off-by: Michał Potomski --- drivers/scsi/ufs/ufshcd-pci.c | 4 +++- drivers/scsi/ufs/ufshcd.c | 55 ++- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 925b0ec7ec54..4fffb1123876 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_drvdata(pdev, hba); + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - pm_runtime_allow(&pdev->dev); + pm_runtime_forbid(&pdev->dev); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 011c3369082c..e7c7ed9bf8a5 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -240,6 +240,28 @@ static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) return tag >= 0 && tag < hba->nutrs; } +static void ufshcd_pm_runtime_get(struct device *dev) +{ + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) + pm_runtime_get_noresume(dev); + else + pm_runtime_get_sync(dev); +} + +static void ufshcd_pm_runtime_put(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + + // Don't trigger PM events while in transition states + if (dev->power.runtime_status == RPM_RESUMING || + dev->power.runtime_status == RPM_SUSPENDING) + pm_runtime_put_noidle(dev); + else + pm_runtime_put_autosuspend(dev); +} + static inline int ufshcd_enable_irq(struct ufs_hba *hba) { int ret = 0; @@ -1345,7 +1367,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, if (value == hba->clk_scaling.is_allowed) goto out; - pm_runtime_get_sync(hba->dev); + ufshcd_pm_runtime_get(hba->dev); ufshcd_hold(hba, false); cancel_work_sync(&hba->clk_scaling.suspend_work); @@ -1364,7 +1386,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, } ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); + ufshcd_pm_runtime_put(hba->dev); out: return count; } @@ -1948,6 +1970,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) unsigned long flags; ufshcd_hold(hba, false); + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); @@ -1959,6 +1982,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) mutex_unlock(&hba->uic_cmd_mutex); + ufshcd_pm_runtime_put(hba->dev); ufshcd_release(hba); return ret; } @@ -2345,6 +2369,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) clear_bit_unlock(tag, &hba->lrb_in_use); goto out; } + ufshcd_pm_runtime_get(hba->dev); WARN_ON(hba->clk_gating.state != CLKS_ON); lrbp = &hba->lrb[tag]; @@ -3555,6 +3580,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) int ret; bool reenable_intr = false; + ufshcd_pm_runtime_get(hba->dev); mutex_lock(&hba->uic_cmd_mutex); init_completion(&uic_async_done); ufshcd_add_delay_before_dme_cmd(hba); @@ -3609,6 +3635,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); spin_unlock_irqrestore(hba->host->host_lock, flags); mutex_unlock(&hba->uic_cmd_mutex); + ufshcd_pm_runtime_put(hba->dev); return ret; } @@ -4386,6 +4413,7 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX); + scsi_autopm_put_device(sdev); return 0; } @@ -4622,6 +4650,7 @@ static void __ufshcd_transfer_req_compl(struct u