Loading drivers/gpu/msm/kgsl.c +3 −3 Original line number Diff line number Diff line Loading @@ -698,8 +698,7 @@ void kgsl_context_detach(struct kgsl_context *context) /* Remove the event group from the list */ kgsl_del_event_group(&context->events); kgsl_sync_timeline_put(context->ktimeline); kgsl_sync_timeline_detach(context->ktimeline); kgsl_context_put(context); } Loading @@ -718,6 +717,8 @@ kgsl_context_destroy(struct kref *kref) */ BUG_ON(!kgsl_context_detached(context)); kgsl_sync_timeline_put(context->ktimeline); write_lock(&device->context_lock); if (context->id != KGSL_CONTEXT_INVALID) { Loading @@ -741,7 +742,6 @@ kgsl_context_destroy(struct kref *kref) context->id = KGSL_CONTEXT_INVALID; } write_unlock(&device->context_lock); kgsl_sync_timeline_destroy(context); kgsl_process_private_put(context->proc_priv); device->ftbl->drawctxt_destroy(context); Loading drivers/gpu/msm/kgsl_sync.c +43 −23 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include <linux/file.h> Loading Loading @@ -249,27 +249,41 @@ static void kgsl_sync_timeline_value_str(struct dma_fence *fence, { struct kgsl_sync_fence *kfence = (struct kgsl_sync_fence *)fence; struct kgsl_sync_timeline *ktimeline = kfence->parent; struct kgsl_context *context = NULL; unsigned long flags; int ret = 0; unsigned int timestamp_retired = 0; unsigned int timestamp_queued = 0; unsigned int timestamp_retired; unsigned int timestamp_queued; if (!kref_get_unless_zero(&ktimeline->kref)) return; if (!ktimeline->device) goto put_timeline; /* * ktimeline->device might be NULL here but kgsl_readtimestamp() * will handle that correctly */ kgsl_readtimestamp(ktimeline->device, ktimeline->context, spin_lock_irqsave(&ktimeline->lock, flags); ret = _kgsl_context_get(ktimeline->context); context = ret ? ktimeline->context : NULL; spin_unlock_irqrestore(&ktimeline->lock, flags); /* Get the last signaled timestamp if the context is not valid */ timestamp_queued = ktimeline->last_timestamp; timestamp_retired = timestamp_queued; if (context) { kgsl_readtimestamp(ktimeline->device, context, KGSL_TIMESTAMP_RETIRED, ×tamp_retired); kgsl_readtimestamp(ktimeline->device, ktimeline->context, kgsl_readtimestamp(ktimeline->device, context, KGSL_TIMESTAMP_QUEUED, ×tamp_queued); kgsl_context_put(context); } snprintf(str, size, "%u queued:%u retired:%u", ktimeline->last_timestamp, timestamp_queued, timestamp_retired); put_timeline: kgsl_sync_timeline_put(ktimeline); } Loading Loading @@ -298,7 +312,7 @@ int kgsl_sync_timeline_create(struct kgsl_context *context) { struct kgsl_sync_timeline *ktimeline; /* Put context when timeline is released */ /* Put context at detach time */ if (!_kgsl_context_get(context)) return -ENOENT; Loading @@ -319,6 +333,11 @@ int kgsl_sync_timeline_create(struct kgsl_context *context) INIT_LIST_HEAD(&ktimeline->child_list_head); spin_lock_init(&ktimeline->lock); ktimeline->device = context->device; /* * The context pointer is valid till detach time, where we put the * refcount on the context */ ktimeline->context = context; context->ktimeline = ktimeline; Loading Loading @@ -351,30 +370,31 @@ static void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline, kgsl_sync_timeline_put(ktimeline); } void kgsl_sync_timeline_destroy(struct kgsl_context *context) void kgsl_sync_timeline_detach(struct kgsl_sync_timeline *ktimeline) { struct kgsl_sync_timeline *ktimeline = context->ktimeline; unsigned long flags; struct kgsl_context *context = ktimeline->context; kfree(ktimeline->name); kfree(ktimeline); /* Set context pointer to NULL and drop our refcount on the context */ spin_lock_irqsave(&ktimeline->lock, flags); ktimeline->context = NULL; spin_unlock_irqrestore(&ktimeline->lock, flags); kgsl_context_put(context); } static void kgsl_sync_timeline_release(struct kref *kref) static void kgsl_sync_timeline_destroy(struct kref *kref) { struct kgsl_sync_timeline *ktimeline = container_of(kref, struct kgsl_sync_timeline, kref); /* * Only put the context refcount here. The context destroy function * will call kgsl_sync_timeline_destroy() to kfree it */ kgsl_context_put(ktimeline->context); kfree(ktimeline->name); kfree(ktimeline); } void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline) { if (ktimeline) kref_put(&ktimeline->kref, kgsl_sync_timeline_release); kref_put(&ktimeline->kref, kgsl_sync_timeline_destroy); } static const struct dma_fence_ops kgsl_sync_fence_ops = { Loading drivers/gpu/msm/kgsl_sync.h +6 −4 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2012-2014,2018-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014,2018-2021 The Linux Foundation. All rights reserved. */ #ifndef __KGSL_SYNC_H #define __KGSL_SYNC_H Loading @@ -9,7 +9,8 @@ /** * struct kgsl_sync_timeline - A sync timeline associated with a kgsl context * @kref: Refcount to keep the struct alive until all its fences are released * @kref: Refcount to keep the struct alive until all its fences are signaled, and as long as the context exists * @name: String to describe this timeline * @fence_context: Used by the fence driver to identify fences belonging to * this context Loading Loading @@ -80,7 +81,7 @@ int kgsl_add_fence_event(struct kgsl_device *device, int kgsl_sync_timeline_create(struct kgsl_context *context); void kgsl_sync_timeline_destroy(struct kgsl_context *context); void kgsl_sync_timeline_detach(struct kgsl_sync_timeline *ktimeline); void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline); Loading Loading @@ -118,7 +119,8 @@ static inline int kgsl_sync_timeline_create(struct kgsl_context *context) return 0; } static inline void kgsl_sync_timeline_destroy(struct kgsl_context *context) static inline void kgsl_sync_timeline_detach( struct kgsl_sync_timeline *ktimeline) { } Loading Loading
drivers/gpu/msm/kgsl.c +3 −3 Original line number Diff line number Diff line Loading @@ -698,8 +698,7 @@ void kgsl_context_detach(struct kgsl_context *context) /* Remove the event group from the list */ kgsl_del_event_group(&context->events); kgsl_sync_timeline_put(context->ktimeline); kgsl_sync_timeline_detach(context->ktimeline); kgsl_context_put(context); } Loading @@ -718,6 +717,8 @@ kgsl_context_destroy(struct kref *kref) */ BUG_ON(!kgsl_context_detached(context)); kgsl_sync_timeline_put(context->ktimeline); write_lock(&device->context_lock); if (context->id != KGSL_CONTEXT_INVALID) { Loading @@ -741,7 +742,6 @@ kgsl_context_destroy(struct kref *kref) context->id = KGSL_CONTEXT_INVALID; } write_unlock(&device->context_lock); kgsl_sync_timeline_destroy(context); kgsl_process_private_put(context->proc_priv); device->ftbl->drawctxt_destroy(context); Loading
drivers/gpu/msm/kgsl_sync.c +43 −23 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include <linux/file.h> Loading Loading @@ -249,27 +249,41 @@ static void kgsl_sync_timeline_value_str(struct dma_fence *fence, { struct kgsl_sync_fence *kfence = (struct kgsl_sync_fence *)fence; struct kgsl_sync_timeline *ktimeline = kfence->parent; struct kgsl_context *context = NULL; unsigned long flags; int ret = 0; unsigned int timestamp_retired = 0; unsigned int timestamp_queued = 0; unsigned int timestamp_retired; unsigned int timestamp_queued; if (!kref_get_unless_zero(&ktimeline->kref)) return; if (!ktimeline->device) goto put_timeline; /* * ktimeline->device might be NULL here but kgsl_readtimestamp() * will handle that correctly */ kgsl_readtimestamp(ktimeline->device, ktimeline->context, spin_lock_irqsave(&ktimeline->lock, flags); ret = _kgsl_context_get(ktimeline->context); context = ret ? ktimeline->context : NULL; spin_unlock_irqrestore(&ktimeline->lock, flags); /* Get the last signaled timestamp if the context is not valid */ timestamp_queued = ktimeline->last_timestamp; timestamp_retired = timestamp_queued; if (context) { kgsl_readtimestamp(ktimeline->device, context, KGSL_TIMESTAMP_RETIRED, ×tamp_retired); kgsl_readtimestamp(ktimeline->device, ktimeline->context, kgsl_readtimestamp(ktimeline->device, context, KGSL_TIMESTAMP_QUEUED, ×tamp_queued); kgsl_context_put(context); } snprintf(str, size, "%u queued:%u retired:%u", ktimeline->last_timestamp, timestamp_queued, timestamp_retired); put_timeline: kgsl_sync_timeline_put(ktimeline); } Loading Loading @@ -298,7 +312,7 @@ int kgsl_sync_timeline_create(struct kgsl_context *context) { struct kgsl_sync_timeline *ktimeline; /* Put context when timeline is released */ /* Put context at detach time */ if (!_kgsl_context_get(context)) return -ENOENT; Loading @@ -319,6 +333,11 @@ int kgsl_sync_timeline_create(struct kgsl_context *context) INIT_LIST_HEAD(&ktimeline->child_list_head); spin_lock_init(&ktimeline->lock); ktimeline->device = context->device; /* * The context pointer is valid till detach time, where we put the * refcount on the context */ ktimeline->context = context; context->ktimeline = ktimeline; Loading Loading @@ -351,30 +370,31 @@ static void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline, kgsl_sync_timeline_put(ktimeline); } void kgsl_sync_timeline_destroy(struct kgsl_context *context) void kgsl_sync_timeline_detach(struct kgsl_sync_timeline *ktimeline) { struct kgsl_sync_timeline *ktimeline = context->ktimeline; unsigned long flags; struct kgsl_context *context = ktimeline->context; kfree(ktimeline->name); kfree(ktimeline); /* Set context pointer to NULL and drop our refcount on the context */ spin_lock_irqsave(&ktimeline->lock, flags); ktimeline->context = NULL; spin_unlock_irqrestore(&ktimeline->lock, flags); kgsl_context_put(context); } static void kgsl_sync_timeline_release(struct kref *kref) static void kgsl_sync_timeline_destroy(struct kref *kref) { struct kgsl_sync_timeline *ktimeline = container_of(kref, struct kgsl_sync_timeline, kref); /* * Only put the context refcount here. The context destroy function * will call kgsl_sync_timeline_destroy() to kfree it */ kgsl_context_put(ktimeline->context); kfree(ktimeline->name); kfree(ktimeline); } void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline) { if (ktimeline) kref_put(&ktimeline->kref, kgsl_sync_timeline_release); kref_put(&ktimeline->kref, kgsl_sync_timeline_destroy); } static const struct dma_fence_ops kgsl_sync_fence_ops = { Loading
drivers/gpu/msm/kgsl_sync.h +6 −4 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2012-2014,2018-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014,2018-2021 The Linux Foundation. All rights reserved. */ #ifndef __KGSL_SYNC_H #define __KGSL_SYNC_H Loading @@ -9,7 +9,8 @@ /** * struct kgsl_sync_timeline - A sync timeline associated with a kgsl context * @kref: Refcount to keep the struct alive until all its fences are released * @kref: Refcount to keep the struct alive until all its fences are signaled, and as long as the context exists * @name: String to describe this timeline * @fence_context: Used by the fence driver to identify fences belonging to * this context Loading Loading @@ -80,7 +81,7 @@ int kgsl_add_fence_event(struct kgsl_device *device, int kgsl_sync_timeline_create(struct kgsl_context *context); void kgsl_sync_timeline_destroy(struct kgsl_context *context); void kgsl_sync_timeline_detach(struct kgsl_sync_timeline *ktimeline); void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline); Loading Loading @@ -118,7 +119,8 @@ static inline int kgsl_sync_timeline_create(struct kgsl_context *context) return 0; } static inline void kgsl_sync_timeline_destroy(struct kgsl_context *context) static inline void kgsl_sync_timeline_detach( struct kgsl_sync_timeline *ktimeline) { } Loading