Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jbarnes/pci-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
  PCI: bus speed strings should be const
  PCI hotplug: Fix build with CONFIG_ACPI unset
  PCI: PCIe: Remove the port driver module exit routine
  PCI: PCIe: Move PCIe PME code to the pcie directory
  PCI: PCIe: Disable PCIe port services during port initialization
  PCI: PCIe: Ask BIOS for control of all native services at once
  ACPI/PCI: Negotiate _OSC control bits before requesting them
  ACPI/PCI: Do not preserve _OSC control bits returned by a query
  ACPI/PCI: Make acpi_pci_query_osc() return control bits
  ACPI/PCI: Reorder checks in acpi_pci_osc_control_set()
  PCI: PCIe: Introduce commad line switch for disabling port services
  PCI: PCIe AER: Introduce pci_aer_available()
  x86/PCI: only define pci_domain_nr if PCI and PCI_DOMAINS are set
  PCI: provide stub pci_domain_nr function for !CONFIG_PCI configs
  • Loading branch information
torvalds committed Sep 7, 2010
2 parents fa2925c + 17134d9 commit d56557a
Show file tree
Hide file tree
Showing 24 changed files with 281 additions and 291 deletions.
17 changes: 10 additions & 7 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1974,15 +1974,18 @@ and is between 256 and 4096 characters. It is defined in the file
force Enable ASPM even on devices that claim not to support it.
WARNING: Forcing ASPM on may cause system lockups.

pcie_ports= [PCIE] PCIe ports handling:
auto Ask the BIOS whether or not to use native PCIe services
associated with PCIe ports (PME, hot-plug, AER). Use
them only if that is allowed by the BIOS.
native Use native PCIe services associated with PCIe ports
unconditionally.
compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
ports driver.

pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
Format: {auto|force}[,nomsi]
auto Use native PCIe PME signaling if the BIOS allows the
kernel to control PCIe config registers of root ports.
force Use native PCIe PME signaling even if the BIOS refuses
to allow the kernel to control the relevant PCIe config
registers.
nomsi Do not use MSI for native PCIe PME signaling (this makes
all PCIe root ports use INTx for everything).
all PCIe root ports use INTx for all services).

pcmv= [HW,PCMCIA] BadgePAD 4

Expand Down
6 changes: 4 additions & 2 deletions arch/x86/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
int node);
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);

#ifdef CONFIG_PCI

#ifdef CONFIG_PCI_DOMAINS
static inline int pci_domain_nr(struct pci_bus *bus)
{
struct pci_sysdata *sd = bus->sysdata;
Expand All @@ -37,13 +40,12 @@ static inline int pci_proc_domain(struct pci_bus *bus)
{
return pci_domain_nr(bus);
}

#endif

/* Can be used to override the logic in pci_scan_bus for skipping
already-configured bus numbers - to be used for buggy BIOSes
or architectures with incomplete PCI setup by the loader */

#ifdef CONFIG_PCI
extern unsigned int pcibios_assign_all_busses(void);
extern int pci_legacy_init(void);
# ifdef CONFIG_ACPI
Expand Down
97 changes: 56 additions & 41 deletions drivers/acpi/pci_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include <linux/pm_runtime.h>
#include <linux/pci.h>
#include <linux/pci-acpi.h>
#include <linux/pci-aspm.h>
#include <linux/acpi.h>
#include <linux/slab.h>
#include <acpi/acpi_bus.h>
Expand Down Expand Up @@ -226,22 +225,31 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle,
return status;
}

static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
u32 support,
u32 *control)
{
acpi_status status;
u32 support_set, result, capbuf[3];
u32 result, capbuf[3];

support &= OSC_PCI_SUPPORT_MASKS;
support |= root->osc_support_set;

/* do _OSC query for all possible controls */
support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS);
capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
capbuf[OSC_SUPPORT_TYPE] = support_set;
capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
capbuf[OSC_SUPPORT_TYPE] = support;
if (control) {
*control &= OSC_PCI_CONTROL_MASKS;
capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
} else {
/* Run _OSC query for all possible controls. */
capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
}

status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
if (ACPI_SUCCESS(status)) {
root->osc_support_set = support_set;
root->osc_control_qry = result;
root->osc_queried = 1;
root->osc_support_set = support;
if (control)
*control = result;
}
return status;
}
Expand All @@ -255,7 +263,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
if (ACPI_FAILURE(status))
return status;
mutex_lock(&osc_lock);
status = acpi_pci_query_osc(root, flags);
status = acpi_pci_query_osc(root, flags, NULL);
mutex_unlock(&osc_lock);
return status;
}
Expand Down Expand Up @@ -365,55 +373,70 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
EXPORT_SYMBOL_GPL(acpi_get_pci_dev);

/**
* acpi_pci_osc_control_set - commit requested control to Firmware
* @handle: acpi_handle for the target ACPI object
* @flags: driver's requested control bits
* acpi_pci_osc_control_set - Request control of PCI root _OSC features.
* @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
* @mask: Mask of _OSC bits to request control of, place to store control mask.
* @req: Mask of _OSC bits the control of is essential to the caller.
*
* Run _OSC query for @mask and if that is successful, compare the returned
* mask of control bits with @req. If all of the @req bits are set in the
* returned mask, run _OSC request for it.
*
* Attempt to take control from Firmware on requested control bits.
* The variable at the @mask address may be modified regardless of whether or
* not the function returns success. On success it will contain the mask of
* _OSC bits the BIOS has granted control of, but its contents are meaningless
* on failure.
**/
acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags)
acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
{
struct acpi_pci_root *root;
acpi_status status;
u32 control_req, result, capbuf[3];
u32 ctrl, capbuf[3];
acpi_handle tmp;
struct acpi_pci_root *root;

status = acpi_get_handle(handle, "_OSC", &tmp);
if (ACPI_FAILURE(status))
return status;
if (!mask)
return AE_BAD_PARAMETER;

control_req = (flags & OSC_PCI_CONTROL_MASKS);
if (!control_req)
ctrl = *mask & OSC_PCI_CONTROL_MASKS;
if ((ctrl & req) != req)
return AE_TYPE;

root = acpi_pci_find_root(handle);
if (!root)
return AE_NOT_EXIST;

status = acpi_get_handle(handle, "_OSC", &tmp);
if (ACPI_FAILURE(status))
return status;

mutex_lock(&osc_lock);

*mask = ctrl | root->osc_control_set;
/* No need to evaluate _OSC if the control was already granted. */
if ((root->osc_control_set & control_req) == control_req)
if ((root->osc_control_set & ctrl) == ctrl)
goto out;

/* Need to query controls first before requesting them */
if (!root->osc_queried) {
status = acpi_pci_query_osc(root, root->osc_support_set);
/* Need to check the available controls bits before requesting them. */
while (*mask) {
status = acpi_pci_query_osc(root, root->osc_support_set, mask);
if (ACPI_FAILURE(status))
goto out;
if (ctrl == *mask)
break;
ctrl = *mask;
}
if ((root->osc_control_qry & control_req) != control_req) {
printk(KERN_DEBUG
"Firmware did not grant requested _OSC control\n");

if ((ctrl & req) != req) {
status = AE_SUPPORT;
goto out;
}

capbuf[OSC_QUERY_TYPE] = 0;
capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req;
status = acpi_pci_run_osc(handle, capbuf, &result);
capbuf[OSC_CONTROL_TYPE] = ctrl;
status = acpi_pci_run_osc(handle, capbuf, mask);
if (ACPI_SUCCESS(status))
root->osc_control_set = result;
root->osc_control_set = *mask;
out:
mutex_unlock(&osc_lock);
return status;
Expand Down Expand Up @@ -544,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (flags != base_flags)
acpi_pci_osc_support(root, flags);

status = acpi_pci_osc_control_set(root->device->handle,
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);

if (ACPI_FAILURE(status)) {
printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
pcie_no_aspm();
}

pci_acpi_add_bus_pm_notifier(device, root->bus);
if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true);
Expand Down
6 changes: 2 additions & 4 deletions drivers/pci/hotplug/acpi_pcihp.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
acpi_handle chandle, handle;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };

flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
OSC_SHPC_NATIVE_HP_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
flags &= OSC_SHPC_NATIVE_HP_CONTROL;
if (!flags) {
err("Invalid flags %u specified!\n", flags);
return -EINVAL;
Expand All @@ -360,7 +358,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
dbg("Trying to get hotplug control for %s\n",
(char *)string.pointer);
status = acpi_pci_osc_control_set(handle, flags);
status = acpi_pci_osc_control_set(handle, &flags, flags);
if (ACPI_SUCCESS(status))
goto got_one;
if (status == AE_SUPPORT)
Expand Down
16 changes: 4 additions & 12 deletions drivers/pci/hotplug/pciehp.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,11 @@ static inline void pciehp_firmware_init(void)
{
pciehp_acpi_slot_detection_init();
}

static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
int retval;
u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
retval = acpi_get_hp_hw_control_from_firmware(dev, flags);
if (retval)
return retval;
return pciehp_acpi_slot_detection_check(dev);
}
#else
#define pciehp_firmware_init() do {} while (0)
#define pciehp_get_hp_hw_control_from_firmware(dev) 0
static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev)
{
return 0;
}
#endif /* CONFIG_ACPI */
#endif /* _PCIEHP_H */
4 changes: 1 addition & 3 deletions drivers/pci/hotplug/pciehp_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev)
acpi_handle handle;
struct dummy_slot *slot, *tmp;
struct pci_dev *pdev = dev->port;
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
if (pciehp_get_hp_hw_control_from_firmware(pdev))
return -ENODEV;

pos = pci_pcie_cap(pdev);
if (!pos)
return -ENODEV;
Expand Down
4 changes: 2 additions & 2 deletions drivers/pci/hotplug/pciehp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644);
MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing");

#define PCIE_MODULE_NAME "pciehp"

Expand Down Expand Up @@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev)
dev_info(&dev->device,
"Bypassing BIOS check for pciehp use on %s\n",
pci_name(dev->port));
else if (pciehp_get_hp_hw_control_from_firmware(dev->port))
else if (pciehp_acpi_slot_detection_check(dev->port))
goto err_out_none;

ctrl = pcie_init(dev);
Expand Down
2 changes: 2 additions & 0 deletions drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }

#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)
Expand Down
3 changes: 2 additions & 1 deletion drivers/pci/pcie/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
obj-$(CONFIG_PCIEASPM) += aspm.o

pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o

obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o

# Build PCI Express AER if needed
obj-$(CONFIG_PCIEAER) += aer/

obj-$(CONFIG_PCIE_PME) += pme/
obj-$(CONFIG_PCIE_PME) += pme.o
9 changes: 6 additions & 3 deletions drivers/pci/pcie/aer/aerdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ void pci_no_aer(void)
pcie_aer_disable = 1; /* has priority over 'forceload' */
}

bool pci_aer_available(void)
{
return !pcie_aer_disable && pci_msi_enabled();
}

static int set_device_error_reporting(struct pci_dev *dev, void *data)
{
bool enable = *((bool *)data);
Expand Down Expand Up @@ -411,9 +416,7 @@ static void aer_error_resume(struct pci_dev *dev)
*/
static int __init aer_service_init(void)
{
if (pcie_aer_disable)
return -ENXIO;
if (!pci_msi_enabled())
if (!pci_aer_available())
return -ENXIO;
return pcie_port_service_register(&aerdriver);
}
Expand Down
36 changes: 0 additions & 36 deletions drivers/pci/pcie/aer/aerdrv_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,6 @@
#include <acpi/apei.h>
#include "aerdrv.h"

/**
* aer_osc_setup - run ACPI _OSC method
* @pciedev: pcie_device which AER is being enabled on
*
* @return: Zero on success. Nonzero otherwise.
*
* Invoked when PCIe bus loads AER service driver. To avoid conflict with
* BIOS AER support requires BIOS to yield AER control to OS native driver.
**/
int aer_osc_setup(struct pcie_device *pciedev)
{
acpi_status status = AE_NOT_FOUND;
struct pci_dev *pdev = pciedev->port;
acpi_handle handle = NULL;

if (acpi_pci_disabled)
return -1;

handle = acpi_find_root_bridge_handle(pdev);
if (handle) {
status = acpi_pci_osc_control_set(handle,
OSC_PCI_EXPRESS_AER_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
}

if (ACPI_FAILURE(status)) {
dev_printk(KERN_DEBUG, &pciedev->device, "AER service couldn't "
"init device: %s\n",
(status == AE_SUPPORT || status == AE_NOT_FOUND) ?
"no _OSC support" : "_OSC failed");
return -1;
}

return 0;
}

#ifdef CONFIG_ACPI_APEI
static inline int hest_match_pci(struct acpi_hest_aer_common *p,
struct pci_dev *pci)
Expand Down
Loading

0 comments on commit d56557a

Please sign in to comment.