summaryrefslogtreecommitdiff
path: root/mali_kbase/mali_kbase_jm.c
blob: 1ac5cd3eafff29086e4024892a193370dd9e3cab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
 *
 * (C) COPYRIGHT 2013-2022 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 license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 */

/*
 * HW access job manager common APIs
 */

#include <mali_kbase.h>
#include "mali_kbase_hwaccess_jm.h"
#include "mali_kbase_jm.h"

#if !MALI_USE_CSF
/**
 * kbase_jm_next_job() - Attempt to run the next @nr_jobs_to_submit jobs on slot
 *			 @js on the active context.
 * @kbdev:		Device pointer
 * @js:			Job slot to run on
 * @nr_jobs_to_submit:	Number of jobs to attempt to submit
 *
 * Return: true if slot can still be submitted on, false if slot is now full.
 */
static bool kbase_jm_next_job(struct kbase_device *kbdev, unsigned int js, int nr_jobs_to_submit)
{
	struct kbase_context *kctx;
	int i;

	kctx = kbdev->hwaccess.active_kctx[js];
	dev_dbg(kbdev->dev, "Trying to run the next %d jobs in kctx %pK (s:%u)\n",
		nr_jobs_to_submit, (void *)kctx, js);

	if (!kctx)
		return true;

	for (i = 0; i < nr_jobs_to_submit; i++) {
		struct kbase_jd_atom *katom = kbase_js_pull(kctx, js);

		if (!katom)
			return true; /* Context has no jobs on this slot */

		kbase_backend_run_atom(kbdev, katom);
	}

	dev_dbg(kbdev->dev, "Slot ringbuffer should now be full (s:%u)\n", js);
	return false;
}

u32 kbase_jm_kick(struct kbase_device *kbdev, u32 js_mask)
{
	u32 ret_mask = 0;

	lockdep_assert_held(&kbdev->hwaccess_lock);
	dev_dbg(kbdev->dev, "JM kick slot mask 0x%x\n", js_mask);

	while (js_mask) {
		unsigned int js = ffs(js_mask) - 1;
		int nr_jobs_to_submit = kbase_backend_slot_free(kbdev, js);

		if (kbase_jm_next_job(kbdev, js, nr_jobs_to_submit))
			ret_mask |= (1 << js);

		js_mask &= ~(1 << js);
	}

	dev_dbg(kbdev->dev, "Can still submit to mask 0x%x\n", ret_mask);
	return ret_mask;
}

void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask)
{
	struct kbasep_js_device_data *js_devdata = &kbdev->js_data;

	lockdep_assert_held(&kbdev->hwaccess_lock);

	if (!down_trylock(&js_devdata->schedule_sem)) {
		kbase_jm_kick(kbdev, js_mask);
		up(&js_devdata->schedule_sem);
	}
}

void kbase_jm_try_kick_all(struct kbase_device *kbdev)
{
	struct kbasep_js_device_data *js_devdata = &kbdev->js_data;

	lockdep_assert_held(&kbdev->hwaccess_lock);

	if (!down_trylock(&js_devdata->schedule_sem)) {
		kbase_jm_kick_all(kbdev);
		up(&js_devdata->schedule_sem);
	}
}

void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)
{
	unsigned int js;

	lockdep_assert_held(&kbdev->hwaccess_lock);

	for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) {
		if (kbdev->hwaccess.active_kctx[js] == kctx) {
			dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%u)\n", (void *)kctx,
				js);
			kbdev->hwaccess.active_kctx[js] = NULL;
		}
	}
}

struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev,
				struct kbase_jd_atom *katom)
{
	lockdep_assert_held(&kbdev->hwaccess_lock);

	dev_dbg(kbdev->dev, "Atom %pK is returning with event code 0x%x\n",
		(void *)katom, katom->event_code);

	KBASE_KTRACE_ADD_JM(kbdev, JM_RETURN_ATOM_TO_JS, katom->kctx, katom,
			    katom->jc, katom->event_code);

	if (katom->event_code != BASE_JD_EVENT_STOPPED &&
			katom->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT) {
		return kbase_js_complete_atom(katom, NULL);
	}

	kbase_js_unpull(katom->kctx, katom);

	return NULL;
}

struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev,
		struct kbase_jd_atom *katom, ktime_t *end_timestamp)
{
	lockdep_assert_held(&kbdev->hwaccess_lock);

	return kbase_js_complete_atom(katom, end_timestamp);
}
#endif /* !MALI_USE_CSF */