160 lines
5.1 KiB
Diff
160 lines
5.1 KiB
Diff
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
|
|
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
|
|
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
|
|
|