dect
/
linux-2.6
Archived
13
0
Fork 0

PCI changes for the v3.8 merge window:

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)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (GNU/Linux)
 
 iQIcBAABAgAGBQJQyKwSAAoJEPGMOI97Hn6zScgQAJZK2VDfCv74mKrgSDNokIzH
 5nVDrc9AHKJm7CUODs6keJK5d4TD/za3Zao68zrYHsJJKes2ni2Z3W34HP2RXKK2
 eOmePXOHYPPZMlimP9r9cVxNu1ZJCyp/yWSBcsPF4zUgWhBWLRaSj85I049gQ0sz
 +05nZYfLjVd3HNiaXsG4CQyMrNF46XEsLhF9vs+Nr2GHPwrpzhfScgYv63oDS86C
 3ICKsjmiRUZcNelxIFYmyxa5u89QdW5XHjzc9eHGQuus24Vxw+TZzsdfc17sUJEE
 HTyXY+RjDpOVhdtwwUjrCEOiyZYvy3g9+3sKxoxgt/76ghdUaR7fxITwB97qVMFD
 T0ESlKjSV/Qv5QYdyy5uP4zwNs/PXCWXkTg/L1m71F30BxKWDa7tgiA6uK7Z7fl5
 1aokKBdk3mtJJJIDJG1YkxPXx/JItTGCNYrx7CcFj49rSjrUWLQdmrYahersRIsB
 3wiD2xTi9e4dXeP/+VGzGOWB/sHk+73jvrvZe/REa1FCnMINDz4+9V9WaGROMqyq
 MQ8kX0KfYcNVNxy1GOXjU5wLpMN/t/QbvI7gwzRP1DAUCJPoOgFy7AjvSTVG3zuy
 8CtdOFttVkUn5dqsbQR0gVbyQVTS3PGSKz5XC/s8kVDWhja0xZTBYwrskM/4zdSD
 Xf48OyYV5EjpC3FYUSiU
 =OE3Q
 -----END PGP SIGNATURE-----

Merge tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

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
  ...
This commit is contained in:
Linus Torvalds 2012-12-13 12:14:47 -08:00
commit 193c0d6825
45 changed files with 1150 additions and 271 deletions

View File

@ -222,3 +222,37 @@ Description:
satisfied too. Reading this attribute will show the current satisfied too. Reading this attribute will show the current
value of d3cold_allowed bit. Writing this attribute will set value of d3cold_allowed bit. Writing this attribute will set
the value of d3cold_allowed bit. 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.

View File

@ -2,6 +2,9 @@
Copyright (C) 2009 Intel Corporation Copyright (C) 2009 Intel Corporation
Yu Zhao <yu.zhao@intel.com> Yu Zhao <yu.zhao@intel.com>
Update: November 2012
-- sysfs-based SRIOV enable-/disable-ment
Donald Dutile <ddutile@redhat.com>
1. Overview 1. Overview
@ -24,10 +27,21 @@ real existing PCI device.
2.1 How can I enable SR-IOV capability 2.1 How can I enable SR-IOV capability
The device driver (PF driver) will control the enabling and disabling Multiple methods are available for SR-IOV enablement.
of the capability via API provided by SR-IOV core. If the hardware In the first method, the device driver (PF driver) will control the
has SR-IOV capability, loading its PF driver would enable it and all enabling and disabling of the capability via API provided by SR-IOV core.
VFs associated with the PF. 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 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 3.1 SR-IOV API
To enable SR-IOV capability: To enable SR-IOV capability:
(a) For the first method, in the driver:
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
'nr_virtfn' is number of VFs to be enabled. '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: To disable SR-IOV capability:
(a) For the first method, in the driver:
void pci_disable_sriov(struct pci_dev *dev); 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: To notify SR-IOV core of Virtual Function Migration:
(a) In the driver:
irqreturn_t pci_sriov_migration(struct pci_dev *dev); irqreturn_t pci_sriov_migration(struct pci_dev *dev);
3.2 Usage example 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 = { static struct pci_driver dev_driver = {
.name = "SR-IOV Physical Function driver", .name = "SR-IOV Physical Function driver",
.id_table = dev_id_table, .id_table = dev_id_table,
@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
.suspend = dev_suspend, .suspend = dev_suspend,
.resume = dev_resume, .resume = dev_resume,
.shutdown = dev_shutdown, .shutdown = dev_shutdown,
.sriov_configure = dev_sriov_configure,
}; };

View File

@ -370,6 +370,7 @@ config X86_NUMACHIP
depends on NUMA depends on NUMA
depends on SMP depends on SMP
depends on X86_X2APIC depends on X86_X2APIC
depends on PCI_MMCONFIG
---help--- ---help---
Adds support for Numascale NumaChip large-SMP systems. Needed to Adds support for Numascale NumaChip large-SMP systems. Needed to
enable more than ~168 cores. enable more than ~168 cores.

View File

@ -8,6 +8,7 @@
* ----------------------------------------------------------------------- */ * ----------------------------------------------------------------------- */
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/pci.h>
#include <asm/efi.h> #include <asm/efi.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/desc.h> #include <asm/desc.h>
@ -245,6 +246,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
*size = len; *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 * 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_graphics(boot_params);
setup_efi_pci(boot_params);
status = efi_call_phys3(sys_table->boottime->allocate_pool, status = efi_call_phys3(sys_table->boottime->allocate_pool,
EFI_LOADER_DATA, sizeof(*gdt), EFI_LOADER_DATA, sizeof(*gdt),
(void **)&gdt); (void **)&gdt);

View File

@ -13,6 +13,7 @@
#define SETUP_NONE 0 #define SETUP_NONE 0
#define SETUP_E820_EXT 1 #define SETUP_E820_EXT 1
#define SETUP_DTB 2 #define SETUP_DTB 2
#define SETUP_PCI 3
/* extensible setup data list node */ /* extensible setup data list node */
struct setup_data { struct setup_data {

View File

@ -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 */

View File

@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
} }
#endif #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 */ #endif /* _ASM_X86_PCI_H */

View File

@ -22,6 +22,7 @@
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/numachip/numachip.h>
#include <asm/numachip/numachip_csr.h> #include <asm/numachip/numachip_csr.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/apic.h> #include <asm/apic.h>
@ -179,6 +180,7 @@ static int __init numachip_system_init(void)
return 0; return 0;
x86_cpuinit.fixup_cpu_id = fixup_cpu_id; x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
x86_init.pci.arch_init = pci_numachip_init;
map_csrs(); map_csrs();

View File

@ -143,11 +143,7 @@ int default_check_phys_apicid_present(int phys_apicid)
} }
#endif #endif
#ifndef CONFIG_DEBUG_BOOT_PARAMS
struct boot_params __initdata boot_params;
#else
struct boot_params boot_params; struct boot_params boot_params;
#endif
/* /*
* Machine setup.. * Machine setup..

View File

@ -16,6 +16,7 @@ obj-$(CONFIG_STA2X11) += sta2x11-fixup.o
obj-$(CONFIG_X86_VISWS) += visws.o obj-$(CONFIG_X86_VISWS) += visws.o
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-$(CONFIG_X86_INTEL_MID) += mrst.o obj-$(CONFIG_X86_INTEL_MID) += mrst.o

View File

@ -12,6 +12,7 @@ struct pci_root_info {
char name[16]; char name[16];
unsigned int res_num; unsigned int res_num;
struct resource *res; struct resource *res;
resource_size_t *res_offset;
struct pci_sysdata sd; struct pci_sysdata sd;
#ifdef CONFIG_PCI_MMCONFIG #ifdef CONFIG_PCI_MMCONFIG
bool mcfg_added; bool mcfg_added;
@ -22,6 +23,7 @@ struct pci_root_info {
}; };
static bool pci_use_crs = true; static bool pci_use_crs = true;
static bool pci_ignore_seg = false;
static int __init set_use_crs(const struct dmi_system_id *id) 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; 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 */ /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
{ {
.callback = set_use_crs, .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 )"), 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) if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
pci_use_crs = false; 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 * 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->flags = flags;
res->start = start; res->start = start;
res->end = end; res->end = end;
info->res_offset[info->res_num] = addr.translation_offset;
if (!pci_use_crs) { if (!pci_use_crs) {
dev_printk(KERN_DEBUG, &info->bridge->dev, 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", "ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict); res, conflict->name, conflict);
else 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); kfree(info->res);
info->res = NULL; info->res = NULL;
kfree(info->res_offset);
info->res_offset = NULL;
info->res_num = 0; info->res_num = 0;
} }
@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
return; return;
size = sizeof(*info->res) * info->res_num; size = sizeof(*info->res) * info->res_num;
info->res_num = 0;
info->res = kzalloc(size, GFP_KERNEL); info->res = kzalloc(size, GFP_KERNEL);
if (!info->res) if (!info->res) {
info->res_num = 0;
return; 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, acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info); info);
@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
int pxm; int pxm;
#endif #endif
if (pci_ignore_seg)
domain = 0;
if (domain && !pci_domains_supported) { if (domain && !pci_domains_supported) {
printk(KERN_WARNING "pci_bus %04x:%02x: " printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (multiple domains not supported)\n", "ignored (multiple domains not supported)\n",

View File

@ -17,6 +17,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#include <asm/setup.h>
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF; PCI_PROBE_MMCONF;
@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; 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 pcibios_enable_device(struct pci_dev *dev, int mask)
{ {
int err; int err;
@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
pcibios_disable_irq(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) if (raw_pci_ext_ops)
return 1; return 1;

129
arch/x86/pci/numachip.c Normal file
View File

@ -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;
}

View File

@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
device_set_run_wake(&dev->dev, false); device_set_run_wake(&dev->dev, false);
pci_acpi_remove_pm_notifier(device); pci_acpi_remove_pm_notifier(device);
acpi_power_resource_unregister_device(&dev->dev, device->handle);
if (!dev->subordinate) if (!dev->subordinate)
goto out; 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.bind = NULL;
device->ops.unbind = NULL; device->ops.unbind = NULL;
@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
{ {
acpi_status status; acpi_status status;
acpi_handle handle; acpi_handle handle;
struct pci_bus *bus; unsigned char bus;
struct pci_dev *dev; struct pci_dev *dev;
dev = acpi_get_pci_dev(device->handle); dev = acpi_get_pci_dev(device->handle);
@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
return 0; return 0;
pci_acpi_add_pm_notifier(device, dev); pci_acpi_add_pm_notifier(device, dev);
acpi_power_resource_register_device(&dev->dev, device->handle);
if (device->wakeup.flags.run_wake) if (device->wakeup.flags.run_wake)
device_set_run_wake(&dev->dev, true); device_set_run_wake(&dev->dev, true);
@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
goto out; goto out;
if (dev->subordinate) if (dev->subordinate)
bus = dev->subordinate; bus = dev->subordinate->number;
else 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: out:
pci_dev_put(dev); pci_dev_put(dev);

View 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_pci_routing_table *prt)
{ {
struct acpi_prt_entry *entry; 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 * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
* it here. * it here.
*/ */
entry->id.segment = pci_domain_nr(bus); entry->id.segment = segment;
entry->id.bus = bus->number; entry->id.bus = bus;
entry->id.device = (prt->address >> 16) & 0xFFFF; entry->id.device = (prt->address >> 16) & 0xFFFF;
entry->pin = prt->pin + 1; 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; 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; acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 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; entry = buffer.pointer;
while (entry && (entry->length > 0)) { 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 *) entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length); ((unsigned long)entry + entry->length);
} }
@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
return 0; 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; struct acpi_prt_entry *entry, *tmp;
printk(KERN_DEBUG printk(KERN_DEBUG
"ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
pci_domain_nr(bus), bus->number); segment, bus);
spin_lock(&acpi_prt_lock); spin_lock(&acpi_prt_lock);
list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
if (pci_domain_nr(bus) == entry->id.segment if (segment == entry->id.segment && bus == entry->id.bus) {
&& bus->number == entry->id.bus) {
list_del(&entry->list); list_del(&entry->list);
kfree(entry); kfree(entry);
} }

View File

@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_handle handle; acpi_handle handle;
struct acpi_device *child; struct acpi_device *child;
u32 flags, base_flags; u32 flags, base_flags;
bool is_osc_granted = false;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root) if (!root)
@ -501,6 +502,20 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root; device->driver_data = root;
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
/*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists.
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
result = acpi_pci_irq_add_prt(device->handle, root->segment,
root->secondary.start);
root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
/* /*
@ -510,6 +525,60 @@ static int acpi_pci_root_add(struct acpi_device *device)
flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
acpi_pci_osc_support(root, flags); acpi_pci_osc_support(root, flags);
/* Indicate support for various _OSC capabilities. */
if (pci_ext_cfg_avail())
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
if (pcie_aspm_support_enabled()) {
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
}
if (pci_msi_enabled())
flags |= OSC_MSI_SUPPORT;
if (flags != base_flags) {
status = acpi_pci_osc_support(root, flags);
if (ACPI_FAILURE(status)) {
dev_info(&device->dev, "ACPI _OSC support "
"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
| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
| OSC_PCI_EXPRESS_PME_CONTROL;
if (pci_aer_available()) {
if (aer_acpi_firmware_first())
dev_dbg(&device->dev,
"PCIe errors handled by BIOS.\n");
else
flags |= OSC_PCI_EXPRESS_AER_CONTROL;
}
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);
if (ACPI_SUCCESS(status)) {
is_osc_granted = true;
dev_info(&device->dev,
"ACPI _OSC control (0x%02x) granted\n", flags);
} else {
is_osc_granted = false;
dev_info(&device->dev,
"ACPI _OSC request failed (%s), "
"returned control mask: 0x%02x\n",
acpi_format_exception(status), flags);
}
} else {
dev_info(&device->dev,
"Unable to request _OSC control "
"(_OSC support mask: 0x%02x)\n", flags);
}
/* /*
* TBD: Need PCI interface for enumeration/configuration of roots. * TBD: Need PCI interface for enumeration/configuration of roots.
*/ */
@ -518,10 +587,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
list_add_tail(&root->node, &acpi_pci_roots); list_add_tail(&root->node, &acpi_pci_roots);
mutex_unlock(&acpi_pci_root_lock); 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 * Scan the Root Bridge
* -------------------- * --------------------
@ -547,81 +612,20 @@ static int acpi_pci_root_add(struct acpi_device *device)
if (result) if (result)
goto out_del_root; goto out_del_root;
/*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists.
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
result = acpi_pci_irq_add_prt(device->handle, root->bus);
/* /*
* Scan and bind all _ADR-Based Devices * Scan and bind all _ADR-Based Devices
*/ */
list_for_each_entry(child, &device->children, node) list_for_each_entry(child, &device->children, node)
acpi_pci_bridge_scan(child); acpi_pci_bridge_scan(child);
/* Indicate support for various _OSC capabilities. */ /* ASPM setting */
if (pci_ext_cfg_avail(root->bus->self)) if (is_osc_granted) {
flags |= OSC_EXT_PCI_CONFIG_SUPPORT; if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
if (pcie_aspm_support_enabled()) pcie_clear_aspm(root->bus);
flags |= OSC_ACTIVE_STATE_PWR_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 "
"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
| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
| OSC_PCI_EXPRESS_PME_CONTROL;
if (pci_aer_available()) {
if (aer_acpi_firmware_first())
dev_dbg(root->bus->bridge,
"PCIe errors handled by BIOS.\n");
else
flags |= OSC_PCI_EXPRESS_AER_CONTROL;
}
dev_info(root->bus->bridge,
"Requesting ACPI _OSC control (0x%02x)\n", flags);
status = acpi_pci_osc_control_set(device->handle, &flags,
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_SUCCESS(status)) {
dev_info(root->bus->bridge,
"ACPI _OSC control (0x%02x) granted\n", flags);
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
/*
* We have ASPM control, but the FADT indicates
* that it's unsupported. Clear it.
*/
pcie_clear_aspm(root->bus);
}
} else {
dev_info(root->bus->bridge,
"ACPI _OSC request failed (%s), "
"returned control mask: 0x%02x\n",
acpi_format_exception(status), flags);
pr_info("ACPI _OSC control for PCIe not granted, "
"disabling ASPM\n");
pcie_no_aspm();
}
} else { } else {
dev_info(root->bus->bridge, pr_info("ACPI _OSC control for PCIe not granted, "
"Unable to request _OSC control " "disabling ASPM\n");
"(_OSC support mask: 0x%02x)\n", flags); pcie_no_aspm();
} }
pci_acpi_add_bus_pm_notifier(device, root->bus); pci_acpi_add_bus_pm_notifier(device, root->bus);
@ -634,6 +638,8 @@ out_del_root:
mutex_lock(&acpi_pci_root_lock); mutex_lock(&acpi_pci_root_lock);
list_del(&root->node); list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock); mutex_unlock(&acpi_pci_root_lock);
acpi_pci_irq_del_prt(root->segment, root->secondary.start);
end: end:
kfree(root); kfree(root);
return result; 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_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver; struct acpi_pci_driver *driver;
if (system_state != SYSTEM_BOOTING)
pci_assign_unassigned_bus_resources(root->bus);
mutex_lock(&acpi_pci_root_lock); mutex_lock(&acpi_pci_root_lock);
list_for_each_entry(driver, &acpi_pci_drivers, node) list_for_each_entry(driver, &acpi_pci_drivers, node)
if (driver->add) if (driver->add)
driver->add(root); driver->add(root);
mutex_unlock(&acpi_pci_root_lock); 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); pci_bus_add_devices(root->bus);
return 0; 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) 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_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver; struct acpi_pci_driver *driver;
pci_stop_root_bus(root->bus);
mutex_lock(&acpi_pci_root_lock); 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) if (driver->remove)
driver->remove(root); driver->remove(root);
mutex_unlock(&acpi_pci_root_lock);
device_set_run_wake(root->bus->bridge, false); device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device); 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); list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock); mutex_unlock(&acpi_pci_root_lock);
kfree(root); kfree(root);

View File

@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap)
G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE)); G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
log2_width = fls(adap->params.pci.width) - 1; log2_width = fls(adap->params.pci.width) - 1;
acklat = ack_lat[log2_width][pldsize]; 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; acklat += fst_trn_tx * 4;
rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4; rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;

View 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) && if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
(AR_SREV_9285(ah))) { (AR_SREV_9285(ah))) {
/* Bluetooth coexistance requires disabling ASPM. */ /* Bluetooth coexistence requires disabling ASPM. */
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, 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 * Both upstream and downstream PCIe components should
* have the same ASPM settings. * have the same ASPM settings.
*/ */
pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, 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"); ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
return; return;
} }
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm); 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; ah->aspm_enabled = true;
/* Initialize PCIe PM and SERDES registers. */ /* Initialize PCIe PM and SERDES registers. */
ath9k_hw_configpcipowersave(ah, false); ath9k_hw_configpcipowersave(ah, false);

View File

@ -917,10 +917,6 @@ struct il4965_scd_bc_tbl {
/* PCI registers */ /* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041 #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 #define IL4965_DEFAULT_TX_RETRY 15
/* EEPROM */ /* EEPROM */

View File

@ -1183,9 +1183,10 @@ EXPORT_SYMBOL(il_power_update_mode);
void void
il_power_initialize(struct il_priv *il) 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; il->power_data.debug_sleep_level_override = -1;
@ -4233,9 +4234,8 @@ il_apm_init(struct il_priv *il)
* power savings, even without L1. * power savings, even without L1.
*/ */
if (il->cfg->set_l0s) { if (il->cfg->set_l0s) {
lctl = il_pcie_link_ctl(il); pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
/* L1-ASPM enabled; disable(!) L0S */ /* L1-ASPM enabled; disable(!) L0S */
il_set_bit(il, CSR_GIO_REG, il_set_bit(il, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED); CSR_GIO_REG_VAL_L0S_ENABLED);

View File

@ -1829,14 +1829,6 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
* PCI * * 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); void il_bg_watchdog(unsigned long data);
u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval); 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, __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
@ -2434,10 +2426,6 @@ struct il_tfd {
/* PCI registers */ /* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041 #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 { struct il_rate_info {
u8 plcp; /* uCode API: RATE_6M_PLCP, etc. */ u8 plcp; /* uCode API: RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: RATE_SISO_6M_PLCP, etc. */ u8 plcp_siso; /* uCode API: RATE_SISO_6M_PLCP, etc. */

View File

@ -94,8 +94,6 @@ static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
/* PCI registers */ /* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041 #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) 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. * power savings, even without L1.
*/ */
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
/* L1-ASPM enabled; disable(!) L0S */ /* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
dev_info(trans->dev, "L1 Enabled; Disabling L0S\n"); 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); iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
dev_info(trans->dev, "L1 Disabled; Enabling L0S\n"); 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);
} }
/* /*

View File

@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
int retval; int retval;
pci_fixup_device(pci_fixup_final, dev); pci_fixup_device(pci_fixup_final, dev);
retval = pcibios_add_device(dev);
if (retval)
return retval;
retval = device_add(&dev->dev); retval = device_add(&dev->dev);
if (retval) if (retval)
return retval; return retval;

View File

@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
module_init(ioapic_init); module_init(ioapic_init);
module_exit(ioapic_exit); module_exit(ioapic_exit);
MODULE_LICENSE("GPL");

View 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].name = pci_name(virtfn);
virtfn->resource[i].flags = res->flags; virtfn->resource[i].flags = res->flags;
size = resource_size(res); 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].start = res->start + size * id;
virtfn->resource[i].end = virtfn->resource[i].start + size - 1; virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
rc = request_resource(res, &virtfn->resource[i]); rc = request_resource(res, &virtfn->resource[i]);
@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
u16 status; u16 status;
struct pci_sriov *iov = dev->sriov; struct pci_sriov *iov = dev->sriov;
if (!iov->nr_virtfn) if (!iov->num_VFs)
return 0; return 0;
if (!(iov->cap & PCI_SRIOV_CAP_VFM)) if (!(iov->cap & PCI_SRIOV_CAP_VFM))
@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
u16 status; u16 status;
struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask); 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); state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_MI) { if (state == PCI_SRIOV_VFM_MI) {
writeb(PCI_SRIOV_VFM_AV, iov->mstate + i); 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; resource_size_t pa;
struct pci_sriov *iov = dev->sriov; struct pci_sriov *iov = dev->sriov;
if (nr_virtfn <= iov->initial) if (nr_virtfn <= iov->initial_VFs)
return 0; return 0;
pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table); 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) if (!nr_virtfn)
return 0; return 0;
if (iov->nr_virtfn) if (iov->num_VFs)
return -EINVAL; return -EINVAL;
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial); pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
if (initial > iov->total || if (initial > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total))) (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
return -EIO; 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))) (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL; return -EINVAL;
@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
msleep(100); msleep(100);
pci_cfg_access_unlock(dev); pci_cfg_access_unlock(dev);
iov->initial = initial; iov->initial_VFs = initial;
if (nr_virtfn < initial) if (nr_virtfn < initial)
initial = nr_virtfn; 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); kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
iov->nr_virtfn = nr_virtfn; iov->num_VFs = nr_virtfn;
return 0; return 0;
@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
int i; int i;
struct pci_sriov *iov = dev->sriov; struct pci_sriov *iov = dev->sriov;
if (!iov->nr_virtfn) if (!iov->num_VFs)
return; return;
if (iov->cap & PCI_SRIOV_CAP_VFM) if (iov->cap & PCI_SRIOV_CAP_VFM)
sriov_disable_migration(dev); 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); virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); 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) if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link"); 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) static int sriov_init(struct pci_dev *dev, int pos)
@ -496,7 +496,7 @@ found:
iov->pos = pos; iov->pos = pos;
iov->nres = nres; iov->nres = nres;
iov->ctrl = ctrl; iov->ctrl = ctrl;
iov->total = total; iov->total_VFs = total;
iov->offset = offset; iov->offset = offset;
iov->stride = stride; iov->stride = stride;
iov->pgsz = pgsz; iov->pgsz = pgsz;
@ -529,7 +529,7 @@ failed:
static void sriov_release(struct pci_dev *dev) 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) if (dev != dev->sriov->dev)
pci_dev_put(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_update_resource(dev, i);
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); 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); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
if (iov->ctrl & PCI_SRIOV_CTRL_VFE) if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
msleep(100); msleep(100);
@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
if (!dev->is_physfn) if (!dev->is_physfn)
continue; continue;
busnr = virtfn_bus(dev, dev->sriov->total - 1); busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
if (busnr > max) if (busnr > max)
max = busnr; max = busnr;
} }
@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
*/ */
int pci_num_vf(struct pci_dev *dev) int pci_num_vf(struct pci_dev *dev)
{ {
if (!dev || !dev->is_physfn) if (!dev->is_physfn)
return 0; return 0;
else
return dev->sriov->nr_virtfn; return dev->sriov->num_VFs;
} }
EXPORT_SYMBOL_GPL(pci_num_vf); 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);

View 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); struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
dev_printk(KERN_ERR, &pdev->dev, dev_err(&pdev->dev,
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n", "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
dev_name(&parent->dev), parent->vendor, parent->device); dev_name(&parent->dev), parent->vendor, parent->device);
dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason); dev_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, "Please report to linux-kernel@vger.kernel.org\n");
WARN_ON(1); WARN_ON(1);
} }

View File

@ -248,31 +248,26 @@ struct drv_dev_and_id {
static long local_pci_probe(void *_ddi) static long local_pci_probe(void *_ddi)
{ {
struct drv_dev_and_id *ddi = _ddi; struct drv_dev_and_id *ddi = _ddi;
struct device *dev = &ddi->dev->dev; struct pci_dev *pci_dev = ddi->dev;
struct device *parent = dev->parent; struct pci_driver *pci_drv = ddi->drv;
struct device *dev = &pci_dev->dev;
int rc; int rc;
/* The parent bridge must be in active state when probing */ /*
if (parent) * Unbound PCI devices are always put in D0, regardless of
pm_runtime_get_sync(parent); * runtime PM status. During probe, the device is set to
/* Unbound PCI devices are always set to disabled and suspended. * active and the usage count is incremented. If the driver
* During probe, the device is set to enabled and active and the * supports runtime PM, it should call pm_runtime_put_noidle()
* usage count is incremented. If the driver supports runtime PM, * in its probe routine and pm_runtime_get_noresume() in its
* it should call pm_runtime_put_noidle() in its probe routine and * remove routine.
* pm_runtime_get_noresume() in its remove routine.
*/ */
pm_runtime_get_noresume(dev); pm_runtime_get_sync(dev);
pm_runtime_set_active(dev); pci_dev->driver = pci_drv;
pm_runtime_enable(dev); rc = pci_drv->probe(pci_dev, ddi->id);
rc = ddi->drv->probe(ddi->dev, ddi->id);
if (rc) { if (rc) {
pm_runtime_disable(dev); pci_dev->driver = NULL;
pm_runtime_set_suspended(dev); pm_runtime_put_sync(dev);
pm_runtime_put_noidle(dev);
} }
if (parent)
pm_runtime_put(parent);
return rc; 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); id = pci_match_device(drv, pci_dev);
if (id) if (id)
error = pci_call_probe(drv, pci_dev, id); error = pci_call_probe(drv, pci_dev, id);
if (error >= 0) { if (error >= 0)
pci_dev->driver = drv;
error = 0; error = 0;
}
} }
return error; return error;
} }
@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
} }
/* Undo the runtime PM settings in local_pci_probe() */ /* Undo the runtime PM settings in local_pci_probe() */
pm_runtime_disable(dev); pm_runtime_put_sync(dev);
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
/* /*
* If the device is still on, set the power state as "unknown", * 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; pci_power_t prev = pci_dev->current_state;
int error; 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) if (!pm || !pm->runtime_suspend)
return -ENOSYS; return -ENOSYS;
@ -1007,10 +1005,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
return 0; return 0;
} }
if (!pci_dev->state_saved) if (!pci_dev->state_saved) {
pci_save_state(pci_dev); pci_save_state(pci_dev);
pci_finish_runtime_suspend(pci_dev);
pci_finish_runtime_suspend(pci_dev); }
return 0; return 0;
} }
@ -1021,6 +1019,13 @@ static int pci_pm_runtime_resume(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 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) if (!pm || !pm->runtime_resume)
return -ENOSYS; return -ENOSYS;
@ -1038,8 +1043,16 @@ static int pci_pm_runtime_resume(struct device *dev)
static int pci_pm_runtime_idle(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; 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) if (!pm)
return -ENOSYS; return -ENOSYS;
@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
return ret; return ret;
} }
out:
pm_runtime_suspend(dev); pm_runtime_suspend(dev);
return 0; return 0;
} }

View 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) 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; return 0;
} }

View File

@ -401,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
} }
#endif #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[] = { struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource), __ATTR_RO(resource),
__ATTR_RO(vendor), __ATTR_RO(vendor),
@ -1262,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
pdev->rom_attr = attr; 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 */ /* add platform-specific attributes */
retval = pcibios_add_platform_entries(pdev); retval = pcibios_add_platform_entries(pdev);
if (retval) if (retval)
goto err_vga_file; goto err_rom_file;
/* add sysfs entries for various capabilities */ /* add sysfs entries for various capabilities */
retval = pci_create_capabilities_sysfs(pdev); retval = pci_create_capabilities_sysfs(pdev);
if (retval) if (retval)
goto err_vga_file; goto err_rom_file;
pci_create_firmware_label_files(pdev); pci_create_firmware_label_files(pdev);
return 0; return 0;
err_vga_file:
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
device_remove_file(&pdev->dev, &vga_attr);
err_rom_file: err_rom_file:
if (rom_size) { if (rom_size) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 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); 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,
};

View File

@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
dr->pinned = 1; 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 * pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable * @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_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 * PCI (as opposed to PCIe) PME requires that the device have
do this, so the PME never gets delivered and the device * its PME# line hooked up correctly. Not all hardware vendors
remains asleep. The easiest way around this is to * do this, so the PME never gets delivered and the device
periodically walk the list of suspended devices and check * remains asleep. The easiest way around this is to
whether any have their PME flag set. The assumption is that * periodically walk the list of suspended devices and check
we'll wake up often enough anyway that this won't be a huge * whether any have their PME flag set. The assumption is that
hit, and the power savings from the devices will still be a * we'll wake up often enough anyway that this won't be a huge
win. */ * 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) { if (dev->pme_poll) {
struct pci_pme_device *pme_dev; struct pci_pme_device *pme_dev;
@ -1900,6 +1923,8 @@ void pci_pm_init(struct pci_dev *dev)
u16 pmc; u16 pmc;
pm_runtime_forbid(&dev->dev); pm_runtime_forbid(&dev->dev);
pm_runtime_set_active(&dev->dev);
pm_runtime_enable(&dev->dev);
device_enable_async_suspend(&dev->dev); device_enable_async_suspend(&dev->dev);
dev->wakeup_prepared = false; 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? * pci_ext_cfg_avail - can we access extended PCI config space?
* @dev: The PCI device of the root bridge.
* *
* Returns 1 if we can access PCI extended config space (offsets * Returns 1 if we can access PCI extended config space (offsets
* greater than 0xff). This is the default implementation. Architecture * greater than 0xff). This is the default implementation. Architecture
* implementations can override this. * implementations can override this.
*/ */
int __weak pci_ext_cfg_avail(struct pci_dev *dev) int __weak pci_ext_cfg_avail(void)
{ {
return 1; return 1;
} }

View 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 pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[]; extern struct device_attribute pcibus_dev_attrs[];
extern struct device_type pci_dev_type;
extern struct bus_attribute pci_bus_attrs[]; extern struct bus_attribute pci_bus_attrs[];
@ -229,13 +230,14 @@ struct pci_sriov {
int nres; /* number of resources */ int nres; /* number of resources */
u32 cap; /* SR-IOV Capabilities */ u32 cap; /* SR-IOV Capabilities */
u16 ctrl; /* SR-IOV Control */ u16 ctrl; /* SR-IOV Control */
u16 total; /* total VFs associated with the PF */ u16 total_VFs; /* total VFs associated with the PF */
u16 initial; /* initial VFs associated with the PF */ u16 initial_VFs; /* initial VFs associated with the PF */
u16 nr_virtfn; /* number of VFs available */ u16 num_VFs; /* number of VFs available */
u16 offset; /* first VF Routing ID offset */ u16 offset; /* first VF Routing ID offset */
u16 stride; /* following VF stride */ u16 stride; /* following VF stride */
u32 pgsz; /* page size for BAR alignment */ u32 pgsz; /* page size for BAR alignment */
u8 link; /* Function Dependency Link */ u8 link; /* Function Dependency Link */
u16 driver_max_VFs; /* max num VFs driver supports */
struct pci_dev *dev; /* lowest numbered PF */ struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */ struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for VF bus */ struct mutex lock; /* lock for VF bus */

View File

@ -87,6 +87,9 @@ struct aer_broadcast_data {
static inline pci_ers_result_t merge_result(enum pci_ers_result orig, static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new) 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) if (new == PCI_ERS_RESULT_NONE)
return orig; return orig;
@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
break; break;
case PCI_ERS_RESULT_DISCONNECT: case PCI_ERS_RESULT_DISCONNECT:
if (new == PCI_ERS_RESULT_NEED_RESET) if (new == PCI_ERS_RESULT_NEED_RESET)
orig = new; orig = PCI_ERS_RESULT_NEED_RESET;
break; break;
default: default:
break; break;

View File

@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
dev->driver ? dev->driver ?
"no AER-aware driver" : "no 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); result_data->result = merge_result(result_data->result, vote);
out:
device_unlock(&dev->dev); device_unlock(&dev->dev);
return 0; return 0;
} }

View File

@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
return; return;
/* Training failed. Restore common clock configurations */ /* Training failed. Restore common clock configurations */
dev_printk(KERN_ERR, &parent->dev, dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
"ASPM: Could not configure common clock\n");
list_for_each_entry(child, &linkbus->devices, bus_list) list_for_each_entry(child, &linkbus->devices, bus_list)
pcie_capability_write_word(child, PCI_EXP_LNKCTL, pcie_capability_write_word(child, PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]); 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) 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) 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; return;
/* Convert ASPM state to upstream/downstream ASPM register state */ /* Convert ASPM state to upstream/downstream ASPM register state */
if (state & ASPM_STATE_L0S_UP) if (state & ASPM_STATE_L0S_UP)
dwstream |= PCIE_LINK_STATE_L0S; dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L0S_DW) if (state & ASPM_STATE_L0S_DW)
upstream |= PCIE_LINK_STATE_L0S; upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L1) { if (state & ASPM_STATE_L1) {
upstream |= PCIE_LINK_STATE_L1; upstream |= PCI_EXP_LNKCTL_ASPM_L1;
dwstream |= PCIE_LINK_STATE_L1; dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
} }
/* /*
* Spec 2.0 suggests all functions should be configured the * 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); pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
dev_printk(KERN_INFO, &child->dev, "disabling ASPM" dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n");
" on pre-1.1 PCIe device. You can enable it"
" with 'pcie_aspm=force'\n");
return -EINVAL; return -EINVAL;
} }
} }

View 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 * the value in this field indicates which MSI-X Table entry is
* used to generate the interrupt message." * used to generate the interrupt message."
*/ */
pos = pci_pcie_cap(dev); pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9; entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
if (entry >= nr_entries) if (entry >= nr_entries)
goto Error; goto Error;

View File

@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = {
void pcie_update_link_speed(struct pci_bus *bus, u16 linksta) 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); EXPORT_SYMBOL_GPL(pcie_update_link_speed);
@ -579,14 +579,16 @@ static void pci_set_bus_speed(struct pci_bus *bus)
if (pos) { if (pos) {
u16 status; u16 status;
enum pci_bus_speed max; 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; max = PCI_SPEED_133MHz_PCIX_533;
} else if (status & 0x4000) { } else if (status & PCI_X_SSTATUS_266MHZ) {
max = PCI_SPEED_133MHz_PCIX_266; max = PCI_SPEED_133MHz_PCIX_266;
} else if (status & 0x0002) { } else if (status & PCI_X_SSTATUS_133MHZ) {
if (((status >> 12) & 0x3) == 2) { if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
max = PCI_SPEED_133MHz_PCIX_ECC; max = PCI_SPEED_133MHz_PCIX_ECC;
} else { } else {
max = PCI_SPEED_133MHz_PCIX; 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->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; return;
} }
@ -607,7 +610,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
u16 linksta; u16 linksta;
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); 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_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
pcie_update_link_speed(bus, 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->sysdata = dev->bus->sysdata;
dev->dev.parent = dev->bus->bridge; dev->dev.parent = dev->bus->bridge;
dev->dev.bus = &pci_bus_type; dev->dev.bus = &pci_bus_type;
dev->dev.type = &pci_dev_type;
dev->hdr_type = hdr_type & 0x7f; dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80); dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal; 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; 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_add_new_bus);
EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge); EXPORT_SYMBOL(pci_scan_bridge);

View File

@ -1790,6 +1790,45 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
quirk_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) static void quirk_netmos(struct pci_dev *dev)
{ {
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;

View File

@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
pci_remove_bus_device(dev); pci_remove_bus_device(dev);
} }
EXPORT_SYMBOL(pci_stop_and_remove_bus_device); 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);
}

View File

@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
loff_t start; loff_t start;
void __iomem *rom; 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 * 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 * memory map if the VGA enable bit of the Bridge Control register is
* set for embedded VGA. * set for embedded VGA.
*/ */
if (res->flags & IORESOURCE_ROM_SHADOW) { } else if (res->flags & IORESOURCE_ROM_SHADOW) {
/* primary video rom always starts here */ /* primary video rom always starts here */
start = (loff_t)0xC0000; start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */ *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)) if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return; return;
iounmap(rom); if (!pdev->rom || !pdev->romlen)
iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */ /* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))

View File

@ -1550,25 +1550,12 @@ enable_all:
} }
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
#ifdef CONFIG_HOTPLUG void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
/**
* pci_rescan_bus - scan a PCI bus for devices.
* @bus: PCI bus to scan
*
* Scan a PCI bus and child buses for new devices, adds them,
* and enables them.
*
* Returns the max number of subordinate bus discovered.
*/
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
{ {
unsigned int max;
struct pci_dev *dev; struct pci_dev *dev;
LIST_HEAD(add_list); /* list of resources that LIST_HEAD(add_list); /* list of resources that
want additional resources */ want additional resources */
max = pci_scan_child_bus(bus);
down_read(&pci_bus_sem); down_read(&pci_bus_sem);
list_for_each_entry(dev, &bus->devices, bus_list) list_for_each_entry(dev, &bus->devices, bus_list)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 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); up_read(&pci_bus_sem);
__pci_bus_assign_resources(bus, &add_list, NULL); __pci_bus_assign_resources(bus, &add_list, NULL);
BUG_ON(!list_empty(&add_list)); BUG_ON(!list_empty(&add_list));
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
return max;
} }
EXPORT_SYMBOL_GPL(pci_rescan_bus);
#endif

View File

@ -1068,13 +1068,16 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
case XenbusStateInitialising: case XenbusStateInitialising:
case XenbusStateInitWait: case XenbusStateInitWait:
case XenbusStateInitialised: case XenbusStateInitialised:
case XenbusStateClosed:
break; break;
case XenbusStateConnected: case XenbusStateConnected:
pcifront_try_connect(pdev); pcifront_try_connect(pdev);
break; break;
case XenbusStateClosed:
if (xdev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing: case XenbusStateClosing:
dev_warn(&xdev->dev, "backend going away!\n"); dev_warn(&xdev->dev, "backend going away!\n");
pcifront_try_disconnect(pdev); pcifront_try_disconnect(pdev);

View File

@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle);
/* ACPI PCI Interrupt Routing (pci_irq.c) */ /* ACPI PCI Interrupt Routing (pci_irq.c) */
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);
void acpi_pci_irq_del_prt(struct pci_bus *bus); void acpi_pci_irq_del_prt(int segment, int bus);
/* ACPI PCI Device Binding (pci_bind.c) */ /* ACPI PCI Device Binding (pci_bind.c) */

View File

@ -196,6 +196,77 @@ typedef struct {
void *create_event_ex; void *create_event_ex;
} efi_boot_services_t; } 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 * Types and defines for EFI ResetSystem
*/ */

View File

@ -333,6 +333,8 @@ struct pci_dev {
}; };
struct pci_ats *ats; /* Address Translation Service */ struct pci_ats *ats; /* Address Translation Service */
#endif #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) 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 */ /* Device driver is fully recovered and operational */
PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5, 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 */ /* PCI bus error event callbacks */
@ -573,6 +578,7 @@ struct pci_driver {
int (*resume_early) (struct pci_dev *dev); int (*resume_early) (struct pci_dev *dev);
int (*resume) (struct pci_dev *dev); /* Device woken up */ int (*resume) (struct pci_dev *dev); /* Device woken up */
void (*shutdown) (struct pci_dev *dev); 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; const struct pci_error_handlers *err_handler;
struct device_driver driver; struct device_driver driver;
struct pci_dynids dynids; 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_dev_put(struct pci_dev *dev);
extern void pci_remove_bus(struct pci_bus *b); extern void pci_remove_bus(struct pci_bus *b);
extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); 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); void pci_setup_cardbus(struct pci_bus *bus);
extern void pci_sort_breadthfirst(void); extern void pci_sort_breadthfirst(void);
#define dev_is_pci(d) ((d)->bus == &pci_bus_type) #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); int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void); void pci_assign_unassigned_resources(void);
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); 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 *); void pdev_enable_device(struct pci_dev *);
int pci_enable_resources(struct pci_dev *, int mask); int pci_enable_resources(struct pci_dev *, int mask);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), 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); void pcibios_set_master(struct pci_dev *dev);
int pcibios_set_pcie_reset_state(struct pci_dev *dev, int pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state); enum pcie_reset_state state);
int pcibios_add_device(struct pci_dev *dev);
#ifdef CONFIG_PCI_MMCONFIG #ifdef CONFIG_PCI_MMCONFIG
extern void __init pci_mmcfg_early_init(void); 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) { } static inline void pci_mmcfg_late_init(void) { }
#endif #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); 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 void pci_disable_sriov(struct pci_dev *dev);
extern irqreturn_t pci_sriov_migration(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_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 #else
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) 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; 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 #endif
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)

View File

@ -349,7 +349,7 @@
#define PCI_AF_STATUS_TP 0x01 #define PCI_AF_STATUS_TP 0x01
#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */ #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 2 /* Modes & Features */
#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ #define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
@ -389,6 +389,19 @@
#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */ #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 */ #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 */ /* PCI Bridge Subsystem ID registers */
#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */ #define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */
@ -456,6 +469,8 @@
#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
#define PCI_EXP_LNKCTL 16 /* Link Control */ #define PCI_EXP_LNKCTL 16 /* Link Control */
#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM 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_RCB 0x0008 /* Read Completion Boundary */
#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ #define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ #define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
@ -544,9 +559,9 @@
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ #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_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ #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_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */
#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.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_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */