clear-pkgs-linux-iot-lts2018/1095-media-ipu4-ici-Avoid-c...

160 lines
5.1 KiB
Diff
Raw Normal View History

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Yew, Chang Ching" <chang.ching.yew@intel.com>
Date: Sun, 5 May 2019 02:47:41 +0000
Subject: [PATCH] media: ipu4: ici: Avoid create new buf object for double
isys_get_buf
When there's unexpected 2 subsequent calls of ici_isys_get_buf with same
buf pointer, the buf object of 1st get_buf call is stored in putbuf_list and
a new buf object of the 2nd get_buf call will be created and pointing to same buf
This will cause multiple buf object created pointing to same buffer and
causing crash or reboot when free
Change-Id: I2aa3fd03b46d2b2dcbb3b5db85b889820e5945c8
Tracked-On: PKT-2287
Signed-off-by: Yew, Chang Ching <chang.ching.yew@intel.com>
---
.../media/pci/intel/ici/ici-isys-frame-buf.c | 49 +++++++++++++++++--
.../media/pci/intel/ici/ici-isys-frame-buf.h | 6 +++
2 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/drivers/media/pci/intel/ici/ici-isys-frame-buf.c b/drivers/media/pci/intel/ici/ici-isys-frame-buf.c
2020-10-27 02:14:06 +08:00
index 3d2e5c96e184..20efc28c380b 100644
--- a/drivers/media/pci/intel/ici/ici-isys-frame-buf.c
+++ b/drivers/media/pci/intel/ici/ici-isys-frame-buf.c
@@ -69,7 +69,8 @@ static struct ici_frame_buf_wrapper
*ici_frame_buf_lookup(struct ici_isys_frame_buf_list
*buf_list,
struct ici_frame_info
- *user_frame_info)
+ *user_frame_info,
+ ici_frame_buf_list_type *buf_list_type)
{
struct ici_frame_buf_wrapper *buf;
int i;
@@ -93,6 +94,7 @@ static struct ici_frame_buf_wrapper
if (new_plane->mem.userptr ==
cur_plane->mem.userptr) {
spin_unlock_irqrestore(&buf_list->lock, flags);
+ *buf_list_type=ICI_ISYS_GETBUF_LIST;
return buf;
}
break;
@@ -100,6 +102,7 @@ static struct ici_frame_buf_wrapper
if (new_plane->mem.dmafd ==
cur_plane->mem.dmafd) {
spin_unlock_irqrestore(&buf_list->lock, flags);
+ *buf_list_type=ICI_ISYS_GETBUF_LIST;
return buf;
}
break;
@@ -108,7 +111,36 @@ static struct ici_frame_buf_wrapper
}
}
+
+ list_for_each_entry(buf, &buf_list->putbuf_list, node) {
+ for (i = 0; i < user_frame_info->num_planes; i++) {
+ struct ici_frame_plane *new_plane =
+ &user_frame_info->frame_planes[i];
+ struct ici_frame_plane *cur_plane =
+ &buf->frame_info.frame_planes[i];
+
+ switch (mem_type) {
+ case ICI_MEM_USERPTR:
+ if (new_plane->mem.userptr ==
+ cur_plane->mem.userptr) {
+ spin_unlock_irqrestore(&buf_list->lock, flags);
+ *buf_list_type=ICI_ISYS_PUTBUF_LIST;
+ return buf;
+ }
+ break;
+ case ICI_MEM_DMABUF:
+ if (new_plane->mem.dmafd ==
+ cur_plane->mem.dmafd) {
+ spin_unlock_irqrestore(&buf_list->lock, flags);
+ *buf_list_type=ICI_ISYS_PUTBUF_LIST;
+ return buf;
+ }
+ break;
+ }
+ }
+ }
spin_unlock_irqrestore(&buf_list->lock, flags);
+ *buf_list_type=ICI_ISYS_NONE;
return NULL;
}
@@ -472,6 +504,7 @@ int ici_isys_get_buf(struct ici_isys_stream *as,
unsigned i;
struct ici_frame_buf_wrapper *buf;
unsigned long flags = 0;
+ ici_frame_buf_list_type buf_list_type;
struct ici_kframe_plane *kframe_plane;
struct ici_isys_frame_buf_list *buf_list = &as->buf_list;
@@ -487,13 +520,16 @@ int ici_isys_get_buf(struct ici_isys_stream *as,
dev_err(&as->isys->adev->dev, "User length not set\n");
return -EINVAL;
}
- buf = ici_frame_buf_lookup(buf_list, frame_info);
+ buf = ici_frame_buf_lookup(buf_list, frame_info, &buf_list_type);
- if (buf) {
+ if (buf && buf_list_type == ICI_ISYS_GETBUF_LIST ) {
buf->state = ICI_BUF_PREPARED;
return 0;
+ } else if (buf && buf_list_type == ICI_ISYS_PUTBUF_LIST ) {
+ return 0;
}
+
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -559,6 +595,7 @@ int ici_isys_get_buf_virt(struct ici_isys_stream *as,
unsigned i;
unsigned long flags = 0;
struct ici_frame_buf_wrapper *buf;
+ ici_frame_buf_list_type buf_list_type;
struct ici_kframe_plane *kframe_plane;
struct ici_isys_frame_buf_list *buf_list = &as->buf_list;
@@ -574,11 +611,13 @@ int ici_isys_get_buf_virt(struct ici_isys_stream *as,
dev_err(&as->isys->adev->dev, "User length not set\n");
return -EINVAL;
}
- buf = ici_frame_buf_lookup(buf_list, &frame_buf->frame_info);
+ buf = ici_frame_buf_lookup(buf_list, &frame_buf->frame_info, &buf_list_type);
- if (buf) {
+ if (buf && (buf_list_type == ICI_ISYS_GETBUF_LIST) ) {
buf->state = ICI_BUF_PREPARED;
return 0;
+ } else if (buf && buf_list_type == ICI_ISYS_PUTBUF_LIST ) {
+ return 0;
}
pr_debug("%s: creating new buf object\n", __func__);
diff --git a/drivers/media/pci/intel/ici/ici-isys-frame-buf.h b/drivers/media/pci/intel/ici/ici-isys-frame-buf.h
2020-10-27 02:14:06 +08:00
index 5072e925e4ba..013f6dbbf54a 100644
--- a/drivers/media/pci/intel/ici/ici-isys-frame-buf.h
+++ b/drivers/media/pci/intel/ici/ici-isys-frame-buf.h
@@ -52,6 +52,12 @@ typedef enum frame_buf_state_ {
ICI_BUF_DONE,
} frame_buf_state;
+typedef enum ici_frame_buf_list_type_ {
+ ICI_ISYS_GETBUF_LIST,
+ ICI_ISYS_PUTBUF_LIST,
+ ICI_ISYS_NONE,
+} ici_frame_buf_list_type;
+
struct ici_frame_buf_wrapper {
struct ici_kframe_info kframe_info;
struct ici_frame_info frame_info;
--
https://clearlinux.org