public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Shaohua Li <shaohua.li@intel.com>
Cc: linux-acpi@vger.kernel.org, linux-pm@lists.linux-foundation.org,
	dbrownell@users.sourceforge.net
Subject: Re: [RFC 3/5] pci wakeup handler
Date: Sun, 19 Oct 2008 21:50:40 +0200	[thread overview]
Message-ID: <200810192150.41305.rjw@sisk.pl> (raw)
In-Reply-To: <20080911063823.196887408@sli10-desk.sh.intel.com>

On Thursday, 11 of September 2008, Shaohua Li wrote:
> pci subsystem wakeup handler.

Perhaps add a bit more explanation here - what is introduced, why and why this
particular way.

> ---
>  drivers/pci/pci-driver.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci.h      |    6 ++
>  2 files changed, 101 insertions(+)
> 
> Index: linux/drivers/pci/pci-driver.c
> ===================================================================
> --- linux.orig/drivers/pci/pci-driver.c	2008-09-11 10:56:26.000000000 +0800
> +++ linux/drivers/pci/pci-driver.c	2008-09-11 11:15:20.000000000 +0800
> @@ -472,12 +472,106 @@ static int pci_pm_resume_noirq(struct de
>  	return error;
>  }
>  
> +/*
> + * Called when dev is suspected to invoke a wakeup event, return 0 if yes
> + * */

Use kerneldoc format of the comment, please.

> +static bool pci_handle_one_wakeup_event(struct pci_dev *pdev)
> +{

I don't really like that being a boolean function.  I'd make it return 0 on
success and error code on failure.

> +	int pme_pos = pdev->pm_cap;
> +	struct pci_driver *drv = pdev->driver;
> +	u16 pmcsr;
> +	bool spurious = false;
> +
> +	if (pme_pos == 0) {
> +		/*
> +		 * Some USB devices haven't PME, but have specific registers to
> +		 * control wakeup
> +		 */
> +		goto out;
> +	}
> +
> +	/* clear PME status and disable PME to avoid interrupt flood */
> +	pci_read_config_word(pdev, pme_pos + PCI_PM_CTRL, &pmcsr);
> +	if (!(pmcsr & PCI_PM_CTRL_PME_STATUS))
> +		return false;
> +	/* I see spurious PME here, just ignore it for now */
> +	if (!(pmcsr & PCI_PM_CTRL_PME_ENABLE))
> +		spurious = true;
> +	else
> +		pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;

If you do this unconditionally, you'll be able to use pci_pme_active() for it.
Actually, you can use pci_pme_enabled() for checking if PME is enabled
and pci_pme_status() for checking if the PME status is set.  Then,
you can remove the reference to the config space from here and use
those low-level callbacks instead of them. 

> +	pmcsr |= PCI_PM_CTRL_PME_STATUS;
> +	pci_write_config_word(pdev, pme_pos + PCI_PM_CTRL, pmcsr);
> +
> +	if (spurious)
> +		return false;
> +	return true;
> +out:
> +	if (drv && drv->pm && drv->pm->base.wakeup_event)
> +		return drv->pm->base.wakeup_event(&pdev->dev);

I'd move this into the 'if (!pme_pos)' block.  And is this what we want really?
In this case the driver's wakeup_event() will be responsible for checking
if the wake-up event is valid etc.

> +	return false;
> +}
> +

Please add a kerneldoc comment and I don't like bool here too.

> +bool pci_handle_wakeup_event(struct pci_dev *target)
> +{
> +	bool ret;
> +	struct pci_dev *tmp = NULL;
> +	int domain_nr, bus_start, bus_end;
> +
> +	/*
> +	 * @target could be a bridge or a device.
> +	 * PCIe native PME case:
> +	 *   @target is device - @target must be the exact device invoking PME
> +	 *   @target is a root port or pcie-pci bridge - should scan legacy pci
> +	 *	devices under the bridge
> +	 * ACPI GPE case:
> +	 *   @target is device - AML code could clear PME status before this
> +	 *	routine is called, so we can't detect if @target invokes PME.
> +	 *	Let's trust AML code
> +	 *   @target is bridge - scan devices under the bridge
> +	 * So: if target is device, trust the device invokes PME. If target is
> +	 * bridge, scan devices under the bridge and only trust device invokes
> +	 * PME which we can detect
> +	 **/

Change this comment into a kerneldoc one before the function, please.

> +	ret = pci_handle_one_wakeup_event(target);
> +	if (!target->subordinate || (target->is_pcie &&
> +	    target->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
> +	    target->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE)) {
> +		/* always trust the device invokes PME even we can't detect */

More details in the comment, please.

> +		device_receive_wakeup_event(&target->dev);

Why do we use device_receive_wakeup_event() here?

> +		return ret;
> +	}
> +
> +	if (ret)
> +		device_receive_wakeup_event(&target->dev);

And here?  What's the idea?

> +
> +	domain_nr = pci_domain_nr(target->bus);
> +	bus_start = target->subordinate->secondary;
> +	bus_end = target->subordinate->subordinate;
> +	while ((tmp = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tmp)) != NULL) {
> +		if (pci_domain_nr(tmp->bus) == domain_nr &&
> +		   tmp->bus->number >= bus_start &&
> +		   tmp->bus->number <= bus_end) {

This cascading 'if ()'s don't look good.  I'd probably use 'continue'.

> +			if (pci_handle_one_wakeup_event(tmp)) {
> +				ret = true;
> +				device_receive_wakeup_event(&tmp->dev);

What exactly is the role of device_receive_wakeup_event() here?

> +			}
> +		}
> +	}
> +	return ret;
> +}
> +EXPORT_SYMBOL(pci_handle_wakeup_event);
> +
> +static bool pci_pm_wakeup_event(struct device *dev)
> +{
> +	return pci_handle_wakeup_event(to_pci_dev(dev));
> +}

What exactly is the point of introducing this function?

>  #else /* !CONFIG_SUSPEND */
>  
>  #define pci_pm_suspend		NULL
>  #define pci_pm_suspend_noirq	NULL
>  #define pci_pm_resume		NULL
>  #define pci_pm_resume_noirq	NULL
> +#define pci_pm_wakeup_event	NULL
>  
>  #endif /* !CONFIG_SUSPEND */
>  
> @@ -651,6 +745,7 @@ struct pm_ext_ops pci_pm_ops = {
>  		.thaw = pci_pm_thaw,
>  		.poweroff = pci_pm_poweroff,
>  		.restore = pci_pm_restore,
> +		.wakeup_event = pci_pm_wakeup_event,
>  	},
>  	.suspend_noirq = pci_pm_suspend_noirq,
>  	.resume_noirq = pci_pm_resume_noirq,
> Index: linux/include/linux/pci.h
> ===================================================================
> --- linux.orig/include/linux/pci.h	2008-09-11 10:56:26.000000000 +0800
> +++ linux/include/linux/pci.h	2008-09-11 10:56:42.000000000 +0800
> @@ -646,6 +646,7 @@ int pci_enable_wake(struct pci_dev *dev,
>  pci_power_t pci_target_state(struct pci_dev *dev);
>  int pci_prepare_to_sleep(struct pci_dev *dev);
>  int pci_back_from_sleep(struct pci_dev *dev);
> +bool pci_handle_wakeup_event(struct pci_dev *target);
>  
>  /* Functions for PCI Hotplug drivers to use */
>  int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
> @@ -949,6 +950,11 @@ static inline int pci_enable_wake(struct
>  	return 0;
>  }
>  
> +static inline bool pci_handle_wakeup_event(struct pci_dev *target)
> +{
> +	return false;
> +}
> +
>  static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
>  {
>  	return -EIO;
> 

Thanks,
Rafael

  parent reply	other threads:[~2008-10-19 19:50 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20080911063037.698427944@sli10-desk.sh.intel.com>
2008-09-11  6:30 ` [RFC 1/5] devcore introduce wakeup_event callback Shaohua Li
2008-09-11  6:30 ` [RFC 2/5] devcore adds generic wakeup event handler Shaohua Li
2008-09-11  6:30 ` [RFC 3/5] pci wakeup handler Shaohua Li
2008-09-11  6:30 ` [RFC 4/5] PCIe native PME detection Shaohua Li
2008-09-11  6:30 ` [RFC 5/5] ACPI GPE based wakeup event detection Shaohua Li
2008-09-14 23:50 ` [RFC 0/5] device wakeup event support v2 Rafael J. Wysocki
     [not found] ` <200809150150.01687.rjw@sisk.pl>
2008-10-06  1:57   ` Shaohua Li
     [not found] ` <20080911063822.973881418@sli10-desk.sh.intel.com>
2008-10-19 19:04   ` [RFC 1/5] devcore introduce wakeup_event callback Rafael J. Wysocki
2008-10-19 19:42     ` Rafael J. Wysocki
2008-10-22  5:23     ` Shaohua Li
     [not found] ` <20080911063823.083409592@sli10-desk.sh.intel.com>
2008-09-11 18:48   ` [RFC 2/5] devcore adds generic wakeup event handler Bjorn Helgaas
2008-10-19 19:06   ` Rafael J. Wysocki
     [not found]   ` <200810192106.58828.rjw@sisk.pl>
2008-10-22  5:24     ` Shaohua Li
     [not found]     ` <20081022052406.GB15271@sli10-desk.sh.intel.com>
2008-10-22 11:57       ` Rafael J. Wysocki
     [not found] ` <20080911063823.196887408@sli10-desk.sh.intel.com>
2008-10-19 19:50   ` Rafael J. Wysocki [this message]
2008-10-22  5:34     ` [RFC 3/5] pci wakeup handler Shaohua Li
     [not found]     ` <20081022053444.GC15271@sli10-desk.sh.intel.com>
2008-10-22 12:01       ` Rafael J. Wysocki
     [not found] ` <20080911063823.312142224@sli10-desk.sh.intel.com>
2008-10-19 20:30   ` [RFC 4/5] PCIe native PME detection Rafael J. Wysocki
2008-10-22  5:49     ` Shaohua Li
     [not found]     ` <20081022054907.GD15271@sli10-desk.sh.intel.com>
2008-10-22 12:08       ` Rafael J. Wysocki
     [not found] ` <20080911063823.432831198@sli10-desk.sh.intel.com>
2008-10-19 20:39   ` [RFC 5/5] ACPI GPE based wakeup event detection Rafael J. Wysocki
2008-10-22  6:51     ` Shaohua Li
     [not found]     ` <20081022065101.GE15271@sli10-desk.sh.intel.com>
2008-10-22 12:12       ` Rafael J. Wysocki
     [not found] <20080908091926.785882370@sli10-desk.sh.intel.com>
2008-09-08  9:19 ` [RFC 3/5] pci wakeup handler shaohua.li
     [not found] ` <20080908092305.438330804@sli10-desk.sh.intel.com>
2008-09-08 13:09   ` Rafael J. Wysocki
     [not found]   ` <200809081509.52070.rjw@sisk.pl>
2008-09-09  1:44     ` Li, Shaohua
     [not found]     ` <76780B19A496DC4B80439008DAD7076C01AC7F30F3@PDSMSX501.ccr.corp.intel.com>
2008-09-09  2:56       ` David Brownell
     [not found]       ` <200809081956.48036.david-b@pacbell.net>
2008-09-09  3:38         ` Li, Shaohua
2008-09-09  2:56   ` David Brownell
     [not found]   ` <200809081956.42663.david-b@pacbell.net>
2008-09-09  3:33     ` Li, Shaohua
     [not found]     ` <76780B19A496DC4B80439008DAD7076C01AC7F326A@PDSMSX501.ccr.corp.intel.com>
2008-09-09  4:04       ` David Brownell
2008-09-09 11:09     ` Rafael J. Wysocki
     [not found]     ` <200809091309.01433.rjw@sisk.pl>
2008-09-09 16:18       ` David Brownell

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=200810192150.41305.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=dbrownell@users.sourceforge.net \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=shaohua.li@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox