aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/linux/vgpu/sysfs_vgpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/os/linux/vgpu/sysfs_vgpu.c')
-rw-r--r--include/os/linux/vgpu/sysfs_vgpu.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/include/os/linux/vgpu/sysfs_vgpu.c b/include/os/linux/vgpu/sysfs_vgpu.c
new file mode 100644
index 0000000..ade5d82
--- /dev/null
+++ b/include/os/linux/vgpu/sysfs_vgpu.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/device.h>
18#include <nvgpu/vgpu/vgpu.h>
19
20#include "os/linux/platform_gk20a.h"
21#include "os/linux/os_linux.h"
22#include "vgpu/ecc_vgpu.h"
23
24static ssize_t vgpu_load_show(struct device *dev,
25 struct device_attribute *attr,
26 char *buf)
27{
28 struct gk20a *g = get_gk20a(dev);
29 struct tegra_vgpu_cmd_msg msg = {0};
30 struct tegra_vgpu_gpu_load_params *p = &msg.params.gpu_load;
31 int err;
32
33 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_LOAD;
34 msg.handle = vgpu_get_handle(g);
35 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
36 if (err)
37 return err;
38
39 return snprintf(buf, PAGE_SIZE, "%u\n", p->load);
40}
41static DEVICE_ATTR(load, S_IRUGO, vgpu_load_show, NULL);
42
43static ssize_t vgpu_ecc_stat_show(struct device *dev,
44 struct device_attribute *attr,
45 char *buf)
46{
47 struct gk20a *g = get_gk20a(dev);
48 struct tegra_vgpu_cmd_msg msg = {0};
49 struct tegra_vgpu_ecc_counter_params *p = &msg.params.ecc_counter;
50 struct dev_ext_attribute *ext_attr = container_of(attr,
51 struct dev_ext_attribute, attr);
52 struct vgpu_ecc_stat *ecc_stat = ext_attr->var;
53 int err;
54
55 p->ecc_id = ecc_stat->ecc_id;
56
57 msg.cmd = TEGRA_VGPU_CMD_GET_ECC_COUNTER_VALUE;
58 msg.handle = vgpu_get_handle(g);
59 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
60 err = err ? err : msg.ret;
61 if (unlikely(err)) {
62 nvgpu_err(g, "ecc: cannot get ECC counter value: %d", err);
63 return err;
64 }
65
66 return snprintf(buf, PAGE_SIZE, "%u\n", p->value);
67}
68
69static int vgpu_create_ecc_sysfs(struct device *dev)
70{
71 struct gk20a *g = get_gk20a(dev);
72 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
73 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
74 struct vgpu_ecc_stat *stats;
75 struct dev_ext_attribute *attrs;
76 int err, i, count;
77
78 err = vgpu_ecc_get_info(g);
79 if (unlikely(err)) {
80 nvgpu_err(g, "ecc: cannot get ECC info: %d", err);
81 return err;
82 }
83
84 stats = priv->ecc_stats;
85 count = priv->ecc_stats_count;
86
87 attrs = nvgpu_kzalloc(g, count * sizeof(*attrs));
88 if (unlikely(!attrs)) {
89 nvgpu_err(g, "ecc: no memory");
90 vgpu_ecc_remove_info(g);
91 return -ENOMEM;
92 }
93
94 for (i = 0; i < count; i++) {
95 sysfs_attr_init(&attrs[i].attr.attr);
96 attrs[i].attr.attr.name = stats[i].name;
97 attrs[i].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO);
98 attrs[i].attr.show = vgpu_ecc_stat_show;
99 attrs[i].attr.store = NULL;
100 attrs[i].var = &stats[i];
101
102 err = device_create_file(dev, &attrs[i].attr);
103 if (unlikely(err)) {
104 nvgpu_warn(g, "ecc: cannot create file \"%s\": %d",
105 stats[i].name, err);
106 }
107 }
108
109 l->ecc_attrs = attrs;
110 return 0;
111}
112
113static void vgpu_remove_ecc_sysfs(struct device *dev)
114{
115 struct gk20a *g = get_gk20a(dev);
116 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
117 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
118 int i;
119
120 if (l->ecc_attrs) {
121 for (i = 0; i < priv->ecc_stats_count; i++)
122 device_remove_file(dev, &l->ecc_attrs[i].attr);
123
124 nvgpu_kfree(g, l->ecc_attrs);
125 l->ecc_attrs = NULL;
126 }
127
128 vgpu_ecc_remove_info(g);
129}
130
131void vgpu_create_sysfs(struct device *dev)
132{
133 if (device_create_file(dev, &dev_attr_load))
134 dev_err(dev, "Failed to create vgpu sysfs attributes!\n");
135
136 vgpu_create_ecc_sysfs(dev);
137}
138
139void vgpu_remove_sysfs(struct device *dev)
140{
141 device_remove_file(dev, &dev_attr_load);
142 vgpu_remove_ecc_sysfs(dev);
143}