blob: db2b585087fb4105b7a1c2acbfacf6b7cade6101 [file] [log] [blame]
Shrenuj Bansala419c792016-10-20 14:05:11 -07001/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/sysfs.h>
14#include <linux/device.h>
15
16#include "kgsl_device.h"
17#include "adreno.h"
18
19struct adreno_sysfs_attribute {
20 struct device_attribute attr;
21 unsigned int (*show)(struct adreno_device *adreno_dev);
22 int (*store)(struct adreno_device *adreno_dev, unsigned int val);
23};
24
25#define _ADRENO_SYSFS_ATTR(_name, __show, __store) \
26struct adreno_sysfs_attribute adreno_attr_##_name = { \
27 .attr = __ATTR(_name, 0644, __show, __store), \
28 .show = _ ## _name ## _show, \
29 .store = _ ## _name ## _store, \
30}
31
32#define ADRENO_SYSFS_ATTR(_a) \
33 container_of((_a), struct adreno_sysfs_attribute, attr)
34
35static struct adreno_device *_get_adreno_dev(struct device *dev)
36{
37 struct kgsl_device *device = kgsl_device_from_dev(dev);
38
39 return device ? ADRENO_DEVICE(device) : NULL;
40}
41
42static int _ft_policy_store(struct adreno_device *adreno_dev,
43 unsigned int val)
44{
45 adreno_dev->ft_policy = val & KGSL_FT_POLICY_MASK;
46 return 0;
47}
48
49static unsigned int _ft_policy_show(struct adreno_device *adreno_dev)
50{
51 return adreno_dev->ft_policy;
52}
53
54static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev,
55 unsigned int val)
56{
57 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
58 int ret = 0;
59
60 mutex_lock(&device->mutex);
61 val &= KGSL_FT_PAGEFAULT_MASK;
62
63 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
64 ret = kgsl_mmu_set_pagefault_policy(&device->mmu,
65 (unsigned long) val);
66
67 if (ret == 0)
68 adreno_dev->ft_pf_policy = val;
69
70 mutex_unlock(&device->mutex);
71
72 return 0;
73}
74
75static unsigned int _ft_pagefault_policy_show(struct adreno_device *adreno_dev)
76{
77 return adreno_dev->ft_pf_policy;
78}
79
Sushmita Susheelendrab1976682016-11-07 14:21:11 -070080static int _gpu_llc_slice_enable_store(struct adreno_device *adreno_dev,
81 unsigned int val)
82{
83 adreno_dev->gpu_llc_slice_enable = val ? true : false;
84 return 0;
85}
86
87static unsigned int _gpu_llc_slice_enable_show(struct adreno_device *adreno_dev)
88{
89 return adreno_dev->gpu_llc_slice_enable;
90}
91
Shrenuj Bansala419c792016-10-20 14:05:11 -070092static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev,
93 unsigned int val)
94{
95 adreno_dev->long_ib_detect = val;
96 return 0;
97}
98
99static unsigned int _ft_long_ib_detect_show(struct adreno_device *adreno_dev)
100{
101 return adreno_dev->long_ib_detect;
102}
103
104static int _ft_hang_intr_status_store(struct adreno_device *adreno_dev,
105 unsigned int val)
106{
107 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
108 int ret = 0;
109
110 if (val == test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv))
111 return 0;
112
113 mutex_lock(&device->mutex);
114 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
115
116 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
117 kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
118 adreno_irqctrl(adreno_dev, 1);
119 } else if (device->state == KGSL_STATE_INIT) {
120 ret = -EACCES;
121 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
122 }
123
124 mutex_unlock(&device->mutex);
125 return ret;
126}
127
128static unsigned int _ft_hang_intr_status_show(struct adreno_device *adreno_dev)
129{
130 return test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
131}
132
133static int _pwrctrl_store(struct adreno_device *adreno_dev,
134 unsigned int val, unsigned int flag)
135{
136 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
137
138 if (val == test_bit(flag, &adreno_dev->pwrctrl_flag))
139 return 0;
140
141 mutex_lock(&device->mutex);
142
143 /* Power down the GPU before changing the state */
144 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
145 change_bit(flag, &adreno_dev->pwrctrl_flag);
146 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
147
148 mutex_unlock(&device->mutex);
149
150 return 0;
151}
152
153static int _preemption_store(struct adreno_device *adreno_dev,
154 unsigned int val)
155{
156 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
157
158 if (test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv) == val)
159 return 0;
160
161 mutex_lock(&device->mutex);
162
163 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
164 change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
165 adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);
166 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
167
168 mutex_unlock(&device->mutex);
169
170 return 0;
171}
172
173static unsigned int _preemption_show(struct adreno_device *adreno_dev)
174{
175 return adreno_is_preemption_enabled(adreno_dev);
176}
177
178static int _hwcg_store(struct adreno_device *adreno_dev,
179 unsigned int val)
180{
181 return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL);
182}
183
184static unsigned int _hwcg_show(struct adreno_device *adreno_dev)
185{
186 return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag);
187}
188
189static int _throttling_store(struct adreno_device *adreno_dev,
190 unsigned int val)
191{
192 return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL);
193}
194
195static unsigned int _throttling_show(struct adreno_device *adreno_dev)
196{
197 return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag);
198}
199
200static int _sptp_pc_store(struct adreno_device *adreno_dev,
201 unsigned int val)
202{
203 return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL);
204}
205
206static unsigned int _sptp_pc_show(struct adreno_device *adreno_dev)
207{
208 return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag);
209}
210
211static int _lm_store(struct adreno_device *adreno_dev, unsigned int val)
212{
213 return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL);
214}
215
216static unsigned int _lm_show(struct adreno_device *adreno_dev)
217{
218 return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag);
219}
220
221static ssize_t _sysfs_store_u32(struct device *dev,
222 struct device_attribute *attr,
223 const char *buf, size_t count)
224{
225 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
226 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
227 unsigned int val = 0;
228 int ret;
229
230 if (adreno_dev == NULL)
231 return 0;
232
233 ret = kgsl_sysfs_store(buf, &val);
234
235 if (!ret && _attr->store)
236 ret = _attr->store(adreno_dev, val);
237
238 return (ssize_t) ret < 0 ? ret : count;
239}
240
241static ssize_t _sysfs_show_u32(struct device *dev,
242 struct device_attribute *attr,
243 char *buf)
244{
245 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
246 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
247 unsigned int val = 0;
248
249 if (adreno_dev == NULL)
250 return 0;
251
252 if (_attr->show)
253 val = _attr->show(adreno_dev);
254
255 return snprintf(buf, PAGE_SIZE, "0x%X\n", val);
256}
257
258static ssize_t _sysfs_store_bool(struct device *dev,
259 struct device_attribute *attr,
260 const char *buf, size_t count)
261{
262 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
263 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
264 unsigned int val = 0;
265 int ret;
266
267 if (adreno_dev == NULL)
268 return 0;
269
270 ret = kgsl_sysfs_store(buf, &val);
271
272 if (!ret && _attr->store)
273 ret = _attr->store(adreno_dev, val ? 1 : 0);
274
275 return (ssize_t) ret < 0 ? ret : count;
276}
277
278static ssize_t _sysfs_show_bool(struct device *dev,
279 struct device_attribute *attr,
280 char *buf)
281{
282 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
283 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
284 unsigned int val = 0;
285
286 if (adreno_dev == NULL)
287 return 0;
288
289 if (_attr->show)
290 val = _attr->show(adreno_dev);
291
292 return snprintf(buf, PAGE_SIZE, "%d\n", val);
293}
294
295#define ADRENO_SYSFS_BOOL(_name) \
296 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_bool, _sysfs_store_bool)
297
298#define ADRENO_SYSFS_U32(_name) \
299 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_u32, _sysfs_store_u32)
300
301static ADRENO_SYSFS_U32(ft_policy);
302static ADRENO_SYSFS_U32(ft_pagefault_policy);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700303static ADRENO_SYSFS_BOOL(ft_long_ib_detect);
304static ADRENO_SYSFS_BOOL(ft_hang_intr_status);
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700305static ADRENO_SYSFS_BOOL(gpu_llc_slice_enable);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700306
307static DEVICE_INT_ATTR(wake_nice, 0644, adreno_wake_nice);
308static DEVICE_INT_ATTR(wake_timeout, 0644, adreno_wake_timeout);
309
310static ADRENO_SYSFS_BOOL(sptp_pc);
311static ADRENO_SYSFS_BOOL(lm);
312static ADRENO_SYSFS_BOOL(preemption);
313static ADRENO_SYSFS_BOOL(hwcg);
314static ADRENO_SYSFS_BOOL(throttling);
315
316
317
318static const struct device_attribute *_attr_list[] = {
319 &adreno_attr_ft_policy.attr,
320 &adreno_attr_ft_pagefault_policy.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700321 &adreno_attr_ft_long_ib_detect.attr,
322 &adreno_attr_ft_hang_intr_status.attr,
323 &dev_attr_wake_nice.attr,
324 &dev_attr_wake_timeout.attr,
325 &adreno_attr_sptp_pc.attr,
326 &adreno_attr_lm.attr,
327 &adreno_attr_preemption.attr,
328 &adreno_attr_hwcg.attr,
329 &adreno_attr_throttling.attr,
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700330 &adreno_attr_gpu_llc_slice_enable.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700331 NULL,
332};
333
334/* Add a ppd directory for controlling different knobs from sysfs */
335struct adreno_ppd_attribute {
336 struct attribute attr;
337 ssize_t (*show)(struct kgsl_device *device, char *buf);
338 ssize_t (*store)(struct kgsl_device *device, const char *buf,
339 size_t count);
340};
341
342#define PPD_ATTR(_name, _mode, _show, _store) \
343struct adreno_ppd_attribute attr_##_name = { \
344 .attr = { .name = __stringify(_name), .mode = _mode }, \
345 .show = _show, \
346 .store = _store, \
347}
348
349#define to_ppd_attr(a) \
350container_of((a), struct adreno_ppd_attribute, attr)
351
352#define kobj_to_device(a) \
353container_of((a), struct kgsl_device, ppd_kobj)
354
355static ssize_t ppd_enable_store(struct kgsl_device *device,
356 const char *buf, size_t count)
357{
358 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
359 unsigned int ppd_on = 0;
360 int ret;
361
362 if (!adreno_is_a430v2(adreno_dev) ||
363 !ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
364 return count;
365
366 ret = kgsl_sysfs_store(buf, &ppd_on);
367 if (ret < 0)
368 return ret;
369
370 ppd_on = (ppd_on) ? 1 : 0;
371
372 if (ppd_on == test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag))
373 return count;
374
375 mutex_lock(&device->mutex);
376
377 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
378 change_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag);
379 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
380
381 mutex_unlock(&device->mutex);
382 return count;
383}
384
385static ssize_t ppd_enable_show(struct kgsl_device *device,
386 char *buf)
387{
388 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
389
390 return snprintf(buf, PAGE_SIZE, "%u\n",
391 test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag));
392}
393/* Add individual ppd attributes here */
394static PPD_ATTR(enable, 0644, ppd_enable_show, ppd_enable_store);
395
396static ssize_t ppd_sysfs_show(struct kobject *kobj,
397 struct attribute *attr, char *buf)
398{
399 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
400 struct kgsl_device *device = kobj_to_device(kobj);
401 ssize_t ret = -EIO;
402
403 if (device != NULL && pattr->show != NULL)
404 ret = pattr->show(device, buf);
405
406 return ret;
407}
408
409static ssize_t ppd_sysfs_store(struct kobject *kobj,
410 struct attribute *attr, const char *buf, size_t count)
411{
412 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
413 struct kgsl_device *device = kobj_to_device(kobj);
414 ssize_t ret = -EIO;
415
416 if (device != NULL && pattr->store != NULL)
417 ret = pattr->store(device, buf, count);
418
419 return ret;
420}
421
422static const struct sysfs_ops ppd_sysfs_ops = {
423 .show = ppd_sysfs_show,
424 .store = ppd_sysfs_store,
425};
426
427static struct kobj_type ktype_ppd = {
428 .sysfs_ops = &ppd_sysfs_ops,
429};
430
431static void ppd_sysfs_close(struct adreno_device *adreno_dev)
432{
433 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
434
435 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
436 return;
437
438 sysfs_remove_file(&device->ppd_kobj, &attr_enable.attr);
439 kobject_put(&device->ppd_kobj);
440}
441
442static int ppd_sysfs_init(struct adreno_device *adreno_dev)
443{
444 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
445 int ret;
446
447 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
448 return -ENODEV;
449
450 ret = kobject_init_and_add(&device->ppd_kobj, &ktype_ppd,
451 &device->dev->kobj, "ppd");
452
453 if (ret == 0)
454 ret = sysfs_create_file(&device->ppd_kobj, &attr_enable.attr);
455
456 return ret;
457}
458
459/**
460 * adreno_sysfs_close() - Take down the adreno sysfs files
461 * @adreno_dev: Pointer to the adreno device
462 *
463 * Take down the sysfs files on when the device goes away
464 */
465void adreno_sysfs_close(struct adreno_device *adreno_dev)
466{
467 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
468
469 ppd_sysfs_close(adreno_dev);
470 kgsl_remove_device_sysfs_files(device->dev, _attr_list);
471}
472
473/**
474 * adreno_sysfs_init() - Initialize adreno sysfs files
475 * @adreno_dev: Pointer to the adreno device
476 *
477 * Initialize many of the adreno specific sysfs files especially for fault
478 * tolerance and power control
479 */
480int adreno_sysfs_init(struct adreno_device *adreno_dev)
481{
482 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
483 int ret;
484
485 ret = kgsl_create_device_sysfs_files(device->dev, _attr_list);
486
487 /* Add the PPD directory and files */
488 if (ret == 0)
489 ppd_sysfs_init(adreno_dev);
490
491 return 0;
492}
493