aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2020-12-15 10:52:25 +0100
committerRichard Weinberger <richard@nod.at>2021-02-12 21:25:46 +0100
commit1fcf9da389018d0d81509ec6419a3fff14f3ebfd (patch)
treeae3735fa60329e9004074c72e312b2c09e93551a /arch/um
parentum: time-travel: rework interrupt handling in ext mode (diff)
downloadlinux-dev-1fcf9da389018d0d81509ec6419a3fff14f3ebfd.tar.xz
linux-dev-1fcf9da389018d0d81509ec6419a3fff14f3ebfd.zip
um: virtio: allow devices to be configured for wakeup
With all the IRQ machinery being in place, we can allow virtio devices to additionally be configured as wakeup sources, in which case basically any interrupt from them wakes us up. Note that this requires a call FD because the VQs are all disabled. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/virtio_uml.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index bda3ab468938..91ddf74ca888 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -55,6 +55,7 @@ struct virtio_uml_device {
u64 protocol_features;
u8 status;
u8 registered:1;
+ u8 suspended:1;
u8 config_changed_irq:1;
uint64_t vq_irq_vq_map;
@@ -390,7 +391,7 @@ static irqreturn_t vu_req_read_message(struct virtio_uml_device *vu_dev,
msg.msg.header.request);
}
- if (ev)
+ if (ev && !vu_dev->suspended)
time_travel_add_irq_event(ev);
if (msg.msg.header.flags & VHOST_USER_FLAG_NEED_REPLY)
@@ -1135,6 +1136,8 @@ static int virtio_uml_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, vu_dev);
+ device_set_wakeup_capable(&vu_dev->vdev.dev, true);
+
rc = register_virtio_device(&vu_dev->vdev);
if (rc)
put_device(&vu_dev->vdev.dev);
@@ -1308,7 +1311,12 @@ static int virtio_uml_suspend(struct platform_device *pdev, pm_message_t state)
vhost_user_set_vring_enable(vu_dev, vq->index, false);
}
- return 0;
+ if (!device_may_wakeup(&vu_dev->vdev.dev)) {
+ vu_dev->suspended = true;
+ return 0;
+ }
+
+ return irq_set_irq_wake(vu_dev->irq, 1);
}
static int virtio_uml_resume(struct platform_device *pdev)
@@ -1323,7 +1331,12 @@ static int virtio_uml_resume(struct platform_device *pdev)
vhost_user_set_vring_enable(vu_dev, vq->index, true);
}
- return 0;
+ vu_dev->suspended = false;
+
+ if (!device_may_wakeup(&vu_dev->vdev.dev))
+ return 0;
+
+ return irq_set_irq_wake(vu_dev->irq, 0);
}
static struct platform_driver virtio_uml_driver = {