All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Feiyang Chen <chris.chenfeiyang@gmail.com>
Cc: Feiyang Chen <chenfeiyang@loongson.cn>,
	bhelgaas@google.com, rafael.j.wysocki@intel.com,
	mika.westerberg@linux.intel.com, anders.roxell@linaro.org,
	linux-pci@vger.kernel.org, linux-pm@vger.kernel.org,
	guyinggang@loongson.cn, siyanteng@loongson.cn,
	chenhuacai@loongson.cn, loongson-kernel@lists.loongnix.cn,
	"Rafael J . Wysocki" <rafael@kernel.org>
Subject: Re: [PATCH v3] PCI/PM: Only read PCI_PM_CTRL register when available
Date: Tue, 29 Aug 2023 11:52:18 -0500	[thread overview]
Message-ID: <20230829165218.GA800705@bhelgaas> (raw)
In-Reply-To: <20230825212507.GA627427@bhelgaas>

On Fri, Aug 25, 2023 at 04:25:07PM -0500, Bjorn Helgaas wrote:
> On Fri, Aug 25, 2023 at 11:57:00AM +0800, Feiyang Chen wrote:
> > On Fri, Aug 25, 2023 at 5:59 AM Bjorn Helgaas <helgaas@kernel.org> wrote:
> > > On Thu, Aug 24, 2023 at 09:37:38AM +0800, Feiyang Chen wrote:
> > > > When the current state is already PCI_D0, pci_power_up() will return
> > > > 0 even though dev->pm_cap is not set. In that case, we should not
> > > > read the PCI_PM_CTRL register in pci_set_full_power_state().
> > > >
> > > > There is nothing more needs to be done below in that case.
> > > > Additionally, pci_power_up() has two callers only and the other one
> > > > ignores the return value, so we can safely move the current state
> > > > check from pci_power_up() to pci_set_full_power_state().
> > >
> > > Does this fix a bug?  I guess it does, because previously
> > > pci_set_full_power_state() did a config read at 0 + PCI_PM_CTRL, i.e.,
> > > offset 4, which is actually PCI_COMMAND, and set dev->current_state
> > > based on that.  So dev->current_state is now junk, right?
> > 
> > Yes.
> > 
> > > This might account for some "Refused to change power state from %s to D0"
> > > messages.
> > >
> > > How did you find this?  It's nice if we can mention a symptom so
> > > people can connect the problem with this fix.
> > 
> > We are attempting to add MSI support for our stmmac driver, but the
> > pci_alloc_irq_vectors() function always fails.
> > After looking into it more, we came across the message "Refused to
> > change power state from D3hot to D0" :)
> 
> So I guess this device doesn't have a PM Capability at all?  Can you
> collect the "sudo lspci -vv" output?  The PM Capability is required
> for all PCIe devices, so maybe this is a conventional PCI device?
> 
> > > This sounds like something that probably should have a stable tag?
> > 
> > Do I need to include the symptom and Cc in the commit message and
> > then send v4?
> 
> > > > Fixes: e200904b275c ("PCI/PM: Split pci_power_up()")
> > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > Reviewed-by: Rafael J. Wysocki <rafael@kernel.org>
> > > > ---
> > > >  drivers/pci/pci.c | 9 +++++----
> > > >  1 file changed, 5 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > index 60230da957e0..7e90ab7b47a1 100644
> > > > --- a/drivers/pci/pci.c
> > > > +++ b/drivers/pci/pci.c
> > > > @@ -1242,9 +1242,6 @@ int pci_power_up(struct pci_dev *dev)
> > > >               else
> > > >                       dev->current_state = state;
> > > >
> > > > -             if (state == PCI_D0)
> > > > -                     return 0;
> > > > -
> > > >               return -EIO;
> > > >       }
> > > >
> > > > @@ -1302,8 +1299,12 @@ static int pci_set_full_power_state(struct pci_dev *dev)
> > > >       int ret;
> > > >
> > > >       ret = pci_power_up(dev);
> > > > -     if (ret < 0)
> > > > +     if (ret < 0) {
> > > > +             if (dev->current_state == PCI_D0)
> > > > +                     return 0;
> > > > +
> > > >               return ret;
> > > > +     }
> > > >       pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
> > > >       dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK;
> 
> One thing that makes me hesitate a little bit is that we rely on the
> failure return from pci_power_up() to guard the dev->pm_cap usage.
> That's slightly obscure, and I liked the way the v1 patch made it
> explicit.
> 
> And it seems slightly weird that when there's no PM cap,
> pci_power_up() always returns failure even if the platform was able to
> put the device in D0.
> 
> Anyway, here's a proposal for commit log and updated comment for
> pci_power_up():

I applied the patch below on pci/pm for v6.6.

> commit 5694ba13b004 ("PCI/PM: Only read PCI_PM_CTRL register when available")
> Author: Feiyang Chen <chenfeiyang@loongson.cn>
> Date:   Thu Aug 24 09:37:38 2023 +0800
> 
>     PCI/PM: Only read PCI_PM_CTRL register when available
>     
>     For a device with no Power Management Capability, pci_power_up() previously
>     returned 0 (success) if the platform was able to put the device in D0,
>     which led to pci_set_full_power_state() trying to read PCI_PM_CTRL, even
>     though it doesn't exist.
>     
>     Since dev->pm_cap == 0 in this case, pci_set_full_power_state() actually
>     read the wrong register, interpreted it as PCI_PM_CTRL, and corrupted
>     dev->current_state.  This led to messages like this in some cases:
>     
>       pci 0000:01:00.0: Refused to change power state from D3hot to D0
>     
>     To prevent this, make pci_power_up() always return a negative failure code
>     if the device lacks a Power Management Capability, even if non-PCI platform
>     power management has been able to put the device in D0.  The failure will
>     prevent pci_set_full_power_state() from trying to access PCI_PM_CTRL.
>     
>     Fixes: e200904b275c ("PCI/PM: Split pci_power_up()")
>     Link: https://lore.kernel.org/r/20230824013738.1894965-1-chenfeiyang@loongson.cn
>     Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>     Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>     Reviewed-by: "Rafael J. Wysocki" <rafael@kernel.org>
>     Cc: stable@vger.kernel.org	# v5.19+
> 
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 60230da957e0..39728196e295 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1226,6 +1226,10 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
>   *
>   * On success, return 0 or 1, depending on whether or not it is necessary to
>   * restore the device's BARs subsequently (1 is returned in that case).
> + *
> + * On failure, return a negative error code.  Always return failure if @dev
> + * lacks a Power Management Capability, even if the platform was able to
> + * put the device in D0 via non-PCI means.
>   */
>  int pci_power_up(struct pci_dev *dev)
>  {
> @@ -1242,9 +1246,6 @@ int pci_power_up(struct pci_dev *dev)
>  		else
>  			dev->current_state = state;
>  
> -		if (state == PCI_D0)
> -			return 0;
> -
>  		return -EIO;
>  	}
>  
> @@ -1302,8 +1303,12 @@ static int pci_set_full_power_state(struct pci_dev *dev)
>  	int ret;
>  
>  	ret = pci_power_up(dev);
> -	if (ret < 0)
> +	if (ret < 0) {
> +		if (dev->current_state == PCI_D0)
> +			return 0;
> +
>  		return ret;
> +	}
>  
>  	pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
>  	dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK;

      parent reply	other threads:[~2023-08-29 16:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-24  1:37 [PATCH v3] PCI/PM: Only read PCI_PM_CTRL register when available Feiyang Chen
2023-08-24 21:59 ` Bjorn Helgaas
2023-08-25  3:57   ` Feiyang Chen
2023-08-25 21:25     ` Bjorn Helgaas
2023-08-28 12:44       ` Yanteng Si
2023-08-29 16:52       ` Bjorn Helgaas [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230829165218.GA800705@bhelgaas \
    --to=helgaas@kernel.org \
    --cc=anders.roxell@linaro.org \
    --cc=bhelgaas@google.com \
    --cc=chenfeiyang@loongson.cn \
    --cc=chenhuacai@loongson.cn \
    --cc=chris.chenfeiyang@gmail.com \
    --cc=guyinggang@loongson.cn \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=loongson-kernel@lists.loongnix.cn \
    --cc=mika.westerberg@linux.intel.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rafael@kernel.org \
    --cc=siyanteng@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.