linux/drivers/s390/net/qeth_l3_sys.c
<<
>>
Prefs
   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}
1021