mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+41
-5
@@ -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",
|
||||
|
||||
+31
-1
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+98
-73
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user