From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Huang Ying <ying.huang@intel.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
linux-pm@vger.kernel.org, Alan Stern <stern@rowland.harvard.edu>
Subject: Re: [BUGFIX -v2 3/4] PCI/PM: Fix config reg access for D3cold and bridge suspending
Date: Mon, 6 Aug 2012 13:11:15 +0200 [thread overview]
Message-ID: <201208061311.15431.rjw@sisk.pl> (raw)
In-Reply-To: <1344216870-21105-4-git-send-email-ying.huang@intel.com>
On Monday, August 06, 2012, Huang Ying wrote:
> This patch fixes the following bug:
>
> http://marc.info/?l=linux-pci&m=134338059022620&w=2
>
> Where lspci does not work properly if a device and the corresponding
> parent bridge (such as PCIe port) is suspended. This is because the
> device configuration space registers will be not accessible if the
> corresponding parent bridge is suspended or the device is put into
> D3cold state.
>
> To solve the issue, the bridge/PCIe port connected to the device is
> put into active state before read/write configuration space registers.
> If the device is in D3cold state, it will be put into active state
> too.
>
> To avoid resume/suspend PCIe port for each configuration register
> read/write, a small delay is added before the PCIe port to go
> suspended.
>
> Reported-by: Bjorn Mork <bjorn@mork.no>
> Signed-off-by: Huang Ying <ying.huang@intel.com>
> ---
> drivers/pci/pci-sysfs.c | 37 +++++++++++++++++++++++++++++++++++++
> drivers/pci/pcie/portdrv_pci.c | 9 +++++++++
> 2 files changed, 46 insertions(+)
>
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -458,6 +458,35 @@ boot_vga_show(struct device *dev, struct
> }
> struct device_attribute vga_attr = __ATTR_RO(boot_vga);
>
> +static void
> +pci_config_pm_runtime_get(struct pci_dev *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *parent = dev->parent;
> +
> + if (parent)
> + pm_runtime_get_sync(parent);
> + pm_runtime_get_noresume(dev);
> + /*
> + * pdev->current_state is set to PCI_D3cold during suspending,
> + * so wait until suspending completes
> + */
> + pm_runtime_barrier(dev);
> + if (pdev->current_state == PCI_D3cold)
> + pm_runtime_resume(dev);
I think it would be good to write a comment explaining why we avoid
doing pm_runtime_get_sync(dev) here.
> +}
> +
> +static void
> +pci_config_pm_runtime_put(struct pci_dev *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *parent = dev->parent;
> +
> + pm_runtime_put(dev);
> + if (parent)
> + pm_runtime_put_sync(parent);
> +}
> +
> static ssize_t
> pci_read_config(struct file *filp, struct kobject *kobj,
> struct bin_attribute *bin_attr,
> @@ -484,6 +513,8 @@ pci_read_config(struct file *filp, struc
> size = count;
> }
>
> + pci_config_pm_runtime_get(dev);
> +
> if ((off & 1) && size) {
> u8 val;
> pci_user_read_config_byte(dev, off, &val);
> @@ -529,6 +560,8 @@ pci_read_config(struct file *filp, struc
> --size;
> }
>
> + pci_config_pm_runtime_put(dev);
> +
> return count;
> }
>
> @@ -549,6 +582,8 @@ pci_write_config(struct file* filp, stru
> count = size;
> }
>
> + pci_config_pm_runtime_get(dev);
> +
> if ((off & 1) && size) {
> pci_user_write_config_byte(dev, off, data[off - init_off]);
> off++;
> @@ -587,6 +622,8 @@ pci_write_config(struct file* filp, stru
> --size;
> }
>
> + pci_config_pm_runtime_put(dev);
> +
> return count;
> }
>
> --- a/drivers/pci/pcie/portdrv_pci.c
> +++ b/drivers/pci/pcie/portdrv_pci.c
> @@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(stru
> {
> return 0;
> }
> +
> +static int pcie_port_runtime_idle(struct device *dev)
> +{
> + /* Delay for a short while to prevent too frequent suspend/resume */
> + pm_schedule_suspend(dev, 10);
> + return -EBUSY;
> +}
> #else
> #define pcie_port_runtime_suspend NULL
> #define pcie_port_runtime_resume NULL
> +#define pcie_port_runtime_idle NULL
> #endif
>
> static const struct dev_pm_ops pcie_portdrv_pm_ops = {
> @@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_port
> .resume_noirq = pcie_port_resume_noirq,
> .runtime_suspend = pcie_port_runtime_suspend,
> .runtime_resume = pcie_port_runtime_resume,
> + .runtime_idle = pcie_port_runtime_idle,
> };
>
> #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
Thanks,
Rafael
next prev parent reply other threads:[~2012-08-06 11:05 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-06 1:34 [PATCH -v2 0/4] PCI/PM: PCI D3cold support fixes for 3.6-rc1 Huang Ying
2012-08-06 1:34 ` [BUGFIX -v2 1/4] PCI/PM: enable D3/D3cold by default for most devices Huang Ying
2012-08-06 1:34 ` [BUGFIX -v2 2/4] PCI/PM: Keep parent bridge active when probing device Huang Ying
2012-08-06 1:34 ` [BUGFIX -v2 3/4] PCI/PM: Fix config reg access for D3cold and bridge suspending Huang Ying
2012-08-06 11:11 ` Rafael J. Wysocki [this message]
2012-08-06 1:34 ` [PATCH -v2 4/4] PCI/PM: Add ABI document for sysfs file d3cold_allowed Huang Ying
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=201208061311.15431.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=bhelgaas@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=stern@rowland.harvard.edu \
--cc=ying.huang@intel.com \
/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.