From 00aaaef9a51a1a25c5d6d52ce510772f149a0eb0 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 11 Nov 2010 15:46:54 +0800 Subject: PCI: MSI: Move MSI-X entry definition to pci_regs.h Then it can be used by others. Reviewed-by: Hidetoshi Seto Reviewed-by: Matthew Wilcox Signed-off-by: Sheng Yang Signed-off-by: Jesse Barnes --- drivers/pci/msi.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index feff3be..65c42f8 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,12 +6,6 @@ #ifndef MSI_H #define MSI_H -#define PCI_MSIX_ENTRY_SIZE 16 -#define PCI_MSIX_ENTRY_LOWER_ADDR 0 -#define PCI_MSIX_ENTRY_UPPER_ADDR 4 -#define PCI_MSIX_ENTRY_DATA 8 -#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 - #define msi_control_reg(base) (base + PCI_MSI_FLAGS) #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) -- cgit v1.1 From 8d805286968811223cca002134ba3d81244d5313 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 11 Nov 2010 15:46:55 +0800 Subject: PCI: Add mask bit definition for MSI-X table Then we can use it instead of magic number 1. Reviewed-by: Hidetoshi Seto Cc: Matthew Wilcox Signed-off-by: Sheng Yang Signed-off-by: Jesse Barnes --- drivers/pci/msi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7c24dce..44b0aee 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -168,8 +168,9 @@ static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; - mask_bits &= ~1; - mask_bits |= flag; + mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; + if (flag) + mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; writel(mask_bits, desc->mask_base + offset); return mask_bits; -- cgit v1.1 From 2f671e2dbff6eb5ef4e2600adbec550c13b8fe72 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 6 Dec 2010 14:00:56 -0500 Subject: PCI: Disable ASPM if BIOS asks us to We currently refuse to touch the ASPM registers if the BIOS tells us that ASPM isn't supported. This can cause problems if the BIOS has (for any reason) enabled ASPM on some devices anyway. Change the code such that we explicitly clear ASPM if the FADT indicates that ASPM isn't supported, and make sure we tidy up appropriately on device removal in order to deal with the hotplug case. If ASPM is disabled because the BIOS doesn't hand over control then we won't touch the registers. Signed-off-by: Matthew Garrett Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 1 + drivers/pci/pcie/aspm.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 24e19c5..d7ea699 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -399,6 +399,7 @@ static int __init acpi_pci_init(void) if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); + pcie_clear_aspm(); pcie_no_aspm(); } diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 7122281..3188cd9 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -68,7 +68,7 @@ struct pcie_link_state { struct aspm_latency acceptable[8]; }; -static int aspm_disabled, aspm_force; +static int aspm_disabled, aspm_force, aspm_clear_state; static DEFINE_MUTEX(aspm_lock); static LIST_HEAD(link_list); @@ -139,7 +139,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) { /* Don't enable Clock PM if the link is not Clock PM capable */ if (!link->clkpm_capable && enable) - return; + enable = 0; /* Need nothing if the specified equals to current state */ if (link->clkpm_enabled == enable) return; @@ -498,6 +498,10 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) struct pci_dev *child; int pos; u32 reg32; + + if (aspm_clear_state) + return -EINVAL; + /* * Some functions in a slot might not all be PCIe functions, * very strange. Disable ASPM for the whole slot @@ -563,12 +567,15 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) struct pcie_link_state *link; int blacklist = !!pcie_aspm_sanity_check(pdev); - if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state) + if (!pci_is_pcie(pdev) || pdev->link_state) return; if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) return; + if (aspm_disabled && !aspm_clear_state) + return; + /* VIA has a strange chipset, root port is under a bridge */ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && pdev->bus->self) @@ -641,7 +648,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link, *root, *parent_link; - if (aspm_disabled || !pci_is_pcie(pdev) || + if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || !parent || !parent->link_state) return; if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && @@ -899,6 +906,12 @@ static int __init pcie_aspm_disable(char *str) __setup("pcie_aspm=", pcie_aspm_disable); +void pcie_clear_aspm(void) +{ + if (!aspm_force) + aspm_clear_state = 1; +} + void pcie_no_aspm(void) { if (!aspm_force) -- cgit v1.1 From 1d3c16a818e992c199844954d95c17fd7ce6cbba Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Tue, 30 Nov 2010 17:43:26 -0600 Subject: PCI: make pci_restore_state return void pci_restore_state only ever returns 0, thus there is no benefit in having it return any value. Also, a large majority of the callers do not check the return code of pci_restore_state. Make the pci_restore_state a void return and avoid the overhead. Acked-by: Mauro Carvalho Chehab Signed-off-by: Jon Mason Signed-off-by: Jesse Barnes --- drivers/pci/pci-driver.c | 3 ++- drivers/pci/pci.c | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 8a6f797..80e551e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -449,7 +449,8 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) return error; } - return pci_restore_state(pci_dev); + pci_restore_state(pci_dev); + return 0; } static void pci_pm_default_resume_early(struct pci_dev *pci_dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 710c8a2..6762dca 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -937,14 +937,13 @@ pci_save_state(struct pci_dev *dev) * pci_restore_state - Restore the saved state of a PCI device * @dev: - PCI device that we're dealing with */ -int -pci_restore_state(struct pci_dev *dev) +void pci_restore_state(struct pci_dev *dev) { int i; u32 val; if (!dev->state_saved) - return 0; + return; /* PCI Express register must be restored first */ pci_restore_pcie_state(dev); @@ -968,8 +967,6 @@ pci_restore_state(struct pci_dev *dev) pci_restore_iov_state(dev); dev->state_saved = false; - - return 0; } static int do_pci_enable_device(struct pci_dev *dev, int bars) -- cgit v1.1 From 23ea3793fd368fd6a1ea20659699e280e2996658 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 18 Nov 2010 15:02:31 -0800 Subject: PCI: fix __pci_device_probe kernel-doc warning Fix kernel-doc warning for __pci_device_probe(): Warning(drivers/pci/pci-driver.c:341): missing initial short description on line: * __pci_device_probe() Signed-off-by: Randy Dunlap Signed-off-by: Jesse Barnes --- drivers/pci/pci-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 80e551e..88246dd 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -338,7 +338,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, } /** - * __pci_device_probe() + * __pci_device_probe - check if a driver wants to claim a specific PCI device * @drv: driver to call to check if it wants the PCI device * @pci_dev: PCI device being probed * -- cgit v1.1 From ee8abf783dd36f65440fd782ad16f9768631d998 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 17 Nov 2010 12:10:40 -0800 Subject: PCI: Skip id checking if no id is passed Will get warning when pci stub driver is built-in kenel like: pci-stub: invalid id string "" So stop early if no id is passed. Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/pci-stub.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index f7b68ca..4c0336b 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -47,6 +47,10 @@ static int __init pci_stub_init(void) if (rc) return rc; + /* no ids passed actually */ + if (ids[0] == '\0') + return 0; + /* add ids specified in the module parameter */ p = ids; while ((id = strsep(&p, ","))) { -- cgit v1.1 From 99a0fadf561e1f553c08f0a29f8b2578f55dd5f0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Dec 2010 10:06:36 +0100 Subject: PCI: pci-stub: ignore zero-length id parameters pci-stub uses strsep() to separate list of ids and generates a warning message when it fails to parse an id. However, not specifying the parameter results in ids set to an empty string. strsep() happily returns the empty string as the first token and thus triggers the warning message spuriously. Make the tokner ignore zero length ids. Reported-by: Chris Wright Reported-by: Prasad Joshi Cc: stable@kernel.org Signed-off-by: Jesse Barnes --- drivers/pci/pci-stub.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index 4c0336b..775e933 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -58,6 +58,9 @@ static int __init pci_stub_init(void) subdevice = PCI_ANY_ID, class=0, class_mask=0; int fields; + if (!strlen(id)) + continue; + fields = sscanf(id, "%x:%x:%x:%x:%x:%x", &vendor, &device, &subvendor, &subdevice, &class, &class_mask); -- cgit v1.1 From fe31e69740eddc7316071ed5165fed6703c8cd12 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 19 Dec 2010 15:57:16 +0100 Subject: PCI/PCIe: Clear Root PME Status bits early during system resume I noticed that PCI Express PMEs don't work on my Toshiba Portege R500 after the system has been woken up from a sleep state by a PME (through Wake-on-LAN). After some investigation it turned out that the BIOS didn't clear the Root PME Status bit in the root port that received the wakeup PME and since the Requester ID was also set in the port's Root Status register, any subsequent PMEs didn't trigger interrupts. This problem can be avoided by clearing the Root PME Status bits in all PCI Express root ports during early resume. For this purpose, add an early resume routine to the PCIe port driver and make this driver be always registered, even if pci_ports_disable is set (in which case the driver's only function is to provide the early resume callback). Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pcie/pme.c | 27 ++++----------------------- drivers/pci/pcie/portdrv.h | 2 ++ drivers/pci/pcie/portdrv_core.c | 25 ++++++++++++++----------- drivers/pci/pcie/portdrv_pci.c | 37 +++++++++++++++++++++++++++++++++---- 4 files changed, 53 insertions(+), 38 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 2f3c904..073f030 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -26,9 +26,6 @@ #include "../pci.h" #include "portdrv.h" -#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ -#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ - /* * If this switch is set, MSI will not be used for PCIe PME signaling. This * causes the PCIe port driver to use INTx interrupts only, but it turns out @@ -74,22 +71,6 @@ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) } /** - * pcie_pme_clear_status - Clear root port PME interrupt status. - * @dev: PCIe root port or event collector. - */ -static void pcie_pme_clear_status(struct pci_dev *dev) -{ - int rtsta_pos; - u32 rtsta; - - rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; - - pci_read_config_dword(dev, rtsta_pos, &rtsta); - rtsta |= PCI_EXP_RTSTA_PME; - pci_write_config_dword(dev, rtsta_pos, rtsta); -} - -/** * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. * @bus: PCI bus to scan. * @@ -253,7 +234,7 @@ static void pcie_pme_work_fn(struct work_struct *work) * Clear PME status of the port. If there are other * pending PMEs, the status will be set again. */ - pcie_pme_clear_status(port); + pcie_clear_root_pme_status(port); spin_unlock_irq(&data->lock); pcie_pme_handle_request(port, rtsta & 0xffff); @@ -378,7 +359,7 @@ static int pcie_pme_probe(struct pcie_device *srv) port = srv->port; pcie_pme_interrupt_enable(port, false); - pcie_pme_clear_status(port); + pcie_clear_root_pme_status(port); ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); if (ret) { @@ -402,7 +383,7 @@ static int pcie_pme_suspend(struct pcie_device *srv) spin_lock_irq(&data->lock); pcie_pme_interrupt_enable(port, false); - pcie_pme_clear_status(port); + pcie_clear_root_pme_status(port); data->noirq = true; spin_unlock_irq(&data->lock); @@ -422,7 +403,7 @@ static int pcie_pme_resume(struct pcie_device *srv) spin_lock_irq(&data->lock); data->noirq = false; - pcie_pme_clear_status(port); + pcie_clear_root_pme_status(port); pcie_pme_interrupt_enable(port, true); spin_unlock_irq(&data->lock); diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 7b5aba0..8fcc035 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -35,6 +35,8 @@ extern void pcie_port_bus_unregister(void); struct pci_dev; +extern void pcie_clear_root_pme_status(struct pci_dev *dev); + #ifdef CONFIG_PCIE_PME extern bool pcie_pme_msi_disabled; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index a9c222d..5130d0d 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -241,17 +241,17 @@ static int get_port_device_capability(struct pci_dev *dev) int cap_mask; int err; + if (pcie_ports_disabled) + return 0; + err = pcie_port_platform_notify(dev, &cap_mask); - if (pcie_ports_auto) { - if (err) { - pcie_no_aspm(); - return 0; - } - } else { + if (!pcie_ports_auto) { cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | PCIE_PORT_SERVICE_VC; if (pci_aer_available()) cap_mask |= PCIE_PORT_SERVICE_AER; + } else if (err) { + return 0; } pos = pci_pcie_cap(dev); @@ -349,15 +349,18 @@ int pcie_port_device_register(struct pci_dev *dev) int status, capabilities, i, nr_service; int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; - /* Get and check PCI Express port services */ - capabilities = get_port_device_capability(dev); - if (!capabilities) - return -ENODEV; - /* Enable PCI Express port device */ status = pci_enable_device(dev); if (status) return status; + + /* Get and check PCI Express port services */ + capabilities = get_port_device_capability(dev); + if (!capabilities) { + pcie_no_aspm(); + return 0; + } + pci_set_master(dev); /* * Initialize service irqs. Don't use service devices that diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f9033e1..e0610bd 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -57,6 +57,22 @@ __setup("pcie_ports=", pcie_port_setup); /* global data */ +/** + * pcie_clear_root_pme_status - Clear root port PME interrupt status. + * @dev: PCIe root port or event collector. + */ +void pcie_clear_root_pme_status(struct pci_dev *dev) +{ + int rtsta_pos; + u32 rtsta; + + rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; + + pci_read_config_dword(dev, rtsta_pos, &rtsta); + rtsta |= PCI_EXP_RTSTA_PME; + pci_write_config_dword(dev, rtsta_pos, rtsta); +} + static int pcie_portdrv_restore_config(struct pci_dev *dev) { int retval; @@ -69,6 +85,20 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) } #ifdef CONFIG_PM +static int pcie_port_resume_noirq(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + /* + * Some BIOSes forget to clear Root PME Status bits after system wakeup + * which breaks ACPI-based runtime wakeup on PCI Express, so clear those + * bits now just in case (shouldn't hurt). + */ + if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + pcie_clear_root_pme_status(pdev); + return 0; +} + static const struct dev_pm_ops pcie_portdrv_pm_ops = { .suspend = pcie_port_device_suspend, .resume = pcie_port_device_resume, @@ -76,6 +106,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { .thaw = pcie_port_device_resume, .poweroff = pcie_port_device_suspend, .restore = pcie_port_device_resume, + .resume_noirq = pcie_port_resume_noirq, }; #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) @@ -327,10 +358,8 @@ static int __init pcie_portdrv_init(void) { int retval; - if (pcie_ports_disabled) { - pcie_no_aspm(); - return -EACCES; - } + if (pcie_ports_disabled) + return pci_register_driver(&pcie_portdriver); dmi_check_system(pcie_portdrv_dmi_table); -- cgit v1.1 From 415e12b2379239973feab91850b0dce985c6058a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 7 Jan 2011 00:55:09 +0100 Subject: PCI/ACPI: Request _OSC control once for each root bridge (v3) Move the evaluation of acpi_pci_osc_control_set() (to request control of PCI Express native features) into acpi_pci_root_add() to avoid calling it many times for the same root complex with the same arguments. Additionally, check if all of the requisite _OSC support bits are set before calling acpi_pci_osc_control_set() for a given root complex. References: https://bugzilla.kernel.org/show_bug.cgi?id=20232 Reported-by: Ozan Caglayan Tested-by: Ozan Caglayan Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pci.h | 8 -------- drivers/pci/pcie/aer/aerdrv.c | 1 + drivers/pci/pcie/aer/aerdrv.h | 3 --- drivers/pci/pcie/portdrv.h | 3 --- drivers/pci/pcie/portdrv_acpi.c | 23 ++++------------------- 5 files changed, 5 insertions(+), 33 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7d33f66..16ae965 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -140,14 +140,6 @@ static inline void pci_no_msi(void) { } static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #endif -#ifdef CONFIG_PCIEAER -void pci_no_aer(void); -bool pci_aer_available(void); -#else -static inline void pci_no_aer(void) { } -static inline bool pci_aer_available(void) { return false; } -#endif - static inline int pci_no_d1d2(struct pci_dev *dev) { unsigned int parent_dstates = 0; diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 2b2b650..58ad791 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 9656e30..80c11d1 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -132,7 +132,6 @@ static inline int aer_osc_setup(struct pcie_device *pciedev) #ifdef CONFIG_ACPI_APEI extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); -extern bool aer_acpi_firmware_first(void); #else static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) { @@ -140,8 +139,6 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) return pci_dev->__aer_firmware_first; return 0; } - -static inline bool aer_acpi_firmware_first(void) { return false; } #endif static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 8fcc035..bd00a01 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -20,9 +20,6 @@ #define get_descriptor_id(type, service) (((type - 4) << 4) | service) -extern bool pcie_ports_disabled; -extern bool pcie_ports_auto; - extern struct bus_type pcie_port_bus_type; extern int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index 5982b6a..a86b56e 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -33,7 +33,7 @@ */ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) { - acpi_status status; + struct acpi_pci_root *root; acpi_handle handle; u32 flags; @@ -44,26 +44,11 @@ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) if (!handle) return -EINVAL; - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL - | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL - | OSC_PCI_EXPRESS_PME_CONTROL; - - if (pci_aer_available()) { - if (aer_acpi_firmware_first()) - dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n"); - else - flags |= OSC_PCI_EXPRESS_AER_CONTROL; - } - - status = acpi_pci_osc_control_set(handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - if (ACPI_FAILURE(status)) { - dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n", - status); + root = acpi_pci_find_root(handle); + if (!root) return -ENODEV; - } - dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags); + flags = root->osc_control_set; *srv_mask = PCIE_PORT_SERVICE_VC; if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) -- cgit v1.1 From ff29530e651a3449aea6b0ef4c7048db9e22ef27 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 5 Jan 2011 10:26:41 -0700 Subject: PCI: sysfs: Update ROM to include default owner write access The PCI sysfs ROM interface requires an enabling write to access the ROM image, but the default file mode is 0400. The original proposed patch adding sysfs ROM support was a true read-only interface, with the enabling bit coming in as a feature request. I suspect it was simply an oversight that the file mode didn't get updated to match the API. Acked-by: Chris Wright Signed-off-by: Alex Williamson Signed-off-by: Jesse Barnes --- drivers/pci/pci-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 63d5042..8ecaac9 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1149,7 +1149,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) sysfs_bin_attr_init(attr); attr->size = rom_size; attr->attr.name = "rom"; - attr->attr.mode = S_IRUSR; + attr->attr.mode = S_IRUSR | S_IWUSR; attr->read = pci_read_rom; attr->write = pci_write_rom; retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); -- cgit v1.1 From b6e335aeeb114dccb07eaa09e8b62ff9510cf745 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 29 Dec 2010 13:21:23 +0100 Subject: PCI/PM: Use pm_wakeup_event() directly for reporting wakeup events After recent changes related to wakeup events pm_wakeup_event() automatically checks if the given device is configured to signal wakeup, so pci_wakeup_event() may be a static inline function calling pm_wakeup_event() directly. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 16 ---------------- drivers/pci/pci.h | 6 ++++++ 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6762dca..bf7ad2c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1297,22 +1297,6 @@ bool pci_check_pme_status(struct pci_dev *dev) return ret; } -/* - * Time to wait before the system can be put into a sleep state after reporting - * a wakeup event signaled by a PCI device. - */ -#define PCI_WAKEUP_COOLDOWN 100 - -/** - * pci_wakeup_event - Report a wakeup event related to a given PCI device. - * @dev: Device to report the wakeup event for. - */ -void pci_wakeup_event(struct pci_dev *dev) -{ - if (device_may_wakeup(&dev->dev)) - pm_wakeup_event(&dev->dev, PCI_WAKEUP_COOLDOWN); -} - /** * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. * @dev: Device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 16ae965..f69d6e0 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -74,6 +74,12 @@ 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); +static inline void pci_wakeup_event(struct pci_dev *dev) +{ + /* Wait 100 ms before the system can be put into a sleep state. */ + pm_wakeup_event(&dev->dev, 100); +} + static inline bool pci_is_bridge(struct pci_dev *pci_dev) { return !!(pci_dev->subordinate); -- cgit v1.1 From 0f953bf6b4efa0daddb7c418130a9bd3ee97f7ed Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 29 Dec 2010 13:22:08 +0100 Subject: PCI/PM: Report wakeup events before resuming devices Make wakeup events be reported by the PCI subsystem before attempting to resume devices or queuing up runtime resume requests for them, because wakeup events should be reported as soon as they have been detected. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 2 +- drivers/pci/pci.c | 2 +- drivers/pci/pcie/pme.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index d7ea699..6fe0772 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -46,9 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) struct pci_dev *pci_dev = context; if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { + pci_wakeup_event(pci_dev); pci_check_pme_status(pci_dev); pm_runtime_resume(&pci_dev->dev); - pci_wakeup_event(pci_dev); if (pci_dev->subordinate) pci_pme_wakeup_bus(pci_dev->subordinate); } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bf7ad2c..b714d78 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1308,8 +1308,8 @@ bool pci_check_pme_status(struct pci_dev *dev) static int pci_pme_wakeup(struct pci_dev *dev, void *ign) { if (pci_check_pme_status(dev)) { - pm_request_resume(&dev->dev); pci_wakeup_event(dev); + pm_request_resume(&dev->dev); } return 0; } diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 073f030..0057344 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -84,8 +84,8 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { /* Skip PCIe devices in case we started from a root port. */ if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { - pm_request_resume(&dev->dev); pci_wakeup_event(dev); + pm_request_resume(&dev->dev); ret = true; } @@ -187,8 +187,8 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) /* The device is there, but we have to check its PME status. */ found = pci_check_pme_status(dev); if (found) { - pm_request_resume(&dev->dev); pci_wakeup_event(dev); + pm_request_resume(&dev->dev); } pci_dev_put(dev); } else if (devfn) { -- cgit v1.1