Skip to content

Commit bd1b9a8

Browse files
lixuzhaJiri Kosina
authored andcommitted
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>
1 parent 3cbf654 commit bd1b9a8

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

drivers/hid/intel-ish-hid/ipc/pci-ish.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
147147

148148
static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
149149
{
150+
struct ishtp_device *dev = pci_get_drvdata(pdev);
151+
u32 fwsts = dev->ops->get_fw_status(dev);
152+
153+
if (dev->suspend_flag || !IPC_IS_ISH_ILUP(fwsts))
154+
return false;
155+
150156
return !pm_resume_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV;
151157
}
152158

@@ -277,10 +283,8 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work)
277283
{
278284
struct pci_dev *pdev = to_pci_dev(ish_resume_device);
279285
struct ishtp_device *dev = pci_get_drvdata(pdev);
280-
uint32_t fwsts = dev->ops->get_fw_status(dev);
281286

282-
if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag
283-
&& IPC_IS_ISH_ILUP(fwsts)) {
287+
if (ish_should_leave_d0i3(pdev)) {
284288
if (device_may_wakeup(&pdev->dev))
285289
disable_irq_wake(pdev->irq);
286290

@@ -384,6 +388,10 @@ static int __maybe_unused ish_resume(struct device *device)
384388
ish_resume_device = device;
385389
dev->resume_flag = 1;
386390

391+
/* If ISH resume from D3, reset ishtp clients before return */
392+
if (!ish_should_leave_d0i3(pdev))
393+
ishtp_reset_handler(dev);
394+
387395
queue_work(dev->unbound_wq, &resume_work);
388396

389397
return 0;

0 commit comments

Comments
 (0)