From 84df749f364209c9623304b7a94ddb954dc343bb Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Fri, 18 Mar 2005 18:53:36 -0500 Subject: [ACPI] Bind ACPI and PCI devices http://bugzilla.kernel.org/show_bug.cgi?id=4277 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) (limited to 'drivers/pci/pci-acpi.c') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index bc01d34e263..f94c86fbc66 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1,9 +1,10 @@ /* * File: pci-acpi.c - * Purpose: Provide PCI supports in ACPI + * Purpose: Provide PCI support in ACPI * - * Copyright (C) 2004 Intel - * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) + * Copyright (C) 2005 David Shaohua Li + * Copyright (C) 2004 Tom Long Nguyen + * Copyright (C) 2004 Intel Corp. */ #include @@ -207,3 +208,53 @@ acpi_status pci_osc_control_set(u32 flags) return status; } EXPORT_SYMBOL(pci_osc_control_set); + +/* ACPI bus type */ +static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) +{ + struct pci_dev * pci_dev; + acpi_integer addr; + + pci_dev = to_pci_dev(dev); + /* Please ref to ACPI spec for the syntax of _ADR */ + addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); + if (!*handle) + return -ENODEV; + return 0; +} + +static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) +{ + int num; + unsigned int seg, bus; + + /* + * The string should be the same as root bridge's name + * Please look at 'pci_scan_bus_parented' + */ + num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus); + if (num != 2) + return -ENODEV; + *handle = acpi_get_pci_rootbridge_handle(seg, bus); + if (!*handle) + return -ENODEV; + return 0; +} + +static struct acpi_bus_type pci_acpi_bus = { + .bus = &pci_bus_type, + .find_device = pci_acpi_find_device, + .find_bridge = pci_acpi_find_root_bridge, +}; + +static int __init pci_acpi_init(void) +{ + int ret; + + ret = register_acpi_bus_type(&pci_acpi_bus); + if (ret) + return 0; + return 0; +} +arch_initcall(pci_acpi_init); -- cgit v1.2.3 From 0f64474b8f7f1f7f3af5b24ef997baa35f923509 Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Sat, 19 Mar 2005 00:15:48 -0500 Subject: [ACPI] PCI can now get suspend state from firmware pci_choose_state() can now call platform_pci_choose_state() and ACPI can answer http://bugzilla.kernel.org/show_bug.cgi?id=4277 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/pci/pci-acpi.c') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index f94c86fbc66..8eb599708de 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1,6 +1,6 @@ /* * File: pci-acpi.c - * Purpose: Provide PCI support in ACPI + * Purpose: Provde PCI support in ACPI * * Copyright (C) 2005 David Shaohua Li * Copyright (C) 2004 Tom Long Nguyen @@ -17,6 +17,7 @@ #include #include +#include "pci.h" static u32 ctrlset_buf[3] = {0, 0, 0}; static u32 global_ctrlsets = 0; @@ -209,6 +210,49 @@ acpi_status pci_osc_control_set(u32 flags) } EXPORT_SYMBOL(pci_osc_control_set); +/* + * _SxD returns the D-state with the highest power + * (lowest D-state number) supported in the S-state "x". + * + * If the devices does not have a _PRW + * (Power Resources for Wake) supporting system wakeup from "x" + * then the OS is free to choose a lower power (higher number + * D-state) than the return value from _SxD. + * + * But if _PRW is enabled at S-state "x", the OS + * must not choose a power lower than _SxD -- + * unless the device has an _SxW method specifying + * the lowest power (highest D-state number) the device + * may enter while still able to wake the system. + * + * ie. depending on global OS policy: + * + * if (_PRW at S-state x) + * choose from highest power _SxD to lowest power _SxW + * else // no _PRW at S-state x + * choose highest power _SxD or any lower power + * + * currently we simply return _SxD, if present. + */ + +static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state) +{ + char dstate_str[] = "_S0D"; + acpi_status status; + unsigned long val; + struct device *dev = &pdev->dev; + + /* Fixme: the check is wrong after pm_message_t is a struct */ + if ((state >= PM_SUSPEND_MAX) || !DEVICE_ACPI_HANDLE(dev)) + return -EINVAL; + dstate_str[2] += state; /* _S1D, _S2D, _S3D, _S4D */ + status = acpi_evaluate_integer(DEVICE_ACPI_HANDLE(dev), dstate_str, + NULL, &val); + if (ACPI_SUCCESS(status)) + return val; + return -ENODEV; +} + /* ACPI bus type */ static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) { @@ -255,6 +299,7 @@ static int __init pci_acpi_init(void) ret = register_acpi_bus_type(&pci_acpi_bus); if (ret) return 0; + platform_pci_choose_state = acpi_pci_choose_state; return 0; } arch_initcall(pci_acpi_init); -- cgit v1.2.3 From b913100d7304ea9596d8d85ab5f3ae04bd2b0ddb Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Sat, 19 Mar 2005 00:16:18 -0500 Subject: [ACPI] pci_set_power_state() now calls platform_pci_set_power_state() and ACPI can answer http://bugzilla.kernel.org/show_bug.cgi?id=4277 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/pci/pci-acpi.c') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 8eb599708de..a0d43ea872d 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -253,6 +253,24 @@ static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state) return -ENODEV; } +static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); + static int state_conv[] = { + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = 3 + }; + int acpi_state = state_conv[(int __force) state]; + + if (!handle) + return -ENODEV; + return acpi_bus_set_power(handle, acpi_state); +} + + /* ACPI bus type */ static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) { @@ -300,6 +318,7 @@ static int __init pci_acpi_init(void) if (ret) return 0; platform_pci_choose_state = acpi_pci_choose_state; + platform_pci_set_power_state = acpi_pci_set_power_state; return 0; } arch_initcall(pci_acpi_init); -- cgit v1.2.3 From a406d9e63e1d7088aad22565449de2e109300e5c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 23 Mar 2005 16:16:03 -0500 Subject: [ACPI] gut acpi_pci_choose_state() to avoid conflict with pending pm_message_t re-definition. Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers/pci/pci-acpi.c') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index a0d43ea872d..e9e37abe1f7 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1,6 +1,6 @@ /* * File: pci-acpi.c - * Purpose: Provde PCI support in ACPI + * Purpose: Provide PCI support in ACPI * * Copyright (C) 2005 David Shaohua Li * Copyright (C) 2004 Tom Long Nguyen @@ -237,19 +237,8 @@ EXPORT_SYMBOL(pci_osc_control_set); static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state) { - char dstate_str[] = "_S0D"; - acpi_status status; - unsigned long val; - struct device *dev = &pdev->dev; + /* TBD */ - /* Fixme: the check is wrong after pm_message_t is a struct */ - if ((state >= PM_SUSPEND_MAX) || !DEVICE_ACPI_HANDLE(dev)) - return -EINVAL; - dstate_str[2] += state; /* _S1D, _S2D, _S3D, _S4D */ - status = acpi_evaluate_integer(DEVICE_ACPI_HANDLE(dev), dstate_str, - NULL, &val); - if (ACPI_SUCCESS(status)) - return val; return -ENODEV; } -- cgit v1.2.3