blob: b06aa98a9a95a6bef3cacf726c40972e41d8fd71 [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
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060054static int _preempt_level_store(struct adreno_device *adreno_dev,
55 unsigned int val)
56{
57 if (val <= 2)
58 adreno_dev->preempt_level = val;
59 return 0;
60}
61
62static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
63{
64 return adreno_dev->preempt_level;
65}
66
67static int _usesgmem_store(struct adreno_device *adreno_dev,
68 unsigned int val)
69{
70 adreno_dev->usesgmem = val ? 1 : 0;
71 return 0;
72}
73
74static unsigned int _usesgmem_show(struct adreno_device *adreno_dev)
75{
76 return adreno_dev->usesgmem;
77}
78
79static int _skipsaverestore_store(struct adreno_device *adreno_dev,
80 unsigned int val)
81{
82 adreno_dev->skipsaverestore = val ? 1 : 0;
83 return 0;
84}
85
86static unsigned int _skipsaverestore_show(struct adreno_device *adreno_dev)
87{
88 return adreno_dev->skipsaverestore;
89}
90
Shrenuj Bansala419c792016-10-20 14:05:11 -070091static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev,
92 unsigned int val)
93{
94 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
95 int ret = 0;
96
97 mutex_lock(&device->mutex);
98 val &= KGSL_FT_PAGEFAULT_MASK;
99
100 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
101 ret = kgsl_mmu_set_pagefault_policy(&device->mmu,
102 (unsigned long) val);
103
104 if (ret == 0)
105 adreno_dev->ft_pf_policy = val;
106
107 mutex_unlock(&device->mutex);
108
109 return 0;
110}
111
112static unsigned int _ft_pagefault_policy_show(struct adreno_device *adreno_dev)
113{
114 return adreno_dev->ft_pf_policy;
115}
116
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700117static int _gpu_llc_slice_enable_store(struct adreno_device *adreno_dev,
118 unsigned int val)
119{
120 adreno_dev->gpu_llc_slice_enable = val ? true : false;
121 return 0;
122}
123
124static unsigned int _gpu_llc_slice_enable_show(struct adreno_device *adreno_dev)
125{
126 return adreno_dev->gpu_llc_slice_enable;
127}
128
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700129static int _gpuhtw_llc_slice_enable_store(struct adreno_device *adreno_dev,
130 unsigned int val)
131{
132 adreno_dev->gpuhtw_llc_slice_enable = val ? true : false;
133 return 0;
134}
135
136static unsigned int
137_gpuhtw_llc_slice_enable_show(struct adreno_device *adreno_dev)
138{
139 return adreno_dev->gpuhtw_llc_slice_enable;
140}
141
Shrenuj Bansala419c792016-10-20 14:05:11 -0700142static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev,
143 unsigned int val)
144{
145 adreno_dev->long_ib_detect = val;
146 return 0;
147}
148
149static unsigned int _ft_long_ib_detect_show(struct adreno_device *adreno_dev)
150{
151 return adreno_dev->long_ib_detect;
152}
153
154static int _ft_hang_intr_status_store(struct adreno_device *adreno_dev,
155 unsigned int val)
156{
157 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
158 int ret = 0;
159
160 if (val == test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv))
161 return 0;
162
163 mutex_lock(&device->mutex);
164 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
165
166 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
167 kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
168 adreno_irqctrl(adreno_dev, 1);
169 } else if (device->state == KGSL_STATE_INIT) {
170 ret = -EACCES;
171 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
172 }
173
174 mutex_unlock(&device->mutex);
175 return ret;
176}
177
178static unsigned int _ft_hang_intr_status_show(struct adreno_device *adreno_dev)
179{
180 return test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
181}
182
183static int _pwrctrl_store(struct adreno_device *adreno_dev,
184 unsigned int val, unsigned int flag)
185{
186 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
187
188 if (val == test_bit(flag, &adreno_dev->pwrctrl_flag))
189 return 0;
190
191 mutex_lock(&device->mutex);
192
193 /* Power down the GPU before changing the state */
194 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
195 change_bit(flag, &adreno_dev->pwrctrl_flag);
196 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
197
198 mutex_unlock(&device->mutex);
199
200 return 0;
201}
202
203static int _preemption_store(struct adreno_device *adreno_dev,
204 unsigned int val)
205{
206 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
207
Harshdeep Dhatt38e57d72017-08-30 13:24:07 -0600208 if (test_bit(ADRENO_DEVICE_PREEMPTION_EXECUTION,
209 &adreno_dev->priv) == val)
Shrenuj Bansala419c792016-10-20 14:05:11 -0700210 return 0;
211
212 mutex_lock(&device->mutex);
213
214 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
Harshdeep Dhatt38e57d72017-08-30 13:24:07 -0600215 change_bit(ADRENO_DEVICE_PREEMPTION_EXECUTION, &adreno_dev->priv);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700216 adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);
217 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
218
219 mutex_unlock(&device->mutex);
220
221 return 0;
222}
223
224static unsigned int _preemption_show(struct adreno_device *adreno_dev)
225{
Harshdeep Dhatt38e57d72017-08-30 13:24:07 -0600226 return adreno_is_preemption_execution_enabled(adreno_dev);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700227}
228
229static int _hwcg_store(struct adreno_device *adreno_dev,
230 unsigned int val)
231{
232 return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL);
233}
234
235static unsigned int _hwcg_show(struct adreno_device *adreno_dev)
236{
237 return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag);
238}
239
240static int _throttling_store(struct adreno_device *adreno_dev,
241 unsigned int val)
242{
243 return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL);
244}
245
246static unsigned int _throttling_show(struct adreno_device *adreno_dev)
247{
248 return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag);
249}
250
251static int _sptp_pc_store(struct adreno_device *adreno_dev,
252 unsigned int val)
253{
254 return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL);
255}
256
257static unsigned int _sptp_pc_show(struct adreno_device *adreno_dev)
258{
259 return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag);
260}
261
262static int _lm_store(struct adreno_device *adreno_dev, unsigned int val)
263{
264 return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL);
265}
266
267static unsigned int _lm_show(struct adreno_device *adreno_dev)
268{
269 return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag);
270}
271
272static ssize_t _sysfs_store_u32(struct device *dev,
273 struct device_attribute *attr,
274 const char *buf, size_t count)
275{
276 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
277 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
278 unsigned int val = 0;
279 int ret;
280
281 if (adreno_dev == NULL)
282 return 0;
283
284 ret = kgsl_sysfs_store(buf, &val);
285
286 if (!ret && _attr->store)
287 ret = _attr->store(adreno_dev, val);
288
289 return (ssize_t) ret < 0 ? ret : count;
290}
291
292static ssize_t _sysfs_show_u32(struct device *dev,
293 struct device_attribute *attr,
294 char *buf)
295{
296 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
297 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
298 unsigned int val = 0;
299
300 if (adreno_dev == NULL)
301 return 0;
302
303 if (_attr->show)
304 val = _attr->show(adreno_dev);
305
306 return snprintf(buf, PAGE_SIZE, "0x%X\n", val);
307}
308
309static ssize_t _sysfs_store_bool(struct device *dev,
310 struct device_attribute *attr,
311 const char *buf, size_t count)
312{
313 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
314 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
315 unsigned int val = 0;
316 int ret;
317
318 if (adreno_dev == NULL)
319 return 0;
320
321 ret = kgsl_sysfs_store(buf, &val);
322
323 if (!ret && _attr->store)
324 ret = _attr->store(adreno_dev, val ? 1 : 0);
325
326 return (ssize_t) ret < 0 ? ret : count;
327}
328
329static ssize_t _sysfs_show_bool(struct device *dev,
330 struct device_attribute *attr,
331 char *buf)
332{
333 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
334 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
335 unsigned int val = 0;
336
337 if (adreno_dev == NULL)
338 return 0;
339
340 if (_attr->show)
341 val = _attr->show(adreno_dev);
342
343 return snprintf(buf, PAGE_SIZE, "%d\n", val);
344}
345
346#define ADRENO_SYSFS_BOOL(_name) \
347 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_bool, _sysfs_store_bool)
348
349#define ADRENO_SYSFS_U32(_name) \
350 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_u32, _sysfs_store_u32)
351
352static ADRENO_SYSFS_U32(ft_policy);
353static ADRENO_SYSFS_U32(ft_pagefault_policy);
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600354static ADRENO_SYSFS_U32(preempt_level);
355static ADRENO_SYSFS_BOOL(usesgmem);
356static ADRENO_SYSFS_BOOL(skipsaverestore);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700357static ADRENO_SYSFS_BOOL(ft_long_ib_detect);
358static ADRENO_SYSFS_BOOL(ft_hang_intr_status);
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700359static ADRENO_SYSFS_BOOL(gpu_llc_slice_enable);
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700360static ADRENO_SYSFS_BOOL(gpuhtw_llc_slice_enable);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700361
362static DEVICE_INT_ATTR(wake_nice, 0644, adreno_wake_nice);
363static DEVICE_INT_ATTR(wake_timeout, 0644, adreno_wake_timeout);
364
365static ADRENO_SYSFS_BOOL(sptp_pc);
366static ADRENO_SYSFS_BOOL(lm);
367static ADRENO_SYSFS_BOOL(preemption);
368static ADRENO_SYSFS_BOOL(hwcg);
369static ADRENO_SYSFS_BOOL(throttling);
370
371
372
373static const struct device_attribute *_attr_list[] = {
374 &adreno_attr_ft_policy.attr,
375 &adreno_attr_ft_pagefault_policy.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700376 &adreno_attr_ft_long_ib_detect.attr,
377 &adreno_attr_ft_hang_intr_status.attr,
378 &dev_attr_wake_nice.attr,
379 &dev_attr_wake_timeout.attr,
380 &adreno_attr_sptp_pc.attr,
381 &adreno_attr_lm.attr,
382 &adreno_attr_preemption.attr,
383 &adreno_attr_hwcg.attr,
384 &adreno_attr_throttling.attr,
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700385 &adreno_attr_gpu_llc_slice_enable.attr,
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700386 &adreno_attr_gpuhtw_llc_slice_enable.attr,
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600387 &adreno_attr_preempt_level.attr,
388 &adreno_attr_usesgmem.attr,
389 &adreno_attr_skipsaverestore.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700390 NULL,
391};
392
393/* Add a ppd directory for controlling different knobs from sysfs */
394struct adreno_ppd_attribute {
395 struct attribute attr;
396 ssize_t (*show)(struct kgsl_device *device, char *buf);
397 ssize_t (*store)(struct kgsl_device *device, const char *buf,
398 size_t count);
399};
400
401#define PPD_ATTR(_name, _mode, _show, _store) \
402struct adreno_ppd_attribute attr_##_name = { \
403 .attr = { .name = __stringify(_name), .mode = _mode }, \
404 .show = _show, \
405 .store = _store, \
406}
407
408#define to_ppd_attr(a) \
409container_of((a), struct adreno_ppd_attribute, attr)
410
411#define kobj_to_device(a) \
412container_of((a), struct kgsl_device, ppd_kobj)
413
414static ssize_t ppd_enable_store(struct kgsl_device *device,
415 const char *buf, size_t count)
416{
417 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
418 unsigned int ppd_on = 0;
419 int ret;
420
421 if (!adreno_is_a430v2(adreno_dev) ||
422 !ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
423 return count;
424
425 ret = kgsl_sysfs_store(buf, &ppd_on);
426 if (ret < 0)
427 return ret;
428
429 ppd_on = (ppd_on) ? 1 : 0;
430
431 if (ppd_on == test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag))
432 return count;
433
434 mutex_lock(&device->mutex);
435
436 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
437 change_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag);
438 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
439
440 mutex_unlock(&device->mutex);
441 return count;
442}
443
444static ssize_t ppd_enable_show(struct kgsl_device *device,
445 char *buf)
446{
447 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
448
449 return snprintf(buf, PAGE_SIZE, "%u\n",
450 test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag));
451}
452/* Add individual ppd attributes here */
453static PPD_ATTR(enable, 0644, ppd_enable_show, ppd_enable_store);
454
455static ssize_t ppd_sysfs_show(struct kobject *kobj,
456 struct attribute *attr, char *buf)
457{
458 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
459 struct kgsl_device *device = kobj_to_device(kobj);
460 ssize_t ret = -EIO;
461
462 if (device != NULL && pattr->show != NULL)
463 ret = pattr->show(device, buf);
464
465 return ret;
466}
467
468static ssize_t ppd_sysfs_store(struct kobject *kobj,
469 struct attribute *attr, const char *buf, size_t count)
470{
471 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
472 struct kgsl_device *device = kobj_to_device(kobj);
473 ssize_t ret = -EIO;
474
475 if (device != NULL && pattr->store != NULL)
476 ret = pattr->store(device, buf, count);
477
478 return ret;
479}
480
481static const struct sysfs_ops ppd_sysfs_ops = {
482 .show = ppd_sysfs_show,
483 .store = ppd_sysfs_store,
484};
485
486static struct kobj_type ktype_ppd = {
487 .sysfs_ops = &ppd_sysfs_ops,
488};
489
490static void ppd_sysfs_close(struct adreno_device *adreno_dev)
491{
492 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
493
494 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
495 return;
496
497 sysfs_remove_file(&device->ppd_kobj, &attr_enable.attr);
498 kobject_put(&device->ppd_kobj);
499}
500
501static int ppd_sysfs_init(struct adreno_device *adreno_dev)
502{
503 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
504 int ret;
505
506 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
507 return -ENODEV;
508
509 ret = kobject_init_and_add(&device->ppd_kobj, &ktype_ppd,
510 &device->dev->kobj, "ppd");
511
512 if (ret == 0)
513 ret = sysfs_create_file(&device->ppd_kobj, &attr_enable.attr);
514
515 return ret;
516}
517
518/**
519 * adreno_sysfs_close() - Take down the adreno sysfs files
520 * @adreno_dev: Pointer to the adreno device
521 *
522 * Take down the sysfs files on when the device goes away
523 */
524void adreno_sysfs_close(struct adreno_device *adreno_dev)
525{
526 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
527
528 ppd_sysfs_close(adreno_dev);
529 kgsl_remove_device_sysfs_files(device->dev, _attr_list);
530}
531
532/**
533 * adreno_sysfs_init() - Initialize adreno sysfs files
534 * @adreno_dev: Pointer to the adreno device
535 *
536 * Initialize many of the adreno specific sysfs files especially for fault
537 * tolerance and power control
538 */
539int adreno_sysfs_init(struct adreno_device *adreno_dev)
540{
541 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
542 int ret;
543
544 ret = kgsl_create_device_sysfs_files(device->dev, _attr_list);
545
546 /* Add the PPD directory and files */
547 if (ret == 0)
548 ppd_sysfs_init(adreno_dev);
549
550 return 0;
551}
552