summaryrefslogtreecommitdiff
path: root/mali_pixel/priority_control_manager.c
blob: 4fa20d3dd10ad35d7650765df02ccc55581ff9de (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
154
155
156
157
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2021 Google LLC.
 *
 * Author: Sidath Senanayake <sidaths@google.com>
 */

#include <linux/fs.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/priority_control_manager.h>

/**
 * enum priorities - The different priorities available on the GPU
 */
enum priorities {
	/**
	 * @PRIORITY_RT: Realtime priority
	 */
	PRIORITY_RT = 0,
	/**
	 * @PRIORITY_HIGH: High priority
	 */
	PRIORITY_HIGH,
	/**
	 * @PRIORITY_MED: Medium priority
	 */
	PRIORITY_MED,
	/**
	 * @PRIORITY_LOW: Low priority
	 */
	PRIORITY_LOW,
	/**
	 * @PRIORITY_COUNT: The number of priority classes
	 */
	PRIORITY_COUNT,
};

static const char* priority_name[PRIORITY_COUNT] = {
	"realtime",
	"high",
	"medium",
	"low",
};

/*
 * TODO(b/182907924) Using permissive mode until we have a mechanism to validate priority requests
 * in place.
 */
#define PERMISSIVE_MODE (1)

/**
 * PRIORITY_DEFAULT - The default priority that applications will be set to.
 */
#define PRIORITY_DEFAULT (PRIORITY_MED)

/**
 * pcm_scheduler_priority_check() - Checks in incoming priority request
 *
 * This function returns which priority a context should run at, taking into
 * consideration what the context is requesting.
 *
 * @pcm_dev:            Pointer to the priority control manager.
 * @task:               The task struct of the process requesting the priority
 *                      check.
 * @requested_priority: The priority that the context is requesting.
 *
 * Return: The priority that should be granted to the context.
 */
static int pcm_scheduler_priority_check(struct priority_control_manager_device *pcm_dev,
	struct task_struct *task, int requested_priority)
{
	int ret;
	struct device *dev = pcm_dev->data;
	kuid_t uid = task->cred->uid;

	switch (requested_priority)
	{

	/* For low priority requests, we don't apply any restrictions */
	case PRIORITY_LOW:
	case PRIORITY_MED:
		ret = requested_priority;
		dev_dbg(dev, "UID %d request for %s priority was granted\n",
			__kuid_val(uid), priority_name[requested_priority]);
		break;

	/* Request is for one of the restricted priorities */
	case PRIORITY_HIGH:
	case PRIORITY_RT:
		if (PERMISSIVE_MODE) {
			ret = requested_priority;
			dev_dbg(dev, "UID %d request for %s priority was granted\n",
				__kuid_val(uid), priority_name[requested_priority]);
		} else {
			ret = PRIORITY_DEFAULT;
			dev_warn(dev,
				"UID %d request for %s priority was denied, granted %s instead\n",
				__kuid_val(uid), priority_name[requested_priority],
				priority_name[ret]);
		}
		break;
	default:
		ret = PRIORITY_DEFAULT;
		dev_warn(dev, "UID %d requested an invalid priority (ID: %d), granted %s instead\n",
			__kuid_val(uid), requested_priority, priority_name[ret]);
	}

	return ret;
}

static int priority_control_manager_probe(struct platform_device *pdev)
{
	struct priority_control_manager_device *pcm_dev;

	pcm_dev = kzalloc(sizeof(*pcm_dev), GFP_KERNEL);
	if (!pcm_dev)
		return -ENOMEM;

	pcm_dev->ops.pcm_scheduler_priority_check = pcm_scheduler_priority_check;
	pcm_dev->data = &pdev->dev;

	platform_set_drvdata(pdev, pcm_dev);
	dev_info(&pdev->dev, "Priority control manager probed successfully\n");

	return 0;
}

static int priority_control_manager_remove(struct platform_device *pdev)
{
	struct priority_control_manager_device *pcm_dev = platform_get_drvdata(pdev);

	dev_info(pcm_dev->data, "Priority control manager removed successfully\n");

	return 0;
}

static const struct of_device_id priority_control_manager_dt_ids[] = {
	{ .compatible = "arm,priority-control-manager" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, priority_control_manager_dt_ids);

struct platform_driver priority_control_manager_driver = {
	.probe = priority_control_manager_probe,
	.remove = priority_control_manager_remove,
	.driver = {
		.name = "mali-pcm",
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(priority_control_manager_dt_ids),
		.suppress_bind_attrs = true,
	}
};