[PATCH v2 3/3] HID: Intel-thc-hid: Intel-quickspi: Refine recover callback
From: Even Xu <even.xu@intel.com>
Date: 2026-07-03 07:58:45
Also in:
lkml
Subsystem:
hid core layer, intel touch host controller (thc) driver, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Even Xu, Xinpeng Sun, Linus Torvalds
Refine recover flow: 1. Use workqueue to handle recover flow instead of processing in irq handler. 2. Call thc_rxdma_reset() API to simplify the recover operation. 3. Disable interrupt during whole recover flow. 4. If recover fails, disable interrupt to avoid interrupt storm. Signed-off-by: Even Xu <even.xu@intel.com> --- .../intel-quickspi/pci-quickspi.c | 46 +++++++++---------- .../intel-quickspi/quickspi-dev.h | 3 ++ 2 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
index f669235f1883..bc9eead77562 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c@@ -252,34 +252,28 @@ static irqreturn_t quickspi_irq_quick_handler(int irq, void *dev_id) } /** - * try_recover - Try to recovery THC and Device - * @qsdev: pointer to quickspi device + * try_recover - Recover callback to recover THC + * @work: pointer to work_struct * - * This function is a error handler, called when fatal error happens. - * It try to reset Touch Device and re-configure THC to recovery + * This function is an error handler, called when fatal error happens. + * It try to reset Touch Device and re-configure THC to recover * transferring between Device and THC. - * - * Return: 0 if successful or error code on failed. */ -static int try_recover(struct quickspi_device *qsdev) +static void try_recover(struct work_struct *work) { - int ret; + struct quickspi_device *qsdev = container_of(work, struct quickspi_device, recover_work); - ret = reset_tic(qsdev); - if (ret) { - dev_err(qsdev->dev, "Reset touch device failed, ret = %d\n", ret); - return ret; - } + if (pm_runtime_resume_and_get(qsdev->dev)) + return; - thc_dma_unconfigure(qsdev->thc_hw); + thc_interrupt_enable(qsdev->thc_hw, false); - ret = thc_dma_configure(qsdev->thc_hw); - if (ret) { - dev_err(qsdev->dev, "Re-configure THC DMA failed, ret = %d\n", ret); - return ret; - } + if (thc_rxdma_reset(qsdev->thc_hw)) + qsdev->state = QUICKSPI_DISABLED; + else + thc_interrupt_enable(qsdev->thc_hw, true); - return 0; + pm_runtime_put_autosuspend(qsdev->dev); } /**
@@ -337,11 +331,10 @@ static irqreturn_t quickspi_irq_thread_handler(int irq, void *dev_id) } end: - thc_interrupt_enable(qsdev->thc_hw, true); - if (err_recover) - if (try_recover(qsdev)) - qsdev->state = QUICKSPI_DISABLED; + schedule_work(&qsdev->recover_work); + else + thc_interrupt_enable(qsdev->thc_hw, true); pm_runtime_put_autosuspend(qsdev->dev);
@@ -385,6 +378,7 @@ static struct quickspi_device *quickspi_dev_init(struct pci_dev *pdev, void __io init_waitqueue_head(&qsdev->report_desc_got_wq); init_waitqueue_head(&qsdev->get_report_cmpl_wq); init_waitqueue_head(&qsdev->set_report_cmpl_wq); + INIT_WORK(&qsdev->recover_work, try_recover); /* thc hw init */ qsdev->thc_hw = thc_dev_init(qsdev->dev, qsdev->mem_addr);
@@ -710,6 +704,8 @@ static void quickspi_remove(struct pci_dev *pdev) if (!qsdev) return; + cancel_work_sync(&qsdev->recover_work); + quickspi_hid_remove(qsdev); quickspi_dma_deinit(qsdev);
@@ -737,6 +733,8 @@ static void quickspi_shutdown(struct pci_dev *pdev) if (!qsdev) return; + cancel_work_sync(&qsdev->recover_work); + /* Must stop DMA before reboot to avoid DMA entering into unknown state */ quickspi_dma_deinit(qsdev);
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
index bf5e18f5a5f4..363e589b0bde 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h@@ -8,6 +8,7 @@ #include <linux/hid-over-spi.h> #include <linux/sizes.h> #include <linux/wait.h> +#include <linux/workqueue.h> #include "quickspi-protocol.h"
@@ -173,6 +174,8 @@ struct quickspi_device { wait_queue_head_t set_report_cmpl_wq; bool set_report_cmpl; + + struct work_struct recover_work; }; #endif /* _QUICKSPI_DEV_H_ */
--
2.43.0