summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXianbin Zhu <xianzhu@codeaurora.org>2019-06-17 20:51:03 +0800
committerXianbin Zhu <xianzhu@codeaurora.org>2019-06-19 14:22:56 +0800
commit291c54b284a48dbaa69a0ddaedc7d05ab41ea59a (patch)
treedb7eb0cf1a199332aa1e02a42b8dbcf1b9dd3705
parentca64572d5459352034107aa68333b9e539c364e4 (diff)
i2c: virtio: reallocate memory for each msg buffer
We'd better reallocate memory for each msg buffer to avoid the memory in stack space be transferred to the backend for the driver of i2c virtualization. Change-Id: I6daa58cf819d4f612ae246b5a685898e28fbeb54 Signed-off-by: Xianbin Zhu <xianzhu@codeaurora.org>
-rw-r--r--drivers/i2c/busses/virtio-i2c.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/i2c/busses/virtio-i2c.c b/drivers/i2c/busses/virtio-i2c.c
index 20d4ff9749cb..674c38aae987 100644
--- a/drivers/i2c/busses/virtio-i2c.c
+++ b/drivers/i2c/busses/virtio-i2c.c
@@ -130,20 +130,28 @@ static int virti2c_transfer_prepare(struct i2c_msg *msg_1,
i2c_req->head.length = msg_1->len;
if (IS_ERR_OR_NULL(msg_2)) {
- i2c_req->head.type = (msg_1->flags & I2C_M_RD) ?
- I2C_VIRTIO_RD : I2C_VIRTIO_WR;
- i2c_req->buf = msg_1->buf;
+ i2c_req->buf = kzalloc(msg_1->len, GFP_KERNEL);
+ if (!i2c_req->buf)
+ return -ENOMEM;
+
+ if (msg_1->flags & I2C_M_RD) {
+ i2c_req->head.type = I2C_VIRTIO_RD;
+ } else {
+ i2c_req->head.type = I2C_VIRTIO_WR;
+ memcpy(i2c_req->buf, msg_1->buf, msg_1->len);
+ }
+
} else {
if (!msg_2->len || IS_ERR_OR_NULL(msg_2->buf))
return -EINVAL;
- i2c_req->head.type = I2C_VIRTIO_RDWR;
- i2c_req->head.total_length = msg_1->len + msg_2->len;
-
i2c_req->buf = kzalloc((msg_1->len + msg_2->len), GFP_KERNEL);
- if (IS_ERR_OR_NULL(i2c_req->buf))
+ if (!i2c_req->buf)
return -ENOMEM;
+ i2c_req->head.type = I2C_VIRTIO_RDWR;
+ i2c_req->head.total_length = msg_1->len + msg_2->len;
+
memcpy(i2c_req->buf, msg_1->buf, msg_1->len);
}
@@ -153,13 +161,12 @@ static int virti2c_transfer_prepare(struct i2c_msg *msg_1,
static void virti2c_transfer_end(struct virtio_i2c_req *req,
struct i2c_msg *msg)
{
- if (req->head.type == I2C_VIRTIO_RDWR) {
+ if (req->head.type == I2C_VIRTIO_RDWR)
memcpy(msg->buf, req->buf + req->head.length, msg->len);
- kfree(req->buf);
- req->buf = NULL;
- }
-
- memset(req, 0, sizeof(struct virtio_i2c_req));
+ else if (req->head.type == I2C_VIRTIO_RD)
+ memcpy(msg->buf, req->buf, msg->len);
+ kfree(req->buf);
+ req->buf = NULL;
}
static int virtio_i2c_master_xfer(struct i2c_adapter *adap,