clear-pkgs-linux-iot-lts2018/0634-hyper_dmabuf-virtio-Ha...

112 lines
3.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mateusz Polrola <mateuszx.potrola@intel.com>
Date: Fri, 24 Aug 2018 09:25:03 +0200
Subject: [PATCH] hyper_dmabuf/virtio: Handle S3 resume correctly (v2)
After resume from S3 virtqueues are reset, so buffers for communication
from SOS to UOS needs to be reinitialized.
That cannot be done directly in resume routine, as that point virtio PCI
device is not yet fully restored, because of that it has to be scheduled
to run after some short delay.
v2: changes:
- schedule reinit of communication from SOS to UOS immediately at the
end of restore routine
- Wait for virtio device to become ready before actually doing reinit
of communication
Signed-off-by: Mateusz Polrola <mateuszx.potrola@intel.com>
---
.../virtio/hyper_dmabuf_virtio_fe_drv.c | 49 +++++++++++++++++--
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/drivers/dma-buf/hyper_dmabuf/virtio/hyper_dmabuf_virtio_fe_drv.c b/drivers/dma-buf/hyper_dmabuf/virtio/hyper_dmabuf_virtio_fe_drv.c
index 5ef8801eb085..e0c811135699 100644
--- a/drivers/dma-buf/hyper_dmabuf/virtio/hyper_dmabuf_virtio_fe_drv.c
+++ b/drivers/dma-buf/hyper_dmabuf/virtio/hyper_dmabuf_virtio_fe_drv.c
@@ -32,6 +32,7 @@
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include <linux/workqueue.h>
#include "../hyper_dmabuf_msg.h"
#include "../hyper_dmabuf_drv.h"
#include "hyper_dmabuf_virtio_common.h"
@@ -222,14 +223,20 @@ static void virtio_hdma_fe_remove(struct virtio_device *vdev)
virtio_hdma_fe_remove_common(vdev);
}
+struct virtio_hdma_restore_work
+{
+ struct work_struct work;
+ struct virtio_device *dev;
+};
+
/*
* Queues empty requests buffers to backend,
* which will be used by it to send requests back to frontend.
*/
-static void virtio_hdma_fe_scan(struct virtio_device *vdev)
+static void virtio_hdma_query_vmid(struct virtio_device *vdev)
{
- struct virtio_hdma_fe_priv *priv =
- (struct virtio_hdma_fe_priv *) vdev->priv;
+ struct virtio_hdma_fe_priv *priv =
+ (struct virtio_hdma_fe_priv *) vdev->priv;
struct hyper_dmabuf_req *rx_req;
int timeout = 1000;
@@ -266,6 +273,29 @@ static void virtio_hdma_fe_scan(struct virtio_device *vdev)
}
}
+/*
+ * Queues empty requests buffers to backend,
+ * which will be used by it to send requests back to frontend.
+ */
+static void virtio_hdma_fe_scan(struct virtio_device *vdev)
+{
+ virtio_hdma_query_vmid(vdev);
+}
+
+static void virtio_hdma_restore_bh(struct work_struct *w)
+{
+ struct virtio_hdma_restore_work *work =
+ (struct virtio_hdma_restore_work *) w;
+
+ while (!(VIRTIO_CONFIG_S_DRIVER_OK &
+ work->dev->config->get_status(work->dev))) {
+ usleep_range(100, 120);
+ }
+
+ virtio_hdma_query_vmid(work->dev);
+ kfree(w);
+}
+
#ifdef CONFIG_PM_SLEEP
static int virtio_hdma_fe_freeze(struct virtio_device *vdev)
{
@@ -275,7 +305,18 @@ static int virtio_hdma_fe_freeze(struct virtio_device *vdev)
static int virtio_hdma_fe_restore(struct virtio_device *vdev)
{
- return virtio_hdma_fe_probe_common(vdev);
+ struct virtio_hdma_restore_work *work;
+ int ret;
+
+ ret = virtio_hdma_fe_probe_common(vdev);
+ if (!ret) {
+ work = kmalloc(sizeof(*work), GFP_KERNEL);
+ INIT_WORK(&work->work, virtio_hdma_restore_bh);
+ work->dev = vdev;
+ schedule_work(&work->work);
+ }
+
+ return ret;
}
#endif
--
https://clearlinux.org