Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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