mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-13 11:51:32 +00:00
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:
commit
193c0d6825
@ -222,3 +222,37 @@ Description:
|
||||
satisfied too. Reading this attribute will show the current
|
||||
value of d3cold_allowed bit. Writing this attribute will set
|
||||
the value of d3cold_allowed bit.
|
||||
|
||||
What: /sys/bus/pci/devices/.../sriov_totalvfs
|
||||
Date: November 2012
|
||||
Contact: Donald Dutile <ddutile@redhat.com>
|
||||
Description:
|
||||
This file appears when a physical PCIe device supports SR-IOV.
|
||||
Userspace applications can read this file to determine the
|
||||
maximum number of Virtual Functions (VFs) a PCIe physical
|
||||
function (PF) can support. Typically, this is the value reported
|
||||
in the PF's SR-IOV extended capability structure's TotalVFs
|
||||
element. Drivers have the ability at probe time to reduce the
|
||||
value read from this file via the pci_sriov_set_totalvfs()
|
||||
function.
|
||||
|
||||
What: /sys/bus/pci/devices/.../sriov_numvfs
|
||||
Date: November 2012
|
||||
Contact: Donald Dutile <ddutile@redhat.com>
|
||||
Description:
|
||||
This file appears when a physical PCIe device supports SR-IOV.
|
||||
Userspace applications can read and write to this file to
|
||||
determine and control the enablement or disablement of Virtual
|
||||
Functions (VFs) on the physical function (PF). A read of this
|
||||
file will return the number of VFs that are enabled on this PF.
|
||||
A number written to this file will enable the specified
|
||||
number of VFs. A userspace application would typically read the
|
||||
file and check that the value is zero, and then write the number
|
||||
of VFs that should be enabled on the PF; the value written
|
||||
should be less than or equal to the value in the sriov_totalvfs
|
||||
file. A userspace application wanting to disable the VFs would
|
||||
write a zero to this file. The core ensures that valid values
|
||||
are written to this file, and returns errors when values are not
|
||||
valid. For example, writing a 2 to this file when sriov_numvfs
|
||||
is not 0 and not 2 already will return an error. Writing a 10
|
||||
when the value of sriov_totalvfs is 8 will return an error.
|
||||
|
@ -2,6 +2,9 @@
|
||||
Copyright (C) 2009 Intel Corporation
|
||||
Yu Zhao <yu.zhao@intel.com>
|
||||
|
||||
Update: November 2012
|
||||
-- sysfs-based SRIOV enable-/disable-ment
|
||||
Donald Dutile <ddutile@redhat.com>
|
||||
|
||||
1. Overview
|
||||
|
||||
@ -24,10 +27,21 @@ real existing PCI device.
|
||||
|
||||
2.1 How can I enable SR-IOV capability
|
||||
|
||||
The device driver (PF driver) will control the enabling and disabling
|
||||
of the capability via API provided by SR-IOV core. If the hardware
|
||||
has SR-IOV capability, loading its PF driver would enable it and all
|
||||
VFs associated with the PF.
|
||||
Multiple methods are available for SR-IOV enablement.
|
||||
In the first method, the device driver (PF driver) will control the
|
||||
enabling and disabling of the capability via API provided by SR-IOV core.
|
||||
If the hardware has SR-IOV capability, loading its PF driver would
|
||||
enable it and all VFs associated with the PF. Some PF drivers require
|
||||
a module parameter to be set to determine the number of VFs to enable.
|
||||
In the second method, a write to the sysfs file sriov_numvfs will
|
||||
enable and disable the VFs associated with a PCIe PF. This method
|
||||
enables per-PF, VF enable/disable values versus the first method,
|
||||
which applies to all PFs of the same device. Additionally, the
|
||||
PCI SRIOV core support ensures that enable/disable operations are
|
||||
valid to reduce duplication in multiple drivers for the same
|
||||
checks, e.g., check numvfs == 0 if enabling VFs, ensure
|
||||
numvfs <= totalvfs.
|
||||
The second method is the recommended method for new/future VF devices.
|
||||
|
||||
2.2 How can I use the Virtual Functions
|
||||
|
||||
@ -40,13 +54,22 @@ requires device driver that is same as a normal PCI device's.
|
||||
3.1 SR-IOV API
|
||||
|
||||
To enable SR-IOV capability:
|
||||
(a) For the first method, in the driver:
|
||||
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
|
||||
'nr_virtfn' is number of VFs to be enabled.
|
||||
(b) For the second method, from sysfs:
|
||||
echo 'nr_virtfn' > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
|
||||
|
||||
To disable SR-IOV capability:
|
||||
(a) For the first method, in the driver:
|
||||
void pci_disable_sriov(struct pci_dev *dev);
|
||||
(b) For the second method, from sysfs:
|
||||
echo 0 > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
|
||||
|
||||
To notify SR-IOV core of Virtual Function Migration:
|
||||
(a) In the driver:
|
||||
irqreturn_t pci_sriov_migration(struct pci_dev *dev);
|
||||
|
||||
3.2 Usage example
|
||||
@ -88,6 +111,22 @@ static void dev_shutdown(struct pci_dev *dev)
|
||||
...
|
||||
}
|
||||
|
||||
static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
{
|
||||
if (numvfs > 0) {
|
||||
...
|
||||
pci_enable_sriov(dev, numvfs);
|
||||
...
|
||||
return numvfs;
|
||||
}
|
||||
if (numvfs == 0) {
|
||||
....
|
||||
pci_disable_sriov(dev);
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_driver dev_driver = {
|
||||
.name = "SR-IOV Physical Function driver",
|
||||
.id_table = dev_id_table,
|
||||
@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
|
||||
.suspend = dev_suspend,
|
||||
.resume = dev_resume,
|
||||
.shutdown = dev_shutdown,
|
||||
.sriov_configure = dev_sriov_configure,
|
||||
};
|
||||
|
@ -370,6 +370,7 @@ config X86_NUMACHIP
|
||||
depends on NUMA
|
||||
depends on SMP
|
||||
depends on X86_X2APIC
|
||||
depends on PCI_MMCONFIG
|
||||
---help---
|
||||
Adds support for Numascale NumaChip large-SMP systems. Needed to
|
||||
enable more than ~168 cores.
|
||||
|
@ -8,6 +8,7 @@
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/desc.h>
|
||||
@ -245,6 +246,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
|
||||
*size = len;
|
||||
}
|
||||
|
||||
static efi_status_t setup_efi_pci(struct boot_params *params)
|
||||
{
|
||||
efi_pci_io_protocol *pci;
|
||||
efi_status_t status;
|
||||
void **pci_handle;
|
||||
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
unsigned long nr_pci, size = 0;
|
||||
int i;
|
||||
struct setup_data *data;
|
||||
|
||||
data = (struct setup_data *)params->hdr.setup_data;
|
||||
|
||||
while (data && data->next)
|
||||
data = (struct setup_data *)data->next;
|
||||
|
||||
status = efi_call_phys5(sys_table->boottime->locate_handle,
|
||||
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &size, pci_handle);
|
||||
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
status = efi_call_phys3(sys_table->boottime->allocate_pool,
|
||||
EFI_LOADER_DATA, size, &pci_handle);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = efi_call_phys5(sys_table->boottime->locate_handle,
|
||||
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &size, pci_handle);
|
||||
}
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
|
||||
nr_pci = size / sizeof(void *);
|
||||
for (i = 0; i < nr_pci; i++) {
|
||||
void *h = pci_handle[i];
|
||||
uint64_t attributes;
|
||||
struct pci_setup_rom *rom;
|
||||
|
||||
status = efi_call_phys3(sys_table->boottime->handle_protocol,
|
||||
h, &pci_proto, &pci);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!pci)
|
||||
continue;
|
||||
|
||||
status = efi_call_phys4(pci->attributes, pci,
|
||||
EfiPciIoAttributeOperationGet, 0,
|
||||
&attributes);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
|
||||
continue;
|
||||
|
||||
if (!pci->romimage || !pci->romsize)
|
||||
continue;
|
||||
|
||||
size = pci->romsize + sizeof(*rom);
|
||||
|
||||
status = efi_call_phys3(sys_table->boottime->allocate_pool,
|
||||
EFI_LOADER_DATA, size, &rom);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
rom->data.type = SETUP_PCI;
|
||||
rom->data.len = size - sizeof(struct setup_data);
|
||||
rom->data.next = 0;
|
||||
rom->pcilen = pci->romsize;
|
||||
|
||||
status = efi_call_phys5(pci->pci.read, pci,
|
||||
EfiPciIoWidthUint16, PCI_VENDOR_ID,
|
||||
1, &(rom->vendor));
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
|
||||
status = efi_call_phys5(pci->pci.read, pci,
|
||||
EfiPciIoWidthUint16, PCI_DEVICE_ID,
|
||||
1, &(rom->devid));
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
|
||||
status = efi_call_phys5(pci->get_location, pci,
|
||||
&(rom->segment), &(rom->bus),
|
||||
&(rom->device), &(rom->function));
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
|
||||
memcpy(rom->romdata, pci->romimage, pci->romsize);
|
||||
|
||||
if (data)
|
||||
data->next = (uint64_t)rom;
|
||||
else
|
||||
params->hdr.setup_data = (uint64_t)rom;
|
||||
|
||||
data = (struct setup_data *)rom;
|
||||
|
||||
continue;
|
||||
free_struct:
|
||||
efi_call_phys1(sys_table->boottime->free_pool, rom);
|
||||
}
|
||||
|
||||
free_handle:
|
||||
efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have Graphics Output Protocol
|
||||
*/
|
||||
@ -1028,6 +1144,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
|
||||
|
||||
setup_graphics(boot_params);
|
||||
|
||||
setup_efi_pci(boot_params);
|
||||
|
||||
status = efi_call_phys3(sys_table->boottime->allocate_pool,
|
||||
EFI_LOADER_DATA, sizeof(*gdt),
|
||||
(void **)&gdt);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define SETUP_NONE 0
|
||||
#define SETUP_E820_EXT 1
|
||||
#define SETUP_DTB 2
|
||||
#define SETUP_PCI 3
|
||||
|
||||
/* extensible setup data list node */
|
||||
struct setup_data {
|
||||
|
19
arch/x86/include/asm/numachip/numachip.h
Normal file
19
arch/x86/include/asm/numachip/numachip.h
Normal 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 */
|
@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct pci_setup_rom {
|
||||
struct setup_data data;
|
||||
uint16_t vendor;
|
||||
uint16_t devid;
|
||||
uint64_t pcilen;
|
||||
unsigned long segment;
|
||||
unsigned long bus;
|
||||
unsigned long device;
|
||||
unsigned long function;
|
||||
uint8_t romdata[0];
|
||||
};
|
||||
|
||||
#endif /* _ASM_X86_PCI_H */
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/numachip/numachip.h>
|
||||
#include <asm/numachip/numachip_csr.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/apic.h>
|
||||
@ -179,6 +180,7 @@ static int __init numachip_system_init(void)
|
||||
return 0;
|
||||
|
||||
x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
|
||||
x86_init.pci.arch_init = pci_numachip_init;
|
||||
|
||||
map_csrs();
|
||||
|
||||
|
@ -143,11 +143,7 @@ int default_check_phys_apicid_present(int phys_apicid)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DEBUG_BOOT_PARAMS
|
||||
struct boot_params __initdata boot_params;
|
||||
#else
|
||||
struct boot_params boot_params;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Machine setup..
|
||||
|
@ -16,6 +16,7 @@ obj-$(CONFIG_STA2X11) += sta2x11-fixup.o
|
||||
obj-$(CONFIG_X86_VISWS) += visws.o
|
||||
|
||||
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
|
||||
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
|
||||
|
||||
obj-$(CONFIG_X86_INTEL_MID) += mrst.o
|
||||
|
||||
|
@ -12,6 +12,7 @@ struct pci_root_info {
|
||||
char name[16];
|
||||
unsigned int res_num;
|
||||
struct resource *res;
|
||||
resource_size_t *res_offset;
|
||||
struct pci_sysdata sd;
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
bool mcfg_added;
|
||||
@ -22,6 +23,7 @@ struct pci_root_info {
|
||||
};
|
||||
|
||||
static bool pci_use_crs = true;
|
||||
static bool pci_ignore_seg = false;
|
||||
|
||||
static int __init set_use_crs(const struct dmi_system_id *id)
|
||||
{
|
||||
@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id pci_use_crs_table[] __initconst = {
|
||||
static int __init set_ignore_seg(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
|
||||
pci_ignore_seg = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id pci_crs_quirks[] __initconst = {
|
||||
/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
|
||||
{
|
||||
.callback = set_use_crs,
|
||||
@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
|
||||
},
|
||||
},
|
||||
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
|
||||
{
|
||||
.callback = set_ignore_seg,
|
||||
.ident = "HP xw9300",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@ -108,7 +127,7 @@ void __init pci_acpi_crs_quirks(void)
|
||||
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
|
||||
pci_use_crs = false;
|
||||
|
||||
dmi_check_system(pci_use_crs_table);
|
||||
dmi_check_system(pci_crs_quirks);
|
||||
|
||||
/*
|
||||
* If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
|
||||
@ -305,6 +324,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
|
||||
res->flags = flags;
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
info->res_offset[info->res_num] = addr.translation_offset;
|
||||
|
||||
if (!pci_use_crs) {
|
||||
dev_printk(KERN_DEBUG, &info->bridge->dev,
|
||||
@ -374,7 +394,8 @@ static void add_resources(struct pci_root_info *info,
|
||||
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
|
||||
res, conflict->name, conflict);
|
||||
else
|
||||
pci_add_resource(resources, res);
|
||||
pci_add_resource_offset(resources, res,
|
||||
info->res_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,6 +403,8 @@ static void free_pci_root_info_res(struct pci_root_info *info)
|
||||
{
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
kfree(info->res_offset);
|
||||
info->res_offset = NULL;
|
||||
info->res_num = 0;
|
||||
}
|
||||
|
||||
@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
||||
return;
|
||||
|
||||
size = sizeof(*info->res) * info->res_num;
|
||||
info->res_num = 0;
|
||||
info->res = kzalloc(size, GFP_KERNEL);
|
||||
if (!info->res)
|
||||
if (!info->res) {
|
||||
info->res_num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(*info->res_offset) * info->res_num;
|
||||
info->res_num = 0;
|
||||
info->res_offset = kzalloc(size, GFP_KERNEL);
|
||||
if (!info->res_offset) {
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
|
||||
info);
|
||||
@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
int pxm;
|
||||
#endif
|
||||
|
||||
if (pci_ignore_seg)
|
||||
domain = 0;
|
||||
|
||||
if (domain && !pci_domains_supported) {
|
||||
printk(KERN_WARNING "pci_bus %04x:%02x: "
|
||||
"ignored (multiple domains not supported)\n",
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/pci_x86.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
|
||||
PCI_PROBE_MMCONF;
|
||||
@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
|
||||
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
|
||||
}
|
||||
|
||||
int pcibios_add_device(struct pci_dev *dev)
|
||||
{
|
||||
struct setup_data *data;
|
||||
struct pci_setup_rom *rom;
|
||||
u64 pa_data;
|
||||
|
||||
pa_data = boot_params.hdr.setup_data;
|
||||
while (pa_data) {
|
||||
data = phys_to_virt(pa_data);
|
||||
|
||||
if (data->type == SETUP_PCI) {
|
||||
rom = (struct pci_setup_rom *)data;
|
||||
|
||||
if ((pci_domain_nr(dev->bus) == rom->segment) &&
|
||||
(dev->bus->number == rom->bus) &&
|
||||
(PCI_SLOT(dev->devfn) == rom->device) &&
|
||||
(PCI_FUNC(dev->devfn) == rom->function) &&
|
||||
(dev->vendor == rom->vendor) &&
|
||||
(dev->device == rom->devid)) {
|
||||
dev->rom = pa_data +
|
||||
offsetof(struct pci_setup_rom, romdata);
|
||||
dev->romlen = rom->pcilen;
|
||||
}
|
||||
}
|
||||
pa_data = data->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
int err;
|
||||
@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pci_ext_cfg_avail(struct pci_dev *dev)
|
||||
int pci_ext_cfg_avail(void)
|
||||
{
|
||||
if (raw_pci_ext_ops)
|
||||
return 1;
|
||||
|
129
arch/x86/pci/numachip.c
Normal file
129
arch/x86/pci/numachip.c
Normal 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;
|
||||
}
|
@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
|
||||
|
||||
device_set_run_wake(&dev->dev, false);
|
||||
pci_acpi_remove_pm_notifier(device);
|
||||
acpi_power_resource_unregister_device(&dev->dev, device->handle);
|
||||
|
||||
if (!dev->subordinate)
|
||||
goto out;
|
||||
|
||||
acpi_pci_irq_del_prt(dev->subordinate);
|
||||
acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
|
||||
|
||||
device->ops.bind = NULL;
|
||||
device->ops.unbind = NULL;
|
||||
@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
struct pci_bus *bus;
|
||||
unsigned char bus;
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev = acpi_get_pci_dev(device->handle);
|
||||
@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
|
||||
return 0;
|
||||
|
||||
pci_acpi_add_pm_notifier(device, dev);
|
||||
acpi_power_resource_register_device(&dev->dev, device->handle);
|
||||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(&dev->dev, true);
|
||||
|
||||
@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
|
||||
goto out;
|
||||
|
||||
if (dev->subordinate)
|
||||
bus = dev->subordinate;
|
||||
bus = dev->subordinate->number;
|
||||
else
|
||||
bus = dev->bus;
|
||||
bus = dev->bus->number;
|
||||
|
||||
acpi_pci_irq_add_prt(device->handle, bus);
|
||||
acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
|
||||
|
||||
out:
|
||||
pci_dev_put(dev);
|
||||
|
@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
|
||||
static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
|
||||
struct acpi_pci_routing_table *prt)
|
||||
{
|
||||
struct acpi_prt_entry *entry;
|
||||
@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
|
||||
* 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
|
||||
* it here.
|
||||
*/
|
||||
entry->id.segment = pci_domain_nr(bus);
|
||||
entry->id.bus = bus->number;
|
||||
entry->id.segment = segment;
|
||||
entry->id.bus = bus;
|
||||
entry->id.device = (prt->address >> 16) & 0xFFFF;
|
||||
entry->pin = prt->pin + 1;
|
||||
|
||||
@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
|
||||
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
|
||||
|
||||
entry = buffer.pointer;
|
||||
while (entry && (entry->length > 0)) {
|
||||
acpi_pci_irq_add_entry(handle, bus, entry);
|
||||
acpi_pci_irq_add_entry(handle, segment, bus, entry);
|
||||
entry = (struct acpi_pci_routing_table *)
|
||||
((unsigned long)entry + entry->length);
|
||||
}
|
||||
@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void acpi_pci_irq_del_prt(struct pci_bus *bus)
|
||||
void acpi_pci_irq_del_prt(int segment, int bus)
|
||||
{
|
||||
struct acpi_prt_entry *entry, *tmp;
|
||||
|
||||
printk(KERN_DEBUG
|
||||
"ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
|
||||
pci_domain_nr(bus), bus->number);
|
||||
segment, bus);
|
||||
spin_lock(&acpi_prt_lock);
|
||||
list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
|
||||
if (pci_domain_nr(bus) == entry->id.segment
|
||||
&& bus->number == entry->id.bus) {
|
||||
if (segment == entry->id.segment && bus == entry->id.bus) {
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
}
|
||||
|
@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
acpi_handle handle;
|
||||
struct acpi_device *child;
|
||||
u32 flags, base_flags;
|
||||
bool is_osc_granted = false;
|
||||
|
||||
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
|
||||
if (!root)
|
||||
@ -501,6 +502,20 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -510,6 +525,60 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
|
||||
acpi_pci_osc_support(root, flags);
|
||||
|
||||
/* Indicate support for various _OSC capabilities. */
|
||||
if (pci_ext_cfg_avail())
|
||||
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.
|
||||
*/
|
||||
@ -518,10 +587,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
list_add_tail(&root->node, &acpi_pci_roots);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
|
||||
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
|
||||
acpi_device_name(device), acpi_device_bid(device),
|
||||
root->segment, &root->secondary);
|
||||
|
||||
/*
|
||||
* Scan the Root Bridge
|
||||
* --------------------
|
||||
@ -547,81 +612,20 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
if (result)
|
||||
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
|
||||
*/
|
||||
list_for_each_entry(child, &device->children, node)
|
||||
acpi_pci_bridge_scan(child);
|
||||
|
||||
/* Indicate support for various _OSC capabilities. */
|
||||
if (pci_ext_cfg_avail(root->bus->self))
|
||||
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(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();
|
||||
}
|
||||
/* ASPM setting */
|
||||
if (is_osc_granted) {
|
||||
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
|
||||
pcie_clear_aspm(root->bus);
|
||||
} else {
|
||||
dev_info(root->bus->bridge,
|
||||
"Unable to request _OSC control "
|
||||
"(_OSC support mask: 0x%02x)\n", flags);
|
||||
pr_info("ACPI _OSC control for PCIe not granted, "
|
||||
"disabling ASPM\n");
|
||||
pcie_no_aspm();
|
||||
}
|
||||
|
||||
pci_acpi_add_bus_pm_notifier(device, root->bus);
|
||||
@ -634,6 +638,8 @@ out_del_root:
|
||||
mutex_lock(&acpi_pci_root_lock);
|
||||
list_del(&root->node);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
|
||||
acpi_pci_irq_del_prt(root->segment, root->secondary.start);
|
||||
end:
|
||||
kfree(root);
|
||||
return result;
|
||||
@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
|
||||
struct acpi_pci_root *root = acpi_driver_data(device);
|
||||
struct acpi_pci_driver *driver;
|
||||
|
||||
if (system_state != SYSTEM_BOOTING)
|
||||
pci_assign_unassigned_bus_resources(root->bus);
|
||||
|
||||
mutex_lock(&acpi_pci_root_lock);
|
||||
list_for_each_entry(driver, &acpi_pci_drivers, node)
|
||||
if (driver->add)
|
||||
driver->add(root);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
|
||||
/* need to after hot-added ioapic is registered */
|
||||
if (system_state != SYSTEM_BOOTING)
|
||||
pci_enable_bridges(root->bus);
|
||||
|
||||
pci_bus_add_devices(root->bus);
|
||||
|
||||
return 0;
|
||||
@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
|
||||
|
||||
static int acpi_pci_root_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
struct acpi_pci_root *root = acpi_driver_data(device);
|
||||
struct acpi_pci_driver *driver;
|
||||
|
||||
pci_stop_root_bus(root->bus);
|
||||
|
||||
mutex_lock(&acpi_pci_root_lock);
|
||||
list_for_each_entry(driver, &acpi_pci_drivers, node)
|
||||
list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
|
||||
if (driver->remove)
|
||||
driver->remove(root);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
|
||||
device_set_run_wake(root->bus->bridge, false);
|
||||
pci_acpi_remove_bus_pm_notifier(device);
|
||||
|
||||
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
|
||||
if (ACPI_SUCCESS(status))
|
||||
acpi_pci_irq_del_prt(root->segment, root->secondary.start);
|
||||
|
||||
pci_remove_root_bus(root->bus);
|
||||
|
||||
mutex_lock(&acpi_pci_root_lock);
|
||||
list_del(&root->node);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
kfree(root);
|
||||
|
@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap)
|
||||
G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
|
||||
log2_width = fls(adap->params.pci.width) - 1;
|
||||
acklat = ack_lat[log2_width][pldsize];
|
||||
if (val & 1) /* check LOsEnable */
|
||||
if (val & PCI_EXP_LNKCTL_ASPM_L0S) /* check LOsEnable */
|
||||
acklat += fst_trn_tx * 4;
|
||||
rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
|
||||
|
||||
|
@ -114,23 +114,23 @@ static void ath_pci_aspm_init(struct ath_common *common)
|
||||
|
||||
if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
|
||||
(AR_SREV_9285(ah))) {
|
||||
/* Bluetooth coexistance requires disabling ASPM. */
|
||||
/* Bluetooth coexistence requires disabling ASPM. */
|
||||
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
|
||||
PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
|
||||
PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
|
||||
|
||||
/*
|
||||
* Both upstream and downstream PCIe components should
|
||||
* have the same ASPM settings.
|
||||
*/
|
||||
pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
|
||||
PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
|
||||
PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
|
||||
|
||||
ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
|
||||
if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
|
||||
if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
|
||||
ah->aspm_enabled = true;
|
||||
/* Initialize PCIe PM and SERDES registers. */
|
||||
ath9k_hw_configpcipowersave(ah, false);
|
||||
|
@ -917,10 +917,6 @@ struct il4965_scd_bc_tbl {
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
|
||||
/* PCI register values */
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
|
||||
|
||||
#define IL4965_DEFAULT_TX_RETRY 15
|
||||
|
||||
/* EEPROM */
|
||||
|
@ -1183,9 +1183,10 @@ EXPORT_SYMBOL(il_power_update_mode);
|
||||
void
|
||||
il_power_initialize(struct il_priv *il)
|
||||
{
|
||||
u16 lctl = il_pcie_link_ctl(il);
|
||||
u16 lctl;
|
||||
|
||||
il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
|
||||
pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
|
||||
il->power_data.pci_pm = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
|
||||
|
||||
il->power_data.debug_sleep_level_override = -1;
|
||||
|
||||
@ -4233,9 +4234,8 @@ il_apm_init(struct il_priv *il)
|
||||
* power savings, even without L1.
|
||||
*/
|
||||
if (il->cfg->set_l0s) {
|
||||
lctl = il_pcie_link_ctl(il);
|
||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
|
||||
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
|
||||
pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
|
||||
if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
|
||||
/* L1-ASPM enabled; disable(!) L0S */
|
||||
il_set_bit(il, CSR_GIO_REG,
|
||||
CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
|
@ -1829,14 +1829,6 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
|
||||
* PCI *
|
||||
*****************************************************/
|
||||
|
||||
static inline u16
|
||||
il_pcie_link_ctl(struct il_priv *il)
|
||||
{
|
||||
u16 pci_lnk_ctl;
|
||||
pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl);
|
||||
return pci_lnk_ctl;
|
||||
}
|
||||
|
||||
void il_bg_watchdog(unsigned long data);
|
||||
u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval);
|
||||
__le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
|
||||
@ -2434,10 +2426,6 @@ struct il_tfd {
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
|
||||
/* PCI register values */
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
|
||||
|
||||
struct il_rate_info {
|
||||
u8 plcp; /* uCode API: RATE_6M_PLCP, etc. */
|
||||
u8 plcp_siso; /* uCode API: RATE_SISO_6M_PLCP, etc. */
|
||||
|
@ -94,8 +94,6 @@ static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
|
||||
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
|
||||
#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
|
||||
|
||||
static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
{
|
||||
@ -111,9 +109,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
* power savings, even without L1.
|
||||
*/
|
||||
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
|
||||
|
||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
|
||||
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
|
||||
if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
|
||||
/* L1-ASPM enabled; disable(!) L0S */
|
||||
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
|
||||
@ -122,7 +118,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
|
||||
}
|
||||
trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
|
||||
trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
|
||||
int retval;
|
||||
|
||||
pci_fixup_device(pci_fixup_final, dev);
|
||||
|
||||
retval = pcibios_add_device(dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = device_add(&dev->dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
|
||||
|
||||
module_init(ioapic_init);
|
||||
module_exit(ioapic_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
|
||||
virtfn->resource[i].name = pci_name(virtfn);
|
||||
virtfn->resource[i].flags = res->flags;
|
||||
size = resource_size(res);
|
||||
do_div(size, iov->total);
|
||||
do_div(size, iov->total_VFs);
|
||||
virtfn->resource[i].start = res->start + size * id;
|
||||
virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
|
||||
rc = request_resource(res, &virtfn->resource[i]);
|
||||
@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
|
||||
u16 status;
|
||||
struct pci_sriov *iov = dev->sriov;
|
||||
|
||||
if (!iov->nr_virtfn)
|
||||
if (!iov->num_VFs)
|
||||
return 0;
|
||||
|
||||
if (!(iov->cap & PCI_SRIOV_CAP_VFM))
|
||||
@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
|
||||
u16 status;
|
||||
struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
|
||||
|
||||
for (i = iov->initial; i < iov->nr_virtfn; i++) {
|
||||
for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
|
||||
state = readb(iov->mstate + i);
|
||||
if (state == PCI_SRIOV_VFM_MI) {
|
||||
writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
|
||||
@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
|
||||
resource_size_t pa;
|
||||
struct pci_sriov *iov = dev->sriov;
|
||||
|
||||
if (nr_virtfn <= iov->initial)
|
||||
if (nr_virtfn <= iov->initial_VFs)
|
||||
return 0;
|
||||
|
||||
pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
|
||||
@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
|
||||
if (!nr_virtfn)
|
||||
return 0;
|
||||
|
||||
if (iov->nr_virtfn)
|
||||
if (iov->num_VFs)
|
||||
return -EINVAL;
|
||||
|
||||
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
|
||||
if (initial > iov->total ||
|
||||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
|
||||
if (initial > iov->total_VFs ||
|
||||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
|
||||
return -EIO;
|
||||
|
||||
if (nr_virtfn < 0 || nr_virtfn > iov->total ||
|
||||
if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
|
||||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
|
||||
return -EINVAL;
|
||||
|
||||
@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
|
||||
msleep(100);
|
||||
pci_cfg_access_unlock(dev);
|
||||
|
||||
iov->initial = initial;
|
||||
iov->initial_VFs = initial;
|
||||
if (nr_virtfn < initial)
|
||||
initial = nr_virtfn;
|
||||
|
||||
@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
|
||||
}
|
||||
|
||||
kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
|
||||
iov->nr_virtfn = nr_virtfn;
|
||||
iov->num_VFs = nr_virtfn;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
|
||||
int i;
|
||||
struct pci_sriov *iov = dev->sriov;
|
||||
|
||||
if (!iov->nr_virtfn)
|
||||
if (!iov->num_VFs)
|
||||
return;
|
||||
|
||||
if (iov->cap & PCI_SRIOV_CAP_VFM)
|
||||
sriov_disable_migration(dev);
|
||||
|
||||
for (i = 0; i < iov->nr_virtfn; i++)
|
||||
for (i = 0; i < iov->num_VFs; i++)
|
||||
virtfn_remove(dev, i, 0);
|
||||
|
||||
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
|
||||
@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev)
|
||||
if (iov->link != dev->devfn)
|
||||
sysfs_remove_link(&dev->dev.kobj, "dep_link");
|
||||
|
||||
iov->nr_virtfn = 0;
|
||||
iov->num_VFs = 0;
|
||||
}
|
||||
|
||||
static int sriov_init(struct pci_dev *dev, int pos)
|
||||
@ -496,7 +496,7 @@ found:
|
||||
iov->pos = pos;
|
||||
iov->nres = nres;
|
||||
iov->ctrl = ctrl;
|
||||
iov->total = total;
|
||||
iov->total_VFs = total;
|
||||
iov->offset = offset;
|
||||
iov->stride = stride;
|
||||
iov->pgsz = pgsz;
|
||||
@ -529,7 +529,7 @@ failed:
|
||||
|
||||
static void sriov_release(struct pci_dev *dev)
|
||||
{
|
||||
BUG_ON(dev->sriov->nr_virtfn);
|
||||
BUG_ON(dev->sriov->num_VFs);
|
||||
|
||||
if (dev != dev->sriov->dev)
|
||||
pci_dev_put(dev->sriov->dev);
|
||||
@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev)
|
||||
pci_update_resource(dev, i);
|
||||
|
||||
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
|
||||
if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
|
||||
msleep(100);
|
||||
@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (!dev->is_physfn)
|
||||
continue;
|
||||
busnr = virtfn_bus(dev, dev->sriov->total - 1);
|
||||
busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
|
||||
if (busnr > max)
|
||||
max = busnr;
|
||||
}
|
||||
@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
|
||||
*/
|
||||
int pci_num_vf(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev || !dev->is_physfn)
|
||||
if (!dev->is_physfn)
|
||||
return 0;
|
||||
else
|
||||
return dev->sriov->nr_virtfn;
|
||||
|
||||
return dev->sriov->num_VFs;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_num_vf);
|
||||
|
||||
/**
|
||||
* pci_sriov_set_totalvfs -- reduce the TotalVFs available
|
||||
* @dev: the PCI PF device
|
||||
* numvfs: number that should be used for TotalVFs supported
|
||||
*
|
||||
* Should be called from PF driver's probe routine with
|
||||
* device's mutex held.
|
||||
*
|
||||
* Returns 0 if PF is an SRIOV-capable device and
|
||||
* value of numvfs valid. If not a PF with VFS, return -EINVAL;
|
||||
* if VFs already enabled, return -EBUSY.
|
||||
*/
|
||||
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
|
||||
{
|
||||
if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
|
||||
return -EINVAL;
|
||||
|
||||
/* Shouldn't change if VFs already enabled */
|
||||
if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
|
||||
return -EBUSY;
|
||||
else
|
||||
dev->sriov->driver_max_VFs = numvfs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
|
||||
|
||||
/**
|
||||
* pci_sriov_get_totalvfs -- get total VFs supported on this devic3
|
||||
* @dev: the PCI PF device
|
||||
*
|
||||
* For a PCIe device with SRIOV support, return the PCIe
|
||||
* SRIOV capability value of TotalVFs or the value of driver_max_VFs
|
||||
* if the driver reduced it. Otherwise, -EINVAL.
|
||||
*/
|
||||
int pci_sriov_get_totalvfs(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev->is_physfn)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->sriov->driver_max_VFs)
|
||||
return dev->sriov->driver_max_VFs;
|
||||
|
||||
return dev->sriov->total_VFs;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
|
||||
|
@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
|
||||
{
|
||||
struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
|
||||
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
|
||||
dev_name(&parent->dev), parent->vendor, parent->device);
|
||||
dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
|
||||
dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
|
||||
dev_name(&parent->dev), parent->vendor, parent->device);
|
||||
dev_err(&pdev->dev, "%s\n", reason);
|
||||
dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
|
@ -248,31 +248,26 @@ struct drv_dev_and_id {
|
||||
static long local_pci_probe(void *_ddi)
|
||||
{
|
||||
struct drv_dev_and_id *ddi = _ddi;
|
||||
struct device *dev = &ddi->dev->dev;
|
||||
struct device *parent = dev->parent;
|
||||
struct pci_dev *pci_dev = ddi->dev;
|
||||
struct pci_driver *pci_drv = ddi->drv;
|
||||
struct device *dev = &pci_dev->dev;
|
||||
int rc;
|
||||
|
||||
/* The parent bridge must be in active state when probing */
|
||||
if (parent)
|
||||
pm_runtime_get_sync(parent);
|
||||
/* Unbound PCI devices are always set to disabled and suspended.
|
||||
* During probe, the device is set to enabled and active and the
|
||||
* usage count is incremented. If the driver supports runtime PM,
|
||||
* it should call pm_runtime_put_noidle() in its probe routine and
|
||||
* pm_runtime_get_noresume() in its remove routine.
|
||||
/*
|
||||
* Unbound PCI devices are always put in D0, regardless of
|
||||
* runtime PM status. During probe, the device is set to
|
||||
* active and the usage count is incremented. If the driver
|
||||
* supports runtime PM, it should call pm_runtime_put_noidle()
|
||||
* in its probe routine and pm_runtime_get_noresume() in its
|
||||
* remove routine.
|
||||
*/
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
rc = ddi->drv->probe(ddi->dev, ddi->id);
|
||||
pm_runtime_get_sync(dev);
|
||||
pci_dev->driver = pci_drv;
|
||||
rc = pci_drv->probe(pci_dev, ddi->id);
|
||||
if (rc) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
pci_dev->driver = NULL;
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
if (parent)
|
||||
pm_runtime_put(parent);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -322,10 +317,8 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
|
||||
id = pci_match_device(drv, pci_dev);
|
||||
if (id)
|
||||
error = pci_call_probe(drv, pci_dev, id);
|
||||
if (error >= 0) {
|
||||
pci_dev->driver = drv;
|
||||
if (error >= 0)
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
|
||||
}
|
||||
|
||||
/* Undo the runtime PM settings in local_pci_probe() */
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
/*
|
||||
* If the device is still on, set the power state as "unknown",
|
||||
@ -986,6 +977,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
pci_power_t prev = pci_dev->current_state;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* If pci_dev->driver is not set (unbound), the device should
|
||||
* always remain in D0 regardless of the runtime PM status
|
||||
*/
|
||||
if (!pci_dev->driver)
|
||||
return 0;
|
||||
|
||||
if (!pm || !pm->runtime_suspend)
|
||||
return -ENOSYS;
|
||||
|
||||
@ -1007,10 +1005,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pci_dev->state_saved)
|
||||
if (!pci_dev->state_saved) {
|
||||
pci_save_state(pci_dev);
|
||||
|
||||
pci_finish_runtime_suspend(pci_dev);
|
||||
pci_finish_runtime_suspend(pci_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1021,6 +1019,13 @@ static int pci_pm_runtime_resume(struct device *dev)
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
|
||||
/*
|
||||
* If pci_dev->driver is not set (unbound), the device should
|
||||
* always remain in D0 regardless of the runtime PM status
|
||||
*/
|
||||
if (!pci_dev->driver)
|
||||
return 0;
|
||||
|
||||
if (!pm || !pm->runtime_resume)
|
||||
return -ENOSYS;
|
||||
|
||||
@ -1038,8 +1043,16 @@ static int pci_pm_runtime_resume(struct device *dev)
|
||||
|
||||
static int pci_pm_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
|
||||
/*
|
||||
* If pci_dev->driver is not set (unbound), the device should
|
||||
* always remain in D0 regardless of the runtime PM status
|
||||
*/
|
||||
if (!pci_dev->driver)
|
||||
goto out;
|
||||
|
||||
if (!pm)
|
||||
return -ENOSYS;
|
||||
|
||||
@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
out:
|
||||
pm_runtime_suspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
|
||||
|
||||
static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
|
||||
dev_info(&dev->dev, "claimed by stub\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -401,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static ssize_t sriov_totalvfs_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
|
||||
}
|
||||
|
||||
|
||||
static ssize_t sriov_numvfs_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
|
||||
}
|
||||
|
||||
/*
|
||||
* num_vfs > 0; number of vfs to enable
|
||||
* num_vfs = 0; disable all vfs
|
||||
*
|
||||
* Note: SRIOV spec doesn't allow partial VF
|
||||
* disable, so its all or none.
|
||||
*/
|
||||
static ssize_t sriov_numvfs_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int num_vfs_enabled = 0;
|
||||
int num_vfs;
|
||||
int ret = 0;
|
||||
u16 total;
|
||||
|
||||
if (kstrtoint(buf, 0, &num_vfs) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* is PF driver loaded w/callback */
|
||||
if (!pdev->driver || !pdev->driver->sriov_configure) {
|
||||
dev_info(&pdev->dev,
|
||||
"Driver doesn't support SRIOV configuration via sysfs\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* if enabling vf's ... */
|
||||
total = pci_sriov_get_totalvfs(pdev);
|
||||
/* Requested VFs to enable < totalvfs and none enabled already */
|
||||
if ((num_vfs > 0) && (num_vfs <= total)) {
|
||||
if (pdev->sriov->num_VFs == 0) {
|
||||
num_vfs_enabled =
|
||||
pdev->driver->sriov_configure(pdev, num_vfs);
|
||||
if ((num_vfs_enabled >= 0) &&
|
||||
(num_vfs_enabled != num_vfs)) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Only %d VFs enabled\n",
|
||||
num_vfs_enabled);
|
||||
return count;
|
||||
} else if (num_vfs_enabled < 0)
|
||||
/* error code from driver callback */
|
||||
return num_vfs_enabled;
|
||||
} else if (num_vfs == pdev->sriov->num_VFs) {
|
||||
dev_warn(&pdev->dev,
|
||||
"%d VFs already enabled; no enable action taken\n",
|
||||
num_vfs);
|
||||
return count;
|
||||
} else {
|
||||
dev_warn(&pdev->dev,
|
||||
"%d VFs already enabled. Disable before enabling %d VFs\n",
|
||||
pdev->sriov->num_VFs, num_vfs);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* disable vfs */
|
||||
if (num_vfs == 0) {
|
||||
if (pdev->sriov->num_VFs != 0) {
|
||||
ret = pdev->driver->sriov_configure(pdev, 0);
|
||||
return ret ? ret : count;
|
||||
} else {
|
||||
dev_warn(&pdev->dev,
|
||||
"All VFs disabled; no disable action taken\n");
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err(&pdev->dev,
|
||||
"Invalid value for number of VFs to enable: %d\n", num_vfs);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
|
||||
static struct device_attribute sriov_numvfs_attr =
|
||||
__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
|
||||
sriov_numvfs_show, sriov_numvfs_store);
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
||||
struct device_attribute pci_dev_attrs[] = {
|
||||
__ATTR_RO(resource),
|
||||
__ATTR_RO(vendor),
|
||||
@ -1262,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
|
||||
pdev->rom_attr = attr;
|
||||
}
|
||||
|
||||
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
|
||||
retval = device_create_file(&pdev->dev, &vga_attr);
|
||||
if (retval)
|
||||
goto err_rom_file;
|
||||
}
|
||||
|
||||
/* add platform-specific attributes */
|
||||
retval = pcibios_add_platform_entries(pdev);
|
||||
if (retval)
|
||||
goto err_vga_file;
|
||||
goto err_rom_file;
|
||||
|
||||
/* add sysfs entries for various capabilities */
|
||||
retval = pci_create_capabilities_sysfs(pdev);
|
||||
if (retval)
|
||||
goto err_vga_file;
|
||||
goto err_rom_file;
|
||||
|
||||
pci_create_firmware_label_files(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_vga_file:
|
||||
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
device_remove_file(&pdev->dev, &vga_attr);
|
||||
err_rom_file:
|
||||
if (rom_size) {
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
|
||||
@ -1370,3 +1461,62 @@ static int __init pci_sysfs_init(void)
|
||||
}
|
||||
|
||||
late_initcall(pci_sysfs_init);
|
||||
|
||||
static struct attribute *pci_dev_dev_attrs[] = {
|
||||
&vga_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (a == &vga_attr.attr)
|
||||
if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static struct attribute *sriov_dev_attrs[] = {
|
||||
&sriov_totalvfs_attr.attr,
|
||||
&sriov_numvfs_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t sriov_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
|
||||
if (!dev_is_pf(dev))
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
static struct attribute_group sriov_dev_attr_group = {
|
||||
.attrs = sriov_dev_attrs,
|
||||
.is_visible = sriov_attrs_are_visible,
|
||||
};
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
||||
static struct attribute_group pci_dev_attr_group = {
|
||||
.attrs = pci_dev_dev_attrs,
|
||||
.is_visible = pci_dev_attrs_are_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *pci_dev_attr_groups[] = {
|
||||
&pci_dev_attr_group,
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
&sriov_dev_attr_group,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct device_type pci_dev_type = {
|
||||
.groups = pci_dev_attr_groups,
|
||||
};
|
||||
|
@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
|
||||
dr->pinned = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pcibios_add_device - provide arch specific hooks when adding device dev
|
||||
* @dev: the PCI device being added
|
||||
*
|
||||
* Permits the platform to provide architecture specific functionality when
|
||||
* devices are added. This is the default implementation. Architecture
|
||||
* implementations can override this.
|
||||
*/
|
||||
int __weak pcibios_add_device (struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcibios_disable_device - disable arch specific PCI resources for device dev
|
||||
* @dev: the PCI device to disable
|
||||
@ -1578,15 +1591,25 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
|
||||
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
|
||||
/* PCI (as opposed to PCIe) PME requires that the device have
|
||||
its PME# line hooked up correctly. Not all hardware vendors
|
||||
do this, so the PME never gets delivered and the device
|
||||
remains asleep. The easiest way around this is to
|
||||
periodically walk the list of suspended devices and check
|
||||
whether any have their PME flag set. The assumption is that
|
||||
we'll wake up often enough anyway that this won't be a huge
|
||||
hit, and the power savings from the devices will still be a
|
||||
win. */
|
||||
/*
|
||||
* PCI (as opposed to PCIe) PME requires that the device have
|
||||
* its PME# line hooked up correctly. Not all hardware vendors
|
||||
* do this, so the PME never gets delivered and the device
|
||||
* remains asleep. The easiest way around this is to
|
||||
* periodically walk the list of suspended devices and check
|
||||
* whether any have their PME flag set. The assumption is that
|
||||
* we'll wake up often enough anyway that this won't be a huge
|
||||
* hit, and the power savings from the devices will still be a
|
||||
* win.
|
||||
*
|
||||
* Although PCIe uses in-band PME message instead of PME# line
|
||||
* to report PME, PME does not work for some PCIe devices in
|
||||
* reality. For example, there are devices that set their PME
|
||||
* status bits, but don't really bother to send a PME message;
|
||||
* there are PCI Express Root Ports that don't bother to
|
||||
* trigger interrupts when they receive PME messages from the
|
||||
* devices below. So PME poll is used for PCIe devices too.
|
||||
*/
|
||||
|
||||
if (dev->pme_poll) {
|
||||
struct pci_pme_device *pme_dev;
|
||||
@ -1900,6 +1923,8 @@ void pci_pm_init(struct pci_dev *dev)
|
||||
u16 pmc;
|
||||
|
||||
pm_runtime_forbid(&dev->dev);
|
||||
pm_runtime_set_active(&dev->dev);
|
||||
pm_runtime_enable(&dev->dev);
|
||||
device_enable_async_suspend(&dev->dev);
|
||||
dev->wakeup_prepared = false;
|
||||
|
||||
@ -3865,14 +3890,13 @@ static void pci_no_domains(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_ext_cfg_enabled - can we access extended PCI config space?
|
||||
* @dev: The PCI device of the root bridge.
|
||||
* pci_ext_cfg_avail - can we access extended PCI config space?
|
||||
*
|
||||
* Returns 1 if we can access PCI extended config space (offsets
|
||||
* greater than 0xff). This is the default implementation. Architecture
|
||||
* implementations can override this.
|
||||
*/
|
||||
int __weak pci_ext_cfg_avail(struct pci_dev *dev)
|
||||
int __weak pci_ext_cfg_avail(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -158,6 +158,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
|
||||
}
|
||||
extern struct device_attribute pci_dev_attrs[];
|
||||
extern struct device_attribute pcibus_dev_attrs[];
|
||||
extern struct device_type pci_dev_type;
|
||||
extern struct bus_attribute pci_bus_attrs[];
|
||||
|
||||
|
||||
@ -229,13 +230,14 @@ struct pci_sriov {
|
||||
int nres; /* number of resources */
|
||||
u32 cap; /* SR-IOV Capabilities */
|
||||
u16 ctrl; /* SR-IOV Control */
|
||||
u16 total; /* total VFs associated with the PF */
|
||||
u16 initial; /* initial VFs associated with the PF */
|
||||
u16 nr_virtfn; /* number of VFs available */
|
||||
u16 total_VFs; /* total VFs associated with the PF */
|
||||
u16 initial_VFs; /* initial VFs associated with the PF */
|
||||
u16 num_VFs; /* number of VFs available */
|
||||
u16 offset; /* first VF Routing ID offset */
|
||||
u16 stride; /* following VF stride */
|
||||
u32 pgsz; /* page size for BAR alignment */
|
||||
u8 link; /* Function Dependency Link */
|
||||
u16 driver_max_VFs; /* max num VFs driver supports */
|
||||
struct pci_dev *dev; /* lowest numbered PF */
|
||||
struct pci_dev *self; /* this PF */
|
||||
struct mutex lock; /* lock for VF bus */
|
||||
|
@ -87,6 +87,9 @@ struct aer_broadcast_data {
|
||||
static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
|
||||
enum pci_ers_result new)
|
||||
{
|
||||
if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
|
||||
return PCI_ERS_RESULT_NO_AER_DRIVER;
|
||||
|
||||
if (new == PCI_ERS_RESULT_NONE)
|
||||
return orig;
|
||||
|
||||
@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
|
||||
break;
|
||||
case PCI_ERS_RESULT_DISCONNECT:
|
||||
if (new == PCI_ERS_RESULT_NEED_RESET)
|
||||
orig = new;
|
||||
orig = PCI_ERS_RESULT_NEED_RESET;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
|
||||
dev->driver ?
|
||||
"no AER-aware driver" : "no driver");
|
||||
}
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If there's any device in the subtree that does not
|
||||
* have an error_detected callback, returning
|
||||
* PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of
|
||||
* the subsequent mmio_enabled/slot_reset/resume
|
||||
* callbacks of "any" device in the subtree. All the
|
||||
* devices in the subtree are left in the error state
|
||||
* without recovery.
|
||||
*/
|
||||
|
||||
if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
|
||||
vote = PCI_ERS_RESULT_NO_AER_DRIVER;
|
||||
else
|
||||
vote = PCI_ERS_RESULT_NONE;
|
||||
} else {
|
||||
err_handler = dev->driver->err_handler;
|
||||
vote = err_handler->error_detected(dev, result_data->state);
|
||||
}
|
||||
|
||||
err_handler = dev->driver->err_handler;
|
||||
vote = err_handler->error_detected(dev, result_data->state);
|
||||
result_data->result = merge_result(result_data->result, vote);
|
||||
out:
|
||||
device_unlock(&dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
|
||||
return;
|
||||
|
||||
/* Training failed. Restore common clock configurations */
|
||||
dev_printk(KERN_ERR, &parent->dev,
|
||||
"ASPM: Could not configure common clock\n");
|
||||
dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
|
||||
list_for_each_entry(child, &linkbus->devices, bus_list)
|
||||
pcie_capability_write_word(child, PCI_EXP_LNKCTL,
|
||||
child_reg[PCI_FUNC(child->devfn)]);
|
||||
@ -427,7 +426,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
|
||||
|
||||
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
|
||||
{
|
||||
pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val);
|
||||
pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
|
||||
PCI_EXP_LNKCTL_ASPMC, val);
|
||||
}
|
||||
|
||||
static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
|
||||
@ -442,12 +442,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
|
||||
return;
|
||||
/* Convert ASPM state to upstream/downstream ASPM register state */
|
||||
if (state & ASPM_STATE_L0S_UP)
|
||||
dwstream |= PCIE_LINK_STATE_L0S;
|
||||
dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
|
||||
if (state & ASPM_STATE_L0S_DW)
|
||||
upstream |= PCIE_LINK_STATE_L0S;
|
||||
upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
|
||||
if (state & ASPM_STATE_L1) {
|
||||
upstream |= PCIE_LINK_STATE_L1;
|
||||
dwstream |= PCIE_LINK_STATE_L1;
|
||||
upstream |= PCI_EXP_LNKCTL_ASPM_L1;
|
||||
dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
|
||||
}
|
||||
/*
|
||||
* Spec 2.0 suggests all functions should be configured the
|
||||
@ -507,9 +507,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
|
||||
*/
|
||||
pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32);
|
||||
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
|
||||
dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
|
||||
" on pre-1.1 PCIe device. You can enable it"
|
||||
" with 'pcie_aspm=force'\n");
|
||||
dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -120,8 +120,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
|
||||
* the value in this field indicates which MSI-X Table entry is
|
||||
* used to generate the interrupt message."
|
||||
*/
|
||||
pos = pci_pcie_cap(dev);
|
||||
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16);
|
||||
pcie_capability_read_word(dev, PCI_EXP_FLAGS, ®16);
|
||||
entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
|
||||
if (entry >= nr_entries)
|
||||
goto Error;
|
||||
|
@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = {
|
||||
|
||||
void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
|
||||
{
|
||||
bus->cur_bus_speed = pcie_link_speed[linksta & 0xf];
|
||||
bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
|
||||
|
||||
@ -579,14 +579,16 @@ static void pci_set_bus_speed(struct pci_bus *bus)
|
||||
if (pos) {
|
||||
u16 status;
|
||||
enum pci_bus_speed max;
|
||||
pci_read_config_word(bridge, pos + 2, &status);
|
||||
|
||||
if (status & 0x8000) {
|
||||
pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS,
|
||||
&status);
|
||||
|
||||
if (status & PCI_X_SSTATUS_533MHZ) {
|
||||
max = PCI_SPEED_133MHz_PCIX_533;
|
||||
} else if (status & 0x4000) {
|
||||
} else if (status & PCI_X_SSTATUS_266MHZ) {
|
||||
max = PCI_SPEED_133MHz_PCIX_266;
|
||||
} else if (status & 0x0002) {
|
||||
if (((status >> 12) & 0x3) == 2) {
|
||||
} else if (status & PCI_X_SSTATUS_133MHZ) {
|
||||
if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
|
||||
max = PCI_SPEED_133MHz_PCIX_ECC;
|
||||
} else {
|
||||
max = PCI_SPEED_133MHz_PCIX;
|
||||
@ -596,7 +598,8 @@ static void pci_set_bus_speed(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
bus->max_bus_speed = max;
|
||||
bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf];
|
||||
bus->cur_bus_speed = pcix_bus_speed[
|
||||
(status & PCI_X_SSTATUS_FREQ) >> 6];
|
||||
|
||||
return;
|
||||
}
|
||||
@ -607,7 +610,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
|
||||
u16 linksta;
|
||||
|
||||
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
|
||||
bus->max_bus_speed = pcie_link_speed[linkcap & 0xf];
|
||||
bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
|
||||
|
||||
pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
|
||||
pcie_update_link_speed(bus, linksta);
|
||||
@ -975,6 +978,7 @@ int pci_setup_device(struct pci_dev *dev)
|
||||
dev->sysdata = dev->bus->sysdata;
|
||||
dev->dev.parent = dev->bus->bridge;
|
||||
dev->dev.bus = &pci_bus_type;
|
||||
dev->dev.type = &pci_dev_type;
|
||||
dev->hdr_type = hdr_type & 0x7f;
|
||||
dev->multifunction = !!(hdr_type & 0x80);
|
||||
dev->error_state = pci_channel_io_normal;
|
||||
@ -1889,6 +1893,28 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_rescan_bus - scan a PCI bus for devices.
|
||||
* @bus: PCI bus to scan
|
||||
*
|
||||
* Scan a PCI bus and child buses for new devices, adds them,
|
||||
* and enables them.
|
||||
*
|
||||
* Returns the max number of subordinate bus discovered.
|
||||
*/
|
||||
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
|
||||
{
|
||||
unsigned int max;
|
||||
|
||||
max = pci_scan_child_bus(bus);
|
||||
pci_assign_unassigned_bus_resources(bus);
|
||||
pci_enable_bridges(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
|
||||
return max;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_rescan_bus);
|
||||
|
||||
EXPORT_SYMBOL(pci_add_new_bus);
|
||||
EXPORT_SYMBOL(pci_scan_slot);
|
||||
EXPORT_SYMBOL(pci_scan_bridge);
|
||||
|
@ -1790,6 +1790,45 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
|
||||
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
|
||||
quirk_tc86c001_ide);
|
||||
|
||||
/*
|
||||
* PLX PCI 9050 PCI Target bridge controller has an errata that prevents the
|
||||
* local configuration registers accessible via BAR0 (memory) or BAR1 (i/o)
|
||||
* being read correctly if bit 7 of the base address is set.
|
||||
* The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128).
|
||||
* Re-allocate the regions to a 256-byte boundary if necessary.
|
||||
*/
|
||||
static void quirk_plx_pci9050(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int bar;
|
||||
|
||||
/* Fixed in revision 2 (PCI 9052). */
|
||||
if (dev->revision >= 2)
|
||||
return;
|
||||
for (bar = 0; bar <= 1; bar++)
|
||||
if (pci_resource_len(dev, bar) == 0x80 &&
|
||||
(pci_resource_start(dev, bar) & 0x80)) {
|
||||
struct resource *r = &dev->resource[bar];
|
||||
dev_info(&dev->dev,
|
||||
"Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
|
||||
bar);
|
||||
r->start = 0;
|
||||
r->end = 0xff;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
||||
quirk_plx_pci9050);
|
||||
/*
|
||||
* The following Meilhaus (vendor ID 0x1402) device IDs (amongst others)
|
||||
* may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b,
|
||||
* 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c,
|
||||
* 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b.
|
||||
*
|
||||
* Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq"
|
||||
* driver.
|
||||
*/
|
||||
DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050);
|
||||
DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050);
|
||||
|
||||
static void quirk_netmos(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
|
||||
|
@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
|
||||
pci_remove_bus_device(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
|
||||
|
||||
void pci_stop_root_bus(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *child, *tmp;
|
||||
struct pci_host_bridge *host_bridge;
|
||||
|
||||
if (!pci_is_root_bus(bus))
|
||||
return;
|
||||
|
||||
host_bridge = to_pci_host_bridge(bus->bridge);
|
||||
list_for_each_entry_safe_reverse(child, tmp,
|
||||
&bus->devices, bus_list)
|
||||
pci_stop_bus_device(child);
|
||||
|
||||
/* stop the host bridge */
|
||||
device_del(&host_bridge->dev);
|
||||
}
|
||||
|
||||
void pci_remove_root_bus(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *child, *tmp;
|
||||
struct pci_host_bridge *host_bridge;
|
||||
|
||||
if (!pci_is_root_bus(bus))
|
||||
return;
|
||||
|
||||
host_bridge = to_pci_host_bridge(bus->bridge);
|
||||
list_for_each_entry_safe(child, tmp,
|
||||
&bus->devices, bus_list)
|
||||
pci_remove_bus_device(child);
|
||||
pci_remove_bus(bus);
|
||||
host_bridge->bus = NULL;
|
||||
|
||||
/* remove the host bridge */
|
||||
put_device(&host_bridge->dev);
|
||||
}
|
||||
|
@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
|
||||
loff_t start;
|
||||
void __iomem *rom;
|
||||
|
||||
/*
|
||||
* Some devices may provide ROMs via a source other than the BAR
|
||||
*/
|
||||
if (pdev->rom && pdev->romlen) {
|
||||
*size = pdev->romlen;
|
||||
return phys_to_virt(pdev->rom);
|
||||
/*
|
||||
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
|
||||
* memory map if the VGA enable bit of the Bridge Control register is
|
||||
* set for embedded VGA.
|
||||
*/
|
||||
if (res->flags & IORESOURCE_ROM_SHADOW) {
|
||||
} else if (res->flags & IORESOURCE_ROM_SHADOW) {
|
||||
/* primary video rom always starts here */
|
||||
start = (loff_t)0xC0000;
|
||||
*size = 0x20000; /* cover C000:0 through E000:0 */
|
||||
@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
|
||||
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
|
||||
return;
|
||||
|
||||
iounmap(rom);
|
||||
if (!pdev->rom || !pdev->romlen)
|
||||
iounmap(rom);
|
||||
|
||||
/* Disable again before continuing, leave enabled if pci=rom */
|
||||
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
|
||||
|
@ -1550,25 +1550,12 @@ enable_all:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
/**
|
||||
* pci_rescan_bus - scan a PCI bus for devices.
|
||||
* @bus: PCI bus to scan
|
||||
*
|
||||
* Scan a PCI bus and child buses for new devices, adds them,
|
||||
* and enables them.
|
||||
*
|
||||
* Returns the max number of subordinate bus discovered.
|
||||
*/
|
||||
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
|
||||
void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
|
||||
{
|
||||
unsigned int max;
|
||||
struct pci_dev *dev;
|
||||
LIST_HEAD(add_list); /* list of resources that
|
||||
want additional resources */
|
||||
|
||||
max = pci_scan_child_bus(bus);
|
||||
|
||||
down_read(&pci_bus_sem);
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
|
||||
up_read(&pci_bus_sem);
|
||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||
BUG_ON(!list_empty(&add_list));
|
||||
|
||||
pci_enable_bridges(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
|
||||
return max;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_rescan_bus);
|
||||
#endif
|
||||
|
@ -1068,13 +1068,16 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
|
||||
case XenbusStateInitialising:
|
||||
case XenbusStateInitWait:
|
||||
case XenbusStateInitialised:
|
||||
case XenbusStateClosed:
|
||||
break;
|
||||
|
||||
case XenbusStateConnected:
|
||||
pcifront_try_connect(pdev);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
if (xdev->state == XenbusStateClosed)
|
||||
break;
|
||||
/* Missed the backend's CLOSING state -- fallthrough */
|
||||
case XenbusStateClosing:
|
||||
dev_warn(&xdev->dev, "backend going away!\n");
|
||||
pcifront_try_disconnect(pdev);
|
||||
|
@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle);
|
||||
|
||||
/* ACPI PCI Interrupt Routing (pci_irq.c) */
|
||||
|
||||
int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus);
|
||||
void acpi_pci_irq_del_prt(struct pci_bus *bus);
|
||||
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
|
||||
void acpi_pci_irq_del_prt(int segment, int bus);
|
||||
|
||||
/* ACPI PCI Device Binding (pci_bind.c) */
|
||||
|
||||
|
@ -196,6 +196,77 @@ typedef struct {
|
||||
void *create_event_ex;
|
||||
} efi_boot_services_t;
|
||||
|
||||
typedef enum {
|
||||
EfiPciIoWidthUint8,
|
||||
EfiPciIoWidthUint16,
|
||||
EfiPciIoWidthUint32,
|
||||
EfiPciIoWidthUint64,
|
||||
EfiPciIoWidthFifoUint8,
|
||||
EfiPciIoWidthFifoUint16,
|
||||
EfiPciIoWidthFifoUint32,
|
||||
EfiPciIoWidthFifoUint64,
|
||||
EfiPciIoWidthFillUint8,
|
||||
EfiPciIoWidthFillUint16,
|
||||
EfiPciIoWidthFillUint32,
|
||||
EfiPciIoWidthFillUint64,
|
||||
EfiPciIoWidthMaximum
|
||||
} EFI_PCI_IO_PROTOCOL_WIDTH;
|
||||
|
||||
typedef enum {
|
||||
EfiPciIoAttributeOperationGet,
|
||||
EfiPciIoAttributeOperationSet,
|
||||
EfiPciIoAttributeOperationEnable,
|
||||
EfiPciIoAttributeOperationDisable,
|
||||
EfiPciIoAttributeOperationSupported,
|
||||
EfiPciIoAttributeOperationMaximum
|
||||
} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *read;
|
||||
void *write;
|
||||
} efi_pci_io_protocol_access_t;
|
||||
|
||||
typedef struct {
|
||||
void *poll_mem;
|
||||
void *poll_io;
|
||||
efi_pci_io_protocol_access_t mem;
|
||||
efi_pci_io_protocol_access_t io;
|
||||
efi_pci_io_protocol_access_t pci;
|
||||
void *copy_mem;
|
||||
void *map;
|
||||
void *unmap;
|
||||
void *allocate_buffer;
|
||||
void *free_buffer;
|
||||
void *flush;
|
||||
void *get_location;
|
||||
void *attributes;
|
||||
void *get_bar_attributes;
|
||||
void *set_bar_attributes;
|
||||
uint64_t romsize;
|
||||
void *romimage;
|
||||
} efi_pci_io_protocol;
|
||||
|
||||
#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
|
||||
#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
|
||||
#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
|
||||
#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
|
||||
#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
|
||||
#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
|
||||
#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
|
||||
#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
|
||||
#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
|
||||
#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
|
||||
#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
|
||||
#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
|
||||
#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
|
||||
#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
|
||||
|
||||
/*
|
||||
* Types and defines for EFI ResetSystem
|
||||
*/
|
||||
|
@ -333,6 +333,8 @@ struct pci_dev {
|
||||
};
|
||||
struct pci_ats *ats; /* Address Translation Service */
|
||||
#endif
|
||||
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
|
||||
size_t romlen; /* Length of ROM if it's not from the BAR */
|
||||
};
|
||||
|
||||
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
|
||||
@ -538,6 +540,9 @@ enum pci_ers_result {
|
||||
|
||||
/* Device driver is fully recovered and operational */
|
||||
PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5,
|
||||
|
||||
/* No AER capabilities registered for the driver */
|
||||
PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
|
||||
};
|
||||
|
||||
/* PCI bus error event callbacks */
|
||||
@ -573,6 +578,7 @@ struct pci_driver {
|
||||
int (*resume_early) (struct pci_dev *dev);
|
||||
int (*resume) (struct pci_dev *dev); /* Device woken up */
|
||||
void (*shutdown) (struct pci_dev *dev);
|
||||
int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */
|
||||
const struct pci_error_handlers *err_handler;
|
||||
struct device_driver driver;
|
||||
struct pci_dynids dynids;
|
||||
@ -726,6 +732,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
|
||||
extern void pci_dev_put(struct pci_dev *dev);
|
||||
extern void pci_remove_bus(struct pci_bus *b);
|
||||
extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
|
||||
void pci_stop_root_bus(struct pci_bus *bus);
|
||||
void pci_remove_root_bus(struct pci_bus *bus);
|
||||
void pci_setup_cardbus(struct pci_bus *bus);
|
||||
extern void pci_sort_breadthfirst(void);
|
||||
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
|
||||
@ -970,6 +978,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
|
||||
int pci_claim_resource(struct pci_dev *, int);
|
||||
void pci_assign_unassigned_resources(void);
|
||||
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
|
||||
void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
|
||||
void pdev_enable_device(struct pci_dev *);
|
||||
int pci_enable_resources(struct pci_dev *, int mask);
|
||||
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
|
||||
@ -1604,6 +1613,7 @@ void pcibios_disable_device(struct pci_dev *dev);
|
||||
void pcibios_set_master(struct pci_dev *dev);
|
||||
int pcibios_set_pcie_reset_state(struct pci_dev *dev,
|
||||
enum pcie_reset_state state);
|
||||
int pcibios_add_device(struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
extern void __init pci_mmcfg_early_init(void);
|
||||
@ -1613,7 +1623,7 @@ static inline void pci_mmcfg_early_init(void) { }
|
||||
static inline void pci_mmcfg_late_init(void) { }
|
||||
#endif
|
||||
|
||||
int pci_ext_cfg_avail(struct pci_dev *dev);
|
||||
int pci_ext_cfg_avail(void);
|
||||
|
||||
void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
|
||||
|
||||
@ -1622,6 +1632,8 @@ extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
|
||||
extern void pci_disable_sriov(struct pci_dev *dev);
|
||||
extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
|
||||
extern int pci_num_vf(struct pci_dev *dev);
|
||||
extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
|
||||
extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
|
||||
#else
|
||||
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
|
||||
{
|
||||
@ -1638,6 +1650,14 @@ static inline int pci_num_vf(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
|
||||
|
@ -349,7 +349,7 @@
|
||||
#define PCI_AF_STATUS_TP 0x01
|
||||
#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */
|
||||
|
||||
/* PCI-X registers */
|
||||
/* PCI-X registers (Type 0 (non-bridge) devices) */
|
||||
|
||||
#define PCI_X_CMD 2 /* Modes & Features */
|
||||
#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
|
||||
@ -389,6 +389,19 @@
|
||||
#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */
|
||||
#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */
|
||||
|
||||
/* PCI-X registers (Type 1 (bridge) devices) */
|
||||
|
||||
#define PCI_X_BRIDGE_SSTATUS 2 /* Secondary Status */
|
||||
#define PCI_X_SSTATUS_64BIT 0x0001 /* Secondary AD interface is 64 bits */
|
||||
#define PCI_X_SSTATUS_133MHZ 0x0002 /* 133 MHz capable */
|
||||
#define PCI_X_SSTATUS_FREQ 0x03c0 /* Secondary Bus Mode and Frequency */
|
||||
#define PCI_X_SSTATUS_VERS 0x3000 /* PCI-X Capability Version */
|
||||
#define PCI_X_SSTATUS_V1 0x1000 /* Mode 2, not Mode 1 */
|
||||
#define PCI_X_SSTATUS_V2 0x2000 /* Mode 1 or Modes 1 and 2 */
|
||||
#define PCI_X_SSTATUS_266MHZ 0x4000 /* 266 MHz capable */
|
||||
#define PCI_X_SSTATUS_533MHZ 0x8000 /* 533 MHz capable */
|
||||
#define PCI_X_BRIDGE_STATUS 4 /* Bridge Status */
|
||||
|
||||
/* PCI Bridge Subsystem ID registers */
|
||||
|
||||
#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */
|
||||
@ -456,6 +469,8 @@
|
||||
#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
|
||||
#define PCI_EXP_LNKCTL 16 /* Link Control */
|
||||
#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */
|
||||
#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */
|
||||
#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */
|
||||
#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
|
||||
#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
|
||||
#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
|
||||
@ -544,9 +559,9 @@
|
||||
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
|
||||
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
|
||||
#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */
|
||||
#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */
|
||||
#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
|
||||
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
|
||||
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
|
||||
|
Loading…
Reference in New Issue
Block a user