qeth_l3_main.c 66.3 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/iucv/af_iucv.h>
36
#include <linux/hashtable.h>
F
Frank Blaschka 已提交
37 38 39

#include "qeth_l3.h"

40

F
Frank Blaschka 已提交
41
static int qeth_l3_set_offline(struct ccwgroup_device *);
42
static void qeth_l3_set_rx_mode(struct net_device *dev);
F
Frank Blaschka 已提交
43 44 45 46 47
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 *);

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

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

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);
}

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

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

76 77 78
static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card,
						   struct qeth_ipaddr *query)
{
79
	u32 key = qeth_l3_ipaddr_hash(query);
80 81 82 83 84 85 86 87 88 89 90 91 92 93
	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 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107
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;
		}
	}
}

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

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

	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;
}

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

153 154 155 156 157 158
	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 已提交
159

160 161
	if (tmp_addr->proto == QETH_PROT_IPV4)
		QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4);
F
Frank Blaschka 已提交
162
	else {
163 164
		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 已提交
165
	}
166

167 168
	addr = qeth_l3_find_addr_by_ip(card, tmp_addr);
	if (!addr || !qeth_l3_addr_match_all(addr, tmp_addr))
169 170 171
		return -ENOENT;

	addr->ref_counter--;
172
	if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0)
173 174 175 176
		return rc;
	if (addr->in_progress)
		return -EINPROGRESS;

177 178
	if (qeth_card_hw_is_reachable(card))
		rc = qeth_l3_deregister_addr_entry(card, addr);
179 180 181 182

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

F
Frank Blaschka 已提交
183 184 185
	return rc;
}

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

192 193 194 195 196 197
	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");
198 199 200

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

206 207 208 209 210 211 212 213 214 215 216 217 218 219
	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 {
220 221 222 223 224 225 226
		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;

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

234 235 236 237 238
		if (!qeth_card_hw_is_reachable(card)) {
			addr->disp_flag = QETH_DISP_ADDR_ADD;
			return 0;
		}

239 240 241 242 243 244 245 246 247
		/* 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;
248
			mutex_unlock(&card->ip_lock);
249
			rc = qeth_l3_register_addr_entry(card, addr);
250
			mutex_lock(&card->ip_lock);
251 252 253 254
			addr->in_progress = 0;
		} else
			rc = qeth_l3_register_addr_entry(card, addr);

255
		if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
256 257
			addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
			if (addr->ref_counter < 1) {
258 259
				qeth_l3_deregister_addr_entry(card, addr);
				hash_del(&addr->hnode);
260 261 262 263 264 265
				kfree(addr);
			}
		} else {
			hash_del(&addr->hnode);
			kfree(addr);
		}
F
Frank Blaschka 已提交
266 267 268 269
	}
	return rc;
}

270 271 272 273 274
static int qeth_l3_modify_ip(struct qeth_card *card, struct qeth_ipaddr *addr,
			     bool add)
{
	int rc;

275
	mutex_lock(&card->ip_lock);
276
	rc = add ? qeth_l3_add_ip(card, addr) : qeth_l3_delete_ip(card, addr);
277
	mutex_unlock(&card->ip_lock);
278 279 280 281

	return rc;
}

282 283 284 285 286 287 288 289 290 291 292 293
static void qeth_l3_drain_rx_mode_cache(struct qeth_card *card)
{
	struct qeth_ipaddr *addr;
	struct hlist_node *tmp;
	int i;

	hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) {
		hash_del(&addr->hnode);
		kfree(addr);
	}
}

294
static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
F
Frank Blaschka 已提交
295 296
{
	struct qeth_ipaddr *addr;
297 298
	struct hlist_node *tmp;
	int i;
F
Frank Blaschka 已提交
299

300
	QETH_CARD_TEXT(card, 4, "clearip");
F
Frank Blaschka 已提交
301

302
	mutex_lock(&card->ip_lock);
303 304 305 306 307

	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
		if (!recover) {
			hash_del(&addr->hnode);
			kfree(addr);
F
Frank Blaschka 已提交
308 309
			continue;
		}
310
		addr->disp_flag = QETH_DISP_ADDR_ADD;
F
Frank Blaschka 已提交
311 312
	}

313
	mutex_unlock(&card->ip_lock);
314
}
315

316
static void qeth_l3_recover_ip(struct qeth_card *card)
F
Frank Blaschka 已提交
317
{
318 319 320 321
	struct qeth_ipaddr *addr;
	struct hlist_node *tmp;
	int i;
	int rc;
F
Frank Blaschka 已提交
322

323
	QETH_CARD_TEXT(card, 4, "recovrip");
324

325
	mutex_lock(&card->ip_lock);
326 327

	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
328
		if (addr->disp_flag == QETH_DISP_ADDR_ADD) {
329 330
			if (addr->proto == QETH_PROT_IPV4) {
				addr->in_progress = 1;
331
				mutex_unlock(&card->ip_lock);
332
				rc = qeth_l3_register_addr_entry(card, addr);
333
				mutex_lock(&card->ip_lock);
334 335 336 337 338 339
				addr->in_progress = 0;
			} else
				rc = qeth_l3_register_addr_entry(card, addr);

			if (!rc) {
				addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
340
				if (addr->ref_counter < 1)
341 342 343 344 345 346 347
					qeth_l3_delete_ip(card, addr);
			} else {
				hash_del(&addr->hnode);
				kfree(addr);
			}
		}
	}
F
Frank Blaschka 已提交
348

349
	mutex_unlock(&card->ip_lock);
F
Frank Blaschka 已提交
350 351
}

352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
static int qeth_l3_setdelip_cb(struct qeth_card *card, struct qeth_reply *reply,
			       unsigned long data)
{
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;

	switch (cmd->hdr.return_code) {
	case IPA_RC_SUCCESS:
		return 0;
	case IPA_RC_DUPLICATE_IP_ADDRESS:
		return -EADDRINUSE;
	case IPA_RC_MC_ADDR_NOT_FOUND:
		return -ENOENT;
	case IPA_RC_LAN_OFFLINE:
		return -ENETDOWN;
	default:
		return -EIO;
	}
}

F
Frank Blaschka 已提交
371 372 373 374 375 376
static int qeth_l3_send_setdelmc(struct qeth_card *card,
			struct qeth_ipaddr *addr, int ipacmd)
{
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;

C
Carsten Otte 已提交
377
	QETH_CARD_TEXT(card, 4, "setdelmc");
F
Frank Blaschka 已提交
378

379 380
	iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
				 IPA_DATA_SIZEOF(setdelipm));
381 382
	if (!iob)
		return -ENOMEM;
383
	cmd = __ipa_cmd(iob);
384 385 386 387 388 389 390
	if (addr->proto == QETH_PROT_IPV6) {
		cmd->data.setdelipm.ip = addr->u.a6.addr;
		ipv6_eth_mc_map(&addr->u.a6.addr, cmd->data.setdelipm.mac);
	} else {
		cmd->data.setdelipm.ip.s6_addr32[3] = addr->u.a4.addr;
		ip_eth_mc_map(addr->u.a4.addr, cmd->data.setdelipm.mac);
	}
F
Frank Blaschka 已提交
391

392
	return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
F
Frank Blaschka 已提交
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
}

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;
	}
}

409 410 411 412 413 414 415 416 417 418 419 420 421
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 已提交
422
static int qeth_l3_send_setdelip(struct qeth_card *card,
423 424
				 struct qeth_ipaddr *addr,
				 enum qeth_ipa_cmds ipacmd)
F
Frank Blaschka 已提交
425 426 427 428
{
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_cmd *cmd;
	__u8 netmask[16];
429
	u32 flags;
F
Frank Blaschka 已提交
430

C
Carsten Otte 已提交
431
	QETH_CARD_TEXT(card, 4, "setdelip");
F
Frank Blaschka 已提交
432

433 434
	iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
				 IPA_DATA_SIZEOF(setdelip6));
435 436
	if (!iob)
		return -ENOMEM;
437
	cmd = __ipa_cmd(iob);
438 439 440 441

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

F
Frank Blaschka 已提交
442 443 444 445 446 447 448 449 450 451 452 453 454
	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;
	}

455
	return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
F
Frank Blaschka 已提交
456 457 458 459 460 461 462 463 464
}

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 已提交
465
	QETH_CARD_TEXT(card, 4, "setroutg");
466 467
	iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SETRTG, prot,
				 IPA_DATA_SIZEOF(setrtg));
468 469
	if (!iob)
		return -ENOMEM;
470
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
471 472 473 474 475 476
	cmd->data.setrtg.type = (type);
	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);

	return rc;
}

477
static int qeth_l3_correct_routing_type(struct qeth_card *card,
F
Frank Blaschka 已提交
478 479
		enum qeth_routing_types *type, enum qeth_prot_versions prot)
{
480
	if (IS_IQD(card)) {
F
Frank Blaschka 已提交
481 482 483 484 485
		switch (*type) {
		case NO_ROUTER:
		case PRIMARY_CONNECTOR:
		case SECONDARY_CONNECTOR:
		case MULTICAST_ROUTER:
486
			return 0;
F
Frank Blaschka 已提交
487 488 489 490 491 492 493 494
		default:
			goto out_inval;
		}
	} else {
		switch (*type) {
		case NO_ROUTER:
		case PRIMARY_ROUTER:
		case SECONDARY_ROUTER:
495
			return 0;
F
Frank Blaschka 已提交
496 497 498
		case MULTICAST_ROUTER:
			if (qeth_is_ipafunc_supported(card, prot,
						      IPA_OSA_MC_ROUTER))
499
				return 0;
F
Frank Blaschka 已提交
500 501 502 503 504 505
		default:
			goto out_inval;
		}
	}
out_inval:
	*type = NO_ROUTER;
506
	return -EINVAL;
F
Frank Blaschka 已提交
507 508 509 510 511 512
}

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

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

515
	rc = qeth_l3_correct_routing_type(card, &card->options.route4.type,
F
Frank Blaschka 已提交
516
				  QETH_PROT_IPV4);
517 518
	if (rc)
		return rc;
F
Frank Blaschka 已提交
519 520 521 522 523

	rc = qeth_l3_send_setrouting(card, card->options.route4.type,
				  QETH_PROT_IPV4);
	if (rc) {
		card->options.route4.type = NO_ROUTER;
524 525
		QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n",
				 rc, CARD_DEVID(card));
F
Frank Blaschka 已提交
526 527 528 529 530 531 532 533
	}
	return rc;
}

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

C
Carsten Otte 已提交
534
	QETH_CARD_TEXT(card, 3, "setrtg6");
F
Frank Blaschka 已提交
535 536 537

	if (!qeth_is_supported(card, IPA_IPV6))
		return 0;
538
	rc = qeth_l3_correct_routing_type(card, &card->options.route6.type,
F
Frank Blaschka 已提交
539
				  QETH_PROT_IPV6);
540 541
	if (rc)
		return rc;
F
Frank Blaschka 已提交
542 543 544 545 546

	rc = qeth_l3_send_setrouting(card, card->options.route6.type,
				  QETH_PROT_IPV6);
	if (rc) {
		card->options.route6.type = NO_ROUTER;
547 548
		QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n",
				 rc, CARD_DEVID(card));
F
Frank Blaschka 已提交
549 550 551 552 553 554 555
	}
	return rc;
}

/*
 * IP address takeover related functions
 */
556 557 558 559 560 561 562 563 564 565 566 567 568 569

/**
 * 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;
570
		addr->ipato = qeth_l3_is_addr_covered_by_ipato(card, addr);
571 572 573
	}
}

F
Frank Blaschka 已提交
574 575 576 577
static void qeth_l3_clear_ipato_list(struct qeth_card *card)
{
	struct qeth_ipato_entry *ipatoe, *tmp;

578
	mutex_lock(&card->ip_lock);
579

F
Frank Blaschka 已提交
580 581 582 583
	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
		list_del(&ipatoe->entry);
		kfree(ipatoe);
	}
584

585
	qeth_l3_update_ipato(card);
586
	mutex_unlock(&card->ip_lock);
F
Frank Blaschka 已提交
587 588 589 590 591 592 593 594
}

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 已提交
595
	QETH_CARD_TEXT(card, 2, "addipato");
596

597
	mutex_lock(&card->ip_lock);
598

F
Frank Blaschka 已提交
599 600 601 602 603 604 605 606 607 608
	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;
		}
	}
609

610
	if (!rc) {
F
Frank Blaschka 已提交
611
		list_add_tail(&new->entry, &card->ipato.entries);
612 613
		qeth_l3_update_ipato(card);
	}
F
Frank Blaschka 已提交
614

615
	mutex_unlock(&card->ip_lock);
616

F
Frank Blaschka 已提交
617 618 619
	return rc;
}

620 621 622
int qeth_l3_del_ipato_entry(struct qeth_card *card,
			    enum qeth_prot_versions proto, u8 *addr,
			    int mask_bits)
F
Frank Blaschka 已提交
623 624
{
	struct qeth_ipato_entry *ipatoe, *tmp;
625
	int rc = -ENOENT;
F
Frank Blaschka 已提交
626

C
Carsten Otte 已提交
627
	QETH_CARD_TEXT(card, 2, "delipato");
628

629
	mutex_lock(&card->ip_lock);
630

F
Frank Blaschka 已提交
631 632 633 634 635 636 637
	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);
638
			qeth_l3_update_ipato(card);
F
Frank Blaschka 已提交
639
			kfree(ipatoe);
640
			rc = 0;
F
Frank Blaschka 已提交
641 642
		}
	}
643

644
	mutex_unlock(&card->ip_lock);
645
	return rc;
F
Frank Blaschka 已提交
646 647
}

648 649 650
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 已提交
651
{
652
	struct qeth_ipaddr addr;
F
Frank Blaschka 已提交
653

654 655 656 657 658
	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);
659

660
	return qeth_l3_modify_ip(card, &addr, add);
F
Frank Blaschka 已提交
661 662
}

663
int qeth_l3_modify_hsuid(struct qeth_card *card, bool add)
F
Frank Blaschka 已提交
664
{
665
	struct qeth_ipaddr addr;
666
	unsigned int i;
F
Frank Blaschka 已提交
667

668 669 670 671 672
	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];
673

674
	return qeth_l3_modify_ip(card, &addr, add);
F
Frank Blaschka 已提交
675 676 677 678 679 680 681 682 683
}

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

684 685
	if (card->options.sniffer)
		return 0;
686

F
Frank Blaschka 已提交
687
	if (addr->proto == QETH_PROT_IPV4) {
C
Carsten Otte 已提交
688 689
		QETH_CARD_TEXT(card, 2, "setaddr4");
		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));
F
Frank Blaschka 已提交
690
	} else if (addr->proto == QETH_PROT_IPV6) {
C
Carsten Otte 已提交
691 692 693
		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 已提交
694
	} else {
C
Carsten Otte 已提交
695 696
		QETH_CARD_TEXT(card, 2, "setaddr?");
		QETH_CARD_HEX(card, 3, addr, sizeof(struct qeth_ipaddr));
F
Frank Blaschka 已提交
697 698 699 700 701
	}
	do {
		if (addr->is_multicast)
			rc =  qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
		else
702
			rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP);
F
Frank Blaschka 已提交
703
		if (rc)
C
Carsten Otte 已提交
704
			QETH_CARD_TEXT(card, 2, "failed");
F
Frank Blaschka 已提交
705 706
	} while ((--cnt > 0) && rc);
	if (rc) {
C
Carsten Otte 已提交
707
		QETH_CARD_TEXT(card, 2, "FAILED");
F
Frank Blaschka 已提交
708
		qeth_l3_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
709 710
		dev_warn(&card->gdev->dev,
			"Registering IP address %s failed\n", buf);
F
Frank Blaschka 已提交
711 712 713 714 715 716 717 718 719
	}
	return rc;
}

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

720 721 722
	if (card->options.sniffer)
		return 0;

F
Frank Blaschka 已提交
723
	if (addr->proto == QETH_PROT_IPV4) {
C
Carsten Otte 已提交
724 725
		QETH_CARD_TEXT(card, 2, "deladdr4");
		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));
F
Frank Blaschka 已提交
726
	} else if (addr->proto == QETH_PROT_IPV6) {
C
Carsten Otte 已提交
727 728 729
		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 已提交
730
	} else {
C
Carsten Otte 已提交
731 732
		QETH_CARD_TEXT(card, 2, "deladdr?");
		QETH_CARD_HEX(card, 3, addr, sizeof(struct qeth_ipaddr));
F
Frank Blaschka 已提交
733 734 735 736
	}
	if (addr->is_multicast)
		rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
	else
737
		rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP);
738
	if (rc)
C
Carsten Otte 已提交
739
		QETH_CARD_TEXT(card, 2, "failed");
F
Frank Blaschka 已提交
740 741 742 743 744 745

	return rc;
}

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

748
	QETH_CARD_TEXT(card, 2, "setadprm");
F
Frank Blaschka 已提交
749 750 751 752

	if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) {
		rc = qeth_setadpparms_change_macaddr(card);
		if (rc)
753
			dev_warn(&card->gdev->dev, "Reading the adapter MAC"
754
				" address failed\n");
F
Frank Blaschka 已提交
755 756 757 758 759 760 761 762 763
	}

	return rc;
}

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

C
Carsten Otte 已提交
764
	QETH_CARD_TEXT(card, 3, "ipaarp");
F
Frank Blaschka 已提交
765 766

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

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

C
Carsten Otte 已提交
786
	QETH_CARD_TEXT(card, 3, "stsrcmac");
F
Frank Blaschka 已提交
787 788

	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
789
		dev_info(&card->gdev->dev,
790
			"Inbound source MAC-address not supported on %s\n",
791
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
792 793 794
		return -EOPNOTSUPP;
	}

795
	rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
796
					  IPA_CMD_ASS_START, NULL);
F
Frank Blaschka 已提交
797
	if (rc)
798
		dev_warn(&card->gdev->dev,
799
			"Starting source MAC-address support for %s failed\n",
800
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
801 802 803 804 805 806 807
	return rc;
}

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

C
Carsten Otte 已提交
808
	QETH_CARD_TEXT(card, 3, "strtvlan");
F
Frank Blaschka 已提交
809 810

	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
811 812
		dev_info(&card->gdev->dev,
			"VLAN not supported on %s\n", QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
813 814 815
		return -EOPNOTSUPP;
	}

816
	rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
817
					  IPA_CMD_ASS_START, NULL);
F
Frank Blaschka 已提交
818
	if (rc) {
819 820 821
		dev_warn(&card->gdev->dev,
			"Starting VLAN support for %s failed\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
822
	} else {
823
		dev_info(&card->gdev->dev, "VLAN enabled\n");
F
Frank Blaschka 已提交
824 825 826 827 828 829 830 831
	}
	return rc;
}

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

C
Carsten Otte 已提交
832
	QETH_CARD_TEXT(card, 3, "stmcast");
F
Frank Blaschka 已提交
833 834

	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
835 836 837
		dev_info(&card->gdev->dev,
			"Multicast not supported on %s\n",
			QETH_CARD_IFNAME(card));
F
Frank Blaschka 已提交
838 839 840
		return -EOPNOTSUPP;
	}

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

static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
{
856
	u32 ipv6_data = 3;
F
Frank Blaschka 已提交
857 858
	int rc;

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

861
	if (IS_IQD(card))
862 863
		goto out;

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

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

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

static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
{
907
	u32 filter_data = 1;
F
Frank Blaschka 已提交
908 909
	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,
920
					  IPA_CMD_ASS_START, NULL);
F
Frank Blaschka 已提交
921
	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,
928
					  IPA_CMD_ASS_CONFIGURE, &filter_data);
F
Frank Blaschka 已提交
929
	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,
938
					  IPA_CMD_ASS_ENABLE, &filter_data);
F
Frank Blaschka 已提交
939
	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

F
Frank Blaschka 已提交
957 958 959 960 961 962 963 964 965 966 967 968
	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)
{
969
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
F
Frank Blaschka 已提交
970

971 972 973 974 975
	if (cmd->hdr.return_code)
		return -EIO;

	ether_addr_copy(card->dev->dev_addr,
			cmd->data.create_destroy_addr.unique_id);
F
Frank Blaschka 已提交
976 977 978 979 980 981 982 983 984
	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;

985
	QETH_CARD_TEXT(card, 2, "hsrmac");
F
Frank Blaschka 已提交
986

987 988
	iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
				 IPA_DATA_SIZEOF(create_destroy_addr));
989 990
	if (!iob)
		return -ENOMEM;
991
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
992 993 994 995 996 997 998 999 1000 1001 1002
	*((__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)
{
1003
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
F
Frank Blaschka 已提交
1004

1005
	if (cmd->hdr.return_code == 0) {
F
Frank Blaschka 已提交
1006 1007
		card->info.unique_id = *((__u16 *)
				&cmd->data.create_destroy_addr.unique_id[6]);
1008
		return 0;
F
Frank Blaschka 已提交
1009
	}
1010 1011 1012 1013 1014

	card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
			       UNIQUE_ID_NOT_BY_CARD;
	dev_warn(&card->gdev->dev, "The network adapter failed to generate a unique ID\n");
	return -EIO;
F
Frank Blaschka 已提交
1015 1016 1017 1018 1019 1020 1021 1022
}

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

1023
	QETH_CARD_TEXT(card, 2, "guniqeid");
F
Frank Blaschka 已提交
1024 1025 1026 1027 1028 1029 1030

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

1031 1032
	iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
				 IPA_DATA_SIZEOF(create_destroy_addr));
1033 1034
	if (!iob)
		return -ENOMEM;
1035
	cmd = __ipa_cmd(iob);
F
Frank Blaschka 已提交
1036 1037 1038 1039 1040 1041 1042
	*((__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;
}

1043 1044 1045 1046 1047 1048 1049
static int
qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
			    unsigned long data)
{
	struct qeth_ipa_cmd	   *cmd;
	__u16 rc;

1050
	QETH_CARD_TEXT(card, 2, "diastrcb");
1051 1052 1053

	cmd = (struct qeth_ipa_cmd *)data;
	rc = cmd->hdr.return_code;
1054
	if (rc)
C
Carsten Otte 已提交
1055
		QETH_CARD_TEXT_(card, 2, "dxter%x", rc);
1056 1057 1058 1059
	switch (cmd->data.diagass.action) {
	case QETH_DIAGS_CMD_TRACE_QUERY:
		break;
	case QETH_DIAGS_CMD_TRACE_DISABLE:
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
		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;
		}
1070 1071
		break;
	case QETH_DIAGS_CMD_TRACE_ENABLE:
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
		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;
		}
1091 1092
		break;
	default:
1093 1094
		QETH_DBF_MESSAGE(2, "Unknown sniffer action (%#06x) on device %x\n",
				 cmd->data.diagass.action, CARD_DEVID(card));
1095 1096
	}

1097
	return rc ? -EIO : 0;
1098 1099 1100 1101 1102 1103 1104 1105
}

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;

1106
	QETH_CARD_TEXT(card, 2, "diagtrac");
1107

1108
	iob = qeth_get_diag_cmd(card, QETH_DIAGS_CMD_TRACE, 0);
1109 1110
	if (!iob)
		return -ENOMEM;
1111
	cmd = __ipa_cmd(iob);
1112 1113 1114 1115 1116
	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);
}

1117 1118
static void
qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev)
F
Frank Blaschka 已提交
1119 1120
{
	struct ip_mc_list *im4;
1121
	struct qeth_ipaddr *tmp, *ipm;
F
Frank Blaschka 已提交
1122

C
Carsten Otte 已提交
1123
	QETH_CARD_TEXT(card, 4, "addmc");
1124 1125

	tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
1126 1127
	if (!tmp)
		return;
1128

S
Sachin Sant 已提交
1129 1130
	for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL;
	     im4 = rcu_dereference(im4->next_rcu)) {
1131
		tmp->u.a4.addr = im4->multiaddr;
1132
		tmp->is_multicast = 1;
1133

1134
		ipm = qeth_l3_find_addr_by_ip(card, tmp);
1135
		if (ipm) {
1136
			/* for mcast, by-IP match means full match */
1137 1138 1139 1140 1141
			ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
		} else {
			ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
			if (!ipm)
				continue;
1142

1143
			ipm->u.a4.addr = im4->multiaddr;
1144 1145 1146 1147 1148
			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 已提交
1149
	}
1150 1151

	kfree(tmp);
F
Frank Blaschka 已提交
1152 1153
}

1154
/* called with rcu_read_lock */
F
Frank Blaschka 已提交
1155 1156 1157
static void qeth_l3_add_vlan_mc(struct qeth_card *card)
{
	struct in_device *in_dev;
J
Jiri Pirko 已提交
1158
	u16 vid;
F
Frank Blaschka 已提交
1159

C
Carsten Otte 已提交
1160
	QETH_CARD_TEXT(card, 4, "addmcvl");
1161

J
Jiri Pirko 已提交
1162
	if (!qeth_is_supported(card, IPA_FULL_VLAN))
F
Frank Blaschka 已提交
1163 1164
		return;

J
Jiri Pirko 已提交
1165 1166 1167
	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
		struct net_device *netdev;

1168
		netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q),
1169
					      vid);
F
Frank Blaschka 已提交
1170 1171 1172
		if (netdev == NULL ||
		    !(netdev->flags & IFF_UP))
			continue;
1173
		in_dev = __in_dev_get_rcu(netdev);
F
Frank Blaschka 已提交
1174 1175
		if (!in_dev)
			continue;
1176
		qeth_l3_add_mc_to_hash(card, in_dev);
F
Frank Blaschka 已提交
1177 1178 1179 1180 1181 1182 1183
	}
}

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

C
Carsten Otte 已提交
1184
	QETH_CARD_TEXT(card, 4, "chkmcv4");
1185

S
Sachin Sant 已提交
1186
	rcu_read_lock();
1187 1188 1189
	in4_dev = __in_dev_get_rcu(card->dev);
	if (in4_dev == NULL)
		goto unlock;
1190
	qeth_l3_add_mc_to_hash(card, in4_dev);
F
Frank Blaschka 已提交
1191
	qeth_l3_add_vlan_mc(card);
1192
unlock:
S
Sachin Sant 已提交
1193
	rcu_read_unlock();
F
Frank Blaschka 已提交
1194 1195
}

J
Julian Wiedmann 已提交
1196 1197
static void qeth_l3_add_mc6_to_hash(struct qeth_card *card,
				    struct inet6_dev *in6_dev)
F
Frank Blaschka 已提交
1198 1199 1200
{
	struct qeth_ipaddr *ipm;
	struct ifmcaddr6 *im6;
1201
	struct qeth_ipaddr *tmp;
F
Frank Blaschka 已提交
1202

C
Carsten Otte 已提交
1203
	QETH_CARD_TEXT(card, 4, "addmc6");
1204 1205

	tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
1206 1207
	if (!tmp)
		return;
1208

F
Frank Blaschka 已提交
1209
	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
1210
		tmp->u.a6.addr = im6->mca_addr;
1211 1212
		tmp->is_multicast = 1;

1213
		ipm = qeth_l3_find_addr_by_ip(card, tmp);
1214
		if (ipm) {
1215
			/* for mcast, by-IP match means full match */
1216 1217 1218 1219
			ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
			continue;
		}

F
Frank Blaschka 已提交
1220 1221 1222
		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
		if (!ipm)
			continue;
1223

1224
		ipm->u.a6.addr = im6->mca_addr;
1225 1226 1227 1228 1229
		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 已提交
1230
	}
1231
	kfree(tmp);
F
Frank Blaschka 已提交
1232 1233
}

1234
/* called with rcu_read_lock */
F
Frank Blaschka 已提交
1235 1236 1237
static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
{
	struct inet6_dev *in_dev;
J
Jiri Pirko 已提交
1238
	u16 vid;
F
Frank Blaschka 已提交
1239

C
Carsten Otte 已提交
1240
	QETH_CARD_TEXT(card, 4, "admc6vl");
1241

J
Jiri Pirko 已提交
1242
	if (!qeth_is_supported(card, IPA_FULL_VLAN))
F
Frank Blaschka 已提交
1243 1244
		return;

J
Jiri Pirko 已提交
1245 1246 1247
	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
		struct net_device *netdev;

1248
		netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q),
1249
					      vid);
F
Frank Blaschka 已提交
1250 1251 1252 1253 1254 1255 1256
		if (netdev == NULL ||
		    !(netdev->flags & IFF_UP))
			continue;
		in_dev = in6_dev_get(netdev);
		if (!in_dev)
			continue;
		read_lock_bh(&in_dev->lock);
1257
		qeth_l3_add_mc6_to_hash(card, in_dev);
F
Frank Blaschka 已提交
1258 1259 1260 1261 1262 1263 1264 1265 1266
		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 已提交
1267
	QETH_CARD_TEXT(card, 4, "chkmcv6");
1268

F
Frank Blaschka 已提交
1269 1270 1271
	if (!qeth_is_supported(card, IPA_IPV6))
		return ;
	in6_dev = in6_dev_get(card->dev);
1272
	if (!in6_dev)
F
Frank Blaschka 已提交
1273
		return;
1274

1275
	rcu_read_lock();
F
Frank Blaschka 已提交
1276
	read_lock_bh(&in6_dev->lock);
1277
	qeth_l3_add_mc6_to_hash(card, in6_dev);
F
Frank Blaschka 已提交
1278 1279
	qeth_l3_add_vlan_mc6(card);
	read_unlock_bh(&in6_dev->lock);
1280
	rcu_read_unlock();
F
Frank Blaschka 已提交
1281 1282 1283
	in6_dev_put(in6_dev);
}

1284 1285
static int qeth_l3_vlan_rx_add_vid(struct net_device *dev,
				   __be16 proto, u16 vid)
F
Frank Blaschka 已提交
1286
{
1287
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1288

J
Jiri Pirko 已提交
1289
	set_bit(vid, card->active_vlans);
1290
	return 0;
F
Frank Blaschka 已提交
1291 1292
}

1293 1294
static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
				    __be16 proto, u16 vid)
F
Frank Blaschka 已提交
1295
{
1296
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1297

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

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

1305 1306
static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
				struct qeth_hdr *hdr)
F
Frank Blaschka 已提交
1307
{
1308 1309 1310 1311 1312 1313 1314 1315 1316
	struct af_iucv_trans_hdr *iucv = (struct af_iucv_trans_hdr *) skb->data;
	struct net_device *dev = skb->dev;

	if (IS_IQD(card) && iucv->magic == ETH_P_AF_IUCV) {
		dev_hard_header(skb, dev, ETH_P_AF_IUCV, dev->dev_addr,
				"FAKELL", skb->len);
		return;
	}

F
Frank Blaschka 已提交
1317
	if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
1318 1319
		u16 prot = (hdr->hdr.l3.flags & QETH_HDR_IPV6) ? ETH_P_IPV6 :
								 ETH_P_IP;
1320
		unsigned char tg_addr[ETH_ALEN];
1321 1322

		skb_reset_network_header(skb);
F
Frank Blaschka 已提交
1323 1324
		switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) {
		case QETH_CAST_MULTICAST:
J
Julian Wiedmann 已提交
1325
			if (prot == ETH_P_IP)
1326
				ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr);
J
Julian Wiedmann 已提交
1327 1328
			else
				ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr);
1329
			QETH_CARD_STAT_INC(card, rx_multicast);
F
Frank Blaschka 已提交
1330 1331
			break;
		case QETH_CAST_BROADCAST:
1332
			ether_addr_copy(tg_addr, card->dev->broadcast);
1333
			QETH_CARD_STAT_INC(card, rx_multicast);
F
Frank Blaschka 已提交
1334 1335
			break;
		default:
1336 1337
			if (card->options.sniffer)
				skb->pkt_type = PACKET_OTHERHOST;
1338
			ether_addr_copy(tg_addr, card->dev->dev_addr);
F
Frank Blaschka 已提交
1339
		}
J
Julian Wiedmann 已提交
1340

1341 1342
		if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
			card->dev->header_ops->create(skb, card->dev, prot,
1343
				tg_addr, &hdr->hdr.l3.next_hop.rx.src_mac,
1344
				skb->len);
1345 1346
		else
			card->dev->header_ops->create(skb, card->dev, prot,
1347
				tg_addr, "FAKELL", skb->len);
F
Frank Blaschka 已提交
1348 1349
	}

1350 1351 1352 1353 1354 1355
	/* 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 :
1356
				hdr->hdr.l3.next_hop.rx.vlan_id;
1357
		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag);
F
Frank Blaschka 已提交
1358 1359
	}

1360
	qeth_rx_csum(card, skb, hdr->hdr.l3.ext_flags);
F
Frank Blaschka 已提交
1361 1362
}

1363 1364
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
				int budget, int *done)
F
Frank Blaschka 已提交
1365
{
1366
	int work_done = 0;
F
Frank Blaschka 已提交
1367 1368 1369 1370
	struct sk_buff *skb;
	struct qeth_hdr *hdr;
	unsigned int len;

1371
	*done = 0;
S
Stefan Raspl 已提交
1372
	WARN_ON_ONCE(!budget);
1373 1374
	while (budget) {
		skb = qeth_core_get_next_skb(card,
1375
			&card->qdio.in_q->bufs[card->rx.b_index],
1376 1377 1378 1379 1380
			&card->rx.b_element, &card->rx.e_offset, &hdr);
		if (!skb) {
			*done = 1;
			break;
		}
F
Frank Blaschka 已提交
1381 1382
		switch (hdr->hdr.l3.id) {
		case QETH_HEADER_TYPE_LAYER3:
1383 1384
			qeth_l3_rebuild_skb(card, skb, hdr);
			/* fall through */
1385 1386 1387
		case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
			skb->protocol = eth_type_trans(skb, skb->dev);
			len = skb->len;
1388
			napi_gro_receive(&card->napi, skb);
1389
			break;
F
Frank Blaschka 已提交
1390 1391
		default:
			dev_kfree_skb_any(skb);
C
Carsten Otte 已提交
1392
			QETH_CARD_TEXT(card, 3, "inbunkno");
1393
			QETH_DBF_HEX(CTRL, 3, hdr, sizeof(*hdr));
1394
			QETH_CARD_STAT_INC(card, rx_dropped_notsupp);
F
Frank Blaschka 已提交
1395 1396
			continue;
		}
1397 1398
		work_done++;
		budget--;
1399 1400
		QETH_CARD_STAT_INC(card, rx_packets);
		QETH_CARD_STAT_ADD(card, rx_bytes, len);
F
Frank Blaschka 已提交
1401
	}
1402 1403 1404
	return work_done;
}

1405
static void qeth_l3_stop_card(struct qeth_card *card)
F
Frank Blaschka 已提交
1406
{
1407
	QETH_CARD_TEXT(card, 2, "stopcard");
F
Frank Blaschka 已提交
1408 1409

	qeth_set_allowed_threads(card, 0, 1);
1410

1411 1412 1413
	cancel_work_sync(&card->rx_mode_work);
	qeth_l3_drain_rx_mode_cache(card);

1414 1415 1416
	if (card->options.sniffer &&
	    (card->info.promisc_mode == SET_PROMISC_MODE_ON))
		qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
1417

F
Frank Blaschka 已提交
1418
	if (card->state == CARD_STATE_SOFTSETUP) {
1419
		qeth_l3_clear_ip_htable(card, 1);
F
Frank Blaschka 已提交
1420 1421 1422 1423 1424
		qeth_clear_ipacmd_list(card);
		card->state = CARD_STATE_HARDSETUP;
	}
	if (card->state == CARD_STATE_HARDSETUP) {
		qeth_qdio_clear_card(card, 0);
1425
		qeth_drain_output_queues(card);
F
Frank Blaschka 已提交
1426 1427 1428
		qeth_clear_working_pool_list(card);
		card->state = CARD_STATE_DOWN;
	}
1429 1430

	flush_workqueue(card->event_wq);
F
Frank Blaschka 已提交
1431 1432
}

1433
static void qeth_l3_set_promisc_mode(struct qeth_card *card)
1434
{
1435
	bool enable = card->dev->flags & IFF_PROMISC;
1436

1437
	if (card->info.promisc_mode == enable)
1438 1439
		return;

1440
	if (IS_VM_NIC(card)) {		/* Guestlan trace */
1441
		if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
1442
			qeth_setadp_promisc_mode(card, enable);
1443 1444
	} else if (card->options.sniffer &&	/* HiperSockets trace */
		   qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) {
1445
		if (enable) {
C
Carsten Otte 已提交
1446
			QETH_CARD_TEXT(card, 3, "+promisc");
1447 1448
			qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_ENABLE);
		} else {
C
Carsten Otte 已提交
1449
			QETH_CARD_TEXT(card, 3, "-promisc");
1450 1451 1452 1453 1454
			qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
		}
	}
}

1455
static void qeth_l3_rx_mode_work(struct work_struct *work)
F
Frank Blaschka 已提交
1456
{
1457 1458
	struct qeth_card *card = container_of(work, struct qeth_card,
					      rx_mode_work);
1459 1460 1461
	struct qeth_ipaddr *addr;
	struct hlist_node *tmp;
	int i, rc;
F
Frank Blaschka 已提交
1462

C
Carsten Otte 已提交
1463
	QETH_CARD_TEXT(card, 3, "setmulti");
1464

1465 1466 1467
	if (!card->options.sniffer) {
		qeth_l3_add_multicast_ipv4(card);
		qeth_l3_add_multicast_ipv6(card);
1468 1469 1470 1471 1472

		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);
1473
				if (!rc || rc == -ENOENT) {
1474 1475 1476 1477 1478 1479
					hash_del(&addr->hnode);
					kfree(addr);
				}
				break;
			case QETH_DISP_ADDR_ADD:
				rc = qeth_l3_register_addr_entry(card, addr);
1480
				if (rc && rc != -ENETDOWN) {
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
					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;
			}
		}
1492
	}
1493 1494

	qeth_l3_set_promisc_mode(card);
F
Frank Blaschka 已提交
1495 1496
}

1497
static int qeth_l3_arp_makerc(u16 rc)
F
Frank Blaschka 已提交
1498
{
1499 1500 1501
	switch (rc) {
	case IPA_RC_SUCCESS:
		return 0;
F
Frank Blaschka 已提交
1502 1503
	case QETH_IPA_ARP_RC_NOTSUPP:
	case QETH_IPA_ARP_RC_Q_NOTSUPP:
1504 1505 1506
		return -EOPNOTSUPP;
	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
		return -EINVAL;
F
Frank Blaschka 已提交
1507
	case QETH_IPA_ARP_RC_Q_NO_DATA:
1508
		return -ENOENT;
F
Frank Blaschka 已提交
1509
	default:
1510
		return -EIO;
F
Frank Blaschka 已提交
1511 1512 1513
	}
}

1514 1515 1516 1517 1518 1519 1520 1521 1522
static int qeth_l3_arp_cmd_cb(struct qeth_card *card, struct qeth_reply *reply,
			      unsigned long data)
{
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;

	qeth_setassparms_cb(card, reply, data);
	return qeth_l3_arp_makerc(cmd->hdr.return_code);
}

F
Frank Blaschka 已提交
1523 1524
static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
{
1525
	struct qeth_cmd_buffer *iob;
F
Frank Blaschka 已提交
1526 1527
	int rc;

C
Carsten Otte 已提交
1528
	QETH_CARD_TEXT(card, 3, "arpstnoe");
F
Frank Blaschka 已提交
1529 1530 1531 1532 1533 1534

	/*
	 * 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
	 */
1535
	if (IS_VM_NIC(card))
F
Frank Blaschka 已提交
1536 1537 1538 1539
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}
1540 1541

	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
1542 1543
				       IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
				       SETASS_DATA_SIZEOF(flags_32bit),
1544 1545 1546 1547 1548 1549
				       QETH_PROT_IPV4);
	if (!iob)
		return -ENOMEM;

	__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (u32) no_entries;
	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
1550 1551 1552
	if (rc)
		QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n",
				 CARD_DEVID(card), rc);
1553
	return rc;
F
Frank Blaschka 已提交
1554 1555
}

1556 1557 1558
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 已提交
1559
{
1560 1561
	__u32 rc;
	__u8 is_hsi;
F
Frank Blaschka 已提交
1562

1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
	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 已提交
1587
	}
1588 1589 1590 1591 1592 1593 1594 1595

	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 已提交
1596 1597 1598 1599 1600 1601 1602 1603
}

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;
1604 1605 1606 1607
	int e;
	int entrybytes_done;
	int stripped_bytes;
	__u8 do_strip_entries;
F
Frank Blaschka 已提交
1608

1609
	QETH_CARD_TEXT(card, 3, "arpquecb");
F
Frank Blaschka 已提交
1610 1611 1612

	qinfo = (struct qeth_arp_query_info *) reply->param;
	cmd = (struct qeth_ipa_cmd *) data;
1613
	QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.prot_version);
F
Frank Blaschka 已提交
1614
	if (cmd->hdr.return_code) {
1615 1616
		QETH_CARD_TEXT(card, 4, "arpcberr");
		QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
1617
		return qeth_l3_arp_makerc(cmd->hdr.return_code);
F
Frank Blaschka 已提交
1618 1619 1620
	}
	if (cmd->data.setassparms.hdr.return_code) {
		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
1621 1622
		QETH_CARD_TEXT(card, 4, "setaperr");
		QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
1623
		return qeth_l3_arp_makerc(cmd->hdr.return_code);
F
Frank Blaschka 已提交
1624 1625
	}
	qdata = &cmd->data.setassparms.data.query_arp;
C
Carsten Otte 已提交
1626
	QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries);
F
Frank Blaschka 已提交
1627

1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
	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) {
1650 1651 1652
			QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOSPC);
			memset(qinfo->udata, 0, 4);
			return -ENOSPC;
1653
		}
F
Frank Blaschka 已提交
1654

1655 1656 1657 1658 1659 1660 1661
		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 已提交
1662 1663 1664 1665
	/* check if all replies received ... */
	if (cmd->data.setassparms.hdr.seq_no <
	    cmd->data.setassparms.hdr.number_of_replies)
		return 1;
1666
	QETH_CARD_TEXT_(card, 4, "nove%i", qinfo->no_entries);
F
Frank Blaschka 已提交
1667 1668 1669 1670 1671 1672
	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);
1673
	QETH_CARD_TEXT_(card, 4, "rc%i", 0);
F
Frank Blaschka 已提交
1674 1675 1676
	return 0;
}

1677 1678 1679
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 已提交
1680 1681
{
	struct qeth_cmd_buffer *iob;
1682
	struct qeth_ipa_cmd *cmd;
F
Frank Blaschka 已提交
1683 1684
	int rc;

1685 1686
	QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot);

1687 1688
	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
				       IPA_CMD_ASS_ARP_QUERY_INFO,
1689
				       SETASS_DATA_SIZEOF(query_arp), prot);
1690 1691
	if (!iob)
		return -ENOMEM;
1692
	cmd = __ipa_cmd(iob);
1693
	cmd->data.setassparms.data.query_arp.request_bits = 0x000F;
1694
	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_query_cb, qinfo);
1695 1696 1697
	if (rc)
		QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n",
				 CARD_DEVID(card), rc);
1698
	return rc;
1699 1700 1701 1702 1703 1704 1705
}

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 已提交
1706
	QETH_CARD_TEXT(card, 3, "arpquery");
F
Frank Blaschka 已提交
1707 1708 1709

	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
			       IPA_ARP_PROCESSING)) {
1710 1711 1712
		QETH_CARD_TEXT(card, 3, "arpqnsup");
		rc = -EOPNOTSUPP;
		goto out;
F
Frank Blaschka 已提交
1713 1714
	}
	/* get size of userspace buffer and mask_bits -> 6 bytes */
1715 1716 1717 1718
	if (copy_from_user(&qinfo, udata, 6)) {
		rc = -EFAULT;
		goto out;
	}
F
Frank Blaschka 已提交
1719
	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
1720 1721 1722 1723
	if (!qinfo.udata) {
		rc = -ENOMEM;
		goto out;
	}
F
Frank Blaschka 已提交
1724
	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
1725
	rc = qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV4, &qinfo);
F
Frank Blaschka 已提交
1726 1727 1728
	if (rc) {
		if (copy_to_user(udata, qinfo.udata, 4))
			rc = -EFAULT;
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
		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 已提交
1739
	}
1740 1741
	QETH_CARD_TEXT(card, 4, "qacts");

1742
free_and_out:
F
Frank Blaschka 已提交
1743
	kfree(qinfo.udata);
1744
out:
F
Frank Blaschka 已提交
1745 1746 1747
	return rc;
}

J
Julian Wiedmann 已提交
1748 1749 1750
static int qeth_l3_arp_modify_entry(struct qeth_card *card,
				    struct qeth_arp_cache_entry *entry,
				    enum qeth_arp_process_subcmds arp_cmd)
F
Frank Blaschka 已提交
1751
{
J
Julian Wiedmann 已提交
1752
	struct qeth_arp_cache_entry *cmd_entry;
F
Frank Blaschka 已提交
1753 1754 1755
	struct qeth_cmd_buffer *iob;
	int rc;

J
Julian Wiedmann 已提交
1756 1757 1758 1759
	if (arp_cmd == IPA_CMD_ASS_ARP_ADD_ENTRY)
		QETH_CARD_TEXT(card, 3, "arpadd");
	else
		QETH_CARD_TEXT(card, 3, "arpdel");
F
Frank Blaschka 已提交
1760 1761 1762 1763 1764 1765

	/*
	 * 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
	 */
1766
	if (IS_VM_NIC(card))
F
Frank Blaschka 已提交
1767 1768 1769 1770 1771
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}

J
Julian Wiedmann 已提交
1772
	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd,
1773 1774
				       SETASS_DATA_SIZEOF(arp_entry),
				       QETH_PROT_IPV4);
1775 1776
	if (!iob)
		return -ENOMEM;
F
Frank Blaschka 已提交
1777

J
Julian Wiedmann 已提交
1778 1779 1780
	cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry;
	ether_addr_copy(cmd_entry->macaddr, entry->macaddr);
	memcpy(cmd_entry->ipaddr, entry->ipaddr, 4);
1781
	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
1782
	if (rc)
J
Julian Wiedmann 已提交
1783 1784
		QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n",
				 arp_cmd, CARD_DEVID(card), rc);
1785
	return rc;
F
Frank Blaschka 已提交
1786 1787 1788 1789
}

static int qeth_l3_arp_flush_cache(struct qeth_card *card)
{
1790
	struct qeth_cmd_buffer *iob;
F
Frank Blaschka 已提交
1791 1792
	int rc;

C
Carsten Otte 已提交
1793
	QETH_CARD_TEXT(card, 3, "arpflush");
F
Frank Blaschka 已提交
1794 1795 1796 1797 1798 1799

	/*
	 * 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
	*/
1800
	if (IS_VM_NIC(card) || IS_IQD(card))
F
Frank Blaschka 已提交
1801 1802 1803 1804
		return -EOPNOTSUPP;
	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
		return -EOPNOTSUPP;
	}
1805 1806 1807 1808 1809 1810 1811 1812

	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
				       IPA_CMD_ASS_ARP_FLUSH_CACHE, 0,
				       QETH_PROT_IPV4);
	if (!iob)
		return -ENOMEM;

	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
1813 1814 1815
	if (rc)
		QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n",
				 CARD_DEVID(card), rc);
1816
	return rc;
F
Frank Blaschka 已提交
1817 1818 1819 1820
}

static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
1821
	struct qeth_card *card = dev->ml_priv;
F
Frank Blaschka 已提交
1822
	struct qeth_arp_cache_entry arp_entry;
J
Julian Wiedmann 已提交
1823
	enum qeth_arp_process_subcmds arp_cmd;
F
Frank Blaschka 已提交
1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
	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:
	case SIOC_QETH_ARP_REMOVE_ENTRY:
J
Julian Wiedmann 已提交
1843 1844 1845 1846 1847 1848 1849 1850 1851
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		if (copy_from_user(&arp_entry, rq->ifr_data, sizeof(arp_entry)))
			return -EFAULT;

		arp_cmd = (cmd == SIOC_QETH_ARP_ADD_ENTRY) ?
				IPA_CMD_ASS_ARP_ADD_ENTRY :
				IPA_CMD_ASS_ARP_REMOVE_ENTRY;
		return qeth_l3_arp_modify_entry(card, &arp_entry, arp_cmd);
F
Frank Blaschka 已提交
1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864
	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;
}

1865 1866
static int qeth_l3_get_cast_type_rcu(struct sk_buff *skb, struct dst_entry *dst,
				     int ipv)
1867
{
1868 1869
	struct neighbour *n = NULL;

1870 1871
	if (dst)
		n = dst_neigh_lookup_skb(dst, skb);
1872

1873
	if (n) {
1874 1875
		int cast_type = n->type;

1876
		neigh_release(n);
1877 1878 1879 1880
		if ((cast_type == RTN_BROADCAST) ||
		    (cast_type == RTN_MULTICAST) ||
		    (cast_type == RTN_ANYCAST))
			return cast_type;
1881
		return RTN_UNICAST;
1882
	}
F
Frank Blaschka 已提交
1883

1884
	/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
1885
	switch (ipv) {
1886
	case 4:
1887 1888
		if (ipv4_is_lbcast(ip_hdr(skb)->daddr))
			return RTN_BROADCAST;
1889
		return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
1890
				RTN_MULTICAST : RTN_UNICAST;
1891 1892 1893 1894 1895
	case 6:
		return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
				RTN_MULTICAST : RTN_UNICAST;
	default:
		/* ... and MAC address */
1896
		return qeth_get_ether_cast_type(skb);
1897
	}
1898 1899
}

1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
static int qeth_l3_get_cast_type(struct sk_buff *skb)
{
	int ipv = qeth_get_ip_version(skb);
	struct dst_entry *dst;
	int cast_type;

	rcu_read_lock();
	dst = qeth_dst_check_rcu(skb, ipv);
	cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
	rcu_read_unlock();

	return cast_type;
}

1914
static u8 qeth_l3_cast_type_to_flag(int cast_type)
F
Frank Blaschka 已提交
1915
{
1916 1917 1918 1919 1920 1921 1922 1923
	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;
}
1924

1925 1926
static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
				struct qeth_hdr *hdr, struct sk_buff *skb,
1927
				int ipv, unsigned int data_len)
1928
{
1929
	struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
1930
	struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
1931
	struct qeth_card *card = queue->card;
1932
	struct dst_entry *dst;
1933
	int cast_type;
1934

1935
	hdr->hdr.l3.length = data_len;
F
Frank Blaschka 已提交
1936

1937
	if (skb_is_gso(skb)) {
1938
		hdr->hdr.l3.id = QETH_HEADER_TYPE_L3_TSO;
1939 1940
	} else {
		hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
1941 1942 1943 1944 1945 1946 1947 1948 1949

		if (skb->protocol == htons(ETH_P_AF_IUCV)) {
			l3_hdr->flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
			l3_hdr->next_hop.ipv6_addr.s6_addr16[0] = htons(0xfe80);
			memcpy(&l3_hdr->next_hop.ipv6_addr.s6_addr32[2],
			       iucv_trans_hdr(skb)->destUserID, 8);
			return;
		}

1950 1951 1952 1953 1954 1955 1956 1957
		if (skb->ip_summed == CHECKSUM_PARTIAL) {
			qeth_tx_csum(skb, &hdr->hdr.l3.ext_flags, ipv);
			/* some HW requires combined L3+L4 csum offload: */
			if (ipv == 4)
				hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
		}
	}

1958 1959 1960 1961 1962 1963 1964 1965 1966
	if (ipv == 4 || IS_IQD(card)) {
		/* NETIF_F_HW_VLAN_CTAG_TX */
		if (skb_vlan_tag_present(skb)) {
			hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_VLAN_FRAME;
			hdr->hdr.l3.vlan_id = skb_vlan_tag_get(skb);
		}
	} else if (veth->h_vlan_proto == htons(ETH_P_8021Q)) {
		hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_INCLUDE_VLAN_TAG;
		hdr->hdr.l3.vlan_id = ntohs(veth->h_vlan_TCI);
F
Frank Blaschka 已提交
1967 1968
	}

F
Frank Blaschka 已提交
1969
	rcu_read_lock();
1970
	dst = qeth_dst_check_rcu(skb, ipv);
1971

1972 1973 1974 1975 1976 1977
	if (IS_IQD(card) && skb_get_queue_mapping(skb) != QETH_IQD_MCAST_TXQ)
		cast_type = RTN_UNICAST;
	else
		cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
	l3_hdr->flags |= qeth_l3_cast_type_to_flag(cast_type);

F
Frank Blaschka 已提交
1978
	if (ipv == 4) {
1979
		struct rtable *rt = (struct rtable *) dst;
1980

1981 1982 1983
		*((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
				rt_nexthop(rt, ip_hdr(skb)->daddr) :
				ip_hdr(skb)->daddr;
1984
	} else if (ipv == 6) {
1985
		struct rt6_info *rt = (struct rt6_info *) dst;
1986

1987
		if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
1988
			l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;
1989
		else
1990
			l3_hdr->next_hop.ipv6_addr = ipv6_hdr(skb)->daddr;
1991

1992
		hdr->hdr.l3.flags |= QETH_HDR_IPV6;
1993
		if (!IS_IQD(card))
1994
			hdr->hdr.l3.flags |= QETH_HDR_PASSTHRU;
1995 1996 1997
	} else {
		/* OSA only: */
		l3_hdr->flags |= QETH_HDR_PASSTHRU;
F
Frank Blaschka 已提交
1998
	}
F
Frank Blaschka 已提交
1999
	rcu_read_unlock();
F
Frank Blaschka 已提交
2000 2001
}

2002 2003 2004 2005 2006 2007 2008
static void qeth_l3_fixup_headers(struct sk_buff *skb)
{
	struct iphdr *iph = ip_hdr(skb);

	/* this is safe, IPv6 traffic takes a different path */
	if (skb->ip_summed == CHECKSUM_PARTIAL)
		iph->check = 0;
2009 2010 2011 2012 2013
	if (skb_is_gso(skb)) {
		iph->tot_len = 0;
		tcp_hdr(skb)->check = ~tcp_v4_check(0, iph->saddr,
						    iph->daddr, 0);
	}
2014 2015
}

2016
static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
2017
			struct qeth_qdio_out_q *queue, int ipv)
2018
{
J
Julian Wiedmann 已提交
2019 2020
	unsigned int hw_hdr_len;
	int rc;
2021

2022
	/* re-use the L2 header area for the HW header: */
J
Julian Wiedmann 已提交
2023 2024
	hw_hdr_len = skb_is_gso(skb) ? sizeof(struct qeth_hdr_tso) :
				       sizeof(struct qeth_hdr);
2025 2026 2027 2028 2029
	rc = skb_cow_head(skb, hw_hdr_len - ETH_HLEN);
	if (rc)
		return rc;
	skb_pull(skb, ETH_HLEN);

2030
	qeth_l3_fixup_headers(skb);
2031
	return qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
2032 2033
}

2034 2035 2036 2037
static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
					   struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;
2038
	u16 txq = skb_get_queue_mapping(skb);
2039 2040
	int ipv = qeth_get_ip_version(skb);
	struct qeth_qdio_out_q *queue;
2041
	int rc;
2042

2043 2044
	if (!skb_is_gso(skb))
		qdisc_skb_cb(skb)->pkt_len = skb->len;
2045
	if (IS_IQD(card)) {
2046 2047
		queue = card->qdio.out_qs[qeth_iqd_translate_txq(dev, txq)];

2048 2049 2050 2051 2052
		if (card->options.sniffer)
			goto tx_drop;
		if ((card->options.cq != QETH_CQ_ENABLED && !ipv) ||
		    (card->options.cq == QETH_CQ_ENABLED &&
		     skb->protocol != htons(ETH_P_AF_IUCV)))
F
Frank Blaschka 已提交
2053
			goto tx_drop;
2054
	} else {
2055
		queue = card->qdio.out_qs[txq];
F
Frank Blaschka 已提交
2056 2057
	}

2058 2059
	if (!(dev->flags & IFF_BROADCAST) &&
	    qeth_l3_get_cast_type(skb) == RTN_BROADCAST)
2060 2061
		goto tx_drop;

2062
	if (ipv == 4 || IS_IQD(card))
2063
		rc = qeth_l3_xmit(card, skb, queue, ipv);
2064
	else
2065
		rc = qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
2066

2067
	if (!rc)
2068
		return NETDEV_TX_OK;
F
Frank Blaschka 已提交
2069 2070

tx_drop:
2071
	QETH_TXQ_STAT_INC(queue, tx_dropped);
2072
	kfree_skb(skb);
F
Frank Blaschka 已提交
2073 2074 2075
	return NETDEV_TX_OK;
}

2076 2077 2078 2079 2080 2081 2082
static void qeth_l3_set_rx_mode(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	schedule_work(&card->rx_mode_work);
}

F
Frank Blaschka 已提交
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
/*
 * 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;
}

2107 2108 2109 2110 2111 2112 2113 2114 2115
static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
						    struct net_device *dev,
						    netdev_features_t features)
{
	if (qeth_get_ip_version(skb) != 4)
		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
	return qeth_features_check(skb, dev, features);
}

2116 2117 2118 2119 2120 2121 2122
static u16 qeth_l3_iqd_select_queue(struct net_device *dev, struct sk_buff *skb,
				    struct net_device *sb_dev)
{
	return qeth_iqd_select_queue(dev, skb, qeth_l3_get_cast_type(skb),
				     sb_dev);
}

2123 2124 2125 2126 2127 2128 2129 2130
static u16 qeth_l3_osa_select_queue(struct net_device *dev, struct sk_buff *skb,
				    struct net_device *sb_dev)
{
	struct qeth_card *card = dev->ml_priv;

	return qeth_get_priority_queue(card, skb);
}

F
Frank Blaschka 已提交
2131
static const struct net_device_ops qeth_l3_netdev_ops = {
2132 2133
	.ndo_open		= qeth_open,
	.ndo_stop		= qeth_stop,
2134
	.ndo_get_stats64	= qeth_get_stats64,
F
Frank Blaschka 已提交
2135
	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
2136
	.ndo_select_queue	= qeth_l3_iqd_select_queue,
F
Frank Blaschka 已提交
2137
	.ndo_validate_addr	= eth_validate_addr,
2138
	.ndo_set_rx_mode	= qeth_l3_set_rx_mode,
2139
	.ndo_do_ioctl		= qeth_do_ioctl,
2140 2141
	.ndo_fix_features	= qeth_fix_features,
	.ndo_set_features	= qeth_set_features,
F
Frank Blaschka 已提交
2142 2143
	.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 已提交
2144
	.ndo_tx_timeout		= qeth_tx_timeout,
F
Frank Blaschka 已提交
2145 2146
};

F
Frank Blaschka 已提交
2147
static const struct net_device_ops qeth_l3_osa_netdev_ops = {
2148 2149
	.ndo_open		= qeth_open,
	.ndo_stop		= qeth_stop,
2150
	.ndo_get_stats64	= qeth_get_stats64,
F
Frank Blaschka 已提交
2151
	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
2152
	.ndo_features_check	= qeth_l3_osa_features_check,
2153
	.ndo_select_queue	= qeth_l3_osa_select_queue,
F
Frank Blaschka 已提交
2154
	.ndo_validate_addr	= eth_validate_addr,
2155
	.ndo_set_rx_mode	= qeth_l3_set_rx_mode,
2156
	.ndo_do_ioctl		= qeth_do_ioctl,
2157 2158
	.ndo_fix_features	= qeth_fix_features,
	.ndo_set_features	= qeth_set_features,
F
Frank Blaschka 已提交
2159 2160
	.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 已提交
2161
	.ndo_tx_timeout		= qeth_tx_timeout,
F
Frank Blaschka 已提交
2162 2163 2164
	.ndo_neigh_setup	= qeth_l3_neigh_setup,
};

J
Julian Wiedmann 已提交
2165
static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
F
Frank Blaschka 已提交
2166
{
2167
	unsigned int headroom;
2168 2169
	int rc;

2170
	if (IS_OSD(card) || IS_OSX(card)) {
F
Frank Blaschka 已提交
2171 2172
		if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
		    (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
2173 2174
			pr_info("qeth_l3: ignoring TR device\n");
			return -ENODEV;
2175 2176 2177 2178 2179 2180 2181 2182 2183
		}

		card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;

		/*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;

2184
		if (!IS_VM_NIC(card)) {
2185 2186 2187 2188 2189
			card->dev->features |= NETIF_F_SG;
			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;
F
Frank Blaschka 已提交
2190
		}
2191 2192 2193 2194 2195

		if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
			card->dev->hw_features |= NETIF_F_IPV6_CSUM;
			card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
		}
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207
		if (qeth_is_supported6(card, IPA_OUTBOUND_TSO)) {
			card->dev->hw_features |= NETIF_F_TSO6;
			card->dev->vlan_features |= NETIF_F_TSO6;
		}

		/* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */
		if (card->dev->hw_features & NETIF_F_TSO6)
			headroom = sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
		else if (card->dev->hw_features & NETIF_F_TSO)
			headroom = sizeof(struct qeth_hdr_tso);
		else
			headroom = sizeof(struct qeth_hdr) + VLAN_HLEN;
2208
	} else if (IS_IQD(card)) {
F
Frank Blaschka 已提交
2209
		card->dev->flags |= IFF_NOARP;
F
Frank Blaschka 已提交
2210
		card->dev->netdev_ops = &qeth_l3_netdev_ops;
2211
		headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
2212

2213 2214
		rc = qeth_l3_iqd_read_initial_mac(card);
		if (rc)
2215
			goto out;
F
Frank Blaschka 已提交
2216 2217 2218
	} else
		return -ENODEV;

2219
	card->dev->needed_headroom = headroom;
2220 2221 2222
	card->dev->features |=	NETIF_F_HW_VLAN_CTAG_TX |
				NETIF_F_HW_VLAN_CTAG_RX |
				NETIF_F_HW_VLAN_CTAG_FILTER;
2223

2224
	netif_keep_dst(card->dev);
2225
	if (card->dev->hw_features & (NETIF_F_TSO | NETIF_F_TSO6))
2226 2227
		netif_set_gso_max_size(card->dev,
				       PAGE_SIZE * (QETH_MAX_BUFFER_ELEMENTS(card) - 1));
F
Frank Blaschka 已提交
2228

2229
	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
2230
	rc = register_netdev(card->dev);
J
Julian Wiedmann 已提交
2231 2232 2233
	if (!rc && carrier_ok)
		netif_carrier_on(card->dev);

2234 2235 2236 2237
out:
	if (rc)
		card->dev->netdev_ops = NULL;
	return rc;
F
Frank Blaschka 已提交
2238 2239
}

2240 2241 2242 2243 2244
static const struct device_type qeth_l3_devtype = {
	.name = "qeth_layer3",
	.groups = qeth_l3_attr_groups,
};

F
Frank Blaschka 已提交
2245 2246 2247
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
2248
	int rc;
F
Frank Blaschka 已提交
2249

2250
	hash_init(card->ip_htable);
2251
	mutex_init(&card->ip_lock);
2252 2253 2254 2255
	card->cmd_wq = alloc_ordered_workqueue("%s_cmd", 0,
					       dev_name(&gdev->dev));
	if (!card->cmd_wq)
		return -ENOMEM;
2256

2257 2258
	if (gdev->dev.type == &qeth_generic_devtype) {
		rc = qeth_l3_create_device_attributes(&gdev->dev);
2259 2260
		if (rc) {
			destroy_workqueue(card->cmd_wq);
2261
			return rc;
2262
		}
2263
	}
2264

2265
	hash_init(card->ip_mc_htable);
2266
	INIT_WORK(&card->rx_mode_work, qeth_l3_rx_mode_work);
F
Frank Blaschka 已提交
2267 2268 2269 2270 2271 2272 2273
	return 0;
}

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

2274 2275
	if (cgdev->dev.type == &qeth_generic_devtype)
		qeth_l3_remove_device_attributes(&cgdev->dev);
2276

2277
	qeth_set_allowed_threads(card, 0, 1);
F
Frank Blaschka 已提交
2278 2279
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);

2280
	if (cgdev->state == CCWGROUP_ONLINE)
F
Frank Blaschka 已提交
2281 2282
		qeth_l3_set_offline(cgdev);

2283
	cancel_work_sync(&card->close_dev_work);
2284 2285
	if (qeth_netdev_is_registered(card->dev))
		unregister_netdev(card->dev);
2286 2287 2288

	flush_workqueue(card->cmd_wq);
	destroy_workqueue(card->cmd_wq);
2289
	qeth_l3_clear_ip_htable(card, 0);
F
Frank Blaschka 已提交
2290 2291 2292
	qeth_l3_clear_ipato_list(card);
}

2293
static int qeth_l3_set_online(struct ccwgroup_device *gdev)
F
Frank Blaschka 已提交
2294 2295
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
2296
	struct net_device *dev = card->dev;
F
Frank Blaschka 已提交
2297
	int rc = 0;
J
Julian Wiedmann 已提交
2298
	bool carrier_ok;
F
Frank Blaschka 已提交
2299

2300
	mutex_lock(&card->discipline_mutex);
2301
	mutex_lock(&card->conf_mutex);
2302
	QETH_CARD_TEXT(card, 2, "setonlin");
F
Frank Blaschka 已提交
2303

J
Julian Wiedmann 已提交
2304
	rc = qeth_core_hardsetup_card(card, &carrier_ok);
F
Frank Blaschka 已提交
2305
	if (rc) {
2306
		QETH_CARD_TEXT_(card, 2, "2err%04x", rc);
2307
		rc = -ENODEV;
F
Frank Blaschka 已提交
2308 2309 2310 2311 2312 2313 2314
		goto out_remove;
	}

	card->state = CARD_STATE_HARDSETUP;
	qeth_print_status_message(card);

	/* softsetup */
2315
	QETH_CARD_TEXT(card, 2, "softsetp");
F
Frank Blaschka 已提交
2316 2317 2318

	rc = qeth_l3_setadapter_parms(card);
	if (rc)
2319
		QETH_CARD_TEXT_(card, 2, "2err%04x", rc);
2320 2321
	if (!card->options.sniffer) {
		rc = qeth_l3_start_ipassists(card);
S
Stefan Raspl 已提交
2322
		if (rc) {
2323
			QETH_CARD_TEXT_(card, 2, "3err%d", rc);
S
Stefan Raspl 已提交
2324 2325
			goto out_remove;
		}
2326 2327
		rc = qeth_l3_setrouting_v4(card);
		if (rc)
2328
			QETH_CARD_TEXT_(card, 2, "4err%04x", rc);
2329 2330
		rc = qeth_l3_setrouting_v6(card);
		if (rc)
2331
			QETH_CARD_TEXT_(card, 2, "5err%04x", rc);
2332
	}
F
Frank Blaschka 已提交
2333 2334 2335

	rc = qeth_init_qdio_queues(card);
	if (rc) {
2336
		QETH_CARD_TEXT_(card, 2, "6err%d", rc);
2337
		rc = -ENODEV;
F
Frank Blaschka 已提交
2338 2339 2340 2341 2342
		goto out_remove;
	}
	card->state = CARD_STATE_SOFTSETUP;

	qeth_set_allowed_threads(card, 0xffffffff, 0);
2343
	qeth_l3_recover_ip(card);
2344

2345 2346 2347 2348 2349
	if (!qeth_netdev_is_registered(dev)) {
		rc = qeth_l3_setup_netdev(card, carrier_ok);
		if (rc)
			goto out_remove;
	} else {
2350
		rtnl_lock();
2351 2352 2353 2354 2355
		if (carrier_ok)
			netif_carrier_on(dev);
		else
			netif_carrier_off(dev);

2356
		netif_device_attach(dev);
2357 2358
		qeth_enable_hw_features(dev);

2359 2360
		if (card->info.open_when_online) {
			card->info.open_when_online = 0;
2361
			dev_open(dev, NULL);
2362
		}
2363
		rtnl_unlock();
F
Frank Blaschka 已提交
2364
	}
S
Stefan Raspl 已提交
2365
	qeth_trace_features(card);
F
Frank Blaschka 已提交
2366 2367
	/* let user_space know that device is online */
	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
2368
	mutex_unlock(&card->conf_mutex);
2369
	mutex_unlock(&card->discipline_mutex);
F
Frank Blaschka 已提交
2370 2371
	return 0;
out_remove:
2372
	qeth_l3_stop_card(card);
F
Frank Blaschka 已提交
2373 2374 2375
	ccw_device_set_offline(CARD_DDEV(card));
	ccw_device_set_offline(CARD_WDEV(card));
	ccw_device_set_offline(CARD_RDEV(card));
2376
	qdio_free(CARD_DDEV(card));
2377

2378
	mutex_unlock(&card->conf_mutex);
2379
	mutex_unlock(&card->discipline_mutex);
2380
	return rc;
F
Frank Blaschka 已提交
2381 2382 2383 2384 2385 2386 2387 2388
}

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;

2389
	mutex_lock(&card->discipline_mutex);
2390
	mutex_lock(&card->conf_mutex);
2391
	QETH_CARD_TEXT(card, 3, "setoffl");
F
Frank Blaschka 已提交
2392

2393 2394 2395 2396 2397
	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}

2398
	rtnl_lock();
2399
	card->info.open_when_online = card->dev->flags & IFF_UP;
2400
	dev_close(card->dev);
2401
	netif_device_detach(card->dev);
2402
	netif_carrier_off(card->dev);
2403 2404
	rtnl_unlock();

2405
	qeth_l3_stop_card(card);
2406
	if (card->options.cq == QETH_CQ_ENABLED) {
2407 2408 2409 2410
		rtnl_lock();
		call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
		rtnl_unlock();
	}
F
Frank Blaschka 已提交
2411 2412 2413 2414 2415 2416
	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)
2417
		QETH_CARD_TEXT_(card, 2, "1err%d", rc);
2418
	qdio_free(CARD_DDEV(card));
2419

F
Frank Blaschka 已提交
2420 2421
	/* let user_space know that device is offline */
	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
2422
	mutex_unlock(&card->conf_mutex);
2423
	mutex_unlock(&card->discipline_mutex);
F
Frank Blaschka 已提交
2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437
	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 已提交
2438 2439
	QETH_CARD_TEXT(card, 2, "recover1");
	QETH_CARD_HEX(card, 2, &card, sizeof(void *));
F
Frank Blaschka 已提交
2440 2441
	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
		return 0;
C
Carsten Otte 已提交
2442
	QETH_CARD_TEXT(card, 2, "recover2");
2443 2444
	dev_warn(&card->gdev->dev,
		"A recovery process has been started for the device\n");
F
Frank Blaschka 已提交
2445
	__qeth_l3_set_offline(card->gdev, 1);
2446
	rc = qeth_l3_set_online(card->gdev);
F
Frank Blaschka 已提交
2447
	if (!rc)
2448 2449
		dev_info(&card->gdev->dev,
			"Device successfully recovered!\n");
2450
	else {
2451
		ccwgroup_set_offline(card->gdev);
S
Stefan Raspl 已提交
2452
		dev_warn(&card->gdev->dev, "The qeth device driver "
2453
				"failed to recover an error on the device\n");
2454
	}
2455 2456
	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
F
Frank Blaschka 已提交
2457 2458 2459
	return 0;
}

2460 2461 2462 2463 2464 2465 2466
/* 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;
}

2467
struct qeth_discipline qeth_l3_discipline = {
2468
	.devtype = &qeth_l3_devtype,
2469
	.process_rx_buffer = qeth_l3_process_inbound_buffer,
2470 2471
	.recover = qeth_l3_recover,
	.setup = qeth_l3_probe_device,
F
Frank Blaschka 已提交
2472 2473 2474
	.remove = qeth_l3_remove_device,
	.set_online = qeth_l3_set_online,
	.set_offline = qeth_l3_set_offline,
2475
	.do_ioctl = qeth_l3_do_ioctl,
2476
	.control_event_handler = qeth_l3_control_event,
F
Frank Blaschka 已提交
2477
};
2478
EXPORT_SYMBOL_GPL(qeth_l3_discipline);
F
Frank Blaschka 已提交
2479

2480 2481 2482 2483 2484 2485
static int qeth_l3_handle_ip_event(struct qeth_card *card,
				   struct qeth_ipaddr *addr,
				   unsigned long event)
{
	switch (event) {
	case NETDEV_UP:
2486
		qeth_l3_modify_ip(card, addr, true);
2487 2488
		return NOTIFY_OK;
	case NETDEV_DOWN:
2489
		qeth_l3_modify_ip(card, addr, false);
2490 2491 2492 2493 2494 2495
		return NOTIFY_OK;
	default:
		return NOTIFY_DONE;
	}
}

2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519
struct qeth_l3_ip_event_work {
	struct work_struct work;
	struct qeth_card *card;
	struct qeth_ipaddr addr;
};

#define to_ip_work(w) container_of((w), struct qeth_l3_ip_event_work, work)

static void qeth_l3_add_ip_worker(struct work_struct *work)
{
	struct qeth_l3_ip_event_work *ip_work = to_ip_work(work);

	qeth_l3_modify_ip(ip_work->card, &ip_work->addr, true);
	kfree(work);
}

static void qeth_l3_delete_ip_worker(struct work_struct *work)
{
	struct qeth_l3_ip_event_work *ip_work = to_ip_work(work);

	qeth_l3_modify_ip(ip_work->card, &ip_work->addr, false);
	kfree(work);
}

2520 2521 2522 2523 2524 2525 2526 2527 2528 2529
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 已提交
2530
static int qeth_l3_ip_event(struct notifier_block *this,
2531
			    unsigned long event, void *ptr)
F
Frank Blaschka 已提交
2532
{
2533

F
Frank Blaschka 已提交
2534
	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
2535
	struct net_device *dev = ifa->ifa_dev->dev;
2536
	struct qeth_ipaddr addr;
F
Frank Blaschka 已提交
2537 2538
	struct qeth_card *card;

2539
	if (dev_net(dev) != &init_net)
2540 2541
		return NOTIFY_DONE;

F
Frank Blaschka 已提交
2542 2543 2544
	card = qeth_l3_get_card_from_dev(dev);
	if (!card)
		return NOTIFY_DONE;
2545
	QETH_CARD_TEXT(card, 3, "ipevent");
F
Frank Blaschka 已提交
2546

2547
	qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4);
2548
	addr.u.a4.addr = ifa->ifa_address;
2549
	addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask);
2550

2551
	return qeth_l3_handle_ip_event(card, &addr, event);
F
Frank Blaschka 已提交
2552 2553 2554 2555 2556 2557 2558 2559
}

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

static int qeth_l3_ip6_event(struct notifier_block *this,
2560
			     unsigned long event, void *ptr)
F
Frank Blaschka 已提交
2561 2562
{
	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
2563
	struct net_device *dev = ifa->idev->dev;
2564
	struct qeth_l3_ip_event_work *ip_work;
F
Frank Blaschka 已提交
2565 2566
	struct qeth_card *card;

2567 2568 2569
	if (event != NETDEV_UP && event != NETDEV_DOWN)
		return NOTIFY_DONE;

F
Frank Blaschka 已提交
2570 2571 2572
	card = qeth_l3_get_card_from_dev(dev);
	if (!card)
		return NOTIFY_DONE;
C
Carsten Otte 已提交
2573
	QETH_CARD_TEXT(card, 3, "ip6event");
F
Frank Blaschka 已提交
2574 2575 2576
	if (!qeth_is_supported(card, IPA_IPV6))
		return NOTIFY_DONE;

2577 2578 2579
	ip_work = kmalloc(sizeof(*ip_work), GFP_ATOMIC);
	if (!ip_work)
		return NOTIFY_DONE;
2580

2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
	if (event == NETDEV_UP)
		INIT_WORK(&ip_work->work, qeth_l3_add_ip_worker);
	else
		INIT_WORK(&ip_work->work, qeth_l3_delete_ip_worker);

	ip_work->card = card;
	qeth_l3_init_ipaddr(&ip_work->addr, QETH_IP_TYPE_NORMAL,
			    QETH_PROT_IPV6);
	ip_work->addr.u.a6.addr = ifa->addr;
	ip_work->addr.u.a6.pfxlen = ifa->prefix_len;

	queue_work(card->cmd_wq, &ip_work->work);
	return NOTIFY_OK;
F
Frank Blaschka 已提交
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
}

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 已提交
2605
	QETH_DBF_TEXT(SETUP, 5, "regnotif");
F
Frank Blaschka 已提交
2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618
	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 已提交
2619
	QETH_DBF_TEXT(SETUP, 5, "unregnot");
S
Stefan Raspl 已提交
2620 2621
	WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
	WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
F
Frank Blaschka 已提交
2622 2623 2624 2625
}

static int __init qeth_l3_init(void)
{
2626
	pr_info("register layer 3 discipline\n");
J
Julian Wiedmann 已提交
2627
	return qeth_l3_register_notifiers();
F
Frank Blaschka 已提交
2628 2629 2630 2631 2632
}

static void __exit qeth_l3_exit(void)
{
	qeth_l3_unregister_notifiers();
2633
	pr_info("unregister layer 3 discipline\n");
F
Frank Blaschka 已提交
2634 2635 2636 2637 2638 2639 2640
}

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");