mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-18 20:04:16 +08:00
Merge branch 'pci/pm'
- Reduce wait time for secondary bus to be ready to speed up resume (Mika Westerberg) - Avoid putting EloPOS E2/S2/H2 (as well as Elo i2) PCIe Ports in D3cold (Ondrej Zary) - Call _REG when transitioning D-states so AML that uses the PCI config space OpRegion works, which fixes some ASMedia GPIO controllers (Mario Limonciello) * pci/pm: PCI/ACPI: Call _REG when transitioning D-states PCI/ACPI: Validate acpi_pci_set_power_state() parameter PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold PCI/PM: Shorten pci_bridge_wait_for_secondary_bus() wait time for slow links
This commit is contained in:
commit
7e229f0e05
@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void acpi_pci_config_space_access(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
int val = enable ? ACPI_REG_CONNECT : ACPI_REG_DISCONNECT;
|
||||
int ret = acpi_evaluate_reg(ACPI_HANDLE(&dev->dev),
|
||||
ACPI_ADR_SPACE_PCI_CONFIG, val);
|
||||
if (ret)
|
||||
pci_dbg(dev, "ACPI _REG %s evaluation failed (%d)\n",
|
||||
enable ? "connect" : "disconnect", ret);
|
||||
}
|
||||
|
||||
int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
@ -1053,32 +1063,49 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
[PCI_D3hot] = ACPI_STATE_D3_HOT,
|
||||
[PCI_D3cold] = ACPI_STATE_D3_COLD,
|
||||
};
|
||||
int error = -EINVAL;
|
||||
int error;
|
||||
|
||||
/* If the ACPI device has _EJ0, ignore the device */
|
||||
if (!adev || acpi_has_method(adev->handle, "_EJ0"))
|
||||
return -ENODEV;
|
||||
|
||||
switch (state) {
|
||||
case PCI_D3cold:
|
||||
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
|
||||
PM_QOS_FLAGS_ALL) {
|
||||
error = -EBUSY;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case PCI_D0:
|
||||
case PCI_D1:
|
||||
case PCI_D2:
|
||||
case PCI_D3hot:
|
||||
error = acpi_device_set_power(adev, state_conv[state]);
|
||||
case PCI_D3cold:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
pci_dbg(dev, "power state changed by ACPI to %s\n",
|
||||
acpi_power_state_string(adev->power.state));
|
||||
if (state == PCI_D3cold) {
|
||||
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
|
||||
PM_QOS_FLAGS_ALL)
|
||||
return -EBUSY;
|
||||
|
||||
return error;
|
||||
/* Notify AML lack of PCI config space availability */
|
||||
acpi_pci_config_space_access(dev, false);
|
||||
}
|
||||
|
||||
error = acpi_device_set_power(adev, state_conv[state]);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
pci_dbg(dev, "power state changed by ACPI to %s\n",
|
||||
acpi_power_state_string(adev->power.state));
|
||||
|
||||
/*
|
||||
* Notify AML of PCI config space availability. Config space is
|
||||
* accessible in all states except D3cold; the only transitions
|
||||
* that change availability are transitions to D3cold and from
|
||||
* D3cold to D0.
|
||||
*/
|
||||
if (state == PCI_D0)
|
||||
acpi_pci_config_space_access(dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
|
@ -64,6 +64,13 @@ struct pci_pme_device {
|
||||
|
||||
#define PME_TIMEOUT 1000 /* How long between PME checks */
|
||||
|
||||
/*
|
||||
* Following exit from Conventional Reset, devices must be ready within 1 sec
|
||||
* (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional
|
||||
* Reset (PCIe r6.0 sec 5.8).
|
||||
*/
|
||||
#define PCI_RESET_WAIT 1000 /* msec */
|
||||
|
||||
/*
|
||||
* Devices may extend the 1 sec period through Request Retry Status
|
||||
* completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper
|
||||
@ -2968,13 +2975,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = {
|
||||
{
|
||||
/*
|
||||
* Downstream device is not accessible after putting a root port
|
||||
* into D3cold and back into D0 on Elo i2.
|
||||
* into D3cold and back into D0 on Elo Continental Z2 board
|
||||
*/
|
||||
.ident = "Elo i2",
|
||||
.ident = "Elo Continental Z2",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Geminilake"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"),
|
||||
},
|
||||
},
|
||||
#endif
|
||||
@ -5102,11 +5109,9 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
|
||||
*
|
||||
* However, 100 ms is the minimum and the PCIe spec says the
|
||||
* software must allow at least 1s before it can determine that the
|
||||
* device that did not respond is a broken device. There is
|
||||
* evidence that 100 ms is not always enough, for example certain
|
||||
* Titan Ridge xHCI controller does not always respond to
|
||||
* configuration requests if we only wait for 100 ms (see
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=203885).
|
||||
* device that did not respond is a broken device. Also device can
|
||||
* take longer than that to respond if it indicates so through Request
|
||||
* Retry Status completions.
|
||||
*
|
||||
* Therefore we wait for 100 ms and check for the device presence
|
||||
* until the timeout expires.
|
||||
@ -5115,16 +5120,36 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
|
||||
return 0;
|
||||
|
||||
if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
|
||||
u16 status;
|
||||
|
||||
pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
|
||||
msleep(delay);
|
||||
} else {
|
||||
pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
|
||||
delay);
|
||||
if (!pcie_wait_for_link_delay(dev, true, delay)) {
|
||||
/* Did not train, no need to wait any further */
|
||||
pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
|
||||
|
||||
if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the port supports active link reporting we now check
|
||||
* whether the link is active and if not bail out early with
|
||||
* the assumption that the device is not present anymore.
|
||||
*/
|
||||
if (!dev->link_active_reporting)
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status);
|
||||
if (!(status & PCI_EXP_LNKSTA_DLLLA))
|
||||
return -ENOTTY;
|
||||
|
||||
return pci_dev_wait(child, reset_type,
|
||||
PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT);
|
||||
}
|
||||
|
||||
pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
|
||||
delay);
|
||||
if (!pcie_wait_for_link_delay(dev, true, delay)) {
|
||||
/* Did not train, no need to wait any further */
|
||||
pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
return pci_dev_wait(child, reset_type,
|
||||
|
@ -66,13 +66,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
|
||||
#define PCI_PM_D3HOT_WAIT 10 /* msec */
|
||||
#define PCI_PM_D3COLD_WAIT 100 /* msec */
|
||||
|
||||
/*
|
||||
* Following exit from Conventional Reset, devices must be ready within 1 sec
|
||||
* (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional
|
||||
* Reset (PCIe r6.0 sec 5.8).
|
||||
*/
|
||||
#define PCI_RESET_WAIT 1000 /* msec */
|
||||
|
||||
void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
|
||||
void pci_refresh_power_state(struct pci_dev *dev);
|
||||
int pci_power_up(struct pci_dev *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user