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