]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 20:14:47 +0000 (12:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 20:14:47 +0000 (12:14 -0800)
Pull PCI update from Bjorn Helgaas:
 "Host bridge hotplug:
   - Untangle _PRT from struct pci_bus (Bjorn Helgaas)
   - Request _OSC control before scanning root bus (Taku Izumi)
   - Assign resources when adding host bridge (Yinghai Lu)
   - Remove root bus when removing host bridge (Yinghai Lu)
   - Remove _PRT during hot remove (Yinghai Lu)

  SRIOV
    - Add sysfs knobs to control numVFs (Don Dutile)

  Power management
   - Notify devices when power resource turned on (Huang Ying)

  Bug fixes
   - Work around broken _SEG on HP xw9300 (Bjorn Helgaas)
   - Keep runtime PM enabled for unbound PCI devices (Huang Ying)
   - Fix Optimus dual-GPU runtime D3 suspend issue (Dave Airlie)
   - Fix xen frontend shutdown issue (David Vrabel)
   - Work around PLX PCI 9050 BAR alignment erratum (Ian Abbott)

  Miscellaneous
   - Add GPL license for drivers/pci/ioapic (Andrew Cooks)
   - Add standard PCI-X, PCIe ASPM register #defines (Bjorn Helgaas)
   - NumaChip remote PCI support (Daniel Blueman)
   - Fix PCIe Link Capabilities Supported Link Speed definition (Jingoo
     Han)
   - Convert dev_printk() to dev_info(), etc (Joe Perches)
   - Add support for non PCI BAR ROM data (Matthew Garrett)
   - Add x86 support for host bridge translation offset (Mike Yoknis)
   - Report success only when every driver supports AER (Vijay
     Pandarathil)"

Fix up trivial conflicts.

* tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (48 commits)
  PCI: Use phys_addr_t for physical ROM address
  x86/PCI: Add NumaChip remote PCI support
  ath9k: Use standard #defines for PCIe Capability ASPM fields
  iwlwifi: Use standard #defines for PCIe Capability ASPM fields
  iwlwifi: collapse wrapper for pcie_capability_read_word()
  iwlegacy: Use standard #defines for PCIe Capability ASPM fields
  iwlegacy: collapse wrapper for pcie_capability_read_word()
  cxgb3: Use standard #defines for PCIe Capability ASPM fields
  PCI: Add standard PCIe Capability Link ASPM field names
  PCI/portdrv: Use PCI Express Capability accessors
  PCI: Use standard PCIe Capability Link register field names
  x86: Use PCI setup data
  PCI: Add support for non-BAR ROMs
  PCI: Add pcibios_add_device
  EFI: Stash ROMs if they're not in the PCI BAR
  PCI: Add and use standard PCI-X Capability register names
  PCI/PM: Keep runtime PM enabled for unbound PCI devices
  xen-pcifront: Handle backend CLOSED without CLOSING
  PCI: SRIOV control and status via sysfs (documentation)
  PCI/AER: Report success only when every device has AER-aware driver
  ...

45 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/PCI/pci-iov-howto.txt
arch/x86/Kconfig
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/bootparam.h
arch/x86/include/asm/numachip/numachip.h [new file with mode: 0644]
arch/x86/include/asm/pci.h
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/setup.c
arch/x86/pci/Makefile
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/numachip.c [new file with mode: 0644]
drivers/acpi/pci_bind.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/iwlegacy/4965.h
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/pci/bus.c
drivers/pci/ioapic.c
drivers/pci/iov.c
drivers/pci/irq.c
drivers/pci/pci-driver.c
drivers/pci/pci-stub.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/xen-pcifront.c
include/acpi/acpi_drivers.h
include/linux/efi.h
include/linux/pci.h
include/uapi/linux/pci_regs.h

index dff1f48d252d8f0d36aa31cccf6514cb02b3d333..1ce5ae329c048fa1f9c84523592d5bfc34c22614 100644 (file)
@@ -222,3 +222,37 @@ 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 <ddutile@redhat.com>
+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 <ddutile@redhat.com>
+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.
index fc73ef5d65b81366360d9d213bc2d675875ad4b7..cfaca7e6989346246e3205c52a353ea960b50ce5 100644 (file)
@@ -2,6 +2,9 @@
                Copyright (C) 2009 Intel Corporation
                    Yu Zhao <yu.zhao@intel.com>
 
+               Update: November 2012
+                       -- sysfs-based SRIOV enable-/disable-ment
+               Donald Dutile <ddutile@redhat.com>
 
 1. Overview
 
@@ -24,10 +27,21 @@ real existing PCI device.
 
 2.1 How can I enable SR-IOV capability
 
-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.
+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.
 
 2.2 How can I use the Virtual Functions
 
@@ -40,13 +54,22 @@ 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/<DOMAIN:BUS:DEVICE.FUNCTION>/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/<DOMAIN:BUS:DEVICE.FUNCTION>/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
@@ -88,6 +111,22 @@ 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,
@@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
        .suspend =      dev_suspend,
        .resume =       dev_resume,
        .shutdown =     dev_shutdown,
+       .sriov_configure = dev_sriov_configure,
 };
index 9195fd80e11ed7efa2e030704eab0b22e161c7cc..65a872bf72f9c693039540519b69f9c8238b7214 100644 (file)
@@ -370,6 +370,7 @@ 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.
index e87b0cac14b5e5d735ab21f9f3b163db52349938..b1942e222768e7c9c2707c14dbdbd9643a51a8b9 100644 (file)
@@ -8,6 +8,7 @@
  * ----------------------------------------------------------------------- */
 
 #include <linux/efi.h>
+#include <linux/pci.h>
 #include <asm/efi.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
@@ -245,6 +246,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
        *size = len;
 }
 
+static efi_status_t setup_efi_pci(struct boot_params *params)
+{
+       efi_pci_io_protocol *pci;
+       efi_status_t status;
+       void **pci_handle;
+       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+       unsigned long nr_pci, size = 0;
+       int i;
+       struct setup_data *data;
+
+       data = (struct setup_data *)params->hdr.setup_data;
+
+       while (data && data->next)
+               data = (struct setup_data *)data->next;
+
+       status = efi_call_phys5(sys_table->boottime->locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+                               NULL, &size, pci_handle);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               status = efi_call_phys3(sys_table->boottime->allocate_pool,
+                                       EFI_LOADER_DATA, size, &pci_handle);
+
+               if (status != EFI_SUCCESS)
+                       return status;
+
+               status = efi_call_phys5(sys_table->boottime->locate_handle,
+                                       EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+                                       NULL, &size, pci_handle);
+       }
+
+       if (status != EFI_SUCCESS)
+               goto free_handle;
+
+       nr_pci = size / sizeof(void *);
+       for (i = 0; i < nr_pci; i++) {
+               void *h = pci_handle[i];
+               uint64_t attributes;
+               struct pci_setup_rom *rom;
+
+               status = efi_call_phys3(sys_table->boottime->handle_protocol,
+                                       h, &pci_proto, &pci);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               if (!pci)
+                       continue;
+
+               status = efi_call_phys4(pci->attributes, pci,
+                                       EfiPciIoAttributeOperationGet, 0,
+                                       &attributes);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+                       continue;
+
+               if (!pci->romimage || !pci->romsize)
+                       continue;
+
+               size = pci->romsize + sizeof(*rom);
+
+               status = efi_call_phys3(sys_table->boottime->allocate_pool,
+                               EFI_LOADER_DATA, size, &rom);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               rom->data.type = SETUP_PCI;
+               rom->data.len = size - sizeof(struct setup_data);
+               rom->data.next = 0;
+               rom->pcilen = pci->romsize;
+
+               status = efi_call_phys5(pci->pci.read, pci,
+                                       EfiPciIoWidthUint16, PCI_VENDOR_ID,
+                                       1, &(rom->vendor));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               status = efi_call_phys5(pci->pci.read, pci,
+                                       EfiPciIoWidthUint16, PCI_DEVICE_ID,
+                                       1, &(rom->devid));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               status = efi_call_phys5(pci->get_location, pci,
+                                       &(rom->segment), &(rom->bus),
+                                       &(rom->device), &(rom->function));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               memcpy(rom->romdata, pci->romimage, pci->romsize);
+
+               if (data)
+                       data->next = (uint64_t)rom;
+               else
+                       params->hdr.setup_data = (uint64_t)rom;
+
+               data = (struct setup_data *)rom;
+
+               continue;
+       free_struct:
+               efi_call_phys1(sys_table->boottime->free_pool, rom);
+       }
+
+free_handle:
+       efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
+       return status;
+}
+
 /*
  * See if we have Graphics Output Protocol
  */
@@ -1028,6 +1144,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
 
        setup_graphics(boot_params);
 
+       setup_efi_pci(boot_params);
+
        status = efi_call_phys3(sys_table->boottime->allocate_pool,
                                EFI_LOADER_DATA, sizeof(*gdt),
                                (void **)&gdt);
index 2ad874cb661cef0ccd4b42cb918004141c28672a..92862cd902012b9fb174d03e6e2cd687787136cf 100644 (file)
@@ -13,6 +13,7 @@
 #define SETUP_NONE                     0
 #define SETUP_E820_EXT                 1
 #define SETUP_DTB                      2
+#define SETUP_PCI                      3
 
 /* extensible setup data list node */
 struct setup_data {
diff --git a/arch/x86/include/asm/numachip/numachip.h b/arch/x86/include/asm/numachip/numachip.h
new file mode 100644 (file)
index 0000000..1c6f7f6
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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 <support@numascale.com>
+ *
+ */
+
+#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 */
index 6e41b9343928941a82533d4fb299c8b70aaf9add..dba7805176bf3cf705b5308d6c7d13b5142f9a61 100644 (file)
@@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
 }
 #endif
 
+struct pci_setup_rom {
+       struct setup_data data;
+       uint16_t vendor;
+       uint16_t devid;
+       uint64_t pcilen;
+       unsigned long segment;
+       unsigned long bus;
+       unsigned long device;
+       unsigned long function;
+       uint8_t romdata[0];
+};
+
 #endif /* _ASM_X86_PCI_H */
index a65829ac2b9a1b4cb9517f94318bc106291061ad..9c2aa89a11cbf8d4a124d25bdea25d726cedba17 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hardirq.h>
 #include <linux/delay.h>
 
+#include <asm/numachip/numachip.h>
 #include <asm/numachip/numachip_csr.h>
 #include <asm/smp.h>
 #include <asm/apic.h>
@@ -179,6 +180,7 @@ 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();
 
index ca45696f30fb8a01a4d6852388d08ab19d4bb778..c228322ca180f51521175adc2d393ad4e718623f 100644 (file)
@@ -143,11 +143,7 @@ int default_check_phys_apicid_present(int phys_apicid)
 }
 #endif
 
-#ifndef CONFIG_DEBUG_BOOT_PARAMS
-struct boot_params __initdata boot_params;
-#else
 struct boot_params boot_params;
-#endif
 
 /*
  * Machine setup..
index 3af5a1e79c9ccc5ebe98c64b3af921562f397141..ee0af58ca5bd7e5e75ae22885a887ff86381fe46 100644 (file)
@@ -16,6 +16,7 @@ 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
 
index 192397c98606690f34d1d510052738f04bbdd931..0c01261fe5a846bc2500fc24c1ff56c2b432e86f 100644 (file)
@@ -12,6 +12,7 @@ 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;
@@ -22,6 +23,7 @@ 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)
 {
@@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
        return 0;
 }
 
-static const struct dmi_system_id pci_use_crs_table[] __initconst = {
+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 = {
        /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
        {
                .callback = set_use_crs,
@@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __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"),
+               },
+       },
        {}
 };
 
@@ -108,7 +127,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_use_crs_table);
+       dmi_check_system(pci_crs_quirks);
 
        /*
         * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
@@ -305,6 +324,7 @@ 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,
@@ -374,7 +394,8 @@ 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(resources, res);
+                       pci_add_resource_offset(resources, res,
+                                       info->res_offset[i]);
        }
 }
 
@@ -382,6 +403,8 @@ 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;
 }
 
@@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
                return;
 
        size = sizeof(*info->res) * info->res_num;
-       info->res_num = 0;
        info->res = kzalloc(size, GFP_KERNEL);
-       if (!info->res)
+       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;
                return;
+       }
 
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
                                info);
@@ -455,6 +488,9 @@ 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",
index 720e973fc34a31b856998715165f7fc50ec9ec6d..1b1dda90a945ede1550294e83dfc51d7a2f9f663 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/pci_x86.h>
+#include <asm/setup.h>
 
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
                                PCI_PROBE_MMCONF;
@@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
        return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
 }
 
+int pcibios_add_device(struct pci_dev *dev)
+{
+       struct setup_data *data;
+       struct pci_setup_rom *rom;
+       u64 pa_data;
+
+       pa_data = boot_params.hdr.setup_data;
+       while (pa_data) {
+               data = phys_to_virt(pa_data);
+
+               if (data->type == SETUP_PCI) {
+                       rom = (struct pci_setup_rom *)data;
+
+                       if ((pci_domain_nr(dev->bus) == rom->segment) &&
+                           (dev->bus->number == rom->bus) &&
+                           (PCI_SLOT(dev->devfn) == rom->device) &&
+                           (PCI_FUNC(dev->devfn) == rom->function) &&
+                           (dev->vendor == rom->vendor) &&
+                           (dev->device == rom->devid)) {
+                               dev->rom = pa_data +
+                                     offsetof(struct pci_setup_rom, romdata);
+                               dev->romlen = rom->pcilen;
+                       }
+               }
+               pa_data = data->next;
+       }
+       return 0;
+}
+
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        int err;
@@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
                pcibios_disable_irq(dev);
 }
 
-int pci_ext_cfg_avail(struct pci_dev *dev)
+int pci_ext_cfg_avail(void)
 {
        if (raw_pci_ext_ops)
                return 1;
diff --git a/arch/x86/pci/numachip.c b/arch/x86/pci/numachip.c
new file mode 100644 (file)
index 0000000..7307d9d
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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 <support@numascale.com>
+ *
+ * PCI accessor functions derived from mmconfig_64.c
+ *
+ */
+
+#include <linux/pci.h>
+#include <asm/pci_x86.h>
+
+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;
+}
index 2ef04098cc1d5f4d01942d3e4de79014c4911efe..a1dee29beed328430491bdbff3cfe386692b06ba 100644 (file)
@@ -45,11 +45,12 @@ 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(dev->subordinate);
+       acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
 
        device->ops.bind = NULL;
        device->ops.unbind = NULL;
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
 {
        acpi_status status;
        acpi_handle handle;
-       struct pci_bus *bus;
+       unsigned char bus;
        struct pci_dev *dev;
 
        dev = acpi_get_pci_dev(device->handle);
@@ -71,6 +72,7 @@ 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);
 
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
                goto out;
 
        if (dev->subordinate)
-               bus = dev->subordinate;
+               bus = dev->subordinate->number;
        else
-               bus = dev->bus;
+               bus = dev->bus->number;
 
-       acpi_pci_irq_add_prt(device->handle, bus);
+       acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
 
 out:
        pci_dev_put(dev);
index 23a0324901307b9f0c930f7be00beeff45dbbec0..68a921d032475edbaa7740d9f880ee5bf52a8db3 100644 (file)
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
        }
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int 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, struct pci_bus *bus,
         * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
         * it here.
         */
-       entry->id.segment = pci_domain_nr(bus);
-       entry->id.bus = bus->number;
+       entry->id.segment = segment;
+       entry->id.bus = bus;
        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, struct pci_bus *bus,
        return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int 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, struct pci_bus *bus)
 
        entry = buffer.pointer;
        while (entry && (entry->length > 0)) {
-               acpi_pci_irq_add_entry(handle, bus, entry);
+               acpi_pci_irq_add_entry(handle, segment, bus, entry);
                entry = (struct acpi_pci_routing_table *)
                    ((unsigned long)entry + entry->length);
        }
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
        return 0;
 }
 
-void acpi_pci_irq_del_prt(struct pci_bus *bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
 {
        struct acpi_prt_entry *entry, *tmp;
 
        printk(KERN_DEBUG
               "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-              pci_domain_nr(bus), bus->number);
+              segment, bus);
        spin_lock(&acpi_prt_lock);
        list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-               if (pci_domain_nr(bus) == entry->id.segment
-                       && bus->number == entry->id.bus) {
+               if (segment == entry->id.segment && bus == entry->id.bus) {
                        list_del(&entry->list);
                        kfree(entry);
                }
index f70b9e5fc1b59098b530e58567bba2ae36ea99d3..7928d4dc705618a833ccce3172ed5113307d4cff 100644 (file)
@@ -454,6 +454,7 @@ static int 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)
@@ -501,52 +502,10 @@ static int 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
         * -----------------
@@ -554,32 +513,36 @@ static int 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->bus);
+               result = acpi_pci_irq_add_prt(device->handle, root->segment,
+                                             root->secondary.start);
+
+       root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
        /*
-        * Scan and bind all _ADR-Based Devices
+        * All supported architectures that use ACPI have support for
+        * PCI domains, so we indicate this in _OSC support capabilities.
         */
-       list_for_each_entry(child, &device->children, node)
-               acpi_pci_bridge_scan(child);
+       flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+       acpi_pci_osc_support(root, flags);
 
        /* Indicate support for various _OSC capabilities. */
-       if (pci_ext_cfg_avail(root->bus->self))
+       if (pci_ext_cfg_avail())
                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(root->bus->bridge, "ACPI _OSC support "
+                       dev_info(&device->dev, "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
@@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device)
 
                if (pci_aer_available()) {
                        if (aer_acpi_firmware_first())
-                               dev_dbg(root->bus->bridge,
+                               dev_dbg(&device->dev,
                                        "PCIe errors handled by BIOS.\n");
                        else
                                flags |= OSC_PCI_EXPRESS_AER_CONTROL;
                }
 
-               dev_info(root->bus->bridge,
+               dev_info(&device->dev,
                        "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)) {
-                       dev_info(root->bus->bridge,
+                       is_osc_granted = true;
+                       dev_info(&device->dev,
                                "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 {
-                       dev_info(root->bus->bridge,
+                       is_osc_granted = false;
+                       dev_info(&device->dev,
                                "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(root->bus->bridge,
-                        "Unable to request _OSC control "
-                        "(_OSC support mask: 0x%02x)\n", flags);
+               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();
        }
 
        pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -634,6 +638,8 @@ out_del_root:
        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;
@@ -644,12 +650,19 @@ 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;
@@ -657,17 +670,29 @@ 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(driver, &acpi_pci_drivers, node)
+       list_for_each_entry_reverse(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);
index aef45d3113bac5e9200d4dae8efc9a754a38d18e..3dee68612c9e87868e3b5b61b475693273480319 100644 (file)
@@ -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 & 1)            /* check LOsEnable */
+       if (val & PCI_EXP_LNKCTL_ASPM_L0S)      /* check LOsEnable */
                acklat += fst_trn_tx * 4;
        rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
 
index 8e9b826f878b423aa1ba0b587c926cf21da68b1e..7ae73fbd91361092f1a0590be0cbc2e2b0ecc9a4 100644 (file)
@@ -114,23 +114,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 coexistance requires disabling ASPM. */
+               /* Bluetooth coexistence requires disabling ASPM. */
                pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
-                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+                       PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
 
                /*
                 * Both upstream and downstream PCIe components should
                 * have the same ASPM settings.
                 */
                pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
-                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+                       PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
 
                ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
                return;
        }
 
        pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
-       if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+       if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
                ah->aspm_enabled = true;
                /* Initialize PCIe PM and SERDES registers. */
                ath9k_hw_configpcipowersave(ah, false);
index 2d092f328547d8ca37dfef233a4619c23f7b5aa4..1b15b0b2292b4fe06c3fa1efcc95279c9901370e 100644 (file)
@@ -917,10 +917,6 @@ 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 */
index 318ed3c9fe7499899d08fc3de1de917438690109..7e16d10a7f140e4bc0a1414af1ec317f7284b9c6 100644 (file)
@@ -1183,9 +1183,10 @@ EXPORT_SYMBOL(il_power_update_mode);
 void
 il_power_initialize(struct il_priv *il)
 {
-       u16 lctl = il_pcie_link_ctl(il);
+       u16 lctl;
 
-       il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       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.debug_sleep_level_override = -1;
 
@@ -4233,9 +4234,8 @@ il_apm_init(struct il_priv *il)
         *    power savings, even without L1.
         */
        if (il->cfg->set_l0s) {
-               lctl = il_pcie_link_ctl(il);
-               if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                   PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+               pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+               if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
                        /* L1-ASPM enabled; disable(!) L0S  */
                        il_set_bit(il, CSR_GIO_REG,
                                   CSR_GIO_REG_VAL_L0S_ENABLED);
index e254cba4557adbf12d6f3e7e0534b3c36c73c2d4..a9a569f432fb3517d5421ea1c4d43cdd96a4d816 100644 (file)
@@ -1829,14 +1829,6 @@ 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,
@@ -2434,10 +2426,6 @@ 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. */
index d66cad4a7d6abcfd4d3bd7677f5ceb09a7a0c7f3..35708b959ad6e563a38d29f1bd75c51e87c9c2c8 100644 (file)
@@ -94,8 +94,6 @@ static void iwl_pcie_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_pcie_apm_config(struct iwl_trans *trans)
 {
@@ -111,9 +109,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
         *    power savings, even without L1.
         */
        pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
-
-       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+       if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
                /* L1-ASPM enabled; disable(!) L0S */
                iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
                dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
@@ -122,7 +118,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
                iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
                dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
        }
-       trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
 }
 
 /*
index a543746fb354d99913cac3323b99b6f5aa71dbc9..ad6a8b63569201050dd3a7b487c5396b6b8ed28f 100644 (file)
@@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
        int retval;
 
        pci_fixup_device(pci_fixup_final, dev);
+
+       retval = pcibios_add_device(dev);
+       if (retval)
+               return retval;
+
        retval = device_add(&dev->dev);
        if (retval)
                return retval;
index 2eca902a428390394af90b7d6387981fc04ea8db..3c6bbdd059a459614ab2710f377d3f9796ccd3aa 100644 (file)
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
 
 module_init(ioapic_init);
 module_exit(ioapic_exit);
+
+MODULE_LICENSE("GPL");
index aeccc911abb829182cbee0b82ecb4c0b49640aa2..bafd2bbcaf6541d1983fababa4563ae174837e15 100644 (file)
@@ -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);
+               do_div(size, iov->total_VFs);
                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->nr_virtfn)
+       if (!iov->num_VFs)
                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; i < iov->nr_virtfn; i++) {
+       for (i = iov->initial_VFs; i < iov->num_VFs; 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)
+       if (nr_virtfn <= iov->initial_VFs)
                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->nr_virtfn)
+       if (iov->num_VFs)
                return -EINVAL;
 
        pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
-       if (initial > iov->total ||
-           (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
+       if (initial > iov->total_VFs ||
+           (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
                return -EIO;
 
-       if (nr_virtfn < 0 || nr_virtfn > iov->total ||
+       if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
            (!(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 = initial;
+       iov->initial_VFs = 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->nr_virtfn = nr_virtfn;
+       iov->num_VFs = 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->nr_virtfn)
+       if (!iov->num_VFs)
                return;
 
        if (iov->cap & PCI_SRIOV_CAP_VFM)
                sriov_disable_migration(dev);
 
-       for (i = 0; i < iov->nr_virtfn; i++)
+       for (i = 0; i < iov->num_VFs; 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->nr_virtfn = 0;
+       iov->num_VFs = 0;
 }
 
 static int sriov_init(struct pci_dev *dev, int pos)
@@ -496,7 +496,7 @@ found:
        iov->pos = pos;
        iov->nres = nres;
        iov->ctrl = ctrl;
-       iov->total = total;
+       iov->total_VFs = total;
        iov->offset = offset;
        iov->stride = stride;
        iov->pgsz = pgsz;
@@ -529,7 +529,7 @@ failed:
 
 static void sriov_release(struct pci_dev *dev)
 {
-       BUG_ON(dev->sriov->nr_virtfn);
+       BUG_ON(dev->sriov->num_VFs);
 
        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->nr_virtfn);
+       pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
        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 - 1);
+               busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
                if (busnr > max)
                        max = busnr;
        }
@@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
  */
 int pci_num_vf(struct pci_dev *dev)
 {
-       if (!dev || !dev->is_physfn)
+       if (!dev->is_physfn)
                return 0;
-       else
-               return dev->sriov->nr_virtfn;
+
+       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;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
index e5f69a43b1b18e0961ff05ddc29ae3872be962fc..b008cf86b9c3f8d4fab1493a41895f196519e94d 100644 (file)
@@ -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_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");
+       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");
        WARN_ON(1);
 }
 
index 1dc78c5cabf8f52175159ef6191a479828497e08..f79cbcd3944bf5e61e76a96022331a665e63f93e 100644 (file)
@@ -248,31 +248,26 @@ struct drv_dev_and_id {
 static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
-       struct device *dev = &ddi->dev->dev;
-       struct device *parent = dev->parent;
+       struct pci_dev *pci_dev = ddi->dev;
+       struct pci_driver *pci_drv = ddi->drv;
+       struct device *dev = &pci_dev->dev;
        int rc;
 
-       /* 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.
+       /*
+        * 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.
         */
-       pm_runtime_get_noresume(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
-
-       rc = ddi->drv->probe(ddi->dev, ddi->id);
+       pm_runtime_get_sync(dev);
+       pci_dev->driver = pci_drv;
+       rc = pci_drv->probe(pci_dev, ddi->id);
        if (rc) {
-               pm_runtime_disable(dev);
-               pm_runtime_set_suspended(dev);
-               pm_runtime_put_noidle(dev);
+               pci_dev->driver = NULL;
+               pm_runtime_put_sync(dev);
        }
-       if (parent)
-               pm_runtime_put(parent);
        return rc;
 }
 
@@ -322,10 +317,8 @@ __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) {
-                       pci_dev->driver = drv;
+               if (error >= 0)
                        error = 0;
-               }
        }
        return error;
 }
@@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
        }
 
        /* Undo the runtime PM settings in local_pci_probe() */
-       pm_runtime_disable(dev);
-       pm_runtime_set_suspended(dev);
-       pm_runtime_put_noidle(dev);
+       pm_runtime_put_sync(dev);
 
        /*
         * If the device is still on, set the power state as "unknown",
@@ -986,6 +977,13 @@ 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;
 
@@ -1007,10 +1005,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;
 }
@@ -1021,6 +1019,13 @@ 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;
 
@@ -1038,8 +1043,16 @@ 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;
 
@@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
                        return ret;
        }
 
+out:
        pm_runtime_suspend(dev);
-
        return 0;
 }
 
index 775e933c222547d14c30840daebd16b5a438be72..6e47c519c51070788ea7fa4e0a3f56896b962ab9 100644 (file)
@@ -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_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
+       dev_info(&dev->dev, "claimed by stub\n");
        return 0;
 }
 
index 68d56f02e721f8de0f3f7f7b5869168bc32e1350..05b78b16d20bdca1acb822e7654360102fb09072 100644 (file)
@@ -401,6 +401,106 @@ 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),
@@ -1262,29 +1362,20 @@ 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_vga_file;
+               goto err_rom_file;
 
        /* add sysfs entries for various capabilities */
        retval = pci_create_capabilities_sysfs(pdev);
        if (retval)
-               goto err_vga_file;
+               goto err_rom_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);
@@ -1370,3 +1461,62 @@ 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,
+};
index bdf66b500f22bae2ba17dc7ed325eae5015b40ac..5cb5820fae40147a29c79913cd1ebadcbfba1348 100644 (file)
@@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
                dr->pinned = 1;
 }
 
+/*
+ * pcibios_add_device - provide arch specific hooks when adding device dev
+ * @dev: the PCI device being added
+ *
+ * Permits the platform to provide architecture specific functionality when
+ * devices are added. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+int __weak pcibios_add_device (struct pci_dev *dev)
+{
+       return 0;
+}
+
 /**
  * pcibios_disable_device - disable arch specific PCI resources for device dev
  * @dev: the PCI device to disable
@@ -1578,15 +1591,25 @@ 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. */
+       /*
+        * 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.
+        */
 
        if (dev->pme_poll) {
                struct pci_pme_device *pme_dev;
@@ -1900,6 +1923,8 @@ 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;
 
@@ -3865,14 +3890,13 @@ static void pci_no_domains(void)
 }
 
 /**
- * pci_ext_cfg_enabled - can we access extended PCI config space?
- * @dev: The PCI device of the root bridge.
+ * pci_ext_cfg_avail - can we access extended PCI config space?
  *
  * 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(struct pci_dev *dev)
+int __weak pci_ext_cfg_avail(void)
 {
        return 1;
 }
index e253881c42759eaeb2b76070f830de192663e347..e8518292826f0182bc23206f0b7e25fe88de858f 100644 (file)
@@ -158,6 +158,7 @@ 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;
 extern struct bus_attribute pci_bus_attrs[];
 
 
@@ -229,13 +230,14 @@ struct pci_sriov {
        int nres;               /* number of resources */
        u32 cap;                /* SR-IOV Capabilities */
        u16 ctrl;               /* SR-IOV Control */
-       u16 total;              /* total VFs associated with the PF */
-       u16 initial;            /* initial VFs associated with the PF */
-       u16 nr_virtfn;          /* number of VFs available */
+       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 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 */
index 94a7598eb262fec103cb9611ba8612e452d1de7b..22f840f4dda1065eb97b54da307b5f6d2dda0c5a 100644 (file)
@@ -87,6 +87,9 @@ 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;
 
@@ -97,7 +100,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 = new;
+                       orig = PCI_ERS_RESULT_NEED_RESET;
                break;
        default:
                break;
index af4e31cd3a3b6b1f895a36afaf4bb874b3e1fb66..421bbc5fee324b485f409e7a025338bc524eecf5 100644 (file)
@@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               goto out;
+
+               /*
+                * 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);
        }
 
-       err_handler = dev->driver->err_handler;
-       vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
-out:
        device_unlock(&dev->dev);
        return 0;
 }
index 213753b283a6838174dd1fd409add971c7a363ae..b52630b8eada26ad35f8304e436c63f3e064edd3 100644 (file)
@@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
                return;
 
        /* Training failed. Restore common clock configurations */
-       dev_printk(KERN_ERR, &parent->dev,
-                  "ASPM: Could not configure common clock\n");
+       dev_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)]);
@@ -427,7 +426,8 @@ 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, 0x3, val);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
+                                          PCI_EXP_LNKCTL_ASPMC, 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 |= PCIE_LINK_STATE_L0S;
+               dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
        if (state & ASPM_STATE_L0S_DW)
-               upstream |= PCIE_LINK_STATE_L0S;
+               upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
        if (state & ASPM_STATE_L1) {
-               upstream |= PCIE_LINK_STATE_L1;
-               dwstream |= PCIE_LINK_STATE_L1;
+               upstream |= PCI_EXP_LNKCTL_ASPM_L1;
+               dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
        }
        /*
         * Spec 2.0 suggests all functions should be configured the
@@ -507,9 +507,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
                 */
                pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
                if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
-                       dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
-                               " on pre-1.1 PCIe device.  You can enable it"
-                               " with 'pcie_aspm=force'\n");
+                       dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'\n");
                        return -EINVAL;
                }
        }
index ed129b4146246144de63db421ff04d28d5d7de27..b42133afca985659f6e9dde41a99ce2a05808a7b 100644 (file)
@@ -120,8 +120,7 @@ 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."
                 */
-               pos = pci_pcie_cap(dev);
-               pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
+               pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
                entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
                if (entry >= nr_entries)
                        goto Error;
index 3683f6094e3f19a3575fc29b2f55dd47250a397f..6186f03d84f37c8aa696d3df504e722a5cd36b38 100644 (file)
@@ -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 & 0xf];
+       bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
 }
 EXPORT_SYMBOL_GPL(pcie_update_link_speed);
 
@@ -579,14 +579,16 @@ 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);
 
-               if (status & 0x8000) {
+               pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS,
+                                    &status);
+
+               if (status & PCI_X_SSTATUS_533MHZ) {
                        max = PCI_SPEED_133MHz_PCIX_533;
-               } else if (status & 0x4000) {
+               } else if (status & PCI_X_SSTATUS_266MHZ) {
                        max = PCI_SPEED_133MHz_PCIX_266;
-               } else if (status & 0x0002) {
-                       if (((status >> 12) & 0x3) == 2) {
+               } else if (status & PCI_X_SSTATUS_133MHZ) {
+                       if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
                                max = PCI_SPEED_133MHz_PCIX_ECC;
                        } else {
                                max = PCI_SPEED_133MHz_PCIX;
@@ -596,7 +598,8 @@ static void pci_set_bus_speed(struct pci_bus *bus)
                }
 
                bus->max_bus_speed = max;
-               bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf];
+               bus->cur_bus_speed = pcix_bus_speed[
+                       (status & PCI_X_SSTATUS_FREQ) >> 6];
 
                return;
        }
@@ -607,7 +610,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 & 0xf];
+               bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
 
                pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
                pcie_update_link_speed(bus, linksta);
@@ -975,6 +978,7 @@ 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;
@@ -1889,6 +1893,28 @@ 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);
index 22ad3ee0cf0b66c90e8663ff4e74ca3119d11730..8f7a6344e79e4ca31f7db08ac63a2d4f168649e1 100644 (file)
@@ -1790,6 +1790,45 @@ 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 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 quirk_netmos(struct pci_dev *dev)
 {
        unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
index 513972f3ed13631f152b4d9b3bef9d8f489db857..7c0fd9252e6f03c1b1f17f53282be0c5a1fdb57d 100644 (file)
@@ -111,3 +111,39 @@ 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);
+}
index 0b3037ab8b9326bd5cbbad3517ff6c1bd348542a..ab886b7ee327af413f98976382869242fcba679b 100644 (file)
@@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        void __iomem *rom;
 
+       /*
+        * Some devices may provide ROMs via a source other than the BAR
+        */
+       if (pdev->rom && pdev->romlen) {
+               *size = pdev->romlen;
+               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
         * set for embedded VGA.
         */
-       if (res->flags & IORESOURCE_ROM_SHADOW) {
+       } else if (res->flags & IORESOURCE_ROM_SHADOW) {
                /* primary video rom always starts here */
                start = (loff_t)0xC0000;
                *size = 0x20000; /* cover C000:0 through E000:0 */
@@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
        if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
                return;
 
-       iounmap(rom);
+       if (!pdev->rom || !pdev->romlen)
+               iounmap(rom);
 
        /* Disable again before continuing, leave enabled if pci=rom */
        if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
index 1e808ca338f804208099472392e8a2117ebb4163..6d3591d57ea00734148e48e8fb2774bc34bb81b6 100644 (file)
@@ -1550,25 +1550,12 @@ enable_all:
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
-#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)
+void pci_assign_unassigned_bus_resources(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 ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(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
index db542f4196a4a77f2b9e6df7f8474a7d4f2b4531..966abc6054d7b625c18a5eeb854dc065b40d43c1 100644 (file)
@@ -1068,13 +1068,16 @@ 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);
index bb145e4b935e79760146f17d5f6bd4c70843278d..8b1d7a6a9695c44582890dc2a89acdd0e709e7b4 100644 (file)
@@ -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, struct pci_bus *bus);
-void acpi_pci_irq_del_prt(struct pci_bus *bus);
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt(int segment, int bus);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
index c47ec36f3f39cc71e53420e9e9433b181780f680..b02099d0b4fc20020dc578257983e804859876b2 100644 (file)
@@ -196,6 +196,77 @@ typedef struct {
        void *create_event_ex;
 } efi_boot_services_t;
 
+typedef enum {
+       EfiPciIoWidthUint8,
+       EfiPciIoWidthUint16,
+       EfiPciIoWidthUint32,
+       EfiPciIoWidthUint64,
+       EfiPciIoWidthFifoUint8,
+       EfiPciIoWidthFifoUint16,
+       EfiPciIoWidthFifoUint32,
+       EfiPciIoWidthFifoUint64,
+       EfiPciIoWidthFillUint8,
+       EfiPciIoWidthFillUint16,
+       EfiPciIoWidthFillUint32,
+       EfiPciIoWidthFillUint64,
+       EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+typedef enum {
+       EfiPciIoAttributeOperationGet,
+       EfiPciIoAttributeOperationSet,
+       EfiPciIoAttributeOperationEnable,
+       EfiPciIoAttributeOperationDisable,
+       EfiPciIoAttributeOperationSupported,
+    EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+
+typedef struct {
+       void *read;
+       void *write;
+} efi_pci_io_protocol_access_t;
+
+typedef struct {
+       void *poll_mem;
+       void *poll_io;
+       efi_pci_io_protocol_access_t mem;
+       efi_pci_io_protocol_access_t io;
+       efi_pci_io_protocol_access_t pci;
+       void *copy_mem;
+       void *map;
+       void *unmap;
+       void *allocate_buffer;
+       void *free_buffer;
+       void *flush;
+       void *get_location;
+       void *attributes;
+       void *get_bar_attributes;
+       void *set_bar_attributes;
+       uint64_t romsize;
+       void *romimage;
+} efi_pci_io_protocol;
+
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
+
 /*
  * Types and defines for EFI ResetSystem
  */
index af8229244ee2875f323af682ef90bb3d9b37134b..15472d691ee68c6aad5dbeb0a75933ec18f00404 100644 (file)
@@ -333,6 +333,8 @@ struct pci_dev {
        };
        struct pci_ats  *ats;   /* Address Translation Service */
 #endif
+       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 */
 };
 
 static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@ -538,6 +540,9 @@ 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 */
@@ -573,6 +578,7 @@ 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;
@@ -726,6 +732,8 @@ 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)
@@ -970,6 +978,7 @@ 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 *),
@@ -1604,6 +1613,7 @@ void pcibios_disable_device(struct pci_dev *dev);
 void pcibios_set_master(struct pci_dev *dev);
 int pcibios_set_pcie_reset_state(struct pci_dev *dev,
                                 enum pcie_reset_state state);
+int pcibios_add_device(struct pci_dev *dev);
 
 #ifdef CONFIG_PCI_MMCONFIG
 extern void __init pci_mmcfg_early_init(void);
@@ -1613,7 +1623,7 @@ static inline void pci_mmcfg_early_init(void) { }
 static inline void pci_mmcfg_late_init(void) { }
 #endif
 
-int pci_ext_cfg_avail(struct pci_dev *dev);
+int pci_ext_cfg_avail(void);
 
 void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 
@@ -1622,6 +1632,8 @@ 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,6 +1650,14 @@ 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)
index 20ae747ddf3483af636aef6f729fe90a33fa852d..6b7b6f1e2fd6a697dd26427c1130a5b51823d899 100644 (file)
 #define  PCI_AF_STATUS_TP      0x01
 #define PCI_CAP_AF_SIZEOF      6       /* size of AF registers */
 
-/* PCI-X registers */
+/* PCI-X registers (Type 0 (non-bridge) devices) */
 
 #define PCI_X_CMD              2       /* Modes & Features */
 #define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
 #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 */
 #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 */
 #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 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_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_CROSSLINK 0x100 /* Crosslink supported */
 #define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
 #define PCI_EXP_LNKSTA2                50      /* Link Status 2 */