summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/vgpu
diff options
context:
space:
mode:
authorKyle Guo <kyleg@nvidia.com>2018-07-12 20:51:42 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-08-15 00:24:53 -0400
commit2a25d03f2b7ad0700f14640282abd72ff587d800 (patch)
tree990b2f40d4625df7d5a9106d3c98dc0ccddf90ac /drivers/gpu/nvgpu/os/linux/vgpu
parent91390d857f6302f9c2923ec4188ea7e24ee537a2 (diff)
gpu: nvgpu: vgpu: ecc sysfs support for vgpu
- fetch ecc info from RM server and create sysfs nodes - new file ecc_vgpu.c for platform-independent code - add 2 new commands: GET_ECC_INFO and GET_ECC_COUNTER_VALUE JIRA EVLR-2590 Change-Id: I040a9fcd23326e432ca93e9a028319f9c1c570f0 Signed-off-by: Kyle Guo <kyleg@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1777428 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/vgpu')
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c b/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c
index 57aad4b4..30ca7f53 100644
--- a/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c
@@ -18,6 +18,8 @@
18#include <nvgpu/vgpu/vgpu.h> 18#include <nvgpu/vgpu/vgpu.h>
19 19
20#include "os/linux/platform_gk20a.h" 20#include "os/linux/platform_gk20a.h"
21#include "os/linux/os_linux.h"
22#include "vgpu/ecc_vgpu.h"
21 23
22static ssize_t vgpu_load_show(struct device *dev, 24static ssize_t vgpu_load_show(struct device *dev,
23 struct device_attribute *attr, 25 struct device_attribute *attr,
@@ -38,13 +40,104 @@ static ssize_t vgpu_load_show(struct device *dev,
38} 40}
39static DEVICE_ATTR(load, S_IRUGO, vgpu_load_show, NULL); 41static DEVICE_ATTR(load, S_IRUGO, vgpu_load_show, NULL);
40 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);
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
41void vgpu_create_sysfs(struct device *dev) 131void vgpu_create_sysfs(struct device *dev)
42{ 132{
43 if (device_create_file(dev, &dev_attr_load)) 133 if (device_create_file(dev, &dev_attr_load))
44 dev_err(dev, "Failed to create vgpu sysfs attributes!\n"); 134 dev_err(dev, "Failed to create vgpu sysfs attributes!\n");
135
136 vgpu_create_ecc_sysfs(dev);
45} 137}
46 138
47void vgpu_remove_sysfs(struct device *dev) 139void vgpu_remove_sysfs(struct device *dev)
48{ 140{
49 device_remove_file(dev, &dev_attr_load); 141 device_remove_file(dev, &dev_attr_load);
142 vgpu_remove_ecc_sysfs(dev);
50} 143}