vlan: move struct vlan_dev_info to private header
[linux-2.6/mini2440.git] / drivers / s390 / net / qeth_l3_sys.c
blobac1993708ae9cc1f09b622b3aa35af5ea0e33603
1 /*
2 * drivers/s390/net/qeth_l3_sys.c
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 */
11 #include "qeth_l3.h"
13 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
14 struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
16 static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
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";
26 static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
27 struct qeth_routing_info *route, char *buf)
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");
54 static ssize_t qeth_l3_dev_route4_show(struct device *dev,
55 struct device_attribute *attr, char *buf)
57 struct qeth_card *card = dev_get_drvdata(dev);
59 if (!card)
60 return -EINVAL;
62 return qeth_l3_dev_route_show(card, &card->options.route4, buf);
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)
69 enum qeth_routing_types old_route_type = route->type;
70 char *tmp;
71 int rc;
73 tmp = strsep((char **) &buf, "\n");
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;
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);
98 return count;
101 static ssize_t qeth_l3_dev_route4_store(struct device *dev,
102 struct device_attribute *attr, const char *buf, size_t count)
104 struct qeth_card *card = dev_get_drvdata(dev);
106 if (!card)
107 return -EINVAL;
109 return qeth_l3_dev_route_store(card, &card->options.route4,
110 QETH_PROT_IPV4, buf, count);
113 static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
114 qeth_l3_dev_route4_store);
116 static ssize_t qeth_l3_dev_route6_show(struct device *dev,
117 struct device_attribute *attr, char *buf)
119 struct qeth_card *card = dev_get_drvdata(dev);
121 if (!card)
122 return -EINVAL;
124 if (!qeth_is_supported(card, IPA_IPV6))
125 return sprintf(buf, "%s\n", "n/a");
127 return qeth_l3_dev_route_show(card, &card->options.route6, buf);
130 static ssize_t qeth_l3_dev_route6_store(struct device *dev,
131 struct device_attribute *attr, const char *buf, size_t count)
133 struct qeth_card *card = dev_get_drvdata(dev);
135 if (!card)
136 return -EINVAL;
138 if (!qeth_is_supported(card, IPA_IPV6)) {
139 return -ENOTSUPP;
142 return qeth_l3_dev_route_store(card, &card->options.route6,
143 QETH_PROT_IPV6, buf, count);
146 static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
147 qeth_l3_dev_route6_store);
149 static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
150 struct device_attribute *attr, char *buf)
152 struct qeth_card *card = dev_get_drvdata(dev);
154 if (!card)
155 return -EINVAL;
157 return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
160 static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
161 struct device_attribute *attr, const char *buf, size_t count)
163 struct qeth_card *card = dev_get_drvdata(dev);
164 char *tmp;
165 int i;
167 if (!card)
168 return -EINVAL;
170 if ((card->state != CARD_STATE_DOWN) &&
171 (card->state != CARD_STATE_RECOVER))
172 return -EPERM;
174 i = simple_strtoul(buf, &tmp, 16);
175 if ((i == 0) || (i == 1))
176 card->options.fake_broadcast = i;
177 else {
178 return -EINVAL;
180 return count;
183 static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
184 qeth_l3_dev_fake_broadcast_store);
186 static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
187 struct device_attribute *attr, char *buf)
189 struct qeth_card *card = dev_get_drvdata(dev);
191 if (!card)
192 return -EINVAL;
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");
198 return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
199 QETH_TR_BROADCAST_ALLRINGS)?
200 "all rings":"local");
203 static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
204 struct device_attribute *attr, const char *buf, size_t count)
206 struct qeth_card *card = dev_get_drvdata(dev);
207 char *tmp;
209 if (!card)
210 return -EINVAL;
212 if ((card->state != CARD_STATE_DOWN) &&
213 (card->state != CARD_STATE_RECOVER))
214 return -EPERM;
216 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
217 (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
218 return -EINVAL;
221 tmp = strsep((char **) &buf, "\n");
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;
232 return count;
235 static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
236 qeth_l3_dev_broadcast_mode_store);
238 static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
239 struct device_attribute *attr, char *buf)
241 struct qeth_card *card = dev_get_drvdata(dev);
243 if (!card)
244 return -EINVAL;
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");
250 return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
251 QETH_TR_MACADDR_CANONICAL)? 1:0);
254 static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
255 struct device_attribute *attr, const char *buf, size_t count)
257 struct qeth_card *card = dev_get_drvdata(dev);
258 char *tmp;
259 int i;
261 if (!card)
262 return -EINVAL;
264 if ((card->state != CARD_STATE_DOWN) &&
265 (card->state != CARD_STATE_RECOVER))
266 return -EPERM;
268 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
269 (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
270 return -EINVAL;
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;
281 return count;
284 static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
285 qeth_l3_dev_canonical_macaddr_store);
287 static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
288 struct device_attribute *attr, char *buf)
290 struct qeth_card *card = dev_get_drvdata(dev);
292 if (!card)
293 return -EINVAL;
295 return sprintf(buf, "%s checksumming\n",
296 qeth_l3_get_checksum_str(card));
299 static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
300 struct device_attribute *attr, const char *buf, size_t count)
302 struct qeth_card *card = dev_get_drvdata(dev);
303 char *tmp;
305 if (!card)
306 return -EINVAL;
308 if ((card->state != CARD_STATE_DOWN) &&
309 (card->state != CARD_STATE_RECOVER))
310 return -EPERM;
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;
322 return count;
325 static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
326 qeth_l3_dev_checksum_store);
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,
338 static struct attribute_group qeth_l3_device_attr_group = {
339 .attrs = qeth_l3_device_attrs,
342 static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
343 struct device_attribute *attr, char *buf)
345 struct qeth_card *card = dev_get_drvdata(dev);
347 if (!card)
348 return -EINVAL;
350 return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
353 static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
354 struct device_attribute *attr, const char *buf, size_t count)
356 struct qeth_card *card = dev_get_drvdata(dev);
357 char *tmp;
359 if (!card)
360 return -EINVAL;
362 if ((card->state != CARD_STATE_DOWN) &&
363 (card->state != CARD_STATE_RECOVER))
364 return -EPERM;
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;
376 return count;
379 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
380 qeth_l3_dev_ipato_enable_show,
381 qeth_l3_dev_ipato_enable_store);
383 static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
384 struct device_attribute *attr, char *buf)
386 struct qeth_card *card = dev_get_drvdata(dev);
388 if (!card)
389 return -EINVAL;
391 return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
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)
398 struct qeth_card *card = dev_get_drvdata(dev);
399 char *tmp;
401 if (!card)
402 return -EINVAL;
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;
414 return count;
417 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
418 qeth_l3_dev_ipato_invert4_show,
419 qeth_l3_dev_ipato_invert4_store);
421 static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
422 enum qeth_prot_versions proto)
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;
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);
446 spin_unlock_irqrestore(&card->ip_lock, flags);
447 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
449 return i;
452 static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
453 struct device_attribute *attr, char *buf)
455 struct qeth_card *card = dev_get_drvdata(dev);
457 if (!card)
458 return -EINVAL;
460 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
463 static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
464 u8 *addr, int *mask_bits)
466 const char *start, *end;
467 char *tmp;
468 char buffer[40] = {0, };
470 start = buf;
471 /* get address string */
472 end = strchr(start, '/');
473 if (!end || (end - start >= 40)) {
474 return -EINVAL;
476 strncpy(buffer, start, end - start);
477 if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
478 return -EINVAL;
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;
487 return 0;
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)
493 struct qeth_ipato_entry *ipatoe;
494 u8 addr[16];
495 int mask_bits;
496 int rc;
498 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
499 if (rc)
500 return rc;
502 ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
503 if (!ipatoe) {
504 return -ENOMEM;
506 ipatoe->proto = proto;
507 memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
508 ipatoe->mask_bits = mask_bits;
510 rc = qeth_l3_add_ipato_entry(card, ipatoe);
511 if (rc) {
512 kfree(ipatoe);
513 return rc;
516 return count;
519 static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
520 struct device_attribute *attr, const char *buf, size_t count)
522 struct qeth_card *card = dev_get_drvdata(dev);
524 if (!card)
525 return -EINVAL;
527 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
530 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
531 qeth_l3_dev_ipato_add4_show,
532 qeth_l3_dev_ipato_add4_store);
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)
537 u8 addr[16];
538 int mask_bits;
539 int rc;
541 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
542 if (rc)
543 return rc;
545 qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
547 return count;
550 static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
551 struct device_attribute *attr, const char *buf, size_t count)
553 struct qeth_card *card = dev_get_drvdata(dev);
555 if (!card)
556 return -EINVAL;
558 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
561 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
562 qeth_l3_dev_ipato_del4_store);
564 static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
565 struct device_attribute *attr, char *buf)
567 struct qeth_card *card = dev_get_drvdata(dev);
569 if (!card)
570 return -EINVAL;
572 return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
575 static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
576 struct device_attribute *attr, const char *buf, size_t count)
578 struct qeth_card *card = dev_get_drvdata(dev);
579 char *tmp;
581 if (!card)
582 return -EINVAL;
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;
594 return count;
597 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
598 qeth_l3_dev_ipato_invert6_show,
599 qeth_l3_dev_ipato_invert6_store);
602 static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
603 struct device_attribute *attr, char *buf)
605 struct qeth_card *card = dev_get_drvdata(dev);
607 if (!card)
608 return -EINVAL;
610 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
613 static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
614 struct device_attribute *attr, const char *buf, size_t count)
616 struct qeth_card *card = dev_get_drvdata(dev);
618 if (!card)
619 return -EINVAL;
621 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
624 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
625 qeth_l3_dev_ipato_add6_show,
626 qeth_l3_dev_ipato_add6_store);
628 static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
629 struct device_attribute *attr, const char *buf, size_t count)
631 struct qeth_card *card = dev_get_drvdata(dev);
633 if (!card)
634 return -EINVAL;
636 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
639 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
640 qeth_l3_dev_ipato_del6_store);
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,
653 static struct attribute_group qeth_device_ipato_group = {
654 .name = "ipa_takeover",
655 .attrs = qeth_ipato_device_attrs,
658 static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
659 enum qeth_prot_versions proto)
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;
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);
684 spin_unlock_irqrestore(&card->ip_lock, flags);
685 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
687 return i;
690 static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
691 struct device_attribute *attr, char *buf)
693 struct qeth_card *card = dev_get_drvdata(dev);
695 if (!card)
696 return -EINVAL;
698 return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
701 static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
702 u8 *addr)
704 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
705 return -EINVAL;
707 return 0;
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)
713 u8 addr[16] = {0, };
714 int rc;
716 rc = qeth_l3_parse_vipae(buf, proto, addr);
717 if (rc)
718 return rc;
720 rc = qeth_l3_add_vipa(card, proto, addr);
721 if (rc)
722 return rc;
724 return count;
727 static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
728 struct device_attribute *attr, const char *buf, size_t count)
730 struct qeth_card *card = dev_get_drvdata(dev);
732 if (!card)
733 return -EINVAL;
735 return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
738 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
739 qeth_l3_dev_vipa_add4_show,
740 qeth_l3_dev_vipa_add4_store);
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)
745 u8 addr[16];
746 int rc;
748 rc = qeth_l3_parse_vipae(buf, proto, addr);
749 if (rc)
750 return rc;
752 qeth_l3_del_vipa(card, proto, addr);
754 return count;
757 static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
758 struct device_attribute *attr, const char *buf, size_t count)
760 struct qeth_card *card = dev_get_drvdata(dev);
762 if (!card)
763 return -EINVAL;
765 return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
768 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
769 qeth_l3_dev_vipa_del4_store);
771 static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
772 struct device_attribute *attr, char *buf)
774 struct qeth_card *card = dev_get_drvdata(dev);
776 if (!card)
777 return -EINVAL;
779 return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
782 static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
783 struct device_attribute *attr, const char *buf, size_t count)
785 struct qeth_card *card = dev_get_drvdata(dev);
787 if (!card)
788 return -EINVAL;
790 return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
793 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
794 qeth_l3_dev_vipa_add6_show,
795 qeth_l3_dev_vipa_add6_store);
797 static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
798 struct device_attribute *attr, const char *buf, size_t count)
800 struct qeth_card *card = dev_get_drvdata(dev);
802 if (!card)
803 return -EINVAL;
805 return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
808 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
809 qeth_l3_dev_vipa_del6_store);
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,
819 static struct attribute_group qeth_device_vipa_group = {
820 .name = "vipa",
821 .attrs = qeth_vipa_device_attrs,
824 static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
825 enum qeth_prot_versions proto)
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;
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);
850 spin_unlock_irqrestore(&card->ip_lock, flags);
851 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
853 return i;
856 static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
857 struct device_attribute *attr, char *buf)
859 struct qeth_card *card = dev_get_drvdata(dev);
861 if (!card)
862 return -EINVAL;
864 return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
867 static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
868 u8 *addr)
870 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
871 return -EINVAL;
873 return 0;
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)
879 u8 addr[16] = {0, };
880 int rc;
882 rc = qeth_l3_parse_rxipe(buf, proto, addr);
883 if (rc)
884 return rc;
886 rc = qeth_l3_add_rxip(card, proto, addr);
887 if (rc)
888 return rc;
890 return count;
893 static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
894 struct device_attribute *attr, const char *buf, size_t count)
896 struct qeth_card *card = dev_get_drvdata(dev);
898 if (!card)
899 return -EINVAL;
901 return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
904 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
905 qeth_l3_dev_rxip_add4_show,
906 qeth_l3_dev_rxip_add4_store);
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)
911 u8 addr[16];
912 int rc;
914 rc = qeth_l3_parse_rxipe(buf, proto, addr);
915 if (rc)
916 return rc;
918 qeth_l3_del_rxip(card, proto, addr);
920 return count;
923 static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
924 struct device_attribute *attr, const char *buf, size_t count)
926 struct qeth_card *card = dev_get_drvdata(dev);
928 if (!card)
929 return -EINVAL;
931 return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
934 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
935 qeth_l3_dev_rxip_del4_store);
937 static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
938 struct device_attribute *attr, char *buf)
940 struct qeth_card *card = dev_get_drvdata(dev);
942 if (!card)
943 return -EINVAL;
945 return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
948 static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
949 struct device_attribute *attr, const char *buf, size_t count)
951 struct qeth_card *card = dev_get_drvdata(dev);
953 if (!card)
954 return -EINVAL;
956 return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
959 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
960 qeth_l3_dev_rxip_add6_show,
961 qeth_l3_dev_rxip_add6_store);
963 static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
964 struct device_attribute *attr, const char *buf, size_t count)
966 struct qeth_card *card = dev_get_drvdata(dev);
968 if (!card)
969 return -EINVAL;
971 return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
974 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
975 qeth_l3_dev_rxip_del6_store);
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,
985 static struct attribute_group qeth_device_rxip_group = {
986 .name = "rxip",
987 .attrs = qeth_rxip_device_attrs,
990 int qeth_l3_create_device_attributes(struct device *dev)
992 int ret;
994 ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
995 if (ret)
996 return ret;
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;
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;
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;
1018 return 0;
1021 void qeth_l3_remove_device_attributes(struct device *dev)
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);