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

Commit c73b3be9 authored by Tarun Karra's avatar Tarun Karra
Browse files

msm: kgsl: Add new API's to track device mutex owner



Add new API's kgsl_mutex_lock/unlock to track device mutex owner.
Mutex owner is an atomic variable and all operations set/clear on
it are also atomic to avoid any race conditions.

If a thread tries to acquire the mutex using new API, try to acquire
the mutex only if mutex owner is not same as current thread. This is
to prevent deadlocks which can happen if a thread tries to acquire
mutex with mutex held.

Change-Id: I3da4d0427ede5458f6a663043c57a4799b72d8fd
Signed-off-by: default avatarTarun Karra <tkarra@codeaurora.org>
parent bfaea932
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ static void adreno_input_work(struct work_struct *work)
			struct adreno_device, input_work);
	struct kgsl_device *device = &adreno_dev->dev;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	device->flags |= KGSL_FLAG_WAKE_ON_TOUCH;

@@ -150,7 +150,7 @@ static void adreno_input_work(struct work_struct *work)
	 */
	mod_timer(&device->idle_timer,
		jiffies + msecs_to_jiffies(_wake_timeout));
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
}

/*
@@ -1914,7 +1914,7 @@ static void adreno_start_work(struct work_struct *work)
	/* Nice ourselves to be higher priority but not too high priority */
	set_user_nice(current, _wake_nice);

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	/*
	 *  If adreno start is already called, no need to call it again
	 *  it can lead to unpredictable behavior if we try to start
@@ -1934,7 +1934,7 @@ static void adreno_start_work(struct work_struct *work)
		_status = _adreno_start(adreno_dev);
	else
		_status = 0;
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
}

/**
@@ -1959,9 +1959,9 @@ static int adreno_start(struct kgsl_device *device, int priority)
	 * higher priority work queue and wait for it to finish
	 */
	queue_work(adreno_wq, &adreno_dev->start_work);
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	flush_work(&adreno_dev->start_work);
	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	return _status;
}
@@ -2315,7 +2315,7 @@ static ssize_t _ft_hang_intr_status_store(struct device *dev,
		return 0;
	adreno_dev = ADRENO_DEVICE(device);

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	ret = kgsl_sysfs_store(buf, &new_setting);
	if (ret)
		goto done;
@@ -2363,7 +2363,7 @@ static ssize_t _ft_hang_intr_status_store(struct device *dev,
		}
	}
done:
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	return ret < 0 ? ret : count;
}

+9 −9
Original line number Diff line number Diff line
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2014, 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
@@ -40,7 +40,7 @@ ssize_t adreno_coresight_show_register(struct device *dev,
	 * otherwise report 0
	 */

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	if (test_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv)) {

		/*
@@ -59,7 +59,7 @@ ssize_t adreno_coresight_show_register(struct device *dev,

		val = cattr->reg->value;
	}
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return snprintf(buf, PAGE_SIZE, "0x%X", val);
}
@@ -85,7 +85,7 @@ ssize_t adreno_coresight_store_register(struct device *dev,
	if (ret)
		return ret;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	/* Ignore writes while coresight is off */
	if (!test_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv))
@@ -104,7 +104,7 @@ ssize_t adreno_coresight_store_register(struct device *dev,
	}

out:
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	return size;
}

@@ -137,7 +137,7 @@ static void adreno_coresight_disable(struct coresight_device *csdev)
	if (coresight == NULL)
		return;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	if (!kgsl_active_count_get(device)) {
		for (i = 0; i < coresight->count; i++)
@@ -149,7 +149,7 @@ static void adreno_coresight_disable(struct coresight_device *csdev)

	clear_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv);

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
}

static int _adreno_coresight_get(struct adreno_device *adreno_dev)
@@ -218,7 +218,7 @@ static int adreno_coresight_enable(struct coresight_device *csdev)
	if (coresight == NULL)
		return -ENODEV;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	if (!test_and_set_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv)) {
		int i;

@@ -231,7 +231,7 @@ static int adreno_coresight_enable(struct coresight_device *csdev)
		ret = _adreno_coresight_set(adreno_dev);
	}

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return ret;
}
+15 −15
Original line number Diff line number Diff line
@@ -298,7 +298,7 @@ static int sendcmd(struct adreno_device *adreno_dev,

	dispatcher->inflight++;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	if (dispatcher->inflight == 1 &&
			!test_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv)) {
@@ -306,7 +306,7 @@ static int sendcmd(struct adreno_device *adreno_dev,
		ret = kgsl_active_count_get(device);
		if (ret) {
			dispatcher->inflight--;
			mutex_unlock(&device->mutex);
			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
			return ret;
		}

@@ -330,7 +330,7 @@ static int sendcmd(struct adreno_device *adreno_dev,
		}
	}

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	if (ret) {
		dispatcher->inflight--;
@@ -903,10 +903,10 @@ static void remove_invalidated_cmdbatches(struct kgsl_device *device,
			drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
			replay[i] = NULL;

			mutex_lock(&device->mutex);
			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
			kgsl_cancel_events_timestamp(device,
				&cmd->context->events, cmd->timestamp);
			mutex_unlock(&device->mutex);
			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

			kgsl_cmdbatch_destroy(cmd);
		}
@@ -1008,7 +1008,7 @@ static int dispatcher_do_fault(struct kgsl_device *device)
	del_timer_sync(&dispatcher->timer);
	del_timer_sync(&dispatcher->fault_timer);

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	/* hang opcode */
	kgsl_cffdump_hang(device);
@@ -1040,7 +1040,7 @@ static int dispatcher_do_fault(struct kgsl_device *device)
		kgsl_device_snapshot(device, 1);
	}

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	/* Allocate memory to store the inflight commands */
	replay = kzalloc(sizeof(*replay) * dispatcher->inflight, GFP_KERNEL);
@@ -1235,12 +1235,12 @@ replay:
	dispatcher->head = dispatcher->tail = 0;

	/* Reset the GPU */
	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	/* make sure halt is not set during recovery */
	halt = adreno_gpu_halt(adreno_dev);
	adreno_set_gpu_halt(adreno_dev, 0);
	ret = adreno_reset(device);
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	/* if any other fault got in until reset then ignore */
	fault = atomic_xchg(&dispatcher->fault, 0);

@@ -1494,12 +1494,12 @@ done:
		mod_timer(&dispatcher->timer, cmdbatch->expires);

		/* There are still things in flight - update the idle counts */
		mutex_lock(&device->mutex);
		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
		kgsl_pwrscale_update(device);
		mutex_unlock(&device->mutex);
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	} else {
		/* There is nothing left in the pipeline.  Shut 'er down boys */
		mutex_lock(&device->mutex);
		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
		complete_all(&dispatcher->idle_gate);
		/*
		 * Stop the fault timer before decrementing the active count to
@@ -1513,7 +1513,7 @@ done:
			clear_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv);
		}

		mutex_unlock(&device->mutex);
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	}

	mutex_unlock(&dispatcher->mutex);
@@ -1852,7 +1852,7 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev)

	adreno_set_gpu_halt(adreno_dev, 1);

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	ret = wait_for_completion_timeout(&dispatcher->idle_gate,
			msecs_to_jiffies(ADRENO_IDLE_TIMEOUT));
@@ -1864,7 +1864,7 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev)
		ret = 0;
	}

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	adreno_set_gpu_halt(adreno_dev, 0);
	/*
	 * requeue dispatcher work to resubmit pending commands
+8 −8
Original line number Diff line number Diff line
@@ -59,9 +59,9 @@ static int _check_context_timestamp(struct kgsl_device *device,
		drawctxt->state != ADRENO_CONTEXT_STATE_ACTIVE)
		return 1;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	ret = kgsl_check_timestamp(device, &drawctxt->base, timestamp);
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return ret;
}
@@ -115,7 +115,7 @@ int adreno_drawctxt_wait(struct adreno_device *adreno_dev,
	io = (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
		? 0 : 1;

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	if (timeout) {
		long ret_temp;
@@ -136,7 +136,7 @@ int adreno_drawctxt_wait(struct adreno_device *adreno_dev,
				io);
	}

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	/* -EDEADLK if the context was invalidated while we were waiting */
	if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID)
@@ -204,7 +204,7 @@ static int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev,
		goto done;
	}

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	if (timeout) {
		ret = (int) wait_event_timeout(drawctxt->waiting,
@@ -220,7 +220,7 @@ static int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev,
			_check_global_timestamp(device, drawctxt, timestamp));
	}

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	if (ret)
		kgsl_cancel_events_timestamp(device, &device->global_events,
@@ -272,10 +272,10 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device,

		mutex_unlock(&drawctxt->mutex);

		mutex_lock(&device->mutex);
		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
		kgsl_cancel_events_timestamp(device, &context->events,
			cmdbatch->timestamp);
		mutex_unlock(&device->mutex);
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

		kgsl_cmdbatch_destroy(cmdbatch);
		mutex_lock(&drawctxt->mutex);
+15 −15
Original line number Diff line number Diff line
@@ -480,9 +480,9 @@ static int profile_enable_get(void *data, u64 *val)
	struct kgsl_device *device = data;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	*val = adreno_profile_enabled(&adreno_dev->profile);
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return 0;
}
@@ -493,13 +493,13 @@ static int profile_enable_set(void *data, u64 val)
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_profile *profile = &adreno_dev->profile;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	profile->enabled = val;

	check_close_profile(profile);

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return 0;
}
@@ -515,11 +515,11 @@ static ssize_t profile_assignments_read(struct file *filep,
	char *buf, *pos;
	ssize_t size = 0;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	buf = kmalloc(max_size, GFP_KERNEL);
	if (!buf) {
		mutex_unlock(&device->mutex);
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
		return -ENOMEM;
	}

@@ -539,7 +539,7 @@ static ssize_t profile_assignments_read(struct file *filep,

	kfree(buf);

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	return size;
}

@@ -669,7 +669,7 @@ static ssize_t profile_assignments_write(struct file *filep,
	if (len >= PAGE_SIZE || len == 0)
		return -EINVAL;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	if (adreno_profile_enabled(profile)) {
		size = -EINVAL;
@@ -735,7 +735,7 @@ error_free:
error_put:
	kgsl_active_count_put(device);
error_unlock:
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	return size;
}

@@ -897,7 +897,7 @@ static ssize_t profile_pipe_print(struct file *filep, char __user *ubuf,
	 * for each perf counter <cntr_reg_off> <start hi & lo> <end hi & low>
	 */

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	while (1) {
		/* process any results that are available into the log_buffer */
@@ -919,10 +919,10 @@ static ssize_t profile_pipe_print(struct file *filep, char __user *ubuf,
			}
		}

		mutex_unlock(&device->mutex);
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ / 10);
		mutex_lock(&device->mutex);
		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

		if (signal_pending(current)) {
			status = 0;
@@ -931,7 +931,7 @@ static ssize_t profile_pipe_print(struct file *filep, char __user *ubuf,
	}

	check_close_profile(profile);
	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return status;
}
@@ -944,7 +944,7 @@ static int profile_groups_print(struct seq_file *s, void *unused)
	struct adreno_perfcount_group *group;
	int i, j, used;

	mutex_lock(&device->mutex);
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

	for (i = 0; i < counters->group_count; ++i) {
		group = &(counters->groups[i]);
@@ -960,7 +960,7 @@ static int profile_groups_print(struct seq_file *s, void *unused)
			group->reg_count, used);
	}

	mutex_unlock(&device->mutex);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	return 0;
}
Loading