msm: ep_pcie: Prevent repetitive wake operation if wake is in process

Sometimes, device receives two consecutive wake-up events, added into a
workqueue. Then device assert WAKE# and host deassert PERST# if device
in D3cold state, triggering deassert perst IRQ. In IRQ thread, device
flush the workqueue to make sure previous d3cold process has completed
before enable endpoint. commit 43917f862f7d ("msm: mhi_dev: Flush
workqueue before processing PERST deassert"). However, the second wake
event is also in the workqueue, so ep_pcie_core_wakeup_host_internal
is invoked and seeing dev->perst_deast is true, setted by deassert
PERST# IRQ. Then device goes to access MHI register to issue inband PME,
leading to NOC error because endpoint is still disabled.

So add a check to prevent wake operation if a previous wake has completed.

10567.834470: [0x8219195 mhi_sm_dev_event_manager] Handling
MHI_DEV_EVENT_CORE_WAKEUP event, current states: M3 & D3_COLD_STATE
10567.834498: ep_pcie_core_toggle_wake_gpio: PCIe V1711211: No. 115 to
assert PCIe WAKE#; perst is asserted; D3hot is  received, WAKE GPIO
state:0
10567.834507: ep_pcie_core_wakeup_host_internal: PCIe V1711211: Set wake
pending : 1 and return ; perst is not de-asserted; D3hot is set
10567.849704: [0x8219195 mhi_dev_notify_sm_event] received:
MHI_DEV_EVENT_HW_ACC_WAKEUP
10567.849976: ep_pcie_handle_perst_irq: PCIe V1711211: No. 1018 PERST
deassertion
10567.850053: [0x8219195 mhi_sm_dev_event_manager] Handling
MHI_DEV_EVENT_HW_ACC_WAKEUP event, current states: M3 & D3_COLD_STATE
10567.850071: ep_pcie_core_wakeup_host_internal: PCIe V1711211: request to
assert WAKE# when in D3hot
10567.860093: ep_pcie_core_issue_inband_pme: PCIe V1711211: request to
assert inband wake.

Change-Id: I85fb37c4171c5ef4974c573f0abba199cb718a84
Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
This commit is contained in:
Qiang Yu 2023-07-28 09:46:33 +08:00 • committed by Pallavi Singh
commit d62bca7bf4

View file

@ -3236,6 +3236,9 @@ static int ep_pcie_core_wakeup_host_internal(enum ep_pcie_event event)
{
struct ep_pcie_dev_t *dev = &ep_pcie_dev;
if (atomic_read(&dev->host_wake_pending))
return 0;
if (!atomic_read(&dev->perst_deast)) {
/*D3 cold handling*/
ep_pcie_core_toggle_wake_gpio(true);