linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending
@ 2012-10-25  1:36 Huang Ying
  2012-10-25 20:27 ` Rafael J. Wysocki
  2012-11-02 16:38 ` Bjorn Helgaas
  0 siblings, 2 replies; 5+ messages in thread
From: Huang Ying @ 2012-10-25  1:36 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel, linux-pci, linux-pm, Rafael J. Wysocki, Huang Ying,
	stable

In

  https://bugzilla.kernel.org/show_bug.cgi?id=48981

Peter reported that /proc/bus/pci/??/??.? does not works for 3.6.
This is 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.

This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
issue.  So the function used to solve sysfs issue is used to solve
this issue.

Cc: stable@vger.kernel.org
Reported-by: Peter <lekensteyn@gmail.com>
Signed-off-by: Huang Ying <ying.huang@intel.com>
---
 drivers/pci/pci-sysfs.c |   34 ----------------------------------
 drivers/pci/pci.c       |   32 ++++++++++++++++++++++++++++++++
 drivers/pci/pci.h       |    2 ++
 drivers/pci/proc.c      |    8 ++++++++
 4 files changed, 42 insertions(+), 34 deletions(-)

--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -458,40 +458,6 @@ 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);
-	/*
-	 * Only need to resume devices in D3cold, because config
-	 * registers are still accessible for devices suspended but
-	 * not in D3cold.
-	 */
-	if (pdev->current_state == PCI_D3cold)
-		pm_runtime_resume(dev);
-}
-
-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,
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *de
 }
 EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 
+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);
+	/*
+	 * Only need to resume devices in D3cold, because config
+	 * registers are still accessible for devices suspended but
+	 * not in D3cold.
+	 */
+	if (pdev->current_state == PCI_D3cold)
+		pm_runtime_resume(dev);
+}
+
+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);
+}
+
 /**
  * pci_pm_init - Initialize PM functions of given PCI device
  * @dev: PCI device to handle.
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s
 extern int pci_finish_runtime_suspend(struct pci_dev *dev);
 extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
 extern void pci_wakeup_bus(struct pci_bus *bus);
+extern void pci_config_pm_runtime_get(struct pci_dev *dev);
+extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
 extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha
 	if (!access_ok(VERIFY_WRITE, buf, cnt))
 		return -EINVAL;
 
+	pci_config_pm_runtime_get(dev);
+
 	if ((pos & 1) && cnt) {
 		unsigned char val;
 		pci_user_read_config_byte(dev, pos, &val);
@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha
 		cnt--;
 	}
 
+	pci_config_pm_runtime_put(dev);
+
 	*ppos = pos;
 	return nbytes;
 }
@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co
 	if (!access_ok(VERIFY_READ, buf, cnt))
 		return -EINVAL;
 
+	pci_config_pm_runtime_get(dev);
+
 	if ((pos & 1) && cnt) {
 		unsigned char val;
 		__get_user(val, buf);
@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co
 		cnt--;
 	}
 
+	pci_config_pm_runtime_put(dev);
+
 	*ppos = pos;
 	i_size_write(ino, dp->size);
 	return nbytes;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending
  2012-10-25  1:36 [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending Huang Ying
@ 2012-10-25 20:27 ` Rafael J. Wysocki
  2012-11-02 16:38 ` Bjorn Helgaas
  1 sibling, 0 replies; 5+ messages in thread
From: Rafael J. Wysocki @ 2012-10-25 20:27 UTC (permalink / raw)
  To: Huang Ying; +Cc: Bjorn Helgaas, linux-kernel, linux-pci, linux-pm, stable

On Thursday, October 25, 2012 09:36:03 AM Huang Ying wrote:
> In
> 
>   https://bugzilla.kernel.org/show_bug.cgi?id=48981
> 
> Peter reported that /proc/bus/pci/??/??.? does not works for 3.6.
> This is 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.
> 
> This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
> issue.  So the function used to solve sysfs issue is used to solve
> this issue.
> 
> Cc: stable@vger.kernel.org
> Reported-by: Peter <lekensteyn@gmail.com>
> Signed-off-by: Huang Ying <ying.huang@intel.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> ---
>  drivers/pci/pci-sysfs.c |   34 ----------------------------------
>  drivers/pci/pci.c       |   32 ++++++++++++++++++++++++++++++++
>  drivers/pci/pci.h       |    2 ++
>  drivers/pci/proc.c      |    8 ++++++++
>  4 files changed, 42 insertions(+), 34 deletions(-)
> 
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -458,40 +458,6 @@ 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);
> -	/*
> -	 * Only need to resume devices in D3cold, because config
> -	 * registers are still accessible for devices suspended but
> -	 * not in D3cold.
> -	 */
> -	if (pdev->current_state == PCI_D3cold)
> -		pm_runtime_resume(dev);
> -}
> -
> -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,
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *de
>  }
>  EXPORT_SYMBOL_GPL(pci_dev_run_wake);
>  
> +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);
> +	/*
> +	 * Only need to resume devices in D3cold, because config
> +	 * registers are still accessible for devices suspended but
> +	 * not in D3cold.
> +	 */
> +	if (pdev->current_state == PCI_D3cold)
> +		pm_runtime_resume(dev);
> +}
> +
> +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);
> +}
> +
>  /**
>   * pci_pm_init - Initialize PM functions of given PCI device
>   * @dev: PCI device to handle.
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s
>  extern int pci_finish_runtime_suspend(struct pci_dev *dev);
>  extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
>  extern void pci_wakeup_bus(struct pci_bus *bus);
> +extern void pci_config_pm_runtime_get(struct pci_dev *dev);
> +extern void pci_config_pm_runtime_put(struct pci_dev *dev);
>  extern void pci_pm_init(struct pci_dev *dev);
>  extern void platform_pci_wakeup_init(struct pci_dev *dev);
>  extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha
>  	if (!access_ok(VERIFY_WRITE, buf, cnt))
>  		return -EINVAL;
>  
> +	pci_config_pm_runtime_get(dev);
> +
>  	if ((pos & 1) && cnt) {
>  		unsigned char val;
>  		pci_user_read_config_byte(dev, pos, &val);
> @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha
>  		cnt--;
>  	}
>  
> +	pci_config_pm_runtime_put(dev);
> +
>  	*ppos = pos;
>  	return nbytes;
>  }
> @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co
>  	if (!access_ok(VERIFY_READ, buf, cnt))
>  		return -EINVAL;
>  
> +	pci_config_pm_runtime_get(dev);
> +
>  	if ((pos & 1) && cnt) {
>  		unsigned char val;
>  		__get_user(val, buf);
> @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co
>  		cnt--;
>  	}
>  
> +	pci_config_pm_runtime_put(dev);
> +
>  	*ppos = pos;
>  	i_size_write(ino, dp->size);
>  	return nbytes;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending
  2012-10-25  1:36 [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending Huang Ying
  2012-10-25 20:27 ` Rafael J. Wysocki
@ 2012-11-02 16:38 ` Bjorn Helgaas
  2012-11-02 20:25   ` Rafael J. Wysocki
  1 sibling, 1 reply; 5+ messages in thread
From: Bjorn Helgaas @ 2012-11-02 16:38 UTC (permalink / raw)
  To: Huang Ying; +Cc: linux-kernel, linux-pci, linux-pm, Rafael J. Wysocki, stable

On Wed, Oct 24, 2012 at 7:36 PM, Huang Ying <ying.huang@intel.com> wrote:
> In
>
>   https://bugzilla.kernel.org/show_bug.cgi?id=48981
>
> Peter reported that /proc/bus/pci/??/??.? does not works for 3.6.
> This is 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.
>
> This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
> issue.  So the function used to solve sysfs issue is used to solve
> this issue.
>
> Cc: stable@vger.kernel.org
> Reported-by: Peter <lekensteyn@gmail.com>

Is this bug the same as the one originally reported by Forrest Loomis
(original reporter of bug 48981)?  And
https://bugzilla.kernel.org/show_bug.cgi?id=49031, reported by Micael
Dias (Rafael marked 49031 as a duplicate of 48981)?

If so, I'll mention Forrest and Micael and bug 49031 here as well.

> Signed-off-by: Huang Ying <ying.huang@intel.com>
> ---
>  drivers/pci/pci-sysfs.c |   34 ----------------------------------
>  drivers/pci/pci.c       |   32 ++++++++++++++++++++++++++++++++
>  drivers/pci/pci.h       |    2 ++
>  drivers/pci/proc.c      |    8 ++++++++
>  4 files changed, 42 insertions(+), 34 deletions(-)
>
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -458,40 +458,6 @@ 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);
> -       /*
> -        * Only need to resume devices in D3cold, because config
> -        * registers are still accessible for devices suspended but
> -        * not in D3cold.
> -        */
> -       if (pdev->current_state == PCI_D3cold)
> -               pm_runtime_resume(dev);
> -}
> -
> -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,
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *de
>  }
>  EXPORT_SYMBOL_GPL(pci_dev_run_wake);
>
> +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);
> +       /*
> +        * Only need to resume devices in D3cold, because config
> +        * registers are still accessible for devices suspended but
> +        * not in D3cold.
> +        */
> +       if (pdev->current_state == PCI_D3cold)
> +               pm_runtime_resume(dev);
> +}
> +
> +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);
> +}
> +
>  /**
>   * pci_pm_init - Initialize PM functions of given PCI device
>   * @dev: PCI device to handle.
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s
>  extern int pci_finish_runtime_suspend(struct pci_dev *dev);
>  extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
>  extern void pci_wakeup_bus(struct pci_bus *bus);
> +extern void pci_config_pm_runtime_get(struct pci_dev *dev);
> +extern void pci_config_pm_runtime_put(struct pci_dev *dev);
>  extern void pci_pm_init(struct pci_dev *dev);
>  extern void platform_pci_wakeup_init(struct pci_dev *dev);
>  extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha
>         if (!access_ok(VERIFY_WRITE, buf, cnt))
>                 return -EINVAL;
>
> +       pci_config_pm_runtime_get(dev);
> +
>         if ((pos & 1) && cnt) {
>                 unsigned char val;
>                 pci_user_read_config_byte(dev, pos, &val);
> @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha
>                 cnt--;
>         }
>
> +       pci_config_pm_runtime_put(dev);
> +
>         *ppos = pos;
>         return nbytes;
>  }
> @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co
>         if (!access_ok(VERIFY_READ, buf, cnt))
>                 return -EINVAL;
>
> +       pci_config_pm_runtime_get(dev);
> +
>         if ((pos & 1) && cnt) {
>                 unsigned char val;
>                 __get_user(val, buf);
> @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co
>                 cnt--;
>         }
>
> +       pci_config_pm_runtime_put(dev);
> +
>         *ppos = pos;
>         i_size_write(ino, dp->size);
>         return nbytes;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending
  2012-11-02 16:38 ` Bjorn Helgaas
@ 2012-11-02 20:25   ` Rafael J. Wysocki
  2012-11-05 22:10     ` Bjorn Helgaas
  0 siblings, 1 reply; 5+ messages in thread
From: Rafael J. Wysocki @ 2012-11-02 20:25 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: Huang Ying, linux-kernel, linux-pci, linux-pm, stable

On Friday, November 02, 2012 10:38:43 AM Bjorn Helgaas wrote:
> On Wed, Oct 24, 2012 at 7:36 PM, Huang Ying <ying.huang@intel.com> wrote:
> > In
> >
> >   https://bugzilla.kernel.org/show_bug.cgi?id=48981
> >
> > Peter reported that /proc/bus/pci/??/??.? does not works for 3.6.
> > This is 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.
> >
> > This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
> > issue.  So the function used to solve sysfs issue is used to solve
> > this issue.
> >
> > Cc: stable@vger.kernel.org
> > Reported-by: Peter <lekensteyn@gmail.com>
> 
> Is this bug the same as the one originally reported by Forrest Loomis
> (original reporter of bug 48981)?  And
> https://bugzilla.kernel.org/show_bug.cgi?id=49031, reported by Micael
> Dias (Rafael marked 49031 as a duplicate of 48981)?
> 
> If so, I'll mention Forrest and Micael and bug 49031 here as well.

No, it's not.  That one turned out to be a duplicate of bko#48981.

Thanks,
Rafael


> > Signed-off-by: Huang Ying <ying.huang@intel.com>
> > ---
> >  drivers/pci/pci-sysfs.c |   34 ----------------------------------
> >  drivers/pci/pci.c       |   32 ++++++++++++++++++++++++++++++++
> >  drivers/pci/pci.h       |    2 ++
> >  drivers/pci/proc.c      |    8 ++++++++
> >  4 files changed, 42 insertions(+), 34 deletions(-)
> >
> > --- a/drivers/pci/pci-sysfs.c
> > +++ b/drivers/pci/pci-sysfs.c
> > @@ -458,40 +458,6 @@ 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);
> > -       /*
> > -        * Only need to resume devices in D3cold, because config
> > -        * registers are still accessible for devices suspended but
> > -        * not in D3cold.
> > -        */
> > -       if (pdev->current_state == PCI_D3cold)
> > -               pm_runtime_resume(dev);
> > -}
> > -
> > -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,
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *de
> >  }
> >  EXPORT_SYMBOL_GPL(pci_dev_run_wake);
> >
> > +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);
> > +       /*
> > +        * Only need to resume devices in D3cold, because config
> > +        * registers are still accessible for devices suspended but
> > +        * not in D3cold.
> > +        */
> > +       if (pdev->current_state == PCI_D3cold)
> > +               pm_runtime_resume(dev);
> > +}
> > +
> > +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);
> > +}
> > +
> >  /**
> >   * pci_pm_init - Initialize PM functions of given PCI device
> >   * @dev: PCI device to handle.
> > --- a/drivers/pci/pci.h
> > +++ b/drivers/pci/pci.h
> > @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s
> >  extern int pci_finish_runtime_suspend(struct pci_dev *dev);
> >  extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
> >  extern void pci_wakeup_bus(struct pci_bus *bus);
> > +extern void pci_config_pm_runtime_get(struct pci_dev *dev);
> > +extern void pci_config_pm_runtime_put(struct pci_dev *dev);
> >  extern void pci_pm_init(struct pci_dev *dev);
> >  extern void platform_pci_wakeup_init(struct pci_dev *dev);
> >  extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
> > --- a/drivers/pci/proc.c
> > +++ b/drivers/pci/proc.c
> > @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha
> >         if (!access_ok(VERIFY_WRITE, buf, cnt))
> >                 return -EINVAL;
> >
> > +       pci_config_pm_runtime_get(dev);
> > +
> >         if ((pos & 1) && cnt) {
> >                 unsigned char val;
> >                 pci_user_read_config_byte(dev, pos, &val);
> > @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha
> >                 cnt--;
> >         }
> >
> > +       pci_config_pm_runtime_put(dev);
> > +
> >         *ppos = pos;
> >         return nbytes;
> >  }
> > @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co
> >         if (!access_ok(VERIFY_READ, buf, cnt))
> >                 return -EINVAL;
> >
> > +       pci_config_pm_runtime_get(dev);
> > +
> >         if ((pos & 1) && cnt) {
> >                 unsigned char val;
> >                 __get_user(val, buf);
> > @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co
> >                 cnt--;
> >         }
> >
> > +       pci_config_pm_runtime_put(dev);
> > +
> >         *ppos = pos;
> >         i_size_write(ino, dp->size);
> >         return nbytes;
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending
  2012-11-02 20:25   ` Rafael J. Wysocki
@ 2012-11-05 22:10     ` Bjorn Helgaas
  0 siblings, 0 replies; 5+ messages in thread
From: Bjorn Helgaas @ 2012-11-05 22:10 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Huang Ying, linux-kernel, linux-pci, linux-pm, stable

On Fri, Nov 2, 2012 at 2:25 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Friday, November 02, 2012 10:38:43 AM Bjorn Helgaas wrote:
>> On Wed, Oct 24, 2012 at 7:36 PM, Huang Ying <ying.huang@intel.com> wrote:
>> > In
>> >
>> >   https://bugzilla.kernel.org/show_bug.cgi?id=48981
>> >
>> > Peter reported that /proc/bus/pci/??/??.? does not works for 3.6.
>> > This is 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.
>> >
>> > This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
>> > issue.  So the function used to solve sysfs issue is used to solve
>> > this issue.
>> >
>> > Cc: stable@vger.kernel.org
>> > Reported-by: Peter <lekensteyn@gmail.com>
>>
>> Is this bug the same as the one originally reported by Forrest Loomis
>> (original reporter of bug 48981)?  And
>> https://bugzilla.kernel.org/show_bug.cgi?id=49031, reported by Micael
>> Dias (Rafael marked 49031 as a duplicate of 48981)?
>>
>> If so, I'll mention Forrest and Micael and bug 49031 here as well.
>
> No, it's not.  That one turned out to be a duplicate of bko#48981.

I applied this to my for-linus branch as v3.7 material.  Thanks!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-11-05 22:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-25  1:36 [BUGFIX] PCI/PM: Fix proc config reg access for D3cold and bridge suspending Huang Ying
2012-10-25 20:27 ` Rafael J. Wysocki
2012-11-02 16:38 ` Bjorn Helgaas
2012-11-02 20:25   ` Rafael J. Wysocki
2012-11-05 22:10     ` Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).