mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
HID: intel-ish-ipc: Reset clients state on resume from D3
When ISH resumes from D3, the connection between ishtp clients and firmware is lost. The ish_resume() function schedules resume_work asynchronously to re-initiate the connection and then returns immediately. This can cause a race where the upper-layer ishtp client driver's .resume() may execute before the connection is fully restored, leaving the client in a stale connected state. If the client sends messages during this window, the firmware cannot respond. To avoid this, reset the ishtp clients' state before returning from ish_resume() if ISH is resuming from D3. Signed-off-by: Zhang Lixu <lixu.zhang@intel.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
@@ -147,6 +147,12 @@ static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
|
||||
|
||||
static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
|
||||
{
|
||||
struct ishtp_device *dev = pci_get_drvdata(pdev);
|
||||
u32 fwsts = dev->ops->get_fw_status(dev);
|
||||
|
||||
if (dev->suspend_flag || !IPC_IS_ISH_ILUP(fwsts))
|
||||
return false;
|
||||
|
||||
return !pm_resume_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV;
|
||||
}
|
||||
|
||||
@@ -277,10 +283,8 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ish_resume_device);
|
||||
struct ishtp_device *dev = pci_get_drvdata(pdev);
|
||||
uint32_t fwsts = dev->ops->get_fw_status(dev);
|
||||
|
||||
if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag
|
||||
&& IPC_IS_ISH_ILUP(fwsts)) {
|
||||
if (ish_should_leave_d0i3(pdev)) {
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
disable_irq_wake(pdev->irq);
|
||||
|
||||
@@ -384,6 +388,10 @@ static int __maybe_unused ish_resume(struct device *device)
|
||||
ish_resume_device = device;
|
||||
dev->resume_flag = 1;
|
||||
|
||||
/* If ISH resume from D3, reset ishtp clients before return */
|
||||
if (!ish_should_leave_d0i3(pdev))
|
||||
ishtp_reset_handler(dev);
|
||||
|
||||
queue_work(dev->unbound_wq, &resume_work);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user