diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c | 90 |
1 files changed, 50 insertions, 40 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c b/drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c index ee59e5de..0fe1c8d2 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c +++ b/drivers/gpu/nvgpu/common/linux/platform_ecc_sysfs.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/hashtable.h> | ||
18 | |||
17 | #include <nvgpu/kmem.h> | 19 | #include <nvgpu/kmem.h> |
18 | #include <nvgpu/bug.h> | 20 | #include <nvgpu/bug.h> |
19 | #include <nvgpu/hashtable.h> | 21 | #include <nvgpu/hashtable.h> |
@@ -28,10 +30,6 @@ | |||
28 | #include "platform_gp10b_tegra.h" | 30 | #include "platform_gp10b_tegra.h" |
29 | #include "platform_ecc_sysfs.h" | 31 | #include "platform_ecc_sysfs.h" |
30 | 32 | ||
31 | #define ECC_STAT_NAME_MAX_SIZE 100 | ||
32 | |||
33 | static DEFINE_HASHTABLE(ecc_hash_table, 5); | ||
34 | |||
35 | static u32 gen_ecc_hash_key(char *str) | 33 | static u32 gen_ecc_hash_key(char *str) |
36 | { | 34 | { |
37 | int i = 0; | 35 | int i = 0; |
@@ -57,6 +55,7 @@ static ssize_t ecc_stat_show(struct device *dev, | |||
57 | struct gk20a_ecc_stat *ecc_stat; | 55 | struct gk20a_ecc_stat *ecc_stat; |
58 | u32 hash_key; | 56 | u32 hash_key; |
59 | struct gk20a *g = get_gk20a(dev); | 57 | struct gk20a *g = get_gk20a(dev); |
58 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
60 | 59 | ||
61 | if (sscanf(ecc_stat_full_name, "ltc%u_lts%u", &hw_unit, | 60 | if (sscanf(ecc_stat_full_name, "ltc%u_lts%u", &hw_unit, |
62 | &subunit) == 2) { | 61 | &subunit) == 2) { |
@@ -78,7 +77,7 @@ static ssize_t ecc_stat_show(struct device *dev, | |||
78 | 77 | ||
79 | hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name); | 78 | hash_key = gen_ecc_hash_key((char *)ecc_stat_base_name); |
80 | 79 | ||
81 | hash_for_each_possible(ecc_hash_table, | 80 | hash_for_each_possible(l->ecc_sysfs_stats_htable, |
82 | ecc_stat, | 81 | ecc_stat, |
83 | hash_node, | 82 | hash_node, |
84 | hash_key) { | 83 | hash_key) { |
@@ -91,11 +90,9 @@ static ssize_t ecc_stat_show(struct device *dev, | |||
91 | return snprintf(buf, PAGE_SIZE, "Error: No ECC stat found!\n"); | 90 | return snprintf(buf, PAGE_SIZE, "Error: No ECC stat found!\n"); |
92 | } | 91 | } |
93 | 92 | ||
94 | int gr_gp10b_ecc_stat_create(struct device *dev, | 93 | int nvgpu_gr_ecc_stat_create(struct device *dev, |
95 | int is_l2, | 94 | int is_l2, char *ecc_stat_name, |
96 | char *ecc_stat_name, | 95 | struct gk20a_ecc_stat *ecc_stat) |
97 | struct gk20a_ecc_stat *ecc_stat, | ||
98 | struct device_attribute **dev_attr_array) | ||
99 | { | 96 | { |
100 | struct gk20a *g = get_gk20a(dev); | 97 | struct gk20a *g = get_gk20a(dev); |
101 | char *ltc_unit_name = "ltc"; | 98 | char *ltc_unit_name = "ltc"; |
@@ -113,32 +110,29 @@ int gr_gp10b_ecc_stat_create(struct device *dev, | |||
113 | num_hw_units = g->gr.tpc_count; | 110 | num_hw_units = g->gr.tpc_count; |
114 | 111 | ||
115 | 112 | ||
116 | return gp10b_ecc_stat_create(dev, num_hw_units, num_subunits, | 113 | return nvgpu_ecc_stat_create(dev, num_hw_units, num_subunits, |
117 | is_l2 ? ltc_unit_name : gr_unit_name, | 114 | is_l2 ? ltc_unit_name : gr_unit_name, |
118 | num_subunits ? lts_unit_name: NULL, | 115 | num_subunits ? lts_unit_name: NULL, |
119 | ecc_stat_name, | 116 | ecc_stat_name, |
120 | ecc_stat, | 117 | ecc_stat); |
121 | dev_attr_array); | ||
122 | } | 118 | } |
123 | 119 | ||
124 | int gp10b_ecc_stat_create(struct device *dev, | 120 | int nvgpu_ecc_stat_create(struct device *dev, |
125 | int num_hw_units, | 121 | int num_hw_units, int num_subunits, |
126 | int num_subunits, | 122 | char *ecc_unit_name, char *ecc_subunit_name, |
127 | char *ecc_unit_name, | 123 | char *ecc_stat_name, |
128 | char *ecc_subunit_name, | 124 | struct gk20a_ecc_stat *ecc_stat) |
129 | char *ecc_stat_name, | ||
130 | struct gk20a_ecc_stat *ecc_stat, | ||
131 | struct device_attribute **__dev_attr_array) | ||
132 | { | 125 | { |
133 | int error = 0; | 126 | int error = 0; |
134 | struct gk20a *g = get_gk20a(dev); | 127 | struct gk20a *g = get_gk20a(dev); |
128 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
135 | int hw_unit = 0; | 129 | int hw_unit = 0; |
136 | int subunit = 0; | 130 | int subunit = 0; |
137 | int element = 0; | 131 | int element = 0; |
138 | u32 hash_key = 0; | 132 | u32 hash_key = 0; |
139 | struct device_attribute *dev_attr_array; | 133 | struct device_attribute *dev_attr_array; |
140 | 134 | ||
141 | int num_elements = num_subunits ? num_subunits*num_hw_units : | 135 | int num_elements = num_subunits ? num_subunits * num_hw_units : |
142 | num_hw_units; | 136 | num_hw_units; |
143 | 137 | ||
144 | /* Allocate arrays */ | 138 | /* Allocate arrays */ |
@@ -146,6 +140,7 @@ int gp10b_ecc_stat_create(struct device *dev, | |||
146 | num_elements); | 140 | num_elements); |
147 | ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_elements); | 141 | ecc_stat->counters = nvgpu_kzalloc(g, sizeof(u32) * num_elements); |
148 | ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_elements); | 142 | ecc_stat->names = nvgpu_kzalloc(g, sizeof(char *) * num_elements); |
143 | |||
149 | for (hw_unit = 0; hw_unit < num_elements; hw_unit++) { | 144 | for (hw_unit = 0; hw_unit < num_elements; hw_unit++) { |
150 | ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) * | 145 | ecc_stat->names[hw_unit] = nvgpu_kzalloc(g, sizeof(char) * |
151 | ECC_STAT_NAME_MAX_SIZE); | 146 | ECC_STAT_NAME_MAX_SIZE); |
@@ -206,44 +201,58 @@ int gp10b_ecc_stat_create(struct device *dev, | |||
206 | 201 | ||
207 | /* Add hash table entry */ | 202 | /* Add hash table entry */ |
208 | hash_key = gen_ecc_hash_key(ecc_stat_name); | 203 | hash_key = gen_ecc_hash_key(ecc_stat_name); |
209 | hash_add(ecc_hash_table, | 204 | hash_add(l->ecc_sysfs_stats_htable, |
210 | &ecc_stat->hash_node, | 205 | &ecc_stat->hash_node, |
211 | hash_key); | 206 | hash_key); |
212 | 207 | ||
213 | *__dev_attr_array = dev_attr_array; | 208 | ecc_stat->attr_array = dev_attr_array; |
214 | 209 | ||
215 | return error; | 210 | return error; |
216 | } | 211 | } |
217 | 212 | ||
218 | void gr_gp10b_ecc_stat_remove(struct device *dev, | 213 | void nvgpu_gr_ecc_stat_remove(struct device *dev, |
219 | int is_l2, | 214 | int is_l2, struct gk20a_ecc_stat *ecc_stat) |
220 | struct gk20a_ecc_stat *ecc_stat, | ||
221 | struct device_attribute *dev_attr_array) | ||
222 | { | 215 | { |
223 | struct gk20a *g = get_gk20a(dev); | 216 | struct gk20a *g = get_gk20a(dev); |
224 | int num_hw_units = 0; | 217 | int num_hw_units = 0; |
218 | int num_subunits = 0; | ||
225 | 219 | ||
226 | if (is_l2 == 1) | 220 | if (is_l2 == 1) |
227 | num_hw_units = g->ltc_count; | 221 | num_hw_units = g->ltc_count; |
228 | else if (is_l2 == 2) | 222 | else if (is_l2 == 2) { |
229 | num_hw_units = g->ltc_count * g->gr.slices_per_ltc; | 223 | num_hw_units = g->ltc_count; |
230 | else | 224 | num_subunits = g->gr.slices_per_ltc; |
225 | } else | ||
231 | num_hw_units = g->gr.tpc_count; | 226 | num_hw_units = g->gr.tpc_count; |
232 | 227 | ||
233 | gp10b_ecc_stat_remove(dev, num_hw_units, ecc_stat, dev_attr_array); | 228 | nvgpu_ecc_stat_remove(dev, num_hw_units, num_subunits, ecc_stat); |
234 | } | 229 | } |
235 | 230 | ||
236 | void gp10b_ecc_stat_remove(struct device *dev, | 231 | void nvgpu_ecc_stat_remove(struct device *dev, |
237 | int num_hw_units, | 232 | int num_hw_units, int num_subunits, |
238 | struct gk20a_ecc_stat *ecc_stat, | 233 | struct gk20a_ecc_stat *ecc_stat) |
239 | struct device_attribute *dev_attr_array) | ||
240 | { | 234 | { |
241 | struct gk20a *g = get_gk20a(dev); | 235 | struct gk20a *g = get_gk20a(dev); |
236 | struct device_attribute *dev_attr_array = ecc_stat->attr_array; | ||
242 | int hw_unit = 0; | 237 | int hw_unit = 0; |
238 | int subunit = 0; | ||
239 | int element = 0; | ||
240 | int num_elements = num_subunits ? num_subunits * num_hw_units : | ||
241 | num_hw_units; | ||
243 | 242 | ||
244 | /* Remove sysfs files */ | 243 | /* Remove sysfs files */ |
245 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | 244 | if (num_subunits) { |
246 | device_remove_file(dev, &dev_attr_array[hw_unit]); | 245 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { |
246 | for (subunit = 0; subunit < num_subunits; subunit++) { | ||
247 | element = hw_unit * num_subunits + subunit; | ||
248 | |||
249 | device_remove_file(dev, | ||
250 | &dev_attr_array[element]); | ||
251 | } | ||
252 | } | ||
253 | } else { | ||
254 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) | ||
255 | device_remove_file(dev, &dev_attr_array[hw_unit]); | ||
247 | } | 256 | } |
248 | 257 | ||
249 | /* Remove hash table entry */ | 258 | /* Remove hash table entry */ |
@@ -251,9 +260,10 @@ void gp10b_ecc_stat_remove(struct device *dev, | |||
251 | 260 | ||
252 | /* Free arrays */ | 261 | /* Free arrays */ |
253 | nvgpu_kfree(g, ecc_stat->counters); | 262 | nvgpu_kfree(g, ecc_stat->counters); |
254 | for (hw_unit = 0; hw_unit < num_hw_units; hw_unit++) { | 263 | |
264 | for (hw_unit = 0; hw_unit < num_elements; hw_unit++) | ||
255 | nvgpu_kfree(g, ecc_stat->names[hw_unit]); | 265 | nvgpu_kfree(g, ecc_stat->names[hw_unit]); |
256 | } | 266 | |
257 | nvgpu_kfree(g, ecc_stat->names); | 267 | nvgpu_kfree(g, ecc_stat->names); |
258 | nvgpu_kfree(g, dev_attr_array); | 268 | nvgpu_kfree(g, dev_attr_array); |
259 | } | 269 | } |