[PATCH v2 1/5] Input: applespi - use unified wait queue with timeouts for drain

From: Shih-Yuan Lee

Date: Mon Jul 20 2026 - 06:21:17 EST


The driver currently maintains a dedicated wait queue 'drain_complete'
specifically to wait for outstanding write requests to complete.
Consolidate this with other wait events by renaming it to 'wait_queue' to
make resource management cleaner.

Furthermore, using wait_event_lock_irq() without a timeout risks blocking
the thread indefinitely during driver unbinding (remove) or PM transition
phases if the hardware fails to respond or interrupts are missed.

Replace wait_event_lock_irq() with wait_event_lock_irq_timeout() in
applespi_drain_writes() and applespi_drain_reads() with a 3-second timeout.
This ensures the driver can gracefully recover and avoid lockups under
unresponsive hardware conditions.

Signed-off-by: Shih-Yuan Lee <fourdollars@xxxxxxxxxx>
---
drivers/input/keyboard/applespi.c | 32 +++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c
index b5ff71cd5a70..64bbeba85ea9 100644
--- a/drivers/input/keyboard/applespi.c
+++ b/drivers/input/keyboard/applespi.c
@@ -417,7 +417,7 @@ struct applespi_data {

bool suspended;
bool drain;
- wait_queue_head_t drain_complete;
+ wait_queue_head_t wait_queue;
bool read_active;
bool write_active;

@@ -677,7 +677,7 @@ static int applespi_setup_spi(struct applespi_data *applespi)
return sts;

spin_lock_init(&applespi->cmd_msg_lock);
- init_waitqueue_head(&applespi->drain_complete);
+ init_waitqueue_head(&applespi->wait_queue);

return 0;
}
@@ -725,7 +725,7 @@ static void applespi_msg_complete(struct applespi_data *applespi,
applespi->write_active = false;

if (applespi->drain && !applespi->write_active)
- wake_up_all(&applespi->drain_complete);
+ wake_up_all(&applespi->wait_queue);

if (is_write_msg) {
applespi->cmd_msg_queued = 0;
@@ -1415,7 +1415,7 @@ static void applespi_got_data(struct applespi_data *applespi)
applespi->read_active = false;
applespi->write_active = false;

- wake_up_all(&applespi->drain_complete);
+ wake_up_all(&applespi->wait_queue);
}

return;
@@ -1793,21 +1793,33 @@ static int applespi_probe(struct spi_device *spi)

static void applespi_drain_writes(struct applespi_data *applespi)
{
- guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&applespi->cmd_msg_lock, flags);

applespi->drain = true;
- wait_event_lock_irq(applespi->drain_complete, !applespi->write_active,
- applespi->cmd_msg_lock);
+ wait_event_lock_irq_timeout(applespi->wait_queue,
+ !applespi->write_active,
+ applespi->cmd_msg_lock,
+ msecs_to_jiffies(3000));
+
+ spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}

static void applespi_drain_reads(struct applespi_data *applespi)
{
- guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&applespi->cmd_msg_lock, flags);

- wait_event_lock_irq(applespi->drain_complete, !applespi->read_active,
- applespi->cmd_msg_lock);
+ wait_event_lock_irq_timeout(applespi->wait_queue,
+ !applespi->read_active,
+ applespi->cmd_msg_lock,
+ msecs_to_jiffies(3000));

applespi->suspended = true;
+
+ spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}

static void applespi_remove(struct spi_device *spi)
--
2.39.5