clear-pkgs-linux-iot-lts2018/1174-rpmb-vritio-FW-fix-rpm...

171 lines
4.1 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tomas Winkler <tomas.winkler@intel.com>
Date: Tue, 17 Sep 2019 01:21:58 +0300
Subject: [PATCH] rpmb: vritio FW: fix rpmb freeze restore code
We should not rip off the whole memory upon pm freeze,
what is needed so to just release virtio queues.
Change-Id: I24df3c760bb746e976e2bdc4fe3fed9bb5854979
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Tracked-On: PKT-2681
---
drivers/char/rpmb/virtio_rpmb.c | 92 +++++++++++++++++++++------------
1 file changed, 59 insertions(+), 33 deletions(-)
diff --git a/drivers/char/rpmb/virtio_rpmb.c b/drivers/char/rpmb/virtio_rpmb.c
index ef3487c98805..0fd81a80c257 100644
--- a/drivers/char/rpmb/virtio_rpmb.c
+++ b/drivers/char/rpmb/virtio_rpmb.c
@@ -57,8 +57,8 @@ static int rpmb_virtio_cmd_seq(struct device *dev, u8 target,
struct virtio_device *vdev = dev_to_virtio(dev);
struct virtio_rpmb_info *vi = vdev->priv;
unsigned int i;
- struct virtio_rpmb_ioc *vio_cmd;
- struct rpmb_ioc_seq_cmd *seq_cmd;
+ struct virtio_rpmb_ioc *vio_cmd = NULL;
+ struct rpmb_ioc_seq_cmd *seq_cmd = NULL;
size_t seq_cmd_sz;
struct scatterlist vio_ioc, vio_seq, frame[3];
struct scatterlist *sgs[5];
@@ -71,6 +71,10 @@ static int rpmb_virtio_cmd_seq(struct device *dev, u8 target,
return -EINVAL;
mutex_lock(&vi->lock);
+ if (IS_ERR(vi->vq)) {
+ ret = PTR_ERR(vi->vq);
+ goto out;
+ }
vio_cmd = kzalloc(sizeof(*vio_cmd), GFP_KERNEL);
seq_cmd_sz = sizeof(*seq_cmd) + sizeof(struct rpmb_ioc_cmd) * ncmds;
@@ -203,41 +207,39 @@ static int rpmb_virtio_dev_init(struct virtio_rpmb_info *vi)
return ret;
}
-static int virtio_rpmb_init(struct virtio_device *vdev)
+static int virtio_rpmb_init_vq(struct virtio_device *vdev)
{
- int ret;
struct virtio_rpmb_info *vi;
- vi = kzalloc(sizeof(*vi), GFP_KERNEL);
+ vi = vdev->priv;
if (!vi)
- return -ENOMEM;
-
- init_waitqueue_head(&vi->have_data);
- mutex_init(&vi->lock);
- vdev->priv = vi;
+ return -EINVAL;
- /* We expect a single virtqueue. */
vi->vq = virtio_find_single_vq(vdev, virtio_rpmb_recv_done, "request");
if (IS_ERR(vi->vq)) {
dev_err(&vdev->dev, "get single vq failed!\n");
- ret = PTR_ERR(vi->vq);
- goto err;
+ return PTR_ERR(vi->vq);
}
+ return 0;
+}
- /* create vrpmb device. */
- ret = rpmb_virtio_dev_init(vi);
- if (ret) {
- dev_err(&vdev->dev, "create vrpmb device failed.\n");
- goto err;
- }
+static int virtio_rpmb_del_vq(struct virtio_device *vdev)
+{
+ struct virtio_rpmb_info *vi;
- dev_info(&vdev->dev, "init done!\n");
+ vi = vdev->priv;
+ if (!vi)
+ return -EINVAL;
- return 0;
+ if (vdev->config->reset)
+ vdev->config->reset(vdev);
-err:
- kfree(vi);
- return ret;
+ if (vdev->config->del_vqs)
+ vdev->config->del_vqs(vdev);
+
+ vi->vq = ERR_PTR(-EAGAIN);
+
+ return 0;
}
static void virtio_rpmb_remove(struct virtio_device *vdev)
@@ -253,30 +255,54 @@ static void virtio_rpmb_remove(struct virtio_device *vdev)
rpmb_dev_unregister(vi->rdev);
- if (vdev->config->reset)
- vdev->config->reset(vdev);
-
- if (vdev->config->del_vqs)
- vdev->config->del_vqs(vdev);
+ virtio_rpmb_del_vq(vdev);
+ vdev->priv = NULL;
kfree(vi);
}
static int virtio_rpmb_probe(struct virtio_device *vdev)
{
- return virtio_rpmb_init(vdev);
+ int ret;
+ struct virtio_rpmb_info *vi;
+
+ vi = kzalloc(sizeof(*vi), GFP_KERNEL);
+ if (!vi)
+ return -ENOMEM;
+
+ init_waitqueue_head(&vi->have_data);
+ mutex_init(&vi->lock);
+ vdev->priv = vi;
+
+ ret = virtio_rpmb_init_vq(vdev);
+ if (ret)
+ goto err;
+
+ /* create vrpmb device. */
+ ret = rpmb_virtio_dev_init(vi);
+ if (ret) {
+ dev_err(&vdev->dev, "create vrpmb device failed.\n");
+ goto err;
+ }
+
+ dev_info(&vdev->dev, "init done!\n");
+
+ return 0;
+err:
+ vdev->priv = NULL;
+ kfree(vi);
+ return ret;
}
#ifdef CONFIG_PM_SLEEP
static int virtio_rpmb_freeze(struct virtio_device *vdev)
{
- virtio_rpmb_remove(vdev);
- return 0;
+ return virtio_rpmb_del_vq(vdev);
}
static int virtio_rpmb_restore(struct virtio_device *vdev)
{
- return virtio_rpmb_init(vdev);
+ return virtio_rpmb_init_vq(vdev);
}
#endif
--
https://clearlinux.org