788 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright IBM Corp. 20074 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,5 * Frank Pavlic <fpavlic@de.ibm.com>,6 * Thomas Spatzier <tspat@de.ibm.com>,7 * Frank Blaschka <frank.blaschka@de.ibm.com>8 */9 10#include <linux/slab.h>11#include <asm/ebcdic.h>12#include <linux/hashtable.h>13#include <linux/inet.h>14#include "qeth_l3.h"15 16#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \17struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)18 19static int qeth_l3_string_to_ipaddr(const char *buf,20 enum qeth_prot_versions proto, u8 *addr)21{22 const char *end;23 24 if ((proto == QETH_PROT_IPV4 && !in4_pton(buf, -1, addr, -1, &end)) ||25 (proto == QETH_PROT_IPV6 && !in6_pton(buf, -1, addr, -1, &end)))26 return -EINVAL;27 return 0;28}29 30static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,31 struct qeth_routing_info *route, char *buf)32{33 switch (route->type) {34 case PRIMARY_ROUTER:35 return sysfs_emit(buf, "%s\n", "primary router");36 case SECONDARY_ROUTER:37 return sysfs_emit(buf, "%s\n", "secondary router");38 case MULTICAST_ROUTER:39 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)40 return sysfs_emit(buf, "%s\n", "multicast router+");41 else42 return sysfs_emit(buf, "%s\n", "multicast router");43 case PRIMARY_CONNECTOR:44 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)45 return sysfs_emit(buf, "%s\n", "primary connector+");46 else47 return sysfs_emit(buf, "%s\n", "primary connector");48 case SECONDARY_CONNECTOR:49 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)50 return sysfs_emit(buf, "%s\n", "secondary connector+");51 else52 return sysfs_emit(buf, "%s\n", "secondary connector");53 default:54 return sysfs_emit(buf, "%s\n", "no");55 }56}57 58static ssize_t qeth_l3_dev_route4_show(struct device *dev,59 struct device_attribute *attr, char *buf)60{61 struct qeth_card *card = dev_get_drvdata(dev);62 63 return qeth_l3_dev_route_show(card, &card->options.route4, buf);64}65 66static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,67 struct qeth_routing_info *route, enum qeth_prot_versions prot,68 const char *buf, size_t count)69{70 enum qeth_routing_types old_route_type = route->type;71 int rc = 0;72 73 mutex_lock(&card->conf_mutex);74 if (sysfs_streq(buf, "no_router")) {75 route->type = NO_ROUTER;76 } else if (sysfs_streq(buf, "primary_connector")) {77 route->type = PRIMARY_CONNECTOR;78 } else if (sysfs_streq(buf, "secondary_connector")) {79 route->type = SECONDARY_CONNECTOR;80 } else if (sysfs_streq(buf, "primary_router")) {81 route->type = PRIMARY_ROUTER;82 } else if (sysfs_streq(buf, "secondary_router")) {83 route->type = SECONDARY_ROUTER;84 } else if (sysfs_streq(buf, "multicast_router")) {85 route->type = MULTICAST_ROUTER;86 } else {87 rc = -EINVAL;88 goto out;89 }90 if (qeth_card_hw_is_reachable(card) &&91 (old_route_type != route->type)) {92 if (prot == QETH_PROT_IPV4)93 rc = qeth_l3_setrouting_v4(card);94 else if (prot == QETH_PROT_IPV6)95 rc = qeth_l3_setrouting_v6(card);96 }97out:98 if (rc)99 route->type = old_route_type;100 mutex_unlock(&card->conf_mutex);101 return rc ? rc : count;102}103 104static ssize_t qeth_l3_dev_route4_store(struct device *dev,105 struct device_attribute *attr, const char *buf, size_t count)106{107 struct qeth_card *card = dev_get_drvdata(dev);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 return qeth_l3_dev_route_show(card, &card->options.route6, buf);122}123 124static ssize_t qeth_l3_dev_route6_store(struct device *dev,125 struct device_attribute *attr, const char *buf, size_t count)126{127 struct qeth_card *card = dev_get_drvdata(dev);128 129 return qeth_l3_dev_route_store(card, &card->options.route6,130 QETH_PROT_IPV6, buf, count);131}132 133static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,134 qeth_l3_dev_route6_store);135 136static ssize_t qeth_l3_dev_sniffer_show(struct device *dev,137 struct device_attribute *attr, char *buf)138{139 struct qeth_card *card = dev_get_drvdata(dev);140 141 return sysfs_emit(buf, "%i\n", card->options.sniffer ? 1 : 0);142}143 144static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,145 struct device_attribute *attr, const char *buf, size_t count)146{147 struct qeth_card *card = dev_get_drvdata(dev);148 int rc = 0;149 unsigned long i;150 151 if (!IS_IQD(card))152 return -EPERM;153 if (card->options.cq == QETH_CQ_ENABLED)154 return -EPERM;155 156 mutex_lock(&card->conf_mutex);157 if (card->state != CARD_STATE_DOWN) {158 rc = -EPERM;159 goto out;160 }161 162 rc = kstrtoul(buf, 16, &i);163 if (rc) {164 rc = -EINVAL;165 goto out;166 }167 switch (i) {168 case 0:169 card->options.sniffer = i;170 break;171 case 1:172 qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);173 if (card->ssqd.qdioac2 & CHSC_AC2_SNIFFER_AVAILABLE) {174 card->options.sniffer = i;175 qeth_resize_buffer_pool(card, QETH_IN_BUF_COUNT_MAX);176 } else {177 rc = -EPERM;178 }179 180 break;181 default:182 rc = -EINVAL;183 }184out:185 mutex_unlock(&card->conf_mutex);186 return rc ? rc : count;187}188 189static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,190 qeth_l3_dev_sniffer_store);191 192static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,193 struct device_attribute *attr, char *buf)194{195 struct qeth_card *card = dev_get_drvdata(dev);196 char tmp_hsuid[9];197 198 if (!IS_IQD(card))199 return -EPERM;200 201 memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));202 EBCASC(tmp_hsuid, 8);203 return sysfs_emit(buf, "%s\n", tmp_hsuid);204}205 206static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,207 struct device_attribute *attr, const char *buf, size_t count)208{209 struct qeth_card *card = dev_get_drvdata(dev);210 int rc = 0;211 char *tmp;212 213 if (!IS_IQD(card))214 return -EPERM;215 216 mutex_lock(&card->conf_mutex);217 if (card->state != CARD_STATE_DOWN) {218 rc = -EPERM;219 goto out;220 }221 222 if (card->options.sniffer) {223 rc = -EPERM;224 goto out;225 }226 227 if (card->options.cq == QETH_CQ_NOTAVAILABLE) {228 rc = -EPERM;229 goto out;230 }231 232 tmp = strsep((char **)&buf, "\n");233 if (strlen(tmp) > 8) {234 rc = -EINVAL;235 goto out;236 }237 238 if (card->options.hsuid[0])239 /* delete old ip address */240 qeth_l3_modify_hsuid(card, false);241 242 if (strlen(tmp) == 0) {243 /* delete ip address only */244 card->options.hsuid[0] = '\0';245 memcpy(card->dev->perm_addr, card->options.hsuid, 9);246 qeth_configure_cq(card, QETH_CQ_DISABLED);247 goto out;248 }249 250 if (qeth_configure_cq(card, QETH_CQ_ENABLED)) {251 rc = -EPERM;252 goto out;253 }254 255 scnprintf(card->options.hsuid, sizeof(card->options.hsuid),256 "%-8s", tmp);257 ASCEBC(card->options.hsuid, 8);258 memcpy(card->dev->perm_addr, card->options.hsuid, 9);259 260 rc = qeth_l3_modify_hsuid(card, true);261 262out:263 mutex_unlock(&card->conf_mutex);264 return rc ? rc : count;265}266 267static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,268 qeth_l3_dev_hsuid_store);269 270 271static struct attribute *qeth_l3_device_attrs[] = {272 &dev_attr_route4.attr,273 &dev_attr_route6.attr,274 &dev_attr_sniffer.attr,275 &dev_attr_hsuid.attr,276 NULL,277};278 279static const struct attribute_group qeth_l3_device_attr_group = {280 .attrs = qeth_l3_device_attrs,281};282 283static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,284 struct device_attribute *attr, char *buf)285{286 struct qeth_card *card = dev_get_drvdata(dev);287 288 return sysfs_emit(buf, "%u\n", card->ipato.enabled ? 1 : 0);289}290 291static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,292 struct device_attribute *attr, const char *buf, size_t count)293{294 struct qeth_card *card = dev_get_drvdata(dev);295 bool enable;296 int rc = 0;297 298 mutex_lock(&card->conf_mutex);299 if (card->state != CARD_STATE_DOWN) {300 rc = -EPERM;301 goto out;302 }303 304 mutex_lock(&card->ip_lock);305 if (sysfs_streq(buf, "toggle")) {306 enable = !card->ipato.enabled;307 } else if (kstrtobool(buf, &enable)) {308 rc = -EINVAL;309 goto unlock_ip;310 }311 312 if (card->ipato.enabled != enable) {313 card->ipato.enabled = enable;314 qeth_l3_update_ipato(card);315 }316 317unlock_ip:318 mutex_unlock(&card->ip_lock);319out:320 mutex_unlock(&card->conf_mutex);321 return rc ? rc : count;322}323 324static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,325 qeth_l3_dev_ipato_enable_show,326 qeth_l3_dev_ipato_enable_store);327 328static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,329 struct device_attribute *attr, char *buf)330{331 struct qeth_card *card = dev_get_drvdata(dev);332 333 return sysfs_emit(buf, "%u\n", card->ipato.invert4 ? 1 : 0);334}335 336static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,337 struct device_attribute *attr,338 const char *buf, size_t count)339{340 struct qeth_card *card = dev_get_drvdata(dev);341 bool invert;342 int rc = 0;343 344 mutex_lock(&card->ip_lock);345 if (sysfs_streq(buf, "toggle")) {346 invert = !card->ipato.invert4;347 } else if (kstrtobool(buf, &invert)) {348 rc = -EINVAL;349 goto out;350 }351 352 if (card->ipato.invert4 != invert) {353 card->ipato.invert4 = invert;354 qeth_l3_update_ipato(card);355 }356 357out:358 mutex_unlock(&card->ip_lock);359 return rc ? rc : count;360}361 362static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,363 qeth_l3_dev_ipato_invert4_show,364 qeth_l3_dev_ipato_invert4_store);365 366static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,367 enum qeth_prot_versions proto)368{369 struct qeth_ipato_entry *ipatoe;370 char addr_str[INET6_ADDRSTRLEN];371 int offset = 0;372 373 mutex_lock(&card->ip_lock);374 list_for_each_entry(ipatoe, &card->ipato.entries, entry) {375 if (ipatoe->proto != proto)376 continue;377 378 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);379 offset += sysfs_emit_at(buf, offset, "%s/%i\n",380 addr_str, ipatoe->mask_bits);381 }382 mutex_unlock(&card->ip_lock);383 384 return offset ? offset : sysfs_emit(buf, "\n");385}386 387static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,388 struct device_attribute *attr, char *buf)389{390 struct qeth_card *card = dev_get_drvdata(dev);391 392 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);393}394 395static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,396 u8 *addr, unsigned int *mask_bits)397{398 char *sep;399 int rc;400 401 /* Expected input pattern: %addr/%mask */402 sep = strnchr(buf, INET6_ADDRSTRLEN, '/');403 if (!sep)404 return -EINVAL;405 406 /* Terminate the %addr sub-string, and parse it: */407 *sep = '\0';408 rc = qeth_l3_string_to_ipaddr(buf, proto, addr);409 if (rc)410 return rc;411 412 rc = kstrtouint(sep + 1, 10, mask_bits);413 if (rc)414 return rc;415 416 if (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))417 return -EINVAL;418 419 return 0;420}421 422static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,423 struct qeth_card *card, enum qeth_prot_versions proto)424{425 struct qeth_ipato_entry *ipatoe;426 unsigned int mask_bits;427 u8 addr[16];428 int rc = 0;429 430 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);431 if (rc)432 return rc;433 434 ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);435 if (!ipatoe)436 return -ENOMEM;437 438 ipatoe->proto = proto;439 memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4) ? 4 : 16);440 ipatoe->mask_bits = mask_bits;441 442 rc = qeth_l3_add_ipato_entry(card, ipatoe);443 if (rc)444 kfree(ipatoe);445 446 return rc ? rc : count;447}448 449static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,450 struct device_attribute *attr, const char *buf, size_t count)451{452 struct qeth_card *card = dev_get_drvdata(dev);453 454 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);455}456 457static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,458 qeth_l3_dev_ipato_add4_show,459 qeth_l3_dev_ipato_add4_store);460 461static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,462 struct qeth_card *card, enum qeth_prot_versions proto)463{464 unsigned int mask_bits;465 u8 addr[16];466 int rc = 0;467 468 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);469 if (!rc)470 rc = qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);471 return rc ? rc : count;472}473 474static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,475 struct device_attribute *attr, const char *buf, size_t count)476{477 struct qeth_card *card = dev_get_drvdata(dev);478 479 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);480}481 482static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,483 qeth_l3_dev_ipato_del4_store);484 485static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,486 struct device_attribute *attr, char *buf)487{488 struct qeth_card *card = dev_get_drvdata(dev);489 490 return sysfs_emit(buf, "%u\n", card->ipato.invert6 ? 1 : 0);491}492 493static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,494 struct device_attribute *attr, const char *buf, size_t count)495{496 struct qeth_card *card = dev_get_drvdata(dev);497 bool invert;498 int rc = 0;499 500 mutex_lock(&card->ip_lock);501 if (sysfs_streq(buf, "toggle")) {502 invert = !card->ipato.invert6;503 } else if (kstrtobool(buf, &invert)) {504 rc = -EINVAL;505 goto out;506 }507 508 if (card->ipato.invert6 != invert) {509 card->ipato.invert6 = invert;510 qeth_l3_update_ipato(card);511 }512 513out:514 mutex_unlock(&card->ip_lock);515 return rc ? rc : count;516}517 518static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,519 qeth_l3_dev_ipato_invert6_show,520 qeth_l3_dev_ipato_invert6_store);521 522 523static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,524 struct device_attribute *attr, char *buf)525{526 struct qeth_card *card = dev_get_drvdata(dev);527 528 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);529}530 531static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,532 struct device_attribute *attr, const char *buf, size_t count)533{534 struct qeth_card *card = dev_get_drvdata(dev);535 536 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);537}538 539static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,540 qeth_l3_dev_ipato_add6_show,541 qeth_l3_dev_ipato_add6_store);542 543static ssize_t qeth_l3_dev_ipato_del6_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 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);549}550 551static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,552 qeth_l3_dev_ipato_del6_store);553 554static struct attribute *qeth_ipato_device_attrs[] = {555 &dev_attr_ipato_enable.attr,556 &dev_attr_ipato_invert4.attr,557 &dev_attr_ipato_add4.attr,558 &dev_attr_ipato_del4.attr,559 &dev_attr_ipato_invert6.attr,560 &dev_attr_ipato_add6.attr,561 &dev_attr_ipato_del6.attr,562 NULL,563};564 565static const struct attribute_group qeth_device_ipato_group = {566 .name = "ipa_takeover",567 .attrs = qeth_ipato_device_attrs,568};569 570static ssize_t qeth_l3_dev_ip_add_show(struct device *dev, char *buf,571 enum qeth_prot_versions proto,572 enum qeth_ip_types type)573{574 struct qeth_card *card = dev_get_drvdata(dev);575 char addr_str[INET6_ADDRSTRLEN];576 struct qeth_ipaddr *ipaddr;577 int offset = 0;578 int i;579 580 mutex_lock(&card->ip_lock);581 hash_for_each(card->ip_htable, i, ipaddr, hnode) {582 if (ipaddr->proto != proto || ipaddr->type != type)583 continue;584 585 qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u, addr_str);586 offset += sysfs_emit_at(buf, offset, "%s\n", addr_str);587 }588 mutex_unlock(&card->ip_lock);589 590 return offset ? offset : sysfs_emit(buf, "\n");591}592 593static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,594 struct device_attribute *attr,595 char *buf)596{597 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,598 QETH_IP_TYPE_VIPA);599}600 601static ssize_t qeth_l3_vipa_store(struct device *dev, const char *buf, bool add,602 size_t count, enum qeth_prot_versions proto)603{604 struct qeth_card *card = dev_get_drvdata(dev);605 u8 addr[16] = {0, };606 int rc;607 608 rc = qeth_l3_string_to_ipaddr(buf, proto, addr);609 if (!rc)610 rc = qeth_l3_modify_rxip_vipa(card, add, addr,611 QETH_IP_TYPE_VIPA, proto);612 return rc ? rc : count;613}614 615static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,616 struct device_attribute *attr, const char *buf, size_t count)617{618 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);619}620 621static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,622 qeth_l3_dev_vipa_add4_show,623 qeth_l3_dev_vipa_add4_store);624 625static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,626 struct device_attribute *attr, const char *buf, size_t count)627{628 return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV4);629}630 631static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,632 qeth_l3_dev_vipa_del4_store);633 634static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,635 struct device_attribute *attr,636 char *buf)637{638 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,639 QETH_IP_TYPE_VIPA);640}641 642static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,643 struct device_attribute *attr, const char *buf, size_t count)644{645 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV6);646}647 648static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,649 qeth_l3_dev_vipa_add6_show,650 qeth_l3_dev_vipa_add6_store);651 652static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,653 struct device_attribute *attr, const char *buf, size_t count)654{655 return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV6);656}657 658static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,659 qeth_l3_dev_vipa_del6_store);660 661static struct attribute *qeth_vipa_device_attrs[] = {662 &dev_attr_vipa_add4.attr,663 &dev_attr_vipa_del4.attr,664 &dev_attr_vipa_add6.attr,665 &dev_attr_vipa_del6.attr,666 NULL,667};668 669static const struct attribute_group qeth_device_vipa_group = {670 .name = "vipa",671 .attrs = qeth_vipa_device_attrs,672};673 674static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,675 struct device_attribute *attr,676 char *buf)677{678 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,679 QETH_IP_TYPE_RXIP);680}681 682static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,683 u8 *addr)684{685 __be32 ipv4_addr;686 struct in6_addr ipv6_addr;687 688 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {689 return -EINVAL;690 }691 if (proto == QETH_PROT_IPV4) {692 memcpy(&ipv4_addr, addr, sizeof(ipv4_addr));693 if (ipv4_is_multicast(ipv4_addr)) {694 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");695 return -EINVAL;696 }697 } else if (proto == QETH_PROT_IPV6) {698 memcpy(&ipv6_addr, addr, sizeof(ipv6_addr));699 if (ipv6_addr_is_multicast(&ipv6_addr)) {700 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");701 return -EINVAL;702 }703 }704 705 return 0;706}707 708static ssize_t qeth_l3_rxip_store(struct device *dev, const char *buf, bool add,709 size_t count, enum qeth_prot_versions proto)710{711 struct qeth_card *card = dev_get_drvdata(dev);712 u8 addr[16] = {0, };713 int rc;714 715 rc = qeth_l3_parse_rxipe(buf, proto, addr);716 if (!rc)717 rc = qeth_l3_modify_rxip_vipa(card, add, addr,718 QETH_IP_TYPE_RXIP, proto);719 return rc ? rc : count;720}721 722static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,723 struct device_attribute *attr, const char *buf, size_t count)724{725 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV4);726}727 728static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,729 qeth_l3_dev_rxip_add4_show,730 qeth_l3_dev_rxip_add4_store);731 732static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,733 struct device_attribute *attr, const char *buf, size_t count)734{735 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV4);736}737 738static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,739 qeth_l3_dev_rxip_del4_store);740 741static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,742 struct device_attribute *attr,743 char *buf)744{745 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,746 QETH_IP_TYPE_RXIP);747}748 749static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,750 struct device_attribute *attr, const char *buf, size_t count)751{752 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV6);753}754 755static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,756 qeth_l3_dev_rxip_add6_show,757 qeth_l3_dev_rxip_add6_store);758 759static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,760 struct device_attribute *attr, const char *buf, size_t count)761{762 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV6);763}764 765static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,766 qeth_l3_dev_rxip_del6_store);767 768static struct attribute *qeth_rxip_device_attrs[] = {769 &dev_attr_rxip_add4.attr,770 &dev_attr_rxip_del4.attr,771 &dev_attr_rxip_add6.attr,772 &dev_attr_rxip_del6.attr,773 NULL,774};775 776static const struct attribute_group qeth_device_rxip_group = {777 .name = "rxip",778 .attrs = qeth_rxip_device_attrs,779};780 781const struct attribute_group *qeth_l3_attr_groups[] = {782 &qeth_l3_device_attr_group,783 &qeth_device_ipato_group,784 &qeth_device_vipa_group,785 &qeth_device_rxip_group,786 NULL,787};788