| From 3f922cd5be091b57d4e7b9758f1f55bf1d46090d Mon Sep 17 00:00:00 2001 |
| From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> |
| Date: Fri, 18 May 2018 16:42:00 -0400 |
| Subject: [PATCH 1198/1795] media: vsp1: Use reference counting for bodies |
| |
| Extend the display list body with a reference count, allowing bodies to |
| be kept as long as a reference is maintained. This provides the ability |
| to keep a cached copy of bodies which will not change, so that they can |
| be re-applied to multiple display lists. |
| |
| Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> |
| Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| (cherry picked from commit 2d9445db0ee9d8695ab3dadb614829b70e43b61f) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/media/platform/vsp1/vsp1_clu.c | 7 ++++++- |
| drivers/media/platform/vsp1/vsp1_dl.c | 16 ++++++++++++++-- |
| drivers/media/platform/vsp1/vsp1_lut.c | 7 ++++++- |
| 3 files changed, 26 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c |
| index 8efa12f5e53f..ea83f1b7d125 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_clu.c |
| +++ b/drivers/media/platform/vsp1/vsp1_clu.c |
| @@ -212,8 +212,13 @@ static void clu_configure(struct vsp1_entity *entity, |
| clu->clu = NULL; |
| spin_unlock_irqrestore(&clu->lock, flags); |
| |
| - if (dlb) |
| + if (dlb) { |
| vsp1_dl_list_add_body(dl, dlb); |
| + |
| + /* Release our local reference. */ |
| + vsp1_dl_body_put(dlb); |
| + } |
| + |
| break; |
| } |
| } |
| diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c |
| index 617c46a03dec..1407c90c6880 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_dl.c |
| +++ b/drivers/media/platform/vsp1/vsp1_dl.c |
| @@ -10,6 +10,7 @@ |
| #include <linux/device.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/gfp.h> |
| +#include <linux/refcount.h> |
| #include <linux/slab.h> |
| #include <linux/workqueue.h> |
| |
| @@ -54,6 +55,8 @@ struct vsp1_dl_body { |
| struct list_head list; |
| struct list_head free; |
| |
| + refcount_t refcnt; |
| + |
| struct vsp1_dl_body_pool *pool; |
| struct vsp1_device *vsp1; |
| |
| @@ -258,6 +261,7 @@ struct vsp1_dl_body *vsp1_dl_body_get(struct vsp1_dl_body_pool *pool) |
| if (!list_empty(&pool->free)) { |
| dlb = list_first_entry(&pool->free, struct vsp1_dl_body, free); |
| list_del(&dlb->free); |
| + refcount_set(&dlb->refcnt, 1); |
| } |
| |
| spin_unlock_irqrestore(&pool->lock, flags); |
| @@ -278,6 +282,9 @@ void vsp1_dl_body_put(struct vsp1_dl_body *dlb) |
| if (!dlb) |
| return; |
| |
| + if (!refcount_dec_and_test(&dlb->refcnt)) |
| + return; |
| + |
| dlb->num_entries = 0; |
| |
| spin_lock_irqsave(&dlb->pool->lock, flags); |
| @@ -463,8 +470,11 @@ void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data) |
| * which bodies are added. |
| * |
| * Adding a body to a display list passes ownership of the body to the list. The |
| - * caller must not touch the body after this call, and must not release it |
| - * explicitly with vsp1_dl_body_put(). |
| + * caller retains its reference to the fragment when adding it to the display |
| + * list, but is not allowed to add new entries to the body. |
| + * |
| + * The reference must be explicitly released by a call to vsp1_dl_body_put() |
| + * when the body isn't needed anymore. |
| * |
| * Additional bodies are only usable for display lists in header mode. |
| * Attempting to add a body to a header-less display list will return an error. |
| @@ -475,6 +485,8 @@ int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) |
| if (dl->dlm->mode != VSP1_DL_MODE_HEADER) |
| return -EINVAL; |
| |
| + refcount_inc(&dlb->refcnt); |
| + |
| list_add_tail(&dlb->list, &dl->bodies); |
| |
| return 0; |
| diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c |
| index 6b358617ce15..b3ea90172439 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_lut.c |
| +++ b/drivers/media/platform/vsp1/vsp1_lut.c |
| @@ -168,8 +168,13 @@ static void lut_configure(struct vsp1_entity *entity, |
| lut->lut = NULL; |
| spin_unlock_irqrestore(&lut->lock, flags); |
| |
| - if (dlb) |
| + if (dlb) { |
| vsp1_dl_list_add_body(dl, dlb); |
| + |
| + /* Release our local reference. */ |
| + vsp1_dl_body_put(dlb); |
| + } |
| + |
| break; |
| } |
| } |
| -- |
| 2.19.0 |
| |