ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / s390 / net / qeth_sys.c
1 /*
2  *
3  * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.24 $)
4  *
5  * Linux on zSeries OSA Express and HiperSockets support
6  * This file contains code related to sysfs.
7  *
8  * Copyright 2000,2003 IBM Corporation
9  *
10  * Author(s): Thomas Spatzier <tspat@de.ibm.com>
11  *            Frank Pavlic <pavlic@de.ibm.com>
12  *
13  */
14 #include <linux/list.h>
15 #include <linux/rwsem.h>
16
17 #include <asm/ebcdic.h>
18
19 #include "qeth.h"
20 #include "qeth_mpc.h"
21 #include "qeth_fs.h"
22
23 /*****************************************************************************/
24 /*                                                                           */
25 /*          /sys-fs stuff UNDER DEVELOPMENT !!!                              */
26 /*                                                                           */
27 /*****************************************************************************/
28 //low/high watermark
29
30 static ssize_t
31 qeth_dev_state_show(struct device *dev, char *buf)
32 {
33         struct qeth_card *card = dev->driver_data;
34         if (!card)
35                 return -EINVAL;
36
37         switch (card->state) {
38         case CARD_STATE_DOWN:
39                 return sprintf(buf, "DOWN\n");
40         case CARD_STATE_HARDSETUP:
41                 return sprintf(buf, "HARDSETUP\n");
42         case CARD_STATE_SOFTSETUP:
43                 return sprintf(buf, "SOFTSETUP\n");
44         case CARD_STATE_UP:
45                 if (card->lan_online)
46                 return sprintf(buf, "UP (LAN ONLINE)\n");
47                 else
48                         return sprintf(buf, "UP (LAN OFFLINE)\n");
49         case CARD_STATE_RECOVER:
50                 return sprintf(buf, "RECOVER\n");
51         default:
52                 return sprintf(buf, "UNKNOWN\n");
53         }
54 }
55
56 static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
57
58 static ssize_t
59 qeth_dev_chpid_show(struct device *dev, char *buf)
60 {
61         struct qeth_card *card = dev->driver_data;
62         if (!card)
63                 return -EINVAL;
64
65         return sprintf(buf, "%02X\n", card->info.chpid);
66 }
67
68 static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
69
70 static ssize_t
71 qeth_dev_if_name_show(struct device *dev, char *buf)
72 {
73         struct qeth_card *card = dev->driver_data;
74         if (!card)
75                 return -EINVAL;
76
77         return sprintf(buf, "%s\n", card->info.if_name);
78 }
79
80 static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
81
82 static ssize_t
83 qeth_dev_card_type_show(struct device *dev, char *buf)
84 {
85         struct qeth_card *card = dev->driver_data;
86         if (!card)
87                 return -EINVAL;
88
89         return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
90 }
91
92 static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
93
94 static ssize_t
95 qeth_dev_portno_show(struct device *dev, char *buf)
96 {
97         struct qeth_card *card = dev->driver_data;
98         if (!card)
99                 return -EINVAL;
100
101         return sprintf(buf, "%i\n", card->info.portno);
102 }
103
104 static ssize_t
105 qeth_dev_portno_store(struct device *dev, const char *buf, size_t count)
106 {
107         struct qeth_card *card = dev->driver_data;
108         char *tmp;
109         unsigned int portno;
110
111         if (!card)
112                 return -EINVAL;
113
114         if ((card->state != CARD_STATE_DOWN) &&
115             (card->state != CARD_STATE_RECOVER))
116                 return -EPERM;
117
118         portno = simple_strtoul(buf, &tmp, 16);
119         if ((portno < 0) || (portno > MAX_PORTNO)){
120                 PRINT_WARN("portno 0x%X is out of range\n", portno);
121                 return -EINVAL;
122         }
123
124         card->info.portno = portno;
125         return count;
126 }
127
128 static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
129
130 static ssize_t
131 qeth_dev_portname_show(struct device *dev, char *buf)
132 {
133         struct qeth_card *card = dev->driver_data;
134         char portname[9] = {0, };
135
136         if (!card)
137                 return -EINVAL;
138
139         if (card->info.portname_required) {
140                 memcpy(portname, card->info.portname + 1, 8);
141                 EBCASC(portname, 8);
142                 return sprintf(buf, "%s\n", portname);
143         } else
144                 return sprintf(buf, "no portname required\n");
145 }
146
147 static ssize_t
148 qeth_dev_portname_store(struct device *dev, const char *buf, size_t count)
149 {
150         struct qeth_card *card = dev->driver_data;
151         char *tmp;
152         int i;
153
154         if (!card)
155                 return -EINVAL;
156
157         if ((card->state != CARD_STATE_DOWN) &&
158             (card->state != CARD_STATE_RECOVER))
159                 return -EPERM;
160
161         tmp = strsep((char **) &buf, "\n");
162         if ((strlen(tmp) > 8) || (strlen(tmp) < 2))
163                 return -EINVAL;
164
165         card->info.portname[0] = strlen(tmp);
166         /* for beauty reasons */
167         for (i = 1; i < 9; i++)
168                 card->info.portname[i] = ' ';
169         strcpy(card->info.portname + 1, tmp);
170         ASCEBC(card->info.portname + 1, 8);
171
172         return count;
173 }
174
175 static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
176                 qeth_dev_portname_store);
177
178 static ssize_t
179 qeth_dev_checksum_show(struct device *dev, char *buf)
180 {
181         struct qeth_card *card = dev->driver_data;
182
183         if (!card)
184                 return -EINVAL;
185
186         return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
187 }
188
189 static ssize_t
190 qeth_dev_checksum_store(struct device *dev, const char *buf, size_t count)
191 {
192         struct qeth_card *card = dev->driver_data;
193         char *tmp;
194
195         if (!card)
196                 return -EINVAL;
197
198         if ((card->state != CARD_STATE_DOWN) &&
199             (card->state != CARD_STATE_RECOVER))
200                 return -EPERM;
201
202         tmp = strsep((char **) &buf, "\n");
203         if (!strcmp(tmp, "sw_checksumming"))
204                 card->options.checksum_type = SW_CHECKSUMMING;
205         else if (!strcmp(tmp, "hw_checksumming"))
206                 card->options.checksum_type = HW_CHECKSUMMING;
207         else if (!strcmp(tmp, "no_checksumming"))
208                 card->options.checksum_type = NO_CHECKSUMMING;
209         else {
210                 PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
211                 return -EINVAL;
212         }
213         return count;
214 }
215
216 static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
217                 qeth_dev_checksum_store);
218
219 static ssize_t
220 qeth_dev_prioqing_show(struct device *dev, char *buf)
221 {
222         struct qeth_card *card = dev->driver_data;
223
224         if (!card)
225                 return -EINVAL;
226
227         switch (card->qdio.do_prio_queueing) {
228         case QETH_PRIO_Q_ING_PREC:
229                 return sprintf(buf, "%s\n", "by precedence");
230         case QETH_PRIO_Q_ING_TOS:
231                 return sprintf(buf, "%s\n", "by type of service");
232         default:
233                 return sprintf(buf, "always queue %i\n",
234                                card->qdio.default_out_queue);
235         }
236 }
237
238 static ssize_t
239 qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count)
240 {
241         struct qeth_card *card = dev->driver_data;
242         char *tmp;
243
244         if (!card)
245                 return -EINVAL;
246
247         if ((card->state != CARD_STATE_DOWN) &&
248             (card->state != CARD_STATE_RECOVER))
249                 return -EPERM;
250
251         tmp = strsep((char **) &buf, "\n");
252         if (!strcmp(tmp, "prio_queueing_prec"))
253                 card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
254         else if (!strcmp(tmp, "prio_queueing_tos"))
255                 card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
256         else if (!strcmp(tmp, "no_prio_queueing:0")) {
257                 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
258                 card->qdio.default_out_queue = 0;
259         } else if (!strcmp(tmp, "no_prio_queueing:1")) {
260                 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
261                 card->qdio.default_out_queue = 1;
262         } else if (!strcmp(tmp, "no_prio_queueing:2")) {
263                 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
264                 card->qdio.default_out_queue = 2;
265         } else if (!strcmp(tmp, "no_prio_queueing:3")) {
266                 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
267                 card->qdio.default_out_queue = 3;
268         } else if (!strcmp(tmp, "no_prio_queueing")) {
269                 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
270                 card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
271         } else {
272                 PRINT_WARN("Unknown queueing type '%s'\n", tmp);
273                 return -EINVAL;
274         }
275         return count;
276 }
277
278 static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
279                 qeth_dev_prioqing_store);
280
281 static ssize_t
282 qeth_dev_bufcnt_show(struct device *dev, char *buf)
283 {
284         struct qeth_card *card = dev->driver_data;
285
286         if (!card)
287                 return -EINVAL;
288
289         return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
290 }
291
292 static ssize_t
293 qeth_dev_bufcnt_store(struct device *dev, const char *buf, size_t count)
294 {
295         struct qeth_card *card = dev->driver_data;
296         char *tmp;
297         int cnt, old_cnt;
298         int rc;
299
300         if (!card)
301                 return -EINVAL;
302
303         if ((card->state != CARD_STATE_DOWN) &&
304             (card->state != CARD_STATE_RECOVER))
305                 return -EPERM;
306
307         old_cnt = card->qdio.in_buf_pool.buf_count;
308         cnt = simple_strtoul(buf, &tmp, 10);
309         cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
310                 ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
311         if (old_cnt != cnt) {
312                 if ((rc = qeth_realloc_buffer_pool(card, cnt)))
313                         PRINT_WARN("Error (%d) while setting "
314                                    "buffer count.\n", rc);
315         }
316         return count;
317 }
318
319 static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
320                 qeth_dev_bufcnt_store);
321
322 static inline ssize_t
323 qeth_dev_route_show(struct qeth_routing_info *route, char *buf)
324 {
325         switch (route->type) {
326         case PRIMARY_ROUTER:
327                 return sprintf(buf, "%s\n", "primary router");
328         case SECONDARY_ROUTER:
329                 return sprintf(buf, "%s\n", "secondary router");
330         case MULTICAST_ROUTER:
331                 return sprintf(buf, "%s\n", "multicast router");
332         case PRIMARY_CONNECTOR:
333                 return sprintf(buf, "%s\n", "primary connector");
334         case SECONDARY_CONNECTOR:
335                 return sprintf(buf, "%s\n", "secondary connector");
336         default:
337                 return sprintf(buf, "%s\n", "no");
338         }
339 }
340
341 static ssize_t
342 qeth_dev_route4_show(struct device *dev, char *buf)
343 {
344         struct qeth_card *card = dev->driver_data;
345
346         if (!card)
347                 return -EINVAL;
348
349         return qeth_dev_route_show(&card->options.route4, buf);
350 }
351
352 static inline ssize_t
353 qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
354                 enum qeth_prot_versions prot, const char *buf, size_t count)
355 {
356         enum qeth_routing_types old_route_type = route->type;
357         char *tmp;
358         int rc;
359
360         tmp = strsep((char **) &buf, "\n");
361
362         if (!strcmp(tmp, "no_router")){
363                 route->type = NO_ROUTER;
364         } else if (!strcmp(tmp, "primary_connector")) {
365                 route->type = PRIMARY_CONNECTOR;
366         } else if (!strcmp(tmp, "secondary_connector")) {
367                 route->type = SECONDARY_CONNECTOR;
368         } else if (!strcmp(tmp, "multicast_router")) {
369                 route->type = MULTICAST_ROUTER;
370         } else if (!strcmp(tmp, "primary_router")) {
371                 route->type = PRIMARY_ROUTER;
372         } else if (!strcmp(tmp, "secondary_router")) {
373                 route->type = SECONDARY_ROUTER;
374         } else if (!strcmp(tmp, "multicast_router")) {
375                 route->type = MULTICAST_ROUTER;
376         } else {
377                 PRINT_WARN("Invalid routing type '%s'.\n", tmp);
378                 return -EINVAL;
379         }
380         if (((card->state == CARD_STATE_SOFTSETUP) ||
381              (card->state == CARD_STATE_UP)) &&
382             (old_route_type != route->type)){
383                 if (prot == QETH_PROT_IPV4)
384                         rc = qeth_setrouting_v4(card);
385                 else if (prot == QETH_PROT_IPV6)
386                         rc = qeth_setrouting_v6(card);
387         }
388         return count;
389 }
390
391 static ssize_t
392 qeth_dev_route4_store(struct device *dev, const char *buf, size_t count)
393 {
394         struct qeth_card *card = dev->driver_data;
395
396         if (!card)
397                 return -EINVAL;
398
399         return qeth_dev_route_store(card, &card->options.route4,
400                                     QETH_PROT_IPV4, buf, count);
401 }
402
403 static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);
404
405 #ifdef CONFIG_QETH_IPV6
406 static ssize_t
407 qeth_dev_route6_show(struct device *dev, char *buf)
408 {
409         struct qeth_card *card = dev->driver_data;
410
411         if (!card)
412                 return -EINVAL;
413
414         if (!qeth_is_supported(card, IPA_IPV6))
415                 return sprintf(buf, "%s\n", "n/a");
416
417         return qeth_dev_route_show(&card->options.route6, buf);
418 }
419
420 static ssize_t
421 qeth_dev_route6_store(struct device *dev, const char *buf, size_t count)
422 {
423         struct qeth_card *card = dev->driver_data;
424
425         if (!card)
426                 return -EINVAL;
427
428         if (!qeth_is_supported(card, IPA_IPV6)){
429                 PRINT_WARN("IPv6 not supported for interface %s.\n"
430                            "Routing status no changed.\n",
431                            card->info.if_name);
432                 return -ENOTSUPP;
433         }
434
435         return qeth_dev_route_store(card, &card->options.route6,
436                                     QETH_PROT_IPV6, buf, count);
437 }
438
439 static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
440 #endif
441
442 static ssize_t
443 qeth_dev_add_hhlen_show(struct device *dev, char *buf)
444 {
445         struct qeth_card *card = dev->driver_data;
446
447         if (!card)
448                 return -EINVAL;
449
450         return sprintf(buf, "%i\n", card->options.add_hhlen);
451 }
452
453 static ssize_t
454 qeth_dev_add_hhlen_store(struct device *dev, const char *buf, size_t count)
455 {
456         struct qeth_card *card = dev->driver_data;
457         char *tmp;
458         int i;
459
460         if (!card)
461                 return -EINVAL;
462
463         if ((card->state != CARD_STATE_DOWN) &&
464             (card->state != CARD_STATE_RECOVER))
465                 return -EPERM;
466
467         i = simple_strtoul(buf, &tmp, 16);
468         if ((i < 0) || (i > MAX_ADD_HHLEN)) {
469                 PRINT_WARN("add_hhlen out of range\n");
470                 return -EINVAL;
471         }
472         card->options.add_hhlen = i;
473
474         return count;
475 }
476
477 static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
478                    qeth_dev_add_hhlen_store);
479
480 static ssize_t
481 qeth_dev_fake_ll_show(struct device *dev, char *buf)
482 {
483         struct qeth_card *card = dev->driver_data;
484
485         if (!card)
486                 return -EINVAL;
487
488         return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
489 }
490
491 static ssize_t
492 qeth_dev_fake_ll_store(struct device *dev, const char *buf, size_t count)
493 {
494         struct qeth_card *card = dev->driver_data;
495         char *tmp;
496         int i;
497
498         if (!card)
499                 return -EINVAL;
500
501         if ((card->state != CARD_STATE_DOWN) &&
502             (card->state != CARD_STATE_RECOVER))
503                 return -EPERM;
504
505         i = simple_strtoul(buf, &tmp, 16);
506         if ((i == 0) || (i == 1))
507                 card->options.fake_ll = i;
508         else {
509                 PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
510                 return -EINVAL;
511         }
512         return count;
513 }
514
515 static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
516                    qeth_dev_fake_ll_store);
517
518 static ssize_t
519 qeth_dev_fake_broadcast_show(struct device *dev, char *buf)
520 {
521         struct qeth_card *card = dev->driver_data;
522
523         if (!card)
524                 return -EINVAL;
525
526         return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
527 }
528
529 static ssize_t
530 qeth_dev_fake_broadcast_store(struct device *dev, const char *buf, size_t count)
531 {
532         struct qeth_card *card = dev->driver_data;
533         char *tmp;
534         int i;
535
536         if (!card)
537                 return -EINVAL;
538
539         if ((card->state != CARD_STATE_DOWN) &&
540             (card->state != CARD_STATE_RECOVER))
541                 return -EPERM;
542
543         i = simple_strtoul(buf, &tmp, 16);
544         if ((i == 0) || (i == 1))
545                 card->options.fake_broadcast = i;
546         else {
547                 PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
548                 return -EINVAL;
549         }
550         return count;
551 }
552
553 static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
554                    qeth_dev_fake_broadcast_store);
555
556 static ssize_t
557 qeth_dev_recover_store(struct device *dev, const char *buf, size_t count)
558 {
559         struct qeth_card *card = dev->driver_data;
560         char *tmp;
561         int i;
562
563         if (!card)
564                 return -EINVAL;
565
566         if (card->state != CARD_STATE_UP)
567                 return -EPERM;
568
569         i = simple_strtoul(buf, &tmp, 16);
570         if (i == 1)
571                 qeth_schedule_recovery(card);
572
573         return count;
574 }
575
576 static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
577
578 static ssize_t
579 qeth_dev_broadcast_mode_show(struct device *dev, char *buf)
580 {
581         struct qeth_card *card = dev->driver_data;
582
583         if (!card)
584                 return -EINVAL;
585
586         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
587               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
588                 return sprintf(buf, "n/a\n");
589
590         return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
591                                      QETH_TR_BROADCAST_ALLRINGS)?
592                        "all rings":"local");
593 }
594
595 static ssize_t
596 qeth_dev_broadcast_mode_store(struct device *dev, const char *buf, size_t count)
597 {
598         struct qeth_card *card = dev->driver_data;
599         char *tmp;
600
601         if (!card)
602                 return -EINVAL;
603
604         if ((card->state != CARD_STATE_DOWN) &&
605             (card->state != CARD_STATE_RECOVER))
606                 return -EPERM;
607
608         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
609               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
610                 PRINT_WARN("Device is not a tokenring device!\n");
611                 return -EINVAL;
612         }
613
614         tmp = strsep((char **) &buf, "\n");
615
616         if (!strcmp(tmp, "local")){
617                 card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
618                 return count;
619         } else if (!strcmp(tmp, "all_rings")) {
620                 card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
621                 return count;
622         } else {
623                 PRINT_WARN("broadcast_mode: invalid mode %s!\n",
624                            tmp);
625                 return -EINVAL;
626         }
627         return count;
628 }
629
630 static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
631                    qeth_dev_broadcast_mode_store);
632
633 static ssize_t
634 qeth_dev_canonical_macaddr_show(struct device *dev, char *buf)
635 {
636         struct qeth_card *card = dev->driver_data;
637
638         if (!card)
639                 return -EINVAL;
640
641         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
642               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
643                 return sprintf(buf, "n/a\n");
644
645         return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
646                                      QETH_TR_MACADDR_CANONICAL)? 1:0);
647 }
648
649 static ssize_t
650 qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf,
651                                   size_t count)
652 {
653         struct qeth_card *card = dev->driver_data;
654         char *tmp;
655         int i;
656
657         if (!card)
658                 return -EINVAL;
659
660         if ((card->state != CARD_STATE_DOWN) &&
661             (card->state != CARD_STATE_RECOVER))
662                 return -EPERM;
663
664         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
665               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
666                 PRINT_WARN("Device is not a tokenring device!\n");
667                 return -EINVAL;
668         }
669
670         i = simple_strtoul(buf, &tmp, 16);
671         if ((i == 0) || (i == 1))
672                 card->options.macaddr_mode = i?
673                         QETH_TR_MACADDR_CANONICAL :
674                         QETH_TR_MACADDR_NONCANONICAL;
675         else {
676                 PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
677                 return -EINVAL;
678         }
679         return count;
680 }
681
682 static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
683                    qeth_dev_canonical_macaddr_store);
684
685 static struct device_attribute * qeth_device_attrs[] = {
686         &dev_attr_state,
687         &dev_attr_chpid,
688         &dev_attr_if_name,
689         &dev_attr_card_type,
690         &dev_attr_portno,
691         &dev_attr_portname,
692         &dev_attr_checksumming,
693         &dev_attr_priority_queueing,
694         &dev_attr_buffer_count,
695         &dev_attr_route4,
696 #ifdef CONFIG_QETH_IPV6
697         &dev_attr_route6,
698 #endif
699         &dev_attr_add_hhlen,
700         &dev_attr_fake_ll,
701         &dev_attr_fake_broadcast,
702         &dev_attr_recover,
703         &dev_attr_broadcast_mode,
704         &dev_attr_canonical_macaddr,
705         NULL,
706 };
707
708 static struct attribute_group qeth_device_attr_group = {
709         .attrs = (struct attribute **)qeth_device_attrs,
710 };
711
712
713 #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)                       \
714 struct device_attribute dev_attr_##_id = {                                   \
715         .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
716         .show   = _show,                                                     \
717         .store  = _store,                                                    \
718 };
719
720 static ssize_t
721 qeth_dev_ipato_enable_show(struct device *dev, char *buf)
722 {
723         struct qeth_card *card = dev->driver_data;
724
725         if (!card)
726                 return -EINVAL;
727
728         return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
729 }
730
731 static ssize_t
732 qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count)
733 {
734         struct qeth_card *card = dev->driver_data;
735         char *tmp;
736
737         if (!card)
738                 return -EINVAL;
739
740         tmp = strsep((char **) &buf, "\n");
741         if (!strcmp(tmp, "toggle")){
742                 card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
743         } else if (!strcmp(tmp, "1")){
744                 card->ipato.enabled = 1;
745         } else if (!strcmp(tmp, "0")){
746                 card->ipato.enabled = 0;
747         } else {
748                 PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
749                            "this file\n");
750                 return -EINVAL;
751         }
752         return count;
753 }
754
755 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
756                         qeth_dev_ipato_enable_show,
757                         qeth_dev_ipato_enable_store);
758
759 static ssize_t
760 qeth_dev_ipato_invert4_show(struct device *dev, char *buf)
761 {
762         struct qeth_card *card = dev->driver_data;
763
764         if (!card)
765                 return -EINVAL;
766
767         return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
768 }
769
770 static ssize_t
771 qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count)
772 {
773         struct qeth_card *card = dev->driver_data;
774         char *tmp;
775
776         if (!card)
777                 return -EINVAL;
778
779         tmp = strsep((char **) &buf, "\n");
780         if (!strcmp(tmp, "toggle")){
781                 card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
782         } else if (!strcmp(tmp, "1")){
783                 card->ipato.invert4 = 1;
784         } else if (!strcmp(tmp, "0")){
785                 card->ipato.invert4 = 0;
786         } else {
787                 PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
788                            "this file\n");
789                 return -EINVAL;
790         }
791         return count;
792 }
793
794 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
795                         qeth_dev_ipato_invert4_show,
796                         qeth_dev_ipato_invert4_store);
797
798 static inline ssize_t
799 qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
800                         enum qeth_prot_versions proto)
801 {
802         struct qeth_ipato_entry *ipatoe;
803         unsigned long flags;
804         char addr_str[49];
805         int i = 0;
806
807         spin_lock_irqsave(&card->ip_lock, flags);
808         list_for_each_entry(ipatoe, &card->ipato.entries, entry){
809                 if (ipatoe->proto != proto)
810                         continue;
811                 qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
812                 i += sprintf(buf + i, "%s/%i\n", addr_str, ipatoe->mask_bits);
813         }
814         spin_unlock_irqrestore(&card->ip_lock, flags);
815         i += sprintf(buf + i, "\n");
816
817         return i;
818 }
819
820 static ssize_t
821 qeth_dev_ipato_add4_show(struct device *dev, char *buf)
822 {
823         struct qeth_card *card = dev->driver_data;
824
825         if (!card)
826                 return -EINVAL;
827
828         return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
829 }
830
831 static inline int
832 qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
833                   u8 *addr, int *mask_bits)
834 {
835         const char *start, *end;
836         char *tmp;
837         char buffer[49] = {0, };
838
839         start = buf;
840         /* get address string */
841         end = strchr(start, '/');
842         if (!end){
843                 PRINT_WARN("Invalid format for ipato_addx/delx. "
844                            "Use <ip addr>/<mask bits>\n");
845                 return -EINVAL;
846         }
847         strncpy(buffer, start, end - start);
848         if (qeth_string_to_ipaddr(buffer, proto, addr)){
849                 PRINT_WARN("Invalid IP address format!\n");
850                 return -EINVAL;
851         }
852         start = end + 1;
853         *mask_bits = simple_strtoul(start, &tmp, 10);
854
855         return 0;
856 }
857
858 static inline ssize_t
859 qeth_dev_ipato_add_store(const char *buf, size_t count,
860                          struct qeth_card *card, enum qeth_prot_versions proto)
861 {
862         struct qeth_ipato_entry *ipatoe;
863         u8 addr[16];
864         int mask_bits;
865         int rc;
866
867         if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
868                 return rc;
869
870         if (!(ipatoe = kmalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){
871                 PRINT_WARN("No memory to allocate ipato entry\n");
872                 return -ENOMEM;
873         }
874         memset(ipatoe, 0, sizeof(struct qeth_ipato_entry));
875         ipatoe->proto = proto;
876         memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
877         ipatoe->mask_bits = mask_bits;
878
879         if ((rc = qeth_add_ipato_entry(card, ipatoe))){
880                 kfree(ipatoe);
881                 return rc;
882         }
883
884         return count;
885 }
886
887 static ssize_t
888 qeth_dev_ipato_add4_store(struct device *dev, const char *buf, size_t count)
889 {
890         struct qeth_card *card = dev->driver_data;
891
892         if (!card)
893                 return -EINVAL;
894
895         return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
896 }
897
898 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
899                         qeth_dev_ipato_add4_show,
900                         qeth_dev_ipato_add4_store);
901
902 static inline ssize_t
903 qeth_dev_ipato_del_store(const char *buf, size_t count,
904                          struct qeth_card *card, enum qeth_prot_versions proto)
905 {
906         u8 addr[16];
907         int mask_bits;
908         int rc;
909
910         if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
911                 return rc;
912
913         qeth_del_ipato_entry(card, proto, addr, mask_bits);
914
915         return count;
916 }
917
918 static ssize_t
919 qeth_dev_ipato_del4_store(struct device *dev, const char *buf, size_t count)
920 {
921         struct qeth_card *card = dev->driver_data;
922
923         if (!card)
924                 return -EINVAL;
925
926         return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
927 }
928
929 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
930                         qeth_dev_ipato_del4_store);
931
932 #ifdef CONFIG_QETH_IPV6
933 static ssize_t
934 qeth_dev_ipato_invert6_show(struct device *dev, char *buf)
935 {
936         struct qeth_card *card = dev->driver_data;
937
938         if (!card)
939                 return -EINVAL;
940
941         return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
942 }
943
944 static ssize_t
945 qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count)
946 {
947         struct qeth_card *card = dev->driver_data;
948         char *tmp;
949
950         if (!card)
951                 return -EINVAL;
952
953         tmp = strsep((char **) &buf, "\n");
954         if (!strcmp(tmp, "toggle")){
955                 card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
956         } else if (!strcmp(tmp, "1")){
957                 card->ipato.invert6 = 1;
958         } else if (!strcmp(tmp, "0")){
959                 card->ipato.invert6 = 0;
960         } else {
961                 PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
962                            "this file\n");
963                 return -EINVAL;
964         }
965         return count;
966 }
967
968 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
969                         qeth_dev_ipato_invert6_show,
970                         qeth_dev_ipato_invert6_store);
971
972
973 static ssize_t
974 qeth_dev_ipato_add6_show(struct device *dev, char *buf)
975 {
976         struct qeth_card *card = dev->driver_data;
977
978         if (!card)
979                 return -EINVAL;
980
981         return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
982 }
983
984 static ssize_t
985 qeth_dev_ipato_add6_store(struct device *dev, const char *buf, size_t count)
986 {
987         struct qeth_card *card = dev->driver_data;
988
989         if (!card)
990                 return -EINVAL;
991
992         return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
993 }
994
995 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
996                         qeth_dev_ipato_add6_show,
997                         qeth_dev_ipato_add6_store);
998
999 static ssize_t
1000 qeth_dev_ipato_del6_store(struct device *dev, const char *buf, size_t count)
1001 {
1002         struct qeth_card *card = dev->driver_data;
1003
1004         if (!card)
1005                 return -EINVAL;
1006
1007         return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
1008 }
1009
1010 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
1011                         qeth_dev_ipato_del6_store);
1012 #endif /* CONFIG_QETH_IPV6 */
1013
1014 static struct device_attribute * qeth_ipato_device_attrs[] = {
1015         &dev_attr_ipato_enable,
1016         &dev_attr_ipato_invert4,
1017         &dev_attr_ipato_add4,
1018         &dev_attr_ipato_del4,
1019 #ifdef CONFIG_QETH_IPV6
1020         &dev_attr_ipato_invert6,
1021         &dev_attr_ipato_add6,
1022         &dev_attr_ipato_del6,
1023 #endif
1024         NULL,
1025 };
1026
1027 static struct attribute_group qeth_device_ipato_group = {
1028         .name = "ipa_takeover",
1029         .attrs = (struct attribute **)qeth_ipato_device_attrs,
1030 };
1031
1032 static inline ssize_t
1033 qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
1034                         enum qeth_prot_versions proto)
1035 {
1036         struct qeth_ipaddr *ipaddr;
1037         char addr_str[49];
1038         unsigned long flags;
1039         int i = 0;
1040
1041         spin_lock_irqsave(&card->ip_lock, flags);
1042         list_for_each_entry(ipaddr, &card->ip_list, entry){
1043                 if (ipaddr->proto != proto)
1044                         continue;
1045                 if (ipaddr->type != QETH_IP_TYPE_VIPA)
1046                         continue;
1047                 qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
1048                 i += sprintf(buf + i, "%s\n", addr_str);
1049         }
1050         spin_unlock_irqrestore(&card->ip_lock, flags);
1051         i += sprintf(buf + i, "\n");
1052
1053         return i;
1054 }
1055
1056 static ssize_t
1057 qeth_dev_vipa_add4_show(struct device *dev, char *buf)
1058 {
1059         struct qeth_card *card = dev->driver_data;
1060
1061         if (!card)
1062                 return -EINVAL;
1063
1064         return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
1065 }
1066
1067 static inline int
1068 qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
1069                  u8 *addr)
1070 {
1071         if (qeth_string_to_ipaddr(buf, proto, addr)){
1072                 PRINT_WARN("Invalid IP address format!\n");
1073                 return -EINVAL;
1074         }
1075         return 0;
1076 }
1077
1078 static inline ssize_t
1079 qeth_dev_vipa_add_store(const char *buf, size_t count,
1080                          struct qeth_card *card, enum qeth_prot_versions proto)
1081 {
1082         u8 addr[16] = {0, };
1083         int rc;
1084
1085         if ((rc = qeth_parse_vipae(buf, proto, addr)))
1086                 return rc;
1087
1088         if ((rc = qeth_add_vipa(card, proto, addr)))
1089                 return rc;
1090
1091         return count;
1092 }
1093
1094 static ssize_t
1095 qeth_dev_vipa_add4_store(struct device *dev, const char *buf, size_t count)
1096 {
1097         struct qeth_card *card = dev->driver_data;
1098
1099         if (!card)
1100                 return -EINVAL;
1101
1102         return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
1103 }
1104
1105 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
1106                         qeth_dev_vipa_add4_show,
1107                         qeth_dev_vipa_add4_store);
1108
1109 static inline ssize_t
1110 qeth_dev_vipa_del_store(const char *buf, size_t count,
1111                          struct qeth_card *card, enum qeth_prot_versions proto)
1112 {
1113         u8 addr[16];
1114         int rc;
1115
1116         if ((rc = qeth_parse_vipae(buf, proto, addr)))
1117                 return rc;
1118
1119         qeth_del_vipa(card, proto, addr);
1120
1121         return count;
1122 }
1123
1124 static ssize_t
1125 qeth_dev_vipa_del4_store(struct device *dev, const char *buf, size_t count)
1126 {
1127         struct qeth_card *card = dev->driver_data;
1128
1129         if (!card)
1130                 return -EINVAL;
1131
1132         return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
1133 }
1134
1135 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
1136                         qeth_dev_vipa_del4_store);
1137
1138 #ifdef CONFIG_QETH_IPV6
1139 static ssize_t
1140 qeth_dev_vipa_add6_show(struct device *dev, char *buf)
1141 {
1142         struct qeth_card *card = dev->driver_data;
1143
1144         if (!card)
1145                 return -EINVAL;
1146
1147         return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
1148 }
1149
1150 static ssize_t
1151 qeth_dev_vipa_add6_store(struct device *dev, const char *buf, size_t count)
1152 {
1153         struct qeth_card *card = dev->driver_data;
1154
1155         if (!card)
1156                 return -EINVAL;
1157
1158         return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
1159 }
1160
1161 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
1162                         qeth_dev_vipa_add6_show,
1163                         qeth_dev_vipa_add6_store);
1164
1165 static ssize_t
1166 qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count)
1167 {
1168         struct qeth_card *card = dev->driver_data;
1169
1170         if (!card)
1171                 return -EINVAL;
1172
1173         return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
1174 }
1175
1176 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
1177                         qeth_dev_vipa_del6_store);
1178 #endif /* CONFIG_QETH_IPV6 */
1179
1180 static struct device_attribute * qeth_vipa_device_attrs[] = {
1181         &dev_attr_vipa_add4,
1182         &dev_attr_vipa_del4,
1183 #ifdef CONFIG_QETH_IPV6
1184         &dev_attr_vipa_add6,
1185         &dev_attr_vipa_del6,
1186 #endif
1187         NULL,
1188 };
1189
1190 static struct attribute_group qeth_device_vipa_group = {
1191         .name = "vipa",
1192         .attrs = (struct attribute **)qeth_vipa_device_attrs,
1193 };
1194
1195 static inline ssize_t
1196 qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
1197                        enum qeth_prot_versions proto)
1198 {
1199         struct qeth_ipaddr *ipaddr;
1200         char addr_str[49];
1201         unsigned long flags;
1202         int i = 0;
1203
1204         spin_lock_irqsave(&card->ip_lock, flags);
1205         list_for_each_entry(ipaddr, &card->ip_list, entry){
1206                 if (ipaddr->proto != proto)
1207                         continue;
1208                 if (ipaddr->type != QETH_IP_TYPE_RXIP)
1209                         continue;
1210                 qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
1211                 i += sprintf(buf + i, "%s\n", addr_str);
1212         }
1213         spin_unlock_irqrestore(&card->ip_lock, flags);
1214         i += sprintf(buf + i, "\n");
1215
1216         return i;
1217 }
1218
1219 static ssize_t
1220 qeth_dev_rxip_add4_show(struct device *dev, char *buf)
1221 {
1222         struct qeth_card *card = dev->driver_data;
1223
1224         if (!card)
1225                 return -EINVAL;
1226
1227         return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
1228 }
1229
1230 static inline int
1231 qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
1232                  u8 *addr)
1233 {
1234         if (qeth_string_to_ipaddr(buf, proto, addr)){
1235                 PRINT_WARN("Invalid IP address format!\n");
1236                 return -EINVAL;
1237         }
1238         return 0;
1239 }
1240
1241 static inline ssize_t
1242 qeth_dev_rxip_add_store(const char *buf, size_t count,
1243                         struct qeth_card *card, enum qeth_prot_versions proto)
1244 {
1245         u8 addr[16] = {0, };
1246         int rc;
1247
1248         if ((rc = qeth_parse_rxipe(buf, proto, addr)))
1249                 return rc;
1250
1251         if ((rc = qeth_add_rxip(card, proto, addr)))
1252                 return rc;
1253
1254         return count;
1255 }
1256
1257 static ssize_t
1258 qeth_dev_rxip_add4_store(struct device *dev, const char *buf, size_t count)
1259 {
1260         struct qeth_card *card = dev->driver_data;
1261
1262         if (!card)
1263                 return -EINVAL;
1264
1265         return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
1266 }
1267
1268 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
1269                         qeth_dev_rxip_add4_show,
1270                         qeth_dev_rxip_add4_store);
1271
1272 static inline ssize_t
1273 qeth_dev_rxip_del_store(const char *buf, size_t count,
1274                         struct qeth_card *card, enum qeth_prot_versions proto)
1275 {
1276         u8 addr[16];
1277         int rc;
1278
1279         if ((rc = qeth_parse_rxipe(buf, proto, addr)))
1280                 return rc;
1281
1282         qeth_del_rxip(card, proto, addr);
1283
1284         return count;
1285 }
1286
1287 static ssize_t
1288 qeth_dev_rxip_del4_store(struct device *dev, const char *buf, size_t count)
1289 {
1290         struct qeth_card *card = dev->driver_data;
1291
1292         if (!card)
1293                 return -EINVAL;
1294
1295         return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
1296 }
1297
1298 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
1299                         qeth_dev_rxip_del4_store);
1300
1301 #ifdef CONFIG_QETH_IPV6
1302 static ssize_t
1303 qeth_dev_rxip_add6_show(struct device *dev, char *buf)
1304 {
1305         struct qeth_card *card = dev->driver_data;
1306
1307         if (!card)
1308                 return -EINVAL;
1309
1310         return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
1311 }
1312
1313 static ssize_t
1314 qeth_dev_rxip_add6_store(struct device *dev, const char *buf, size_t count)
1315 {
1316         struct qeth_card *card = dev->driver_data;
1317
1318         if (!card)
1319                 return -EINVAL;
1320
1321         return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
1322 }
1323
1324 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
1325                         qeth_dev_rxip_add6_show,
1326                         qeth_dev_rxip_add6_store);
1327
1328 static ssize_t
1329 qeth_dev_rxip_del6_store(struct device *dev, const char *buf, size_t count)
1330 {
1331         struct qeth_card *card = dev->driver_data;
1332
1333         if (!card)
1334                 return -EINVAL;
1335
1336         return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
1337 }
1338
1339 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
1340                         qeth_dev_rxip_del6_store);
1341 #endif /* CONFIG_QETH_IPV6 */
1342
1343 static struct device_attribute * qeth_rxip_device_attrs[] = {
1344         &dev_attr_rxip_add4,
1345         &dev_attr_rxip_del4,
1346 #ifdef CONFIG_QETH_IPV6
1347         &dev_attr_rxip_add6,
1348         &dev_attr_rxip_del6,
1349 #endif
1350         NULL,
1351 };
1352
1353 static struct attribute_group qeth_device_rxip_group = {
1354         .name = "rxip",
1355         .attrs = (struct attribute **)qeth_rxip_device_attrs,
1356 };
1357
1358 int
1359 qeth_create_device_attributes(struct device *dev)
1360 {
1361         int ret;
1362
1363         if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
1364                 return ret;
1365         if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
1366                 sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
1367                 return ret;
1368         }
1369         if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){
1370                 sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
1371                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1372                 return ret;
1373         }
1374         if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){
1375                 sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
1376                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1377                 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1378         }
1379
1380         return ret;
1381 }
1382
1383 void
1384 qeth_remove_device_attributes(struct device *dev)
1385 {
1386         sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
1387         sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1388         sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1389         sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
1390 }
1391
1392 /**********************/
1393 /* DRIVER ATTRIBUTES  */
1394 /**********************/
1395 static ssize_t
1396 qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
1397                         size_t count)
1398 {
1399         const char *start, *end;
1400         char bus_ids[3][BUS_ID_SIZE], *argv[3];
1401         int i;
1402         int err;
1403
1404         start = buf;
1405         for (i = 0; i < 3; i++) {
1406                 static const char delim[] = { ',', ',', '\n' };
1407                 int len;
1408
1409                 if (!(end = strchr(start, delim[i])))
1410                         return -EINVAL;
1411                 len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
1412                 strncpy(bus_ids[i], start, len);
1413                 bus_ids[i][len] = '\0';
1414                 start = end + 1;
1415                 argv[i] = bus_ids[i];
1416         }
1417         err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id,
1418                         &qeth_ccw_driver, 3, argv);
1419         if (err)
1420                 return err;
1421         else
1422                 return count;
1423 }
1424
1425
1426 static DRIVER_ATTR(group, 0200, 0, qeth_driver_group_store);
1427
1428 static ssize_t
1429 qeth_driver_snmp_register_show(struct device_driver *ddrv, char *buf)
1430 {
1431         /* TODO */
1432         return 0;
1433 }
1434
1435 static ssize_t
1436 qeth_driver_snmp_register_store(struct device_driver *ddrv, const char *buf,
1437                                 size_t count)
1438 {
1439         /* TODO */
1440         return count;
1441 }
1442
1443 static DRIVER_ATTR(snmp_register, 0644, qeth_driver_snmp_register_show,
1444                    qeth_driver_snmp_register_store);
1445
1446 int
1447 qeth_create_driver_attributes(void)
1448 {
1449         int rc;
1450
1451         if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
1452                                      &driver_attr_group)))
1453                 return rc;
1454         return driver_create_file(&qeth_ccwgroup_driver.driver,
1455                                   &driver_attr_snmp_register);
1456 }
1457
1458 void
1459 qeth_remove_driver_attributes(void)
1460 {
1461         driver_remove_file(&qeth_ccwgroup_driver.driver,
1462                         &driver_attr_group);
1463         driver_remove_file(&qeth_ccwgroup_driver.driver,
1464                         &driver_attr_snmp_register);
1465 }