Linux Audio

Check our new training course

Loading...
   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 <linux/slab.h>
  12#include <asm/ebcdic.h>
  13#include "qeth_l3.h"
  14
  15#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  16struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  17
  18static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
  19			struct qeth_routing_info *route, char *buf)
  20{
  21	switch (route->type) {
  22	case PRIMARY_ROUTER:
  23		return sprintf(buf, "%s\n", "primary router");
  24	case SECONDARY_ROUTER:
  25		return sprintf(buf, "%s\n", "secondary router");
  26	case MULTICAST_ROUTER:
  27		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  28			return sprintf(buf, "%s\n", "multicast router+");
  29		else
  30			return sprintf(buf, "%s\n", "multicast router");
  31	case PRIMARY_CONNECTOR:
  32		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  33			return sprintf(buf, "%s\n", "primary connector+");
  34		else
  35			return sprintf(buf, "%s\n", "primary connector");
  36	case SECONDARY_CONNECTOR:
  37		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  38			return sprintf(buf, "%s\n", "secondary connector+");
  39		else
  40			return sprintf(buf, "%s\n", "secondary connector");
  41	default:
  42		return sprintf(buf, "%s\n", "no");
  43	}
  44}
  45
  46static ssize_t qeth_l3_dev_route4_show(struct device *dev,
  47			struct device_attribute *attr, char *buf)
  48{
  49	struct qeth_card *card = dev_get_drvdata(dev);
  50
  51	if (!card)
  52		return -EINVAL;
  53
  54	return qeth_l3_dev_route_show(card, &card->options.route4, buf);
  55}
  56
  57static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
  58		struct qeth_routing_info *route, enum qeth_prot_versions prot,
  59		const char *buf, size_t count)
  60{
  61	enum qeth_routing_types old_route_type = route->type;
  62	char *tmp;
  63	int rc = 0;
  64
  65	tmp = strsep((char **) &buf, "\n");
  66	mutex_lock(&card->conf_mutex);
  67	if (!strcmp(tmp, "no_router")) {
  68		route->type = NO_ROUTER;
  69	} else if (!strcmp(tmp, "primary_connector")) {
  70		route->type = PRIMARY_CONNECTOR;
  71	} else if (!strcmp(tmp, "secondary_connector")) {
  72		route->type = SECONDARY_CONNECTOR;
  73	} else if (!strcmp(tmp, "primary_router")) {
  74		route->type = PRIMARY_ROUTER;
  75	} else if (!strcmp(tmp, "secondary_router")) {
  76		route->type = SECONDARY_ROUTER;
  77	} else if (!strcmp(tmp, "multicast_router")) {
  78		route->type = MULTICAST_ROUTER;
  79	} else {
  80		rc = -EINVAL;
  81		goto out;
  82	}
  83	if (((card->state == CARD_STATE_SOFTSETUP) ||
  84	     (card->state == CARD_STATE_UP)) &&
  85	    (old_route_type != route->type)) {
  86		if (prot == QETH_PROT_IPV4)
  87			rc = qeth_l3_setrouting_v4(card);
  88		else if (prot == QETH_PROT_IPV6)
  89			rc = qeth_l3_setrouting_v6(card);
  90	}
  91out:
  92	mutex_unlock(&card->conf_mutex);
  93	return rc ? rc : count;
  94}
  95
  96static ssize_t qeth_l3_dev_route4_store(struct device *dev,
  97		struct device_attribute *attr, const char *buf, size_t count)
  98{
  99	struct qeth_card *card = dev_get_drvdata(dev);
 100
 101	if (!card)
 102		return -EINVAL;
 103
 104	return qeth_l3_dev_route_store(card, &card->options.route4,
 105				QETH_PROT_IPV4, buf, count);
 106}
 107
 108static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
 109			qeth_l3_dev_route4_store);
 110
 111static ssize_t qeth_l3_dev_route6_show(struct device *dev,
 112			struct device_attribute *attr, char *buf)
 113{
 114	struct qeth_card *card = dev_get_drvdata(dev);
 115
 116	if (!card)
 117		return -EINVAL;
 118
 119	return qeth_l3_dev_route_show(card, &card->options.route6, buf);
 120}
 121
 122static ssize_t qeth_l3_dev_route6_store(struct device *dev,
 123		struct device_attribute *attr, const char *buf, size_t count)
 124{
 125	struct qeth_card *card = dev_get_drvdata(dev);
 126
 127	if (!card)
 128		return -EINVAL;
 129
 130	return qeth_l3_dev_route_store(card, &card->options.route6,
 131				QETH_PROT_IPV6, buf, count);
 132}
 133
 134static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
 135			qeth_l3_dev_route6_store);
 136
 137static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
 138			struct device_attribute *attr, char *buf)
 139{
 140	struct qeth_card *card = dev_get_drvdata(dev);
 141
 142	if (!card)
 143		return -EINVAL;
 144
 145	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
 146}
 147
 148static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
 149		struct device_attribute *attr, const char *buf, size_t count)
 150{
 151	struct qeth_card *card = dev_get_drvdata(dev);
 152	char *tmp;
 153	int i, rc = 0;
 154
 155	if (!card)
 156		return -EINVAL;
 157
 158	mutex_lock(&card->conf_mutex);
 159	if ((card->state != CARD_STATE_DOWN) &&
 160	    (card->state != CARD_STATE_RECOVER)) {
 161		rc = -EPERM;
 162		goto out;
 163	}
 164
 165	i = simple_strtoul(buf, &tmp, 16);
 166	if ((i == 0) || (i == 1))
 167		card->options.fake_broadcast = i;
 168	else
 169		rc = -EINVAL;
 170out:
 171	mutex_unlock(&card->conf_mutex);
 172	return rc ? rc : count;
 173}
 174
 175static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
 176		   qeth_l3_dev_fake_broadcast_store);
 177
 178static ssize_t qeth_l3_dev_sniffer_show(struct device *dev,
 179		struct device_attribute *attr, char *buf)
 180{
 181	struct qeth_card *card = dev_get_drvdata(dev);
 182
 183	if (!card)
 184		return -EINVAL;
 185
 186	return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0);
 187}
 188
 189static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
 190		struct device_attribute *attr, const char *buf, size_t count)
 191{
 192	struct qeth_card *card = dev_get_drvdata(dev);
 193	int rc = 0;
 194	unsigned long i;
 195
 196	if (!card)
 197		return -EINVAL;
 198
 199	if (card->info.type != QETH_CARD_TYPE_IQD)
 200		return -EPERM;
 201	if (card->options.cq == QETH_CQ_ENABLED)
 202		return -EPERM;
 203
 204	mutex_lock(&card->conf_mutex);
 205	if ((card->state != CARD_STATE_DOWN) &&
 206	    (card->state != CARD_STATE_RECOVER)) {
 207		rc = -EPERM;
 208		goto out;
 209	}
 210
 211	rc = strict_strtoul(buf, 16, &i);
 212	if (rc) {
 213		rc = -EINVAL;
 214		goto out;
 215	}
 216	switch (i) {
 217	case 0:
 218		card->options.sniffer = i;
 219		break;
 220	case 1:
 221		qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
 222		if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) {
 223			card->options.sniffer = i;
 224			if (card->qdio.init_pool.buf_count !=
 225					QETH_IN_BUF_COUNT_MAX)
 226				qeth_realloc_buffer_pool(card,
 227					QETH_IN_BUF_COUNT_MAX);
 228		} else
 229			rc = -EPERM;
 230		break;
 231	default:
 232		rc = -EINVAL;
 233	}
 234out:
 235	mutex_unlock(&card->conf_mutex);
 236	return rc ? rc : count;
 237}
 238
 239static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
 240		qeth_l3_dev_sniffer_store);
 241
 242
 243static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
 244		struct device_attribute *attr, char *buf)
 245{
 246	struct qeth_card *card = dev_get_drvdata(dev);
 247	char tmp_hsuid[9];
 248
 249	if (!card)
 250		return -EINVAL;
 251
 252	if (card->info.type != QETH_CARD_TYPE_IQD)
 253		return -EPERM;
 254
 255	if (card->state == CARD_STATE_DOWN)
 256		return -EPERM;
 257
 258	memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
 259	EBCASC(tmp_hsuid, 8);
 260	return sprintf(buf, "%s\n", tmp_hsuid);
 261}
 262
 263static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
 264		struct device_attribute *attr, const char *buf, size_t count)
 265{
 266	struct qeth_card *card = dev_get_drvdata(dev);
 267	struct qeth_ipaddr *addr;
 268	char *tmp;
 269	int i;
 270
 271	if (!card)
 272		return -EINVAL;
 273
 274	if (card->info.type != QETH_CARD_TYPE_IQD)
 275		return -EPERM;
 276	if (card->state != CARD_STATE_DOWN &&
 277	    card->state != CARD_STATE_RECOVER)
 278		return -EPERM;
 279	if (card->options.sniffer)
 280		return -EPERM;
 281	if (card->options.cq == QETH_CQ_NOTAVAILABLE)
 282		return -EPERM;
 283
 284	tmp = strsep((char **)&buf, "\n");
 285	if (strlen(tmp) > 8)
 286		return -EINVAL;
 287
 288	if (card->options.hsuid[0]) {
 289		/* delete old ip address */
 290		addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
 291		if (addr != NULL) {
 292			addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
 293			addr->u.a6.addr.s6_addr32[1] = 0x00000000;
 294			for (i = 8; i < 16; i++)
 295				addr->u.a6.addr.s6_addr[i] =
 296					card->options.hsuid[i - 8];
 297			addr->u.a6.pfxlen = 0;
 298			addr->type = QETH_IP_TYPE_NORMAL;
 299		} else
 300			return -ENOMEM;
 301		if (!qeth_l3_delete_ip(card, addr))
 302			kfree(addr);
 303		qeth_l3_set_ip_addr_list(card);
 304	}
 305
 306	if (strlen(tmp) == 0) {
 307		/* delete ip address only */
 308		card->options.hsuid[0] = '\0';
 309		if (card->dev)
 310			memcpy(card->dev->perm_addr, card->options.hsuid, 9);
 311		qeth_configure_cq(card, QETH_CQ_DISABLED);
 312		return count;
 313	}
 314
 315	if (qeth_configure_cq(card, QETH_CQ_ENABLED))
 316		return -EPERM;
 317
 318	for (i = 0; i < 8; i++)
 319		card->options.hsuid[i] = ' ';
 320	card->options.hsuid[8] = '\0';
 321	strncpy(card->options.hsuid, tmp, strlen(tmp));
 322	ASCEBC(card->options.hsuid, 8);
 323	if (card->dev)
 324		memcpy(card->dev->perm_addr, card->options.hsuid, 9);
 325
 326	addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
 327	if (addr != NULL) {
 328		addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
 329		addr->u.a6.addr.s6_addr32[1] = 0x00000000;
 330		for (i = 8; i < 16; i++)
 331			addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
 332		addr->u.a6.pfxlen = 0;
 333		addr->type = QETH_IP_TYPE_NORMAL;
 334	} else
 335		return -ENOMEM;
 336	if (!qeth_l3_add_ip(card, addr))
 337		kfree(addr);
 338	qeth_l3_set_ip_addr_list(card);
 339
 340	return count;
 341}
 342
 343static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
 344		   qeth_l3_dev_hsuid_store);
 345
 346
 347static struct attribute *qeth_l3_device_attrs[] = {
 348	&dev_attr_route4.attr,
 349	&dev_attr_route6.attr,
 350	&dev_attr_fake_broadcast.attr,
 351	&dev_attr_sniffer.attr,
 352	&dev_attr_hsuid.attr,
 353	NULL,
 354};
 355
 356static struct attribute_group qeth_l3_device_attr_group = {
 357	.attrs = qeth_l3_device_attrs,
 358};
 359
 360static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
 361			struct device_attribute *attr, char *buf)
 362{
 363	struct qeth_card *card = dev_get_drvdata(dev);
 364
 365	if (!card)
 366		return -EINVAL;
 367
 368	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
 369}
 370
 371static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
 372		struct device_attribute *attr, const char *buf, size_t count)
 373{
 374	struct qeth_card *card = dev_get_drvdata(dev);
 375	struct qeth_ipaddr *tmpipa, *t;
 376	char *tmp;
 377	int rc = 0;
 378
 379	if (!card)
 380		return -EINVAL;
 381
 382	mutex_lock(&card->conf_mutex);
 383	if ((card->state != CARD_STATE_DOWN) &&
 384	    (card->state != CARD_STATE_RECOVER)) {
 385		rc = -EPERM;
 386		goto out;
 387	}
 388
 389	tmp = strsep((char **) &buf, "\n");
 390	if (!strcmp(tmp, "toggle")) {
 391		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
 392	} else if (!strcmp(tmp, "1")) {
 393		card->ipato.enabled = 1;
 394		list_for_each_entry_safe(tmpipa, t, card->ip_tbd_list, entry) {
 395			if ((tmpipa->type == QETH_IP_TYPE_NORMAL) &&
 396				qeth_l3_is_addr_covered_by_ipato(card, tmpipa))
 397				tmpipa->set_flags |=
 398					QETH_IPA_SETIP_TAKEOVER_FLAG;
 399		}
 400
 401	} else if (!strcmp(tmp, "0")) {
 402		card->ipato.enabled = 0;
 403		list_for_each_entry_safe(tmpipa, t, card->ip_tbd_list, entry) {
 404			if (tmpipa->set_flags &
 405				QETH_IPA_SETIP_TAKEOVER_FLAG)
 406				tmpipa->set_flags &=
 407					~QETH_IPA_SETIP_TAKEOVER_FLAG;
 408		}
 409	} else
 410		rc = -EINVAL;
 411out:
 412	mutex_unlock(&card->conf_mutex);
 413	return rc ? rc : count;
 414}
 415
 416static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
 417			qeth_l3_dev_ipato_enable_show,
 418			qeth_l3_dev_ipato_enable_store);
 419
 420static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
 421				struct device_attribute *attr, char *buf)
 422{
 423	struct qeth_card *card = dev_get_drvdata(dev);
 424
 425	if (!card)
 426		return -EINVAL;
 427
 428	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
 429}
 430
 431static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
 432				struct device_attribute *attr,
 433				const char *buf, size_t count)
 434{
 435	struct qeth_card *card = dev_get_drvdata(dev);
 436	char *tmp;
 437	int rc = 0;
 438
 439	if (!card)
 440		return -EINVAL;
 441
 442	mutex_lock(&card->conf_mutex);
 443	tmp = strsep((char **) &buf, "\n");
 444	if (!strcmp(tmp, "toggle")) {
 445		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
 446	} else if (!strcmp(tmp, "1")) {
 447		card->ipato.invert4 = 1;
 448	} else if (!strcmp(tmp, "0")) {
 449		card->ipato.invert4 = 0;
 450	} else
 451		rc = -EINVAL;
 452	mutex_unlock(&card->conf_mutex);
 453	return rc ? rc : count;
 454}
 455
 456static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
 457			qeth_l3_dev_ipato_invert4_show,
 458			qeth_l3_dev_ipato_invert4_store);
 459
 460static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
 461			enum qeth_prot_versions proto)
 462{
 463	struct qeth_ipato_entry *ipatoe;
 464	unsigned long flags;
 465	char addr_str[40];
 466	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
 467	int i = 0;
 468
 469	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
 470	/* add strlen for "/<mask>\n" */
 471	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
 472	spin_lock_irqsave(&card->ip_lock, flags);
 473	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
 474		if (ipatoe->proto != proto)
 475			continue;
 476		/* String must not be longer than PAGE_SIZE. So we check if
 477		 * string length gets near PAGE_SIZE. Then we can savely display
 478		 * the next IPv6 address (worst case, compared to IPv4) */
 479		if ((PAGE_SIZE - i) <= entry_len)
 480			break;
 481		qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
 482		i += snprintf(buf + i, PAGE_SIZE - i,
 483			      "%s/%i\n", addr_str, ipatoe->mask_bits);
 484	}
 485	spin_unlock_irqrestore(&card->ip_lock, flags);
 486	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
 487
 488	return i;
 489}
 490
 491static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
 492				struct device_attribute *attr, char *buf)
 493{
 494	struct qeth_card *card = dev_get_drvdata(dev);
 495
 496	if (!card)
 497		return -EINVAL;
 498
 499	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
 500}
 501
 502static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
 503		  u8 *addr, int *mask_bits)
 504{
 505	const char *start, *end;
 506	char *tmp;
 507	char buffer[40] = {0, };
 508
 509	start = buf;
 510	/* get address string */
 511	end = strchr(start, '/');
 512	if (!end || (end - start >= 40)) {
 513		return -EINVAL;
 514	}
 515	strncpy(buffer, start, end - start);
 516	if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
 517		return -EINVAL;
 518	}
 519	start = end + 1;
 520	*mask_bits = simple_strtoul(start, &tmp, 10);
 521	if (!strlen(start) ||
 522	    (tmp == start) ||
 523	    (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
 524		return -EINVAL;
 525	}
 526	return 0;
 527}
 528
 529static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
 530			 struct qeth_card *card, enum qeth_prot_versions proto)
 531{
 532	struct qeth_ipato_entry *ipatoe;
 533	u8 addr[16];
 534	int mask_bits;
 535	int rc = 0;
 536
 537	mutex_lock(&card->conf_mutex);
 538	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
 539	if (rc)
 540		goto out;
 541
 542	ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
 543	if (!ipatoe) {
 544		rc = -ENOMEM;
 545		goto out;
 546	}
 547	ipatoe->proto = proto;
 548	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
 549	ipatoe->mask_bits = mask_bits;
 550
 551	rc = qeth_l3_add_ipato_entry(card, ipatoe);
 552	if (rc)
 553		kfree(ipatoe);
 554out:
 555	mutex_unlock(&card->conf_mutex);
 556	return rc ? rc : count;
 557}
 558
 559static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
 560		struct device_attribute *attr, const char *buf, size_t count)
 561{
 562	struct qeth_card *card = dev_get_drvdata(dev);
 563
 564	if (!card)
 565		return -EINVAL;
 566
 567	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
 568}
 569
 570static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
 571			qeth_l3_dev_ipato_add4_show,
 572			qeth_l3_dev_ipato_add4_store);
 573
 574static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
 575			 struct qeth_card *card, enum qeth_prot_versions proto)
 576{
 577	u8 addr[16];
 578	int mask_bits;
 579	int rc = 0;
 580
 581	mutex_lock(&card->conf_mutex);
 582	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
 583	if (!rc)
 584		qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
 585	mutex_unlock(&card->conf_mutex);
 586	return rc ? rc : count;
 587}
 588
 589static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
 590		struct device_attribute *attr, const char *buf, size_t count)
 591{
 592	struct qeth_card *card = dev_get_drvdata(dev);
 593
 594	if (!card)
 595		return -EINVAL;
 596
 597	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
 598}
 599
 600static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
 601			qeth_l3_dev_ipato_del4_store);
 602
 603static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
 604		struct device_attribute *attr, char *buf)
 605{
 606	struct qeth_card *card = dev_get_drvdata(dev);
 607
 608	if (!card)
 609		return -EINVAL;
 610
 611	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
 612}
 613
 614static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
 615		struct device_attribute *attr, const char *buf, size_t count)
 616{
 617	struct qeth_card *card = dev_get_drvdata(dev);
 618	char *tmp;
 619	int rc = 0;
 620
 621	if (!card)
 622		return -EINVAL;
 623
 624	mutex_lock(&card->conf_mutex);
 625	tmp = strsep((char **) &buf, "\n");
 626	if (!strcmp(tmp, "toggle")) {
 627		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
 628	} else if (!strcmp(tmp, "1")) {
 629		card->ipato.invert6 = 1;
 630	} else if (!strcmp(tmp, "0")) {
 631		card->ipato.invert6 = 0;
 632	} else
 633		rc = -EINVAL;
 634	mutex_unlock(&card->conf_mutex);
 635	return rc ? rc : count;
 636}
 637
 638static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
 639			qeth_l3_dev_ipato_invert6_show,
 640			qeth_l3_dev_ipato_invert6_store);
 641
 642
 643static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
 644				struct device_attribute *attr, char *buf)
 645{
 646	struct qeth_card *card = dev_get_drvdata(dev);
 647
 648	if (!card)
 649		return -EINVAL;
 650
 651	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
 652}
 653
 654static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
 655		struct device_attribute *attr, const char *buf, size_t count)
 656{
 657	struct qeth_card *card = dev_get_drvdata(dev);
 658
 659	if (!card)
 660		return -EINVAL;
 661
 662	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
 663}
 664
 665static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
 666			qeth_l3_dev_ipato_add6_show,
 667			qeth_l3_dev_ipato_add6_store);
 668
 669static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
 670		struct device_attribute *attr, const char *buf, size_t count)
 671{
 672	struct qeth_card *card = dev_get_drvdata(dev);
 673
 674	if (!card)
 675		return -EINVAL;
 676
 677	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
 678}
 679
 680static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
 681			qeth_l3_dev_ipato_del6_store);
 682
 683static struct attribute *qeth_ipato_device_attrs[] = {
 684	&dev_attr_ipato_enable.attr,
 685	&dev_attr_ipato_invert4.attr,
 686	&dev_attr_ipato_add4.attr,
 687	&dev_attr_ipato_del4.attr,
 688	&dev_attr_ipato_invert6.attr,
 689	&dev_attr_ipato_add6.attr,
 690	&dev_attr_ipato_del6.attr,
 691	NULL,
 692};
 693
 694static struct attribute_group qeth_device_ipato_group = {
 695	.name = "ipa_takeover",
 696	.attrs = qeth_ipato_device_attrs,
 697};
 698
 699static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
 700			enum qeth_prot_versions proto)
 701{
 702	struct qeth_ipaddr *ipaddr;
 703	char addr_str[40];
 704	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
 705	unsigned long flags;
 706	int i = 0;
 707
 708	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
 709	entry_len += 2; /* \n + terminator */
 710	spin_lock_irqsave(&card->ip_lock, flags);
 711	list_for_each_entry(ipaddr, &card->ip_list, entry) {
 712		if (ipaddr->proto != proto)
 713			continue;
 714		if (ipaddr->type != QETH_IP_TYPE_VIPA)
 715			continue;
 716		/* String must not be longer than PAGE_SIZE. So we check if
 717		 * string length gets near PAGE_SIZE. Then we can savely display
 718		 * the next IPv6 address (worst case, compared to IPv4) */
 719		if ((PAGE_SIZE - i) <= entry_len)
 720			break;
 721		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
 722			addr_str);
 723		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
 724	}
 725	spin_unlock_irqrestore(&card->ip_lock, flags);
 726	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
 727
 728	return i;
 729}
 730
 731static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
 732			struct device_attribute *attr, char *buf)
 733{
 734	struct qeth_card *card = dev_get_drvdata(dev);
 735
 736	if (!card)
 737		return -EINVAL;
 738
 739	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
 740}
 741
 742static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
 743		 u8 *addr)
 744{
 745	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
 746		return -EINVAL;
 747	}
 748	return 0;
 749}
 750
 751static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
 752			struct qeth_card *card, enum qeth_prot_versions proto)
 753{
 754	u8 addr[16] = {0, };
 755	int rc;
 756
 757	mutex_lock(&card->conf_mutex);
 758	rc = qeth_l3_parse_vipae(buf, proto, addr);
 759	if (!rc)
 760		rc = qeth_l3_add_vipa(card, proto, addr);
 761	mutex_unlock(&card->conf_mutex);
 762	return rc ? rc : count;
 763}
 764
 765static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
 766		struct device_attribute *attr, const char *buf, size_t count)
 767{
 768	struct qeth_card *card = dev_get_drvdata(dev);
 769
 770	if (!card)
 771		return -EINVAL;
 772
 773	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
 774}
 775
 776static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
 777			qeth_l3_dev_vipa_add4_show,
 778			qeth_l3_dev_vipa_add4_store);
 779
 780static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
 781			 struct qeth_card *card, enum qeth_prot_versions proto)
 782{
 783	u8 addr[16];
 784	int rc;
 785
 786	mutex_lock(&card->conf_mutex);
 787	rc = qeth_l3_parse_vipae(buf, proto, addr);
 788	if (!rc)
 789		qeth_l3_del_vipa(card, proto, addr);
 790	mutex_unlock(&card->conf_mutex);
 791	return rc ? rc : count;
 792}
 793
 794static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
 795		struct device_attribute *attr, const char *buf, size_t count)
 796{
 797	struct qeth_card *card = dev_get_drvdata(dev);
 798
 799	if (!card)
 800		return -EINVAL;
 801
 802	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
 803}
 804
 805static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
 806			qeth_l3_dev_vipa_del4_store);
 807
 808static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
 809				struct device_attribute *attr, char *buf)
 810{
 811	struct qeth_card *card = dev_get_drvdata(dev);
 812
 813	if (!card)
 814		return -EINVAL;
 815
 816	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
 817}
 818
 819static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
 820		struct device_attribute *attr, const char *buf, size_t count)
 821{
 822	struct qeth_card *card = dev_get_drvdata(dev);
 823
 824	if (!card)
 825		return -EINVAL;
 826
 827	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
 828}
 829
 830static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
 831			qeth_l3_dev_vipa_add6_show,
 832			qeth_l3_dev_vipa_add6_store);
 833
 834static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
 835		struct device_attribute *attr, const char *buf, size_t count)
 836{
 837	struct qeth_card *card = dev_get_drvdata(dev);
 838
 839	if (!card)
 840		return -EINVAL;
 841
 842	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
 843}
 844
 845static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
 846			qeth_l3_dev_vipa_del6_store);
 847
 848static struct attribute *qeth_vipa_device_attrs[] = {
 849	&dev_attr_vipa_add4.attr,
 850	&dev_attr_vipa_del4.attr,
 851	&dev_attr_vipa_add6.attr,
 852	&dev_attr_vipa_del6.attr,
 853	NULL,
 854};
 855
 856static struct attribute_group qeth_device_vipa_group = {
 857	.name = "vipa",
 858	.attrs = qeth_vipa_device_attrs,
 859};
 860
 861static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
 862		       enum qeth_prot_versions proto)
 863{
 864	struct qeth_ipaddr *ipaddr;
 865	char addr_str[40];
 866	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
 867	unsigned long flags;
 868	int i = 0;
 869
 870	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
 871	entry_len += 2; /* \n + terminator */
 872	spin_lock_irqsave(&card->ip_lock, flags);
 873	list_for_each_entry(ipaddr, &card->ip_list, entry) {
 874		if (ipaddr->proto != proto)
 875			continue;
 876		if (ipaddr->type != QETH_IP_TYPE_RXIP)
 877			continue;
 878		/* String must not be longer than PAGE_SIZE. So we check if
 879		 * string length gets near PAGE_SIZE. Then we can savely display
 880		 * the next IPv6 address (worst case, compared to IPv4) */
 881		if ((PAGE_SIZE - i) <= entry_len)
 882			break;
 883		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
 884			addr_str);
 885		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
 886	}
 887	spin_unlock_irqrestore(&card->ip_lock, flags);
 888	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
 889
 890	return i;
 891}
 892
 893static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
 894			struct device_attribute *attr, char *buf)
 895{
 896	struct qeth_card *card = dev_get_drvdata(dev);
 897
 898	if (!card)
 899		return -EINVAL;
 900
 901	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
 902}
 903
 904static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
 905		 u8 *addr)
 906{
 907	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
 908		return -EINVAL;
 909	}
 910	return 0;
 911}
 912
 913static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
 914			struct qeth_card *card, enum qeth_prot_versions proto)
 915{
 916	u8 addr[16] = {0, };
 917	int rc;
 918
 919	mutex_lock(&card->conf_mutex);
 920	rc = qeth_l3_parse_rxipe(buf, proto, addr);
 921	if (!rc)
 922		rc = qeth_l3_add_rxip(card, proto, addr);
 923	mutex_unlock(&card->conf_mutex);
 924	return rc ? rc : count;
 925}
 926
 927static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
 928		struct device_attribute *attr, const char *buf, size_t count)
 929{
 930	struct qeth_card *card = dev_get_drvdata(dev);
 931
 932	if (!card)
 933		return -EINVAL;
 934
 935	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
 936}
 937
 938static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
 939			qeth_l3_dev_rxip_add4_show,
 940			qeth_l3_dev_rxip_add4_store);
 941
 942static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
 943			struct qeth_card *card, enum qeth_prot_versions proto)
 944{
 945	u8 addr[16];
 946	int rc;
 947
 948	mutex_lock(&card->conf_mutex);
 949	rc = qeth_l3_parse_rxipe(buf, proto, addr);
 950	if (!rc)
 951		qeth_l3_del_rxip(card, proto, addr);
 952	mutex_unlock(&card->conf_mutex);
 953	return rc ? rc : count;
 954}
 955
 956static ssize_t qeth_l3_dev_rxip_del4_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_IPV4);
 965}
 966
 967static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
 968			qeth_l3_dev_rxip_del4_store);
 969
 970static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
 971		struct device_attribute *attr, char *buf)
 972{
 973	struct qeth_card *card = dev_get_drvdata(dev);
 974
 975	if (!card)
 976		return -EINVAL;
 977
 978	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
 979}
 980
 981static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
 982		struct device_attribute *attr, const char *buf, size_t count)
 983{
 984	struct qeth_card *card = dev_get_drvdata(dev);
 985
 986	if (!card)
 987		return -EINVAL;
 988
 989	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
 990}
 991
 992static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
 993			qeth_l3_dev_rxip_add6_show,
 994			qeth_l3_dev_rxip_add6_store);
 995
 996static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
 997		struct device_attribute *attr, const char *buf, size_t count)
 998{
 999	struct qeth_card *card = dev_get_drvdata(dev);
1000
1001	if (!card)
1002		return -EINVAL;
1003
1004	return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
1005}
1006
1007static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
1008			qeth_l3_dev_rxip_del6_store);
1009
1010static struct attribute *qeth_rxip_device_attrs[] = {
1011	&dev_attr_rxip_add4.attr,
1012	&dev_attr_rxip_del4.attr,
1013	&dev_attr_rxip_add6.attr,
1014	&dev_attr_rxip_del6.attr,
1015	NULL,
1016};
1017
1018static struct attribute_group qeth_device_rxip_group = {
1019	.name = "rxip",
1020	.attrs = qeth_rxip_device_attrs,
1021};
1022
1023int qeth_l3_create_device_attributes(struct device *dev)
1024{
1025	int ret;
1026
1027	ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
1028	if (ret)
1029		return ret;
1030
1031	ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
1032	if (ret) {
1033		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1034		return ret;
1035	}
1036
1037	ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
1038	if (ret) {
1039		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1040		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1041		return ret;
1042	}
1043
1044	ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
1045	if (ret) {
1046		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1047		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1048		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1049		return ret;
1050	}
1051	return 0;
1052}
1053
1054void qeth_l3_remove_device_attributes(struct device *dev)
1055{
1056	sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1057	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1058	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1059	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
1060}