diff options
author | Lajos Molnar <molnar@ti.com> | 2011-04-07 08:41:25 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-04-07 08:41:25 +0100 |
commit | 23da91cf9817b567bfbf4125ed1189751c09e3f3 (patch) | |
tree | e490c0f073fcb49bbcf39b9a0b50f9081313513c /drivers | |
parent | ad30a7c4f0b692183c9ea0970e5457ab0a64fc87 (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.h | 38 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler-iface.c | 96 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler-main.c | 8 |
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; |