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>
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)
20 else if (card->options.checksum_type == HW_CHECKSUMMING)
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) {
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+");
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+");
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+");
48 return sprintf(buf, "%s\n", "secondary connector");
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);
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;
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;
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);
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);
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);
124 return qeth_l3_dev_route_show(card, &card->options.route6, buf);
127 static ssize_t qeth_l3_dev_route6_store(struct device *dev,
128 struct device_attribute *attr, const char *buf, size_t count)
130 struct qeth_card *card = dev_get_drvdata(dev);
135 return qeth_l3_dev_route_store(card, &card->options.route6,
136 QETH_PROT_IPV6, buf, count);
139 static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
140 qeth_l3_dev_route6_store);
142 static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
143 struct device_attribute *attr, char *buf)
145 struct qeth_card *card = dev_get_drvdata(dev);
150 return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
153 static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
154 struct device_attribute *attr, const char *buf, size_t count)
156 struct qeth_card *card = dev_get_drvdata(dev);
163 if ((card->state != CARD_STATE_DOWN) &&
164 (card->state != CARD_STATE_RECOVER))
167 i = simple_strtoul(buf, &tmp, 16);
168 if ((i == 0) || (i == 1))
169 card->options.fake_broadcast = i;
176 static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
177 qeth_l3_dev_fake_broadcast_store);
179 static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
180 struct device_attribute *attr, char *buf)
182 struct qeth_card *card = dev_get_drvdata(dev);
187 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
188 (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
189 return sprintf(buf, "n/a\n");
191 return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
192 QETH_TR_BROADCAST_ALLRINGS)?
193 "all rings":"local");
196 static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
197 struct device_attribute *attr, const char *buf, size_t count)
199 struct qeth_card *card = dev_get_drvdata(dev);
205 if ((card->state != CARD_STATE_DOWN) &&
206 (card->state != CARD_STATE_RECOVER))
209 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
210 (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
214 tmp = strsep((char **) &buf, "\n");
216 if (!strcmp(tmp, "local")) {
217 card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
219 } else if (!strcmp(tmp, "all_rings")) {
220 card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
228 static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
229 qeth_l3_dev_broadcast_mode_store);
231 static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
232 struct device_attribute *attr, char *buf)
234 struct qeth_card *card = dev_get_drvdata(dev);
239 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
240 (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
241 return sprintf(buf, "n/a\n");
243 return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
244 QETH_TR_MACADDR_CANONICAL)? 1:0);
247 static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
248 struct device_attribute *attr, const char *buf, size_t count)
250 struct qeth_card *card = dev_get_drvdata(dev);
257 if ((card->state != CARD_STATE_DOWN) &&
258 (card->state != CARD_STATE_RECOVER))
261 if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
262 (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
266 i = simple_strtoul(buf, &tmp, 16);
267 if ((i == 0) || (i == 1))
268 card->options.macaddr_mode = i?
269 QETH_TR_MACADDR_CANONICAL :
270 QETH_TR_MACADDR_NONCANONICAL;
277 static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
278 qeth_l3_dev_canonical_macaddr_store);
280 static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
281 struct device_attribute *attr, char *buf)
283 struct qeth_card *card = dev_get_drvdata(dev);
288 return sprintf(buf, "%s checksumming\n",
289 qeth_l3_get_checksum_str(card));
292 static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
293 struct device_attribute *attr, const char *buf, size_t count)
295 struct qeth_card *card = dev_get_drvdata(dev);
301 if ((card->state != CARD_STATE_DOWN) &&
302 (card->state != CARD_STATE_RECOVER))
305 tmp = strsep((char **) &buf, "\n");
306 if (!strcmp(tmp, "sw_checksumming"))
307 card->options.checksum_type = SW_CHECKSUMMING;
308 else if (!strcmp(tmp, "hw_checksumming"))
309 card->options.checksum_type = HW_CHECKSUMMING;
310 else if (!strcmp(tmp, "no_checksumming"))
311 card->options.checksum_type = NO_CHECKSUMMING;
318 static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
319 qeth_l3_dev_checksum_store);
321 static ssize_t qeth_l3_dev_large_send_show(struct device *dev,
322 struct device_attribute *attr, char *buf)
324 struct qeth_card *card = dev_get_drvdata(dev);
329 switch (card->options.large_send) {
330 case QETH_LARGE_SEND_NO:
331 return sprintf(buf, "%s\n", "no");
332 case QETH_LARGE_SEND_TSO:
333 return sprintf(buf, "%s\n", "TSO");
335 return sprintf(buf, "%s\n", "N/A");
339 static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
340 struct device_attribute *attr, const char *buf, size_t count)
342 struct qeth_card *card = dev_get_drvdata(dev);
343 enum qeth_large_send_types type;
349 tmp = strsep((char **) &buf, "\n");
350 if (!strcmp(tmp, "no"))
351 type = QETH_LARGE_SEND_NO;
352 else if (!strcmp(tmp, "TSO"))
353 type = QETH_LARGE_SEND_TSO;
357 if (card->options.large_send == type)
359 rc = qeth_l3_set_large_send(card, type);
365 static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
366 qeth_l3_dev_large_send_store);
368 static struct attribute *qeth_l3_device_attrs[] = {
369 &dev_attr_route4.attr,
370 &dev_attr_route6.attr,
371 &dev_attr_fake_broadcast.attr,
372 &dev_attr_broadcast_mode.attr,
373 &dev_attr_canonical_macaddr.attr,
374 &dev_attr_checksumming.attr,
375 &dev_attr_large_send.attr,
379 static struct attribute_group qeth_l3_device_attr_group = {
380 .attrs = qeth_l3_device_attrs,
383 static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
384 struct device_attribute *attr, char *buf)
386 struct qeth_card *card = dev_get_drvdata(dev);
391 return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
394 static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
395 struct device_attribute *attr, const char *buf, size_t count)
397 struct qeth_card *card = dev_get_drvdata(dev);
403 if ((card->state != CARD_STATE_DOWN) &&
404 (card->state != CARD_STATE_RECOVER))
407 tmp = strsep((char **) &buf, "\n");
408 if (!strcmp(tmp, "toggle")) {
409 card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
410 } else if (!strcmp(tmp, "1")) {
411 card->ipato.enabled = 1;
412 } else if (!strcmp(tmp, "0")) {
413 card->ipato.enabled = 0;
420 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
421 qeth_l3_dev_ipato_enable_show,
422 qeth_l3_dev_ipato_enable_store);
424 static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
425 struct device_attribute *attr, char *buf)
427 struct qeth_card *card = dev_get_drvdata(dev);
432 return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
435 static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
436 struct device_attribute *attr,
437 const char *buf, size_t count)
439 struct qeth_card *card = dev_get_drvdata(dev);
445 tmp = strsep((char **) &buf, "\n");
446 if (!strcmp(tmp, "toggle")) {
447 card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
448 } else if (!strcmp(tmp, "1")) {
449 card->ipato.invert4 = 1;
450 } else if (!strcmp(tmp, "0")) {
451 card->ipato.invert4 = 0;
458 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
459 qeth_l3_dev_ipato_invert4_show,
460 qeth_l3_dev_ipato_invert4_store);
462 static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
463 enum qeth_prot_versions proto)
465 struct qeth_ipato_entry *ipatoe;
468 int entry_len; /* length of 1 entry string, differs between v4 and v6 */
471 entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
472 /* add strlen for "/<mask>\n" */
473 entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
474 spin_lock_irqsave(&card->ip_lock, flags);
475 list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
476 if (ipatoe->proto != proto)
478 /* String must not be longer than PAGE_SIZE. So we check if
479 * string length gets near PAGE_SIZE. Then we can savely display
480 * the next IPv6 address (worst case, compared to IPv4) */
481 if ((PAGE_SIZE - i) <= entry_len)
483 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
484 i += snprintf(buf + i, PAGE_SIZE - i,
485 "%s/%i\n", addr_str, ipatoe->mask_bits);
487 spin_unlock_irqrestore(&card->ip_lock, flags);
488 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
493 static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
494 struct device_attribute *attr, char *buf)
496 struct qeth_card *card = dev_get_drvdata(dev);
501 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
504 static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
505 u8 *addr, int *mask_bits)
507 const char *start, *end;
509 char buffer[40] = {0, };
512 /* get address string */
513 end = strchr(start, '/');
514 if (!end || (end - start >= 40)) {
517 strncpy(buffer, start, end - start);
518 if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
522 *mask_bits = simple_strtoul(start, &tmp, 10);
523 if (!strlen(start) ||
525 (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
531 static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
532 struct qeth_card *card, enum qeth_prot_versions proto)
534 struct qeth_ipato_entry *ipatoe;
539 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
543 ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
547 ipatoe->proto = proto;
548 memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
549 ipatoe->mask_bits = mask_bits;
551 rc = qeth_l3_add_ipato_entry(card, ipatoe);
560 static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
561 struct device_attribute *attr, const char *buf, size_t count)
563 struct qeth_card *card = dev_get_drvdata(dev);
568 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
571 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
572 qeth_l3_dev_ipato_add4_show,
573 qeth_l3_dev_ipato_add4_store);
575 static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
576 struct qeth_card *card, enum qeth_prot_versions proto)
582 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
586 qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
591 static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
592 struct device_attribute *attr, const char *buf, size_t count)
594 struct qeth_card *card = dev_get_drvdata(dev);
599 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
602 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
603 qeth_l3_dev_ipato_del4_store);
605 static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
606 struct device_attribute *attr, char *buf)
608 struct qeth_card *card = dev_get_drvdata(dev);
613 return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
616 static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
617 struct device_attribute *attr, const char *buf, size_t count)
619 struct qeth_card *card = dev_get_drvdata(dev);
625 tmp = strsep((char **) &buf, "\n");
626 if (!strcmp(tmp, "toggle")) {
627 card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
628 } else if (!strcmp(tmp, "1")) {
629 card->ipato.invert6 = 1;
630 } else if (!strcmp(tmp, "0")) {
631 card->ipato.invert6 = 0;
638 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
639 qeth_l3_dev_ipato_invert6_show,
640 qeth_l3_dev_ipato_invert6_store);
643 static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
644 struct device_attribute *attr, char *buf)
646 struct qeth_card *card = dev_get_drvdata(dev);
651 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
654 static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
655 struct device_attribute *attr, const char *buf, size_t count)
657 struct qeth_card *card = dev_get_drvdata(dev);
662 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
665 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
666 qeth_l3_dev_ipato_add6_show,
667 qeth_l3_dev_ipato_add6_store);
669 static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
670 struct device_attribute *attr, const char *buf, size_t count)
672 struct qeth_card *card = dev_get_drvdata(dev);
677 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
680 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
681 qeth_l3_dev_ipato_del6_store);
683 static struct attribute *qeth_ipato_device_attrs[] = {
684 &dev_attr_ipato_enable.attr,
685 &dev_attr_ipato_invert4.attr,
686 &dev_attr_ipato_add4.attr,
687 &dev_attr_ipato_del4.attr,
688 &dev_attr_ipato_invert6.attr,
689 &dev_attr_ipato_add6.attr,
690 &dev_attr_ipato_del6.attr,
694 static struct attribute_group qeth_device_ipato_group = {
695 .name = "ipa_takeover",
696 .attrs = qeth_ipato_device_attrs,
699 static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
700 enum qeth_prot_versions proto)
702 struct qeth_ipaddr *ipaddr;
704 int entry_len; /* length of 1 entry string, differs between v4 and v6 */
708 entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
709 entry_len += 2; /* \n + terminator */
710 spin_lock_irqsave(&card->ip_lock, flags);
711 list_for_each_entry(ipaddr, &card->ip_list, entry) {
712 if (ipaddr->proto != proto)
714 if (ipaddr->type != QETH_IP_TYPE_VIPA)
716 /* String must not be longer than PAGE_SIZE. So we check if
717 * string length gets near PAGE_SIZE. Then we can savely display
718 * the next IPv6 address (worst case, compared to IPv4) */
719 if ((PAGE_SIZE - i) <= entry_len)
721 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
723 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
725 spin_unlock_irqrestore(&card->ip_lock, flags);
726 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
731 static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
732 struct device_attribute *attr, char *buf)
734 struct qeth_card *card = dev_get_drvdata(dev);
739 return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
742 static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
745 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
751 static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
752 struct qeth_card *card, enum qeth_prot_versions proto)
757 rc = qeth_l3_parse_vipae(buf, proto, addr);
761 rc = qeth_l3_add_vipa(card, proto, addr);
768 static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
769 struct device_attribute *attr, const char *buf, size_t count)
771 struct qeth_card *card = dev_get_drvdata(dev);
776 return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
779 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
780 qeth_l3_dev_vipa_add4_show,
781 qeth_l3_dev_vipa_add4_store);
783 static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
784 struct qeth_card *card, enum qeth_prot_versions proto)
789 rc = qeth_l3_parse_vipae(buf, proto, addr);
793 qeth_l3_del_vipa(card, proto, addr);
798 static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
799 struct device_attribute *attr, const char *buf, size_t count)
801 struct qeth_card *card = dev_get_drvdata(dev);
806 return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
809 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
810 qeth_l3_dev_vipa_del4_store);
812 static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
813 struct device_attribute *attr, char *buf)
815 struct qeth_card *card = dev_get_drvdata(dev);
820 return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
823 static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
824 struct device_attribute *attr, const char *buf, size_t count)
826 struct qeth_card *card = dev_get_drvdata(dev);
831 return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
834 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
835 qeth_l3_dev_vipa_add6_show,
836 qeth_l3_dev_vipa_add6_store);
838 static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
839 struct device_attribute *attr, const char *buf, size_t count)
841 struct qeth_card *card = dev_get_drvdata(dev);
846 return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
849 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
850 qeth_l3_dev_vipa_del6_store);
852 static struct attribute *qeth_vipa_device_attrs[] = {
853 &dev_attr_vipa_add4.attr,
854 &dev_attr_vipa_del4.attr,
855 &dev_attr_vipa_add6.attr,
856 &dev_attr_vipa_del6.attr,
860 static struct attribute_group qeth_device_vipa_group = {
862 .attrs = qeth_vipa_device_attrs,
865 static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
866 enum qeth_prot_versions proto)
868 struct qeth_ipaddr *ipaddr;
870 int entry_len; /* length of 1 entry string, differs between v4 and v6 */
874 entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
875 entry_len += 2; /* \n + terminator */
876 spin_lock_irqsave(&card->ip_lock, flags);
877 list_for_each_entry(ipaddr, &card->ip_list, entry) {
878 if (ipaddr->proto != proto)
880 if (ipaddr->type != QETH_IP_TYPE_RXIP)
882 /* String must not be longer than PAGE_SIZE. So we check if
883 * string length gets near PAGE_SIZE. Then we can savely display
884 * the next IPv6 address (worst case, compared to IPv4) */
885 if ((PAGE_SIZE - i) <= entry_len)
887 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
889 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
891 spin_unlock_irqrestore(&card->ip_lock, flags);
892 i += snprintf(buf + i, PAGE_SIZE - i, "\n");
897 static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
898 struct device_attribute *attr, char *buf)
900 struct qeth_card *card = dev_get_drvdata(dev);
905 return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
908 static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
911 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
917 static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
918 struct qeth_card *card, enum qeth_prot_versions proto)
923 rc = qeth_l3_parse_rxipe(buf, proto, addr);
927 rc = qeth_l3_add_rxip(card, proto, addr);
934 static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
935 struct device_attribute *attr, const char *buf, size_t count)
937 struct qeth_card *card = dev_get_drvdata(dev);
942 return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
945 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
946 qeth_l3_dev_rxip_add4_show,
947 qeth_l3_dev_rxip_add4_store);
949 static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
950 struct qeth_card *card, enum qeth_prot_versions proto)
955 rc = qeth_l3_parse_rxipe(buf, proto, addr);
959 qeth_l3_del_rxip(card, proto, addr);
964 static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
965 struct device_attribute *attr, const char *buf, size_t count)
967 struct qeth_card *card = dev_get_drvdata(dev);
972 return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
975 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
976 qeth_l3_dev_rxip_del4_store);
978 static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
979 struct device_attribute *attr, char *buf)
981 struct qeth_card *card = dev_get_drvdata(dev);
986 return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
989 static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
990 struct device_attribute *attr, const char *buf, size_t count)
992 struct qeth_card *card = dev_get_drvdata(dev);
997 return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
1000 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
1001 qeth_l3_dev_rxip_add6_show,
1002 qeth_l3_dev_rxip_add6_store);
1004 static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
1005 struct device_attribute *attr, const char *buf, size_t count)
1007 struct qeth_card *card = dev_get_drvdata(dev);
1012 return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
1015 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
1016 qeth_l3_dev_rxip_del6_store);
1018 static struct attribute *qeth_rxip_device_attrs[] = {
1019 &dev_attr_rxip_add4.attr,
1020 &dev_attr_rxip_del4.attr,
1021 &dev_attr_rxip_add6.attr,
1022 &dev_attr_rxip_del6.attr,
1026 static struct attribute_group qeth_device_rxip_group = {
1028 .attrs = qeth_rxip_device_attrs,
1031 int qeth_l3_create_device_attributes(struct device *dev)
1035 ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
1039 ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
1041 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1045 ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
1047 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1048 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1052 ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
1054 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1055 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1056 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1062 void qeth_l3_remove_device_attributes(struct device *dev)
1064 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1065 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1066 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1067 sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);