All of lore.kernel.org
 help / color / mirror / Atom feed
From: Huang Ying <ying.huang@intel.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: "Bjørn Mork" <bjorn@mork.no>,
	"huang ying" <huang.ying.caritas@gmail.com>,
	"Rafael J. Wysocki" <rjw@sisk.pl>,
	"Zheng Yan" <zheng.z.yan@intel.com>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	linux-pci@vger.kernel.org, linux-usb@vger.kernel.org
Subject: Re: bisected regression, v3.5 -> next-20120724: PCI PM causes USB hotplug failure
Date: Tue, 31 Jul 2012 11:18:42 +0800	[thread overview]
Message-ID: <1343704722.2591.11.camel@yhuang-dev> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1207301017190.1386-100000@iolanthe.rowland.org>

On Mon, 2012-07-30 at 10:19 -0400, Alan Stern wrote:
> On Mon, 30 Jul 2012, Huang Ying wrote:
> 
> > > Yup, that worked in the quick test I just did.
> > > 
> > >  lspci reading the device config will still not wake the bridge, but I
> > > assume that is intentional?  But loading the device driver now wakes
> > > both the bridge and the device, so that works.
> > 
> > Do you have time to test the following patch to fix the lspci issue?
> > 
> > Subject: [BUGFIX] PCI/PM: Keep parent bridge active when read/write config reg
> > 
> > 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.
> > 
> > To solve the issue, the bridge/PCIe port connected to the device is
> > put into active state before read/write configuration space registers.
> 
> What happens when you run lspci and the device is in D3cold?  Then even 
> if the parent bridge is active, lspci will still fail.
> 
> It seems that in this case you need to resume the device itself, not 
> just its parent.

How about the following patch?

Subject: [BUGFIX] PCI/PM: Keep parent bridge active when read/write config reg

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        |   68 ++++++++++++++++++++++++++++++-----------
 drivers/pci/pcie/portdrv_pci.c |    9 +++++
 2 files changed, 60 insertions(+), 17 deletions(-)

--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -463,15 +463,17 @@ pci_read_config(struct file *filp, struc
 		struct bin_attribute *bin_attr,
 		char *buf, loff_t off, size_t count)
 {
-	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+	struct device *dev = container_of(kobj,struct device,kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct device *parent = dev->parent;
 	unsigned int size = 64;
 	loff_t init_off = off;
 	u8 *data = (u8*) buf;
 
 	/* Several chips lock up trying to read undefined config space */
 	if (security_capable(filp->f_cred, &init_user_ns, CAP_SYS_ADMIN) == 0) {
-		size = dev->cfg_size;
-	} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+		size = pdev->cfg_size;
+	} else if (pdev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 		size = 128;
 	}
 
@@ -484,9 +486,20 @@ pci_read_config(struct file *filp, struc
 		size = count;
 	}
 
+	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);
+
 	if ((off & 1) && size) {
 		u8 val;
-		pci_user_read_config_byte(dev, off, &val);
+		pci_user_read_config_byte(pdev, off, &val);
 		data[off - init_off] = val;
 		off++;
 		size--;
@@ -494,7 +507,7 @@ pci_read_config(struct file *filp, struc
 
 	if ((off & 3) && size > 2) {
 		u16 val;
-		pci_user_read_config_word(dev, off, &val);
+		pci_user_read_config_word(pdev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		off += 2;
@@ -503,7 +516,7 @@ pci_read_config(struct file *filp, struc
 
 	while (size > 3) {
 		u32 val;
-		pci_user_read_config_dword(dev, off, &val);
+		pci_user_read_config_dword(pdev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		data[off - init_off + 2] = (val >> 16) & 0xff;
@@ -514,7 +527,7 @@ pci_read_config(struct file *filp, struc
 
 	if (size >= 2) {
 		u16 val;
-		pci_user_read_config_word(dev, off, &val);
+		pci_user_read_config_word(pdev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		off += 2;
@@ -523,12 +536,16 @@ pci_read_config(struct file *filp, struc
 
 	if (size > 0) {
 		u8 val;
-		pci_user_read_config_byte(dev, off, &val);
+		pci_user_read_config_byte(pdev, off, &val);
 		data[off - init_off] = val;
 		off++;
 		--size;
 	}
 
+	pm_runtime_put(dev);
+	if (parent)
+		pm_runtime_put(parent);
+
 	return count;
 }
 
@@ -537,20 +554,33 @@ pci_write_config(struct file* filp, stru
 		 struct bin_attribute *bin_attr,
 		 char *buf, loff_t off, size_t count)
 {
-	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+	struct device *dev = container_of(kobj,struct device,kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct device *parent = dev->parent;
 	unsigned int size = count;
 	loff_t init_off = off;
 	u8 *data = (u8*) buf;
 
-	if (off > dev->cfg_size)
+	if (off > pdev->cfg_size)
 		return 0;
-	if (off + count > dev->cfg_size) {
-		size = dev->cfg_size - off;
+	if (off + count > pdev->cfg_size) {
+		size = pdev->cfg_size - off;
 		count = size;
 	}
 	
+	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);
+
 	if ((off & 1) && size) {
-		pci_user_write_config_byte(dev, off, data[off - init_off]);
+		pci_user_write_config_byte(pdev, off, data[off - init_off]);
 		off++;
 		size--;
 	}
@@ -558,7 +588,7 @@ pci_write_config(struct file* filp, stru
 	if ((off & 3) && size > 2) {
 		u16 val = data[off - init_off];
 		val |= (u16) data[off - init_off + 1] << 8;
-                pci_user_write_config_word(dev, off, val);
+                pci_user_write_config_word(pdev, off, val);
                 off += 2;
                 size -= 2;
         }
@@ -568,7 +598,7 @@ pci_write_config(struct file* filp, stru
 		val |= (u32) data[off - init_off + 1] << 8;
 		val |= (u32) data[off - init_off + 2] << 16;
 		val |= (u32) data[off - init_off + 3] << 24;
-		pci_user_write_config_dword(dev, off, val);
+		pci_user_write_config_dword(pdev, off, val);
 		off += 4;
 		size -= 4;
 	}
@@ -576,17 +606,21 @@ pci_write_config(struct file* filp, stru
 	if (size >= 2) {
 		u16 val = data[off - init_off];
 		val |= (u16) data[off - init_off + 1] << 8;
-		pci_user_write_config_word(dev, off, val);
+		pci_user_write_config_word(pdev, off, val);
 		off += 2;
 		size -= 2;
 	}
 
 	if (size) {
-		pci_user_write_config_byte(dev, off, data[off - init_off]);
+		pci_user_write_config_byte(pdev, off, data[off - init_off]);
 		off++;
 		--size;
 	}
 
+	pm_runtime_put(dev);
+	if (parent)
+		pm_runtime_put(parent);
+
 	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)



  parent reply	other threads:[~2012-07-31  3:18 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <Pine.LNX.4.44L0.1207241312050.1164-100000@iolanthe.rowland.org>
     [not found] ` <87r4s0opck.fsf@nemi.mork.no>
2012-07-25  4:08   ` bisected regression, v3.5 -> next-20120724: PCI PM causes USB hotplug failure Bjørn Mork
2012-07-25  4:34     ` Huang Ying
2012-07-25  9:58       ` Bjørn Mork
2012-07-25 13:30         ` huang ying
2012-07-25 13:58           ` Bjørn Mork
2012-07-25 18:56             ` Rafael J. Wysocki
2012-07-25 20:02             ` Rafael J. Wysocki
2012-07-25 22:36               ` Bjørn Mork
2012-07-26  2:38                 ` Huang Ying
2012-07-26  2:38               ` Huang Ying
2012-07-26  8:54             ` Huang Ying
2012-07-26 10:35               ` Bjørn Mork
2012-07-26 11:02                 ` Bjørn Mork
2012-07-26 12:04                   ` Bjørn Mork
2012-07-26 15:03                 ` Alan Stern
2012-07-26 16:24                   ` Bjørn Mork
2012-07-27  5:35                 ` Huang Ying
2012-07-27  9:11                   ` Bjørn Mork
2012-07-30  3:15                     ` Huang Ying
2012-07-30  8:08                       ` Bjørn Mork
2012-07-30 13:31                         ` huang ying
2012-07-30 16:57                           ` Bjørn Mork
2012-07-31  0:22                             ` Huang Ying
2012-07-30 14:19                       ` Alan Stern
2012-07-31  0:24                         ` Huang Ying
2012-07-31  3:18                         ` Huang Ying [this message]
2012-07-31 17:07                           ` Alan Stern
2012-07-27 15:03                   ` Alan Stern
2012-07-27 19:11                     ` Rafael J. Wysocki
2012-07-27 19:39                       ` Alan Stern
2012-07-27 19:54                         ` Rafael J. Wysocki
2012-07-28 16:12                           ` Alan Stern
2012-07-28 20:26                             ` Rafael J. Wysocki
2012-07-28 21:12                               ` Alan Stern
2012-07-29 13:55                                 ` Rafael J. Wysocki
2012-07-29 14:55                                   ` Alan Stern
2012-07-29 19:18                                     ` Rafael J. Wysocki
2012-07-31 20:31                                       ` Do we need asynchronous pm_runtime_get()? (was: Re: bisected regression ...) Rafael J. Wysocki
2012-07-31 21:05                                         ` Alan Stern
2012-07-31 21:34                                           ` Rafael J. Wysocki
2012-07-31 21:49                                             ` Rafael J. Wysocki
2012-08-01 14:36                                             ` Alan Stern
2012-08-01 21:24                                               ` Rafael J. Wysocki
2012-08-02 20:16                                                 ` Alan Stern
2012-08-02 21:26                                                   ` Rafael J. Wysocki
2012-08-03  2:20                                                     ` Alan Stern
2012-08-03  3:37                                                       ` Ming Lei
2012-08-03 14:28                                                         ` Alan Stern
2012-08-04 19:47                                                         ` Rafael J. Wysocki
2012-08-04 20:25                                                           ` Alan Stern
2012-08-04 20:48                                                             ` Rafael J. Wysocki
2012-08-04 20:48                                                               ` Alan Stern
2012-08-04 21:15                                                                 ` Rafael J. Wysocki
2012-08-04 22:13                                                                   ` Alan Stern
2012-08-05 15:26                                                                     ` Rafael J. Wysocki
2012-08-06 13:30                                                                       ` Ming Lei
2012-08-06 14:47                                                                         ` Alan Stern
2012-08-07  1:35                                                                           ` Ming Lei
2012-08-07 11:23                                                                             ` Rafael J. Wysocki
2012-08-07 15:14                                                                               ` Ming Lei
2012-08-07 15:42                                                                                 ` Alan Stern
2012-08-07 16:30                                                                                   ` Ming Lei
2012-08-07 20:57                                                                                     ` Rafael J. Wysocki
2012-08-07 20:45                                                                                 ` Rafael J. Wysocki
2012-08-08  2:02                                                                                   ` Ming Lei
2012-08-08 18:42                                                                                     ` Alan Stern
2012-08-08 20:16                                                                                       ` Rafael J. Wysocki
2012-08-09  5:55                                                                                         ` Ming Lei
2012-08-09 10:46                                                                                           ` Rafael J. Wysocki
2012-08-09 10:55                                                                                             ` Ming Lei
2012-08-09 19:41                                                                                               ` Rafael J. Wysocki
2012-08-10  3:19                                                                                                 ` Ming Lei
2012-08-10 20:29                                                                                                   ` Rafael J. Wysocki
2012-08-08 22:27                                                                                     ` Rafael J. Wysocki
2012-08-06 15:48                                                                       ` Alan Stern
2012-08-06 20:30                                                                         ` Rafael J. Wysocki
2012-08-07 12:28                                                                           ` Rafael J. Wysocki
2012-08-07 17:15                                                                             ` Alan Stern
2012-08-07 21:31                                                                               ` Rafael J. Wysocki
2012-08-03 14:05                                                       ` Alan Stern
2012-08-04 20:08                                                         ` Rafael J. Wysocki
2012-08-04 20:42                                                           ` Alan Stern
2012-08-04 20:59                                                             ` Rafael J. Wysocki
2012-08-04 19:35                                                       ` Rafael J. Wysocki
2012-07-29 20:12                                     ` bisected regression, v3.5 -> next-20120724: PCI PM causes USB hotplug failure Jassi Brar
2012-07-29 21:44                                       ` Alan Stern
2012-07-25 19:51           ` [PATCH] PCI / PM: Fix messages printed by acpi_pci_set_power_state() Rafael J. Wysocki
2012-07-25 20:02             ` Alan Stern
2012-07-25 20:48               ` [PATCH][update] " Rafael J. Wysocki

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=1343704722.2591.11.camel@yhuang-dev \
    --to=ying.huang@intel.com \
    --cc=bhelgaas@google.com \
    --cc=bjorn@mork.no \
    --cc=huang.ying.caritas@gmail.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=rjw@sisk.pl \
    --cc=stern@rowland.harvard.edu \
    --cc=zheng.z.yan@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.