mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge branch 'pci/misc' into next
* pci/misc: PCI: Read capability list as dwords, not bytes PCI: Don't clear ASPM bits when the FADT declares it's unsupported PCI: Clarify policy for vendor IDs in pci.txt PCI/ACPI: Optimize device state transition delays PCI: Export pci_find_host_bridge() for use inside PCI core PCI: Make a shareable UUID for PCI firmware ACPI _DSM PCI: Fix typo in Thunderbolt kernel message
This commit is contained in:
commit
5468d5a64b
12 changed files with 118 additions and 56 deletions
|
|
@ -16,7 +16,7 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
|
|||
return bus;
|
||||
}
|
||||
|
||||
static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
|
||||
struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_bus *root_bus = find_pci_root_bus(bus);
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
|
|||
void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
|
||||
struct resource *res)
|
||||
{
|
||||
struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
|
||||
struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
|
||||
struct resource_entry *window;
|
||||
resource_size_t offset = 0;
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ static bool region_contains(struct pci_bus_region *region1,
|
|||
void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
|
||||
struct pci_bus_region *region)
|
||||
{
|
||||
struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
|
||||
struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
|
||||
struct resource_entry *window;
|
||||
resource_size_t offset = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,15 @@
|
|||
#include <linux/pm_qos.h>
|
||||
#include "pci.h"
|
||||
|
||||
/*
|
||||
* The UUID is defined in the PCI Firmware Specification available here:
|
||||
* https://www.pcisig.com/members/downloads/pcifw_r3_1_13Dec10.pdf
|
||||
*/
|
||||
const u8 pci_acpi_dsm_uuid[] = {
|
||||
0xd0, 0x37, 0xc9, 0xe5, 0x53, 0x35, 0x7a, 0x4d,
|
||||
0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d
|
||||
};
|
||||
|
||||
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
|
||||
{
|
||||
acpi_status status = AE_NOT_EXIST;
|
||||
|
|
@ -528,11 +537,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
|
|||
|
||||
void acpi_pci_add_bus(struct pci_bus *bus)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
struct pci_host_bridge *bridge;
|
||||
|
||||
if (acpi_pci_disabled || !bus->bridge)
|
||||
return;
|
||||
|
||||
acpi_pci_slot_enumerate(bus);
|
||||
acpiphp_enumerate_slots(bus);
|
||||
|
||||
/*
|
||||
* For a host bridge, check its _DSM for function 8 and if
|
||||
* that is available, mark it in pci_host_bridge.
|
||||
*/
|
||||
if (!pci_is_root_bus(bus))
|
||||
return;
|
||||
|
||||
obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), pci_acpi_dsm_uuid, 3,
|
||||
RESET_DELAY_DSM, NULL);
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 1) {
|
||||
bridge = pci_find_host_bridge(bus);
|
||||
bridge->ignore_reset_delay = 1;
|
||||
}
|
||||
ACPI_FREE(obj);
|
||||
}
|
||||
|
||||
void acpi_pci_remove_bus(struct pci_bus *bus)
|
||||
|
|
@ -558,6 +588,57 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
|
|||
check_children);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI
|
||||
* @pdev: the PCI device whose delay is to be updated
|
||||
* @adev: the companion ACPI device of this PCI device
|
||||
*
|
||||
* Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
|
||||
* control method of either the device itself or the PCI host bridge.
|
||||
*
|
||||
* Function 8, "Reset Delay," applies to the entire hierarchy below a PCI
|
||||
* host bridge. If it returns one, the OS may assume that all devices in
|
||||
* the hierarchy have already completed power-on reset delays.
|
||||
*
|
||||
* Function 9, "Device Readiness Durations," applies only to the object
|
||||
* where it is located. It returns delay durations required after various
|
||||
* events if the device requires less time than the spec requires. Delays
|
||||
* from this function take precedence over the Reset Delay function.
|
||||
*
|
||||
* These _DSM functions are defined by the draft ECN of January 28, 2014,
|
||||
* titled "ACPI additions for FW latency optimizations."
|
||||
*/
|
||||
static void pci_acpi_optimize_delay(struct pci_dev *pdev,
|
||||
acpi_handle handle)
|
||||
{
|
||||
struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
|
||||
int value;
|
||||
union acpi_object *obj, *elements;
|
||||
|
||||
if (bridge->ignore_reset_delay)
|
||||
pdev->d3cold_delay = 0;
|
||||
|
||||
obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
|
||||
FUNCTION_DELAY_DSM, NULL);
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 5) {
|
||||
elements = obj->package.elements;
|
||||
if (elements[0].type == ACPI_TYPE_INTEGER) {
|
||||
value = (int)elements[0].integer.value / 1000;
|
||||
if (value < PCI_PM_D3COLD_WAIT)
|
||||
pdev->d3cold_delay = value;
|
||||
}
|
||||
if (elements[3].type == ACPI_TYPE_INTEGER) {
|
||||
value = (int)elements[3].integer.value / 1000;
|
||||
if (value < PCI_PM_D3_WAIT)
|
||||
pdev->d3_delay = value;
|
||||
}
|
||||
}
|
||||
ACPI_FREE(obj);
|
||||
}
|
||||
|
||||
static void pci_acpi_setup(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
|
|
@ -566,6 +647,8 @@ static void pci_acpi_setup(struct device *dev)
|
|||
if (!adev)
|
||||
return;
|
||||
|
||||
pci_acpi_optimize_delay(pci_dev, adev->handle);
|
||||
|
||||
pci_acpi_add_pm_notifier(adev, pci_dev);
|
||||
if (!adev->wakeup.flags.valid)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
#include <linux/pci-acpi.h>
|
||||
#include "pci.h"
|
||||
|
||||
#define DEVICE_LABEL_DSM 0x07
|
||||
|
||||
#ifdef CONFIG_DMI
|
||||
enum smbios_attr_enum {
|
||||
SMBIOS_ATTR_NONE = 0,
|
||||
|
|
@ -148,11 +146,6 @@ static inline void pci_remove_smbiosname_file(struct pci_dev *pdev)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const char device_label_dsm_uuid[] = {
|
||||
0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
|
||||
0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
|
||||
};
|
||||
|
||||
enum acpi_attr_enum {
|
||||
ACPI_ATTR_LABEL_SHOW,
|
||||
ACPI_ATTR_INDEX_SHOW,
|
||||
|
|
@ -179,7 +172,7 @@ static int dsm_get_label(struct device *dev, char *buf,
|
|||
if (!handle)
|
||||
return -1;
|
||||
|
||||
obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2,
|
||||
obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 0x2,
|
||||
DEVICE_LABEL_DSM, NULL);
|
||||
if (!obj)
|
||||
return -1;
|
||||
|
|
@ -219,7 +212,7 @@ static bool device_has_dsm(struct device *dev)
|
|||
if (!handle)
|
||||
return false;
|
||||
|
||||
return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2,
|
||||
return !!acpi_check_dsm(handle, pci_acpi_dsm_uuid, 0x2,
|
||||
1 << DEVICE_LABEL_DSM);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,19 +146,22 @@ static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
|
|||
u8 pos, int cap, int *ttl)
|
||||
{
|
||||
u8 id;
|
||||
u16 ent;
|
||||
|
||||
pci_bus_read_config_byte(bus, devfn, pos, &pos);
|
||||
|
||||
while ((*ttl)--) {
|
||||
pci_bus_read_config_byte(bus, devfn, pos, &pos);
|
||||
if (pos < 0x40)
|
||||
break;
|
||||
pos &= ~3;
|
||||
pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
|
||||
&id);
|
||||
pci_bus_read_config_word(bus, devfn, pos, &ent);
|
||||
|
||||
id = ent & 0xff;
|
||||
if (id == 0xff)
|
||||
break;
|
||||
if (id == cap)
|
||||
return pos;
|
||||
pos += PCI_CAP_LIST_NEXT;
|
||||
pos = (ent >> 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,4 +321,6 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
|
||||
|
||||
#endif /* DRIVERS_PCI_H */
|
||||
|
|
|
|||
|
|
@ -782,24 +782,6 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_disable_link_state);
|
||||
|
||||
void pcie_clear_aspm(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *child;
|
||||
|
||||
if (aspm_force)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Clear any ASPM setup that the firmware has carried out on this bus
|
||||
*/
|
||||
list_for_each_entry(child, &bus->devices, bus_list) {
|
||||
__pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
|
||||
PCIE_LINK_STATE_L1 |
|
||||
PCIE_LINK_STATE_CLKPM,
|
||||
false, true);
|
||||
}
|
||||
}
|
||||
|
||||
static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -3182,7 +3182,7 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
|
|||
|| nhi->subsystem_vendor != 0x2222
|
||||
|| nhi->subsystem_device != 0x1111)
|
||||
goto out;
|
||||
dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n");
|
||||
dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n");
|
||||
device_pm_wait_for_dev(&dev->dev, &nhi->dev);
|
||||
out:
|
||||
pci_dev_put(nhi);
|
||||
|
|
|
|||
Loading…
Reference in a new issue