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