Loading drivers/gpu/msm/kgsl.c +22 −0 Original line number Diff line number Diff line Loading @@ -788,6 +788,7 @@ static void kgsl_destroy_process_private(struct kref *kref) debugfs_remove_recursive(private->debug_root); idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); kgsl_mmu_putpagetable(private->pagetable); kfree(private); Loading Loading @@ -893,6 +894,8 @@ kgsl_get_process_private(struct kgsl_device *device) private->mem_rb = RB_ROOT; idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; Loading Loading @@ -948,13 +951,24 @@ static int kgsl_release(struct inode *inodep, struct file *filep) struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_syncsource *syncsource; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; next = 0; while (1) { syncsource = idr_get_next(&private->syncsource_idr, &next); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } kgsl_mutex_lock(&device->mutex, &device->mutex_owner); next = 0; while (1) { read_lock(&device->context_lock); context = idr_get_next(&device->context_idr, &next); Loading Loading @@ -3542,6 +3556,14 @@ static const struct kgsl_ioctl kgsl_ioctl_funcs[] = { kgsl_ioctl_gpumem_sync_cache, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK, kgsl_ioctl_gpumem_sync_cache_bulk, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE, kgsl_ioctl_syncsource_create, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY, kgsl_ioctl_syncsource_destroy, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE, kgsl_ioctl_syncsource_create_fence, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE, kgsl_ioctl_syncsource_signal_fence, 0), }; long kgsl_ioctl_helper(struct file *filep, unsigned int cmd, Loading drivers/gpu/msm/kgsl_compat.c +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "kgsl.h" #include "kgsl_compat.h" #include "kgsl_device.h" #include "kgsl_sync.h" #include "adreno.h" Loading Loading @@ -343,6 +344,14 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = { kgsl_ioctl_gpumem_sync_cache_compat, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK_COMPAT, kgsl_ioctl_gpumem_sync_cache_bulk_compat, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE, kgsl_ioctl_syncsource_create, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY, kgsl_ioctl_syncsource_destroy, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE, kgsl_ioctl_syncsource_create_fence, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE, kgsl_ioctl_syncsource_signal_fence, 0), }; long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, Loading drivers/gpu/msm/kgsl_device.h +3 −0 Original line number Diff line number Diff line Loading @@ -532,6 +532,7 @@ struct kgsl_context { * @kobj: Pointer to a kobj for the sysfs directory for this process * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process * @syncsource_idr: sync sources created by this process */ struct kgsl_process_private { unsigned long priv; Loading @@ -555,6 +556,8 @@ struct kgsl_process_private { unsigned int cur; unsigned int max; } stats[KGSL_MEM_ENTRY_MAX]; struct idr syncsource_idr; }; /** Loading drivers/gpu/msm/kgsl_sync.c +199 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/err.h> #include <linux/file.h> #include <linux/oneshot_sync.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/uaccess.h> Loading Loading @@ -356,3 +357,201 @@ int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_waiter *kwaiter) } return 0; } #ifdef CONFIG_ONESHOT_SYNC struct kgsl_syncsource { struct kref refcount; int id; struct kgsl_process_private *private; struct oneshot_sync_timeline *oneshot; }; long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource *syncsource = NULL; struct kgsl_syncsource_create *param = data; int ret = -EINVAL; int id = 0; struct kgsl_process_private *private = dev_priv->process_priv; char name[32]; syncsource = kzalloc(sizeof(*syncsource), GFP_KERNEL); if (syncsource == NULL) { ret = -ENOMEM; goto out; } snprintf(name, sizeof(name), "kgsl-syncsource-pid-%d", current->group_leader->pid); syncsource->oneshot = oneshot_timeline_create(name); if (syncsource->oneshot == NULL) { ret = -ENOMEM; goto out; } mutex_lock(&private->process_private_mutex); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_KERNEL); if (id > 0) { kref_init(&syncsource->refcount); syncsource->id = id; syncsource->private = private; param->id = id; ret = 0; } else { ret = id; } mutex_unlock(&private->process_private_mutex); out: if (ret) { if (syncsource && syncsource->oneshot) oneshot_timeline_destroy(syncsource->oneshot); kfree(syncsource); } return ret; } static struct kgsl_syncsource * kgsl_syncsource_get(struct kgsl_process_private *private, int id) { int result = 0; struct kgsl_syncsource *syncsource = NULL; mutex_lock(&private->process_private_mutex); syncsource = idr_find(&private->syncsource_idr, id); if (syncsource) result = kref_get_unless_zero(&syncsource->refcount); mutex_unlock(&private->process_private_mutex); return result ? syncsource : NULL; } static void kgsl_syncsource_destroy(struct kref *kref) { struct kgsl_syncsource *syncsource = container_of(kref, struct kgsl_syncsource, refcount); struct kgsl_process_private *private = syncsource->private; mutex_lock(&private->process_private_mutex); if (syncsource->id != 0) { idr_remove(&private->syncsource_idr, syncsource->id); syncsource->id = 0; } oneshot_timeline_destroy(syncsource->oneshot); mutex_unlock(&private->process_private_mutex); kfree(syncsource); } void kgsl_syncsource_put(struct kgsl_syncsource *syncsource) { if (syncsource) kref_put(&syncsource->refcount, kgsl_syncsource_destroy); } long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource_destroy *param = data; struct kgsl_syncsource *syncsource = NULL; struct kgsl_process_private *private; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) return -EINVAL; private = syncsource->private; mutex_lock(&private->process_private_mutex); idr_remove(&private->syncsource_idr, param->id); syncsource->id = 0; mutex_unlock(&private->process_private_mutex); /* put reference from syncsource creation */ kgsl_syncsource_put(syncsource); /* put reference from getting the syncsource above */ kgsl_syncsource_put(syncsource); return 0; } long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource_create_fence *param = data; struct kgsl_syncsource *syncsource = NULL; int ret = -EINVAL; struct sync_fence *fence = NULL; int fd = -1; char name[32]; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) goto out; snprintf(name, sizeof(name), "kgsl-syncsource-pid-%d-%d", current->group_leader->pid, syncsource->id); fence = oneshot_fence_create(syncsource->oneshot, name); if (fence == NULL) { ret = -ENOMEM; goto out; } fd = get_unused_fd_flags(0); if (fd < 0) { ret = -EBADF; goto out; } ret = 0; sync_fence_install(fence, fd); param->fence_fd = fd; out: if (ret) { if (fence) sync_fence_put(fence); } kgsl_syncsource_put(syncsource); return ret; } long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { int ret = -EINVAL; struct kgsl_syncsource_signal_fence *param = data; struct kgsl_syncsource *syncsource = NULL; struct sync_fence *fence = NULL; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) goto out; fence = sync_fence_fdget(param->fence_fd); if (fence == NULL) { ret = -EBADF; goto out; } ret = oneshot_fence_signal(syncsource->oneshot, fence); out: if (fence) sync_fence_put(fence); kgsl_syncsource_put(syncsource); return ret; } #endif drivers/gpu/msm/kgsl_sync.h +49 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ struct kgsl_sync_fence_waiter { void *priv; }; struct kgsl_syncsource; #if defined(CONFIG_SYNC) int kgsl_add_fence_event(struct kgsl_device *device, u32 context_id, u32 timestamp, void __user *data, int len, Loading Loading @@ -77,4 +79,51 @@ kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_waiter *waiter) #endif #ifdef CONFIG_ONESHOT_SYNC long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_syncsource_put(struct kgsl_syncsource *syncsource); #else static inline long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline void kgsl_syncsource_put(struct kgsl_syncsource *syncsource) { } #endif #endif /* __KGSL_SYNC_H */ Loading
drivers/gpu/msm/kgsl.c +22 −0 Original line number Diff line number Diff line Loading @@ -788,6 +788,7 @@ static void kgsl_destroy_process_private(struct kref *kref) debugfs_remove_recursive(private->debug_root); idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); kgsl_mmu_putpagetable(private->pagetable); kfree(private); Loading Loading @@ -893,6 +894,8 @@ kgsl_get_process_private(struct kgsl_device *device) private->mem_rb = RB_ROOT; idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; Loading Loading @@ -948,13 +951,24 @@ static int kgsl_release(struct inode *inodep, struct file *filep) struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_syncsource *syncsource; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; next = 0; while (1) { syncsource = idr_get_next(&private->syncsource_idr, &next); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } kgsl_mutex_lock(&device->mutex, &device->mutex_owner); next = 0; while (1) { read_lock(&device->context_lock); context = idr_get_next(&device->context_idr, &next); Loading Loading @@ -3542,6 +3556,14 @@ static const struct kgsl_ioctl kgsl_ioctl_funcs[] = { kgsl_ioctl_gpumem_sync_cache, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK, kgsl_ioctl_gpumem_sync_cache_bulk, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE, kgsl_ioctl_syncsource_create, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY, kgsl_ioctl_syncsource_destroy, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE, kgsl_ioctl_syncsource_create_fence, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE, kgsl_ioctl_syncsource_signal_fence, 0), }; long kgsl_ioctl_helper(struct file *filep, unsigned int cmd, Loading
drivers/gpu/msm/kgsl_compat.c +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "kgsl.h" #include "kgsl_compat.h" #include "kgsl_device.h" #include "kgsl_sync.h" #include "adreno.h" Loading Loading @@ -343,6 +344,14 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = { kgsl_ioctl_gpumem_sync_cache_compat, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK_COMPAT, kgsl_ioctl_gpumem_sync_cache_bulk_compat, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE, kgsl_ioctl_syncsource_create, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY, kgsl_ioctl_syncsource_destroy, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE, kgsl_ioctl_syncsource_create_fence, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE, kgsl_ioctl_syncsource_signal_fence, 0), }; long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, Loading
drivers/gpu/msm/kgsl_device.h +3 −0 Original line number Diff line number Diff line Loading @@ -532,6 +532,7 @@ struct kgsl_context { * @kobj: Pointer to a kobj for the sysfs directory for this process * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process * @syncsource_idr: sync sources created by this process */ struct kgsl_process_private { unsigned long priv; Loading @@ -555,6 +556,8 @@ struct kgsl_process_private { unsigned int cur; unsigned int max; } stats[KGSL_MEM_ENTRY_MAX]; struct idr syncsource_idr; }; /** Loading
drivers/gpu/msm/kgsl_sync.c +199 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/err.h> #include <linux/file.h> #include <linux/oneshot_sync.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/uaccess.h> Loading Loading @@ -356,3 +357,201 @@ int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_waiter *kwaiter) } return 0; } #ifdef CONFIG_ONESHOT_SYNC struct kgsl_syncsource { struct kref refcount; int id; struct kgsl_process_private *private; struct oneshot_sync_timeline *oneshot; }; long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource *syncsource = NULL; struct kgsl_syncsource_create *param = data; int ret = -EINVAL; int id = 0; struct kgsl_process_private *private = dev_priv->process_priv; char name[32]; syncsource = kzalloc(sizeof(*syncsource), GFP_KERNEL); if (syncsource == NULL) { ret = -ENOMEM; goto out; } snprintf(name, sizeof(name), "kgsl-syncsource-pid-%d", current->group_leader->pid); syncsource->oneshot = oneshot_timeline_create(name); if (syncsource->oneshot == NULL) { ret = -ENOMEM; goto out; } mutex_lock(&private->process_private_mutex); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_KERNEL); if (id > 0) { kref_init(&syncsource->refcount); syncsource->id = id; syncsource->private = private; param->id = id; ret = 0; } else { ret = id; } mutex_unlock(&private->process_private_mutex); out: if (ret) { if (syncsource && syncsource->oneshot) oneshot_timeline_destroy(syncsource->oneshot); kfree(syncsource); } return ret; } static struct kgsl_syncsource * kgsl_syncsource_get(struct kgsl_process_private *private, int id) { int result = 0; struct kgsl_syncsource *syncsource = NULL; mutex_lock(&private->process_private_mutex); syncsource = idr_find(&private->syncsource_idr, id); if (syncsource) result = kref_get_unless_zero(&syncsource->refcount); mutex_unlock(&private->process_private_mutex); return result ? syncsource : NULL; } static void kgsl_syncsource_destroy(struct kref *kref) { struct kgsl_syncsource *syncsource = container_of(kref, struct kgsl_syncsource, refcount); struct kgsl_process_private *private = syncsource->private; mutex_lock(&private->process_private_mutex); if (syncsource->id != 0) { idr_remove(&private->syncsource_idr, syncsource->id); syncsource->id = 0; } oneshot_timeline_destroy(syncsource->oneshot); mutex_unlock(&private->process_private_mutex); kfree(syncsource); } void kgsl_syncsource_put(struct kgsl_syncsource *syncsource) { if (syncsource) kref_put(&syncsource->refcount, kgsl_syncsource_destroy); } long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource_destroy *param = data; struct kgsl_syncsource *syncsource = NULL; struct kgsl_process_private *private; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) return -EINVAL; private = syncsource->private; mutex_lock(&private->process_private_mutex); idr_remove(&private->syncsource_idr, param->id); syncsource->id = 0; mutex_unlock(&private->process_private_mutex); /* put reference from syncsource creation */ kgsl_syncsource_put(syncsource); /* put reference from getting the syncsource above */ kgsl_syncsource_put(syncsource); return 0; } long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_syncsource_create_fence *param = data; struct kgsl_syncsource *syncsource = NULL; int ret = -EINVAL; struct sync_fence *fence = NULL; int fd = -1; char name[32]; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) goto out; snprintf(name, sizeof(name), "kgsl-syncsource-pid-%d-%d", current->group_leader->pid, syncsource->id); fence = oneshot_fence_create(syncsource->oneshot, name); if (fence == NULL) { ret = -ENOMEM; goto out; } fd = get_unused_fd_flags(0); if (fd < 0) { ret = -EBADF; goto out; } ret = 0; sync_fence_install(fence, fd); param->fence_fd = fd; out: if (ret) { if (fence) sync_fence_put(fence); } kgsl_syncsource_put(syncsource); return ret; } long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { int ret = -EINVAL; struct kgsl_syncsource_signal_fence *param = data; struct kgsl_syncsource *syncsource = NULL; struct sync_fence *fence = NULL; syncsource = kgsl_syncsource_get(dev_priv->process_priv, param->id); if (syncsource == NULL) goto out; fence = sync_fence_fdget(param->fence_fd); if (fence == NULL) { ret = -EBADF; goto out; } ret = oneshot_fence_signal(syncsource->oneshot, fence); out: if (fence) sync_fence_put(fence); kgsl_syncsource_put(syncsource); return ret; } #endif
drivers/gpu/msm/kgsl_sync.h +49 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ struct kgsl_sync_fence_waiter { void *priv; }; struct kgsl_syncsource; #if defined(CONFIG_SYNC) int kgsl_add_fence_event(struct kgsl_device *device, u32 context_id, u32 timestamp, void __user *data, int len, Loading Loading @@ -77,4 +79,51 @@ kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_waiter *waiter) #endif #ifdef CONFIG_ONESHOT_SYNC long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_syncsource_put(struct kgsl_syncsource *syncsource); #else static inline long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_create_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline long kgsl_ioctl_syncsource_signal_fence(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { return -ENOIOCTLCMD; } static inline void kgsl_syncsource_put(struct kgsl_syncsource *syncsource) { } #endif #endif /* __KGSL_SYNC_H */