diff --git a/[refs] b/[refs] index 4165c29620eb..a48b66b4d5bb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3ced69f8bba1b766d6c1ea8f26c32a9b3e6fe75c +refs/heads/master: dbd3fc3345390a989a033427aa915a0dfb62149f diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-pci b/trunk/Documentation/ABI/testing/sysfs-bus-pci index 1ce5ae329c04..dff1f48d252d 100644 --- a/trunk/Documentation/ABI/testing/sysfs-bus-pci +++ b/trunk/Documentation/ABI/testing/sysfs-bus-pci @@ -222,37 +222,3 @@ Description: satisfied too. Reading this attribute will show the current value of d3cold_allowed bit. Writing this attribute will set the value of d3cold_allowed bit. - -What: /sys/bus/pci/devices/.../sriov_totalvfs -Date: November 2012 -Contact: Donald Dutile -Description: - This file appears when a physical PCIe device supports SR-IOV. - Userspace applications can read this file to determine the - maximum number of Virtual Functions (VFs) a PCIe physical - function (PF) can support. Typically, this is the value reported - in the PF's SR-IOV extended capability structure's TotalVFs - element. Drivers have the ability at probe time to reduce the - value read from this file via the pci_sriov_set_totalvfs() - function. - -What: /sys/bus/pci/devices/.../sriov_numvfs -Date: November 2012 -Contact: Donald Dutile -Description: - This file appears when a physical PCIe device supports SR-IOV. - Userspace applications can read and write to this file to - determine and control the enablement or disablement of Virtual - Functions (VFs) on the physical function (PF). A read of this - file will return the number of VFs that are enabled on this PF. - A number written to this file will enable the specified - number of VFs. A userspace application would typically read the - file and check that the value is zero, and then write the number - of VFs that should be enabled on the PF; the value written - should be less than or equal to the value in the sriov_totalvfs - file. A userspace application wanting to disable the VFs would - write a zero to this file. The core ensures that valid values - are written to this file, and returns errors when values are not - valid. For example, writing a 2 to this file when sriov_numvfs - is not 0 and not 2 already will return an error. Writing a 10 - when the value of sriov_totalvfs is 8 will return an error. diff --git a/trunk/Documentation/PCI/pci-iov-howto.txt b/trunk/Documentation/PCI/pci-iov-howto.txt index cfaca7e69893..fc73ef5d65b8 100644 --- a/trunk/Documentation/PCI/pci-iov-howto.txt +++ b/trunk/Documentation/PCI/pci-iov-howto.txt @@ -2,9 +2,6 @@ Copyright (C) 2009 Intel Corporation Yu Zhao - Update: November 2012 - -- sysfs-based SRIOV enable-/disable-ment - Donald Dutile 1. Overview @@ -27,21 +24,10 @@ real existing PCI device. 2.1 How can I enable SR-IOV capability -Multiple methods are available for SR-IOV enablement. -In the first method, the device driver (PF driver) will control the -enabling and disabling of the capability via API provided by SR-IOV core. -If the hardware has SR-IOV capability, loading its PF driver would -enable it and all VFs associated with the PF. Some PF drivers require -a module parameter to be set to determine the number of VFs to enable. -In the second method, a write to the sysfs file sriov_numvfs will -enable and disable the VFs associated with a PCIe PF. This method -enables per-PF, VF enable/disable values versus the first method, -which applies to all PFs of the same device. Additionally, the -PCI SRIOV core support ensures that enable/disable operations are -valid to reduce duplication in multiple drivers for the same -checks, e.g., check numvfs == 0 if enabling VFs, ensure -numvfs <= totalvfs. -The second method is the recommended method for new/future VF devices. +The device driver (PF driver) will control the enabling and disabling +of the capability via API provided by SR-IOV core. If the hardware +has SR-IOV capability, loading its PF driver would enable it and all +VFs associated with the PF. 2.2 How can I use the Virtual Functions @@ -54,22 +40,13 @@ requires device driver that is same as a normal PCI device's. 3.1 SR-IOV API To enable SR-IOV capability: -(a) For the first method, in the driver: int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); 'nr_virtfn' is number of VFs to be enabled. -(b) For the second method, from sysfs: - echo 'nr_virtfn' > \ - /sys/bus/pci/devices//sriov_numvfs To disable SR-IOV capability: -(a) For the first method, in the driver: void pci_disable_sriov(struct pci_dev *dev); -(b) For the second method, from sysfs: - echo 0 > \ - /sys/bus/pci/devices//sriov_numvfs To notify SR-IOV core of Virtual Function Migration: -(a) In the driver: irqreturn_t pci_sriov_migration(struct pci_dev *dev); 3.2 Usage example @@ -111,22 +88,6 @@ static void dev_shutdown(struct pci_dev *dev) ... } -static int dev_sriov_configure(struct pci_dev *dev, int numvfs) -{ - if (numvfs > 0) { - ... - pci_enable_sriov(dev, numvfs); - ... - return numvfs; - } - if (numvfs == 0) { - .... - pci_disable_sriov(dev); - ... - return 0; - } -} - static struct pci_driver dev_driver = { .name = "SR-IOV Physical Function driver", .id_table = dev_id_table, @@ -135,5 +96,4 @@ static struct pci_driver dev_driver = { .suspend = dev_suspend, .resume = dev_resume, .shutdown = dev_shutdown, - .sriov_configure = dev_sriov_configure, }; diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 17fb8eb3fa6b..46c3bff3ced2 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -374,7 +374,6 @@ config X86_NUMACHIP depends on NUMA depends on SMP depends on X86_X2APIC - depends on PCI_MMCONFIG ---help--- Adds support for Numascale NumaChip large-SMP systems. Needed to enable more than ~168 cores. diff --git a/trunk/arch/x86/include/asm/numachip/numachip.h b/trunk/arch/x86/include/asm/numachip/numachip.h deleted file mode 100644 index 1c6f7f6212c1..000000000000 --- a/trunk/arch/x86/include/asm/numachip/numachip.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Numascale NumaConnect-specific header file - * - * Copyright (C) 2012 Numascale AS. All rights reserved. - * - * Send feedback to - * - */ - -#ifndef _ASM_X86_NUMACHIP_NUMACHIP_H -#define _ASM_X86_NUMACHIP_NUMACHIP_H - -extern int __init pci_numachip_init(void); - -#endif /* _ASM_X86_NUMACHIP_NUMACHIP_H */ diff --git a/trunk/arch/x86/kernel/apic/apic_numachip.c b/trunk/arch/x86/kernel/apic/apic_numachip.c index 9c2aa89a11cb..a65829ac2b9a 100644 --- a/trunk/arch/x86/kernel/apic/apic_numachip.c +++ b/trunk/arch/x86/kernel/apic/apic_numachip.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -180,7 +179,6 @@ static int __init numachip_system_init(void) return 0; x86_cpuinit.fixup_cpu_id = fixup_cpu_id; - x86_init.pci.arch_init = pci_numachip_init; map_csrs(); diff --git a/trunk/arch/x86/pci/Makefile b/trunk/arch/x86/pci/Makefile index ee0af58ca5bd..3af5a1e79c9c 100644 --- a/trunk/arch/x86/pci/Makefile +++ b/trunk/arch/x86/pci/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_STA2X11) += sta2x11-fixup.o obj-$(CONFIG_X86_VISWS) += visws.o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o -obj-$(CONFIG_X86_NUMACHIP) += numachip.o obj-$(CONFIG_X86_INTEL_MID) += mrst.o diff --git a/trunk/arch/x86/pci/acpi.c b/trunk/arch/x86/pci/acpi.c index 0c01261fe5a8..192397c98606 100644 --- a/trunk/arch/x86/pci/acpi.c +++ b/trunk/arch/x86/pci/acpi.c @@ -12,7 +12,6 @@ struct pci_root_info { char name[16]; unsigned int res_num; struct resource *res; - resource_size_t *res_offset; struct pci_sysdata sd; #ifdef CONFIG_PCI_MMCONFIG bool mcfg_added; @@ -23,7 +22,6 @@ struct pci_root_info { }; static bool pci_use_crs = true; -static bool pci_ignore_seg = false; static int __init set_use_crs(const struct dmi_system_id *id) { @@ -37,14 +35,7 @@ static int __init set_nouse_crs(const struct dmi_system_id *id) return 0; } -static int __init set_ignore_seg(const struct dmi_system_id *id) -{ - printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident); - pci_ignore_seg = true; - return 0; -} - -static const struct dmi_system_id pci_crs_quirks[] __initconst = { +static const struct dmi_system_id pci_use_crs_table[] __initconst = { /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */ { .callback = set_use_crs, @@ -107,16 +98,6 @@ static const struct dmi_system_id pci_crs_quirks[] __initconst = { DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"), }, }, - - /* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */ - { - .callback = set_ignore_seg, - .ident = "HP xw9300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"), - }, - }, {} }; @@ -127,7 +108,7 @@ void __init pci_acpi_crs_quirks(void) if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) pci_use_crs = false; - dmi_check_system(pci_crs_quirks); + dmi_check_system(pci_use_crs_table); /* * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that @@ -324,7 +305,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) res->flags = flags; res->start = start; res->end = end; - info->res_offset[info->res_num] = addr.translation_offset; if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev, @@ -394,8 +374,7 @@ static void add_resources(struct pci_root_info *info, "ignoring host bridge window %pR (conflicts with %s %pR)\n", res, conflict->name, conflict); else - pci_add_resource_offset(resources, res, - info->res_offset[i]); + pci_add_resource(resources, res); } } @@ -403,8 +382,6 @@ static void free_pci_root_info_res(struct pci_root_info *info) { kfree(info->res); info->res = NULL; - kfree(info->res_offset); - info->res_offset = NULL; info->res_num = 0; } @@ -455,20 +432,10 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, return; size = sizeof(*info->res) * info->res_num; - info->res = kzalloc(size, GFP_KERNEL); - if (!info->res) { - info->res_num = 0; - return; - } - - size = sizeof(*info->res_offset) * info->res_num; info->res_num = 0; - info->res_offset = kzalloc(size, GFP_KERNEL); - if (!info->res_offset) { - kfree(info->res); - info->res = NULL; + info->res = kzalloc(size, GFP_KERNEL); + if (!info->res) return; - } acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, info); @@ -488,9 +455,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) int pxm; #endif - if (pci_ignore_seg) - domain = 0; - if (domain && !pci_domains_supported) { printk(KERN_WARNING "pci_bus %04x:%02x: " "ignored (multiple domains not supported)\n", diff --git a/trunk/arch/x86/pci/common.c b/trunk/arch/x86/pci/common.c index 6a6b01778dab..d07f3bbca5a1 100644 --- a/trunk/arch/x86/pci/common.c +++ b/trunk/arch/x86/pci/common.c @@ -628,8 +628,8 @@ int pcibios_add_device(struct pci_dev *dev) (PCI_FUNC(dev->devfn) == rom->function) && (dev->vendor == rom->vendor) && (dev->device == rom->devid)) { - dev->rom = (void *)(unsigned long)(pa_data + - offsetof(struct pci_setup_rom, romdata)); + dev->rom = pa_data + + offsetof(struct pci_setup_rom, romdata); dev->romlen = rom->pcilen; } } @@ -656,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } -int pci_ext_cfg_avail(void) +int pci_ext_cfg_avail(struct pci_dev *dev) { if (raw_pci_ext_ops) return 1; diff --git a/trunk/arch/x86/pci/numachip.c b/trunk/arch/x86/pci/numachip.c deleted file mode 100644 index 7307d9d12d15..000000000000 --- a/trunk/arch/x86/pci/numachip.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Numascale NumaConnect-specific PCI code - * - * Copyright (C) 2012 Numascale AS. All rights reserved. - * - * Send feedback to - * - * PCI accessor functions derived from mmconfig_64.c - * - */ - -#include -#include - -static u8 limit __read_mostly; - -static inline char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) -{ - struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus); - - if (cfg && cfg->virt) - return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12)); - return NULL; -} - -static int pci_mmcfg_read_numachip(unsigned int seg, unsigned int bus, - unsigned int devfn, int reg, int len, u32 *value) -{ - char __iomem *addr; - - /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ - if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { -err: *value = -1; - return -EINVAL; - } - - /* Ensure AMD Northbridges don't decode reads to other devices */ - if (unlikely(bus == 0 && devfn >= limit)) { - *value = -1; - return 0; - } - - rcu_read_lock(); - addr = pci_dev_base(seg, bus, devfn); - if (!addr) { - rcu_read_unlock(); - goto err; - } - - switch (len) { - case 1: - *value = mmio_config_readb(addr + reg); - break; - case 2: - *value = mmio_config_readw(addr + reg); - break; - case 4: - *value = mmio_config_readl(addr + reg); - break; - } - rcu_read_unlock(); - - return 0; -} - -static int pci_mmcfg_write_numachip(unsigned int seg, unsigned int bus, - unsigned int devfn, int reg, int len, u32 value) -{ - char __iomem *addr; - - /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ - if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) - return -EINVAL; - - /* Ensure AMD Northbridges don't decode writes to other devices */ - if (unlikely(bus == 0 && devfn >= limit)) - return 0; - - rcu_read_lock(); - addr = pci_dev_base(seg, bus, devfn); - if (!addr) { - rcu_read_unlock(); - return -EINVAL; - } - - switch (len) { - case 1: - mmio_config_writeb(addr + reg, value); - break; - case 2: - mmio_config_writew(addr + reg, value); - break; - case 4: - mmio_config_writel(addr + reg, value); - break; - } - rcu_read_unlock(); - - return 0; -} - -const struct pci_raw_ops pci_mmcfg_numachip = { - .read = pci_mmcfg_read_numachip, - .write = pci_mmcfg_write_numachip, -}; - -int __init pci_numachip_init(void) -{ - int ret = 0; - u32 val; - - /* For remote I/O, restrict bus 0 access to the actual number of AMD - Northbridges, which starts at device number 0x18 */ - ret = raw_pci_read(0, 0, PCI_DEVFN(0x18, 0), 0x60, sizeof(val), &val); - if (ret) - goto out; - - /* HyperTransport fabric size in bits 6:4 */ - limit = PCI_DEVFN(0x18 + ((val >> 4) & 7) + 1, 0); - - /* Use NumaChip PCI accessors for non-extended and extended access */ - raw_pci_ops = raw_pci_ext_ops = &pci_mmcfg_numachip; -out: - return ret; -} diff --git a/trunk/drivers/acpi/pci_bind.c b/trunk/drivers/acpi/pci_bind.c index a1dee29beed3..2ef04098cc1d 100644 --- a/trunk/drivers/acpi/pci_bind.c +++ b/trunk/drivers/acpi/pci_bind.c @@ -45,12 +45,11 @@ static int acpi_pci_unbind(struct acpi_device *device) device_set_run_wake(&dev->dev, false); pci_acpi_remove_pm_notifier(device); - acpi_power_resource_unregister_device(&dev->dev, device->handle); if (!dev->subordinate) goto out; - acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); + acpi_pci_irq_del_prt(dev->subordinate); device->ops.bind = NULL; device->ops.unbind = NULL; @@ -64,7 +63,7 @@ static int acpi_pci_bind(struct acpi_device *device) { acpi_status status; acpi_handle handle; - unsigned char bus; + struct pci_bus *bus; struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); @@ -72,7 +71,6 @@ static int acpi_pci_bind(struct acpi_device *device) return 0; pci_acpi_add_pm_notifier(device, dev); - acpi_power_resource_register_device(&dev->dev, device->handle); if (device->wakeup.flags.run_wake) device_set_run_wake(&dev->dev, true); @@ -102,11 +100,11 @@ static int acpi_pci_bind(struct acpi_device *device) goto out; if (dev->subordinate) - bus = dev->subordinate->number; + bus = dev->subordinate; else - bus = dev->bus->number; + bus = dev->bus; - acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); + acpi_pci_irq_add_prt(device->handle, bus); out: pci_dev_put(dev); diff --git a/trunk/drivers/acpi/pci_irq.c b/trunk/drivers/acpi/pci_irq.c index 8835cc38aa30..0eefa12e648c 100644 --- a/trunk/drivers/acpi/pci_irq.c +++ b/trunk/drivers/acpi/pci_irq.c @@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, } } -static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, +static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, struct acpi_pci_routing_table *prt) { struct acpi_prt_entry *entry; @@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert * it here. */ - entry->id.segment = segment; - entry->id.bus = bus; + entry->id.segment = pci_domain_nr(bus); + entry->id.bus = bus->number; entry->id.device = (prt->address >> 16) & 0xFFFF; entry->pin = prt->pin + 1; @@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, return 0; } -int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) +int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) entry = buffer.pointer; while (entry && (entry->length > 0)) { - acpi_pci_irq_add_entry(handle, segment, bus, entry); + acpi_pci_irq_add_entry(handle, bus, entry); entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length); } @@ -282,16 +282,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) return 0; } -void acpi_pci_irq_del_prt(int segment, int bus) +void acpi_pci_irq_del_prt(struct pci_bus *bus) { struct acpi_prt_entry *entry, *tmp; printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", - segment, bus); + pci_domain_nr(bus), bus->number); spin_lock(&acpi_prt_lock); list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { - if (segment == entry->id.segment && bus == entry->id.bus) { + if (pci_domain_nr(bus) == entry->id.segment + && bus->number == entry->id.bus) { list_del(&entry->list); kfree(entry); } diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index ab781f00e32d..bce469c0b48a 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -454,7 +454,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) acpi_handle handle; struct acpi_device *child; u32 flags, base_flags; - bool is_osc_granted = false; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -502,10 +501,52 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); + + /* + * All supported architectures that use ACPI have support for + * PCI domains, so we indicate this in _OSC support capabilities. + */ + flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; + acpi_pci_osc_support(root, flags); + + /* + * TBD: Need PCI interface for enumeration/configuration of roots. + */ + + mutex_lock(&acpi_pci_root_lock); + list_add_tail(&root->node, &acpi_pci_roots); + mutex_unlock(&acpi_pci_root_lock); + printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), root->segment, &root->secondary); + /* + * Scan the Root Bridge + * -------------------- + * Must do this prior to any attempt to bind the root device, as the + * PCI namespace does not get created until this call is made (and + * thus the root bridge's pci_dev does not exist). + */ + root->bus = pci_acpi_scan_root(root); + if (!root->bus) { + printk(KERN_ERR PREFIX + "Bus %04x:%02x not present in PCI namespace\n", + root->segment, (unsigned int)root->secondary.start); + result = -ENODEV; + goto out_del_root; + } + + /* + * Attach ACPI-PCI Context + * ----------------------- + * Thus binding the ACPI and PCI devices. + */ + result = acpi_pci_bind_root(device); + if (result) + goto out_del_root; + /* * PCI Routing Table * ----------------- @@ -513,36 +554,32 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) - result = acpi_pci_irq_add_prt(device->handle, root->segment, - root->secondary.start); - - root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); + result = acpi_pci_irq_add_prt(device->handle, root->bus); /* - * All supported architectures that use ACPI have support for - * PCI domains, so we indicate this in _OSC support capabilities. + * Scan and bind all _ADR-Based Devices */ - flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; - acpi_pci_osc_support(root, flags); + list_for_each_entry(child, &device->children, node) + acpi_pci_bridge_scan(child); /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail()) + if (pci_ext_cfg_avail(root->bus->self)) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; - if (pcie_aspm_support_enabled()) { + if (pcie_aspm_support_enabled()) flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; - } + OSC_CLOCK_PWR_CAPABILITY_SUPPORT; if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; if (flags != base_flags) { status = acpi_pci_osc_support(root, flags); if (ACPI_FAILURE(status)) { - dev_info(&device->dev, "ACPI _OSC support " + dev_info(root->bus->bridge, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); pcie_no_aspm(); flags = base_flags; } } + if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL @@ -551,81 +588,40 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (pci_aer_available()) { if (aer_acpi_firmware_first()) - dev_dbg(&device->dev, + dev_dbg(root->bus->bridge, "PCIe errors handled by BIOS.\n"); else flags |= OSC_PCI_EXPRESS_AER_CONTROL; } - dev_info(&device->dev, + dev_info(root->bus->bridge, "Requesting ACPI _OSC control (0x%02x)\n", flags); status = acpi_pci_osc_control_set(device->handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); if (ACPI_SUCCESS(status)) { - is_osc_granted = true; - dev_info(&device->dev, + dev_info(root->bus->bridge, "ACPI _OSC control (0x%02x) granted\n", flags); + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { + /* + * We have ASPM control, but the FADT indicates + * that it's unsupported. Clear it. + */ + pcie_clear_aspm(root->bus); + } } else { - is_osc_granted = false; - dev_info(&device->dev, + dev_info(root->bus->bridge, "ACPI _OSC request failed (%s), " "returned control mask: 0x%02x\n", acpi_format_exception(status), flags); + pr_info("ACPI _OSC control for PCIe not granted, " + "disabling ASPM\n"); + pcie_no_aspm(); } } else { - dev_info(&device->dev, - "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", flags); - } - - /* - * TBD: Need PCI interface for enumeration/configuration of roots. - */ - - mutex_lock(&acpi_pci_root_lock); - list_add_tail(&root->node, &acpi_pci_roots); - mutex_unlock(&acpi_pci_root_lock); - - /* - * Scan the Root Bridge - * -------------------- - * Must do this prior to any attempt to bind the root device, as the - * PCI namespace does not get created until this call is made (and - * thus the root bridge's pci_dev does not exist). - */ - root->bus = pci_acpi_scan_root(root); - if (!root->bus) { - printk(KERN_ERR PREFIX - "Bus %04x:%02x not present in PCI namespace\n", - root->segment, (unsigned int)root->secondary.start); - result = -ENODEV; - goto out_del_root; - } - - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - - /* ASPM setting */ - if (is_osc_granted) { - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) - pcie_clear_aspm(root->bus); - } else { - pr_info("ACPI _OSC control for PCIe not granted, " - "disabling ASPM\n"); - pcie_no_aspm(); + dev_info(root->bus->bridge, + "Unable to request _OSC control " + "(_OSC support mask: 0x%02x)\n", flags); } pci_acpi_add_bus_pm_notifier(device, root->bus); @@ -638,8 +634,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); - - acpi_pci_irq_del_prt(root->segment, root->secondary.start); end: kfree(root); return result; @@ -650,19 +644,12 @@ static int acpi_pci_root_start(struct acpi_device *device) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; - if (system_state != SYSTEM_BOOTING) - pci_assign_unassigned_bus_resources(root->bus); - mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->add) driver->add(root); mutex_unlock(&acpi_pci_root_lock); - /* need to after hot-added ioapic is registered */ - if (system_state != SYSTEM_BOOTING) - pci_enable_bridges(root->bus); - pci_bus_add_devices(root->bus); return 0; @@ -670,29 +657,17 @@ static int acpi_pci_root_start(struct acpi_device *device) static int acpi_pci_root_remove(struct acpi_device *device, int type) { - acpi_status status; - acpi_handle handle; struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; - pci_stop_root_bus(root->bus); - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) + list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root); - mutex_unlock(&acpi_pci_root_lock); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_SUCCESS(status)) - acpi_pci_irq_del_prt(root->segment, root->secondary.start); - - pci_remove_root_bus(root->bus); - - mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index 3dee68612c9e..aef45d3113ba 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap) G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE)); log2_width = fls(adap->params.pci.width) - 1; acklat = ack_lat[log2_width][pldsize]; - if (val & PCI_EXP_LNKCTL_ASPM_L0S) /* check LOsEnable */ + if (val & 1) /* check LOsEnable */ acklat += fst_trn_tx * 4; rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4; diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index 71d82078fc7f..f088f4bf9a26 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -125,23 +125,23 @@ static void ath_pci_aspm_init(struct ath_common *common) if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && (AR_SREV_9285(ah))) { - /* Bluetooth coexistence requires disabling ASPM. */ + /* Bluetooth coexistance requires disabling ASPM. */ pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1); + PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); /* * Both upstream and downstream PCIe components should * have the same ASPM settings. */ pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1); + PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); ath_info(common, "Disabling ASPM since BTCOEX is enabled\n"); return; } pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm); - if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) { + if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { ah->aspm_enabled = true; /* Initialize PCIe PM and SERDES registers. */ ath9k_hw_configpcipowersave(ah, false); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965.h b/trunk/drivers/net/wireless/iwlegacy/4965.h index 1b15b0b2292b..2d092f328547 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965.h +++ b/trunk/drivers/net/wireless/iwlegacy/4965.h @@ -917,6 +917,10 @@ struct il4965_scd_bc_tbl { /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 +/* PCI register values */ +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 + #define IL4965_DEFAULT_TX_RETRY 15 /* EEPROM */ diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index 7e16d10a7f14..318ed3c9fe74 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -1183,10 +1183,9 @@ EXPORT_SYMBOL(il_power_update_mode); void il_power_initialize(struct il_priv *il) { - u16 lctl; + u16 lctl = il_pcie_link_ctl(il); - pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl); - il->power_data.pci_pm = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); + il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); il->power_data.debug_sleep_level_override = -1; @@ -4234,8 +4233,9 @@ il_apm_init(struct il_priv *il) * power savings, even without L1. */ if (il->cfg->set_l0s) { - pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl); - if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { + lctl = il_pcie_link_ctl(il); + if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == + PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ il_set_bit(il, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); diff --git a/trunk/drivers/net/wireless/iwlegacy/common.h b/trunk/drivers/net/wireless/iwlegacy/common.h index e181f3b573d9..b4bb813362bd 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.h +++ b/trunk/drivers/net/wireless/iwlegacy/common.h @@ -1829,6 +1829,14 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd); * PCI * *****************************************************/ +static inline u16 +il_pcie_link_ctl(struct il_priv *il) +{ + u16 pci_lnk_ctl; + pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl); + return pci_lnk_ctl; +} + void il_bg_watchdog(unsigned long data); u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval); __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon, @@ -2426,6 +2434,10 @@ struct il_tfd { /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 +/* PCI register values */ +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 + struct il_rate_info { u8 plcp; /* uCode API: RATE_6M_PLCP, etc. */ u8 plcp_siso; /* uCode API: RATE_SISO_6M_PLCP, etc. */ diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index 1dfa6be03058..fe0fffd04304 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -670,12 +670,21 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 -static void iwl_apm_config(struct iwl_trans *trans) +static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 lctl; + u16 pci_lnk_ctl; + + pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, + &pci_lnk_ctl); + return pci_lnk_ctl; +} +static void iwl_apm_config(struct iwl_trans *trans) +{ /* * HW bug W/A for instability in PCIe bus L0S->L1 transition. * Check if BIOS (or OS) enabled L1-ASPM on this device. @@ -684,9 +693,10 @@ static void iwl_apm_config(struct iwl_trans *trans) * If not (unlikely), enable L0S, so there is at least some * power savings, even without L1. */ + u16 lctl = iwl_pciexp_link_ctrl(trans); - pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); - if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { + if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == + PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, trans->dev, @@ -697,7 +707,7 @@ static void iwl_apm_config(struct iwl_trans *trans) dev_printk(KERN_INFO, trans->dev, "L1 Disabled; Enabling L0S\n"); } - trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); + trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); } /* diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index ad6a8b635692..4f22fa16a3ba 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -325,7 +325,10 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), } else next = dev->bus_list.next; + /* Run device routines with the device locked */ + device_lock(&dev->dev); retval = cb(dev, userdata); + device_unlock(&dev->dev); if (retval) break; } diff --git a/trunk/drivers/pci/ioapic.c b/trunk/drivers/pci/ioapic.c index 22436f74eb50..205af8dc83c2 100644 --- a/trunk/drivers/pci/ioapic.c +++ b/trunk/drivers/pci/ioapic.c @@ -125,5 +125,3 @@ static void __exit ioapic_exit(void) module_init(ioapic_init); module_exit(ioapic_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/pci/iov.c b/trunk/drivers/pci/iov.c index bafd2bbcaf65..aeccc911abb8 100644 --- a/trunk/drivers/pci/iov.c +++ b/trunk/drivers/pci/iov.c @@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset) virtfn->resource[i].name = pci_name(virtfn); virtfn->resource[i].flags = res->flags; size = resource_size(res); - do_div(size, iov->total_VFs); + do_div(size, iov->total); virtfn->resource[i].start = res->start + size * id; virtfn->resource[i].end = virtfn->resource[i].start + size - 1; rc = request_resource(res, &virtfn->resource[i]); @@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev) u16 status; struct pci_sriov *iov = dev->sriov; - if (!iov->num_VFs) + if (!iov->nr_virtfn) return 0; if (!(iov->cap & PCI_SRIOV_CAP_VFM)) @@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work) u16 status; struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask); - for (i = iov->initial_VFs; i < iov->num_VFs; i++) { + for (i = iov->initial; i < iov->nr_virtfn; i++) { state = readb(iov->mstate + i); if (state == PCI_SRIOV_VFM_MI) { writeb(PCI_SRIOV_VFM_AV, iov->mstate + i); @@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn) resource_size_t pa; struct pci_sriov *iov = dev->sriov; - if (nr_virtfn <= iov->initial_VFs) + if (nr_virtfn <= iov->initial) return 0; pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table); @@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) if (!nr_virtfn) return 0; - if (iov->num_VFs) + if (iov->nr_virtfn) return -EINVAL; pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial); - if (initial > iov->total_VFs || - (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs))) + if (initial > iov->total || + (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total))) return -EIO; - if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs || + if (nr_virtfn < 0 || nr_virtfn > iov->total || (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) return -EINVAL; @@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) msleep(100); pci_cfg_access_unlock(dev); - iov->initial_VFs = initial; + iov->initial = initial; if (nr_virtfn < initial) initial = nr_virtfn; @@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) } kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE); - iov->num_VFs = nr_virtfn; + iov->nr_virtfn = nr_virtfn; return 0; @@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev) int i; struct pci_sriov *iov = dev->sriov; - if (!iov->num_VFs) + if (!iov->nr_virtfn) return; if (iov->cap & PCI_SRIOV_CAP_VFM) sriov_disable_migration(dev); - for (i = 0; i < iov->num_VFs; i++) + for (i = 0; i < iov->nr_virtfn; i++) virtfn_remove(dev, i, 0); iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); @@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev) if (iov->link != dev->devfn) sysfs_remove_link(&dev->dev.kobj, "dep_link"); - iov->num_VFs = 0; + iov->nr_virtfn = 0; } static int sriov_init(struct pci_dev *dev, int pos) @@ -496,7 +496,7 @@ static int sriov_init(struct pci_dev *dev, int pos) iov->pos = pos; iov->nres = nres; iov->ctrl = ctrl; - iov->total_VFs = total; + iov->total = total; iov->offset = offset; iov->stride = stride; iov->pgsz = pgsz; @@ -529,7 +529,7 @@ static int sriov_init(struct pci_dev *dev, int pos) static void sriov_release(struct pci_dev *dev) { - BUG_ON(dev->sriov->num_VFs); + BUG_ON(dev->sriov->nr_virtfn); if (dev != dev->sriov->dev) pci_dev_put(dev->sriov->dev); @@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev) pci_update_resource(dev, i); pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); if (iov->ctrl & PCI_SRIOV_CTRL_VFE) msleep(100); @@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { if (!dev->is_physfn) continue; - busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1); + busnr = virtfn_bus(dev, dev->sriov->total - 1); if (busnr > max) max = busnr; } @@ -729,56 +729,9 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration); */ int pci_num_vf(struct pci_dev *dev) { - if (!dev->is_physfn) + if (!dev || !dev->is_physfn) return 0; - - return dev->sriov->num_VFs; -} -EXPORT_SYMBOL_GPL(pci_num_vf); - -/** - * pci_sriov_set_totalvfs -- reduce the TotalVFs available - * @dev: the PCI PF device - * numvfs: number that should be used for TotalVFs supported - * - * Should be called from PF driver's probe routine with - * device's mutex held. - * - * Returns 0 if PF is an SRIOV-capable device and - * value of numvfs valid. If not a PF with VFS, return -EINVAL; - * if VFs already enabled, return -EBUSY. - */ -int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) -{ - if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs)) - return -EINVAL; - - /* Shouldn't change if VFs already enabled */ - if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE) - return -EBUSY; else - dev->sriov->driver_max_VFs = numvfs; - - return 0; -} -EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs); - -/** - * pci_sriov_get_totalvfs -- get total VFs supported on this devic3 - * @dev: the PCI PF device - * - * For a PCIe device with SRIOV support, return the PCIe - * SRIOV capability value of TotalVFs or the value of driver_max_VFs - * if the driver reduced it. Otherwise, -EINVAL. - */ -int pci_sriov_get_totalvfs(struct pci_dev *dev) -{ - if (!dev->is_physfn) - return -EINVAL; - - if (dev->sriov->driver_max_VFs) - return dev->sriov->driver_max_VFs; - - return dev->sriov->total_VFs; + return dev->sriov->nr_virtfn; } -EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs); +EXPORT_SYMBOL_GPL(pci_num_vf); diff --git a/trunk/drivers/pci/irq.c b/trunk/drivers/pci/irq.c index b008cf86b9c3..e5f69a43b1b1 100644 --- a/trunk/drivers/pci/irq.c +++ b/trunk/drivers/pci/irq.c @@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason) { struct pci_dev *parent = to_pci_dev(pdev->dev.parent); - dev_err(&pdev->dev, - "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n", - dev_name(&parent->dev), parent->vendor, parent->device); - dev_err(&pdev->dev, "%s\n", reason); - dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n"); + dev_printk(KERN_ERR, &pdev->dev, + "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n", + dev_name(&parent->dev), parent->vendor, parent->device); + dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason); + dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n"); WARN_ON(1); } diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index c3088e54fc43..94c6e2aa03d6 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -256,26 +256,31 @@ struct drv_dev_and_id { static long local_pci_probe(void *_ddi) { struct drv_dev_and_id *ddi = _ddi; - struct pci_dev *pci_dev = ddi->dev; - struct pci_driver *pci_drv = ddi->drv; - struct device *dev = &pci_dev->dev; + struct device *dev = &ddi->dev->dev; + struct device *parent = dev->parent; int rc; - /* - * Unbound PCI devices are always put in D0, regardless of - * runtime PM status. During probe, the device is set to - * active and the usage count is incremented. If the driver - * supports runtime PM, it should call pm_runtime_put_noidle() - * in its probe routine and pm_runtime_get_noresume() in its - * remove routine. + /* The parent bridge must be in active state when probing */ + if (parent) + pm_runtime_get_sync(parent); + /* Unbound PCI devices are always set to disabled and suspended. + * During probe, the device is set to enabled and active and the + * usage count is incremented. If the driver supports runtime PM, + * it should call pm_runtime_put_noidle() in its probe routine and + * pm_runtime_get_noresume() in its remove routine. */ - pm_runtime_get_sync(dev); - pci_dev->driver = pci_drv; - rc = pci_drv->probe(pci_dev, ddi->id); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + rc = ddi->drv->probe(ddi->dev, ddi->id); if (rc) { - pci_dev->driver = NULL; - pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); } + if (parent) + pm_runtime_put(parent); return rc; } @@ -325,8 +330,10 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) id = pci_match_device(drv, pci_dev); if (id) error = pci_call_probe(drv, pci_dev, id); - if (error >= 0) + if (error >= 0) { + pci_dev->driver = drv; error = 0; + } } return error; } @@ -362,7 +369,9 @@ static int pci_device_remove(struct device * dev) } /* Undo the runtime PM settings in local_pci_probe() */ - pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); /* * If the device is still on, set the power state as "unknown", @@ -389,8 +398,6 @@ static void pci_device_shutdown(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; - pm_runtime_resume(dev); - if (drv && drv->shutdown) drv->shutdown(pci_dev); pci_msi_shutdown(pci_dev); @@ -401,6 +408,16 @@ static void pci_device_shutdown(struct device *dev) * continue to do DMA */ pci_disable_device(pci_dev); + + /* + * Devices may be enabled to wake up by runtime PM, but they need not + * be supposed to wake up the system from its "power off" state (e.g. + * ACPI S5). Therefore disable wakeup for all devices that aren't + * supposed to wake up the system at this point. The state argument + * will be ignored by pci_enable_wake(). + */ + if (!device_may_wakeup(dev)) + pci_enable_wake(pci_dev, PCI_UNKNOWN, false); } #ifdef CONFIG_PM @@ -985,13 +1002,6 @@ static int pci_pm_runtime_suspend(struct device *dev) pci_power_t prev = pci_dev->current_state; int error; - /* - * If pci_dev->driver is not set (unbound), the device should - * always remain in D0 regardless of the runtime PM status - */ - if (!pci_dev->driver) - return 0; - if (!pm || !pm->runtime_suspend) return -ENOSYS; @@ -1013,10 +1023,10 @@ static int pci_pm_runtime_suspend(struct device *dev) return 0; } - if (!pci_dev->state_saved) { + if (!pci_dev->state_saved) pci_save_state(pci_dev); - pci_finish_runtime_suspend(pci_dev); - } + + pci_finish_runtime_suspend(pci_dev); return 0; } @@ -1027,13 +1037,6 @@ static int pci_pm_runtime_resume(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - /* - * If pci_dev->driver is not set (unbound), the device should - * always remain in D0 regardless of the runtime PM status - */ - if (!pci_dev->driver) - return 0; - if (!pm || !pm->runtime_resume) return -ENOSYS; @@ -1051,16 +1054,8 @@ static int pci_pm_runtime_resume(struct device *dev) static int pci_pm_runtime_idle(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - /* - * If pci_dev->driver is not set (unbound), the device should - * always remain in D0 regardless of the runtime PM status - */ - if (!pci_dev->driver) - goto out; - if (!pm) return -ENOSYS; @@ -1070,8 +1065,8 @@ static int pci_pm_runtime_idle(struct device *dev) return ret; } -out: pm_runtime_suspend(dev); + return 0; } diff --git a/trunk/drivers/pci/pci-stub.c b/trunk/drivers/pci/pci-stub.c index 6e47c519c510..775e933c2225 100644 --- a/trunk/drivers/pci/pci-stub.c +++ b/trunk/drivers/pci/pci-stub.c @@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is " static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id) { - dev_info(&dev->dev, "claimed by stub\n"); + dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n"); return 0; } diff --git a/trunk/drivers/pci/pci-sysfs.c b/trunk/drivers/pci/pci-sysfs.c index 5d883a152789..02d107b15281 100644 --- a/trunk/drivers/pci/pci-sysfs.c +++ b/trunk/drivers/pci/pci-sysfs.c @@ -404,106 +404,6 @@ static ssize_t d3cold_allowed_show(struct device *dev, } #endif -#ifdef CONFIG_PCI_IOV -static ssize_t sriov_totalvfs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev); - - return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev)); -} - - -static ssize_t sriov_numvfs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev); - - return sprintf(buf, "%u\n", pdev->sriov->num_VFs); -} - -/* - * num_vfs > 0; number of vfs to enable - * num_vfs = 0; disable all vfs - * - * Note: SRIOV spec doesn't allow partial VF - * disable, so its all or none. - */ -static ssize_t sriov_numvfs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int num_vfs_enabled = 0; - int num_vfs; - int ret = 0; - u16 total; - - if (kstrtoint(buf, 0, &num_vfs) < 0) - return -EINVAL; - - /* is PF driver loaded w/callback */ - if (!pdev->driver || !pdev->driver->sriov_configure) { - dev_info(&pdev->dev, - "Driver doesn't support SRIOV configuration via sysfs\n"); - return -ENOSYS; - } - - /* if enabling vf's ... */ - total = pci_sriov_get_totalvfs(pdev); - /* Requested VFs to enable < totalvfs and none enabled already */ - if ((num_vfs > 0) && (num_vfs <= total)) { - if (pdev->sriov->num_VFs == 0) { - num_vfs_enabled = - pdev->driver->sriov_configure(pdev, num_vfs); - if ((num_vfs_enabled >= 0) && - (num_vfs_enabled != num_vfs)) { - dev_warn(&pdev->dev, - "Only %d VFs enabled\n", - num_vfs_enabled); - return count; - } else if (num_vfs_enabled < 0) - /* error code from driver callback */ - return num_vfs_enabled; - } else if (num_vfs == pdev->sriov->num_VFs) { - dev_warn(&pdev->dev, - "%d VFs already enabled; no enable action taken\n", - num_vfs); - return count; - } else { - dev_warn(&pdev->dev, - "%d VFs already enabled. Disable before enabling %d VFs\n", - pdev->sriov->num_VFs, num_vfs); - return -EINVAL; - } - } - - /* disable vfs */ - if (num_vfs == 0) { - if (pdev->sriov->num_VFs != 0) { - ret = pdev->driver->sriov_configure(pdev, 0); - return ret ? ret : count; - } else { - dev_warn(&pdev->dev, - "All VFs disabled; no disable action taken\n"); - return count; - } - } - - dev_err(&pdev->dev, - "Invalid value for number of VFs to enable: %d\n", num_vfs); - - return -EINVAL; -} - -static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); -static struct device_attribute sriov_numvfs_attr = - __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), - sriov_numvfs_show, sriov_numvfs_store); -#endif /* CONFIG_PCI_IOV */ - struct device_attribute pci_dev_attrs[] = { __ATTR_RO(resource), __ATTR_RO(vendor), @@ -558,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } 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, @@ -1369,20 +1303,29 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) pdev->rom_attr = attr; } + if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { + retval = device_create_file(&pdev->dev, &vga_attr); + if (retval) + goto err_rom_file; + } + /* add platform-specific attributes */ retval = pcibios_add_platform_entries(pdev); if (retval) - goto err_rom_file; + goto err_vga_file; /* add sysfs entries for various capabilities */ retval = pci_create_capabilities_sysfs(pdev); if (retval) - goto err_rom_file; + goto err_vga_file; pci_create_firmware_label_files(pdev); return 0; +err_vga_file: + if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) + device_remove_file(&pdev->dev, &vga_attr); err_rom_file: if (rom_size) { sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); @@ -1468,62 +1411,3 @@ static int __init pci_sysfs_init(void) } late_initcall(pci_sysfs_init); - -static struct attribute *pci_dev_dev_attrs[] = { - &vga_attr.attr, - NULL, -}; - -static umode_t pci_dev_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct pci_dev *pdev = to_pci_dev(dev); - - if (a == &vga_attr.attr) - if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return 0; - - return a->mode; -} - -#ifdef CONFIG_PCI_IOV -static struct attribute *sriov_dev_attrs[] = { - &sriov_totalvfs_attr.attr, - &sriov_numvfs_attr.attr, - NULL, -}; - -static umode_t sriov_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - - if (!dev_is_pf(dev)) - return 0; - - return a->mode; -} - -static struct attribute_group sriov_dev_attr_group = { - .attrs = sriov_dev_attrs, - .is_visible = sriov_attrs_are_visible, -}; -#endif /* CONFIG_PCI_IOV */ - -static struct attribute_group pci_dev_attr_group = { - .attrs = pci_dev_dev_attrs, - .is_visible = pci_dev_attrs_are_visible, -}; - -static const struct attribute_group *pci_dev_attr_groups[] = { - &pci_dev_attr_group, -#ifdef CONFIG_PCI_IOV - &sriov_dev_attr_group, -#endif - NULL, -}; - -struct device_type pci_dev_type = { - .groups = pci_dev_attr_groups, -}; diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 7c2e25ee2c5a..fa0ddd51a216 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -1591,25 +1591,15 @@ void pci_pme_active(struct pci_dev *dev, bool enable) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); - /* - * PCI (as opposed to PCIe) PME requires that the device have - * its PME# line hooked up correctly. Not all hardware vendors - * do this, so the PME never gets delivered and the device - * remains asleep. The easiest way around this is to - * periodically walk the list of suspended devices and check - * whether any have their PME flag set. The assumption is that - * we'll wake up often enough anyway that this won't be a huge - * hit, and the power savings from the devices will still be a - * win. - * - * Although PCIe uses in-band PME message instead of PME# line - * to report PME, PME does not work for some PCIe devices in - * reality. For example, there are devices that set their PME - * status bits, but don't really bother to send a PME message; - * there are PCI Express Root Ports that don't bother to - * trigger interrupts when they receive PME messages from the - * devices below. So PME poll is used for PCIe devices too. - */ + /* PCI (as opposed to PCIe) PME requires that the device have + its PME# line hooked up correctly. Not all hardware vendors + do this, so the PME never gets delivered and the device + remains asleep. The easiest way around this is to + periodically walk the list of suspended devices and check + whether any have their PME flag set. The assumption is that + we'll wake up often enough anyway that this won't be a huge + hit, and the power savings from the devices will still be a + win. */ if (dev->pme_poll) { struct pci_pme_device *pme_dev; @@ -1881,38 +1871,6 @@ bool pci_dev_run_wake(struct pci_dev *dev) } 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. @@ -1923,8 +1881,6 @@ void pci_pm_init(struct pci_dev *dev) u16 pmc; pm_runtime_forbid(&dev->dev); - pm_runtime_set_active(&dev->dev); - pm_runtime_enable(&dev->dev); device_enable_async_suspend(&dev->dev); dev->wakeup_prepared = false; @@ -3890,13 +3846,14 @@ static void __devinit pci_no_domains(void) } /** - * pci_ext_cfg_avail - can we access extended PCI config space? + * pci_ext_cfg_enabled - can we access extended PCI config space? + * @dev: The PCI device of the root bridge. * * Returns 1 if we can access PCI extended config space (offsets * greater than 0xff). This is the default implementation. Architecture * implementations can override this. */ -int __weak pci_ext_cfg_avail(void) +int __weak pci_ext_cfg_avail(struct pci_dev *dev) { return 1; } diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index 11a713bc7293..bacbcba69cf3 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -72,8 +72,6 @@ extern void pci_disable_enabled_device(struct pci_dev *dev); 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); @@ -159,7 +157,6 @@ static inline int pci_no_d1d2(struct pci_dev *dev) } extern struct device_attribute pci_dev_attrs[]; extern struct device_attribute pcibus_dev_attrs[]; -extern struct device_type pci_dev_type; #ifdef CONFIG_HOTPLUG extern struct bus_attribute pci_bus_attrs[]; #else @@ -235,14 +232,13 @@ struct pci_sriov { int nres; /* number of resources */ u32 cap; /* SR-IOV Capabilities */ u16 ctrl; /* SR-IOV Control */ - u16 total_VFs; /* total VFs associated with the PF */ - u16 initial_VFs; /* initial VFs associated with the PF */ - u16 num_VFs; /* number of VFs available */ + u16 total; /* total VFs associated with the PF */ + u16 initial; /* initial VFs associated with the PF */ + u16 nr_virtfn; /* number of VFs available */ u16 offset; /* first VF Routing ID offset */ u16 stride; /* following VF stride */ u32 pgsz; /* page size for BAR alignment */ u8 link; /* Function Dependency Link */ - u16 driver_max_VFs; /* max num VFs driver supports */ struct pci_dev *dev; /* lowest numbered PF */ struct pci_dev *self; /* this PF */ struct mutex lock; /* lock for VF bus */ diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.h b/trunk/drivers/pci/pcie/aer/aerdrv.h index 22f840f4dda1..94a7598eb262 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.h +++ b/trunk/drivers/pci/pcie/aer/aerdrv.h @@ -87,9 +87,6 @@ struct aer_broadcast_data { static inline pci_ers_result_t merge_result(enum pci_ers_result orig, enum pci_ers_result new) { - if (new == PCI_ERS_RESULT_NO_AER_DRIVER) - return PCI_ERS_RESULT_NO_AER_DRIVER; - if (new == PCI_ERS_RESULT_NONE) return orig; @@ -100,7 +97,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, break; case PCI_ERS_RESULT_DISCONNECT: if (new == PCI_ERS_RESULT_NEED_RESET) - orig = PCI_ERS_RESULT_NEED_RESET; + orig = new; break; default: break; diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_core.c b/trunk/drivers/pci/pcie/aer/aerdrv_core.c index 421bbc5fee32..06bad96af415 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_core.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_core.c @@ -213,7 +213,6 @@ static int report_error_detected(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; - device_lock(&dev->dev); dev->error_state = result_data->state; if (!dev->driver || @@ -232,28 +231,12 @@ static int report_error_detected(struct pci_dev *dev, void *data) dev->driver ? "no AER-aware driver" : "no driver"); } - - /* - * If there's any device in the subtree that does not - * have an error_detected callback, returning - * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of - * the subsequent mmio_enabled/slot_reset/resume - * callbacks of "any" device in the subtree. All the - * devices in the subtree are left in the error state - * without recovery. - */ - - if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) - vote = PCI_ERS_RESULT_NO_AER_DRIVER; - else - vote = PCI_ERS_RESULT_NONE; - } else { - err_handler = dev->driver->err_handler; - vote = err_handler->error_detected(dev, result_data->state); + return 0; } + err_handler = dev->driver->err_handler; + vote = err_handler->error_detected(dev, result_data->state); result_data->result = merge_result(result_data->result, vote); - device_unlock(&dev->dev); return 0; } @@ -264,17 +247,14 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; - device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->mmio_enabled) - goto out; + return 0; err_handler = dev->driver->err_handler; vote = err_handler->mmio_enabled(dev); result_data->result = merge_result(result_data->result, vote); -out: - device_unlock(&dev->dev); return 0; } @@ -285,17 +265,14 @@ static int report_slot_reset(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; - device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->slot_reset) - goto out; + return 0; err_handler = dev->driver->err_handler; vote = err_handler->slot_reset(dev); result_data->result = merge_result(result_data->result, vote); -out: - device_unlock(&dev->dev); return 0; } @@ -303,18 +280,15 @@ static int report_resume(struct pci_dev *dev, void *data) { const struct pci_error_handlers *err_handler; - device_lock(&dev->dev); dev->error_state = pci_channel_io_normal; if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->resume) - goto out; + return 0; err_handler = dev->driver->err_handler; err_handler->resume(dev); -out: - device_unlock(&dev->dev); return 0; } diff --git a/trunk/drivers/pci/pcie/aspm.c b/trunk/drivers/pci/pcie/aspm.c index b52630b8eada..213753b283a6 100644 --- a/trunk/drivers/pci/pcie/aspm.c +++ b/trunk/drivers/pci/pcie/aspm.c @@ -242,7 +242,8 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) return; /* Training failed. Restore common clock configurations */ - dev_err(&parent->dev, "ASPM: Could not configure common clock\n"); + dev_printk(KERN_ERR, &parent->dev, + "ASPM: Could not configure common clock\n"); list_for_each_entry(child, &linkbus->devices, bus_list) pcie_capability_write_word(child, PCI_EXP_LNKCTL, child_reg[PCI_FUNC(child->devfn)]); @@ -426,8 +427,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) { - pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC, val); + pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val); } static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) @@ -442,12 +442,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) return; /* Convert ASPM state to upstream/downstream ASPM register state */ if (state & ASPM_STATE_L0S_UP) - dwstream |= PCI_EXP_LNKCTL_ASPM_L0S; + dwstream |= PCIE_LINK_STATE_L0S; if (state & ASPM_STATE_L0S_DW) - upstream |= PCI_EXP_LNKCTL_ASPM_L0S; + upstream |= PCIE_LINK_STATE_L0S; if (state & ASPM_STATE_L1) { - upstream |= PCI_EXP_LNKCTL_ASPM_L1; - dwstream |= PCI_EXP_LNKCTL_ASPM_L1; + upstream |= PCIE_LINK_STATE_L1; + dwstream |= PCIE_LINK_STATE_L1; } /* * Spec 2.0 suggests all functions should be configured the @@ -507,7 +507,9 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) */ pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { - dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n"); + dev_printk(KERN_INFO, &child->dev, "disabling ASPM" + " on pre-1.1 PCIe device. You can enable it" + " with 'pcie_aspm=force'\n"); return -EINVAL; } } diff --git a/trunk/drivers/pci/pcie/portdrv_core.c b/trunk/drivers/pci/pcie/portdrv_core.c index b42133afca98..d03a7a39b2d8 100644 --- a/trunk/drivers/pci/pcie/portdrv_core.c +++ b/trunk/drivers/pci/pcie/portdrv_core.c @@ -120,7 +120,8 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) * the value in this field indicates which MSI-X Table entry is * used to generate the interrupt message." */ - pcie_capability_read_word(dev, PCI_EXP_FLAGS, ®16); + pos = pci_pcie_cap(dev); + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9; if (entry >= nr_entries) goto Error; @@ -271,8 +272,7 @@ static int get_port_device_capability(struct pci_dev *dev) } /* Hot-Plug Capable */ - if ((cap_mask & PCIE_PORT_SERVICE_HP) && - dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) { + if (cap_mask & PCIE_PORT_SERVICE_HP) { pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index d46ef2df23da..ec909afa90b6 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = { void pcie_update_link_speed(struct pci_bus *bus, u16 linksta) { - bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS]; + bus->cur_bus_speed = pcie_link_speed[linksta & 0xf]; } EXPORT_SYMBOL_GPL(pcie_update_link_speed); @@ -579,16 +579,14 @@ static void pci_set_bus_speed(struct pci_bus *bus) if (pos) { u16 status; enum pci_bus_speed max; + pci_read_config_word(bridge, pos + 2, &status); - pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS, - &status); - - if (status & PCI_X_SSTATUS_533MHZ) { + if (status & 0x8000) { max = PCI_SPEED_133MHz_PCIX_533; - } else if (status & PCI_X_SSTATUS_266MHZ) { + } else if (status & 0x4000) { max = PCI_SPEED_133MHz_PCIX_266; - } else if (status & PCI_X_SSTATUS_133MHZ) { - if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) { + } else if (status & 0x0002) { + if (((status >> 12) & 0x3) == 2) { max = PCI_SPEED_133MHz_PCIX_ECC; } else { max = PCI_SPEED_133MHz_PCIX; @@ -598,8 +596,7 @@ static void pci_set_bus_speed(struct pci_bus *bus) } bus->max_bus_speed = max; - bus->cur_bus_speed = pcix_bus_speed[ - (status & PCI_X_SSTATUS_FREQ) >> 6]; + bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf]; return; } @@ -610,7 +607,7 @@ static void pci_set_bus_speed(struct pci_bus *bus) u16 linksta; pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); - bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; + bus->max_bus_speed = pcie_link_speed[linkcap & 0xf]; pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); @@ -978,7 +975,6 @@ int pci_setup_device(struct pci_dev *dev) dev->sysdata = dev->bus->sysdata; dev->dev.parent = dev->bus->bridge; dev->dev.bus = &pci_bus_type; - dev->dev.type = &pci_dev_type; dev->hdr_type = hdr_type & 0x7f; dev->multifunction = !!(hdr_type & 0x80); dev->error_state = pci_channel_io_normal; @@ -1894,28 +1890,6 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge) return max; } -/** - * pci_rescan_bus - scan a PCI bus for devices. - * @bus: PCI bus to scan - * - * Scan a PCI bus and child buses for new devices, adds them, - * and enables them. - * - * Returns the max number of subordinate bus discovered. - */ -unsigned int __ref pci_rescan_bus(struct pci_bus *bus) -{ - unsigned int max; - - max = pci_scan_child_bus(bus); - pci_assign_unassigned_bus_resources(bus); - pci_enable_bridges(bus); - pci_bus_add_devices(bus); - - return max; -} -EXPORT_SYMBOL_GPL(pci_rescan_bus); - EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_bridge); diff --git a/trunk/drivers/pci/proc.c b/trunk/drivers/pci/proc.c index 9b8505ccc56d..eb907a8faf2a 100644 --- a/trunk/drivers/pci/proc.c +++ b/trunk/drivers/pci/proc.c @@ -76,8 +76,6 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp 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); @@ -123,8 +121,6 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp cnt--; } - pci_config_pm_runtime_put(dev); - *ppos = pos; return nbytes; } @@ -150,8 +146,6 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof 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); @@ -197,8 +191,6 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof cnt--; } - pci_config_pm_runtime_put(dev); - *ppos = pos; i_size_write(ino, dp->size); return nbytes; diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 0c59f7aba12b..7a451ff56ecc 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -1790,45 +1790,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, quirk_tc86c001_ide); -/* - * PLX PCI 9050 PCI Target bridge controller has an errata that prevents the - * local configuration registers accessible via BAR0 (memory) or BAR1 (i/o) - * being read correctly if bit 7 of the base address is set. - * The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128). - * Re-allocate the regions to a 256-byte boundary if necessary. - */ -static void __devinit quirk_plx_pci9050(struct pci_dev *dev) -{ - unsigned int bar; - - /* Fixed in revision 2 (PCI 9052). */ - if (dev->revision >= 2) - return; - for (bar = 0; bar <= 1; bar++) - if (pci_resource_len(dev, bar) == 0x80 && - (pci_resource_start(dev, bar) & 0x80)) { - struct resource *r = &dev->resource[bar]; - dev_info(&dev->dev, - "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n", - bar); - r->start = 0; - r->end = 0xff; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - quirk_plx_pci9050); -/* - * The following Meilhaus (vendor ID 0x1402) device IDs (amongst others) - * may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b, - * 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c, - * 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b. - * - * Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq" - * driver. - */ -DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050); -DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050); - static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; diff --git a/trunk/drivers/pci/remove.c b/trunk/drivers/pci/remove.c index 7c0fd9252e6f..513972f3ed13 100644 --- a/trunk/drivers/pci/remove.c +++ b/trunk/drivers/pci/remove.c @@ -111,39 +111,3 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev) pci_remove_bus_device(dev); } EXPORT_SYMBOL(pci_stop_and_remove_bus_device); - -void pci_stop_root_bus(struct pci_bus *bus) -{ - struct pci_dev *child, *tmp; - struct pci_host_bridge *host_bridge; - - if (!pci_is_root_bus(bus)) - return; - - host_bridge = to_pci_host_bridge(bus->bridge); - list_for_each_entry_safe_reverse(child, tmp, - &bus->devices, bus_list) - pci_stop_bus_device(child); - - /* stop the host bridge */ - device_del(&host_bridge->dev); -} - -void pci_remove_root_bus(struct pci_bus *bus) -{ - struct pci_dev *child, *tmp; - struct pci_host_bridge *host_bridge; - - if (!pci_is_root_bus(bus)) - return; - - host_bridge = to_pci_host_bridge(bus->bridge); - list_for_each_entry_safe(child, tmp, - &bus->devices, bus_list) - pci_remove_bus_device(child); - pci_remove_bus(bus); - host_bridge->bus = NULL; - - /* remove the host bridge */ - put_device(&host_bridge->dev); -} diff --git a/trunk/drivers/pci/rom.c b/trunk/drivers/pci/rom.c index 3a3828fbc879..ab886b7ee327 100644 --- a/trunk/drivers/pci/rom.c +++ b/trunk/drivers/pci/rom.c @@ -122,7 +122,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) */ if (pdev->rom && pdev->romlen) { *size = pdev->romlen; - return phys_to_virt((phys_addr_t)pdev->rom); + return phys_to_virt(pdev->rom); /* * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy * memory map if the VGA enable bit of the Bridge Control register is diff --git a/trunk/drivers/pci/setup-bus.c b/trunk/drivers/pci/setup-bus.c index 6d3591d57ea0..1e808ca338f8 100644 --- a/trunk/drivers/pci/setup-bus.c +++ b/trunk/drivers/pci/setup-bus.c @@ -1550,12 +1550,25 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) } EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); -void pci_assign_unassigned_bus_resources(struct pci_bus *bus) +#ifdef CONFIG_HOTPLUG +/** + * pci_rescan_bus - scan a PCI bus for devices. + * @bus: PCI bus to scan + * + * Scan a PCI bus and child buses for new devices, adds them, + * and enables them. + * + * Returns the max number of subordinate bus discovered. + */ +unsigned int __ref pci_rescan_bus(struct pci_bus *bus) { + unsigned int max; struct pci_dev *dev; LIST_HEAD(add_list); /* list of resources that want additional resources */ + max = pci_scan_child_bus(bus); + down_read(&pci_bus_sem); list_for_each_entry(dev, &bus->devices, bus_list) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || @@ -1566,4 +1579,11 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus) up_read(&pci_bus_sem); __pci_bus_assign_resources(bus, &add_list, NULL); BUG_ON(!list_empty(&add_list)); + + pci_enable_bridges(bus); + pci_bus_add_devices(bus); + + return max; } +EXPORT_SYMBOL_GPL(pci_rescan_bus); +#endif diff --git a/trunk/drivers/pci/xen-pcifront.c b/trunk/drivers/pci/xen-pcifront.c index a0c73120b262..0aab85a51559 100644 --- a/trunk/drivers/pci/xen-pcifront.c +++ b/trunk/drivers/pci/xen-pcifront.c @@ -1068,16 +1068,13 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev, case XenbusStateInitialising: case XenbusStateInitWait: case XenbusStateInitialised: + case XenbusStateClosed: break; case XenbusStateConnected: pcifront_try_connect(pdev); break; - case XenbusStateClosed: - if (xdev->state == XenbusStateClosed) - break; - /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: dev_warn(&xdev->dev, "backend going away!\n"); pcifront_try_disconnect(pdev); diff --git a/trunk/include/acpi/acpi_drivers.h b/trunk/include/acpi/acpi_drivers.h index 8b1d7a6a9695..bb145e4b935e 100644 --- a/trunk/include/acpi/acpi_drivers.h +++ b/trunk/include/acpi/acpi_drivers.h @@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle); /* ACPI PCI Interrupt Routing (pci_irq.c) */ -int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus); -void acpi_pci_irq_del_prt(int segment, int bus); +int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus); +void acpi_pci_irq_del_prt(struct pci_bus *bus); /* ACPI PCI Device Binding (pci_bind.c) */ diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index ea41a0a52a59..957563b7a5e3 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -333,7 +333,7 @@ struct pci_dev { }; struct pci_ats *ats; /* Address Translation Service */ #endif - void *rom; /* Physical pointer to ROM if it's not from the BAR */ + phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */ size_t romlen; /* Length of ROM if it's not from the BAR */ }; @@ -540,9 +540,6 @@ enum pci_ers_result { /* Device driver is fully recovered and operational */ PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5, - - /* No AER capabilities registered for the driver */ - PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6, }; /* PCI bus error event callbacks */ @@ -578,7 +575,6 @@ struct pci_driver { int (*resume_early) (struct pci_dev *dev); int (*resume) (struct pci_dev *dev); /* Device woken up */ void (*shutdown) (struct pci_dev *dev); - int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */ const struct pci_error_handlers *err_handler; struct device_driver driver; struct pci_dynids dynids; @@ -718,8 +714,6 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev); extern void pci_dev_put(struct pci_dev *dev); extern void pci_remove_bus(struct pci_bus *b); extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); -void pci_stop_root_bus(struct pci_bus *bus); -void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); extern void pci_sort_breadthfirst(void); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) @@ -966,7 +960,6 @@ void pci_bus_size_bridges(struct pci_bus *bus); int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); -void pci_assign_unassigned_bus_resources(struct pci_bus *bus); void pdev_enable_device(struct pci_dev *); int pci_enable_resources(struct pci_dev *, int mask); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), @@ -1611,7 +1604,7 @@ static inline void pci_mmcfg_early_init(void) { } static inline void pci_mmcfg_late_init(void) { } #endif -int pci_ext_cfg_avail(void); +int pci_ext_cfg_avail(struct pci_dev *dev); void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); @@ -1620,8 +1613,6 @@ extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); extern void pci_disable_sriov(struct pci_dev *dev); extern irqreturn_t pci_sriov_migration(struct pci_dev *dev); extern int pci_num_vf(struct pci_dev *dev); -extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); -extern int pci_sriov_get_totalvfs(struct pci_dev *dev); #else static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { @@ -1638,14 +1629,6 @@ static inline int pci_num_vf(struct pci_dev *dev) { return 0; } -static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) -{ - return 0; -} -static inline int pci_sriov_get_totalvfs(struct pci_dev *dev) -{ - return 0; -} #endif #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) diff --git a/trunk/include/uapi/linux/pci_regs.h b/trunk/include/uapi/linux/pci_regs.h index 6b7b6f1e2fd6..20ae747ddf34 100644 --- a/trunk/include/uapi/linux/pci_regs.h +++ b/trunk/include/uapi/linux/pci_regs.h @@ -349,7 +349,7 @@ #define PCI_AF_STATUS_TP 0x01 #define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */ -/* PCI-X registers (Type 0 (non-bridge) devices) */ +/* PCI-X registers */ #define PCI_X_CMD 2 /* Modes & Features */ #define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ @@ -389,19 +389,6 @@ #define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */ #define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */ -/* PCI-X registers (Type 1 (bridge) devices) */ - -#define PCI_X_BRIDGE_SSTATUS 2 /* Secondary Status */ -#define PCI_X_SSTATUS_64BIT 0x0001 /* Secondary AD interface is 64 bits */ -#define PCI_X_SSTATUS_133MHZ 0x0002 /* 133 MHz capable */ -#define PCI_X_SSTATUS_FREQ 0x03c0 /* Secondary Bus Mode and Frequency */ -#define PCI_X_SSTATUS_VERS 0x3000 /* PCI-X Capability Version */ -#define PCI_X_SSTATUS_V1 0x1000 /* Mode 2, not Mode 1 */ -#define PCI_X_SSTATUS_V2 0x2000 /* Mode 1 or Modes 1 and 2 */ -#define PCI_X_SSTATUS_266MHZ 0x4000 /* 266 MHz capable */ -#define PCI_X_SSTATUS_533MHZ 0x8000 /* 533 MHz capable */ -#define PCI_X_BRIDGE_STATUS 4 /* Bridge Status */ - /* PCI Bridge Subsystem ID registers */ #define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */ @@ -469,8 +456,6 @@ #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ #define PCI_EXP_LNKCTL 16 /* Link Control */ #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ -#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */ -#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */ #define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ #define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ #define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ @@ -559,9 +544,9 @@ #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */ #define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ -#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ -#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ -#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ +#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */