[PATCH] IB/ipath: purge sps_lid and sps_mlid arrays
[safe/jmp/linux-2.6] / drivers / infiniband / hw / ipath / ipath_sysfs.c
1 /*
2  * Copyright (c) 2006 QLogic, Inc. 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 #include <linux/pci.h>
36
37 #include "ipath_kernel.h"
38 #include "ips_common.h"
39 #include "ipath_layer.h"
40
41 /**
42  * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
43  * @str: the string containing the number
44  * @valp: where to put the result
45  *
46  * returns the number of bytes consumed, or negative value on error
47  */
48 int ipath_parse_ushort(const char *str, unsigned short *valp)
49 {
50         unsigned long val;
51         char *end;
52         int ret;
53
54         if (!isdigit(str[0])) {
55                 ret = -EINVAL;
56                 goto bail;
57         }
58
59         val = simple_strtoul(str, &end, 0);
60
61         if (val > 0xffff) {
62                 ret = -EINVAL;
63                 goto bail;
64         }
65
66         *valp = val;
67
68         ret = end + 1 - str;
69         if (ret == 0)
70                 ret = -EINVAL;
71
72 bail:
73         return ret;
74 }
75
76 static ssize_t show_version(struct device_driver *dev, char *buf)
77 {
78         /* The string printed here is already newline-terminated. */
79         return scnprintf(buf, PAGE_SIZE, "%s", ipath_core_version);
80 }
81
82 static ssize_t show_num_units(struct device_driver *dev, char *buf)
83 {
84         return scnprintf(buf, PAGE_SIZE, "%d\n",
85                          ipath_count_units(NULL, NULL, NULL));
86 }
87
88 #define DRIVER_STAT(name, attr) \
89         static ssize_t show_stat_##name(struct device_driver *dev, \
90                                         char *buf) \
91         { \
92                 return scnprintf( \
93                         buf, PAGE_SIZE, "%llu\n", \
94                         (unsigned long long) ipath_stats.sps_ ##attr); \
95         } \
96         static DRIVER_ATTR(name, S_IRUGO, show_stat_##name, NULL)
97
98 DRIVER_STAT(intrs, ints);
99 DRIVER_STAT(err_intrs, errints);
100 DRIVER_STAT(errs, errs);
101 DRIVER_STAT(pkt_errs, pkterrs);
102 DRIVER_STAT(crc_errs, crcerrs);
103 DRIVER_STAT(hw_errs, hwerrs);
104 DRIVER_STAT(ib_link, iblink);
105 DRIVER_STAT(port0_pkts, port0pkts);
106 DRIVER_STAT(ether_spkts, ether_spkts);
107 DRIVER_STAT(ether_rpkts, ether_rpkts);
108 DRIVER_STAT(sma_spkts, sma_spkts);
109 DRIVER_STAT(sma_rpkts, sma_rpkts);
110 DRIVER_STAT(hdrq_full, hdrqfull);
111 DRIVER_STAT(etid_full, etidfull);
112 DRIVER_STAT(no_piobufs, nopiobufs);
113 DRIVER_STAT(ports, ports);
114 DRIVER_STAT(pkey0, pkeys[0]);
115 DRIVER_STAT(pkey1, pkeys[1]);
116 DRIVER_STAT(pkey2, pkeys[2]);
117 DRIVER_STAT(pkey3, pkeys[3]);
118
119 DRIVER_STAT(nports, nports);
120 DRIVER_STAT(null_intr, nullintr);
121 DRIVER_STAT(max_pkts_call, maxpkts_call);
122 DRIVER_STAT(avg_pkts_call, avgpkts_call);
123 DRIVER_STAT(page_locks, pagelocks);
124 DRIVER_STAT(page_unlocks, pageunlocks);
125 DRIVER_STAT(krdrops, krdrops);
126
127 static struct attribute *driver_stat_attributes[] = {
128         &driver_attr_intrs.attr,
129         &driver_attr_err_intrs.attr,
130         &driver_attr_errs.attr,
131         &driver_attr_pkt_errs.attr,
132         &driver_attr_crc_errs.attr,
133         &driver_attr_hw_errs.attr,
134         &driver_attr_ib_link.attr,
135         &driver_attr_port0_pkts.attr,
136         &driver_attr_ether_spkts.attr,
137         &driver_attr_ether_rpkts.attr,
138         &driver_attr_sma_spkts.attr,
139         &driver_attr_sma_rpkts.attr,
140         &driver_attr_hdrq_full.attr,
141         &driver_attr_etid_full.attr,
142         &driver_attr_no_piobufs.attr,
143         &driver_attr_ports.attr,
144         &driver_attr_pkey0.attr,
145         &driver_attr_pkey1.attr,
146         &driver_attr_pkey2.attr,
147         &driver_attr_pkey3.attr,
148         &driver_attr_nports.attr,
149         &driver_attr_null_intr.attr,
150         &driver_attr_max_pkts_call.attr,
151         &driver_attr_avg_pkts_call.attr,
152         &driver_attr_page_locks.attr,
153         &driver_attr_page_unlocks.attr,
154         &driver_attr_krdrops.attr,
155         NULL
156 };
157
158 static struct attribute_group driver_stat_attr_group = {
159         .name = "stats",
160         .attrs = driver_stat_attributes
161 };
162
163 static ssize_t show_status(struct device *dev,
164                            struct device_attribute *attr,
165                            char *buf)
166 {
167         struct ipath_devdata *dd = dev_get_drvdata(dev);
168         ssize_t ret;
169
170         if (!dd->ipath_statusp) {
171                 ret = -EINVAL;
172                 goto bail;
173         }
174
175         ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
176                         (unsigned long long) *(dd->ipath_statusp));
177
178 bail:
179         return ret;
180 }
181
182 static const char *ipath_status_str[] = {
183         "Initted",
184         "Disabled",
185         "Admin_Disabled",
186         "OIB_SMA",
187         "SMA",
188         "Present",
189         "IB_link_up",
190         "IB_configured",
191         "NoIBcable",
192         "Fatal_Hardware_Error",
193         NULL,
194 };
195
196 static ssize_t show_status_str(struct device *dev,
197                                struct device_attribute *attr,
198                                char *buf)
199 {
200         struct ipath_devdata *dd = dev_get_drvdata(dev);
201         int i, any;
202         u64 s;
203         ssize_t ret;
204
205         if (!dd->ipath_statusp) {
206                 ret = -EINVAL;
207                 goto bail;
208         }
209
210         s = *(dd->ipath_statusp);
211         *buf = '\0';
212         for (any = i = 0; s && ipath_status_str[i]; i++) {
213                 if (s & 1) {
214                         if (any && strlcat(buf, " ", PAGE_SIZE) >=
215                             PAGE_SIZE)
216                                 /* overflow */
217                                 break;
218                         if (strlcat(buf, ipath_status_str[i],
219                                     PAGE_SIZE) >= PAGE_SIZE)
220                                 break;
221                         any = 1;
222                 }
223                 s >>= 1;
224         }
225         if (any)
226                 strlcat(buf, "\n", PAGE_SIZE);
227
228         ret = strlen(buf);
229
230 bail:
231         return ret;
232 }
233
234 static ssize_t show_boardversion(struct device *dev,
235                                struct device_attribute *attr,
236                                char *buf)
237 {
238         struct ipath_devdata *dd = dev_get_drvdata(dev);
239         /* The string printed here is already newline-terminated. */
240         return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
241 }
242
243 static ssize_t show_lid(struct device *dev,
244                         struct device_attribute *attr,
245                         char *buf)
246 {
247         struct ipath_devdata *dd = dev_get_drvdata(dev);
248
249         return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
250 }
251
252 static ssize_t store_lid(struct device *dev,
253                          struct device_attribute *attr,
254                           const char *buf,
255                           size_t count)
256 {
257         struct ipath_devdata *dd = dev_get_drvdata(dev);
258         u16 lid = 0;
259         int ret;
260
261         ret = ipath_parse_ushort(buf, &lid);
262         if (ret < 0)
263                 goto invalid;
264
265         if (lid == 0 || lid >= IPS_MULTICAST_LID_BASE) {
266                 ret = -EINVAL;
267                 goto invalid;
268         }
269
270         ipath_set_lid(dd, lid, 0);
271
272         goto bail;
273 invalid:
274         ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid);
275 bail:
276         return ret;
277 }
278
279 static ssize_t show_mlid(struct device *dev,
280                          struct device_attribute *attr,
281                          char *buf)
282 {
283         struct ipath_devdata *dd = dev_get_drvdata(dev);
284
285         return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
286 }
287
288 static ssize_t store_mlid(struct device *dev,
289                          struct device_attribute *attr,
290                           const char *buf,
291                           size_t count)
292 {
293         struct ipath_devdata *dd = dev_get_drvdata(dev);
294         int unit;
295         u16 mlid;
296         int ret;
297
298         ret = ipath_parse_ushort(buf, &mlid);
299         if (ret < 0 || mlid < IPS_MULTICAST_LID_BASE)
300                 goto invalid;
301
302         unit = dd->ipath_unit;
303
304         dd->ipath_mlid = mlid;
305         ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST);
306
307         goto bail;
308 invalid:
309         ipath_dev_err(dd, "attempt to set invalid MLID\n");
310 bail:
311         return ret;
312 }
313
314 static ssize_t show_guid(struct device *dev,
315                          struct device_attribute *attr,
316                          char *buf)
317 {
318         struct ipath_devdata *dd = dev_get_drvdata(dev);
319         u8 *guid;
320
321         guid = (u8 *) & (dd->ipath_guid);
322
323         return scnprintf(buf, PAGE_SIZE,
324                          "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
325                          guid[0], guid[1], guid[2], guid[3],
326                          guid[4], guid[5], guid[6], guid[7]);
327 }
328
329 static ssize_t store_guid(struct device *dev,
330                          struct device_attribute *attr,
331                           const char *buf,
332                           size_t count)
333 {
334         struct ipath_devdata *dd = dev_get_drvdata(dev);
335         ssize_t ret;
336         unsigned short guid[8];
337         __be64 nguid;
338         u8 *ng;
339         int i;
340
341         if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
342                    &guid[0], &guid[1], &guid[2], &guid[3],
343                    &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
344                 goto invalid;
345
346         ng = (u8 *) &nguid;
347
348         for (i = 0; i < 8; i++) {
349                 if (guid[i] > 0xff)
350                         goto invalid;
351                 ng[i] = guid[i];
352         }
353
354         dd->ipath_guid = nguid;
355         dd->ipath_nguid = 1;
356
357         ret = strlen(buf);
358         goto bail;
359
360 invalid:
361         ipath_dev_err(dd, "attempt to set invalid GUID\n");
362         ret = -EINVAL;
363
364 bail:
365         return ret;
366 }
367
368 static ssize_t show_nguid(struct device *dev,
369                           struct device_attribute *attr,
370                           char *buf)
371 {
372         struct ipath_devdata *dd = dev_get_drvdata(dev);
373
374         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
375 }
376
377 static ssize_t show_serial(struct device *dev,
378                            struct device_attribute *attr,
379                            char *buf)
380 {
381         struct ipath_devdata *dd = dev_get_drvdata(dev);
382
383         buf[sizeof dd->ipath_serial] = '\0';
384         memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
385         strcat(buf, "\n");
386         return strlen(buf);
387 }
388
389 static ssize_t show_unit(struct device *dev,
390                          struct device_attribute *attr,
391                          char *buf)
392 {
393         struct ipath_devdata *dd = dev_get_drvdata(dev);
394
395         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
396 }
397
398 #define DEVICE_COUNTER(name, attr) \
399         static ssize_t show_counter_##name(struct device *dev, \
400                                            struct device_attribute *attr, \
401                                            char *buf) \
402         { \
403                 struct ipath_devdata *dd = dev_get_drvdata(dev); \
404                 return scnprintf(\
405                         buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
406                         ipath_snap_cntr( \
407                                 dd, offsetof(struct infinipath_counters, \
408                                              attr) / sizeof(u64)));     \
409         } \
410         static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
411
412 DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
413 DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
414 DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
415 DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
416 DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
417 DEVICE_COUNTER(lb_ints, LBIntCnt);
418 DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
419 DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
420 DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
421 DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
422 DEVICE_COUNTER(rx_dwords, RxDwordCnt);
423 DEVICE_COUNTER(rx_ebps, RxEBPCnt);
424 DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
425 DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
426 DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
427 DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
428 DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
429 DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
430 DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
431 DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
432 DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
433 DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
434 DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
435 DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
436 DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
437 DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
438 DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
439 DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
440 DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
441 DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
442 DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
443 DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
444 DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
445 DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
446 DEVICE_COUNTER(tx_dwords, TxDwordCnt);
447 DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
448 DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
449 DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
450 DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
451 DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
452 DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
453
454 static struct attribute *dev_counter_attributes[] = {
455         &dev_attr_ib_link_downeds.attr,
456         &dev_attr_ib_link_err_recoveries.attr,
457         &dev_attr_ib_status_changes.attr,
458         &dev_attr_ib_symbol_errs.attr,
459         &dev_attr_lb_flow_stalls.attr,
460         &dev_attr_lb_ints.attr,
461         &dev_attr_rx_bad_formats.attr,
462         &dev_attr_rx_buf_ovfls.attr,
463         &dev_attr_rx_data_pkts.attr,
464         &dev_attr_rx_dropped_pkts.attr,
465         &dev_attr_rx_dwords.attr,
466         &dev_attr_rx_ebps.attr,
467         &dev_attr_rx_flow_ctrl_errs.attr,
468         &dev_attr_rx_flow_pkts.attr,
469         &dev_attr_rx_icrc_errs.attr,
470         &dev_attr_rx_len_errs.attr,
471         &dev_attr_rx_link_problems.attr,
472         &dev_attr_rx_lpcrc_errs.attr,
473         &dev_attr_rx_max_min_len_errs.attr,
474         &dev_attr_rx_p0_hdr_egr_ovfls.attr,
475         &dev_attr_rx_p1_hdr_egr_ovfls.attr,
476         &dev_attr_rx_p2_hdr_egr_ovfls.attr,
477         &dev_attr_rx_p3_hdr_egr_ovfls.attr,
478         &dev_attr_rx_p4_hdr_egr_ovfls.attr,
479         &dev_attr_rx_p5_hdr_egr_ovfls.attr,
480         &dev_attr_rx_p6_hdr_egr_ovfls.attr,
481         &dev_attr_rx_p7_hdr_egr_ovfls.attr,
482         &dev_attr_rx_p8_hdr_egr_ovfls.attr,
483         &dev_attr_rx_pkey_mismatches.attr,
484         &dev_attr_rx_tid_full_errs.attr,
485         &dev_attr_rx_tid_valid_errs.attr,
486         &dev_attr_rx_vcrc_errs.attr,
487         &dev_attr_tx_data_pkts.attr,
488         &dev_attr_tx_dropped_pkts.attr,
489         &dev_attr_tx_dwords.attr,
490         &dev_attr_tx_flow_pkts.attr,
491         &dev_attr_tx_flow_stalls.attr,
492         &dev_attr_tx_len_errs.attr,
493         &dev_attr_tx_max_min_len_errs.attr,
494         &dev_attr_tx_underruns.attr,
495         &dev_attr_tx_unsup_vl_errs.attr,
496         NULL
497 };
498
499 static struct attribute_group dev_counter_attr_group = {
500         .name = "counters",
501         .attrs = dev_counter_attributes
502 };
503
504 static ssize_t store_reset(struct device *dev,
505                          struct device_attribute *attr,
506                           const char *buf,
507                           size_t count)
508 {
509         struct ipath_devdata *dd = dev_get_drvdata(dev);
510         int ret;
511
512         if (count < 5 || memcmp(buf, "reset", 5)) {
513                 ret = -EINVAL;
514                 goto bail;
515         }
516
517         if (dd->ipath_flags & IPATH_DISABLED) {
518                 /*
519                  * post-reset init would re-enable interrupts, etc.
520                  * so don't allow reset on disabled devices.  Not
521                  * perfect error, but about the best choice.
522                  */
523                 dev_info(dev,"Unit %d is disabled, can't reset\n",
524                          dd->ipath_unit);
525                 ret = -EINVAL;
526         }
527         ret = ipath_reset_device(dd->ipath_unit);
528 bail:
529         return ret<0 ? ret : count;
530 }
531
532 static ssize_t store_link_state(struct device *dev,
533                          struct device_attribute *attr,
534                           const char *buf,
535                           size_t count)
536 {
537         struct ipath_devdata *dd = dev_get_drvdata(dev);
538         int ret, r;
539         u16 state;
540
541         ret = ipath_parse_ushort(buf, &state);
542         if (ret < 0)
543                 goto invalid;
544
545         r = ipath_layer_set_linkstate(dd, state);
546         if (r < 0) {
547                 ret = r;
548                 goto bail;
549         }
550
551         goto bail;
552 invalid:
553         ipath_dev_err(dd, "attempt to set invalid link state\n");
554 bail:
555         return ret;
556 }
557
558 static ssize_t show_mtu(struct device *dev,
559                          struct device_attribute *attr,
560                          char *buf)
561 {
562         struct ipath_devdata *dd = dev_get_drvdata(dev);
563         return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
564 }
565
566 static ssize_t store_mtu(struct device *dev,
567                          struct device_attribute *attr,
568                           const char *buf,
569                           size_t count)
570 {
571         struct ipath_devdata *dd = dev_get_drvdata(dev);
572         ssize_t ret;
573         u16 mtu = 0;
574         int r;
575
576         ret = ipath_parse_ushort(buf, &mtu);
577         if (ret < 0)
578                 goto invalid;
579
580         r = ipath_layer_set_mtu(dd, mtu);
581         if (r < 0)
582                 ret = r;
583
584         goto bail;
585 invalid:
586         ipath_dev_err(dd, "attempt to set invalid MTU\n");
587 bail:
588         return ret;
589 }
590
591 static ssize_t show_enabled(struct device *dev,
592                          struct device_attribute *attr,
593                          char *buf)
594 {
595         struct ipath_devdata *dd = dev_get_drvdata(dev);
596         return scnprintf(buf, PAGE_SIZE, "%u\n",
597                          (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
598 }
599
600 static ssize_t store_enabled(struct device *dev,
601                          struct device_attribute *attr,
602                           const char *buf,
603                           size_t count)
604 {
605         struct ipath_devdata *dd = dev_get_drvdata(dev);
606         ssize_t ret;
607         u16 enable = 0;
608
609         ret = ipath_parse_ushort(buf, &enable);
610         if (ret < 0) {
611                 ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
612                 goto bail;
613         }
614
615         if (enable) {
616                 if (!(dd->ipath_flags & IPATH_DISABLED))
617                         goto bail;
618
619                 dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
620                 /* same as post-reset */
621                 ret = ipath_init_chip(dd, 1);
622                 if (ret)
623                         ipath_dev_err(dd, "Failed to enable unit %d\n",
624                                       dd->ipath_unit);
625                 else {
626                         dd->ipath_flags &= ~IPATH_DISABLED;
627                         *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
628                 }
629         }
630         else if (!(dd->ipath_flags & IPATH_DISABLED)) {
631                 dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
632                 ipath_shutdown_device(dd);
633                 dd->ipath_flags |= IPATH_DISABLED;
634                 *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
635         }
636
637 bail:
638         return ret;
639 }
640
641 static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
642 static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
643
644 static struct attribute *driver_attributes[] = {
645         &driver_attr_num_units.attr,
646         &driver_attr_version.attr,
647         NULL
648 };
649
650 static struct attribute_group driver_attr_group = {
651         .attrs = driver_attributes
652 };
653
654 static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
655 static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
656 static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
657 static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
658 static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
659 static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
660 static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
661 static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
662 static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
663 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
664 static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
665 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
666 static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
667
668 static struct attribute *dev_attributes[] = {
669         &dev_attr_guid.attr,
670         &dev_attr_lid.attr,
671         &dev_attr_link_state.attr,
672         &dev_attr_mlid.attr,
673         &dev_attr_mtu.attr,
674         &dev_attr_nguid.attr,
675         &dev_attr_serial.attr,
676         &dev_attr_status.attr,
677         &dev_attr_status_str.attr,
678         &dev_attr_boardversion.attr,
679         &dev_attr_unit.attr,
680         &dev_attr_enabled.attr,
681         NULL
682 };
683
684 static struct attribute_group dev_attr_group = {
685         .attrs = dev_attributes
686 };
687
688 /**
689  * ipath_expose_reset - create a device reset file
690  * @dev: the device structure
691  *
692  * Only expose a file that lets us reset the device after someone
693  * enters diag mode.  A device reset is quite likely to crash the
694  * machine entirely, so we don't want to normally make it
695  * available.
696  *
697  * Called with ipath_mutex held.
698  */
699 int ipath_expose_reset(struct device *dev)
700 {
701         static int exposed;
702         int ret;
703
704         if (!exposed) {
705                 ret = device_create_file(dev, &dev_attr_reset);
706                 exposed = 1;
707         }
708         else
709                 ret = 0;
710
711         return ret;
712 }
713
714 int ipath_driver_create_group(struct device_driver *drv)
715 {
716         int ret;
717
718         ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
719         if (ret)
720                 goto bail;
721
722         ret = sysfs_create_group(&drv->kobj, &driver_stat_attr_group);
723         if (ret)
724                 sysfs_remove_group(&drv->kobj, &driver_attr_group);
725
726 bail:
727         return ret;
728 }
729
730 void ipath_driver_remove_group(struct device_driver *drv)
731 {
732         sysfs_remove_group(&drv->kobj, &driver_stat_attr_group);
733         sysfs_remove_group(&drv->kobj, &driver_attr_group);
734 }
735
736 int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
737 {
738         int ret;
739         char unit[5];
740
741         ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
742         if (ret)
743                 goto bail;
744
745         ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
746         if (ret)
747                 goto bail_attrs;
748
749         snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
750         ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
751         if (ret == 0)
752                 goto bail;
753
754         sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
755 bail_attrs:
756         sysfs_remove_group(&dev->kobj, &dev_attr_group);
757 bail:
758         return ret;
759 }
760
761 void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
762 {
763         char unit[5];
764
765         snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
766         sysfs_remove_link(&dev->driver->kobj, unit);
767
768         sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
769         sysfs_remove_group(&dev->kobj, &dev_attr_group);
770
771         device_remove_file(dev, &dev_attr_reset);
772 }