brintos

brintos / linux-shallow public Read only

0
0
Text · 20.0 KiB · a6b6422 Raw
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