mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
virtio: rtc: time out alarm requests
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: 9d4f22fd56 ("virtio_rtc: Add RTC class driver")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn>
Reviewed-by: Peter Hilber <peter.hilber@oss.qualcomm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260714024352.71307-1-zhaoguohan@kylinos.cn>
This commit is contained in:
committed by
Michael S. Tsirkin
parent
2de8556576
commit
68e00d9212
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user