From 030590f22f6c1f33f7bc37f458dcdd6bda5a0287 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 22 Dec 2011 17:19:45 +0200 Subject: [PATCH] staging: mrst: ossync: Avoid double kmalloc() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Allow the user to embed the pending_sync structure inside its own structure, and use container_of() in the callback. This means we can now get by with one kmalloc() per flip, instead of two. As PVRSRVCallbackOnSync() can no longer fail, change the return type to void. Signed-off-by: Ville Syrjälä Signed-off-by: Artem Bityutskiy --- drivers/staging/mrst/drv/psb_page_flip.c | 17 ++++--- .../mrst/pvr/services4/srvkm/env/linux/ossync.c | 52 +++++++--------------- .../mrst/pvr/services4/srvkm/include/ossync.h | 18 +++++++- 3 files changed, 40 insertions(+), 47 deletions(-) diff --git a/drivers/staging/mrst/drv/psb_page_flip.c b/drivers/staging/mrst/drv/psb_page_flip.c index d02d34d..536548c 100644 --- a/drivers/staging/mrst/drv/psb_page_flip.c +++ b/drivers/staging/mrst/drv/psb_page_flip.c @@ -43,6 +43,7 @@ struct pending_flip { struct drm_pending_vblank_event *event; PVRSRV_KERNEL_MEM_INFO *old_mem_info; uint32_t offset; + struct pvr_pending_sync pending_sync; }; static void @@ -161,10 +162,10 @@ psb_intel_crtc_process_vblank(struct drm_crtc *crtc) } static void -sync_callback(void *data) +sync_callback(struct pvr_pending_sync *pending_sync) { - struct pending_flip *pending_flip = data; - + struct pending_flip *pending_flip = + container_of(pending_sync, struct pending_flip, pending_sync); struct drm_crtc* crtc = pending_flip->crtc; struct drm_device *dev = crtc->dev; struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); @@ -207,11 +208,9 @@ psb_intel_crtc_page_flip(struct drm_crtc *crtc, increase_read_ops_pending(current_fb_mem_info); - ret = PVRSRVCallbackOnSync(new_fb_mem_info->psKernelSyncInfo, - PVRSRV_SYNC_WRITE, sync_callback, - new_pending_flip); - if (ret < 0) - kfree(new_pending_flip); + PVRSRVCallbackOnSync(new_fb_mem_info->psKernelSyncInfo, + PVRSRV_SYNC_WRITE, sync_callback, + &new_pending_flip->pending_sync); - return ret; + return 0; } diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c index b555b00..601a23e 100644 --- a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c +++ b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c @@ -30,19 +30,6 @@ DEFINE_SPINLOCK(sync_lock); LIST_HEAD(sync_list); -typedef void (*callback_t)(void *); - -struct pending_sync { - PVRSRV_KERNEL_SYNC_INFO *sync_info; - u32 pending_read_ops; - u32 pending_write_ops; - unsigned int flags; - callback_t callback; - void *user_data; - - struct list_head list; -}; - #define ops_after(a, b) ((s32)(b) - (s32)(a) < 0) static bool pending_ops_completed(PVRSRV_KERNEL_SYNC_INFO *sync_info, @@ -64,45 +51,40 @@ static bool pending_ops_completed(PVRSRV_KERNEL_SYNC_INFO *sync_info, /* Returns 0 if the callback was successfully registered. * Returns a negative value on error. */ -int +void PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, unsigned int flags, - callback_t callback, void *user_data) + pvr_sync_callback callback, + struct pvr_pending_sync *pending_sync) { - struct pending_sync *pending_sync; u32 pending_read_ops = sync_info->psSyncData->ui32ReadOpsPending; u32 pending_write_ops = sync_info->psSyncData->ui32WriteOpsPending; - /* If the object is already in sync, don't add it to the list */ - if (pending_ops_completed(sync_info, flags, - pending_read_ops, - pending_write_ops)) { - callback(user_data); - return 0; - } - - pending_sync = kmalloc(sizeof *pending_sync, GFP_KERNEL); - if (!pending_sync) - return -ENOMEM; - pending_sync->sync_info = sync_info; pending_sync->pending_read_ops = pending_read_ops; pending_sync->pending_write_ops = pending_write_ops; pending_sync->flags = flags; pending_sync->callback = callback; - pending_sync->user_data = user_data; + + /* If the object is already in sync, don't add it to the list */ + if (pending_ops_completed(sync_info, flags, + pending_read_ops, + pending_write_ops)) { + callback(pending_sync); + return; + } spin_lock_irq(&sync_lock); list_add_tail(&pending_sync->list, &sync_list); spin_unlock_irq(&sync_lock); - return 0; + return; } void -PVRSRVCheckPendingSyncs() +PVRSRVCheckPendingSyncs(void) { - struct pending_sync *ps, *tmp; + struct pvr_pending_sync *ps, *tmp; unsigned long flags; LIST_HEAD(completed_list); @@ -120,9 +102,7 @@ PVRSRVCheckPendingSyncs() spin_unlock_irqrestore(&sync_lock, flags); /* Execute the callbacks */ - list_for_each_entry_safe(ps, tmp, &completed_list, list) { - ps->callback(ps->user_data); - kfree(ps); - } + list_for_each_entry_safe(ps, tmp, &completed_list, list) + ps->callback(ps); } diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h b/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h index 894e01e..a0c927f 100644 --- a/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h +++ b/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h @@ -27,8 +27,22 @@ #define PVRSRV_SYNC_READ (1 << 0) #define PVRSRV_SYNC_WRITE (1 << 1) -int PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, unsigned int flags, - void (*callback)(void *), void *user_data); +struct pvr_pending_sync; + +typedef void (*pvr_sync_callback)(struct pvr_pending_sync *pending_sync); + +struct pvr_pending_sync { + PVRSRV_KERNEL_SYNC_INFO *sync_info; + u32 pending_read_ops; + u32 pending_write_ops; + unsigned int flags; + pvr_sync_callback callback; + struct list_head list; +}; + +void PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, unsigned int flags, + pvr_sync_callback callback, + struct pvr_pending_sync *pending_sync); void PVRSRVCheckPendingSyncs(void); #endif /* _OSSYNC_H_ */ -- 2.7.4