1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* |
3 | * Copyright(c) 2015-2017 Intel Corporation. |
4 | */ |
5 | |
6 | #include <linux/ctype.h> |
7 | #include <rdma/ib_sysfs.h> |
8 | |
9 | #include "hfi.h" |
10 | #include "mad.h" |
11 | #include "trace.h" |
12 | |
13 | static struct hfi1_pportdata *hfi1_get_pportdata_kobj(struct kobject *kobj) |
14 | { |
15 | u32 port_num; |
16 | struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, port_num: &port_num); |
17 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
18 | |
19 | return &dd->pport[port_num - 1]; |
20 | } |
21 | |
22 | /* |
23 | * Start of per-port congestion control structures and support code |
24 | */ |
25 | |
26 | /* |
27 | * Congestion control table size followed by table entries |
28 | */ |
29 | static ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj, |
30 | struct bin_attribute *bin_attr, char *buf, |
31 | loff_t pos, size_t count) |
32 | { |
33 | int ret; |
34 | struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj); |
35 | struct cc_state *cc_state; |
36 | |
37 | ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) |
38 | + sizeof(__be16); |
39 | |
40 | if (pos > ret) |
41 | return -EINVAL; |
42 | |
43 | if (count > ret - pos) |
44 | count = ret - pos; |
45 | |
46 | if (!count) |
47 | return count; |
48 | |
49 | rcu_read_lock(); |
50 | cc_state = get_cc_state(ppd); |
51 | if (!cc_state) { |
52 | rcu_read_unlock(); |
53 | return -EINVAL; |
54 | } |
55 | memcpy(buf, (void *)&cc_state->cct + pos, count); |
56 | rcu_read_unlock(); |
57 | |
58 | return count; |
59 | } |
60 | static BIN_ATTR_RO(cc_table_bin, PAGE_SIZE); |
61 | |
62 | /* |
63 | * Congestion settings: port control, control map and an array of 16 |
64 | * entries for the congestion entries - increase, timer, event log |
65 | * trigger threshold and the minimum injection rate delay. |
66 | */ |
67 | static ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj, |
68 | struct bin_attribute *bin_attr, |
69 | char *buf, loff_t pos, size_t count) |
70 | { |
71 | struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj); |
72 | int ret; |
73 | struct cc_state *cc_state; |
74 | |
75 | ret = sizeof(struct opa_congestion_setting_attr_shadow); |
76 | |
77 | if (pos > ret) |
78 | return -EINVAL; |
79 | if (count > ret - pos) |
80 | count = ret - pos; |
81 | |
82 | if (!count) |
83 | return count; |
84 | |
85 | rcu_read_lock(); |
86 | cc_state = get_cc_state(ppd); |
87 | if (!cc_state) { |
88 | rcu_read_unlock(); |
89 | return -EINVAL; |
90 | } |
91 | memcpy(buf, (void *)&cc_state->cong_setting + pos, count); |
92 | rcu_read_unlock(); |
93 | |
94 | return count; |
95 | } |
96 | static BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE); |
97 | |
98 | static struct bin_attribute *port_cc_bin_attributes[] = { |
99 | &bin_attr_cc_setting_bin, |
100 | &bin_attr_cc_table_bin, |
101 | NULL |
102 | }; |
103 | |
104 | static ssize_t cc_prescan_show(struct ib_device *ibdev, u32 port_num, |
105 | struct ib_port_attribute *attr, char *buf) |
106 | { |
107 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
108 | struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; |
109 | |
110 | return sysfs_emit(buf, fmt: "%s\n" , ppd->cc_prescan ? "on" : "off" ); |
111 | } |
112 | |
113 | static ssize_t cc_prescan_store(struct ib_device *ibdev, u32 port_num, |
114 | struct ib_port_attribute *attr, const char *buf, |
115 | size_t count) |
116 | { |
117 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
118 | struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; |
119 | |
120 | if (!memcmp(p: buf, q: "on" , size: 2)) |
121 | ppd->cc_prescan = true; |
122 | else if (!memcmp(p: buf, q: "off" , size: 3)) |
123 | ppd->cc_prescan = false; |
124 | |
125 | return count; |
126 | } |
127 | static IB_PORT_ATTR_ADMIN_RW(cc_prescan); |
128 | |
129 | static struct attribute *port_cc_attributes[] = { |
130 | &ib_port_attr_cc_prescan.attr, |
131 | NULL |
132 | }; |
133 | |
134 | static const struct attribute_group port_cc_group = { |
135 | .name = "CCMgtA" , |
136 | .attrs = port_cc_attributes, |
137 | .bin_attrs = port_cc_bin_attributes, |
138 | }; |
139 | |
140 | /* Start sc2vl */ |
141 | struct hfi1_sc2vl_attr { |
142 | struct ib_port_attribute attr; |
143 | int sc; |
144 | }; |
145 | |
146 | static ssize_t sc2vl_attr_show(struct ib_device *ibdev, u32 port_num, |
147 | struct ib_port_attribute *attr, char *buf) |
148 | { |
149 | struct hfi1_sc2vl_attr *sattr = |
150 | container_of(attr, struct hfi1_sc2vl_attr, attr); |
151 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
152 | |
153 | return sysfs_emit(buf, fmt: "%u\n" , *((u8 *)dd->sc2vl + sattr->sc)); |
154 | } |
155 | |
156 | #define HFI1_SC2VL_ATTR(N) \ |
157 | static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \ |
158 | .attr = __ATTR(N, 0444, sc2vl_attr_show, NULL), \ |
159 | .sc = N, \ |
160 | } |
161 | |
162 | HFI1_SC2VL_ATTR(0); |
163 | HFI1_SC2VL_ATTR(1); |
164 | HFI1_SC2VL_ATTR(2); |
165 | HFI1_SC2VL_ATTR(3); |
166 | HFI1_SC2VL_ATTR(4); |
167 | HFI1_SC2VL_ATTR(5); |
168 | HFI1_SC2VL_ATTR(6); |
169 | HFI1_SC2VL_ATTR(7); |
170 | HFI1_SC2VL_ATTR(8); |
171 | HFI1_SC2VL_ATTR(9); |
172 | HFI1_SC2VL_ATTR(10); |
173 | HFI1_SC2VL_ATTR(11); |
174 | HFI1_SC2VL_ATTR(12); |
175 | HFI1_SC2VL_ATTR(13); |
176 | HFI1_SC2VL_ATTR(14); |
177 | HFI1_SC2VL_ATTR(15); |
178 | HFI1_SC2VL_ATTR(16); |
179 | HFI1_SC2VL_ATTR(17); |
180 | HFI1_SC2VL_ATTR(18); |
181 | HFI1_SC2VL_ATTR(19); |
182 | HFI1_SC2VL_ATTR(20); |
183 | HFI1_SC2VL_ATTR(21); |
184 | HFI1_SC2VL_ATTR(22); |
185 | HFI1_SC2VL_ATTR(23); |
186 | HFI1_SC2VL_ATTR(24); |
187 | HFI1_SC2VL_ATTR(25); |
188 | HFI1_SC2VL_ATTR(26); |
189 | HFI1_SC2VL_ATTR(27); |
190 | HFI1_SC2VL_ATTR(28); |
191 | HFI1_SC2VL_ATTR(29); |
192 | HFI1_SC2VL_ATTR(30); |
193 | HFI1_SC2VL_ATTR(31); |
194 | |
195 | static struct attribute *port_sc2vl_attributes[] = { |
196 | &hfi1_sc2vl_attr_0.attr.attr, |
197 | &hfi1_sc2vl_attr_1.attr.attr, |
198 | &hfi1_sc2vl_attr_2.attr.attr, |
199 | &hfi1_sc2vl_attr_3.attr.attr, |
200 | &hfi1_sc2vl_attr_4.attr.attr, |
201 | &hfi1_sc2vl_attr_5.attr.attr, |
202 | &hfi1_sc2vl_attr_6.attr.attr, |
203 | &hfi1_sc2vl_attr_7.attr.attr, |
204 | &hfi1_sc2vl_attr_8.attr.attr, |
205 | &hfi1_sc2vl_attr_9.attr.attr, |
206 | &hfi1_sc2vl_attr_10.attr.attr, |
207 | &hfi1_sc2vl_attr_11.attr.attr, |
208 | &hfi1_sc2vl_attr_12.attr.attr, |
209 | &hfi1_sc2vl_attr_13.attr.attr, |
210 | &hfi1_sc2vl_attr_14.attr.attr, |
211 | &hfi1_sc2vl_attr_15.attr.attr, |
212 | &hfi1_sc2vl_attr_16.attr.attr, |
213 | &hfi1_sc2vl_attr_17.attr.attr, |
214 | &hfi1_sc2vl_attr_18.attr.attr, |
215 | &hfi1_sc2vl_attr_19.attr.attr, |
216 | &hfi1_sc2vl_attr_20.attr.attr, |
217 | &hfi1_sc2vl_attr_21.attr.attr, |
218 | &hfi1_sc2vl_attr_22.attr.attr, |
219 | &hfi1_sc2vl_attr_23.attr.attr, |
220 | &hfi1_sc2vl_attr_24.attr.attr, |
221 | &hfi1_sc2vl_attr_25.attr.attr, |
222 | &hfi1_sc2vl_attr_26.attr.attr, |
223 | &hfi1_sc2vl_attr_27.attr.attr, |
224 | &hfi1_sc2vl_attr_28.attr.attr, |
225 | &hfi1_sc2vl_attr_29.attr.attr, |
226 | &hfi1_sc2vl_attr_30.attr.attr, |
227 | &hfi1_sc2vl_attr_31.attr.attr, |
228 | NULL |
229 | }; |
230 | |
231 | static const struct attribute_group port_sc2vl_group = { |
232 | .name = "sc2vl" , |
233 | .attrs = port_sc2vl_attributes, |
234 | }; |
235 | /* End sc2vl */ |
236 | |
237 | /* Start sl2sc */ |
238 | struct hfi1_sl2sc_attr { |
239 | struct ib_port_attribute attr; |
240 | int sl; |
241 | }; |
242 | |
243 | static ssize_t sl2sc_attr_show(struct ib_device *ibdev, u32 port_num, |
244 | struct ib_port_attribute *attr, char *buf) |
245 | { |
246 | struct hfi1_sl2sc_attr *sattr = |
247 | container_of(attr, struct hfi1_sl2sc_attr, attr); |
248 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
249 | struct hfi1_ibport *ibp = &dd->pport[port_num - 1].ibport_data; |
250 | |
251 | return sysfs_emit(buf, fmt: "%u\n" , ibp->sl_to_sc[sattr->sl]); |
252 | } |
253 | |
254 | #define HFI1_SL2SC_ATTR(N) \ |
255 | static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = { \ |
256 | .attr = __ATTR(N, 0444, sl2sc_attr_show, NULL), .sl = N \ |
257 | } |
258 | |
259 | HFI1_SL2SC_ATTR(0); |
260 | HFI1_SL2SC_ATTR(1); |
261 | HFI1_SL2SC_ATTR(2); |
262 | HFI1_SL2SC_ATTR(3); |
263 | HFI1_SL2SC_ATTR(4); |
264 | HFI1_SL2SC_ATTR(5); |
265 | HFI1_SL2SC_ATTR(6); |
266 | HFI1_SL2SC_ATTR(7); |
267 | HFI1_SL2SC_ATTR(8); |
268 | HFI1_SL2SC_ATTR(9); |
269 | HFI1_SL2SC_ATTR(10); |
270 | HFI1_SL2SC_ATTR(11); |
271 | HFI1_SL2SC_ATTR(12); |
272 | HFI1_SL2SC_ATTR(13); |
273 | HFI1_SL2SC_ATTR(14); |
274 | HFI1_SL2SC_ATTR(15); |
275 | HFI1_SL2SC_ATTR(16); |
276 | HFI1_SL2SC_ATTR(17); |
277 | HFI1_SL2SC_ATTR(18); |
278 | HFI1_SL2SC_ATTR(19); |
279 | HFI1_SL2SC_ATTR(20); |
280 | HFI1_SL2SC_ATTR(21); |
281 | HFI1_SL2SC_ATTR(22); |
282 | HFI1_SL2SC_ATTR(23); |
283 | HFI1_SL2SC_ATTR(24); |
284 | HFI1_SL2SC_ATTR(25); |
285 | HFI1_SL2SC_ATTR(26); |
286 | HFI1_SL2SC_ATTR(27); |
287 | HFI1_SL2SC_ATTR(28); |
288 | HFI1_SL2SC_ATTR(29); |
289 | HFI1_SL2SC_ATTR(30); |
290 | HFI1_SL2SC_ATTR(31); |
291 | |
292 | static struct attribute *port_sl2sc_attributes[] = { |
293 | &hfi1_sl2sc_attr_0.attr.attr, |
294 | &hfi1_sl2sc_attr_1.attr.attr, |
295 | &hfi1_sl2sc_attr_2.attr.attr, |
296 | &hfi1_sl2sc_attr_3.attr.attr, |
297 | &hfi1_sl2sc_attr_4.attr.attr, |
298 | &hfi1_sl2sc_attr_5.attr.attr, |
299 | &hfi1_sl2sc_attr_6.attr.attr, |
300 | &hfi1_sl2sc_attr_7.attr.attr, |
301 | &hfi1_sl2sc_attr_8.attr.attr, |
302 | &hfi1_sl2sc_attr_9.attr.attr, |
303 | &hfi1_sl2sc_attr_10.attr.attr, |
304 | &hfi1_sl2sc_attr_11.attr.attr, |
305 | &hfi1_sl2sc_attr_12.attr.attr, |
306 | &hfi1_sl2sc_attr_13.attr.attr, |
307 | &hfi1_sl2sc_attr_14.attr.attr, |
308 | &hfi1_sl2sc_attr_15.attr.attr, |
309 | &hfi1_sl2sc_attr_16.attr.attr, |
310 | &hfi1_sl2sc_attr_17.attr.attr, |
311 | &hfi1_sl2sc_attr_18.attr.attr, |
312 | &hfi1_sl2sc_attr_19.attr.attr, |
313 | &hfi1_sl2sc_attr_20.attr.attr, |
314 | &hfi1_sl2sc_attr_21.attr.attr, |
315 | &hfi1_sl2sc_attr_22.attr.attr, |
316 | &hfi1_sl2sc_attr_23.attr.attr, |
317 | &hfi1_sl2sc_attr_24.attr.attr, |
318 | &hfi1_sl2sc_attr_25.attr.attr, |
319 | &hfi1_sl2sc_attr_26.attr.attr, |
320 | &hfi1_sl2sc_attr_27.attr.attr, |
321 | &hfi1_sl2sc_attr_28.attr.attr, |
322 | &hfi1_sl2sc_attr_29.attr.attr, |
323 | &hfi1_sl2sc_attr_30.attr.attr, |
324 | &hfi1_sl2sc_attr_31.attr.attr, |
325 | NULL |
326 | }; |
327 | |
328 | static const struct attribute_group port_sl2sc_group = { |
329 | .name = "sl2sc" , |
330 | .attrs = port_sl2sc_attributes, |
331 | }; |
332 | |
333 | /* End sl2sc */ |
334 | |
335 | /* Start vl2mtu */ |
336 | |
337 | struct hfi1_vl2mtu_attr { |
338 | struct ib_port_attribute attr; |
339 | int vl; |
340 | }; |
341 | |
342 | static ssize_t vl2mtu_attr_show(struct ib_device *ibdev, u32 port_num, |
343 | struct ib_port_attribute *attr, char *buf) |
344 | { |
345 | struct hfi1_vl2mtu_attr *vlattr = |
346 | container_of(attr, struct hfi1_vl2mtu_attr, attr); |
347 | struct hfi1_devdata *dd = dd_from_ibdev(ibdev); |
348 | |
349 | return sysfs_emit(buf, fmt: "%u\n" , dd->vld[vlattr->vl].mtu); |
350 | } |
351 | |
352 | #define HFI1_VL2MTU_ATTR(N) \ |
353 | static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \ |
354 | .attr = __ATTR(N, 0444, vl2mtu_attr_show, NULL), \ |
355 | .vl = N, \ |
356 | } |
357 | |
358 | HFI1_VL2MTU_ATTR(0); |
359 | HFI1_VL2MTU_ATTR(1); |
360 | HFI1_VL2MTU_ATTR(2); |
361 | HFI1_VL2MTU_ATTR(3); |
362 | HFI1_VL2MTU_ATTR(4); |
363 | HFI1_VL2MTU_ATTR(5); |
364 | HFI1_VL2MTU_ATTR(6); |
365 | HFI1_VL2MTU_ATTR(7); |
366 | HFI1_VL2MTU_ATTR(8); |
367 | HFI1_VL2MTU_ATTR(9); |
368 | HFI1_VL2MTU_ATTR(10); |
369 | HFI1_VL2MTU_ATTR(11); |
370 | HFI1_VL2MTU_ATTR(12); |
371 | HFI1_VL2MTU_ATTR(13); |
372 | HFI1_VL2MTU_ATTR(14); |
373 | HFI1_VL2MTU_ATTR(15); |
374 | |
375 | static struct attribute *port_vl2mtu_attributes[] = { |
376 | &hfi1_vl2mtu_attr_0.attr.attr, |
377 | &hfi1_vl2mtu_attr_1.attr.attr, |
378 | &hfi1_vl2mtu_attr_2.attr.attr, |
379 | &hfi1_vl2mtu_attr_3.attr.attr, |
380 | &hfi1_vl2mtu_attr_4.attr.attr, |
381 | &hfi1_vl2mtu_attr_5.attr.attr, |
382 | &hfi1_vl2mtu_attr_6.attr.attr, |
383 | &hfi1_vl2mtu_attr_7.attr.attr, |
384 | &hfi1_vl2mtu_attr_8.attr.attr, |
385 | &hfi1_vl2mtu_attr_9.attr.attr, |
386 | &hfi1_vl2mtu_attr_10.attr.attr, |
387 | &hfi1_vl2mtu_attr_11.attr.attr, |
388 | &hfi1_vl2mtu_attr_12.attr.attr, |
389 | &hfi1_vl2mtu_attr_13.attr.attr, |
390 | &hfi1_vl2mtu_attr_14.attr.attr, |
391 | &hfi1_vl2mtu_attr_15.attr.attr, |
392 | NULL |
393 | }; |
394 | |
395 | static const struct attribute_group port_vl2mtu_group = { |
396 | .name = "vl2mtu" , |
397 | .attrs = port_vl2mtu_attributes, |
398 | }; |
399 | |
400 | /* end of per-port file structures and support code */ |
401 | |
402 | /* |
403 | * Start of per-unit (or driver, in some cases, but replicated |
404 | * per unit) functions (these get a device *) |
405 | */ |
406 | static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr, |
407 | char *buf) |
408 | { |
409 | struct hfi1_ibdev *dev = |
410 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
411 | |
412 | return sysfs_emit(buf, fmt: "%x\n" , dd_from_dev(dev)->minrev); |
413 | } |
414 | static DEVICE_ATTR_RO(hw_rev); |
415 | |
416 | static ssize_t board_id_show(struct device *device, |
417 | struct device_attribute *attr, char *buf) |
418 | { |
419 | struct hfi1_ibdev *dev = |
420 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
421 | struct hfi1_devdata *dd = dd_from_dev(dev); |
422 | |
423 | if (!dd->boardname) |
424 | return -EINVAL; |
425 | |
426 | return sysfs_emit(buf, fmt: "%s\n" , dd->boardname); |
427 | } |
428 | static DEVICE_ATTR_RO(board_id); |
429 | |
430 | static ssize_t boardversion_show(struct device *device, |
431 | struct device_attribute *attr, char *buf) |
432 | { |
433 | struct hfi1_ibdev *dev = |
434 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
435 | struct hfi1_devdata *dd = dd_from_dev(dev); |
436 | |
437 | /* The string printed here is already newline-terminated. */ |
438 | return sysfs_emit(buf, fmt: "%s" , dd->boardversion); |
439 | } |
440 | static DEVICE_ATTR_RO(boardversion); |
441 | |
442 | static ssize_t nctxts_show(struct device *device, |
443 | struct device_attribute *attr, char *buf) |
444 | { |
445 | struct hfi1_ibdev *dev = |
446 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
447 | struct hfi1_devdata *dd = dd_from_dev(dev); |
448 | |
449 | /* |
450 | * Return the smaller of send and receive contexts. |
451 | * Normally, user level applications would require both a send |
452 | * and a receive context, so returning the smaller of the two counts |
453 | * give a more accurate picture of total contexts available. |
454 | */ |
455 | return sysfs_emit(buf, fmt: "%u\n" , |
456 | min(dd->num_user_contexts, |
457 | (u32)dd->sc_sizes[SC_USER].count)); |
458 | } |
459 | static DEVICE_ATTR_RO(nctxts); |
460 | |
461 | static ssize_t nfreectxts_show(struct device *device, |
462 | struct device_attribute *attr, char *buf) |
463 | { |
464 | struct hfi1_ibdev *dev = |
465 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
466 | struct hfi1_devdata *dd = dd_from_dev(dev); |
467 | |
468 | /* Return the number of free user ports (contexts) available. */ |
469 | return sysfs_emit(buf, fmt: "%u\n" , dd->freectxts); |
470 | } |
471 | static DEVICE_ATTR_RO(nfreectxts); |
472 | |
473 | static ssize_t serial_show(struct device *device, |
474 | struct device_attribute *attr, char *buf) |
475 | { |
476 | struct hfi1_ibdev *dev = |
477 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
478 | struct hfi1_devdata *dd = dd_from_dev(dev); |
479 | |
480 | /* dd->serial is already newline terminated in chip.c */ |
481 | return sysfs_emit(buf, fmt: "%s" , dd->serial); |
482 | } |
483 | static DEVICE_ATTR_RO(serial); |
484 | |
485 | static ssize_t chip_reset_store(struct device *device, |
486 | struct device_attribute *attr, const char *buf, |
487 | size_t count) |
488 | { |
489 | struct hfi1_ibdev *dev = |
490 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
491 | struct hfi1_devdata *dd = dd_from_dev(dev); |
492 | int ret; |
493 | |
494 | if (count < 5 || memcmp(p: buf, q: "reset" , size: 5) || !dd->diag_client) { |
495 | ret = -EINVAL; |
496 | goto bail; |
497 | } |
498 | |
499 | ret = hfi1_reset_device(dd->unit); |
500 | bail: |
501 | return ret < 0 ? ret : count; |
502 | } |
503 | static DEVICE_ATTR_WO(chip_reset); |
504 | |
505 | /* |
506 | * Convert the reported temperature from an integer (reported in |
507 | * units of 0.25C) to a floating point number. |
508 | */ |
509 | #define temp_d(t) ((t) >> 2) |
510 | #define temp_f(t) (((t)&0x3) * 25u) |
511 | |
512 | /* |
513 | * Dump tempsense values, in decimal, to ease shell-scripts. |
514 | */ |
515 | static ssize_t tempsense_show(struct device *device, |
516 | struct device_attribute *attr, char *buf) |
517 | { |
518 | struct hfi1_ibdev *dev = |
519 | rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev); |
520 | struct hfi1_devdata *dd = dd_from_dev(dev); |
521 | struct hfi1_temp temp; |
522 | int ret; |
523 | |
524 | ret = hfi1_tempsense_rd(dd, temp: &temp); |
525 | if (ret) |
526 | return ret; |
527 | |
528 | return sysfs_emit(buf, fmt: "%u.%02u %u.%02u %u.%02u %u.%02u %u %u %u\n" , |
529 | temp_d(temp.curr), temp_f(temp.curr), |
530 | temp_d(temp.lo_lim), temp_f(temp.lo_lim), |
531 | temp_d(temp.hi_lim), temp_f(temp.hi_lim), |
532 | temp_d(temp.crit_lim), temp_f(temp.crit_lim), |
533 | temp.triggers & 0x1, |
534 | temp.triggers & 0x2, |
535 | temp.triggers & 0x4); |
536 | } |
537 | static DEVICE_ATTR_RO(tempsense); |
538 | |
539 | /* |
540 | * end of per-unit (or driver, in some cases, but replicated |
541 | * per unit) functions |
542 | */ |
543 | |
544 | /* start of per-unit file structures and support code */ |
545 | static struct attribute *hfi1_attributes[] = { |
546 | &dev_attr_hw_rev.attr, |
547 | &dev_attr_board_id.attr, |
548 | &dev_attr_nctxts.attr, |
549 | &dev_attr_nfreectxts.attr, |
550 | &dev_attr_serial.attr, |
551 | &dev_attr_boardversion.attr, |
552 | &dev_attr_tempsense.attr, |
553 | &dev_attr_chip_reset.attr, |
554 | NULL, |
555 | }; |
556 | |
557 | const struct attribute_group ib_hfi1_attr_group = { |
558 | .attrs = hfi1_attributes, |
559 | }; |
560 | |
561 | const struct attribute_group *hfi1_attr_port_groups[] = { |
562 | &port_cc_group, |
563 | &port_sc2vl_group, |
564 | &port_sl2sc_group, |
565 | &port_vl2mtu_group, |
566 | NULL, |
567 | }; |
568 | |
569 | struct sde_attribute { |
570 | struct attribute attr; |
571 | ssize_t (*show)(struct sdma_engine *sde, char *buf); |
572 | ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt); |
573 | }; |
574 | |
575 | static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf) |
576 | { |
577 | struct sde_attribute *sde_attr = |
578 | container_of(attr, struct sde_attribute, attr); |
579 | struct sdma_engine *sde = |
580 | container_of(kobj, struct sdma_engine, kobj); |
581 | |
582 | if (!sde_attr->show) |
583 | return -EINVAL; |
584 | |
585 | return sde_attr->show(sde, buf); |
586 | } |
587 | |
588 | static ssize_t sde_store(struct kobject *kobj, struct attribute *attr, |
589 | const char *buf, size_t count) |
590 | { |
591 | struct sde_attribute *sde_attr = |
592 | container_of(attr, struct sde_attribute, attr); |
593 | struct sdma_engine *sde = |
594 | container_of(kobj, struct sdma_engine, kobj); |
595 | |
596 | if (!capable(CAP_SYS_ADMIN)) |
597 | return -EPERM; |
598 | |
599 | if (!sde_attr->store) |
600 | return -EINVAL; |
601 | |
602 | return sde_attr->store(sde, buf, count); |
603 | } |
604 | |
605 | static const struct sysfs_ops sde_sysfs_ops = { |
606 | .show = sde_show, |
607 | .store = sde_store, |
608 | }; |
609 | |
610 | static struct kobj_type sde_ktype = { |
611 | .sysfs_ops = &sde_sysfs_ops, |
612 | }; |
613 | |
614 | #define SDE_ATTR(_name, _mode, _show, _store) \ |
615 | struct sde_attribute sde_attr_##_name = \ |
616 | __ATTR(_name, _mode, _show, _store) |
617 | |
618 | static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf) |
619 | { |
620 | return sdma_get_cpu_to_sde_map(sde, buf); |
621 | } |
622 | |
623 | static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde, |
624 | const char *buf, size_t count) |
625 | { |
626 | return sdma_set_cpu_to_sde_map(sde, buf, count); |
627 | } |
628 | |
629 | static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf) |
630 | { |
631 | int vl; |
632 | |
633 | vl = sdma_engine_get_vl(sde); |
634 | if (vl < 0) |
635 | return vl; |
636 | |
637 | return sysfs_emit(buf, fmt: "%d\n" , vl); |
638 | } |
639 | |
640 | static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO, |
641 | sde_show_cpu_to_sde_map, |
642 | sde_store_cpu_to_sde_map); |
643 | static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL); |
644 | |
645 | static struct sde_attribute *sde_attribs[] = { |
646 | &sde_attr_cpu_list, |
647 | &sde_attr_vl |
648 | }; |
649 | |
650 | /* |
651 | * Register and create our files in /sys/class/infiniband. |
652 | */ |
653 | int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd) |
654 | { |
655 | struct ib_device *dev = &dd->verbs_dev.rdi.ibdev; |
656 | struct device *class_dev = &dev->dev; |
657 | int i, j, ret; |
658 | |
659 | for (i = 0; i < dd->num_sdma; i++) { |
660 | ret = kobject_init_and_add(kobj: &dd->per_sdma[i].kobj, |
661 | ktype: &sde_ktype, parent: &class_dev->kobj, |
662 | fmt: "sdma%d" , i); |
663 | if (ret) |
664 | goto bail; |
665 | |
666 | for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) { |
667 | ret = sysfs_create_file(kobj: &dd->per_sdma[i].kobj, |
668 | attr: &sde_attribs[j]->attr); |
669 | if (ret) |
670 | goto bail; |
671 | } |
672 | } |
673 | |
674 | return 0; |
675 | bail: |
676 | /* |
677 | * The function kobject_put() will call kobject_del() if the kobject |
678 | * has been added successfully. The sysfs files created under the |
679 | * kobject directory will also be removed during the process. |
680 | */ |
681 | for (; i >= 0; i--) |
682 | kobject_put(kobj: &dd->per_sdma[i].kobj); |
683 | |
684 | return ret; |
685 | } |
686 | |
687 | /* |
688 | * Unregister and remove our files in /sys/class/infiniband. |
689 | */ |
690 | void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd) |
691 | { |
692 | int i; |
693 | |
694 | /* Unwind operations in hfi1_verbs_register_sysfs() */ |
695 | for (i = 0; i < dd->num_sdma; i++) |
696 | kobject_put(kobj: &dd->per_sdma[i].kobj); |
697 | } |
698 | |