]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/s390/net/qeth_l3_sys.c
kbuild: Fixup deb-pkg target to generate separate firmware deb
[linux-2.6-omap-h63xx.git] / drivers / s390 / net / qeth_l3_sys.c
1 /*
2  *  drivers/s390/net/qeth_l3_sys.c
3  *
4  *    Copyright IBM Corp. 2007
5  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
6  *               Frank Pavlic <fpavlic@de.ibm.com>,
7  *               Thomas Spatzier <tspat@de.ibm.com>,
8  *               Frank Blaschka <frank.blaschka@de.ibm.com>
9  */
10
11 #include "qeth_l3.h"
12
13 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
14 struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
15
16 static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
17 {
18         if (card->options.checksum_type == SW_CHECKSUMMING)
19                 return "sw";
20         else if (card->options.checksum_type == HW_CHECKSUMMING)
21                 return "hw";
22         else
23                 return "no";
24 }
25
26 static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
27                         struct qeth_routing_info *route, char *buf)
28 {
29         switch (route->type) {
30         case PRIMARY_ROUTER:
31                 return sprintf(buf, "%s\n", "primary router");
32         case SECONDARY_ROUTER:
33                 return sprintf(buf, "%s\n", "secondary router");
34         case MULTICAST_ROUTER:
35                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
36                         return sprintf(buf, "%s\n", "multicast router+");
37                 else
38                         return sprintf(buf, "%s\n", "multicast router");
39         case PRIMARY_CONNECTOR:
40                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
41                         return sprintf(buf, "%s\n", "primary connector+");
42                 else
43                         return sprintf(buf, "%s\n", "primary connector");
44         case SECONDARY_CONNECTOR:
45                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
46                         return sprintf(buf, "%s\n", "secondary connector+");
47                 else
48                         return sprintf(buf, "%s\n", "secondary connector");
49         default:
50                 return sprintf(buf, "%s\n", "no");
51         }
52 }
53
54 static ssize_t qeth_l3_dev_route4_show(struct device *dev,
55                         struct device_attribute *attr, char *buf)
56 {
57         struct qeth_card *card = dev_get_drvdata(dev);
58
59         if (!card)
60                 return -EINVAL;
61
62         return qeth_l3_dev_route_show(card, &card->options.route4, buf);
63 }
64
65 static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
66                 struct qeth_routing_info *route, enum qeth_prot_versions prot,
67                 const char *buf, size_t count)
68 {
69         enum qeth_routing_types old_route_type = route->type;
70         char *tmp;
71         int rc;
72
73         tmp = strsep((char **) &buf, "\n");
74
75         if (!strcmp(tmp, "no_router")) {
76                 route->type = NO_ROUTER;
77         } else if (!strcmp(tmp, "primary_connector")) {
78                 route->type = PRIMARY_CONNECTOR;
79         } else if (!strcmp(tmp, "secondary_connector")) {
80                 route->type = SECONDARY_CONNECTOR;
81         } else if (!strcmp(tmp, "primary_router")) {
82                 route->type = PRIMARY_ROUTER;
83         } else if (!strcmp(tmp, "secondary_router")) {
84                 route->type = SECONDARY_ROUTER;
85         } else if (!strcmp(tmp, "multicast_router")) {
86                 route->type = MULTICAST_ROUTER;
87         } else {
88                 return -EINVAL;
89         }
90         if (((card->state == CARD_STATE_SOFTSETUP) ||
91              (card->state == CARD_STATE_UP)) &&
92             (old_route_type != route->type)) {
93                 if (prot == QETH_PROT_IPV4)
94                         rc = qeth_l3_setrouting_v4(card);
95                 else if (prot == QETH_PROT_IPV6)
96                         rc = qeth_l3_setrouting_v6(card);
97         }
98         return count;
99 }
100
101 static ssize_t qeth_l3_dev_route4_store(struct device *dev,
102                 struct device_attribute *attr, const char *buf, size_t count)
103 {
104         struct qeth_card *card = dev_get_drvdata(dev);
105
106         if (!card)
107                 return -EINVAL;
108
109         return qeth_l3_dev_route_store(card, &card->options.route4,
110                                 QETH_PROT_IPV4, buf, count);
111 }
112
113 static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
114                         qeth_l3_dev_route4_store);
115
116 static ssize_t qeth_l3_dev_route6_show(struct device *dev,
117                         struct device_attribute *attr, char *buf)
118 {
119         struct qeth_card *card = dev_get_drvdata(dev);
120
121         if (!card)
122                 return -EINVAL;
123
124         if (!qeth_is_supported(card, IPA_IPV6))
125                 return sprintf(buf, "%s\n", "n/a");
126
127         return qeth_l3_dev_route_show(card, &card->options.route6, buf);
128 }
129
130 static ssize_t qeth_l3_dev_route6_store(struct device *dev,
131                 struct device_attribute *attr, const char *buf, size_t count)
132 {
133         struct qeth_card *card = dev_get_drvdata(dev);
134
135         if (!card)
136                 return -EINVAL;
137
138         if (!qeth_is_supported(card, IPA_IPV6)) {
139                 return -EOPNOTSUPP;
140         }
141
142         return qeth_l3_dev_route_store(card, &card->options.route6,
143                                 QETH_PROT_IPV6, buf, count);
144 }
145
146 static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
147                         qeth_l3_dev_route6_store);
148
149 static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
150                         struct device_attribute *attr, char *buf)
151 {
152         struct qeth_card *card = dev_get_drvdata(dev);
153
154         if (!card)
155                 return -EINVAL;
156
157         return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
158 }
159
160 static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
161                 struct device_attribute *attr, const char *buf, size_t count)
162 {
163         struct qeth_card *card = dev_get_drvdata(dev);
164         char *tmp;
165         int i;
166
167         if (!card)
168                 return -EINVAL;
169
170         if ((card->state != CARD_STATE_DOWN) &&
171             (card->state != CARD_STATE_RECOVER))
172                 return -EPERM;
173
174         i = simple_strtoul(buf, &tmp, 16);
175         if ((i == 0) || (i == 1))
176                 card->options.fake_broadcast = i;
177         else {
178                 return -EINVAL;
179         }
180         return count;
181 }
182
183 static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
184                    qeth_l3_dev_fake_broadcast_store);
185
186 static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
187                                 struct device_attribute *attr, char *buf)
188 {
189         struct qeth_card *card = dev_get_drvdata(dev);
190
191         if (!card)
192                 return -EINVAL;
193
194         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
195               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
196                 return sprintf(buf, "n/a\n");
197
198         return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
199                                      QETH_TR_BROADCAST_ALLRINGS)?
200                        "all rings":"local");
201 }
202
203 static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
204                 struct device_attribute *attr, const char *buf, size_t count)
205 {
206         struct qeth_card *card = dev_get_drvdata(dev);
207         char *tmp;
208
209         if (!card)
210                 return -EINVAL;
211
212         if ((card->state != CARD_STATE_DOWN) &&
213             (card->state != CARD_STATE_RECOVER))
214                 return -EPERM;
215
216         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
217               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
218                 return -EINVAL;
219         }
220
221         tmp = strsep((char **) &buf, "\n");
222
223         if (!strcmp(tmp, "local")) {
224                 card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
225                 return count;
226         } else if (!strcmp(tmp, "all_rings")) {
227                 card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
228                 return count;
229         } else {
230                 return -EINVAL;
231         }
232         return count;
233 }
234
235 static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
236                    qeth_l3_dev_broadcast_mode_store);
237
238 static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
239                                 struct device_attribute *attr, char *buf)
240 {
241         struct qeth_card *card = dev_get_drvdata(dev);
242
243         if (!card)
244                 return -EINVAL;
245
246         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
247               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
248                 return sprintf(buf, "n/a\n");
249
250         return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
251                                      QETH_TR_MACADDR_CANONICAL)? 1:0);
252 }
253
254 static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
255                 struct device_attribute *attr, const char *buf, size_t count)
256 {
257         struct qeth_card *card = dev_get_drvdata(dev);
258         char *tmp;
259         int i;
260
261         if (!card)
262                 return -EINVAL;
263
264         if ((card->state != CARD_STATE_DOWN) &&
265             (card->state != CARD_STATE_RECOVER))
266                 return -EPERM;
267
268         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
269               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
270                 return -EINVAL;
271         }
272
273         i = simple_strtoul(buf, &tmp, 16);
274         if ((i == 0) || (i == 1))
275                 card->options.macaddr_mode = i?
276                         QETH_TR_MACADDR_CANONICAL :
277                         QETH_TR_MACADDR_NONCANONICAL;
278         else {
279                 return -EINVAL;
280         }
281         return count;
282 }
283
284 static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
285                    qeth_l3_dev_canonical_macaddr_store);
286
287 static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
288                         struct device_attribute *attr, char *buf)
289 {
290         struct qeth_card *card = dev_get_drvdata(dev);
291
292         if (!card)
293                 return -EINVAL;
294
295         return sprintf(buf, "%s checksumming\n",
296                         qeth_l3_get_checksum_str(card));
297 }
298
299 static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
300                 struct device_attribute *attr, const char *buf, size_t count)
301 {
302         struct qeth_card *card = dev_get_drvdata(dev);
303         char *tmp;
304
305         if (!card)
306                 return -EINVAL;
307
308         if ((card->state != CARD_STATE_DOWN) &&
309             (card->state != CARD_STATE_RECOVER))
310                 return -EPERM;
311
312         tmp = strsep((char **) &buf, "\n");
313         if (!strcmp(tmp, "sw_checksumming"))
314                 card->options.checksum_type = SW_CHECKSUMMING;
315         else if (!strcmp(tmp, "hw_checksumming"))
316                 card->options.checksum_type = HW_CHECKSUMMING;
317         else if (!strcmp(tmp, "no_checksumming"))
318                 card->options.checksum_type = NO_CHECKSUMMING;
319         else {
320                 return -EINVAL;
321         }
322         return count;
323 }
324
325 static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
326                 qeth_l3_dev_checksum_store);
327
328 static struct attribute *qeth_l3_device_attrs[] = {
329         &dev_attr_route4.attr,
330         &dev_attr_route6.attr,
331         &dev_attr_fake_broadcast.attr,
332         &dev_attr_broadcast_mode.attr,
333         &dev_attr_canonical_macaddr.attr,
334         &dev_attr_checksumming.attr,
335         NULL,
336 };
337
338 static struct attribute_group qeth_l3_device_attr_group = {
339         .attrs = qeth_l3_device_attrs,
340 };
341
342 static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
343                         struct device_attribute *attr, char *buf)
344 {
345         struct qeth_card *card = dev_get_drvdata(dev);
346
347         if (!card)
348                 return -EINVAL;
349
350         return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
351 }
352
353 static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
354                 struct device_attribute *attr, const char *buf, size_t count)
355 {
356         struct qeth_card *card = dev_get_drvdata(dev);
357         char *tmp;
358
359         if (!card)
360                 return -EINVAL;
361
362         if ((card->state != CARD_STATE_DOWN) &&
363             (card->state != CARD_STATE_RECOVER))
364                 return -EPERM;
365
366         tmp = strsep((char **) &buf, "\n");
367         if (!strcmp(tmp, "toggle")) {
368                 card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
369         } else if (!strcmp(tmp, "1")) {
370                 card->ipato.enabled = 1;
371         } else if (!strcmp(tmp, "0")) {
372                 card->ipato.enabled = 0;
373         } else {
374                 return -EINVAL;
375         }
376         return count;
377 }
378
379 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
380                         qeth_l3_dev_ipato_enable_show,
381                         qeth_l3_dev_ipato_enable_store);
382
383 static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
384                                 struct device_attribute *attr, char *buf)
385 {
386         struct qeth_card *card = dev_get_drvdata(dev);
387
388         if (!card)
389                 return -EINVAL;
390
391         return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
392 }
393
394 static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
395                                 struct device_attribute *attr,
396                                 const char *buf, size_t count)
397 {
398         struct qeth_card *card = dev_get_drvdata(dev);
399         char *tmp;
400
401         if (!card)
402                 return -EINVAL;
403
404         tmp = strsep((char **) &buf, "\n");
405         if (!strcmp(tmp, "toggle")) {
406                 card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
407         } else if (!strcmp(tmp, "1")) {
408                 card->ipato.invert4 = 1;
409         } else if (!strcmp(tmp, "0")) {
410                 card->ipato.invert4 = 0;
411         } else {
412                 return -EINVAL;
413         }
414         return count;
415 }
416
417 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
418                         qeth_l3_dev_ipato_invert4_show,
419                         qeth_l3_dev_ipato_invert4_store);
420
421 static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
422                         enum qeth_prot_versions proto)
423 {
424         struct qeth_ipato_entry *ipatoe;
425         unsigned long flags;
426         char addr_str[40];
427         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
428         int i = 0;
429
430         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
431         /* add strlen for "/<mask>\n" */
432         entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
433         spin_lock_irqsave(&card->ip_lock, flags);
434         list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
435                 if (ipatoe->proto != proto)
436                         continue;
437                 /* String must not be longer than PAGE_SIZE. So we check if
438                  * string length gets near PAGE_SIZE. Then we can savely display
439                  * the next IPv6 address (worst case, compared to IPv4) */
440                 if ((PAGE_SIZE - i) <= entry_len)
441                         break;
442                 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
443                 i += snprintf(buf + i, PAGE_SIZE - i,
444                               "%s/%i\n", addr_str, ipatoe->mask_bits);
445         }
446         spin_unlock_irqrestore(&card->ip_lock, flags);
447         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
448
449         return i;
450 }
451
452 static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
453                                 struct device_attribute *attr, char *buf)
454 {
455         struct qeth_card *card = dev_get_drvdata(dev);
456
457         if (!card)
458                 return -EINVAL;
459
460         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
461 }
462
463 static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
464                   u8 *addr, int *mask_bits)
465 {
466         const char *start, *end;
467         char *tmp;
468         char buffer[40] = {0, };
469
470         start = buf;
471         /* get address string */
472         end = strchr(start, '/');
473         if (!end || (end - start >= 40)) {
474                 return -EINVAL;
475         }
476         strncpy(buffer, start, end - start);
477         if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
478                 return -EINVAL;
479         }
480         start = end + 1;
481         *mask_bits = simple_strtoul(start, &tmp, 10);
482         if (!strlen(start) ||
483             (tmp == start) ||
484             (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
485                 return -EINVAL;
486         }
487         return 0;
488 }
489
490 static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
491                          struct qeth_card *card, enum qeth_prot_versions proto)
492 {
493         struct qeth_ipato_entry *ipatoe;
494         u8 addr[16];
495         int mask_bits;
496         int rc;
497
498         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
499         if (rc)
500                 return rc;
501
502         ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
503         if (!ipatoe) {
504                 return -ENOMEM;
505         }
506         ipatoe->proto = proto;
507         memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
508         ipatoe->mask_bits = mask_bits;
509
510         rc = qeth_l3_add_ipato_entry(card, ipatoe);
511         if (rc) {
512                 kfree(ipatoe);
513                 return rc;
514         }
515
516         return count;
517 }
518
519 static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
520                 struct device_attribute *attr, const char *buf, size_t count)
521 {
522         struct qeth_card *card = dev_get_drvdata(dev);
523
524         if (!card)
525                 return -EINVAL;
526
527         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
528 }
529
530 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
531                         qeth_l3_dev_ipato_add4_show,
532                         qeth_l3_dev_ipato_add4_store);
533
534 static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
535                          struct qeth_card *card, enum qeth_prot_versions proto)
536 {
537         u8 addr[16];
538         int mask_bits;
539         int rc;
540
541         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
542         if (rc)
543                 return rc;
544
545         qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
546
547         return count;
548 }
549
550 static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
551                 struct device_attribute *attr, const char *buf, size_t count)
552 {
553         struct qeth_card *card = dev_get_drvdata(dev);
554
555         if (!card)
556                 return -EINVAL;
557
558         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
559 }
560
561 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
562                         qeth_l3_dev_ipato_del4_store);
563
564 static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
565                 struct device_attribute *attr, char *buf)
566 {
567         struct qeth_card *card = dev_get_drvdata(dev);
568
569         if (!card)
570                 return -EINVAL;
571
572         return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
573 }
574
575 static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
576                 struct device_attribute *attr, const char *buf, size_t count)
577 {
578         struct qeth_card *card = dev_get_drvdata(dev);
579         char *tmp;
580
581         if (!card)
582                 return -EINVAL;
583
584         tmp = strsep((char **) &buf, "\n");
585         if (!strcmp(tmp, "toggle")) {
586                 card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
587         } else if (!strcmp(tmp, "1")) {
588                 card->ipato.invert6 = 1;
589         } else if (!strcmp(tmp, "0")) {
590                 card->ipato.invert6 = 0;
591         } else {
592                 return -EINVAL;
593         }
594         return count;
595 }
596
597 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
598                         qeth_l3_dev_ipato_invert6_show,
599                         qeth_l3_dev_ipato_invert6_store);
600
601
602 static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
603                                 struct device_attribute *attr, char *buf)
604 {
605         struct qeth_card *card = dev_get_drvdata(dev);
606
607         if (!card)
608                 return -EINVAL;
609
610         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
611 }
612
613 static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
614                 struct device_attribute *attr, const char *buf, size_t count)
615 {
616         struct qeth_card *card = dev_get_drvdata(dev);
617
618         if (!card)
619                 return -EINVAL;
620
621         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
622 }
623
624 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
625                         qeth_l3_dev_ipato_add6_show,
626                         qeth_l3_dev_ipato_add6_store);
627
628 static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
629                 struct device_attribute *attr, const char *buf, size_t count)
630 {
631         struct qeth_card *card = dev_get_drvdata(dev);
632
633         if (!card)
634                 return -EINVAL;
635
636         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
637 }
638
639 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
640                         qeth_l3_dev_ipato_del6_store);
641
642 static struct attribute *qeth_ipato_device_attrs[] = {
643         &dev_attr_ipato_enable.attr,
644         &dev_attr_ipato_invert4.attr,
645         &dev_attr_ipato_add4.attr,
646         &dev_attr_ipato_del4.attr,
647         &dev_attr_ipato_invert6.attr,
648         &dev_attr_ipato_add6.attr,
649         &dev_attr_ipato_del6.attr,
650         NULL,
651 };
652
653 static struct attribute_group qeth_device_ipato_group = {
654         .name = "ipa_takeover",
655         .attrs = qeth_ipato_device_attrs,
656 };
657
658 static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
659                         enum qeth_prot_versions proto)
660 {
661         struct qeth_ipaddr *ipaddr;
662         char addr_str[40];
663         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
664         unsigned long flags;
665         int i = 0;
666
667         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
668         entry_len += 2; /* \n + terminator */
669         spin_lock_irqsave(&card->ip_lock, flags);
670         list_for_each_entry(ipaddr, &card->ip_list, entry) {
671                 if (ipaddr->proto != proto)
672                         continue;
673                 if (ipaddr->type != QETH_IP_TYPE_VIPA)
674                         continue;
675                 /* String must not be longer than PAGE_SIZE. So we check if
676                  * string length gets near PAGE_SIZE. Then we can savely display
677                  * the next IPv6 address (worst case, compared to IPv4) */
678                 if ((PAGE_SIZE - i) <= entry_len)
679                         break;
680                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
681                         addr_str);
682                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
683         }
684         spin_unlock_irqrestore(&card->ip_lock, flags);
685         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
686
687         return i;
688 }
689
690 static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
691                         struct device_attribute *attr, char *buf)
692 {
693         struct qeth_card *card = dev_get_drvdata(dev);
694
695         if (!card)
696                 return -EINVAL;
697
698         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
699 }
700
701 static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
702                  u8 *addr)
703 {
704         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
705                 return -EINVAL;
706         }
707         return 0;
708 }
709
710 static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
711                         struct qeth_card *card, enum qeth_prot_versions proto)
712 {
713         u8 addr[16] = {0, };
714         int rc;
715
716         rc = qeth_l3_parse_vipae(buf, proto, addr);
717         if (rc)
718                 return rc;
719
720         rc = qeth_l3_add_vipa(card, proto, addr);
721         if (rc)
722                 return rc;
723
724         return count;
725 }
726
727 static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
728                 struct device_attribute *attr, const char *buf, size_t count)
729 {
730         struct qeth_card *card = dev_get_drvdata(dev);
731
732         if (!card)
733                 return -EINVAL;
734
735         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
736 }
737
738 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
739                         qeth_l3_dev_vipa_add4_show,
740                         qeth_l3_dev_vipa_add4_store);
741
742 static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
743                          struct qeth_card *card, enum qeth_prot_versions proto)
744 {
745         u8 addr[16];
746         int rc;
747
748         rc = qeth_l3_parse_vipae(buf, proto, addr);
749         if (rc)
750                 return rc;
751
752         qeth_l3_del_vipa(card, proto, addr);
753
754         return count;
755 }
756
757 static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
758                 struct device_attribute *attr, const char *buf, size_t count)
759 {
760         struct qeth_card *card = dev_get_drvdata(dev);
761
762         if (!card)
763                 return -EINVAL;
764
765         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
766 }
767
768 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
769                         qeth_l3_dev_vipa_del4_store);
770
771 static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
772                                 struct device_attribute *attr, char *buf)
773 {
774         struct qeth_card *card = dev_get_drvdata(dev);
775
776         if (!card)
777                 return -EINVAL;
778
779         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
780 }
781
782 static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
783                 struct device_attribute *attr, const char *buf, size_t count)
784 {
785         struct qeth_card *card = dev_get_drvdata(dev);
786
787         if (!card)
788                 return -EINVAL;
789
790         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
791 }
792
793 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
794                         qeth_l3_dev_vipa_add6_show,
795                         qeth_l3_dev_vipa_add6_store);
796
797 static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
798                 struct device_attribute *attr, const char *buf, size_t count)
799 {
800         struct qeth_card *card = dev_get_drvdata(dev);
801
802         if (!card)
803                 return -EINVAL;
804
805         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
806 }
807
808 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
809                         qeth_l3_dev_vipa_del6_store);
810
811 static struct attribute *qeth_vipa_device_attrs[] = {
812         &dev_attr_vipa_add4.attr,
813         &dev_attr_vipa_del4.attr,
814         &dev_attr_vipa_add6.attr,
815         &dev_attr_vipa_del6.attr,
816         NULL,
817 };
818
819 static struct attribute_group qeth_device_vipa_group = {
820         .name = "vipa",
821         .attrs = qeth_vipa_device_attrs,
822 };
823
824 static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
825                        enum qeth_prot_versions proto)
826 {
827         struct qeth_ipaddr *ipaddr;
828         char addr_str[40];
829         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
830         unsigned long flags;
831         int i = 0;
832
833         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
834         entry_len += 2; /* \n + terminator */
835         spin_lock_irqsave(&card->ip_lock, flags);
836         list_for_each_entry(ipaddr, &card->ip_list, entry) {
837                 if (ipaddr->proto != proto)
838                         continue;
839                 if (ipaddr->type != QETH_IP_TYPE_RXIP)
840                         continue;
841                 /* String must not be longer than PAGE_SIZE. So we check if
842                  * string length gets near PAGE_SIZE. Then we can savely display
843                  * the next IPv6 address (worst case, compared to IPv4) */
844                 if ((PAGE_SIZE - i) <= entry_len)
845                         break;
846                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
847                         addr_str);
848                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
849         }
850         spin_unlock_irqrestore(&card->ip_lock, flags);
851         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
852
853         return i;
854 }
855
856 static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
857                         struct device_attribute *attr, char *buf)
858 {
859         struct qeth_card *card = dev_get_drvdata(dev);
860
861         if (!card)
862                 return -EINVAL;
863
864         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
865 }
866
867 static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
868                  u8 *addr)
869 {
870         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
871                 return -EINVAL;
872         }
873         return 0;
874 }
875
876 static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
877                         struct qeth_card *card, enum qeth_prot_versions proto)
878 {
879         u8 addr[16] = {0, };
880         int rc;
881
882         rc = qeth_l3_parse_rxipe(buf, proto, addr);
883         if (rc)
884                 return rc;
885
886         rc = qeth_l3_add_rxip(card, proto, addr);
887         if (rc)
888                 return rc;
889
890         return count;
891 }
892
893 static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
894                 struct device_attribute *attr, const char *buf, size_t count)
895 {
896         struct qeth_card *card = dev_get_drvdata(dev);
897
898         if (!card)
899                 return -EINVAL;
900
901         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
902 }
903
904 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
905                         qeth_l3_dev_rxip_add4_show,
906                         qeth_l3_dev_rxip_add4_store);
907
908 static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
909                         struct qeth_card *card, enum qeth_prot_versions proto)
910 {
911         u8 addr[16];
912         int rc;
913
914         rc = qeth_l3_parse_rxipe(buf, proto, addr);
915         if (rc)
916                 return rc;
917
918         qeth_l3_del_rxip(card, proto, addr);
919
920         return count;
921 }
922
923 static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
924                 struct device_attribute *attr, const char *buf, size_t count)
925 {
926         struct qeth_card *card = dev_get_drvdata(dev);
927
928         if (!card)
929                 return -EINVAL;
930
931         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
932 }
933
934 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
935                         qeth_l3_dev_rxip_del4_store);
936
937 static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
938                 struct device_attribute *attr, char *buf)
939 {
940         struct qeth_card *card = dev_get_drvdata(dev);
941
942         if (!card)
943                 return -EINVAL;
944
945         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
946 }
947
948 static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
949                 struct device_attribute *attr, const char *buf, size_t count)
950 {
951         struct qeth_card *card = dev_get_drvdata(dev);
952
953         if (!card)
954                 return -EINVAL;
955
956         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
957 }
958
959 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
960                         qeth_l3_dev_rxip_add6_show,
961                         qeth_l3_dev_rxip_add6_store);
962
963 static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
964                 struct device_attribute *attr, const char *buf, size_t count)
965 {
966         struct qeth_card *card = dev_get_drvdata(dev);
967
968         if (!card)
969                 return -EINVAL;
970
971         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
972 }
973
974 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
975                         qeth_l3_dev_rxip_del6_store);
976
977 static struct attribute *qeth_rxip_device_attrs[] = {
978         &dev_attr_rxip_add4.attr,
979         &dev_attr_rxip_del4.attr,
980         &dev_attr_rxip_add6.attr,
981         &dev_attr_rxip_del6.attr,
982         NULL,
983 };
984
985 static struct attribute_group qeth_device_rxip_group = {
986         .name = "rxip",
987         .attrs = qeth_rxip_device_attrs,
988 };
989
990 int qeth_l3_create_device_attributes(struct device *dev)
991 {
992         int ret;
993
994         ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
995         if (ret)
996                 return ret;
997
998         ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
999         if (ret) {
1000                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1001                 return ret;
1002         }
1003
1004         ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
1005         if (ret) {
1006                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1007                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1008                 return ret;
1009         }
1010
1011         ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
1012         if (ret) {
1013                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1014                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1015                 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1016                 return ret;
1017         }
1018         return 0;
1019 }
1020
1021 void qeth_l3_remove_device_attributes(struct device *dev)
1022 {
1023         sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1024         sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1025         sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1026         sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
1027 }