qeth_l3_main.c 77.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
F
Frank Blaschka 已提交
2
/*
3
 *    Copyright IBM Corp. 2007, 2009
F
Frank Blaschka 已提交
4 5 6 7 8 9
 *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
 *		 Frank Pavlic <fpavlic@de.ibm.com>,
 *		 Thomas Spatzier <tspat@de.ibm.com>,
 *		 Frank Blaschka <frank.blaschka@de.ibm.com>
 */

10 11 12
#define KMSG_COMPONENT "qeth"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

F
Frank Blaschka 已提交
13 14
#include <linux/module.h>
#include <linux/moduleparam.h>
J
Jiri Pirko 已提交
15
#include <linux/bitops.h>
F
Frank Blaschka 已提交
16 17 18 19 20
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
21
#include <linux/in.h>
F
Frank Blaschka 已提交
22
#include <linux/ipv6.h>
F
Frank Blaschka 已提交
23 24
#include <linux/inetdevice.h>
#include <linux/igmp.h>
25
#include <linux/slab.h>
26
#include <linux/if_ether.h>
J
Jiri Pirko 已提交
27
#include <linux/if_vlan.h>
28
#include <linux/skbuff.h>
F
Frank Blaschka 已提交
29 30 31

#include <net/ip.h>
#include <net/arp.h>
32
#include <net/route.h>
33
#include <net/ipv6.h>
34
#include <net/ip6_route.h>
35
#include <net/ip6_fib.h>
F
Frank Blaschka 已提交
36
#include <net/ip6_checksum.h>
37
#include <net/iucv/af_iucv.h>
38
#include <linux/hashtable.h>
F
Frank Blaschka 已提交
39 40 41

#include "qeth_l3.h"

42

F
Frank Blaschka 已提交
43 44
static int qeth_l3_set_offline(struct ccwgroup_device *);
static int qeth_l3_stop(struct net_device *);
45
static void qeth_l3_set_rx_mode(struct net_device *dev);
F
Frank Blaschka 已提交
46 47 48 49 50
static int qeth_l3_register_addr_entry(struct qeth_card *,
		struct qeth_ipaddr *);
static int qeth_l3_deregister_addr_entry(struct qeth_card *,
		struct qeth_ipaddr *);

51
static void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf)
F
Frank Blaschka 已提交
52
{
53
	sprintf(buf, "%pI4", addr);
F
Frank Blaschka 已提交
54 55
}

56
static void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
F
Frank Blaschka 已提交
57
{
J
Joe Perches 已提交
58
	sprintf(buf, "%pI6", addr);
F
Frank Blaschka 已提交
59 60 61 62 63 64 65 66 67 68 69
}

void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
				char *buf)
{
	if (proto == QETH_PROT_IPV4)
		qeth_l3_ipaddr4_to_string(addr, buf);
	else if (proto == QETH_PROT_IPV6)
		qeth_l3_ipaddr6_to_string(addr, buf);
}

70
static struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions prot)
71 72 73 74 75 76 77 78
{
	struct qeth_ipaddr *addr = kmalloc(sizeof(*addr), GFP_ATOMIC);

	if (addr)
		qeth_l3_init_ipaddr(addr, QETH_IP_TYPE_NORMAL, prot);
	return addr;
}

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card,
						   struct qeth_ipaddr *query)
{
	u64 key = qeth_l3_ipaddr_hash(query);
	struct qeth_ipaddr *addr;

	if (query->is_multicast) {
		hash_for_each_possible(card->ip_mc_htable, addr, hnode, key)
			if (qeth_l3_addr_match_ip(addr, query))
				return addr;
	} else {
		hash_for_each_possible(card->ip_htable,  addr, hnode, key)
			if (qeth_l3_addr_match_ip(addr, query))
				return addr;
	}
	return NULL;
}

F
Frank Blaschka 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110
static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
{
	int i, j;
	u8 octet;

	for (i = 0; i < len; ++i) {
		octet = addr[i];
		for (j = 7; j >= 0; --j) {
			bits[i*8 + j] = octet & 1;
			octet >>= 1;
		}
	}
}

111 112
static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
					     struct qeth_ipaddr *addr)
F
Frank Blaschka 已提交
113 114 115 116 117 118 119 120
{
	struct qeth_ipato_entry *ipatoe;
	u8 addr_bits[128] = {0, };
	u8 ipatoe_bits[128] = {0, };
	int rc = 0;

	if (!card->ipato.enabled)
		return 0;
121 122
	if (addr->type != QETH_IP_TYPE_NORMAL)
		return 0;
F
Frank Blaschka 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

	qeth_l3_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
				  (addr->proto == QETH_PROT_IPV4)? 4:16);
	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
		if (addr->proto != ipatoe->proto)
			continue;
		qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
					  (ipatoe->proto == QETH_PROT_IPV4) ?
					  4 : 16);
		if (addr->proto == QETH_PROT_IPV4)
			rc = !memcmp(addr_bits, ipatoe_bits,
				     min(32, ipatoe->mask_bits));
		else
			rc = !memcmp(addr_bits, ipatoe_bits,
				     min(128, ipatoe->mask_bits));
		if (rc)
			break;
	}
	/* invert? */
	if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
		rc = !rc;
	else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
		rc = !rc;

	return rc;
}

150 151
static int qeth_l3_delete_ip(struct qeth_card *card,
			     struct qeth_ipaddr *tmp_addr)
F
Frank Blaschka 已提交
152 153
{
	int rc = 0;
154
	struct qeth_ipaddr *addr;
F
Frank Blaschka 已提交
155

156 157 158 159 160 161
	if (tmp_addr->type == QETH_IP_TYPE_RXIP)
		QETH_CARD_TEXT(card, 2, "delrxip");
	else if (tmp_addr->type == QETH_IP_TYPE_VIPA)
		QETH_CARD_TEXT(card, 2, "delvipa");
	else
		QETH_CARD_TEXT(card, 2, "delip");
F
Frank Blaschka 已提交
162

163 164
	if (tmp_addr->proto == QETH_PROT_IPV4)
		QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4);
F
Frank Blaschka 已提交
165
	else {
166 167
		QETH_CARD_HEX(card, 4, &tmp_addr->u.a6.addr, 8);
		QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8);
F
Frank Blaschka 已提交
168
	}
169

170 171
	addr = qeth_l3_find_addr_by_ip(card, tmp_addr);
	if (!addr || !qeth_l3_addr_match_all(addr, tmp_addr))
172 173 174
		return -ENOENT;

	addr->ref_counter--;
175
	if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0)
176 177 178 179
		return rc;
	if (addr->in_progress)
		return -EINPROGRESS;

180 181
	if (qeth_card_hw_is_reachable(card))
		rc = qeth_l3_deregister_addr_entry(card, addr);
182 183 184 185

	hash_del(&addr->hnode);
	kfree(addr);

F
Frank Blaschka 已提交
186 187 188
	return rc;
}

189
static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
F
Frank Blaschka 已提交
190 191
{
	int rc = 0;
192
	struct qeth_ipaddr *addr;
193
	char buf[40];
F
Frank Blaschka 已提交
194

195 196 197 198 199 200
	if (tmp_addr->type == QETH_IP_TYPE_RXIP)
		QETH_CARD_TEXT(card, 2, "addrxip");
	else if (tmp_addr->type == QETH_IP_TYPE_VIPA)
		QETH_CARD_TEXT(card, 2, "addvipa");
	else
		QETH_CARD_TEXT(card, 2, "addip");
201 202 203

	if (tmp_addr->proto == QETH_PROT_IPV4)
		QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4);
F
Frank Blaschka 已提交
204
	else {
205 206 207 208
		QETH_CARD_HEX(card, 4, &tmp_addr->u.a6.addr, 8);
		QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8);
	}

209 210 211 212 213 214 215 216 217 218 219 220 221 222
	addr = qeth_l3_find_addr_by_ip(card, tmp_addr);
	if (addr) {
		if (tmp_addr->type != QETH_IP_TYPE_NORMAL)
			return -EADDRINUSE;
		if (qeth_l3_addr_match_all(addr, tmp_addr)) {
			addr->ref_counter++;
			return 0;
		}
		qeth_l3_ipaddr_to_string(tmp_addr->proto, (u8 *)&tmp_addr->u,
					 buf);
		dev_warn(&card->gdev->dev,
			 "Registering IP address %s failed\n", buf);
		return -EADDRINUSE;
	} else {
223 224 225 226 227 228 229
		addr = qeth_l3_get_addr_buffer(tmp_addr->proto);
		if (!addr)
			return -ENOMEM;

		memcpy(addr, tmp_addr, sizeof(struct qeth_ipaddr));
		addr->ref_counter = 1;

230
		if (qeth_l3_is_addr_covered_by_ipato(card, addr)) {
231
			QETH_CARD_TEXT(card, 2, "tkovaddr");
232
			addr->ipato = 1;
233 234 235 236
		}
		hash_add(card->ip_htable, &addr->hnode,
				qeth_l3_ipaddr_hash(addr));

237 238 239 240 241
		if (!qeth_card_hw_is_reachable(card)) {
			addr->disp_flag = QETH_DISP_ADDR_ADD;
			return 0;
		}

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
		/* qeth_l3_register_addr_entry can go to sleep
		 * if we add a IPV4 addr. It is caused by the reason
		 * that SETIP ipa cmd starts ARP staff for IPV4 addr.
		 * Thus we should unlock spinlock, and make a protection
		 * using in_progress variable to indicate that there is
		 * an hardware operation with this IPV4 address
		 */
		if (addr->proto == QETH_PROT_IPV4) {
			addr->in_progress = 1;
			spin_unlock_bh(&card->ip_lock);
			rc = qeth_l3_register_addr_entry(card, addr);
			spin_lock_bh(&card->ip_lock);
			addr->in_progress = 0;
		} else
			rc = qeth_l3_register_addr_entry(card, addr);

		if (!rc || (rc == IPA_RC_DUPLICATE_IP_ADDRESS) ||
				(rc == IPA_RC_LAN_OFFLINE)) {
			addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
			if (addr->ref_counter < 1) {
262 263
				qeth_l3_deregister_addr_entry(card, addr);
				hash_del(&addr->hnode);
264 265 266 267 268 269
				kfree(addr);
			}
		} else {
			hash_del(&addr->hnode);
			kfree(addr);
		}
F
Frank Blaschka 已提交
270 271 272 273
	}
	return rc;
}

274
static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
F
Frank Blaschka 已提交
275 276
{
	struct qeth_ipaddr *addr;
277 278
	struct hlist_node *tmp;
	int i;
F
Frank Blaschka 已提交
279

280
	QETH_CARD_TEXT(card, 4, "clearip");
F
Frank Blaschka 已提交
281

282
	if (recover && card->options.sniffer)
283
		return;
284

285 286 287 288 289 290
	spin_lock_bh(&card->ip_lock);

	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
		if (!recover) {
			hash_del(&addr->hnode);
			kfree(addr);
F
Frank Blaschka 已提交
291 292
			continue;
		}
293
		addr->disp_flag = QETH_DISP_ADDR_ADD;
F
Frank Blaschka 已提交
294 295
	}

296
	spin_unlock_bh(&card->ip_lock);
F
Frank Blaschka 已提交
297

298 299 300 301
	spin_lock_bh(&card->mclock);

	hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) {
		hash_del(&addr->hnode);
F
Frank Blaschka 已提交
302 303 304
		kfree(addr);
	}

305 306
	spin_unlock_bh(&card->mclock);

F
Frank Blaschka 已提交
307

308 309
}
static void qeth_l3_recover_ip(struct qeth_card *card)
F
Frank Blaschka 已提交
310
{
311 312 313 314
	struct qeth_ipaddr *addr;
	struct hlist_node *tmp;
	int i;
	int rc;
F
Frank Blaschka 已提交
315

316
	QETH_CARD_TEXT(card, 4, "recovrip");
317 318 319 320

	spin_lock_bh(&card->ip_lock);

	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
321
		if (addr->disp_flag == QETH_DISP_ADDR_ADD) {
322 323 324 325 326 327 328 329 330 331 332
			if (addr->proto == QETH_PROT_IPV4) {
				addr->in_progress = 1;
				spin_unlock_bh(&card->ip_lock);
				rc = qeth_l3_register_addr_entry(card, addr);
				spin_lock_bh(&card->ip_lock);
				addr->in_progress = 0;
			} else
				rc = qeth_l3_register_addr_entry(card, addr);

			if (!rc) {
				addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
333
				if (addr->ref_counter < 1)
334 335 336 337 338 339 340
					qeth_l3_delete_ip(card, addr);
			} else {
				hash_del(&addr->hnode);
				kfree(addr);
			}
		}
	}
F
Frank Blaschka 已提交
341

342
	spin_unlock_bh(&card->ip_lock);
F
Frank Blaschka 已提交
343 344 345 346 347 348 349 350 351 352

}

static int qeth_l3_send_setdelmc(struct qeth_card *card,
			struct qeth_ipaddr *addr, int ipacmd)
{
	int rc;
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;

C
Carsten Otte 已提交
353
	QETH_CARD_TEXT(card, 4, "setdelmc");
F
Frank Blaschka 已提交
354 355

	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
356 357
	if (!iob)
		return -ENOMEM;
358
	cmd = __ipa_cmd(iob);
359
	ether_addr_copy(cmd->data.setdelipm.mac, addr->mac);
F
Frank Blaschka 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	if (addr->proto == QETH_PROT_IPV6)
		memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
		       sizeof(struct in6_addr));
	else
		memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);

	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);

	return rc;
}

static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
{
	int i, j;
	for (i = 0; i < 16; i++) {
		j = (len) - (i * 8);
		if (j >= 8)
			netmask[i] = 0xff;
		else if (j > 0)
			netmask[i] = (u8)(0xFF00 >> j);
		else
			netmask[i] = 0;
	}
}

385 386 387 388 389 390 391 392 393 394 395 396 397
static u32 qeth_l3_get_setdelip_flags(struct qeth_ipaddr *addr, bool set)
{
	switch (addr->type) {
	case QETH_IP_TYPE_RXIP:
		return (set) ? QETH_IPA_SETIP_TAKEOVER_FLAG : 0;
	case QETH_IP_TYPE_VIPA:
		return (set) ? QETH_IPA_SETIP_VIPA_FLAG :
			       QETH_IPA_DELIP_VIPA_FLAG;
	default:
		return (set && addr->ipato) ? QETH_IPA_SETIP_TAKEOVER_FLAG : 0;
	}
}

F
Frank Blaschka 已提交
398
static int qeth_l3_send_setdelip(struct qeth_card *card,
399 400
				 struct qeth_ipaddr *addr,
				 enum qeth_ipa_cmds ipacmd)
F
Frank Blaschka 已提交
401 402 403 404
{
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;
	__u8 netmask[16];
405
	u32 flags;
F
Frank Blaschka 已提交
406

C
Carsten Otte 已提交
407
	QETH_CARD_TEXT(card, 4, "setdelip");
F
Frank Blaschka 已提交
408 409

	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
410 411
	if (!iob)
		return -ENOMEM;
412
	cmd = __ipa_cmd(iob);
413 414 415 416

	flags = qeth_l3_get_setdelip_flags(addr, ipacmd == IPA_CMD_SETIP);
	QETH_CARD_TEXT_(card, 4, "flags%02X", flags);

F
Frank Blaschka 已提交
417 418 419 420 421 422 423 424 425 426 427 428 429
	if (addr->proto == QETH_PROT_IPV6) {
		memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
		       sizeof(struct in6_addr));
		qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen);
		memcpy(cmd->data.setdelip6.mask, netmask,
		       sizeof(struct in6_addr));
		cmd->data.setdelip6.flags = flags;
	} else {
		memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
		memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
		cmd->data.setdelip4.flags = flags;
	}

430
	return qeth_send_ipa_cmd(card, iob, NULL, NULL);
F
Frank Blaschka 已提交
431 432 433 434 435 436 437 438 439
}

static int qeth_l3_send_setrouting(struct qeth_card *card,
	enum qeth_routing_types type, enum qeth_prot_versions prot)
{
	int rc;
	struct qeth_ipa_cmd *cmd;
	struct qeth_cmd_buffer *iob;

C
Carsten Otte 已提交
440
	QETH_CARD_TEXT(card, 4, "setroutg");
F
Frank Blaschka 已提交
441
	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
442 443
	if (!iob)
		return -ENOMEM;
444
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
445 446 447 448 449 450
	cmd->data.setrtg.type = (type);
	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);

	return rc;
}

451
static int qeth_l3_correct_routing_type(struct qeth_card *card,
F
Frank Blaschka 已提交
452 453 454 455 456 457 458 459
		enum qeth_routing_types *type, enum qeth_prot_versions prot)
{
	if (card->info.type == QETH_CARD_TYPE_IQD) {
		switch (*type) {
		case NO_ROUTER:
		case PRIMARY_CONNECTOR:
		case SECONDARY_CONNECTOR:
		case MULTICAST_ROUTER:
460
			return 0;
F
Frank Blaschka 已提交
461 462 463 464 465 466 467 468
		default:
			goto out_inval;
		}
	} else {
		switch (*type) {
		case NO_ROUTER:
		case PRIMARY_ROUTER:
		case SECONDARY_ROUTER:
469
			return 0;
F
Frank Blaschka 已提交
470 471 472
		case MULTICAST_ROUTER:
			if (qeth_is_ipafunc_supported(card, prot,
						      IPA_OSA_MC_ROUTER))
473
				return 0;
F
Frank Blaschka 已提交
474 475 476 477 478 479
		default:
			goto out_inval;
		}
	}
out_inval:
	*type = NO_ROUTER;
480
	return -EINVAL;
F
Frank Blaschka 已提交
481 482 483 484 485 486
}

int qeth_l3_setrouting_v4(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
487
	QETH_CARD_TEXT(card, 3, "setrtg4");
F
Frank Blaschka 已提交
488

489
	rc = qeth_l3_correct_routing_type(card, &card->options.route4.type,
F
Frank Blaschka 已提交
490
				  QETH_PROT_IPV4);
491 492
	if (rc)
		return rc;
F
Frank Blaschka 已提交
493 494 495 496 497

	rc = qeth_l3_send_setrouting(card, card->options.route4.type,
				  QETH_PROT_IPV4);
	if (rc) {
		card->options.route4.type = NO_ROUTER;
498 499 500
		QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type"
			" on %s. Type set to 'no router'.\n", rc,
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
501 502 503 504 505 506 507 508
	}
	return rc;
}

int qeth_l3_setrouting_v6(struct qeth_card *card)
{
	int rc = 0;

C
Carsten Otte 已提交
509
	QETH_CARD_TEXT(card, 3, "setrtg6");
F
Frank Blaschka 已提交
510 511 512

	if (!qeth_is_supported(card, IPA_IPV6))
		return 0;
513
	rc = qeth_l3_correct_routing_type(card, &card->options.route6.type,
F
Frank Blaschka 已提交
514
				  QETH_PROT_IPV6);
515 516
	if (rc)
		return rc;
F
Frank Blaschka 已提交
517 518 519 520 521

	rc = qeth_l3_send_setrouting(card, card->options.route6.type,
				  QETH_PROT_IPV6);
	if (rc) {
		card->options.route6.type = NO_ROUTER;
522 523 524
		QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type"
			" on %s. Type set to 'no router'.\n", rc,
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
525 526 527 528 529 530 531
	}
	return rc;
}

/*
 * IP address takeover related functions
 */
532 533 534 535 536 537 538 539 540 541 542 543 544 545

/**
 * qeth_l3_update_ipato() - Update 'takeover' property, for all NORMAL IPs.
 *
 * Caller must hold ip_lock.
 */
void qeth_l3_update_ipato(struct qeth_card *card)
{
	struct qeth_ipaddr *addr;
	unsigned int i;

	hash_for_each(card->ip_htable, i, addr, hnode) {
		if (addr->type != QETH_IP_TYPE_NORMAL)
			continue;
546
		addr->ipato = qeth_l3_is_addr_covered_by_ipato(card, addr);
547 548 549
	}
}

F
Frank Blaschka 已提交
550 551 552 553
static void qeth_l3_clear_ipato_list(struct qeth_card *card)
{
	struct qeth_ipato_entry *ipatoe, *tmp;

554 555
	spin_lock_bh(&card->ip_lock);

F
Frank Blaschka 已提交
556 557 558 559
	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
		list_del(&ipatoe->entry);
		kfree(ipatoe);
	}
560

561
	qeth_l3_update_ipato(card);
562
	spin_unlock_bh(&card->ip_lock);
F
Frank Blaschka 已提交
563 564 565 566 567 568 569 570
}

int qeth_l3_add_ipato_entry(struct qeth_card *card,
				struct qeth_ipato_entry *new)
{
	struct qeth_ipato_entry *ipatoe;
	int rc = 0;

C
Carsten Otte 已提交
571
	QETH_CARD_TEXT(card, 2, "addipato");
572 573 574

	spin_lock_bh(&card->ip_lock);

F
Frank Blaschka 已提交
575 576 577 578 579 580 581 582 583 584
	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
		if (ipatoe->proto != new->proto)
			continue;
		if (!memcmp(ipatoe->addr, new->addr,
			    (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
		    (ipatoe->mask_bits == new->mask_bits)) {
			rc = -EEXIST;
			break;
		}
	}
585

586
	if (!rc) {
F
Frank Blaschka 已提交
587
		list_add_tail(&new->entry, &card->ipato.entries);
588 589
		qeth_l3_update_ipato(card);
	}
F
Frank Blaschka 已提交
590

591 592
	spin_unlock_bh(&card->ip_lock);

F
Frank Blaschka 已提交
593 594 595
	return rc;
}

596 597 598
int qeth_l3_del_ipato_entry(struct qeth_card *card,
			    enum qeth_prot_versions proto, u8 *addr,
			    int mask_bits)
F
Frank Blaschka 已提交
599 600
{
	struct qeth_ipato_entry *ipatoe, *tmp;
601
	int rc = -ENOENT;
F
Frank Blaschka 已提交
602

C
Carsten Otte 已提交
603
	QETH_CARD_TEXT(card, 2, "delipato");
604 605 606

	spin_lock_bh(&card->ip_lock);

F
Frank Blaschka 已提交
607 608 609 610 611 612 613
	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
		if (ipatoe->proto != proto)
			continue;
		if (!memcmp(ipatoe->addr, addr,
			    (proto == QETH_PROT_IPV4)? 4:16) &&
		    (ipatoe->mask_bits == mask_bits)) {
			list_del(&ipatoe->entry);
614
			qeth_l3_update_ipato(card);
F
Frank Blaschka 已提交
615
			kfree(ipatoe);
616
			rc = 0;
F
Frank Blaschka 已提交
617 618
		}
	}
619 620

	spin_unlock_bh(&card->ip_lock);
621
	return rc;
F
Frank Blaschka 已提交
622 623
}

624 625 626
int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
			     enum qeth_ip_types type,
			     enum qeth_prot_versions proto)
F
Frank Blaschka 已提交
627
{
628
	struct qeth_ipaddr addr;
629
	int rc;
F
Frank Blaschka 已提交
630

631 632 633 634 635
	qeth_l3_init_ipaddr(&addr, type, proto);
	if (proto == QETH_PROT_IPV4)
		memcpy(&addr.u.a4.addr, ip, 4);
	else
		memcpy(&addr.u.a6.addr, ip, 16);
636 637

	spin_lock_bh(&card->ip_lock);
638
	rc = add ? qeth_l3_add_ip(card, &addr) : qeth_l3_delete_ip(card, &addr);
639 640
	spin_unlock_bh(&card->ip_lock);
	return rc;
F
Frank Blaschka 已提交
641 642
}

643
int qeth_l3_modify_hsuid(struct qeth_card *card, bool add)
F
Frank Blaschka 已提交
644
{
645 646
	struct qeth_ipaddr addr;
	int rc, i;
F
Frank Blaschka 已提交
647

648 649 650 651 652
	qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV6);
	addr.u.a6.addr.s6_addr[0] = 0xfe;
	addr.u.a6.addr.s6_addr[1] = 0x80;
	for (i = 0; i < 8; i++)
		addr.u.a6.addr.s6_addr[8+i] = card->options.hsuid[i];
653 654

	spin_lock_bh(&card->ip_lock);
655
	rc = add ? qeth_l3_add_ip(card, &addr) : qeth_l3_delete_ip(card, &addr);
656
	spin_unlock_bh(&card->ip_lock);
657
	return rc;
F
Frank Blaschka 已提交
658 659 660 661 662 663 664 665 666
}

static int qeth_l3_register_addr_entry(struct qeth_card *card,
				struct qeth_ipaddr *addr)
{
	char buf[50];
	int rc = 0;
	int cnt = 3;

667

F
Frank Blaschka 已提交
668
	if (addr->proto == QETH_PROT_IPV4) {
C
Carsten Otte 已提交
669 670
		QETH_CARD_TEXT(card, 2, "setaddr4");
		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));
F
Frank Blaschka 已提交
671
	} else if (addr->proto == QETH_PROT_IPV6) {
C
Carsten Otte 已提交
672 673 674
		QETH_CARD_TEXT(card, 2, "setaddr6");
		QETH_CARD_HEX(card, 3, &addr->u.a6.addr, 8);
		QETH_CARD_HEX(card, 3, ((char *)&addr->u.a6.addr) + 8, 8);
F
Frank Blaschka 已提交
675
	} else {
C
Carsten Otte 已提交
676 677
		QETH_CARD_TEXT(card, 2, "setaddr?");
		QETH_CARD_HEX(card, 3, addr, sizeof(struct qeth_ipaddr));
F
Frank Blaschka 已提交
678 679 680 681 682
	}
	do {
		if (addr->is_multicast)
			rc =  qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
		else
683
			rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP);
F
Frank Blaschka 已提交
684
		if (rc)
C
Carsten Otte 已提交
685
			QETH_CARD_TEXT(card, 2, "failed");
F
Frank Blaschka 已提交
686 687
	} while ((--cnt > 0) && rc);
	if (rc) {
C
Carsten Otte 已提交
688
		QETH_CARD_TEXT(card, 2, "FAILED");
F
Frank Blaschka 已提交
689
		qeth_l3_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
690 691
		dev_warn(&card->gdev->dev,
			"Registering IP address %s failed\n", buf);
F
Frank Blaschka 已提交
692 693 694 695 696 697 698 699 700 701
	}
	return rc;
}

static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
						struct qeth_ipaddr *addr)
{
	int rc = 0;

	if (addr->proto == QETH_PROT_IPV4) {
C
Carsten Otte 已提交
702 703
		QETH_CARD_TEXT(card, 2, "deladdr4");
		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));
F
Frank Blaschka 已提交
704
	} else if (addr->proto == QETH_PROT_IPV6) {
C
Carsten Otte 已提交
705 706 707
		QETH_CARD_TEXT(card, 2, "deladdr6");
		QETH_CARD_HEX(card, 3, &addr->u.a6.addr, 8);
		QETH_CARD_HEX(card, 3, ((char *)&addr->u.a6.addr) + 8, 8);
F
Frank Blaschka 已提交
708
	} else {
C
Carsten Otte 已提交
709 710
		QETH_CARD_TEXT(card, 2, "deladdr?");
		QETH_CARD_HEX(card, 3, addr, sizeof(struct qeth_ipaddr));
F
Frank Blaschka 已提交
711 712 713 714
	}
	if (addr->is_multicast)
		rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
	else
715
		rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP);
716
	if (rc)
C
Carsten Otte 已提交
717
		QETH_CARD_TEXT(card, 2, "failed");
F
Frank Blaschka 已提交
718 719 720 721 722 723

	return rc;
}

static int qeth_l3_setadapter_parms(struct qeth_card *card)
{
724
	int rc = 0;
F
Frank Blaschka 已提交
725

726
	QETH_DBF_TEXT(SETUP, 2, "setadprm");
F
Frank Blaschka 已提交
727 728 729 730

	if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) {
		rc = qeth_setadpparms_change_macaddr(card);
		if (rc)
731
			dev_warn(&card->gdev->dev, "Reading the adapter MAC"
732
				" address failed\n");
F
Frank Blaschka 已提交
733 734 735 736 737 738 739 740 741 742 743
	}

	return rc;
}

static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
		enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
{
	int rc;
	struct qeth_cmd_buffer *iob;

C
Carsten Otte 已提交
744
	QETH_CARD_TEXT(card, 4, "simassp6");
745
	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
F
Frank Blaschka 已提交
746
				       0, QETH_PROT_IPV6);
747 748
	if (!iob)
		return -ENOMEM;
749
	rc = qeth_send_setassparms(card, iob, 0, 0,
750
				   qeth_setassparms_cb, NULL);
F
Frank Blaschka 已提交
751 752 753 754 755 756 757
	return rc;
}

static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
758
	QETH_CARD_TEXT(card, 3, "ipaarp");
F
Frank Blaschka 已提交
759 760

	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
761 762 763
		dev_info(&card->gdev->dev,
			"ARP processing not supported on %s!\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
764 765
		return 0;
	}
766 767
	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
					  IPA_CMD_ASS_START, 0);
F
Frank Blaschka 已提交
768
	if (rc) {
769 770 771
		dev_warn(&card->gdev->dev,
			"Starting ARP processing support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
772 773 774 775 776 777 778 779
	}
	return rc;
}

static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
780
	QETH_CARD_TEXT(card, 3, "stsrcmac");
F
Frank Blaschka 已提交
781 782

	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
783
		dev_info(&card->gdev->dev,
784
			"Inbound source MAC-address not supported on %s\n",
785
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
786 787 788
		return -EOPNOTSUPP;
	}

789
	rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
F
Frank Blaschka 已提交
790 791
					  IPA_CMD_ASS_START, 0);
	if (rc)
792
		dev_warn(&card->gdev->dev,
793
			"Starting source MAC-address support for %s failed\n",
794
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
795 796 797 798 799 800 801
	return rc;
}

static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
{
	int rc = 0;

C
Carsten Otte 已提交
802
	QETH_CARD_TEXT(card, 3, "strtvlan");
F
Frank Blaschka 已提交
803 804

	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
805 806
		dev_info(&card->gdev->dev,
			"VLAN not supported on %s\n", QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
807 808 809
		return -EOPNOTSUPP;
	}

810
	rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
F
Frank Blaschka 已提交
811 812
					  IPA_CMD_ASS_START, 0);
	if (rc) {
813 814 815
		dev_warn(&card->gdev->dev,
			"Starting VLAN support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
816
	} else {
817
		dev_info(&card->gdev->dev, "VLAN enabled\n");
F
Frank Blaschka 已提交
818 819 820 821 822 823 824 825
	}
	return rc;
}

static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
826
	QETH_CARD_TEXT(card, 3, "stmcast");
F
Frank Blaschka 已提交
827 828

	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
829 830 831
		dev_info(&card->gdev->dev,
			"Multicast not supported on %s\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
832 833 834
		return -EOPNOTSUPP;
	}

835
	rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
F
Frank Blaschka 已提交
836 837
					  IPA_CMD_ASS_START, 0);
	if (rc) {
838 839 840
		dev_warn(&card->gdev->dev,
			"Starting multicast support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
841
	} else {
842
		dev_info(&card->gdev->dev, "Multicast enabled\n");
F
Frank Blaschka 已提交
843 844 845 846 847 848 849 850 851
		card->dev->flags |= IFF_MULTICAST;
	}
	return rc;
}

static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
852
	QETH_CARD_TEXT(card, 3, "softipv6");
F
Frank Blaschka 已提交
853

854
	rc = qeth_query_ipassists(card, QETH_PROT_IPV6);
F
Frank Blaschka 已提交
855
	if (rc) {
856 857 858
		dev_err(&card->gdev->dev,
			"Activating IPv6 support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
859 860
		return rc;
	}
861 862 863 864

	if (card->info.type == QETH_CARD_TYPE_IQD)
		goto out;

865
	rc = qeth_send_simple_setassparms(card, IPA_IPV6,
F
Frank Blaschka 已提交
866 867
					  IPA_CMD_ASS_START, 3);
	if (rc) {
868 869 870
		dev_err(&card->gdev->dev,
			"Activating IPv6 support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
871 872 873 874 875
		return rc;
	}
	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6,
					       IPA_CMD_ASS_START);
	if (rc) {
876 877 878
		dev_err(&card->gdev->dev,
			"Activating IPv6 support for %s failed\n",
			 QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
879 880 881 882 883
		return rc;
	}
	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
					       IPA_CMD_ASS_START);
	if (rc) {
884 885 886
		dev_warn(&card->gdev->dev,
			"Enabling the passthrough mode for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
887 888 889
		return rc;
	}
out:
890
	dev_info(&card->gdev->dev, "IPV6 enabled\n");
F
Frank Blaschka 已提交
891 892 893 894 895
	return 0;
}

static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
{
C
Carsten Otte 已提交
896
	QETH_CARD_TEXT(card, 3, "strtipv6");
F
Frank Blaschka 已提交
897 898

	if (!qeth_is_supported(card, IPA_IPV6)) {
899 900
		dev_info(&card->gdev->dev,
			"IPv6 not supported on %s\n", QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
901 902
		return 0;
	}
J
Julian Wiedmann 已提交
903
	return qeth_l3_softsetup_ipv6(card);
F
Frank Blaschka 已提交
904 905 906 907 908 909
}

static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
{
	int rc;

C
Carsten Otte 已提交
910
	QETH_CARD_TEXT(card, 3, "stbrdcst");
F
Frank Blaschka 已提交
911 912
	card->info.broadcast_capable = 0;
	if (!qeth_is_supported(card, IPA_FILTERING)) {
913 914 915
		dev_info(&card->gdev->dev,
			"Broadcast not supported on %s\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
916 917 918
		rc = -EOPNOTSUPP;
		goto out;
	}
919
	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
F
Frank Blaschka 已提交
920 921
					  IPA_CMD_ASS_START, 0);
	if (rc) {
922 923
		dev_warn(&card->gdev->dev, "Enabling broadcast filtering for "
			"%s failed\n", QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
924 925 926
		goto out;
	}

927
	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
F
Frank Blaschka 已提交
928 929
					  IPA_CMD_ASS_CONFIGURE, 1);
	if (rc) {
930 931 932
		dev_warn(&card->gdev->dev,
			"Setting up broadcast filtering for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
933 934 935
		goto out;
	}
	card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
936
	dev_info(&card->gdev->dev, "Broadcast enabled\n");
937
	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
F
Frank Blaschka 已提交
938 939
					  IPA_CMD_ASS_ENABLE, 1);
	if (rc) {
940 941
		dev_warn(&card->gdev->dev, "Setting up broadcast echo "
			"filtering for %s failed\n", QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
942 943 944 945 946 947 948 949 950 951 952 953 954
		goto out;
	}
	card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
out:
	if (card->info.broadcast_capable)
		card->dev->flags |= IFF_BROADCAST;
	else
		card->dev->flags &= ~IFF_BROADCAST;
	return rc;
}

static int qeth_l3_start_ipassists(struct qeth_card *card)
{
C
Carsten Otte 已提交
955
	QETH_CARD_TEXT(card, 3, "strtipas");
E
Einar Lueck 已提交
956

S
Stefan Raspl 已提交
957 958
	if (qeth_set_access_ctrl_online(card, 0))
		return -EIO;
F
Frank Blaschka 已提交
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
	qeth_l3_start_ipa_arp_processing(card);	/* go on*/
	qeth_l3_start_ipa_source_mac(card);	/* go on*/
	qeth_l3_start_ipa_vlan(card);		/* go on*/
	qeth_l3_start_ipa_multicast(card);		/* go on*/
	qeth_l3_start_ipa_ipv6(card);		/* go on*/
	qeth_l3_start_ipa_broadcast(card);		/* go on*/
	return 0;
}

static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
		struct qeth_reply *reply, unsigned long data)
{
	struct qeth_ipa_cmd *cmd;

	cmd = (struct qeth_ipa_cmd *) data;
	if (cmd->hdr.return_code == 0)
975 976
		ether_addr_copy(card->dev->dev_addr,
				cmd->data.create_destroy_addr.unique_id);
F
Frank Blaschka 已提交
977
	else
J
Joe Perches 已提交
978
		eth_random_addr(card->dev->dev_addr);
F
Frank Blaschka 已提交
979 980 981 982 983 984 985 986 987 988

	return 0;
}

static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
{
	int rc = 0;
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;

989
	QETH_DBF_TEXT(SETUP, 2, "hsrmac");
F
Frank Blaschka 已提交
990 991 992

	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
				     QETH_PROT_IPV6);
993 994
	if (!iob)
		return -ENOMEM;
995
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
			card->info.unique_id;

	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_iqd_read_initial_mac_cb,
				NULL);
	return rc;
}

static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
		struct qeth_reply *reply, unsigned long data)
{
	struct qeth_ipa_cmd *cmd;

	cmd = (struct qeth_ipa_cmd *) data;
	if (cmd->hdr.return_code == 0)
		card->info.unique_id = *((__u16 *)
				&cmd->data.create_destroy_addr.unique_id[6]);
	else {
		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
					UNIQUE_ID_NOT_BY_CARD;
1016 1017
		dev_warn(&card->gdev->dev, "The network adapter failed to "
			"generate a unique ID\n");
F
Frank Blaschka 已提交
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
	}
	return 0;
}

static int qeth_l3_get_unique_id(struct qeth_card *card)
{
	int rc = 0;
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;

1028
	QETH_DBF_TEXT(SETUP, 2, "guniqeid");
F
Frank Blaschka 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037

	if (!qeth_is_supported(card, IPA_IPV6)) {
		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
					UNIQUE_ID_NOT_BY_CARD;
		return 0;
	}

	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
				     QETH_PROT_IPV6);
1038 1039
	if (!iob)
		return -ENOMEM;
1040
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
1041 1042 1043 1044 1045 1046 1047
	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
			card->info.unique_id;

	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_get_unique_id_cb, NULL);
	return rc;
}

1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
static int
qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
			    unsigned long data)
{
	struct qeth_ipa_cmd	   *cmd;
	__u16 rc;

	QETH_DBF_TEXT(SETUP, 2, "diastrcb");

	cmd = (struct qeth_ipa_cmd *)data;
	rc = cmd->hdr.return_code;
1059
	if (rc)
C
Carsten Otte 已提交
1060
		QETH_CARD_TEXT_(card, 2, "dxter%x", rc);
1061 1062 1063 1064
	switch (cmd->data.diagass.action) {
	case QETH_DIAGS_CMD_TRACE_QUERY:
		break;
	case QETH_DIAGS_CMD_TRACE_DISABLE:
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
		switch (rc) {
		case 0:
		case IPA_RC_INVALID_SUBCMD:
			card->info.promisc_mode = SET_PROMISC_MODE_OFF;
			dev_info(&card->gdev->dev, "The HiperSockets network "
				"traffic analyzer is deactivated\n");
			break;
		default:
			break;
		}
1075 1076
		break;
	case QETH_DIAGS_CMD_TRACE_ENABLE:
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
		switch (rc) {
		case 0:
			card->info.promisc_mode = SET_PROMISC_MODE_ON;
			dev_info(&card->gdev->dev, "The HiperSockets network "
				"traffic analyzer is activated\n");
			break;
		case IPA_RC_HARDWARE_AUTH_ERROR:
			dev_warn(&card->gdev->dev, "The device is not "
				"authorized to run as a HiperSockets network "
				"traffic analyzer\n");
			break;
		case IPA_RC_TRACE_ALREADY_ACTIVE:
			dev_warn(&card->gdev->dev, "A HiperSockets "
				"network traffic analyzer is already "
				"active in the HiperSockets LAN\n");
			break;
		default:
			break;
		}
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
		break;
	default:
		QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n",
			cmd->data.diagass.action, QETH_CARD_IFNAME(card));
	}

	return 0;
}

static int
qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd)
{
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd    *cmd;

	QETH_DBF_TEXT(SETUP, 2, "diagtrac");

	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
1114 1115
	if (!iob)
		return -ENOMEM;
1116
	cmd = __ipa_cmd(iob);
1117 1118 1119 1120 1121 1122 1123
	cmd->data.diagass.subcmd_len = 16;
	cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE;
	cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET;
	cmd->data.diagass.action = diags_cmd;
	return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL);
}

1124 1125
static void
qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev)
F
Frank Blaschka 已提交
1126 1127
{
	struct ip_mc_list *im4;
1128
	struct qeth_ipaddr *tmp, *ipm;
F
Frank Blaschka 已提交
1129

C
Carsten Otte 已提交
1130
	QETH_CARD_TEXT(card, 4, "addmc");
1131 1132

	tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
1133 1134
	if (!tmp)
		return;
1135

S
Sachin Sant 已提交
1136 1137
	for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL;
	     im4 = rcu_dereference(im4->next_rcu)) {
1138
		ip_eth_mc_map(im4->multiaddr, tmp->mac);
1139
		tmp->u.a4.addr = be32_to_cpu(im4->multiaddr);
1140
		tmp->is_multicast = 1;
1141

1142
		ipm = qeth_l3_find_addr_by_ip(card, tmp);
1143
		if (ipm) {
1144
			/* for mcast, by-IP match means full match */
1145 1146 1147 1148 1149
			ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
		} else {
			ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
			if (!ipm)
				continue;
1150
			ether_addr_copy(ipm->mac, tmp->mac);
1151
			ipm->u.a4.addr = be32_to_cpu(im4->multiaddr);
1152 1153 1154 1155 1156
			ipm->is_multicast = 1;
			ipm->disp_flag = QETH_DISP_ADDR_ADD;
			hash_add(card->ip_mc_htable,
					&ipm->hnode, qeth_l3_ipaddr_hash(ipm));
		}
F
Frank Blaschka 已提交
1157
	}
1158 1159

	kfree(tmp);
F
Frank Blaschka 已提交
1160 1161
}

1162
/* called with rcu_read_lock */
F
Frank Blaschka 已提交
1163 1164 1165
static void qeth_l3_add_vlan_mc(struct qeth_card *card)
{
	struct in_device *in_dev;
J
Jiri Pirko 已提交
1166
	u16 vid;
F
Frank Blaschka 已提交
1167

C
Carsten Otte 已提交
1168
	QETH_CARD_TEXT(card, 4, "addmcvl");
1169

J
Jiri Pirko 已提交
1170
	if (!qeth_is_supported(card, IPA_FULL_VLAN))
F
Frank Blaschka 已提交
1171 1172
		return;

J
Jiri Pirko 已提交
1173 1174 1175
	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
		struct net_device *netdev;

1176
		netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q),
1177
					      vid);
F
Frank Blaschka 已提交
1178 1179 1180
		if (netdev == NULL ||
		    !(netdev->flags & IFF_UP))
			continue;
1181
		in_dev = __in_dev_get_rcu(netdev);
F
Frank Blaschka 已提交
1182 1183
		if (!in_dev)
			continue;
1184
		qeth_l3_add_mc_to_hash(card, in_dev);
F
Frank Blaschka 已提交
1185 1186 1187 1188 1189 1190 1191
	}
}

static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
{
	struct in_device *in4_dev;

C
Carsten Otte 已提交
1192
	QETH_CARD_TEXT(card, 4, "chkmcv4");
1193

S
Sachin Sant 已提交
1194
	rcu_read_lock();
1195 1196 1197
	in4_dev = __in_dev_get_rcu(card->dev);
	if (in4_dev == NULL)
		goto unlock;
1198
	qeth_l3_add_mc_to_hash(card, in4_dev);
F
Frank Blaschka 已提交
1199
	qeth_l3_add_vlan_mc(card);
1200
unlock:
S
Sachin Sant 已提交
1201
	rcu_read_unlock();
F
Frank Blaschka 已提交
1202 1203
}

J
Julian Wiedmann 已提交
1204 1205
static void qeth_l3_add_mc6_to_hash(struct qeth_card *card,
				    struct inet6_dev *in6_dev)
F
Frank Blaschka 已提交
1206 1207 1208
{
	struct qeth_ipaddr *ipm;
	struct ifmcaddr6 *im6;
1209
	struct qeth_ipaddr *tmp;
F
Frank Blaschka 已提交
1210

C
Carsten Otte 已提交
1211
	QETH_CARD_TEXT(card, 4, "addmc6");
1212 1213

	tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
1214 1215
	if (!tmp)
		return;
1216

F
Frank Blaschka 已提交
1217
	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
1218
		ipv6_eth_mc_map(&im6->mca_addr, tmp->mac);
1219 1220 1221 1222
		memcpy(&tmp->u.a6.addr, &im6->mca_addr.s6_addr,
		       sizeof(struct in6_addr));
		tmp->is_multicast = 1;

1223
		ipm = qeth_l3_find_addr_by_ip(card, tmp);
1224
		if (ipm) {
1225
			/* for mcast, by-IP match means full match */
1226 1227 1228 1229
			ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
			continue;
		}

F
Frank Blaschka 已提交
1230 1231 1232
		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
		if (!ipm)
			continue;
1233

1234
		ether_addr_copy(ipm->mac, tmp->mac);
F
Frank Blaschka 已提交
1235 1236
		memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
		       sizeof(struct in6_addr));
1237 1238 1239 1240 1241
		ipm->is_multicast = 1;
		ipm->disp_flag = QETH_DISP_ADDR_ADD;
		hash_add(card->ip_mc_htable,
				&ipm->hnode, qeth_l3_ipaddr_hash(ipm));

F
Frank Blaschka 已提交
1242
	}
1243
	kfree(tmp);
F
Frank Blaschka 已提交
1244 1245
}

1246
/* called with rcu_read_lock */
F
Frank Blaschka 已提交
1247 1248 1249
static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
{
	struct inet6_dev *in_dev;
J
Jiri Pirko 已提交
1250
	u16 vid;
F
Frank Blaschka 已提交
1251

C
Carsten Otte 已提交
1252
	QETH_CARD_TEXT(card, 4, "admc6vl");
1253

J
Jiri Pirko 已提交
1254
	if (!qeth_is_supported(card, IPA_FULL_VLAN))
F
Frank Blaschka 已提交
1255 1256
		return;

J
Jiri Pirko 已提交
1257 1258 1259
	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
		struct net_device *netdev;

1260
		netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q),
1261
					      vid);
F
Frank Blaschka 已提交
1262 1263 1264 1265 1266 1267 1268
		if (netdev == NULL ||
		    !(netdev->flags & IFF_UP))
			continue;
		in_dev = in6_dev_get(netdev);
		if (!in_dev)
			continue;
		read_lock_bh(&in_dev->lock);
1269
		qeth_l3_add_mc6_to_hash(card, in_dev);
F
Frank Blaschka 已提交
1270 1271 1272 1273 1274 1275 1276 1277 1278
		read_unlock_bh(&in_dev->lock);
		in6_dev_put(in_dev);
	}
}

static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
{
	struct inet6_dev *in6_dev;

C
Carsten Otte 已提交
1279
	QETH_CARD_TEXT(card, 4, "chkmcv6");
1280

F
Frank Blaschka 已提交
1281 1282 1283
	if (!qeth_is_supported(card, IPA_IPV6))
		return ;
	in6_dev = in6_dev_get(card->dev);
1284
	if (!in6_dev)
F
Frank Blaschka 已提交
1285
		return;
1286

1287
	rcu_read_lock();
F
Frank Blaschka 已提交
1288
	read_lock_bh(&in6_dev->lock);
1289
	qeth_l3_add_mc6_to_hash(card, in6_dev);
F
Frank Blaschka 已提交
1290 1291
	qeth_l3_add_vlan_mc6(card);
	read_unlock_bh(&in6_dev->lock);
1292
	rcu_read_unlock();
F
Frank Blaschka 已提交
1293 1294 1295
	in6_dev_put(in6_dev);
}

1296 1297
static int qeth_l3_vlan_rx_add_vid(struct net_device *dev,
				   __be16 proto, u16 vid)
F
Frank Blaschka 已提交
1298
{
1299
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1300

J
Jiri Pirko 已提交
1301
	set_bit(vid, card->active_vlans);
1302
	return 0;
F
Frank Blaschka 已提交
1303 1304
}

1305 1306
static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
				    __be16 proto, u16 vid)
F
Frank Blaschka 已提交
1307
{
1308
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1309

C
Carsten Otte 已提交
1310
	QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
1311

1312
	if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
C
Carsten Otte 已提交
1313
		QETH_CARD_TEXT(card, 3, "kidREC");
1314
		return 0;
1315
	}
J
Jiri Pirko 已提交
1316
	clear_bit(vid, card->active_vlans);
1317
	qeth_l3_set_rx_mode(dev);
1318
	return 0;
F
Frank Blaschka 已提交
1319 1320
}

1321 1322
static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
				struct qeth_hdr *hdr)
F
Frank Blaschka 已提交
1323 1324
{
	if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
1325 1326
		u16 prot = (hdr->hdr.l3.flags & QETH_HDR_IPV6) ? ETH_P_IPV6 :
								 ETH_P_IP;
1327
		unsigned char tg_addr[ETH_ALEN];
1328 1329

		skb_reset_network_header(skb);
F
Frank Blaschka 已提交
1330 1331
		switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) {
		case QETH_CAST_MULTICAST:
J
Julian Wiedmann 已提交
1332
			if (prot == ETH_P_IP)
1333
				ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr);
J
Julian Wiedmann 已提交
1334 1335 1336
			else
				ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr);

F
Frank Blaschka 已提交
1337 1338 1339
			card->stats.multicast++;
			break;
		case QETH_CAST_BROADCAST:
1340
			ether_addr_copy(tg_addr, card->dev->broadcast);
F
Frank Blaschka 已提交
1341 1342 1343
			card->stats.multicast++;
			break;
		default:
1344 1345
			if (card->options.sniffer)
				skb->pkt_type = PACKET_OTHERHOST;
1346
			ether_addr_copy(tg_addr, card->dev->dev_addr);
F
Frank Blaschka 已提交
1347
		}
J
Julian Wiedmann 已提交
1348

1349 1350
		if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
			card->dev->header_ops->create(skb, card->dev, prot,
1351
				tg_addr, &hdr->hdr.l3.next_hop.rx.src_mac,
1352
				skb->len);
1353 1354
		else
			card->dev->header_ops->create(skb, card->dev, prot,
1355
				tg_addr, "FAKELL", skb->len);
F
Frank Blaschka 已提交
1356 1357
	}

1358
	skb->protocol = eth_type_trans(skb, card->dev);
F
Frank Blaschka 已提交
1359

1360 1361 1362 1363 1364 1365
	/* copy VLAN tag from hdr into skb */
	if (!card->options.sniffer &&
	    (hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_VLAN_FRAME |
				      QETH_HDR_EXT_INCLUDE_VLAN_TAG))) {
		u16 tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ?
				hdr->hdr.l3.vlan_id :
1366
				hdr->hdr.l3.next_hop.rx.vlan_id;
1367
		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag);
F
Frank Blaschka 已提交
1368 1369
	}

1370
	if (card->dev->features & NETIF_F_RXCSUM) {
F
Frank Blaschka 已提交
1371
		if ((hdr->hdr.l3.ext_flags &
1372 1373 1374 1375
		    (QETH_HDR_EXT_CSUM_HDR_REQ |
		     QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
		    (QETH_HDR_EXT_CSUM_HDR_REQ |
		     QETH_HDR_EXT_CSUM_TRANSP_REQ))
F
Frank Blaschka 已提交
1376 1377
			skb->ip_summed = CHECKSUM_UNNECESSARY;
		else
1378
			skb->ip_summed = CHECKSUM_NONE;
1379 1380
	} else
		skb->ip_summed = CHECKSUM_NONE;
F
Frank Blaschka 已提交
1381 1382
}

1383 1384
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
				int budget, int *done)
F
Frank Blaschka 已提交
1385
{
1386
	int work_done = 0;
F
Frank Blaschka 已提交
1387 1388 1389
	struct sk_buff *skb;
	struct qeth_hdr *hdr;
	unsigned int len;
1390
	__u16 magic;
F
Frank Blaschka 已提交
1391

1392
	*done = 0;
S
Stefan Raspl 已提交
1393
	WARN_ON_ONCE(!budget);
1394 1395
	while (budget) {
		skb = qeth_core_get_next_skb(card,
1396
			&card->qdio.in_q->bufs[card->rx.b_index],
1397 1398 1399 1400 1401
			&card->rx.b_element, &card->rx.e_offset, &hdr);
		if (!skb) {
			*done = 1;
			break;
		}
F
Frank Blaschka 已提交
1402 1403
		switch (hdr->hdr.l3.id) {
		case QETH_HEADER_TYPE_LAYER3:
1404 1405 1406
			magic = *(__u16 *)skb->data;
			if ((card->info.type == QETH_CARD_TYPE_IQD) &&
			    (magic == ETH_P_AF_IUCV)) {
1407
				skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
1408 1409
				len = skb->len;
				card->dev->header_ops->create(skb, card->dev, 0,
1410
					card->dev->dev_addr, "FAKELL", len);
1411
				skb_reset_mac_header(skb);
1412 1413
				netif_receive_skb(skb);
			} else {
1414
				qeth_l3_rebuild_skb(card, skb, hdr);
1415 1416 1417
				len = skb->len;
				napi_gro_receive(&card->napi, skb);
			}
F
Frank Blaschka 已提交
1418
			break;
1419 1420 1421 1422 1423
		case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
			skb->protocol = eth_type_trans(skb, skb->dev);
			len = skb->len;
			netif_receive_skb(skb);
			break;
F
Frank Blaschka 已提交
1424 1425
		default:
			dev_kfree_skb_any(skb);
C
Carsten Otte 已提交
1426
			QETH_CARD_TEXT(card, 3, "inbunkno");
1427
			QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
F
Frank Blaschka 已提交
1428 1429
			continue;
		}
1430 1431
		work_done++;
		budget--;
F
Frank Blaschka 已提交
1432 1433 1434
		card->stats.rx_packets++;
		card->stats.rx_bytes += len;
	}
1435 1436 1437
	return work_done;
}

1438
static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
F
Frank Blaschka 已提交
1439
{
1440 1441
	QETH_DBF_TEXT(SETUP, 2, "stopcard");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
F
Frank Blaschka 已提交
1442 1443

	qeth_set_allowed_threads(card, 0, 1);
1444 1445 1446
	if (card->options.sniffer &&
	    (card->info.promisc_mode == SET_PROMISC_MODE_ON))
		qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
F
Frank Blaschka 已提交
1447 1448 1449 1450 1451
	if (card->read.state == CH_STATE_UP &&
	    card->write.state == CH_STATE_UP &&
	    (card->state == CARD_STATE_UP)) {
		if (recovery_mode)
			qeth_l3_stop(card->dev);
1452
		else {
1453 1454 1455
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
1456
		}
F
Frank Blaschka 已提交
1457 1458 1459
		card->state = CARD_STATE_SOFTSETUP;
	}
	if (card->state == CARD_STATE_SOFTSETUP) {
1460
		qeth_l3_clear_ip_htable(card, 1);
F
Frank Blaschka 已提交
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
		qeth_clear_ipacmd_list(card);
		card->state = CARD_STATE_HARDSETUP;
	}
	if (card->state == CARD_STATE_HARDSETUP) {
		qeth_qdio_clear_card(card, 0);
		qeth_clear_qdio_buffers(card);
		qeth_clear_working_pool_list(card);
		card->state = CARD_STATE_DOWN;
	}
	if (card->state == CARD_STATE_DOWN) {
		qeth_clear_cmd_buffers(&card->read);
		qeth_clear_cmd_buffers(&card->write);
	}
}

1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
/*
 * test for and Switch promiscuous mode (on or off)
 *  either for guestlan or HiperSocket Sniffer
 */
static void
qeth_l3_handle_promisc_mode(struct qeth_card *card)
{
	struct net_device *dev = card->dev;

	if (((dev->flags & IFF_PROMISC) &&
	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
	    (!(dev->flags & IFF_PROMISC) &&
	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
		return;

	if (card->info.guestlan) {		/* Guestlan trace */
		if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
			qeth_setadp_promisc_mode(card);
	} else if (card->options.sniffer &&	/* HiperSockets trace */
		   qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) {
		if (dev->flags & IFF_PROMISC) {
C
Carsten Otte 已提交
1497
			QETH_CARD_TEXT(card, 3, "+promisc");
1498 1499
			qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_ENABLE);
		} else {
C
Carsten Otte 已提交
1500
			QETH_CARD_TEXT(card, 3, "-promisc");
1501 1502 1503 1504 1505
			qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
		}
	}
}

1506
static void qeth_l3_set_rx_mode(struct net_device *dev)
F
Frank Blaschka 已提交
1507
{
1508
	struct qeth_card *card = dev->ml_priv;
1509 1510 1511
	struct qeth_ipaddr *addr;
	struct hlist_node *tmp;
	int i, rc;
F
Frank Blaschka 已提交
1512

C
Carsten Otte 已提交
1513
	QETH_CARD_TEXT(card, 3, "setmulti");
1514 1515 1516
	if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
	    (card->state != CARD_STATE_UP))
		return;
1517
	if (!card->options.sniffer) {
1518 1519
		spin_lock_bh(&card->mclock);

1520 1521
		qeth_l3_add_multicast_ipv4(card);
		qeth_l3_add_multicast_ipv6(card);
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545

		hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) {
			switch (addr->disp_flag) {
			case QETH_DISP_ADDR_DELETE:
				rc = qeth_l3_deregister_addr_entry(card, addr);
				if (!rc || rc == IPA_RC_MC_ADDR_NOT_FOUND) {
					hash_del(&addr->hnode);
					kfree(addr);
				}
				break;
			case QETH_DISP_ADDR_ADD:
				rc = qeth_l3_register_addr_entry(card, addr);
				if (rc && rc != IPA_RC_LAN_OFFLINE) {
					hash_del(&addr->hnode);
					kfree(addr);
					break;
				}
				addr->ref_counter = 1;
				/* fall through */
			default:
				/* for next call to set_rx_mode(): */
				addr->disp_flag = QETH_DISP_ADDR_DELETE;
			}
		}
1546 1547 1548

		spin_unlock_bh(&card->mclock);

1549 1550 1551 1552
		if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
			return;
	}
	qeth_l3_handle_promisc_mode(card);
F
Frank Blaschka 已提交
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
}

static const char *qeth_l3_arp_get_error_cause(int *rc)
{
	switch (*rc) {
	case QETH_IPA_ARP_RC_FAILED:
		*rc = -EIO;
		return "operation failed";
	case QETH_IPA_ARP_RC_NOTSUPP:
		*rc = -EOPNOTSUPP;
		return "operation not supported";
	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
		*rc = -EINVAL;
		return "argument out of range";
	case QETH_IPA_ARP_RC_Q_NOTSUPP:
		*rc = -EOPNOTSUPP;
		return "query operation not supported";
	case QETH_IPA_ARP_RC_Q_NO_DATA:
		*rc = -ENOENT;
		return "no query data available";
	default:
		return "unknown error";
	}
}

static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
{
	int tmp;
	int rc;

C
Carsten Otte 已提交
1583
	QETH_CARD_TEXT(card, 3, "arpstnoe");
F
Frank Blaschka 已提交
1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594

	/*
	 * currently GuestLAN only supports the ARP assist function
	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
	 * thus we say EOPNOTSUPP for this ARP function
	 */
	if (card->info.guestlan)
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}
1595
	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
F
Frank Blaschka 已提交
1596 1597 1598 1599
					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
					  no_entries);
	if (rc) {
		tmp = rc;
1600 1601
		QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on "
			"%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card),
F
Frank Blaschka 已提交
1602 1603 1604 1605 1606
			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
	}
	return rc;
}

1607 1608 1609
static __u32 get_arp_entry_size(struct qeth_card *card,
			struct qeth_arp_query_data *qdata,
			struct qeth_arp_entrytype *type, __u8 strip_entries)
F
Frank Blaschka 已提交
1610
{
1611 1612
	__u32 rc;
	__u8 is_hsi;
F
Frank Blaschka 已提交
1613

1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
	is_hsi = qdata->reply_bits == 5;
	if (type->ip == QETHARP_IP_ADDR_V4) {
		QETH_CARD_TEXT(card, 4, "arpev4");
		if (strip_entries) {
			rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5_short) :
				sizeof(struct qeth_arp_qi_entry7_short);
		} else {
			rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5) :
				sizeof(struct qeth_arp_qi_entry7);
		}
	} else if (type->ip == QETHARP_IP_ADDR_V6) {
		QETH_CARD_TEXT(card, 4, "arpev6");
		if (strip_entries) {
			rc = is_hsi ?
				sizeof(struct qeth_arp_qi_entry5_short_ipv6) :
				sizeof(struct qeth_arp_qi_entry7_short_ipv6);
		} else {
			rc = is_hsi ?
				sizeof(struct qeth_arp_qi_entry5_ipv6) :
				sizeof(struct qeth_arp_qi_entry7_ipv6);
		}
	} else {
		QETH_CARD_TEXT(card, 4, "arpinv");
		rc = 0;
F
Frank Blaschka 已提交
1638
	}
1639 1640 1641 1642 1643 1644 1645 1646

	return rc;
}

static int arpentry_matches_prot(struct qeth_arp_entrytype *type, __u16 prot)
{
	return (type->ip == QETHARP_IP_ADDR_V4 && prot == QETH_PROT_IPV4) ||
		(type->ip == QETHARP_IP_ADDR_V6 && prot == QETH_PROT_IPV6);
F
Frank Blaschka 已提交
1647 1648 1649 1650 1651 1652 1653 1654 1655
}

static int qeth_l3_arp_query_cb(struct qeth_card *card,
		struct qeth_reply *reply, unsigned long data)
{
	struct qeth_ipa_cmd *cmd;
	struct qeth_arp_query_data *qdata;
	struct qeth_arp_query_info *qinfo;
	int i;
1656 1657 1658 1659
	int e;
	int entrybytes_done;
	int stripped_bytes;
	__u8 do_strip_entries;
F
Frank Blaschka 已提交
1660

1661
	QETH_CARD_TEXT(card, 3, "arpquecb");
F
Frank Blaschka 已提交
1662 1663 1664

	qinfo = (struct qeth_arp_query_info *) reply->param;
	cmd = (struct qeth_ipa_cmd *) data;
1665
	QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.prot_version);
F
Frank Blaschka 已提交
1666
	if (cmd->hdr.return_code) {
1667 1668
		QETH_CARD_TEXT(card, 4, "arpcberr");
		QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
F
Frank Blaschka 已提交
1669 1670 1671 1672
		return 0;
	}
	if (cmd->data.setassparms.hdr.return_code) {
		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
1673 1674
		QETH_CARD_TEXT(card, 4, "setaperr");
		QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
F
Frank Blaschka 已提交
1675 1676 1677
		return 0;
	}
	qdata = &cmd->data.setassparms.data.query_arp;
C
Carsten Otte 已提交
1678
	QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries);
F
Frank Blaschka 已提交
1679

1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
	do_strip_entries = (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) > 0;
	stripped_bytes = do_strip_entries ? QETH_QARP_MEDIASPECIFIC_BYTES : 0;
	entrybytes_done = 0;
	for (e = 0; e < qdata->no_entries; ++e) {
		char *cur_entry;
		__u32 esize;
		struct qeth_arp_entrytype *etype;

		cur_entry = &qdata->data + entrybytes_done;
		etype = &((struct qeth_arp_qi_entry5 *) cur_entry)->type;
		if (!arpentry_matches_prot(etype, cmd->hdr.prot_version)) {
			QETH_CARD_TEXT(card, 4, "pmis");
			QETH_CARD_TEXT_(card, 4, "%i", etype->ip);
			break;
		}
		esize = get_arp_entry_size(card, qdata, etype,
			do_strip_entries);
		QETH_CARD_TEXT_(card, 5, "esz%i", esize);
		if (!esize)
			break;

		if ((qinfo->udata_len - qinfo->udata_offset) < esize) {
			QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM);
1703
			cmd->hdr.return_code = IPA_RC_ENOMEM;
1704 1705
			goto out_error;
		}
F
Frank Blaschka 已提交
1706

1707 1708 1709 1710 1711 1712 1713
		memcpy(qinfo->udata + qinfo->udata_offset,
			&qdata->data + entrybytes_done + stripped_bytes,
			esize);
		entrybytes_done += esize + stripped_bytes;
		qinfo->udata_offset += esize;
		++qinfo->no_entries;
	}
F
Frank Blaschka 已提交
1714 1715 1716 1717
	/* check if all replies received ... */
	if (cmd->data.setassparms.hdr.seq_no <
	    cmd->data.setassparms.hdr.number_of_replies)
		return 1;
1718
	QETH_CARD_TEXT_(card, 4, "nove%i", qinfo->no_entries);
F
Frank Blaschka 已提交
1719 1720 1721 1722 1723 1724
	memcpy(qinfo->udata, &qinfo->no_entries, 4);
	/* keep STRIP_ENTRIES flag so the user program can distinguish
	 * stripped entries from normal ones */
	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
		qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
	memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
1725
	QETH_CARD_TEXT_(card, 4, "rc%i", 0);
F
Frank Blaschka 已提交
1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
	return 0;
out_error:
	i = 0;
	memcpy(qinfo->udata, &i, 4);
	return 0;
}

static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card,
		struct qeth_cmd_buffer *iob, int len,
		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
			unsigned long),
		void *reply_param)
{
C
Carsten Otte 已提交
1739
	QETH_CARD_TEXT(card, 4, "sendarp");
F
Frank Blaschka 已提交
1740 1741 1742 1743 1744 1745 1746 1747

	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
				      reply_cb, reply_param);
}

1748 1749 1750
static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
	enum qeth_prot_versions prot,
	struct qeth_arp_query_info *qinfo)
F
Frank Blaschka 已提交
1751 1752
{
	struct qeth_cmd_buffer *iob;
1753
	struct qeth_ipa_cmd *cmd;
F
Frank Blaschka 已提交
1754 1755 1756
	int tmp;
	int rc;

1757 1758
	QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot);

1759 1760 1761 1762 1763
	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
				       IPA_CMD_ASS_ARP_QUERY_INFO,
				       sizeof(struct qeth_arp_query_data)
						- sizeof(char),
				       prot);
1764 1765
	if (!iob)
		return -ENOMEM;
1766
	cmd = __ipa_cmd(iob);
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788
	cmd->data.setassparms.data.query_arp.request_bits = 0x000F;
	cmd->data.setassparms.data.query_arp.reply_bits = 0;
	cmd->data.setassparms.data.query_arp.no_entries = 0;
	rc = qeth_l3_send_ipa_arp_cmd(card, iob,
			   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
			   qeth_l3_arp_query_cb, (void *)qinfo);
	if (rc) {
		tmp = rc;
		QETH_DBF_MESSAGE(2,
			"Error while querying ARP cache on %s: %s "
			"(0x%x/%d)\n", QETH_CARD_IFNAME(card),
			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
	}

	return rc;
}

static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
{
	struct qeth_arp_query_info qinfo = {0, };
	int rc;

C
Carsten Otte 已提交
1789
	QETH_CARD_TEXT(card, 3, "arpquery");
F
Frank Blaschka 已提交
1790 1791 1792

	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
			       IPA_ARP_PROCESSING)) {
1793 1794 1795
		QETH_CARD_TEXT(card, 3, "arpqnsup");
		rc = -EOPNOTSUPP;
		goto out;
F
Frank Blaschka 已提交
1796 1797
	}
	/* get size of userspace buffer and mask_bits -> 6 bytes */
1798 1799 1800 1801
	if (copy_from_user(&qinfo, udata, 6)) {
		rc = -EFAULT;
		goto out;
	}
F
Frank Blaschka 已提交
1802
	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
1803 1804 1805 1806
	if (!qinfo.udata) {
		rc = -ENOMEM;
		goto out;
	}
F
Frank Blaschka 已提交
1807
	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
1808
	rc = qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV4, &qinfo);
F
Frank Blaschka 已提交
1809 1810 1811
	if (rc) {
		if (copy_to_user(udata, qinfo.udata, 4))
			rc = -EFAULT;
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
		goto free_and_out;
	}
	if (qinfo.mask_bits & QETH_QARP_WITH_IPV6) {
		/* fails in case of GuestLAN QDIO mode */
		qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV6, &qinfo);
	}
	if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) {
		QETH_CARD_TEXT(card, 4, "qactf");
		rc = -EFAULT;
		goto free_and_out;
F
Frank Blaschka 已提交
1822
	}
1823 1824
	QETH_CARD_TEXT(card, 4, "qacts");

1825
free_and_out:
F
Frank Blaschka 已提交
1826
	kfree(qinfo.udata);
1827
out:
F
Frank Blaschka 已提交
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838
	return rc;
}

static int qeth_l3_arp_add_entry(struct qeth_card *card,
				struct qeth_arp_cache_entry *entry)
{
	struct qeth_cmd_buffer *iob;
	char buf[16];
	int tmp;
	int rc;

C
Carsten Otte 已提交
1839
	QETH_CARD_TEXT(card, 3, "arpadent");
F
Frank Blaschka 已提交
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851

	/*
	 * currently GuestLAN only supports the ARP assist function
	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
	 * thus we say EOPNOTSUPP for this ARP function
	 */
	if (card->info.guestlan)
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}

1852
	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
F
Frank Blaschka 已提交
1853 1854 1855
				       IPA_CMD_ASS_ARP_ADD_ENTRY,
				       sizeof(struct qeth_arp_cache_entry),
				       QETH_PROT_IPV4);
1856 1857
	if (!iob)
		return -ENOMEM;
1858
	rc = qeth_send_setassparms(card, iob,
F
Frank Blaschka 已提交
1859 1860
				   sizeof(struct qeth_arp_cache_entry),
				   (unsigned long) entry,
1861
				   qeth_setassparms_cb, NULL);
F
Frank Blaschka 已提交
1862 1863 1864
	if (rc) {
		tmp = rc;
		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
1865 1866 1867
		QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s "
			"on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card),
			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
F
Frank Blaschka 已提交
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
	}
	return rc;
}

static int qeth_l3_arp_remove_entry(struct qeth_card *card,
				struct qeth_arp_cache_entry *entry)
{
	struct qeth_cmd_buffer *iob;
	char buf[16] = {0, };
	int tmp;
	int rc;

C
Carsten Otte 已提交
1880
	QETH_CARD_TEXT(card, 3, "arprment");
F
Frank Blaschka 已提交
1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892

	/*
	 * currently GuestLAN only supports the ARP assist function
	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
	 * thus we say EOPNOTSUPP for this ARP function
	 */
	if (card->info.guestlan)
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}
	memcpy(buf, entry, 12);
1893
	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
F
Frank Blaschka 已提交
1894 1895 1896
				       IPA_CMD_ASS_ARP_REMOVE_ENTRY,
				       12,
				       QETH_PROT_IPV4);
1897 1898
	if (!iob)
		return -ENOMEM;
1899
	rc = qeth_send_setassparms(card, iob,
F
Frank Blaschka 已提交
1900
				   12, (unsigned long)buf,
1901
				   qeth_setassparms_cb, NULL);
F
Frank Blaschka 已提交
1902 1903 1904 1905
	if (rc) {
		tmp = rc;
		memset(buf, 0, 16);
		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
1906 1907 1908
		QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s"
			" on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card),
			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
F
Frank Blaschka 已提交
1909 1910 1911 1912 1913 1914 1915 1916 1917
	}
	return rc;
}

static int qeth_l3_arp_flush_cache(struct qeth_card *card)
{
	int rc;
	int tmp;

C
Carsten Otte 已提交
1918
	QETH_CARD_TEXT(card, 3, "arpflush");
F
Frank Blaschka 已提交
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929

	/*
	 * currently GuestLAN only supports the ARP assist function
	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
	 * thus we say EOPNOTSUPP for this ARP function
	*/
	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}
1930
	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
F
Frank Blaschka 已提交
1931 1932 1933
					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
	if (rc) {
		tmp = rc;
1934 1935
		QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s "
			"(0x%x/%d)\n", QETH_CARD_IFNAME(card),
F
Frank Blaschka 已提交
1936 1937 1938 1939 1940 1941 1942
			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
	}
	return rc;
}

static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
1943
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
	struct qeth_arp_cache_entry arp_entry;
	int rc = 0;

	switch (cmd) {
	case SIOC_QETH_ARP_SET_NO_ENTRIES:
		if (!capable(CAP_NET_ADMIN)) {
			rc = -EPERM;
			break;
		}
		rc = qeth_l3_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
		break;
	case SIOC_QETH_ARP_QUERY_INFO:
		if (!capable(CAP_NET_ADMIN)) {
			rc = -EPERM;
			break;
		}
		rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
		break;
	case SIOC_QETH_ARP_ADD_ENTRY:
		if (!capable(CAP_NET_ADMIN)) {
			rc = -EPERM;
			break;
		}
		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
				   sizeof(struct qeth_arp_cache_entry)))
			rc = -EFAULT;
		else
			rc = qeth_l3_arp_add_entry(card, &arp_entry);
		break;
	case SIOC_QETH_ARP_REMOVE_ENTRY:
		if (!capable(CAP_NET_ADMIN)) {
			rc = -EPERM;
			break;
		}
		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
				   sizeof(struct qeth_arp_cache_entry)))
			rc = -EFAULT;
		else
			rc = qeth_l3_arp_remove_entry(card, &arp_entry);
		break;
	case SIOC_QETH_ARP_FLUSH_CACHE:
		if (!capable(CAP_NET_ADMIN)) {
			rc = -EPERM;
			break;
		}
		rc = qeth_l3_arp_flush_cache(card);
		break;
	default:
		rc = -EOPNOTSUPP;
	}
	return rc;
}

1997
static int qeth_l3_get_cast_type(struct sk_buff *skb)
1998
{
1999 2000 2001
	struct neighbour *n = NULL;
	struct dst_entry *dst;

F
Frank Blaschka 已提交
2002
	rcu_read_lock();
2003 2004
	dst = skb_dst(skb);
	if (dst)
2005
		n = dst_neigh_lookup_skb(dst, skb);
2006
	if (n) {
2007 2008
		int cast_type = n->type;

F
Frank Blaschka 已提交
2009
		rcu_read_unlock();
2010
		neigh_release(n);
2011 2012 2013 2014
		if ((cast_type == RTN_BROADCAST) ||
		    (cast_type == RTN_MULTICAST) ||
		    (cast_type == RTN_ANYCAST))
			return cast_type;
2015
		return RTN_UNSPEC;
2016
	}
F
Frank Blaschka 已提交
2017 2018
	rcu_read_unlock();

2019
	/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
2020
	if (be16_to_cpu(skb->protocol) == ETH_P_IPV6)
2021 2022
		return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
				RTN_MULTICAST : RTN_UNSPEC;
2023
	else if (be16_to_cpu(skb->protocol) == ETH_P_IP)
2024 2025 2026 2027
		return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
				RTN_MULTICAST : RTN_UNSPEC;

	/* ... and MAC address */
2028
	if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, skb->dev->broadcast))
2029
		return RTN_BROADCAST;
2030
	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
2031 2032 2033 2034
		return RTN_MULTICAST;

	/* default to unicast */
	return RTN_UNSPEC;
2035 2036
}

2037 2038 2039 2040 2041 2042 2043 2044 2045
static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
		struct qeth_hdr *hdr, struct sk_buff *skb)
{
	char daddr[16];
	struct af_iucv_trans_hdr *iucv_hdr;

	memset(hdr, 0, sizeof(struct qeth_hdr));
	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
	hdr->hdr.l3.ext_flags = 0;
2046
	hdr->hdr.l3.length = skb->len - ETH_HLEN;
2047
	hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
2048 2049

	iucv_hdr = (struct af_iucv_trans_hdr *) (skb->data + ETH_HLEN);
2050 2051 2052 2053
	memset(daddr, 0, sizeof(daddr));
	daddr[0] = 0xfe;
	daddr[1] = 0x80;
	memcpy(&daddr[8], iucv_hdr->destUserID, 8);
2054
	memcpy(hdr->hdr.l3.next_hop.ipv6_addr, daddr, 16);
2055 2056
}

2057
static u8 qeth_l3_cast_type_to_flag(int cast_type)
F
Frank Blaschka 已提交
2058
{
2059 2060 2061 2062 2063 2064 2065 2066
	if (cast_type == RTN_MULTICAST)
		return QETH_CAST_MULTICAST;
	if (cast_type == RTN_ANYCAST)
		return QETH_CAST_ANYCAST;
	if (cast_type == RTN_BROADCAST)
		return QETH_CAST_BROADCAST;
	return QETH_CAST_UNICAST;
}
2067

2068
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
2069 2070
				struct sk_buff *skb, int ipv, int cast_type,
				unsigned int data_len)
2071
{
F
Frank Blaschka 已提交
2072 2073
	memset(hdr, 0, sizeof(struct qeth_hdr));
	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
2074
	hdr->hdr.l3.length = data_len;
F
Frank Blaschka 已提交
2075 2076 2077 2078 2079

	/*
	 * before we're going to overwrite this location with next hop ip.
	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
	 */
2080
	if (skb_vlan_tag_present(skb)) {
2081 2082 2083 2084
		if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
			hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
		else
			hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG;
2085
		hdr->hdr.l3.vlan_id = skb_vlan_tag_get(skb);
F
Frank Blaschka 已提交
2086 2087
	}

2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098
	/* OSA only: */
	if (!ipv) {
		hdr->hdr.l3.flags = QETH_HDR_PASSTHRU;
		if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest,
					    skb->dev->broadcast))
			hdr->hdr.l3.flags |= QETH_CAST_BROADCAST;
		else
			hdr->hdr.l3.flags |= (cast_type == RTN_MULTICAST) ?
				QETH_CAST_MULTICAST : QETH_CAST_UNICAST;
		return;
	}
F
Frank Blaschka 已提交
2099

2100
	hdr->hdr.l3.flags = qeth_l3_cast_type_to_flag(cast_type);
F
Frank Blaschka 已提交
2101
	rcu_read_lock();
F
Frank Blaschka 已提交
2102
	if (ipv == 4) {
2103
		struct rtable *rt = skb_rtable(skb);
2104

2105 2106 2107 2108 2109 2110 2111
		*((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
				rt_nexthop(rt, ip_hdr(skb)->daddr) :
				ip_hdr(skb)->daddr;
	} else {
		/* IPv6 */
		const struct rt6_info *rt = skb_rt6_info(skb);
		const struct in6_addr *next_hop;
2112

2113
		if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
2114 2115 2116 2117
			next_hop = &rt->rt6i_gateway;
		else
			next_hop = &ipv6_hdr(skb)->daddr;
		memcpy(hdr->hdr.l3.next_hop.ipv6_addr, next_hop, 16);
2118

2119 2120 2121
		hdr->hdr.l3.flags |= QETH_HDR_IPV6;
		if (card->info.type != QETH_CARD_TYPE_IQD)
			hdr->hdr.l3.flags |= QETH_HDR_PASSTHRU;
F
Frank Blaschka 已提交
2122
	}
F
Frank Blaschka 已提交
2123
	rcu_read_unlock();
F
Frank Blaschka 已提交
2124 2125
}

J
Julian Wiedmann 已提交
2126 2127
static void qeth_l3_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr,
			     struct sk_buff *skb)
2128 2129 2130 2131 2132 2133 2134 2135
{
	struct iphdr *iph = ip_hdr(skb);

	/* tcph->check contains already the pseudo hdr checksum
	 * so just set the header flags
	 */
	if (iph->protocol == IPPROTO_UDP)
		hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP;
2136 2137 2138
	hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
		QETH_HDR_EXT_CSUM_HDR_REQ;
	iph->check = 0;
2139 2140 2141 2142
	if (card->options.performance_stats)
		card->perf_stats.tx_csum++;
}

F
Frank Blaschka 已提交
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160
static void qeth_tso_fill_header(struct qeth_card *card,
		struct qeth_hdr *qhdr, struct sk_buff *skb)
{
	struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr;
	struct tcphdr *tcph = tcp_hdr(skb);
	struct iphdr *iph = ip_hdr(skb);
	struct ipv6hdr *ip6h = ipv6_hdr(skb);

	/*fix header to TSO values ...*/
	hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
	/*set values which are fix for the first approach ...*/
	hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
	hdr->ext.imb_hdr_no  = 1;
	hdr->ext.hdr_type    = 1;
	hdr->ext.hdr_version = 1;
	hdr->ext.hdr_len     = 28;
	/*insert non-fix values */
	hdr->ext.mss = skb_shinfo(skb)->gso_size;
2161
	hdr->ext.dg_hdr_len = (__u16)(ip_hdrlen(skb) + tcp_hdrlen(skb));
F
Frank Blaschka 已提交
2162 2163 2164
	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
				       sizeof(struct qeth_hdr_tso));
	tcph->check = 0;
2165
	if (be16_to_cpu(skb->protocol) == ETH_P_IPV6) {
F
Frank Blaschka 已提交
2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177
		ip6h->payload_len = 0;
		tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
					       0, IPPROTO_TCP, 0);
	} else {
		/*OSA want us to set these values ...*/
		tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
					 0, IPPROTO_TCP, 0);
		iph->tot_len = 0;
		iph->check = 0;
	}
}

2178
/**
2179 2180 2181 2182
 * qeth_l3_get_elements_no_tso() - find number of SBALEs for skb data for tso
 * @card:			   qeth card structure, to check max. elems.
 * @skb:			   SKB address
 * @extra_elems:		   extra elems needed, to check against max.
2183 2184 2185 2186 2187 2188 2189 2190
 *
 * Returns the number of pages, and thus QDIO buffer elements, needed to cover
 * skb data, including linear part and fragments, but excluding TCP header.
 * (Exclusion of TCP header distinguishes it from qeth_get_elements_no().)
 * Checks if the result plus extra_elems fits under the limit for the card.
 * Returns 0 if it does not.
 * Note: extra_elems is not included in the returned result.
 */
2191
static int qeth_l3_get_elements_no_tso(struct qeth_card *card,
2192
			struct sk_buff *skb, int extra_elems)
F
Frank Blaschka 已提交
2193
{
2194 2195 2196 2197 2198 2199
	addr_t start = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb);
	addr_t end = (addr_t)skb->data + skb_headlen(skb);
	int elements = qeth_get_elements_for_frags(skb);

	if (start != end)
		elements += qeth_get_elements_for_range(start, end);
2200

2201 2202 2203 2204 2205 2206
	if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
		QETH_DBF_MESSAGE(2,
	"Invalid size of TSO IP packet (Number=%d / Length=%d). Discarded.\n",
				elements + extra_elems, skb->len);
		return 0;
	}
F
Frank Blaschka 已提交
2207 2208 2209
	return elements;
}

2210 2211
static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
					   struct net_device *dev)
F
Frank Blaschka 已提交
2212 2213
{
	int rc;
2214
	__be16 *tag;
F
Frank Blaschka 已提交
2215
	struct qeth_hdr *hdr = NULL;
2216 2217
	int hdr_elements = 0;
	int elements;
2218
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
2219 2220
	struct sk_buff *new_skb = NULL;
	int ipv = qeth_get_ip_version(skb);
2221
	int cast_type = qeth_l3_get_cast_type(skb);
2222 2223 2224 2225 2226
	struct qeth_qdio_out_q *queue =
		card->qdio.out_qs[card->qdio.do_prio_queueing
			|| (cast_type && card->info.is_multicast_different) ?
			qeth_get_priority_queue(card, skb, ipv, cast_type) :
			card->qdio.default_out_queue];
F
Frank Blaschka 已提交
2227
	int tx_bytes = skb->len;
2228
	unsigned int hd_len = 0;
2229
	bool use_tso;
2230
	int data_offset = -1;
2231
	unsigned int nr_frags;
F
Frank Blaschka 已提交
2232

2233 2234 2235
	if (((card->info.type == QETH_CARD_TYPE_IQD) &&
	     (((card->options.cq != QETH_CQ_ENABLED) && !ipv) ||
	      ((card->options.cq == QETH_CQ_ENABLED) &&
2236
	       (be16_to_cpu(skb->protocol) != ETH_P_AF_IUCV)))) ||
2237
	    card->options.sniffer)
F
Frank Blaschka 已提交
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253
			goto tx_drop;

	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
		card->stats.tx_carrier_errors++;
		goto tx_drop;
	}

	if ((cast_type == RTN_BROADCAST) &&
	    (card->info.broadcast_capable == 0))
		goto tx_drop;

	if (card->options.performance_stats) {
		card->perf_stats.outbound_cnt++;
		card->perf_stats.outbound_start_time = qeth_get_micros();
	}

2254 2255
	/* Ignore segment size from skb_is_gso(), 1 page is always used. */
	use_tso = skb_is_gso(skb) &&
2256
		  (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4);
2257

2258
	if (card->info.type == QETH_CARD_TYPE_IQD) {
2259
		new_skb = skb;
2260
		data_offset = ETH_HLEN;
2261
		hd_len = sizeof(*hdr);
2262 2263 2264
		hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
		if (!hdr)
			goto tx_drop;
2265
		hdr_elements++;
2266 2267 2268 2269 2270 2271
	} else {
		/* create a clone with writeable headroom */
		new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)
					+ VLAN_HLEN);
		if (!new_skb)
			goto tx_drop;
F
Frank Blaschka 已提交
2272

2273
		if (ipv == 4) {
2274
			skb_pull(new_skb, ETH_HLEN);
F
Frank Blaschka 已提交
2275 2276
		}

2277
		if (ipv != 4 && skb_vlan_tag_present(new_skb)) {
F
Frank Blaschka 已提交
2278 2279 2280 2281 2282 2283
			skb_push(new_skb, VLAN_HLEN);
			skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
			skb_copy_to_linear_data_offset(new_skb, 4,
				new_skb->data + 8, 4);
			skb_copy_to_linear_data_offset(new_skb, 8,
				new_skb->data + 12, 4);
2284 2285 2286
			tag = (__be16 *)(new_skb->data + 12);
			*tag = cpu_to_be16(ETH_P_8021Q);
			*(tag + 1) = cpu_to_be16(skb_vlan_tag_get(new_skb));
F
Frank Blaschka 已提交
2287 2288 2289 2290 2291 2292
		}
	}

	netif_stop_queue(dev);

	/* fix hardware limitation: as long as we do not have sbal
F
Frank Blaschka 已提交
2293
	 * chaining we can not send long frag lists
F
Frank Blaschka 已提交
2294
	 */
2295 2296
	if ((card->info.type != QETH_CARD_TYPE_IQD) &&
	    ((use_tso && !qeth_l3_get_elements_no_tso(card, new_skb, 1)) ||
2297
	     (!use_tso && !qeth_get_elements_no(card, new_skb, 0, 0)))) {
2298 2299 2300 2301 2302 2303 2304 2305 2306
		int lin_rc = skb_linearize(new_skb);

		if (card->options.performance_stats) {
			if (lin_rc)
				card->perf_stats.tx_linfail++;
			else
				card->perf_stats.tx_lin++;
		}
		if (lin_rc)
2307
			goto tx_drop;
F
Frank Blaschka 已提交
2308
	}
2309
	nr_frags = skb_shinfo(new_skb)->nr_frags;
F
Frank Blaschka 已提交
2310

2311
	if (use_tso) {
2312
		hdr = skb_push(new_skb, sizeof(struct qeth_hdr_tso));
F
Frank Blaschka 已提交
2313
		memset(hdr, 0, sizeof(struct qeth_hdr_tso));
2314 2315
		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type,
				    new_skb->len - sizeof(struct qeth_hdr_tso));
F
Frank Blaschka 已提交
2316
		qeth_tso_fill_header(card, hdr, new_skb);
2317
		hdr_elements++;
F
Frank Blaschka 已提交
2318
	} else {
2319
		if (data_offset < 0) {
2320
			hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
2321 2322 2323
			qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type,
					    new_skb->len -
					    sizeof(struct qeth_hdr));
2324
		} else {
2325
			if (be16_to_cpu(new_skb->protocol) == ETH_P_AF_IUCV)
2326 2327 2328
				qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb);
			else {
				qeth_l3_fill_header(card, hdr, new_skb, ipv,
2329 2330
						    cast_type,
						    new_skb->len - data_offset);
2331
			}
2332
		}
2333 2334 2335

		if (skb->ip_summed == CHECKSUM_PARTIAL)
			qeth_l3_hdr_csum(card, hdr, new_skb);
F
Frank Blaschka 已提交
2336 2337
	}

2338 2339
	elements = use_tso ?
		   qeth_l3_get_elements_no_tso(card, new_skb, hdr_elements) :
2340 2341
		   qeth_get_elements_no(card, new_skb, hdr_elements,
					(data_offset > 0) ? data_offset : 0);
2342
	if (!elements) {
F
Frank Blaschka 已提交
2343 2344 2345
		if (data_offset >= 0)
			kmem_cache_free(qeth_core_header_cache, hdr);
		goto tx_drop;
2346
	}
2347
	elements += hdr_elements;
F
Frank Blaschka 已提交
2348

2349 2350
	if (card->info.type != QETH_CARD_TYPE_IQD) {
		int len;
2351 2352 2353 2354 2355
		if (use_tso) {
			hd_len = sizeof(struct qeth_hdr_tso) +
				 ip_hdrlen(new_skb) + tcp_hdrlen(new_skb);
			len = hd_len;
		} else {
2356
			len = sizeof(struct qeth_hdr_layer3);
2357
		}
2358

S
Stefan Raspl 已提交
2359
		if (qeth_hdr_chk_and_bounce(new_skb, &hdr, len))
2360
			goto tx_drop;
2361
		rc = qeth_do_send_packet(card, queue, new_skb, hdr, hd_len,
2362
					 hd_len, elements);
2363
	} else
2364 2365
		rc = qeth_do_send_packet_fast(queue, new_skb, hdr, data_offset,
					      hd_len);
F
Frank Blaschka 已提交
2366 2367 2368 2369 2370 2371 2372

	if (!rc) {
		card->stats.tx_packets++;
		card->stats.tx_bytes += tx_bytes;
		if (new_skb != skb)
			dev_kfree_skb_any(skb);
		if (card->options.performance_stats) {
2373
			if (use_tso) {
F
Frank Blaschka 已提交
2374 2375 2376
				card->perf_stats.large_send_bytes += tx_bytes;
				card->perf_stats.large_send_cnt++;
			}
F
Frank Blaschka 已提交
2377
			if (nr_frags) {
F
Frank Blaschka 已提交
2378 2379
				card->perf_stats.sg_skbs_sent++;
				/* nr_frags + skb->data */
F
Frank Blaschka 已提交
2380
				card->perf_stats.sg_frags_sent += nr_frags + 1;
F
Frank Blaschka 已提交
2381 2382
			}
		}
2383
		rc = NETDEV_TX_OK;
F
Frank Blaschka 已提交
2384
	} else {
2385 2386 2387
		if (data_offset >= 0)
			kmem_cache_free(qeth_core_header_cache, hdr);

F
Frank Blaschka 已提交
2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407
		if (rc == -EBUSY) {
			if (new_skb != skb)
				dev_kfree_skb_any(new_skb);
			return NETDEV_TX_BUSY;
		} else
			goto tx_drop;
	}

	netif_wake_queue(dev);
	if (card->options.performance_stats)
		card->perf_stats.outbound_time += qeth_get_micros() -
			card->perf_stats.outbound_start_time;
	return rc;

tx_drop:
	card->stats.tx_dropped++;
	card->stats.tx_errors++;
	if ((new_skb != skb) && new_skb)
		dev_kfree_skb_any(new_skb);
	dev_kfree_skb_any(skb);
2408
	netif_wake_queue(dev);
F
Frank Blaschka 已提交
2409 2410 2411
	return NETDEV_TX_OK;
}

2412
static int __qeth_l3_open(struct net_device *dev)
F
Frank Blaschka 已提交
2413
{
2414
	struct qeth_card *card = dev->ml_priv;
2415
	int rc = 0;
F
Frank Blaschka 已提交
2416

C
Carsten Otte 已提交
2417
	QETH_CARD_TEXT(card, 4, "qethopen");
2418 2419
	if (card->state == CARD_STATE_UP)
		return rc;
F
Frank Blaschka 已提交
2420 2421 2422 2423 2424 2425
	if (card->state != CARD_STATE_SOFTSETUP)
		return -ENODEV;
	card->data.state = CH_STATE_UP;
	card->state = CARD_STATE_UP;
	netif_start_queue(dev);

2426 2427 2428 2429 2430 2431
	if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
		napi_enable(&card->napi);
		napi_schedule(&card->napi);
	} else
		rc = -EIO;
	return rc;
F
Frank Blaschka 已提交
2432 2433
}

2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
static int qeth_l3_open(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	QETH_CARD_TEXT(card, 5, "qethope_");
	if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
		QETH_CARD_TEXT(card, 3, "openREC");
		return -ERESTARTSYS;
	}
	return __qeth_l3_open(dev);
}

F
Frank Blaschka 已提交
2446 2447
static int qeth_l3_stop(struct net_device *dev)
{
2448
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
2449

C
Carsten Otte 已提交
2450
	QETH_CARD_TEXT(card, 4, "qethstop");
F
Frank Blaschka 已提交
2451
	netif_tx_disable(dev);
2452
	if (card->state == CARD_STATE_UP) {
F
Frank Blaschka 已提交
2453
		card->state = CARD_STATE_SOFTSETUP;
2454 2455
		napi_disable(&card->napi);
	}
F
Frank Blaschka 已提交
2456 2457 2458
	return 0;
}

2459
static const struct ethtool_ops qeth_l3_ethtool_ops = {
F
Frank Blaschka 已提交
2460 2461 2462
	.get_link = ethtool_op_get_link,
	.get_strings = qeth_core_get_strings,
	.get_ethtool_stats = qeth_core_get_ethtool_stats,
2463
	.get_sset_count = qeth_core_get_sset_count,
F
Frank Blaschka 已提交
2464
	.get_drvinfo = qeth_core_get_drvinfo,
2465
	.get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
F
Frank Blaschka 已提交
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491
};

/*
 * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
 * NOARP on the netdevice is no option because it also turns off neighbor
 * solicitation. For IPv4 we install a neighbor_setup function. We don't want
 * arp resolution but we want the hard header (packet socket will work
 * e.g. tcpdump)
 */
static int qeth_l3_neigh_setup_noarp(struct neighbour *n)
{
	n->nud_state = NUD_NOARP;
	memcpy(n->ha, "FAKELL", 6);
	n->output = n->ops->connected_output;
	return 0;
}

static int
qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
{
	if (np->tbl->family == AF_INET)
		np->neigh_setup = qeth_l3_neigh_setup_noarp;

	return 0;
}

F
Frank Blaschka 已提交
2492
static const struct net_device_ops qeth_l3_netdev_ops = {
F
Frank Blaschka 已提交
2493 2494 2495 2496 2497
	.ndo_open		= qeth_l3_open,
	.ndo_stop		= qeth_l3_stop,
	.ndo_get_stats		= qeth_get_stats,
	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
	.ndo_validate_addr	= eth_validate_addr,
2498
	.ndo_set_rx_mode	= qeth_l3_set_rx_mode,
2499
	.ndo_do_ioctl		= qeth_do_ioctl,
J
Jiri Pirko 已提交
2500
	.ndo_change_mtu		= qeth_change_mtu,
2501 2502
	.ndo_fix_features	= qeth_fix_features,
	.ndo_set_features	= qeth_set_features,
F
Frank Blaschka 已提交
2503 2504
	.ndo_vlan_rx_add_vid	= qeth_l3_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid   = qeth_l3_vlan_rx_kill_vid,
J
Jiri Pirko 已提交
2505
	.ndo_tx_timeout		= qeth_tx_timeout,
F
Frank Blaschka 已提交
2506 2507
};

F
Frank Blaschka 已提交
2508 2509 2510 2511 2512
static const struct net_device_ops qeth_l3_osa_netdev_ops = {
	.ndo_open		= qeth_l3_open,
	.ndo_stop		= qeth_l3_stop,
	.ndo_get_stats		= qeth_get_stats,
	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
2513
	.ndo_features_check	= qeth_features_check,
F
Frank Blaschka 已提交
2514
	.ndo_validate_addr	= eth_validate_addr,
2515
	.ndo_set_rx_mode	= qeth_l3_set_rx_mode,
2516
	.ndo_do_ioctl		= qeth_do_ioctl,
J
Jiri Pirko 已提交
2517
	.ndo_change_mtu		= qeth_change_mtu,
2518 2519
	.ndo_fix_features	= qeth_fix_features,
	.ndo_set_features	= qeth_set_features,
F
Frank Blaschka 已提交
2520 2521
	.ndo_vlan_rx_add_vid	= qeth_l3_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid   = qeth_l3_vlan_rx_kill_vid,
J
Jiri Pirko 已提交
2522
	.ndo_tx_timeout		= qeth_tx_timeout,
F
Frank Blaschka 已提交
2523 2524 2525
	.ndo_neigh_setup	= qeth_l3_neigh_setup,
};

F
Frank Blaschka 已提交
2526 2527
static int qeth_l3_setup_netdev(struct qeth_card *card)
{
2528 2529
	int rc;

2530 2531
	if (card->info.type == QETH_CARD_TYPE_OSD ||
	    card->info.type == QETH_CARD_TYPE_OSX) {
F
Frank Blaschka 已提交
2532 2533
		if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
		    (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
2534 2535
			pr_info("qeth_l3: ignoring TR device\n");
			return -ENODEV;
F
Frank Blaschka 已提交
2536 2537 2538 2539
		} else {
			card->dev = alloc_etherdev(0);
			if (!card->dev)
				return -ENODEV;
F
Frank Blaschka 已提交
2540
			card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
F
Frank Blaschka 已提交
2541 2542 2543 2544 2545 2546

			/*IPv6 address autoconfiguration stuff*/
			qeth_l3_get_unique_id(card);
			if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
				card->dev->dev_id = card->info.unique_id &
							 0xffff;
2547 2548 2549 2550

			card->dev->hw_features |= NETIF_F_SG;
			card->dev->vlan_features |= NETIF_F_SG;

2551
			if (!card->info.guestlan) {
2552
				card->dev->features |= NETIF_F_SG;
2553 2554 2555 2556
				card->dev->hw_features |= NETIF_F_TSO |
					NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
				card->dev->vlan_features |= NETIF_F_TSO |
					NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
2557
			}
F
Frank Blaschka 已提交
2558 2559
		}
	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
2560 2561
		card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
					 ether_setup);
F
Frank Blaschka 已提交
2562 2563 2564
		if (!card->dev)
			return -ENODEV;
		card->dev->flags |= IFF_NOARP;
F
Frank Blaschka 已提交
2565
		card->dev->netdev_ops = &qeth_l3_netdev_ops;
2566 2567 2568
		rc = qeth_l3_iqd_read_initial_mac(card);
		if (rc)
			return rc;
2569 2570
		if (card->options.hsuid[0])
			memcpy(card->dev->perm_addr, card->options.hsuid, 9);
F
Frank Blaschka 已提交
2571 2572 2573
	} else
		return -ENODEV;

2574
	card->dev->ml_priv = card;
F
Frank Blaschka 已提交
2575 2576
	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
	card->dev->mtu = card->info.initial_mtu;
2577 2578
	card->dev->min_mtu = 64;
	card->dev->max_mtu = ETH_MAX_MTU;
2579
	card->dev->dev_port = card->info.portno;
2580
	card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
2581 2582 2583
	card->dev->features |=	NETIF_F_HW_VLAN_CTAG_TX |
				NETIF_F_HW_VLAN_CTAG_RX |
				NETIF_F_HW_VLAN_CTAG_FILTER;
2584
	netif_keep_dst(card->dev);
2585 2586
	netif_set_gso_max_size(card->dev, (QETH_MAX_BUFFER_ELEMENTS(card) - 1) *
					  PAGE_SIZE);
F
Frank Blaschka 已提交
2587 2588

	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
2589
	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
2590
	netif_carrier_off(card->dev);
F
Frank Blaschka 已提交
2591 2592 2593
	return register_netdev(card->dev);
}

2594 2595 2596 2597 2598
static const struct device_type qeth_l3_devtype = {
	.name = "qeth_layer3",
	.groups = qeth_l3_attr_groups,
};

F
Frank Blaschka 已提交
2599 2600 2601
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
2602
	int rc;
F
Frank Blaschka 已提交
2603

2604 2605 2606 2607 2608
	if (gdev->dev.type == &qeth_generic_devtype) {
		rc = qeth_l3_create_device_attributes(&gdev->dev);
		if (rc)
			return rc;
	}
2609 2610
	hash_init(card->ip_htable);
	hash_init(card->ip_mc_htable);
F
Frank Blaschka 已提交
2611
	card->options.layer2 = 0;
2612
	card->info.hwtrap = 0;
F
Frank Blaschka 已提交
2613 2614 2615 2616 2617 2618 2619
	return 0;
}

static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
{
	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);

2620 2621
	if (cgdev->dev.type == &qeth_generic_devtype)
		qeth_l3_remove_device_attributes(&cgdev->dev);
2622

2623
	qeth_set_allowed_threads(card, 0, 1);
F
Frank Blaschka 已提交
2624 2625
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);

2626
	if (cgdev->state == CCWGROUP_ONLINE)
F
Frank Blaschka 已提交
2627 2628 2629 2630
		qeth_l3_set_offline(cgdev);

	if (card->dev) {
		unregister_netdev(card->dev);
2631
		free_netdev(card->dev);
F
Frank Blaschka 已提交
2632 2633 2634
		card->dev = NULL;
	}

2635
	qeth_l3_clear_ip_htable(card, 0);
F
Frank Blaschka 已提交
2636 2637 2638 2639 2640 2641 2642 2643 2644 2645
	qeth_l3_clear_ipato_list(card);
	return;
}

static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	int rc = 0;
	enum qeth_card_states recover_flag;

2646
	mutex_lock(&card->discipline_mutex);
2647
	mutex_lock(&card->conf_mutex);
2648 2649
	QETH_DBF_TEXT(SETUP, 2, "setonlin");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
F
Frank Blaschka 已提交
2650 2651 2652 2653

	recover_flag = card->state;
	rc = qeth_core_hardsetup_card(card);
	if (rc) {
2654
		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
2655
		rc = -ENODEV;
F
Frank Blaschka 已提交
2656 2657 2658
		goto out_remove;
	}

2659 2660
	if (!card->dev && qeth_l3_setup_netdev(card)) {
		rc = -ENODEV;
F
Frank Blaschka 已提交
2661
		goto out_remove;
2662
	}
F
Frank Blaschka 已提交
2663

2664 2665 2666 2667 2668 2669 2670
	if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
		if (card->info.hwtrap &&
		    qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
			card->info.hwtrap = 0;
	} else
		card->info.hwtrap = 0;

F
Frank Blaschka 已提交
2671 2672 2673 2674
	card->state = CARD_STATE_HARDSETUP;
	qeth_print_status_message(card);

	/* softsetup */
2675
	QETH_DBF_TEXT(SETUP, 2, "softsetp");
F
Frank Blaschka 已提交
2676 2677 2678

	rc = qeth_l3_setadapter_parms(card);
	if (rc)
2679
		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
2680 2681
	if (!card->options.sniffer) {
		rc = qeth_l3_start_ipassists(card);
S
Stefan Raspl 已提交
2682
		if (rc) {
2683
			QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
S
Stefan Raspl 已提交
2684 2685
			goto out_remove;
		}
2686 2687
		rc = qeth_l3_setrouting_v4(card);
		if (rc)
2688
			QETH_DBF_TEXT_(SETUP, 2, "4err%04x", rc);
2689 2690
		rc = qeth_l3_setrouting_v6(card);
		if (rc)
2691
			QETH_DBF_TEXT_(SETUP, 2, "5err%04x", rc);
2692
	}
F
Frank Blaschka 已提交
2693 2694 2695 2696
	netif_tx_disable(card->dev);

	rc = qeth_init_qdio_queues(card);
	if (rc) {
2697
		QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
2698
		rc = -ENODEV;
F
Frank Blaschka 已提交
2699 2700 2701 2702 2703
		goto out_remove;
	}
	card->state = CARD_STATE_SOFTSETUP;

	qeth_set_allowed_threads(card, 0xffffffff, 0);
2704
	qeth_l3_recover_ip(card);
2705 2706 2707 2708
	if (card->lan_online)
		netif_carrier_on(card->dev);
	else
		netif_carrier_off(card->dev);
2709
	if (recover_flag == CARD_STATE_RECOVER) {
2710
		rtnl_lock();
2711
		if (recovery_mode)
2712
			__qeth_l3_open(card->dev);
2713
		else
2714
			dev_open(card->dev);
2715
		qeth_l3_set_rx_mode(card->dev);
2716
		qeth_recover_features(card->dev);
2717
		rtnl_unlock();
F
Frank Blaschka 已提交
2718
	}
S
Stefan Raspl 已提交
2719
	qeth_trace_features(card);
F
Frank Blaschka 已提交
2720 2721
	/* let user_space know that device is online */
	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
2722
	mutex_unlock(&card->conf_mutex);
2723
	mutex_unlock(&card->discipline_mutex);
F
Frank Blaschka 已提交
2724 2725 2726 2727 2728 2729
	return 0;
out_remove:
	qeth_l3_stop_card(card, 0);
	ccw_device_set_offline(CARD_DDEV(card));
	ccw_device_set_offline(CARD_WDEV(card));
	ccw_device_set_offline(CARD_RDEV(card));
2730
	qdio_free(CARD_DDEV(card));
F
Frank Blaschka 已提交
2731 2732 2733 2734
	if (recover_flag == CARD_STATE_RECOVER)
		card->state = CARD_STATE_RECOVER;
	else
		card->state = CARD_STATE_DOWN;
2735
	mutex_unlock(&card->conf_mutex);
2736
	mutex_unlock(&card->discipline_mutex);
2737
	return rc;
F
Frank Blaschka 已提交
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751
}

static int qeth_l3_set_online(struct ccwgroup_device *gdev)
{
	return __qeth_l3_set_online(gdev, 0);
}

static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
			int recovery_mode)
{
	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
	int rc = 0, rc2 = 0, rc3 = 0;
	enum qeth_card_states recover_flag;

2752
	mutex_lock(&card->discipline_mutex);
2753
	mutex_lock(&card->conf_mutex);
2754 2755
	QETH_DBF_TEXT(SETUP, 3, "setoffl");
	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
F
Frank Blaschka 已提交
2756 2757 2758 2759

	if (card->dev && netif_carrier_ok(card->dev))
		netif_carrier_off(card->dev);
	recover_flag = card->state;
2760 2761 2762 2763
	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}
2764
	qeth_l3_stop_card(card, recovery_mode);
2765 2766 2767 2768 2769
	if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) {
		rtnl_lock();
		call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
		rtnl_unlock();
	}
F
Frank Blaschka 已提交
2770 2771 2772 2773 2774 2775
	rc  = ccw_device_set_offline(CARD_DDEV(card));
	rc2 = ccw_device_set_offline(CARD_WDEV(card));
	rc3 = ccw_device_set_offline(CARD_RDEV(card));
	if (!rc)
		rc = (rc2) ? rc2 : rc3;
	if (rc)
2776
		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
2777
	qdio_free(CARD_DDEV(card));
F
Frank Blaschka 已提交
2778 2779 2780 2781
	if (recover_flag == CARD_STATE_UP)
		card->state = CARD_STATE_RECOVER;
	/* let user_space know that device is offline */
	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
2782
	mutex_unlock(&card->conf_mutex);
2783
	mutex_unlock(&card->discipline_mutex);
F
Frank Blaschka 已提交
2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
	return 0;
}

static int qeth_l3_set_offline(struct ccwgroup_device *cgdev)
{
	return __qeth_l3_set_offline(cgdev, 0);
}

static int qeth_l3_recover(void *ptr)
{
	struct qeth_card *card;
	int rc = 0;

	card = (struct qeth_card *) ptr;
C
Carsten Otte 已提交
2798 2799
	QETH_CARD_TEXT(card, 2, "recover1");
	QETH_CARD_HEX(card, 2, &card, sizeof(void *));
F
Frank Blaschka 已提交
2800 2801
	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
		return 0;
C
Carsten Otte 已提交
2802
	QETH_CARD_TEXT(card, 2, "recover2");
2803 2804
	dev_warn(&card->gdev->dev,
		"A recovery process has been started for the device\n");
2805
	qeth_set_recovery_task(card);
F
Frank Blaschka 已提交
2806 2807 2808
	__qeth_l3_set_offline(card->gdev, 1);
	rc = __qeth_l3_set_online(card->gdev, 1);
	if (!rc)
2809 2810
		dev_info(&card->gdev->dev,
			"Device successfully recovered!\n");
2811
	else {
S
Stefan Raspl 已提交
2812 2813
		qeth_close_dev(card);
		dev_warn(&card->gdev->dev, "The qeth device driver "
2814
				"failed to recover an error on the device\n");
2815
	}
2816
	qeth_clear_recovery_task(card);
2817 2818
	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
F
Frank Blaschka 已提交
2819 2820 2821
	return 0;
}

2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832
static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);

	if (card->dev)
		netif_device_detach(card->dev);
	qeth_set_allowed_threads(card, 0, 1);
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
	if (gdev->state == CCWGROUP_OFFLINE)
		return 0;
	if (card->state == CARD_STATE_UP) {
2833 2834
		if (card->info.hwtrap)
			qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851
		__qeth_l3_set_offline(card->gdev, 1);
	} else
		__qeth_l3_set_offline(card->gdev, 0);
	return 0;
}

static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	int rc = 0;

	if (gdev->state == CCWGROUP_OFFLINE)
		goto out;

	if (card->state == CARD_STATE_RECOVER) {
		rc = __qeth_l3_set_online(card->gdev, 1);
		if (rc) {
2852 2853 2854
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867
		}
	} else
		rc = __qeth_l3_set_online(card->gdev, 0);
out:
	qeth_set_allowed_threads(card, 0xffffffff, 0);
	if (card->dev)
		netif_device_attach(card->dev);
	if (rc)
		dev_warn(&card->gdev->dev, "The qeth device driver "
			"failed to recover an error on the device\n");
	return rc;
}

2868 2869 2870 2871 2872 2873 2874
/* Returns zero if the command is successfully "consumed" */
static int qeth_l3_control_event(struct qeth_card *card,
					struct qeth_ipa_cmd *cmd)
{
	return 1;
}

2875
struct qeth_discipline qeth_l3_discipline = {
2876
	.devtype = &qeth_l3_devtype,
2877
	.process_rx_buffer = qeth_l3_process_inbound_buffer,
2878 2879
	.recover = qeth_l3_recover,
	.setup = qeth_l3_probe_device,
F
Frank Blaschka 已提交
2880 2881 2882
	.remove = qeth_l3_remove_device,
	.set_online = qeth_l3_set_online,
	.set_offline = qeth_l3_set_offline,
2883 2884 2885
	.freeze = qeth_l3_pm_suspend,
	.thaw = qeth_l3_pm_resume,
	.restore = qeth_l3_pm_resume,
2886
	.do_ioctl = qeth_l3_do_ioctl,
2887
	.control_event_handler = qeth_l3_control_event,
F
Frank Blaschka 已提交
2888
};
2889
EXPORT_SYMBOL_GPL(qeth_l3_discipline);
F
Frank Blaschka 已提交
2890

2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910
static int qeth_l3_handle_ip_event(struct qeth_card *card,
				   struct qeth_ipaddr *addr,
				   unsigned long event)
{
	switch (event) {
	case NETDEV_UP:
		spin_lock_bh(&card->ip_lock);
		qeth_l3_add_ip(card, addr);
		spin_unlock_bh(&card->ip_lock);
		return NOTIFY_OK;
	case NETDEV_DOWN:
		spin_lock_bh(&card->ip_lock);
		qeth_l3_delete_ip(card, addr);
		spin_unlock_bh(&card->ip_lock);
		return NOTIFY_OK;
	default:
		return NOTIFY_DONE;
	}
}

2911 2912 2913 2914 2915 2916 2917 2918 2919 2920
static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
{
	if (is_vlan_dev(dev))
		dev = vlan_dev_real_dev(dev);
	if (dev->netdev_ops == &qeth_l3_osa_netdev_ops ||
	    dev->netdev_ops == &qeth_l3_netdev_ops)
		return (struct qeth_card *) dev->ml_priv;
	return NULL;
}

F
Frank Blaschka 已提交
2921
static int qeth_l3_ip_event(struct notifier_block *this,
2922
			    unsigned long event, void *ptr)
F
Frank Blaschka 已提交
2923
{
2924

F
Frank Blaschka 已提交
2925
	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
2926
	struct net_device *dev = ifa->ifa_dev->dev;
2927
	struct qeth_ipaddr addr;
F
Frank Blaschka 已提交
2928 2929
	struct qeth_card *card;

2930
	if (dev_net(dev) != &init_net)
2931 2932
		return NOTIFY_DONE;

F
Frank Blaschka 已提交
2933 2934 2935
	card = qeth_l3_get_card_from_dev(dev);
	if (!card)
		return NOTIFY_DONE;
2936
	QETH_CARD_TEXT(card, 3, "ipevent");
F
Frank Blaschka 已提交
2937

2938 2939 2940
	qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4);
	addr.u.a4.addr = be32_to_cpu(ifa->ifa_address);
	addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask);
2941

2942
	return qeth_l3_handle_ip_event(card, &addr, event);
F
Frank Blaschka 已提交
2943 2944 2945 2946 2947 2948 2949 2950
}

static struct notifier_block qeth_l3_ip_notifier = {
	qeth_l3_ip_event,
	NULL,
};

static int qeth_l3_ip6_event(struct notifier_block *this,
2951
			     unsigned long event, void *ptr)
F
Frank Blaschka 已提交
2952 2953
{
	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
2954
	struct net_device *dev = ifa->idev->dev;
2955
	struct qeth_ipaddr addr;
F
Frank Blaschka 已提交
2956 2957 2958 2959 2960
	struct qeth_card *card;

	card = qeth_l3_get_card_from_dev(dev);
	if (!card)
		return NOTIFY_DONE;
C
Carsten Otte 已提交
2961
	QETH_CARD_TEXT(card, 3, "ip6event");
F
Frank Blaschka 已提交
2962 2963 2964
	if (!qeth_is_supported(card, IPA_IPV6))
		return NOTIFY_DONE;

2965 2966 2967
	qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV6);
	addr.u.a6.addr = ifa->addr;
	addr.u.a6.pfxlen = ifa->prefix_len;
2968

2969
	return qeth_l3_handle_ip_event(card, &addr, event);
F
Frank Blaschka 已提交
2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
}

static struct notifier_block qeth_l3_ip6_notifier = {
	qeth_l3_ip6_event,
	NULL,
};

static int qeth_l3_register_notifiers(void)
{
	int rc;

C
Carsten Otte 已提交
2981
	QETH_DBF_TEXT(SETUP, 5, "regnotif");
F
Frank Blaschka 已提交
2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994
	rc = register_inetaddr_notifier(&qeth_l3_ip_notifier);
	if (rc)
		return rc;
	rc = register_inet6addr_notifier(&qeth_l3_ip6_notifier);
	if (rc) {
		unregister_inetaddr_notifier(&qeth_l3_ip_notifier);
		return rc;
	}
	return 0;
}

static void qeth_l3_unregister_notifiers(void)
{
C
Carsten Otte 已提交
2995
	QETH_DBF_TEXT(SETUP, 5, "unregnot");
S
Stefan Raspl 已提交
2996 2997
	WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
	WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
F
Frank Blaschka 已提交
2998 2999 3000 3001
}

static int __init qeth_l3_init(void)
{
3002
	pr_info("register layer 3 discipline\n");
J
Julian Wiedmann 已提交
3003
	return qeth_l3_register_notifiers();
F
Frank Blaschka 已提交
3004 3005 3006 3007 3008
}

static void __exit qeth_l3_exit(void)
{
	qeth_l3_unregister_notifiers();
3009
	pr_info("unregister layer 3 discipline\n");
F
Frank Blaschka 已提交
3010 3011 3012 3013 3014 3015 3016
}

module_init(qeth_l3_init);
module_exit(qeth_l3_exit);
MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
MODULE_DESCRIPTION("qeth layer 3 discipline");
MODULE_LICENSE("GPL");