summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-04-07 08:41:25 +0100
committerAndy Green <andy.green@linaro.org>2011-04-07 08:41:25 +0100
commit23da91cf9817b567bfbf4125ed1189751c09e3f3 (patch)
treee490c0f073fcb49bbcf39b9a0b50f9081313513c /drivers
parentad30a7c4f0b692183c9ea0970e5457ab0a64fc87 (diff)
TILER: Fixed ioctl handling issues.
Added support for NV12 packing decision based on whether container is shared between 8 and 16-bit modes. Fixed mutex handling of QBLK. Simplified mutex handling of QBUF, URBUF. Added support for looking up block info by key & id. RBUF now fills out block info for each mapped block. Signed-off-by: Lajos Molnar <molnar@ti.com> Signed-off-by: David Sin <davidsin@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/tiler/_tiler.h38
-rw-r--r--drivers/media/video/tiler/tiler-iface.c96
-rw-r--r--drivers/media/video/tiler/tiler-main.c8
3 files changed, 77 insertions, 65 deletions
diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h
index 2dd0903d939..149f3002730 100644
--- a/drivers/media/video/tiler/_tiler.h
+++ b/drivers/media/video/tiler/_tiler.h
@@ -59,27 +59,37 @@ struct tiler_ops {
s32 (*map) (enum tiler_fmt fmt, u32 width, u32 height,
u32 key, u32 gid, struct process_info *pi,
struct mem_info **info, u32 usr_addr);
+ void (*reserve_nv12) (u32 n, u32 width, u32 height, u32 align, u32 offs,
+ u32 gid, struct process_info *pi, bool can_together);
+ void (*reserve) (u32 n, enum tiler_fmt fmt, u32 width, u32 height,
+ u32 align, u32 offs, u32 gid, struct process_info *pi);
+ void (*unreserve) (u32 gid, struct process_info *pi);
+ /* block access operations */
struct mem_info * (*lock) (u32 key, u32 id, struct gid_info *gi);
- void (*unlock_free) (struct mem_info *mi, bool free);
-
- struct mem_info * (*get_by_ssptr) (u32 sys_addr);
+ struct mem_info * (*lock_by_ssptr) (u32 sys_addr);
void (*describe) (struct mem_info *i, struct tiler_block_info *blk);
+ void (*unlock_free) (struct mem_info *mi, bool free);
- void (*add_reserved) (struct list_head *reserved, struct gid_info *gi);
- void (*release) (struct list_head *reserved);
-
+ s32 (*lay_2d) (enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band,
+ u16 align, u16 offs, struct gid_info *gi,
+ struct list_head *pos);
+ s32 (*lay_nv12) (int n, u16 w, u16 w1, u16 h, struct gid_info *gi,
+ u8 *p);
/* group operations */
struct gid_info * (*get_gi) (struct process_info *pi, u32 gid);
void (*release_gi) (struct gid_info *gi);
void (*destroy_group) (struct gid_info *pi);
+ /* group access operations */
+ void (*add_reserved) (struct list_head *reserved, struct gid_info *gi);
+ void (*release) (struct list_head *reserved);
+ /* area operations */
s32 (*analize) (enum tiler_fmt fmt, u32 width, u32 height,
u16 *x_area, u16 *y_area, u16 *band,
u16 *align, u16 *offs, u16 *in_offs);
-
/* process operations */
void (*cleanup) (void);
@@ -88,19 +98,9 @@ struct tiler_ops {
u32 (*addr) (struct tiler_view_orient orient, enum tiler_fmt fmt,
u32 x, u32 y);
- /* reservation operations */
- void (*reserve_nv12) (u32 n, u32 width, u32 height, u32 align, u32 offs,
- u32 gid, struct process_info *pi, bool can_together);
- void (*reserve) (u32 n, enum tiler_fmt fmt, u32 width, u32 height,
- u32 align, u32 offs, u32 gid, struct process_info *pi);
- void (*unreserve) (u32 gid, struct process_info *pi);
-
- s32 (*lay_2d) (enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band,
- u16 align, u16 offs, struct gid_info *gi,
- struct list_head *pos);
- s32 (*lay_nv12) (int n, u16 w, u16 w1, u16 h, struct gid_info *gi,
- u8 *p);
+ /* additional info */
const struct file_operations *fops;
+ bool nv12_packed;
};
void tiler_iface_init(struct tiler_ops *tiler);
diff --git a/drivers/media/video/tiler/tiler-iface.c b/drivers/media/video/tiler/tiler-iface.c
index 15f4a3f55d6..33c3c61a036 100644
--- a/drivers/media/video/tiler/tiler-iface.c
+++ b/drivers/media/video/tiler/tiler-iface.c
@@ -115,6 +115,7 @@ static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi)
return -EACCES;
}
_b->mi[i] = mi;
+ ops->describe(mi, b->blocks + i);
b->length += tiler_size(&mi->blk);
}
@@ -126,17 +127,6 @@ static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi)
return 0;
}
-static s32 register_buf(struct __buf_info *_b, struct process_info *pi)
-{
- s32 r;
-
- mutex_lock(&mtx);
- r = _m_register_buf(_b, pi);
- mutex_unlock(&mtx);
-
- return r;
-}
-
/* unregister a buffer */
/* must have mutex */
static void _m_unregister_buf(struct __buf_info *_b)
@@ -296,7 +286,7 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
struct __buf_info *_b = NULL;
struct tiler_buf_info buf_info = {0};
struct tiler_block_info block_info = {0};
- struct mem_info *mi;
+ struct mem_info *mi = NULL;
switch (cmd) {
case TILIOC_GBLK:
@@ -411,21 +401,23 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
return -EFAULT;
mutex_lock(&mtx);
+ r = -ENOENT;
list_for_each_entry(_b, &pi->bufs, by_pid) {
if (buf_info.offset == _b->buf_info.offset) {
- if (copy_to_user((void __user *)arg,
- &_b->buf_info,
- sizeof(_b->buf_info))) {
- mutex_unlock(&mtx);
- return -EFAULT;
- } else {
- mutex_unlock(&mtx);
- return 0;
- }
+ memcpy(&buf_info, &_b->buf_info,
+ sizeof(buf_info));
+ r = 0;
+ break;
}
}
mutex_unlock(&mtx);
- return -EFAULT;
+
+ if (r)
+ return r;
+
+ if (copy_to_user((void __user *)arg, &_b->buf_info,
+ sizeof(_b->buf_info)))
+ return -EFAULT;
break;
#endif
case TILIOC_RBUF:
@@ -440,14 +432,19 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
kfree(_b); return -EFAULT;
}
- r = register_buf(_b, pi);
+ mutex_lock(&mtx);
+ r = _m_register_buf(_b, pi);
+ mutex_unlock(&mtx);
+
if (r) {
kfree(_b); return -EACCES;
}
if (copy_to_user((void __user *)arg, &_b->buf_info,
sizeof(_b->buf_info))) {
+ mutex_lock(&mtx);
_m_unregister_buf(_b);
+ mutex_unlock(&mtx);
return -EFAULT;
}
break;
@@ -456,17 +453,18 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
sizeof(buf_info)))
return -EFAULT;
+ r = -EFAULT;
mutex_lock(&mtx);
/* buffer registration is per process */
list_for_each_entry(_b, &pi->bufs, by_pid) {
if (buf_info.offset == _b->buf_info.offset) {
_m_unregister_buf(_b);
- mutex_unlock(&mtx);
- return 0;
+ r = 0;
+ break;
}
}
mutex_unlock(&mtx);
- return -EFAULT;
+ return r;
break;
case TILIOC_PRBLK:
if (copy_from_user(&block_info, (void __user *)arg,
@@ -475,45 +473,55 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
if (block_info.fmt == TILFMT_8AND16) {
ops->reserve_nv12(block_info.key,
+ block_info.dim.area.width,
+ block_info.dim.area.height,
+ block_info.align,
+ block_info.offs,
+ block_info.group_id, pi,
+ ops->nv12_packed);
+ } else {
+ ops->reserve(block_info.key,
+ block_info.fmt,
block_info.dim.area.width,
block_info.dim.area.height,
block_info.align,
block_info.offs,
- block_info.group_id, pi,
- true /* :TODO: get can_together */);
- } else {
- ops->reserve(block_info.key,
- block_info.fmt,
- block_info.dim.area.width,
- block_info.dim.area.height,
- block_info.align,
- block_info.offs,
- block_info.group_id, pi);
+ block_info.group_id, pi);
}
break;
case TILIOC_URBLK:
ops->unreserve(arg, pi);
break;
-#ifndef CONFIG_TILER_SECURE
case TILIOC_QBLK:
- if (!ssptr_lookup)
- return -EPERM;
-
if (copy_from_user(&block_info, (void __user *)arg,
sizeof(block_info)))
return -EFAULT;
- mi = ops->get_by_ssptr(block_info.ssptr);
+ if (block_info.id) {
+ /* look up by id if specified */
+ mutex_lock(&mtx);
+ mi = _m_lock_block(block_info.key, block_info.id, pi);
+ mutex_unlock(&mtx);
+ } else
+#ifndef CONFIG_TILER_SECURE
+ if (ssptr_lookup) {
+ /* otherwise, look up by ssptr if allowed */
+ mi = ops->lock_by_ssptr(block_info.ssptr);
+ } else
+#endif
+ return -EPERM;
+
if (mi)
ops->describe(mi, &block_info);
- else
+ ops->unlock_free(mi, false);
+
+ if (!mi)
return -EFAULT;
if (copy_to_user((void __user *)arg, &block_info,
sizeof(block_info)))
return -EFAULT;
break;
-#endif
default:
return -EINVAL;
}
@@ -598,7 +606,7 @@ s32 tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs,
if (pi)
ops->reserve_nv12(n, width, height, align, offs, gid, pi,
- true /* :TODO: get can_together */);
+ ops->nv12_packed);
return 0;
}
EXPORT_SYMBOL(tiler_reservex_nv12);
diff --git a/drivers/media/video/tiler/tiler-main.c b/drivers/media/video/tiler/tiler-main.c
index a909aa2481b..7c6e4ca83f2 100644
--- a/drivers/media/video/tiler/tiler-main.c
+++ b/drivers/media/video/tiler/tiler-main.c
@@ -817,8 +817,10 @@ static struct mem_info *find_block_by_ssptr(u32 sys_addr)
mutex_lock(&mtx);
list_for_each_entry(i, &blocks, global) {
if (tiler_fmt(i->blk.phys) == TILER_GET_ACC_MODE(sys_addr) &&
- tcm_is_in(pt, i->area))
+ tcm_is_in(pt, i->area)) {
+ i->refs++;
goto found;
+ }
}
i = NULL;
@@ -1129,7 +1131,7 @@ static s32 __init tiler_init(void)
tiler.lay_2d = lay_2d;
tiler.lay_nv12 = lay_nv12;
tiler.destroy_group = destroy_group;
- tiler.get_by_ssptr = find_block_by_ssptr;
+ tiler.lock_by_ssptr = find_block_by_ssptr;
tiler.describe = fill_block_info;
tiler.get_gi = get_gi;
tiler.release_gi = release_gi;
@@ -1164,6 +1166,8 @@ static s32 __init tiler_init(void)
TMM_SET(TILFMT_32BIT, tmm_pat);
TMM_SET(TILFMT_PAGE, tmm_pat);
+ tiler.nv12_packed = TCM(TILFMT_8BIT) == TCM(TILFMT_16BIT);
+
tiler_device = kmalloc(sizeof(*tiler_device), GFP_KERNEL);
if (!tiler_device || !sita || !tmm_pat) {
r = -ENOMEM;