aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMykhailo Denysiuk <x0172934@ti.com>2012-04-27 15:29:04 +0300
committerZiyann <jaraidaniel@gmail.com>2014-10-01 12:58:17 +0200
commit5ce0778fe01e2deb6daa221f60ce3b25c0fb4a4b (patch)
treed59ac88bd9fbc130ed4919449ebb1a5a360cdb2e
parent4a9c8d6e885170d7447897e07663afbb329c6ab5 (diff)
downloadkernel_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.c27
-rw-r--r--drivers/video/omap2/dsscomp/queue.c76
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);