Commit 5d7936b8 authored by Kieran Bingham's avatar Kieran Bingham Committed by Mauro Carvalho Chehab

media: vsp1: Convert display lists to use new body pool

Adapt the dl->body0 object to use an object from the body pool. This
greatly reduces the pressure on the TLB for IPMMU use cases, as all of
the lists use a single allocation for the main body.

The CLU and LUT objects pre-allocate a pool containing three bodies,
allowing a userspace update before the hardware has committed a previous
set of tables.

Bodies are no longer 'freed' in interrupt context, but instead released
back to their respective pools. This allows us to remove the garbage
collector in the DLM.
Signed-off-by: default avatarKieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 5de04739
......@@ -19,6 +19,8 @@
#define CLU_MIN_SIZE 4U
#define CLU_MAX_SIZE 8190U
#define CLU_SIZE (17 * 17 * 17)
/* -----------------------------------------------------------------------------
* Device Access
*/
......@@ -43,19 +45,19 @@ static int clu_set_table(struct vsp1_clu *clu, struct v4l2_ctrl *ctrl)
struct vsp1_dl_body *dlb;
unsigned int i;
dlb = vsp1_dl_body_alloc(clu->entity.vsp1, 1 + 17 * 17 * 17);
dlb = vsp1_dl_body_get(clu->pool);
if (!dlb)
return -ENOMEM;
vsp1_dl_body_write(dlb, VI6_CLU_ADDR, 0);
for (i = 0; i < 17 * 17 * 17; ++i)
for (i = 0; i < CLU_SIZE; ++i)
vsp1_dl_body_write(dlb, VI6_CLU_DATA, ctrl->p_new.p_u32[i]);
spin_lock_irq(&clu->lock);
swap(clu->clu, dlb);
spin_unlock_irq(&clu->lock);
vsp1_dl_body_free(dlb);
vsp1_dl_body_put(dlb);
return 0;
}
......@@ -216,8 +218,16 @@ static void clu_configure(struct vsp1_entity *entity,
}
}
static void clu_destroy(struct vsp1_entity *entity)
{
struct vsp1_clu *clu = to_clu(&entity->subdev);
vsp1_dl_body_pool_destroy(clu->pool);
}
static const struct vsp1_entity_operations clu_entity_ops = {
.configure = clu_configure,
.destroy = clu_destroy,
};
/* -----------------------------------------------------------------------------
......@@ -243,6 +253,17 @@ struct vsp1_clu *vsp1_clu_create(struct vsp1_device *vsp1)
if (ret < 0)
return ERR_PTR(ret);
/*
* Pre-allocate a body pool, with 3 bodies allowing a userspace update
* before the hardware has committed a previous set of tables, handling
* both the queued and pending dl entries. One extra entry is added to
* the CLU_SIZE to allow for the VI6_CLU_ADDR header.
*/
clu->pool = vsp1_dl_body_pool_create(clu->entity.vsp1, 3, CLU_SIZE + 1,
0);
if (!clu->pool)
return ERR_PTR(-ENOMEM);
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&clu->ctrls, 2);
v4l2_ctrl_new_custom(&clu->ctrls, &clu_table_control, NULL);
......
......@@ -32,6 +32,7 @@ struct vsp1_clu {
spinlock_t lock;
unsigned int mode;
struct vsp1_dl_body *clu;
struct vsp1_dl_body_pool *pool;
};
static inline struct vsp1_clu *to_clu(struct v4l2_subdev *subdev)
......
This diff is collapsed.
......@@ -41,9 +41,6 @@ void vsp1_dl_body_pool_destroy(struct vsp1_dl_body_pool *pool);
struct vsp1_dl_body *vsp1_dl_body_get(struct vsp1_dl_body_pool *pool);
void vsp1_dl_body_put(struct vsp1_dl_body *dlb);
struct vsp1_dl_body *vsp1_dl_body_alloc(struct vsp1_device *vsp1,
unsigned int num_entries);
void vsp1_dl_body_free(struct vsp1_dl_body *dlb);
void vsp1_dl_body_write(struct vsp1_dl_body *dlb, u32 reg, u32 data);
int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb);
int vsp1_dl_list_add_chain(struct vsp1_dl_list *head, struct vsp1_dl_list *dl);
......
......@@ -19,6 +19,8 @@
#define LUT_MIN_SIZE 4U
#define LUT_MAX_SIZE 8190U
#define LUT_SIZE 256
/* -----------------------------------------------------------------------------
* Device Access
*/
......@@ -40,11 +42,11 @@ static int lut_set_table(struct vsp1_lut *lut, struct v4l2_ctrl *ctrl)
struct vsp1_dl_body *dlb;
unsigned int i;
dlb = vsp1_dl_body_alloc(lut->entity.vsp1, 256);
dlb = vsp1_dl_body_get(lut->pool);
if (!dlb)
return -ENOMEM;
for (i = 0; i < 256; ++i)
for (i = 0; i < LUT_SIZE; ++i)
vsp1_dl_body_write(dlb, VI6_LUT_TABLE + 4 * i,
ctrl->p_new.p_u32[i]);
......@@ -52,7 +54,7 @@ static int lut_set_table(struct vsp1_lut *lut, struct v4l2_ctrl *ctrl)
swap(lut->lut, dlb);
spin_unlock_irq(&lut->lock);
vsp1_dl_body_free(dlb);
vsp1_dl_body_put(dlb);
return 0;
}
......@@ -83,7 +85,7 @@ static const struct v4l2_ctrl_config lut_table_control = {
.max = 0x00ffffff,
.step = 1,
.def = 0,
.dims = { 256},
.dims = { LUT_SIZE },
};
/* -----------------------------------------------------------------------------
......@@ -172,8 +174,16 @@ static void lut_configure(struct vsp1_entity *entity,
}
}
static void lut_destroy(struct vsp1_entity *entity)
{
struct vsp1_lut *lut = to_lut(&entity->subdev);
vsp1_dl_body_pool_destroy(lut->pool);
}
static const struct vsp1_entity_operations lut_entity_ops = {
.configure = lut_configure,
.destroy = lut_destroy,
};
/* -----------------------------------------------------------------------------
......@@ -199,6 +209,15 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
if (ret < 0)
return ERR_PTR(ret);
/*
* Pre-allocate a body pool, with 3 bodies allowing a userspace update
* before the hardware has committed a previous set of tables, handling
* both the queued and pending dl entries.
*/
lut->pool = vsp1_dl_body_pool_create(vsp1, 3, LUT_SIZE, 0);
if (!lut->pool)
return ERR_PTR(-ENOMEM);
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&lut->ctrls, 1);
v4l2_ctrl_new_custom(&lut->ctrls, &lut_table_control, NULL);
......
......@@ -29,6 +29,7 @@ struct vsp1_lut {
spinlock_t lock;
struct vsp1_dl_body *lut;
struct vsp1_dl_body_pool *pool;
};
static inline struct vsp1_lut *to_lut(struct v4l2_subdev *subdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment