RTC class operations run with rtc_device.ops_lock held. The virtio RTC
alarm requests currently wait without a timeout for the device to return
their requestq buffers.

On surprise removal, virtio-pci marks the virtqueues broken before
unregistering the virtio device. If an alarm request is waiting when the
device stops responding, viortc_remove() blocks in viortc_class_stop()
while trying to acquire ops_lock. The request cannot complete and device
removal hangs until the waiting task is signalled.

Use the same 60-second timeout as clock read requests for alarm reads,
alarm programming, and alarm interrupt enable requests. The existing
message reference counting keeps a timed-out request alive until a late
response or device teardown.

Fixes: 9d4f22fd563e ("virtio_rtc: Add RTC class driver")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: GuoHan Zhao <[email protected]>
---
 drivers/virtio/virtio_rtc_driver.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/virtio/virtio_rtc_driver.c 
b/drivers/virtio/virtio_rtc_driver.c
index 4419735b0f0d..74616ba5be11 100644
--- a/drivers/virtio/virtio_rtc_driver.c
+++ b/drivers/virtio/virtio_rtc_driver.c
@@ -574,8 +574,8 @@ static int viortc_msg_xfer(struct viortc_vq *vq, struct 
viortc_msg *msg,
  * read requests
  */
 
-/** timeout for clock readings, where timeouts are considered non-fatal */
-#define VIORTC_MSG_READ_TIMEOUT secs_to_jiffies(60)
+/** timeout for runtime requests, where timeouts are considered non-fatal */
+#define VIORTC_MSG_TIMEOUT secs_to_jiffies(60)
 
 /**
  * viortc_read() - VIRTIO_RTC_REQ_READ wrapper
@@ -600,7 +600,7 @@ int viortc_read(struct viortc_dev *viortc, u16 vio_clk_id, 
u64 *reading)
        VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
 
        ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
-                             VIORTC_MSG_READ_TIMEOUT);
+                             VIORTC_MSG_TIMEOUT);
        if (ret) {
                dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
                        ret);
@@ -642,7 +642,7 @@ int viortc_read_cross(struct viortc_dev *viortc, u16 
vio_clk_id, u8 hw_counter,
        VIORTC_MSG_WRITE(hdl, hw_counter, &hw_counter);
 
        ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
-                             VIORTC_MSG_READ_TIMEOUT);
+                             VIORTC_MSG_TIMEOUT);
        if (ret) {
                dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
                        ret);
@@ -809,7 +809,7 @@ int viortc_read_alarm(struct viortc_dev *viortc, u16 
vio_clk_id,
        VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
 
        ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
-                             0);
+                             VIORTC_MSG_TIMEOUT);
        if (ret) {
                dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
                        ret);
@@ -858,7 +858,7 @@ int viortc_set_alarm(struct viortc_dev *viortc, u16 
vio_clk_id, u64 alarm_time,
        VIORTC_MSG_WRITE(hdl, flags, &flags);
 
        ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
-                             0);
+                             VIORTC_MSG_TIMEOUT);
        if (ret) {
                dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
                        ret);
@@ -900,7 +900,7 @@ int viortc_set_alarm_enabled(struct viortc_dev *viortc, u16 
vio_clk_id,
        VIORTC_MSG_WRITE(hdl, flags, &flags);
 
        ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
-                             0);
+                             VIORTC_MSG_TIMEOUT);
        if (ret) {
                dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
                        ret);

base-commit: 3b029c035b34bbc693405ddf759f0e9b920c27f1
-- 
2.43.0


Reply via email to