diff options
author | Mykhailo Denysiuk <x0172934@ti.com> | 2012-04-27 15:29:04 +0300 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 12:58:17 +0200 |
commit | 5ce0778fe01e2deb6daa221f60ce3b25c0fb4a4b (patch) | |
tree | d59ac88bd9fbc130ed4919449ebb1a5a360cdb2e | |
parent | 4a9c8d6e885170d7447897e07663afbb329c6ab5 (diff) | |
download | kernel_samsung_tuna-5ce0778fe01e2deb6daa221f60ce3b25c0fb4a4b.zip kernel_samsung_tuna-5ce0778fe01e2deb6daa221f60ce3b25c0fb4a4b.tar.gz kernel_samsung_tuna-5ce0778fe01e2deb6daa221f60ce3b25c0fb4a4b.tar.bz2 |
OMAPDSS: DSSCOMP: efficiency improvement.
This change adds 3 local caches of objects, which are used at each flip buffer
action. In original variant kzalloc()/kfree() functions are called each time
dsscomp_gralloc_queue() function is called. This meens that slab|slob|slub
common cache is used at each frame draw action. Call to kzalloc()/kfree()
result in synchronization with other code, which uses common cache, and can
result in dips in FPS, when other code allocates/frees memory.
This change improves reliability, autonomy and efficiency of DSSCOMP module.
Change-Id: Id50778f4579309fb71318a32820b9d6441a6dac1
Signed-off-by: Mykhailo Denysiuk <x0172934@ti.com>
-rw-r--r-- | drivers/video/omap2/dsscomp/gralloc.c | 27 | ||||
-rw-r--r-- | drivers/video/omap2/dsscomp/queue.c | 76 |
2 files changed, 84 insertions, 19 deletions
diff --git a/drivers/video/omap2/dsscomp/gralloc.c b/drivers/video/omap2/dsscomp/gralloc.c index 8bb7cdc..8545248 100644 --- a/drivers/video/omap2/dsscomp/gralloc.c +++ b/drivers/video/omap2/dsscomp/gralloc.c @@ -38,6 +38,9 @@ struct dsscomp_gralloc_t { bool programmed; }; +/* local cache */ +static struct kmem_cache *gsync_cachep; + /* queued gralloc compositions */ static LIST_HEAD(flip_queue); @@ -102,7 +105,8 @@ static void dsscomp_gralloc_cb(void *data, int status) if (gsync->cb_fn) gsync->cb_fn(gsync->cb_arg, 1); - kfree(gsync); + + kmem_cache_free(gsync_cachep, gsync); } } @@ -180,8 +184,16 @@ int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d, mutex_lock(&mtx); - /* create sync object with 1 temporary ref */ - gsync = kzalloc(sizeof(*gsync), GFP_KERNEL); + /* allocate sync object with 1 temporary ref */ + gsync = kmem_cache_zalloc(gsync_cachep, GFP_KERNEL); + if (!gsync) { + mutex_unlock(&mtx); + mutex_unlock(&local_mtx); + pr_err("DSSCOMP: %s: can't allocate object from cache\n", + __func__); + BUG(); + } + gsync->cb_arg = cb_arg; gsync->cb_fn = cb_fn; gsync->refs.counter = 1; @@ -598,6 +610,15 @@ void dsscomp_gralloc_init(struct dsscomp_dev *cdev_) if (!i) ZERO(free_slots); } + + /* create cache at first time */ + if (!gsync_cachep) { + gsync_cachep = kmem_cache_create("gsync_cache", + sizeof(struct dsscomp_gralloc_t), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!gsync_cachep) + pr_err("DSSCOMP: %s: can't create cache\n", __func__); + } } void dsscomp_gralloc_exit(void) diff --git a/drivers/video/omap2/dsscomp/queue.c b/drivers/video/omap2/dsscomp/queue.c index 540b8c8..560294c 100644 --- a/drivers/video/omap2/dsscomp/queue.c +++ b/drivers/video/omap2/dsscomp/queue.c @@ -99,6 +99,21 @@ static void maskref_decmask(struct maskref *om, u32 mask) * =========================================================================== */ +struct dsscomp_cb_work { + struct work_struct work; + struct dsscomp_data *comp; + int status; +}; + +struct dsscomp_apply_work { + struct work_struct work; + dsscomp_t comp; +}; + +/* Local caches */ +static struct kmem_cache *dsscomp_cb_wk_cachep; +static struct kmem_cache *dsscomp_app_wk_cachep; + /* Initialize queue structures, and set up state of the displays */ int dsscomp_queue_init(struct dsscomp_dev *cdev_) { @@ -132,6 +147,31 @@ int dsscomp_queue_init(struct dsscomp_dev *cdev_) if (!cb_wkq) goto error; + /* create cache for dsscomp_cb_work structures */ + if (!dsscomp_cb_wk_cachep) { + dsscomp_cb_wk_cachep = kmem_cache_create("cb_wk_cache", + sizeof(struct dsscomp_cb_work), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!dsscomp_cb_wk_cachep) { + pr_err("DSSCOMP: %s: can't create cache\n", + __func__); + goto error; + } + } + + /* create cache for dsscomp_apply_work structures */ + if (!dsscomp_app_wk_cachep) { + dsscomp_app_wk_cachep = kmem_cache_create("app_wk_cache", + sizeof(struct dsscomp_apply_work), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!dsscomp_app_wk_cachep) { + pr_err("DSSCOMP: %s: can't create cache\n", __func__); + /* destroy previously created cache */ + kmem_cache_destroy(dsscomp_cb_wk_cachep); + goto error; + } + } + return 0; error: while (i--) @@ -379,12 +419,6 @@ void dsscomp_drop(dsscomp_t comp) } EXPORT_SYMBOL(dsscomp_drop); -struct dsscomp_cb_work { - struct work_struct work; - struct dsscomp_data *comp; - int status; -}; - static void dsscomp_mgr_delayed_cb(struct work_struct *work) { struct dsscomp_cb_work *wk = container_of(work, typeof(*wk), work); @@ -392,7 +426,7 @@ static void dsscomp_mgr_delayed_cb(struct work_struct *work) int status = wk->status; u32 ix; - kfree(work); + kmem_cache_free(dsscomp_cb_wk_cachep, wk); mutex_lock(&mtx); @@ -439,7 +473,16 @@ static u32 dsscomp_mgr_callback(void *data, int id, int status) (status == DSS_COMPLETION_DISPLAYED && comp->state != DSSCOMP_STATE_DISPLAYED) || (status & DSS_COMPLETION_RELEASED)) { - struct dsscomp_cb_work *wk = kzalloc(sizeof(*wk), GFP_ATOMIC); + struct dsscomp_cb_work *wk; + + /* allocate work object from cache */ + wk = kmem_cache_zalloc(dsscomp_cb_wk_cachep, GFP_ATOMIC); + if (!wk) { + pr_err("DSSCOMP: %s: can't allocate cache object\n", + __func__); + BUG(); + } + wk->comp = comp; wk->status = status; INIT_WORK(&wk->work, dsscomp_mgr_delayed_cb); @@ -688,11 +731,6 @@ done: return r; } -struct dsscomp_apply_work { - struct work_struct work; - dsscomp_t comp; -}; - int dsscomp_state_notifier(struct notifier_block *nb, unsigned long arg, void *ptr) { @@ -718,15 +756,21 @@ static void dsscomp_do_apply(struct work_struct *work) /* complete compositions that failed to apply */ if (dsscomp_apply(wk->comp)) dsscomp_mgr_callback(wk->comp, -1, DSS_COMPLETION_ECLIPSED_SET); - kfree(wk); + kmem_cache_free(dsscomp_app_wk_cachep, wk); } int dsscomp_delayed_apply(dsscomp_t comp) { /* don't block in case we are called from interrupt context */ - struct dsscomp_apply_work *wk = kzalloc(sizeof(*wk), GFP_NOWAIT); - if (!wk) + struct dsscomp_apply_work *wk; + + /* allocate work object from cache */ + wk = kmem_cache_zalloc(dsscomp_app_wk_cachep, GFP_NOWAIT); + if (!wk) { + pr_warn("DSSCOMP: %s: can't allocate object from cache\n", + __func__); return -ENOMEM; + } mutex_lock(&mtx); |