Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aece175d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Protect the event->handle with spinlock"

parents dd74db03 48a3738b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ typedef void (*reg_read_fill_t)(struct kgsl_device *device, int i,
static void sync_event_print(struct seq_file *s,
		struct kgsl_cmdbatch_sync_event *sync_event)
{
	unsigned long flags;

	switch (sync_event->type) {
	case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: {
		seq_printf(s, "sync: ctx: %d ts: %d",
@@ -138,9 +140,13 @@ static void sync_event_print(struct seq_file *s,
		break;
	}
	case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
		spin_lock_irqsave(&sync_event->handle_lock, flags);

		seq_printf(s, "sync: [%pk] %s", sync_event->handle,
		(sync_event->handle && sync_event->handle->fence)
				? sync_event->handle->fence->name : "NULL");

		spin_unlock_irqrestore(&sync_event->handle_lock, flags);
		break;
	default:
		seq_printf(s, "sync: type: %d", sync_event->type);
+41 −4
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ void kgsl_dump_syncpoints(struct kgsl_device *device,
{
	struct kgsl_cmdbatch_sync_event *event;
	unsigned int i;
	unsigned long flags;

	for (i = 0; i < cmdbatch->numsyncs; i++) {
		event = &cmdbatch->synclist[i];
@@ -79,12 +80,16 @@ void kgsl_dump_syncpoints(struct kgsl_device *device,
			break;
		}
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
			spin_lock_irqsave(&event->handle_lock, flags);

			if (event->handle)
				dev_err(device->dev, "  fence: [%pK] %s\n",
					event->handle->fence,
					event->handle->name);
			else
				dev_err(device->dev, "  fence: invalid\n");

			spin_unlock_irqrestore(&event->handle_lock, flags);
			break;
		}
	}
@@ -96,6 +101,7 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
	struct kgsl_cmdbatch *cmdbatch = (struct kgsl_cmdbatch *) data;
	struct kgsl_cmdbatch_sync_event *event;
	unsigned int i;
	unsigned long flags;

	if (cmdbatch == NULL || cmdbatch->context == NULL)
		return;
@@ -124,12 +130,16 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
				i, event->context->id, event->timestamp);
			break;
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
			spin_lock_irqsave(&event->handle_lock, flags);

			if (event->handle != NULL) {
				dev_err(device->dev, "       [%d] FENCE %s\n",
				i, event->handle->fence ?
					event->handle->fence->name : "NULL");
				kgsl_sync_fence_log(event->handle->fence);
			}

			spin_unlock_irqrestore(&event->handle_lock, flags);
			break;
		}
	}
@@ -221,7 +231,7 @@ static inline void _free_memobj_list(struct list_head *list)
void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
{
	unsigned int i;
	unsigned long pending;
	unsigned long pending, flags;

	if (IS_ERR_OR_NULL(cmdbatch))
		return;
@@ -255,8 +265,17 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
				kgsl_cmdbatch_sync_func, event);
			break;
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
			if (kgsl_sync_fence_async_cancel(event->handle))
			spin_lock_irqsave(&event->handle_lock, flags);

			if (kgsl_sync_fence_async_cancel(event->handle)) {
				event->handle = NULL;
				spin_unlock_irqrestore(
						&event->handle_lock, flags);
				kgsl_cmdbatch_put(cmdbatch);
			} else {
				spin_unlock_irqrestore(
						&event->handle_lock, flags);
			}
			break;
		}
	}
@@ -293,12 +312,23 @@ EXPORT_SYMBOL(kgsl_cmdbatch_destroy);
 */
static void kgsl_cmdbatch_sync_fence_func(void *priv)
{
	unsigned long flags;
	struct kgsl_cmdbatch_sync_event *event = priv;

	kgsl_cmdbatch_sync_expire(event->device, event);

	trace_syncpoint_fence_expire(event->cmdbatch,
		event->handle ? event->handle->name : "unknown");

	kgsl_cmdbatch_sync_expire(event->device, event);
	spin_lock_irqsave(&event->handle_lock, flags);

	/*
	 * Setting the event->handle to NULL here make sure that
	 * other function does not dereference a invalid pointer.
	 */
	event->handle = NULL;

	spin_unlock_irqrestore(&event->handle_lock, flags);

	kgsl_cmdbatch_put(event->cmdbatch);
}
@@ -317,6 +347,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
	struct kgsl_cmdbatch_sync_event *event;
	struct sync_fence *fence = NULL;
	unsigned int id;
	unsigned long flags;
	int ret = 0;

	fence = sync_fence_fdget(sync->fd);
@@ -335,19 +366,23 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
	event->device = device;
	event->context = NULL;

	spin_lock_init(&event->handle_lock);
	set_bit(event->id, &cmdbatch->pending);

	trace_syncpoint_fence(cmdbatch, fence->name);

	spin_lock_irqsave(&event->handle_lock, flags);

	event->handle = kgsl_sync_fence_async_wait(sync->fd,
		kgsl_cmdbatch_sync_fence_func, event);

	if (IS_ERR_OR_NULL(event->handle)) {
		ret = PTR_ERR(event->handle);

		clear_bit(event->id, &cmdbatch->pending);
		event->handle = NULL;
		spin_unlock_irqrestore(&event->handle_lock, flags);

		clear_bit(event->id, &cmdbatch->pending);
		kgsl_cmdbatch_put(cmdbatch);

		/*
@@ -357,6 +392,8 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
		*/
		trace_syncpoint_fence_expire(cmdbatch, (ret < 0) ?
				"error" : fence->name);
	} else {
		spin_unlock_irqrestore(&event->handle_lock, flags);
	}

	sync_fence_put(fence);
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -84,6 +84,7 @@ struct kgsl_cmdbatch {
 * @context: Pointer to the KGSL context that owns the cmdbatch
 * @timestamp: Pending timestamp for the event
 * @handle: Pointer to a sync fence handle
 * @handle_lock: Spin lock to protect handle
 * @device: Pointer to the KGSL device
 */
struct kgsl_cmdbatch_sync_event {
@@ -93,6 +94,7 @@ struct kgsl_cmdbatch_sync_event {
	struct kgsl_context *context;
	unsigned int timestamp;
	struct kgsl_sync_fence_waiter *handle;
	spinlock_t handle_lock;
	struct kgsl_device *device;
};