]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/infiniband/hw/ipath/ipath_sysfs.c
IB/ipath: Provide I/O bus speeds for diagnostic purposes
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_sysfs.c
1 /*
2  * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
3  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33
34 #include <linux/ctype.h>
35
36 #include "ipath_kernel.h"
37 #include "ipath_common.h"
38
39 /**
40  * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
41  * @str: the string containing the number
42  * @valp: where to put the result
43  *
44  * returns the number of bytes consumed, or negative value on error
45  */
46 int ipath_parse_ushort(const char *str, unsigned short *valp)
47 {
48         unsigned long val;
49         char *end;
50         int ret;
51
52         if (!isdigit(str[0])) {
53                 ret = -EINVAL;
54                 goto bail;
55         }
56
57         val = simple_strtoul(str, &end, 0);
58
59         if (val > 0xffff) {
60                 ret = -EINVAL;
61                 goto bail;
62         }
63
64         *valp = val;
65
66         ret = end + 1 - str;
67         if (ret == 0)
68                 ret = -EINVAL;
69
70 bail:
71         return ret;
72 }
73
74 static ssize_t show_version(struct device_driver *dev, char *buf)
75 {
76         /* The string printed here is already newline-terminated. */
77         return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version);
78 }
79
80 static ssize_t show_num_units(struct device_driver *dev, char *buf)
81 {
82         return scnprintf(buf, PAGE_SIZE, "%d\n",
83                          ipath_count_units(NULL, NULL, NULL));
84 }
85
86 static ssize_t show_status(struct device *dev,
87                            struct device_attribute *attr,
88                            char *buf)
89 {
90         struct ipath_devdata *dd = dev_get_drvdata(dev);
91         ssize_t ret;
92
93         if (!dd->ipath_statusp) {
94                 ret = -EINVAL;
95                 goto bail;
96         }
97
98         ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
99                         (unsigned long long) *(dd->ipath_statusp));
100
101 bail:
102         return ret;
103 }
104
105 static const char *ipath_status_str[] = {
106         "Initted",
107         "Disabled",
108         "Admin_Disabled",
109         "", /* This used to be the old "OIB_SMA" status. */
110         "", /* This used to be the old "SMA" status. */
111         "Present",
112         "IB_link_up",
113         "IB_configured",
114         "NoIBcable",
115         "Fatal_Hardware_Error",
116         NULL,
117 };
118
119 static ssize_t show_status_str(struct device *dev,
120                                struct device_attribute *attr,
121                                char *buf)
122 {
123         struct ipath_devdata *dd = dev_get_drvdata(dev);
124         int i, any;
125         u64 s;
126         ssize_t ret;
127
128         if (!dd->ipath_statusp) {
129                 ret = -EINVAL;
130                 goto bail;
131         }
132
133         s = *(dd->ipath_statusp);
134         *buf = '\0';
135         for (any = i = 0; s && ipath_status_str[i]; i++) {
136                 if (s & 1) {
137                         if (any && strlcat(buf, " ", PAGE_SIZE) >=
138                             PAGE_SIZE)
139                                 /* overflow */
140                                 break;
141                         if (strlcat(buf, ipath_status_str[i],
142                                     PAGE_SIZE) >= PAGE_SIZE)
143                                 break;
144                         any = 1;
145                 }
146                 s >>= 1;
147         }
148         if (any)
149                 strlcat(buf, "\n", PAGE_SIZE);
150
151         ret = strlen(buf);
152
153 bail:
154         return ret;
155 }
156
157 static ssize_t show_boardversion(struct device *dev,
158                                struct device_attribute *attr,
159                                char *buf)
160 {
161         struct ipath_devdata *dd = dev_get_drvdata(dev);
162         /* The string printed here is already newline-terminated. */
163         return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
164 }
165
166 static ssize_t show_localbus_info(struct device *dev,
167                                struct device_attribute *attr,
168                                char *buf)
169 {
170         struct ipath_devdata *dd = dev_get_drvdata(dev);
171         /* The string printed here is already newline-terminated. */
172         return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info);
173 }
174
175 static ssize_t show_lmc(struct device *dev,
176                         struct device_attribute *attr,
177                         char *buf)
178 {
179         struct ipath_devdata *dd = dev_get_drvdata(dev);
180
181         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_lmc);
182 }
183
184 static ssize_t store_lmc(struct device *dev,
185                          struct device_attribute *attr,
186                          const char *buf,
187                          size_t count)
188 {
189         struct ipath_devdata *dd = dev_get_drvdata(dev);
190         u16 lmc = 0;
191         int ret;
192
193         ret = ipath_parse_ushort(buf, &lmc);
194         if (ret < 0)
195                 goto invalid;
196
197         if (lmc > 7) {
198                 ret = -EINVAL;
199                 goto invalid;
200         }
201
202         ipath_set_lid(dd, dd->ipath_lid, lmc);
203
204         goto bail;
205 invalid:
206         ipath_dev_err(dd, "attempt to set invalid LMC %u\n", lmc);
207 bail:
208         return ret;
209 }
210
211 static ssize_t show_lid(struct device *dev,
212                         struct device_attribute *attr,
213                         char *buf)
214 {
215         struct ipath_devdata *dd = dev_get_drvdata(dev);
216
217         return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
218 }
219
220 static ssize_t store_lid(struct device *dev,
221                          struct device_attribute *attr,
222                           const char *buf,
223                           size_t count)
224 {
225         struct ipath_devdata *dd = dev_get_drvdata(dev);
226         u16 lid = 0;
227         int ret;
228
229         ret = ipath_parse_ushort(buf, &lid);
230         if (ret < 0)
231                 goto invalid;
232
233         if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) {
234                 ret = -EINVAL;
235                 goto invalid;
236         }
237
238         ipath_set_lid(dd, lid, dd->ipath_lmc);
239
240         goto bail;
241 invalid:
242         ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid);
243 bail:
244         return ret;
245 }
246
247 static ssize_t show_mlid(struct device *dev,
248                          struct device_attribute *attr,
249                          char *buf)
250 {
251         struct ipath_devdata *dd = dev_get_drvdata(dev);
252
253         return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
254 }
255
256 static ssize_t store_mlid(struct device *dev,
257                          struct device_attribute *attr,
258                           const char *buf,
259                           size_t count)
260 {
261         struct ipath_devdata *dd = dev_get_drvdata(dev);
262         u16 mlid;
263         int ret;
264
265         ret = ipath_parse_ushort(buf, &mlid);
266         if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE)
267                 goto invalid;
268
269         dd->ipath_mlid = mlid;
270
271         goto bail;
272 invalid:
273         ipath_dev_err(dd, "attempt to set invalid MLID\n");
274 bail:
275         return ret;
276 }
277
278 static ssize_t show_guid(struct device *dev,
279                          struct device_attribute *attr,
280                          char *buf)
281 {
282         struct ipath_devdata *dd = dev_get_drvdata(dev);
283         u8 *guid;
284
285         guid = (u8 *) & (dd->ipath_guid);
286
287         return scnprintf(buf, PAGE_SIZE,
288                          "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
289                          guid[0], guid[1], guid[2], guid[3],
290                          guid[4], guid[5], guid[6], guid[7]);
291 }
292
293 static ssize_t store_guid(struct device *dev,
294                          struct device_attribute *attr,
295                           const char *buf,
296                           size_t count)
297 {
298         struct ipath_devdata *dd = dev_get_drvdata(dev);
299         ssize_t ret;
300         unsigned short guid[8];
301         __be64 new_guid;
302         u8 *ng;
303         int i;
304
305         if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
306                    &guid[0], &guid[1], &guid[2], &guid[3],
307                    &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
308                 goto invalid;
309
310         ng = (u8 *) &new_guid;
311
312         for (i = 0; i < 8; i++) {
313                 if (guid[i] > 0xff)
314                         goto invalid;
315                 ng[i] = guid[i];
316         }
317
318         if (new_guid == 0)
319                 goto invalid;
320
321         dd->ipath_guid = new_guid;
322         dd->ipath_nguid = 1;
323
324         ret = strlen(buf);
325         goto bail;
326
327 invalid:
328         ipath_dev_err(dd, "attempt to set invalid GUID\n");
329         ret = -EINVAL;
330
331 bail:
332         return ret;
333 }
334
335 static ssize_t show_nguid(struct device *dev,
336                           struct device_attribute *attr,
337                           char *buf)
338 {
339         struct ipath_devdata *dd = dev_get_drvdata(dev);
340
341         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
342 }
343
344 static ssize_t show_nports(struct device *dev,
345                            struct device_attribute *attr,
346                            char *buf)
347 {
348         struct ipath_devdata *dd = dev_get_drvdata(dev);
349
350         /* Return the number of user ports available. */
351         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1);
352 }
353
354 static ssize_t show_serial(struct device *dev,
355                            struct device_attribute *attr,
356                            char *buf)
357 {
358         struct ipath_devdata *dd = dev_get_drvdata(dev);
359
360         buf[sizeof dd->ipath_serial] = '\0';
361         memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
362         strcat(buf, "\n");
363         return strlen(buf);
364 }
365
366 static ssize_t show_unit(struct device *dev,
367                          struct device_attribute *attr,
368                          char *buf)
369 {
370         struct ipath_devdata *dd = dev_get_drvdata(dev);
371
372         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
373 }
374
375 static ssize_t show_jint_max_packets(struct device *dev,
376                                      struct device_attribute *attr,
377                                      char *buf)
378 {
379         struct ipath_devdata *dd = dev_get_drvdata(dev);
380
381         return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets);
382 }
383
384 static ssize_t store_jint_max_packets(struct device *dev,
385                                       struct device_attribute *attr,
386                                       const char *buf,
387                                       size_t count)
388 {
389         struct ipath_devdata *dd = dev_get_drvdata(dev);
390         u16 v = 0;
391         int ret;
392
393         ret = ipath_parse_ushort(buf, &v);
394         if (ret < 0)
395                 ipath_dev_err(dd, "invalid jint_max_packets.\n");
396         else
397                 dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v);
398
399         return ret;
400 }
401
402 static ssize_t show_jint_idle_ticks(struct device *dev,
403                                     struct device_attribute *attr,
404                                     char *buf)
405 {
406         struct ipath_devdata *dd = dev_get_drvdata(dev);
407
408         return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks);
409 }
410
411 static ssize_t store_jint_idle_ticks(struct device *dev,
412                                      struct device_attribute *attr,
413                                      const char *buf,
414                                      size_t count)
415 {
416         struct ipath_devdata *dd = dev_get_drvdata(dev);
417         u16 v = 0;
418         int ret;
419
420         ret = ipath_parse_ushort(buf, &v);
421         if (ret < 0)
422                 ipath_dev_err(dd, "invalid jint_idle_ticks.\n");
423         else
424                 dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets);
425
426         return ret;
427 }
428
429 #define DEVICE_COUNTER(name, attr) \
430         static ssize_t show_counter_##name(struct device *dev, \
431                                            struct device_attribute *attr, \
432                                            char *buf) \
433         { \
434                 struct ipath_devdata *dd = dev_get_drvdata(dev); \
435                 return scnprintf(\
436                         buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
437                         ipath_snap_cntr( \
438                                 dd, offsetof(struct infinipath_counters, \
439                                              attr) / sizeof(u64)));     \
440         } \
441         static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
442
443 DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
444 DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
445 DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
446 DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
447 DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
448 DEVICE_COUNTER(lb_ints, LBIntCnt);
449 DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
450 DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
451 DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
452 DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
453 DEVICE_COUNTER(rx_dwords, RxDwordCnt);
454 DEVICE_COUNTER(rx_ebps, RxEBPCnt);
455 DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
456 DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
457 DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
458 DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
459 DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
460 DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
461 DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
462 DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
463 DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
464 DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
465 DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
466 DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
467 DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
468 DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
469 DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
470 DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
471 DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
472 DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
473 DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
474 DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
475 DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
476 DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
477 DEVICE_COUNTER(tx_dwords, TxDwordCnt);
478 DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
479 DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
480 DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
481 DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
482 DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
483 DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
484
485 static struct attribute *dev_counter_attributes[] = {
486         &dev_attr_ib_link_downeds.attr,
487         &dev_attr_ib_link_err_recoveries.attr,
488         &dev_attr_ib_status_changes.attr,
489         &dev_attr_ib_symbol_errs.attr,
490         &dev_attr_lb_flow_stalls.attr,
491         &dev_attr_lb_ints.attr,
492         &dev_attr_rx_bad_formats.attr,
493         &dev_attr_rx_buf_ovfls.attr,
494         &dev_attr_rx_data_pkts.attr,
495         &dev_attr_rx_dropped_pkts.attr,
496         &dev_attr_rx_dwords.attr,
497         &dev_attr_rx_ebps.attr,
498         &dev_attr_rx_flow_ctrl_errs.attr,
499         &dev_attr_rx_flow_pkts.attr,
500         &dev_attr_rx_icrc_errs.attr,
501         &dev_attr_rx_len_errs.attr,
502         &dev_attr_rx_link_problems.attr,
503         &dev_attr_rx_lpcrc_errs.attr,
504         &dev_attr_rx_max_min_len_errs.attr,
505         &dev_attr_rx_p0_hdr_egr_ovfls.attr,
506         &dev_attr_rx_p1_hdr_egr_ovfls.attr,
507         &dev_attr_rx_p2_hdr_egr_ovfls.attr,
508         &dev_attr_rx_p3_hdr_egr_ovfls.attr,
509         &dev_attr_rx_p4_hdr_egr_ovfls.attr,
510         &dev_attr_rx_p5_hdr_egr_ovfls.attr,
511         &dev_attr_rx_p6_hdr_egr_ovfls.attr,
512         &dev_attr_rx_p7_hdr_egr_ovfls.attr,
513         &dev_attr_rx_p8_hdr_egr_ovfls.attr,
514         &dev_attr_rx_pkey_mismatches.attr,
515         &dev_attr_rx_tid_full_errs.attr,
516         &dev_attr_rx_tid_valid_errs.attr,
517         &dev_attr_rx_vcrc_errs.attr,
518         &dev_attr_tx_data_pkts.attr,
519         &dev_attr_tx_dropped_pkts.attr,
520         &dev_attr_tx_dwords.attr,
521         &dev_attr_tx_flow_pkts.attr,
522         &dev_attr_tx_flow_stalls.attr,
523         &dev_attr_tx_len_errs.attr,
524         &dev_attr_tx_max_min_len_errs.attr,
525         &dev_attr_tx_underruns.attr,
526         &dev_attr_tx_unsup_vl_errs.attr,
527         NULL
528 };
529
530 static struct attribute_group dev_counter_attr_group = {
531         .name = "counters",
532         .attrs = dev_counter_attributes
533 };
534
535 static ssize_t store_reset(struct device *dev,
536                          struct device_attribute *attr,
537                           const char *buf,
538                           size_t count)
539 {
540         struct ipath_devdata *dd = dev_get_drvdata(dev);
541         int ret;
542
543         if (count < 5 || memcmp(buf, "reset", 5)) {
544                 ret = -EINVAL;
545                 goto bail;
546         }
547
548         if (dd->ipath_flags & IPATH_DISABLED) {
549                 /*
550                  * post-reset init would re-enable interrupts, etc.
551                  * so don't allow reset on disabled devices.  Not
552                  * perfect error, but about the best choice.
553                  */
554                 dev_info(dev,"Unit %d is disabled, can't reset\n",
555                          dd->ipath_unit);
556                 ret = -EINVAL;
557         }
558         ret = ipath_reset_device(dd->ipath_unit);
559 bail:
560         return ret<0 ? ret : count;
561 }
562
563 static ssize_t store_link_state(struct device *dev,
564                          struct device_attribute *attr,
565                           const char *buf,
566                           size_t count)
567 {
568         struct ipath_devdata *dd = dev_get_drvdata(dev);
569         int ret, r;
570         u16 state;
571
572         ret = ipath_parse_ushort(buf, &state);
573         if (ret < 0)
574                 goto invalid;
575
576         r = ipath_set_linkstate(dd, state);
577         if (r < 0) {
578                 ret = r;
579                 goto bail;
580         }
581
582         goto bail;
583 invalid:
584         ipath_dev_err(dd, "attempt to set invalid link state\n");
585 bail:
586         return ret;
587 }
588
589 static ssize_t show_mtu(struct device *dev,
590                          struct device_attribute *attr,
591                          char *buf)
592 {
593         struct ipath_devdata *dd = dev_get_drvdata(dev);
594         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
595 }
596
597 static ssize_t store_mtu(struct device *dev,
598                          struct device_attribute *attr,
599                           const char *buf,
600                           size_t count)
601 {
602         struct ipath_devdata *dd = dev_get_drvdata(dev);
603         ssize_t ret;
604         u16 mtu = 0;
605         int r;
606
607         ret = ipath_parse_ushort(buf, &mtu);
608         if (ret < 0)
609                 goto invalid;
610
611         r = ipath_set_mtu(dd, mtu);
612         if (r < 0)
613                 ret = r;
614
615         goto bail;
616 invalid:
617         ipath_dev_err(dd, "attempt to set invalid MTU\n");
618 bail:
619         return ret;
620 }
621
622 static ssize_t show_enabled(struct device *dev,
623                          struct device_attribute *attr,
624                          char *buf)
625 {
626         struct ipath_devdata *dd = dev_get_drvdata(dev);
627         return scnprintf(buf, PAGE_SIZE, "%u\n",
628                          (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
629 }
630
631 static ssize_t store_enabled(struct device *dev,
632                          struct device_attribute *attr,
633                           const char *buf,
634                           size_t count)
635 {
636         struct ipath_devdata *dd = dev_get_drvdata(dev);
637         ssize_t ret;
638         u16 enable = 0;
639
640         ret = ipath_parse_ushort(buf, &enable);
641         if (ret < 0) {
642                 ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
643                 goto bail;
644         }
645
646         if (enable) {
647                 if (!(dd->ipath_flags & IPATH_DISABLED))
648                         goto bail;
649
650                 dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
651                 /* same as post-reset */
652                 ret = ipath_init_chip(dd, 1);
653                 if (ret)
654                         ipath_dev_err(dd, "Failed to enable unit %d\n",
655                                       dd->ipath_unit);
656                 else {
657                         dd->ipath_flags &= ~IPATH_DISABLED;
658                         *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
659                 }
660         }
661         else if (!(dd->ipath_flags & IPATH_DISABLED)) {
662                 dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
663                 ipath_shutdown_device(dd);
664                 dd->ipath_flags |= IPATH_DISABLED;
665                 *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
666         }
667
668 bail:
669         return ret;
670 }
671
672 static ssize_t store_rx_pol_inv(struct device *dev,
673                           struct device_attribute *attr,
674                           const char *buf,
675                           size_t count)
676 {
677         struct ipath_devdata *dd = dev_get_drvdata(dev);
678         int ret, r;
679         u16 val;
680
681         ret = ipath_parse_ushort(buf, &val);
682         if (ret < 0)
683                 goto invalid;
684
685         r = ipath_set_rx_pol_inv(dd, val);
686         if (r < 0) {
687                 ret = r;
688                 goto bail;
689         }
690
691         goto bail;
692 invalid:
693         ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n");
694 bail:
695         return ret;
696 }
697
698 static ssize_t store_led_override(struct device *dev,
699                           struct device_attribute *attr,
700                           const char *buf,
701                           size_t count)
702 {
703         struct ipath_devdata *dd = dev_get_drvdata(dev);
704         int ret;
705         u16 val;
706
707         ret = ipath_parse_ushort(buf, &val);
708         if (ret > 0)
709                 ipath_set_led_override(dd, val);
710         else
711                 ipath_dev_err(dd, "attempt to set invalid LED override\n");
712         return ret;
713 }
714
715 static ssize_t show_logged_errs(struct device *dev,
716                                 struct device_attribute *attr,
717                                 char *buf)
718 {
719         struct ipath_devdata *dd = dev_get_drvdata(dev);
720         int idx, count;
721
722         /* force consistency with actual EEPROM */
723         if (ipath_update_eeprom_log(dd) != 0)
724                 return -ENXIO;
725
726         count = 0;
727         for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
728                 count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
729                         dd->ipath_eep_st_errs[idx],
730                         idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' ');
731         }
732
733         return count;
734 }
735
736 /*
737  * New sysfs entries to control various IB config. These all turn into
738  * accesses via ipath_f_get/set_ib_cfg.
739  *
740  * Get/Set heartbeat enable. Or of 1=enabled, 2=auto
741  */
742 static ssize_t show_hrtbt_enb(struct device *dev,
743                          struct device_attribute *attr,
744                          char *buf)
745 {
746         struct ipath_devdata *dd = dev_get_drvdata(dev);
747         int ret;
748
749         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT);
750         if (ret >= 0)
751                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
752         return ret;
753 }
754
755 static ssize_t store_hrtbt_enb(struct device *dev,
756                           struct device_attribute *attr,
757                           const char *buf,
758                           size_t count)
759 {
760         struct ipath_devdata *dd = dev_get_drvdata(dev);
761         int ret, r;
762         u16 val;
763
764         ret = ipath_parse_ushort(buf, &val);
765         if (ret >= 0 && val > 3)
766                 ret = -EINVAL;
767         if (ret < 0) {
768                 ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
769                 goto bail;
770         }
771
772         /*
773          * Set the "intentional" heartbeat enable per either of
774          * "Enable" and "Auto", as these are normally set together.
775          * This bit is consulted when leaving loopback mode,
776          * because entering loopback mode overrides it and automatically
777          * disables heartbeat.
778          */
779         r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val);
780         if (r < 0)
781                 ret = r;
782         else if (val == IPATH_IB_HRTBT_OFF)
783                 dd->ipath_flags |= IPATH_NO_HRTBT;
784         else
785                 dd->ipath_flags &= ~IPATH_NO_HRTBT;
786
787 bail:
788         return ret;
789 }
790
791 /*
792  * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric,
793  * _not_ the particular encoding of any given chip)
794  */
795 static ssize_t show_lwid_enb(struct device *dev,
796                          struct device_attribute *attr,
797                          char *buf)
798 {
799         struct ipath_devdata *dd = dev_get_drvdata(dev);
800         int ret;
801
802         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB);
803         if (ret >= 0)
804                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
805         return ret;
806 }
807
808 static ssize_t store_lwid_enb(struct device *dev,
809                           struct device_attribute *attr,
810                           const char *buf,
811                           size_t count)
812 {
813         struct ipath_devdata *dd = dev_get_drvdata(dev);
814         int ret, r;
815         u16 val;
816
817         ret = ipath_parse_ushort(buf, &val);
818         if (ret >= 0 && (val == 0 || val > 3))
819                 ret = -EINVAL;
820         if (ret < 0) {
821                 ipath_dev_err(dd,
822                         "attempt to set invalid Link Width (enable)\n");
823                 goto bail;
824         }
825
826         r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val);
827         if (r < 0)
828                 ret = r;
829
830 bail:
831         return ret;
832 }
833
834 /* Get current link width */
835 static ssize_t show_lwid(struct device *dev,
836                          struct device_attribute *attr,
837                          char *buf)
838
839 {
840         struct ipath_devdata *dd = dev_get_drvdata(dev);
841         int ret;
842
843         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID);
844         if (ret >= 0)
845                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
846         return ret;
847 }
848
849 /*
850  * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR.
851  */
852 static ssize_t show_spd_enb(struct device *dev,
853                          struct device_attribute *attr,
854                          char *buf)
855 {
856         struct ipath_devdata *dd = dev_get_drvdata(dev);
857         int ret;
858
859         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB);
860         if (ret >= 0)
861                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
862         return ret;
863 }
864
865 static ssize_t store_spd_enb(struct device *dev,
866                           struct device_attribute *attr,
867                           const char *buf,
868                           size_t count)
869 {
870         struct ipath_devdata *dd = dev_get_drvdata(dev);
871         int ret, r;
872         u16 val;
873
874         ret = ipath_parse_ushort(buf, &val);
875         if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR)))
876                 ret = -EINVAL;
877         if (ret < 0) {
878                 ipath_dev_err(dd,
879                         "attempt to set invalid Link Speed (enable)\n");
880                 goto bail;
881         }
882
883         r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val);
884         if (r < 0)
885                 ret = r;
886
887 bail:
888         return ret;
889 }
890
891 /* Get current link speed */
892 static ssize_t show_spd(struct device *dev,
893                          struct device_attribute *attr,
894                          char *buf)
895 {
896         struct ipath_devdata *dd = dev_get_drvdata(dev);
897         int ret;
898
899         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD);
900         if (ret >= 0)
901                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
902         return ret;
903 }
904
905 /*
906  * Get/Set RX polarity-invert enable. 0=no, 1=yes.
907  */
908 static ssize_t show_rx_polinv_enb(struct device *dev,
909                          struct device_attribute *attr,
910                          char *buf)
911 {
912         struct ipath_devdata *dd = dev_get_drvdata(dev);
913         int ret;
914
915         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB);
916         if (ret >= 0)
917                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
918         return ret;
919 }
920
921 static ssize_t store_rx_polinv_enb(struct device *dev,
922                           struct device_attribute *attr,
923                           const char *buf,
924                           size_t count)
925 {
926         struct ipath_devdata *dd = dev_get_drvdata(dev);
927         int ret, r;
928         u16 val;
929
930         ret = ipath_parse_ushort(buf, &val);
931         if (ret < 0 || val > 1)
932                 goto invalid;
933
934         r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
935         if (r < 0) {
936                 ret = r;
937                 goto bail;
938         }
939
940         goto bail;
941 invalid:
942         ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
943 bail:
944         return ret;
945 }
946 /*
947  * Get/Set RX lane-reversal enable. 0=no, 1=yes.
948  */
949 static ssize_t show_lanerev_enb(struct device *dev,
950                          struct device_attribute *attr,
951                          char *buf)
952 {
953         struct ipath_devdata *dd = dev_get_drvdata(dev);
954         int ret;
955
956         ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB);
957         if (ret >= 0)
958                 ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
959         return ret;
960 }
961
962 static ssize_t store_lanerev_enb(struct device *dev,
963                           struct device_attribute *attr,
964                           const char *buf,
965                           size_t count)
966 {
967         struct ipath_devdata *dd = dev_get_drvdata(dev);
968         int ret, r;
969         u16 val;
970
971         ret = ipath_parse_ushort(buf, &val);
972         if (ret >= 0 && val > 1) {
973                 ret = -EINVAL;
974                 ipath_dev_err(dd,
975                         "attempt to set invalid Lane reversal (enable)\n");
976                 goto bail;
977         }
978
979         r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val);
980         if (r < 0)
981                 ret = r;
982
983 bail:
984         return ret;
985 }
986
987 static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
988 static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
989
990 static struct attribute *driver_attributes[] = {
991         &driver_attr_num_units.attr,
992         &driver_attr_version.attr,
993         NULL
994 };
995
996 static struct attribute_group driver_attr_group = {
997         .attrs = driver_attributes
998 };
999
1000 struct attribute_group *ipath_driver_attr_groups[] = {
1001         &driver_attr_group,
1002         NULL,
1003 };
1004
1005 static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
1006 static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc);
1007 static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
1008 static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
1009 static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
1010 static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
1011 static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
1012 static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
1013 static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL);
1014 static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
1015 static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
1016 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
1017 static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
1018 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
1019 static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
1020 static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
1021 static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
1022 static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
1023 static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
1024 static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
1025                    show_jint_max_packets, store_jint_max_packets);
1026 static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
1027                    show_jint_idle_ticks, store_jint_idle_ticks);
1028
1029 static struct attribute *dev_attributes[] = {
1030         &dev_attr_guid.attr,
1031         &dev_attr_lmc.attr,
1032         &dev_attr_lid.attr,
1033         &dev_attr_link_state.attr,
1034         &dev_attr_mlid.attr,
1035         &dev_attr_mtu.attr,
1036         &dev_attr_nguid.attr,
1037         &dev_attr_nports.attr,
1038         &dev_attr_serial.attr,
1039         &dev_attr_status.attr,
1040         &dev_attr_status_str.attr,
1041         &dev_attr_boardversion.attr,
1042         &dev_attr_unit.attr,
1043         &dev_attr_enabled.attr,
1044         &dev_attr_rx_pol_inv.attr,
1045         &dev_attr_led_override.attr,
1046         &dev_attr_logged_errors.attr,
1047         &dev_attr_localbus_info.attr,
1048         NULL
1049 };
1050
1051 static struct attribute_group dev_attr_group = {
1052         .attrs = dev_attributes
1053 };
1054
1055 static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
1056                    store_hrtbt_enb);
1057 static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb,
1058                    store_lwid_enb);
1059 static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL);
1060 static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb,
1061                    store_spd_enb);
1062 static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL);
1063 static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb,
1064                    store_rx_polinv_enb);
1065 static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb,
1066                    store_lanerev_enb);
1067
1068 static struct attribute *dev_ibcfg_attributes[] = {
1069         &dev_attr_hrtbt_enable.attr,
1070         &dev_attr_link_width_enable.attr,
1071         &dev_attr_link_width.attr,
1072         &dev_attr_link_speed_enable.attr,
1073         &dev_attr_link_speed.attr,
1074         &dev_attr_rx_pol_inv_enable.attr,
1075         &dev_attr_rx_lane_rev_enable.attr,
1076         NULL
1077 };
1078
1079 static struct attribute_group dev_ibcfg_attr_group = {
1080         .attrs = dev_ibcfg_attributes
1081 };
1082
1083 /**
1084  * ipath_expose_reset - create a device reset file
1085  * @dev: the device structure
1086  *
1087  * Only expose a file that lets us reset the device after someone
1088  * enters diag mode.  A device reset is quite likely to crash the
1089  * machine entirely, so we don't want to normally make it
1090  * available.
1091  *
1092  * Called with ipath_mutex held.
1093  */
1094 int ipath_expose_reset(struct device *dev)
1095 {
1096         static int exposed;
1097         int ret;
1098
1099         if (!exposed) {
1100                 ret = device_create_file(dev, &dev_attr_reset);
1101                 exposed = 1;
1102         }
1103         else
1104                 ret = 0;
1105
1106         return ret;
1107 }
1108
1109 int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
1110 {
1111         int ret;
1112
1113         ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
1114         if (ret)
1115                 goto bail;
1116
1117         ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
1118         if (ret)
1119                 goto bail_attrs;
1120
1121         if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
1122                 ret = device_create_file(dev, &dev_attr_jint_idle_ticks);
1123                 if (ret)
1124                         goto bail_counter;
1125                 ret = device_create_file(dev, &dev_attr_jint_max_packets);
1126                 if (ret)
1127                         goto bail_idle;
1128
1129                 ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group);
1130                 if (ret)
1131                         goto bail_max;
1132         }
1133
1134         return 0;
1135
1136 bail_max:
1137         device_remove_file(dev, &dev_attr_jint_max_packets);
1138 bail_idle:
1139         device_remove_file(dev, &dev_attr_jint_idle_ticks);
1140 bail_counter:
1141         sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
1142 bail_attrs:
1143         sysfs_remove_group(&dev->kobj, &dev_attr_group);
1144 bail:
1145         return ret;
1146 }
1147
1148 void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
1149 {
1150         sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
1151
1152         if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
1153                 sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group);
1154                 device_remove_file(dev, &dev_attr_jint_idle_ticks);
1155                 device_remove_file(dev, &dev_attr_jint_max_packets);
1156         }
1157
1158         sysfs_remove_group(&dev->kobj, &dev_attr_group);
1159
1160         device_remove_file(dev, &dev_attr_reset);
1161 }