diff options
Diffstat (limited to 'drivers/video/omap2/dsscomp/queue.c')
-rw-r--r-- | drivers/video/omap2/dsscomp/queue.c | 76 |
1 files changed, 60 insertions, 16 deletions
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); |