/*
 *
 * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */




/*
 * Register backend context / address space management
 */

#include <mali_kbase.h>
#include <mali_kbase_hwaccess_jm.h>
#include <mali_kbase_ctx_sched.h>

/**
 * assign_and_activate_kctx_addr_space - Assign an AS to a context
 * @kbdev: Kbase device
 * @kctx: Kbase context
 * @current_as: Address Space to assign
 *
 * Assign an Address Space (AS) to a context, and add the context to the Policy.
 *
 * This includes
 *   setting up the global runpool_irq structure and the context on the AS,
 *   Activating the MMU on the AS,
 *   Allowing jobs to be submitted on the AS.
 *
 * Context:
 *   kbasep_js_kctx_info.jsctx_mutex held,
 *   kbasep_js_device_data.runpool_mutex held,
 *   AS transaction mutex held,
 *   Runpool IRQ lock held
 */
static void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev,
						struct kbase_context *kctx,
						struct kbase_as *current_as)
{
	struct kbasep_js_device_data *js_devdata = &kbdev->js_data;

	lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex);
	lockdep_assert_held(&js_devdata->runpool_mutex);
	lockdep_assert_held(&kbdev->hwaccess_lock);

	/* Attribute handling */
	kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx);

	/* Allow it to run jobs */
	kbasep_js_set_submit_allowed(js_devdata, kctx);

	kbase_js_runpool_inc_context_count(kbdev, kctx);
}

bool kbase_backend_use_ctx_sched(struct kbase_device *kbdev,
						struct kbase_context *kctx)
{
	int i;

	if (kbdev->hwaccess.active_kctx == kctx) {
		/* Context is already active */
		return true;
	}

	for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
		if (kbdev->as_to_kctx[i] == kctx) {
			/* Context already has ASID - mark as active */
			return true;
		}
	}

	/* Context does not have address space assigned */
	return false;
}

void kbase_backend_release_ctx_irq(struct kbase_device *kbdev,
						struct kbase_context *kctx)
{
	int as_nr = kctx->as_nr;

	if (as_nr == KBASEP_AS_NR_INVALID) {
		WARN(1, "Attempting to release context without ASID\n");
		return;
	}

	lockdep_assert_held(&kbdev->hwaccess_lock);

	if (atomic_read(&kctx->refcount) != 1) {
		WARN(1, "Attempting to release active ASID\n");
		return;
	}

	kbasep_js_clear_submit_allowed(&kbdev->js_data, kctx);

	kbase_ctx_sched_release_ctx(kctx);
	kbase_js_runpool_dec_context_count(kbdev, kctx);
}

void kbase_backend_release_ctx_noirq(struct kbase_device *kbdev,
						struct kbase_context *kctx)
{
}

int kbase_backend_find_and_release_free_address_space(
		struct kbase_device *kbdev, struct kbase_context *kctx)
{
	struct kbasep_js_device_data *js_devdata;
	struct kbasep_js_kctx_info *js_kctx_info;
	unsigned long flags;
	int i;

	js_devdata = &kbdev->js_data;
	js_kctx_info = &kctx->jctx.sched_info;

	mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
	mutex_lock(&js_devdata->runpool_mutex);

	spin_lock_irqsave(&kbdev->hwaccess_lock, flags);

	for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
		struct kbasep_js_kctx_info *as_js_kctx_info;
		struct kbase_context *as_kctx;

		as_kctx = kbdev->as_to_kctx[i];
		as_js_kctx_info = &as_kctx->jctx.sched_info;

		/* Don't release privileged or active contexts, or contexts with
		 * jobs running.
		 * Note that a context will have at least 1 reference (which
		 * was previously taken by kbasep_js_schedule_ctx()) until
		 * descheduled.
		 */
		if (as_kctx && !kbase_ctx_flag(as_kctx, KCTX_PRIVILEGED) &&
			atomic_read(&as_kctx->refcount) == 1) {
			if (!kbasep_js_runpool_retain_ctx_nolock(kbdev,
								as_kctx)) {
				WARN(1, "Failed to retain active context\n");

				spin_unlock_irqrestore(&kbdev->hwaccess_lock,
						flags);
				mutex_unlock(&js_devdata->runpool_mutex);
				mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);

				return KBASEP_AS_NR_INVALID;
			}

			kbasep_js_clear_submit_allowed(js_devdata, as_kctx);

			/* Drop and retake locks to take the jsctx_mutex on the
			 * context we're about to release without violating lock
			 * ordering
			 */
			spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
			mutex_unlock(&js_devdata->runpool_mutex);
			mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);


			/* Release context from address space */
			mutex_lock(&as_js_kctx_info->ctx.jsctx_mutex);
			mutex_lock(&js_devdata->runpool_mutex);

			kbasep_js_runpool_release_ctx_nolock(kbdev, as_kctx);

			if (!kbase_ctx_flag(as_kctx, KCTX_SCHEDULED)) {
				kbasep_js_runpool_requeue_or_kill_ctx(kbdev,
								as_kctx,
								true);

				mutex_unlock(&js_devdata->runpool_mutex);
				mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex);

				return i;
			}

			/* Context was retained while locks were dropped,
			 * continue looking for free AS */

			mutex_unlock(&js_devdata->runpool_mutex);
			mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex);

			mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
			mutex_lock(&js_devdata->runpool_mutex);
			spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
		}
	}

	spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);

	mutex_unlock(&js_devdata->runpool_mutex);
	mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);

	return KBASEP_AS_NR_INVALID;
}

bool kbase_backend_use_ctx(struct kbase_device *kbdev,
				struct kbase_context *kctx,
				int as_nr)
{
	struct kbasep_js_device_data *js_devdata;
	struct kbase_as *new_address_space = NULL;

	js_devdata = &kbdev->js_data;

	if (kbdev->hwaccess.active_kctx == kctx) {
		WARN(1, "Context is already scheduled in\n");
		return false;
	}

	new_address_space = &kbdev->as[as_nr];

	lockdep_assert_held(&js_devdata->runpool_mutex);
	lockdep_assert_held(&kbdev->mmu_hw_mutex);
	lockdep_assert_held(&kbdev->hwaccess_lock);

	assign_and_activate_kctx_addr_space(kbdev, kctx, new_address_space);

	if (kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) {
		/* We need to retain it to keep the corresponding address space
		 */
		kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
	}

	return true;
}

