lec.c 66.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * lec.c: Lan Emulation driver
L
Linus Torvalds 已提交
3
 *
4
 * Marko Kiiskila <mkiiskila@yahoo.com>
L
Linus Torvalds 已提交
5 6 7 8
 */

#include <linux/kernel.h>
#include <linux/bitops.h>
9
#include <linux/capability.h>
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

/* We are ethernet device */
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <net/arp.h>
#include <net/dst.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>

/* TokenRing if needed */
#ifdef CONFIG_TR
#include <linux/trdevice.h>
#endif

/* And atm device */
#include <linux/atmdev.h>
#include <linux/atmlec.h>

/* Proxy LEC knows about bridging */
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
#include "../bridge/br_private.h"

40
static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48 49 50
#endif

/* Modular too */
#include <linux/module.h>
#include <linux/init.h>

#include "lec.h"
#include "lec_arpc.h"
#include "resources.h"

51 52 53 54 55
#define DUMP_PACKETS 0		/*
				 * 0 = None,
				 * 1 = 30 first bytes
				 * 2 = Whole packet
				 */
L
Linus Torvalds 已提交
56

57 58 59 60
#define LEC_UNRES_QUE_LEN 8	/*
				 * number of tx packets to queue for a
				 * single destination while waiting for SVC
				 */
L
Linus Torvalds 已提交
61 62 63 64 65 66

static int lec_open(struct net_device *dev);
static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int lec_close(struct net_device *dev);
static struct net_device_stats *lec_get_stats(struct net_device *dev);
static void lec_init(struct net_device *dev);
67 68
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
					  unsigned char *mac_addr);
L
Linus Torvalds 已提交
69
static int lec_arp_remove(struct lec_priv *priv,
70
			  struct lec_arp_table *to_remove);
L
Linus Torvalds 已提交
71
/* LANE2 functions */
72 73
static void lane2_associate_ind(struct net_device *dev, u8 *mac_address,
				u8 *tlvs, u32 sizeoftlvs);
L
Linus Torvalds 已提交
74
static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
75 76 77
			 u8 **tlvs, u32 *sizeoftlvs);
static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
			       u8 *tlvs, u32 sizeoftlvs);
L
Linus Torvalds 已提交
78

79
static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
L
Linus Torvalds 已提交
80 81 82 83 84
			   unsigned long permanent);
static void lec_arp_check_empties(struct lec_priv *priv,
				  struct atm_vcc *vcc, struct sk_buff *skb);
static void lec_arp_destroy(struct lec_priv *priv);
static void lec_arp_init(struct lec_priv *priv);
85
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
L
Linus Torvalds 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98
				       unsigned char *mac_to_find,
				       int is_rdesc,
				       struct lec_arp_table **ret_entry);
static void lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
			   unsigned char *atm_addr, unsigned long remoteflag,
			   unsigned int targetless_le_arp);
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
static void lec_set_flush_tran_id(struct lec_priv *priv,
				  unsigned char *atm_addr,
				  unsigned long tran_id);
static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
			  struct atm_vcc *vcc,
99 100
			  void (*old_push) (struct atm_vcc *vcc,
					    struct sk_buff *skb));
L
Linus Torvalds 已提交
101 102
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);

103 104 105 106 107 108 109 110 111 112 113 114 115
/* must be done under lec_arp_lock */
static inline void lec_arp_hold(struct lec_arp_table *entry)
{
	atomic_inc(&entry->usage);
}

static inline void lec_arp_put(struct lec_arp_table *entry)
{
	if (atomic_dec_and_test(&entry->usage))
		kfree(entry);
}


L
Linus Torvalds 已提交
116
static struct lane2_ops lane2_ops = {
117 118 119
	lane2_resolve,		/* resolve,             spec 3.1.3 */
	lane2_associate_req,	/* associate_req,       spec 3.1.4 */
	NULL			/* associate indicator, spec 3.1.5 */
L
Linus Torvalds 已提交
120 121
};

122
static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
L
Linus Torvalds 已提交
123 124 125 126 127 128 129

/* Device structures */
static struct net_device *dev_lec[MAX_LEC_ITF];

#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
{
130 131 132 133 134 135 136 137 138 139 140 141
	struct ethhdr *eth;
	char *buff;
	struct lec_priv *priv;

	/*
	 * Check if this is a BPDU. If so, ask zeppelin to send
	 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
	 * as the Config BPDU has
	 */
	eth = (struct ethhdr *)skb->data;
	buff = skb->data + skb->dev->hard_header_len;
	if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
L
Linus Torvalds 已提交
142
		struct sock *sk;
143 144 145 146 147 148 149 150 151 152 153 154 155 156
		struct sk_buff *skb2;
		struct atmlec_msg *mesg;

		skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
		if (skb2 == NULL)
			return;
		skb2->len = sizeof(struct atmlec_msg);
		mesg = (struct atmlec_msg *)skb2->data;
		mesg->type = l_topology_change;
		buff += 4;
		mesg->content.normal.flag = *buff & 0x01;	/* 0x01 is topology change */

		priv = (struct lec_priv *)dev->priv;
		atm_force_charge(priv->lecd, skb2->truesize);
L
Linus Torvalds 已提交
157
		sk = sk_atm(priv->lecd);
158 159 160
		skb_queue_tail(&sk->sk_receive_queue, skb2);
		sk->sk_data_ready(sk, skb2->len);
	}
L
Linus Torvalds 已提交
161

162
	return;
L
Linus Torvalds 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
}
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */

/*
 * Modelled after tr_type_trans
 * All multicast and ARE or STE frames go to BUS.
 * Non source routed frames go by destination address.
 * Last hop source routed frames go by destination address.
 * Not last hop source routed frames go by _next_ route descriptor.
 * Returns pointer to destination MAC address or fills in rdesc
 * and returns NULL.
 */
#ifdef CONFIG_TR
static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
{
178
	struct trh_hdr *trh;
179
	unsigned int riflen, num_rdsc;
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

	trh = (struct trh_hdr *)packet;
	if (trh->daddr[0] & (uint8_t) 0x80)
		return bus_mac;	/* multicast */

	if (trh->saddr[0] & TR_RII) {
		riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
		if ((ntohs(trh->rcf) >> 13) != 0)
			return bus_mac;	/* ARE or STE */
	} else
		return trh->daddr;	/* not source routed */

	if (riflen < 6)
		return trh->daddr;	/* last hop, source routed */

	/* riflen is 6 or more, packet has more than one route descriptor */
	num_rdsc = (riflen / 2) - 1;
	memset(rdesc, 0, ETH_ALEN);
	/* offset 4 comes from LAN destination field in LE control frames */
	if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT))
A
Al Viro 已提交
200
		memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(__be16));
201
	else {
A
Al Viro 已提交
202
		memcpy(&rdesc[4], &trh->rseg[1], sizeof(__be16));
203 204 205 206
		rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
	}

	return NULL;
L
Linus Torvalds 已提交
207 208 209 210 211 212 213 214 215 216 217 218
}
#endif /* CONFIG_TR */

/*
 * Open/initialize the netdevice. This is called (in the current kernel)
 * sometime after booting when the 'ifconfig' program is run.
 *
 * This routine should set everything up anew at each open, even
 * registers that "should" only need to be set once at boot, so that
 * there is non-reboot way to recover if something goes wrong.
 */

219
static int lec_open(struct net_device *dev)
L
Linus Torvalds 已提交
220
{
221 222
	struct lec_priv *priv = (struct lec_priv *)dev->priv;

L
Linus Torvalds 已提交
223
	netif_start_queue(dev);
224 225 226
	memset(&priv->stats, 0, sizeof(struct net_device_stats));

	return 0;
L
Linus Torvalds 已提交
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
}

static __inline__ void
lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
{
	ATM_SKB(skb)->vcc = vcc;
	ATM_SKB(skb)->atm_options = vcc->atm_options;

	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
	if (vcc->send(vcc, skb) < 0) {
		priv->stats.tx_dropped++;
		return;
	}

	priv->stats.tx_packets++;
	priv->stats.tx_bytes += skb->len;
}

245
static void lec_tx_timeout(struct net_device *dev)
L
Linus Torvalds 已提交
246 247 248 249 250 251
{
	printk(KERN_INFO "%s: tx timeout\n", dev->name);
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}

252
static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
L
Linus Torvalds 已提交
253
{
254 255 256 257
	struct sk_buff *skb2;
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
	struct lecdatahdr_8023 *lec_h;
	struct atm_vcc *vcc;
L
Linus Torvalds 已提交
258
	struct lec_arp_table *entry;
259
	unsigned char *dst;
L
Linus Torvalds 已提交
260 261
	int min_frame_size;
#ifdef CONFIG_TR
262
	unsigned char rdesc[ETH_ALEN];	/* Token Ring route descriptor */
L
Linus Torvalds 已提交
263
#endif
264
	int is_rdesc;
L
Linus Torvalds 已提交
265
#if DUMP_PACKETS > 0
266 267
	char buf[300];
	int i = 0;
L
Linus Torvalds 已提交
268
#endif /* DUMP_PACKETS >0 */
269

270
	pr_debug("lec_start_xmit called\n");
271 272 273 274 275 276 277
	if (!priv->lecd) {
		printk("%s:No lecd attached\n", dev->name);
		priv->stats.tx_errors++;
		netif_stop_queue(dev);
		return -EUNATCH;
	}

278
	pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
279
		(long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb),
280
		(long)skb_end_pointer(skb));
L
Linus Torvalds 已提交
281
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
282 283
	if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
		lec_handle_bridge(skb, dev);
L
Linus Torvalds 已提交
284 285
#endif

286 287
	/* Make sure we have room for lec_id */
	if (skb_headroom(skb) < 2) {
L
Linus Torvalds 已提交
288

289
		pr_debug("lec_start_xmit: reallocating skb\n");
290 291 292 293 294 295 296
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
			return 0;
		skb = skb2;
	}
	skb_push(skb, 2);
L
Linus Torvalds 已提交
297

298 299 300
	/* Put le header to place, works for TokenRing too */
	lec_h = (struct lecdatahdr_8023 *)skb->data;
	lec_h->le_header = htons(priv->lecid);
L
Linus Torvalds 已提交
301 302

#ifdef CONFIG_TR
303 304 305 306 307 308 309 310 311 312 313
	/*
	 * Ugly. Use this to realign Token Ring packets for
	 * e.g. PCA-200E driver.
	 */
	if (priv->is_trdev) {
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
			return 0;
		skb = skb2;
	}
L
Linus Torvalds 已提交
314 315 316
#endif

#if DUMP_PACKETS > 0
317 318
	printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
	       skb->len, priv->lecid);
L
Linus Torvalds 已提交
319
#if DUMP_PACKETS >= 2
320 321 322
	for (i = 0; i < skb->len && i < 99; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
323
#elif DUMP_PACKETS >= 1
324 325 326
	for (i = 0; i < skb->len && i < 30; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
327
#endif /* DUMP_PACKETS >= 1 */
328 329 330 331
	if (i == skb->len)
		printk("%s\n", buf);
	else
		printk("%s...\n", buf);
L
Linus Torvalds 已提交
332 333
#endif /* DUMP_PACKETS > 0 */

334
	/* Minimum ethernet-frame size */
L
Linus Torvalds 已提交
335
#ifdef CONFIG_TR
336 337
	if (priv->is_trdev)
		min_frame_size = LEC_MINIMUM_8025_SIZE;
L
Linus Torvalds 已提交
338 339
	else
#endif
340 341 342 343 344 345 346 347 348 349 350 351 352
		min_frame_size = LEC_MINIMUM_8023_SIZE;
	if (skb->len < min_frame_size) {
		if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
			skb2 = skb_copy_expand(skb, 0,
					       min_frame_size - skb->truesize,
					       GFP_ATOMIC);
			dev_kfree_skb(skb);
			if (skb2 == NULL) {
				priv->stats.tx_dropped++;
				return 0;
			}
			skb = skb2;
		}
L
Linus Torvalds 已提交
353
		skb_put(skb, min_frame_size - skb->len);
354 355 356 357 358
	}

	/* Send to right vcc */
	is_rdesc = 0;
	dst = lec_h->h_dest;
L
Linus Torvalds 已提交
359
#ifdef CONFIG_TR
360 361 362 363 364 365 366
	if (priv->is_trdev) {
		dst = get_tr_dst(skb->data + 2, rdesc);
		if (dst == NULL) {
			dst = rdesc;
			is_rdesc = 1;
		}
	}
L
Linus Torvalds 已提交
367
#endif
368 369
	entry = NULL;
	vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
370
	pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n", dev->name,
371 372 373
		vcc, vcc ? vcc->flags : 0, entry);
	if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
		if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
374
			pr_debug("%s:lec_start_xmit: queuing packet, ",
375
				dev->name);
376 377 378 379
			pr_debug("MAC address " MAC_FMT "\n",
				 lec_h->h_dest[0], lec_h->h_dest[1],
				 lec_h->h_dest[2], lec_h->h_dest[3],
				 lec_h->h_dest[4], lec_h->h_dest[5]);
380 381
			skb_queue_tail(&entry->tx_wait, skb);
		} else {
382
			pr_debug
383 384
			    ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
			     dev->name);
385 386 387 388
			pr_debug("MAC address " MAC_FMT "\n",
				 lec_h->h_dest[0], lec_h->h_dest[1],
				 lec_h->h_dest[2], lec_h->h_dest[3],
				 lec_h->h_dest[4], lec_h->h_dest[5]);
389 390 391
			priv->stats.tx_dropped++;
			dev_kfree_skb(skb);
		}
392
		goto out;
393 394 395
	}
#if DUMP_PACKETS > 0
	printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci);
L
Linus Torvalds 已提交
396
#endif /* DUMP_PACKETS > 0 */
397 398

	while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
399
		pr_debug("lec.c: emptying tx queue, ");
400 401 402 403
		pr_debug("MAC address " MAC_FMT "\n",
			 lec_h->h_dest[0], lec_h->h_dest[1],
			 lec_h->h_dest[2], lec_h->h_dest[3],
			 lec_h->h_dest[4], lec_h->h_dest[5]);
L
Linus Torvalds 已提交
404
		lec_send(vcc, skb2, priv);
405
	}
L
Linus Torvalds 已提交
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424

	lec_send(vcc, skb, priv);

	if (!atm_may_send(vcc, 0)) {
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);

		vpriv->xoff = 1;
		netif_stop_queue(dev);

		/*
		 * vcc->pop() might have occurred in between, making
		 * the vcc usuable again.  Since xmit is serialized,
		 * this is the only situation we have to re-test.
		 */

		if (atm_may_send(vcc, 0))
			netif_wake_queue(dev);
	}

425 426 427
out:
	if (entry)
		lec_arp_put(entry);
L
Linus Torvalds 已提交
428
	dev->trans_start = jiffies;
429
	return 0;
L
Linus Torvalds 已提交
430 431 432
}

/* The inverse routine to net_open(). */
433
static int lec_close(struct net_device *dev)
L
Linus Torvalds 已提交
434
{
435 436
	netif_stop_queue(dev);
	return 0;
L
Linus Torvalds 已提交
437 438 439 440 441 442
}

/*
 * Get the current statistics.
 * This may be called with the card open or closed.
 */
443
static struct net_device_stats *lec_get_stats(struct net_device *dev)
L
Linus Torvalds 已提交
444
{
445
	return &((struct lec_priv *)dev->priv)->stats;
L
Linus Torvalds 已提交
446 447
}

448
static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
449 450
{
	unsigned long flags;
451 452 453 454 455 456
	struct net_device *dev = (struct net_device *)vcc->proto_data;
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
	struct atmlec_msg *mesg;
	struct lec_arp_table *entry;
	int i;
	char *tmp;		/* FIXME */
L
Linus Torvalds 已提交
457 458

	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
459 460 461
	mesg = (struct atmlec_msg *)skb->data;
	tmp = skb->data;
	tmp += sizeof(struct atmlec_msg);
462
	pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
	switch (mesg->type) {
	case l_set_mac_addr:
		for (i = 0; i < 6; i++) {
			dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
		}
		break;
	case l_del_mac_addr:
		for (i = 0; i < 6; i++) {
			dev->dev_addr[i] = 0;
		}
		break;
	case l_addr_delete:
		lec_addr_delete(priv, mesg->content.normal.atm_addr,
				mesg->content.normal.flag);
		break;
	case l_topology_change:
		priv->topology_change = mesg->content.normal.flag;
		break;
	case l_flush_complete:
		lec_flush_complete(priv, mesg->content.normal.flag);
		break;
	case l_narp_req:	/* LANE2: see 7.1.35 in the lane2 spec */
L
Linus Torvalds 已提交
485
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
486 487
		entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
		lec_arp_remove(priv, entry);
L
Linus Torvalds 已提交
488 489
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

490 491 492 493 494 495 496 497
		if (mesg->content.normal.no_source_le_narp)
			break;
		/* FALL THROUGH */
	case l_arp_update:
		lec_arp_update(priv, mesg->content.normal.mac_addr,
			       mesg->content.normal.atm_addr,
			       mesg->content.normal.flag,
			       mesg->content.normal.targetless_le_arp);
498
		pr_debug("lec: in l_arp_update\n");
499
		if (mesg->sizeoftlvs != 0) {	/* LANE2 3.1.5 */
500
			pr_debug("lec: LANE2 3.1.5, got tlvs, size %d\n",
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
				mesg->sizeoftlvs);
			lane2_associate_ind(dev, mesg->content.normal.mac_addr,
					    tmp, mesg->sizeoftlvs);
		}
		break;
	case l_config:
		priv->maximum_unknown_frame_count =
		    mesg->content.config.maximum_unknown_frame_count;
		priv->max_unknown_frame_time =
		    (mesg->content.config.max_unknown_frame_time * HZ);
		priv->max_retry_count = mesg->content.config.max_retry_count;
		priv->aging_time = (mesg->content.config.aging_time * HZ);
		priv->forward_delay_time =
		    (mesg->content.config.forward_delay_time * HZ);
		priv->arp_response_time =
		    (mesg->content.config.arp_response_time * HZ);
		priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);
		priv->path_switching_delay =
		    (mesg->content.config.path_switching_delay * HZ);
		priv->lane_version = mesg->content.config.lane_version;	/* LANE2 */
L
Linus Torvalds 已提交
521 522 523 524 525
		priv->lane2_ops = NULL;
		if (priv->lane_version > 1)
			priv->lane2_ops = &lane2_ops;
		if (dev->change_mtu(dev, mesg->content.config.mtu))
			printk("%s: change_mtu to %d failed\n", dev->name,
526
			       mesg->content.config.mtu);
L
Linus Torvalds 已提交
527
		priv->is_proxy = mesg->content.config.is_proxy;
528 529 530 531 532 533 534 535 536 537
		break;
	case l_flush_tran_id:
		lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
				      mesg->content.normal.flag);
		break;
	case l_set_lecid:
		priv->lecid =
		    (unsigned short)(0xffff & mesg->content.normal.flag);
		break;
	case l_should_bridge:
L
Linus Torvalds 已提交
538
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
539 540 541
		{
			struct net_bridge_fdb_entry *f;

542
			pr_debug
543
			    ("%s: bridge zeppelin asks about " MAC_FMT "\n",
544
			     dev->name,
545 546 547 548 549 550
			     mesg->content.proxy.mac_addr[0],
			     mesg->content.proxy.mac_addr[1],
			     mesg->content.proxy.mac_addr[2],
			     mesg->content.proxy.mac_addr[3],
			     mesg->content.proxy.mac_addr[4],
			     mesg->content.proxy.mac_addr[5]);
551 552 553 554 555 556 557 558 559 560 561 562

			if (br_fdb_get_hook == NULL || dev->br_port == NULL)
				break;

			f = br_fdb_get_hook(dev->br_port->br,
					    mesg->content.proxy.mac_addr);
			if (f != NULL && f->dst->dev != dev
			    && f->dst->state == BR_STATE_FORWARDING) {
				/* hit from bridge table, send LE_ARP_RESPONSE */
				struct sk_buff *skb2;
				struct sock *sk;

563
				pr_debug
564 565 566 567 568 569 570 571 572 573
				    ("%s: entry found, responding to zeppelin\n",
				     dev->name);
				skb2 =
				    alloc_skb(sizeof(struct atmlec_msg),
					      GFP_ATOMIC);
				if (skb2 == NULL) {
					br_fdb_put_hook(f);
					break;
				}
				skb2->len = sizeof(struct atmlec_msg);
574 575
				skb_copy_to_linear_data(skb2, mesg,
							sizeof(*mesg));
576 577 578 579 580 581 582 583
				atm_force_charge(priv->lecd, skb2->truesize);
				sk = sk_atm(priv->lecd);
				skb_queue_tail(&sk->sk_receive_queue, skb2);
				sk->sk_data_ready(sk, skb2->len);
			}
			if (f != NULL)
				br_fdb_put_hook(f);
		}
L
Linus Torvalds 已提交
584
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
585 586 587 588 589 590 591 592
		break;
	default:
		printk("%s: Unknown message type %d\n", dev->name, mesg->type);
		dev_kfree_skb(skb);
		return -EINVAL;
	}
	dev_kfree_skb(skb);
	return 0;
L
Linus Torvalds 已提交
593 594
}

595
static void lec_atm_close(struct atm_vcc *vcc)
L
Linus Torvalds 已提交
596
{
597 598 599
	struct sk_buff *skb;
	struct net_device *dev = (struct net_device *)vcc->proto_data;
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
L
Linus Torvalds 已提交
600

601 602
	priv->lecd = NULL;
	/* Do something needful? */
L
Linus Torvalds 已提交
603

604 605
	netif_stop_queue(dev);
	lec_arp_destroy(priv);
L
Linus Torvalds 已提交
606

607
	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
L
Linus Torvalds 已提交
608
		printk("%s lec_atm_close: closing with messages pending\n",
609 610 611
		       dev->name);
	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
		atm_return(vcc, skb->truesize);
L
Linus Torvalds 已提交
612
		dev_kfree_skb(skb);
613 614
	}

L
Linus Torvalds 已提交
615
	printk("%s: Shut down!\n", dev->name);
616
	module_put(THIS_MODULE);
L
Linus Torvalds 已提交
617 618 619
}

static struct atmdev_ops lecdev_ops = {
620 621
	.close = lec_atm_close,
	.send = lec_atm_send
L
Linus Torvalds 已提交
622 623 624
};

static struct atm_dev lecatm_dev = {
625 626 627
	.ops = &lecdev_ops,
	.type = "lec",
	.number = 999,		/* dummy device number */
628
	.lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)
L
Linus Torvalds 已提交
629 630 631 632 633 634
};

/*
 * LANE2: new argument struct sk_buff *data contains
 * the LE_ARP based TLVs introduced in the LANE2 spec
 */
635 636 637 638
static int
send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
	     unsigned char *mac_addr, unsigned char *atm_addr,
	     struct sk_buff *data)
L
Linus Torvalds 已提交
639 640 641 642 643 644 645 646 647 648 649 650 651
{
	struct sock *sk;
	struct sk_buff *skb;
	struct atmlec_msg *mesg;

	if (!priv || !priv->lecd) {
		return -1;
	}
	skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
	if (!skb)
		return -1;
	skb->len = sizeof(struct atmlec_msg);
	mesg = (struct atmlec_msg *)skb->data;
652
	memset(mesg, 0, sizeof(struct atmlec_msg));
L
Linus Torvalds 已提交
653
	mesg->type = type;
654 655
	if (data != NULL)
		mesg->sizeoftlvs = data->len;
L
Linus Torvalds 已提交
656 657
	if (mac_addr)
		memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
658 659
	else
		mesg->content.normal.targetless_le_arp = 1;
L
Linus Torvalds 已提交
660 661 662
	if (atm_addr)
		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);

663
	atm_force_charge(priv->lecd, skb->truesize);
L
Linus Torvalds 已提交
664 665
	sk = sk_atm(priv->lecd);
	skb_queue_tail(&sk->sk_receive_queue, skb);
666
	sk->sk_data_ready(sk, skb->len);
L
Linus Torvalds 已提交
667

668
	if (data != NULL) {
669
		pr_debug("lec: about to send %d bytes of data\n", data->len);
670 671 672 673
		atm_force_charge(priv->lecd, data->truesize);
		skb_queue_tail(&sk->sk_receive_queue, data);
		sk->sk_data_ready(sk, skb->len);
	}
L
Linus Torvalds 已提交
674

675
	return 0;
L
Linus Torvalds 已提交
676 677 678 679 680
}

/* shamelessly stolen from drivers/net/net_init.c */
static int lec_change_mtu(struct net_device *dev, int new_mtu)
{
681 682 683 684
	if ((new_mtu < 68) || (new_mtu > 18190))
		return -EINVAL;
	dev->mtu = new_mtu;
	return 0;
L
Linus Torvalds 已提交
685 686 687 688
}

static void lec_set_multicast_list(struct net_device *dev)
{
689 690 691 692 693
	/*
	 * by default, all multicast frames arrive over the bus.
	 * eventually support selective multicast service
	 */
	return;
L
Linus Torvalds 已提交
694 695
}

696
static void lec_init(struct net_device *dev)
L
Linus Torvalds 已提交
697
{
698 699 700 701
	dev->change_mtu = lec_change_mtu;
	dev->open = lec_open;
	dev->stop = lec_close;
	dev->hard_start_xmit = lec_start_xmit;
L
Linus Torvalds 已提交
702 703
	dev->tx_timeout = lec_tx_timeout;

704 705 706 707 708
	dev->get_stats = lec_get_stats;
	dev->set_multicast_list = lec_set_multicast_list;
	dev->do_ioctl = NULL;
	printk("%s: Initialized!\n", dev->name);
	return;
L
Linus Torvalds 已提交
709 710 711
}

static unsigned char lec_ctrl_magic[] = {
712 713 714 715 716
	0xff,
	0x00,
	0x01,
	0x01
};
L
Linus Torvalds 已提交
717

718 719 720 721
#define LEC_DATA_DIRECT_8023  2
#define LEC_DATA_DIRECT_8025  3

static int lec_is_data_direct(struct atm_vcc *vcc)
722
{
723 724
	return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
		(vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
725
}
726

727
static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
728
{
729
	unsigned long flags;
730 731
	struct net_device *dev = (struct net_device *)vcc->proto_data;
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
L
Linus Torvalds 已提交
732 733

#if DUMP_PACKETS >0
734 735
	int i = 0;
	char buf[300];
L
Linus Torvalds 已提交
736

737 738
	printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
	       vcc->vpi, vcc->vci);
L
Linus Torvalds 已提交
739
#endif
740
	if (!skb) {
741
		pr_debug("%s: null skb\n", dev->name);
742 743 744
		lec_vcc_close(priv, vcc);
		return;
	}
L
Linus Torvalds 已提交
745
#if DUMP_PACKETS > 0
746 747
	printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
	       skb->len, priv->lecid);
L
Linus Torvalds 已提交
748
#if DUMP_PACKETS >= 2
749 750 751
	for (i = 0; i < skb->len && i < 99; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
752
#elif DUMP_PACKETS >= 1
753 754 755
	for (i = 0; i < skb->len && i < 30; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
756
#endif /* DUMP_PACKETS >= 1 */
757 758 759 760
	if (i == skb->len)
		printk("%s\n", buf);
	else
		printk("%s...\n", buf);
L
Linus Torvalds 已提交
761
#endif /* DUMP_PACKETS > 0 */
762
	if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {	/* Control frame, to daemon */
L
Linus Torvalds 已提交
763 764
		struct sock *sk = sk_atm(vcc);

765
		pr_debug("%s: To daemon\n", dev->name);
766 767 768
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
	} else {		/* Data frame, queue to protocol handlers */
769
		struct lec_arp_table *entry;
770 771 772
		unsigned char *src, *dst;

		atm_return(vcc, skb->truesize);
A
Al Viro 已提交
773
		if (*(__be16 *) skb->data == htons(priv->lecid) ||
774 775 776 777 778
		    !priv->lecd || !(dev->flags & IFF_UP)) {
			/*
			 * Probably looping back, or if lecd is missing,
			 * lecd has gone down
			 */
779
			pr_debug("Ignoring frame...\n");
780 781 782
			dev_kfree_skb(skb);
			return;
		}
L
Linus Torvalds 已提交
783
#ifdef CONFIG_TR
784 785 786
		if (priv->is_trdev)
			dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
		else
L
Linus Torvalds 已提交
787
#endif
788
			dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
789

790 791
		/*
		 * If this is a Data Direct VCC, and the VCC does not match
792 793 794 795 796 797
		 * the LE_ARP cache entry, delete the LE_ARP cache entry.
		 */
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
		if (lec_is_data_direct(vcc)) {
#ifdef CONFIG_TR
			if (priv->is_trdev)
798 799 800
				src =
				    ((struct lecdatahdr_8025 *)skb->data)->
				    h_source;
801 802
			else
#endif
803 804 805
				src =
				    ((struct lecdatahdr_8023 *)skb->data)->
				    h_source;
806 807 808
			entry = lec_arp_find(priv, src);
			if (entry && entry->vcc != vcc) {
				lec_arp_remove(priv, entry);
809
				lec_arp_put(entry);
810 811 812
			}
		}
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
L
Linus Torvalds 已提交
813

814 815
		if (!(dst[0] & 0x01) &&	/* Never filter Multi/Broadcast */
		    !priv->is_proxy &&	/* Proxy wants all the packets */
L
Linus Torvalds 已提交
816
		    memcmp(dst, dev->dev_addr, dev->addr_len)) {
817 818 819
			dev_kfree_skb(skb);
			return;
		}
820
		if (!hlist_empty(&priv->lec_arp_empty_ones)) {
821 822 823
			lec_arp_check_empties(priv, vcc, skb);
		}
		skb_pull(skb, 2);	/* skip lec_id */
L
Linus Torvalds 已提交
824
#ifdef CONFIG_TR
825 826 827
		if (priv->is_trdev)
			skb->protocol = tr_type_trans(skb, dev);
		else
L
Linus Torvalds 已提交
828
#endif
829 830 831 832 833 834
			skb->protocol = eth_type_trans(skb, dev);
		priv->stats.rx_packets++;
		priv->stats.rx_bytes += skb->len;
		memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
		netif_rx(skb);
	}
L
Linus Torvalds 已提交
835 836
}

837
static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
{
	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
	struct net_device *dev = skb->dev;

	if (vpriv == NULL) {
		printk("lec_pop(): vpriv = NULL!?!?!?\n");
		return;
	}

	vpriv->old_pop(vcc, skb);

	if (vpriv->xoff && atm_may_send(vcc, 0)) {
		vpriv->xoff = 0;
		if (netif_running(dev) && netif_queue_stopped(dev))
			netif_wake_queue(dev);
	}
}

856
static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
L
Linus Torvalds 已提交
857 858
{
	struct lec_vcc_priv *vpriv;
859 860 861 862 863 864 865 866 867 868 869 870 871
	int bytes_left;
	struct atmlec_ioc ioc_data;

	/* Lecd must be up in this case */
	bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
	if (bytes_left != 0) {
		printk
		    ("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
		     bytes_left);
	}
	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
	    !dev_lec[ioc_data.dev_num])
		return -EINVAL;
L
Linus Torvalds 已提交
872 873 874 875 876 877
	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
	vcc->pop = lec_pop;
878 879 880 881 882
	lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
		      &ioc_data, vcc, vcc->push);
	vcc->proto_data = dev_lec[ioc_data.dev_num];
	vcc->push = lec_push;
	return 0;
L
Linus Torvalds 已提交
883 884
}

885
static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
L
Linus Torvalds 已提交
886
{
887 888 889 890
	if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
		return -EINVAL;
	vcc->proto_data = dev_lec[arg];
	return (lec_mcast_make((struct lec_priv *)dev_lec[arg]->priv, vcc));
L
Linus Torvalds 已提交
891 892 893
}

/* Initialize device. */
894 895 896 897 898 899 900 901 902
static int lecd_attach(struct atm_vcc *vcc, int arg)
{
	int i;
	struct lec_priv *priv;

	if (arg < 0)
		i = 0;
	else
		i = arg;
L
Linus Torvalds 已提交
903
#ifdef CONFIG_TR
904 905 906 907 908
	if (arg >= MAX_LEC_ITF)
		return -EINVAL;
#else				/* Reserve the top NUM_TR_DEVS for TR */
	if (arg >= (MAX_LEC_ITF - NUM_TR_DEVS))
		return -EINVAL;
L
Linus Torvalds 已提交
909
#endif
910 911
	if (!dev_lec[i]) {
		int is_trdev, size;
L
Linus Torvalds 已提交
912

913 914 915
		is_trdev = 0;
		if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
			is_trdev = 1;
L
Linus Torvalds 已提交
916

917
		size = sizeof(struct lec_priv);
L
Linus Torvalds 已提交
918
#ifdef CONFIG_TR
919 920 921
		if (is_trdev)
			dev_lec[i] = alloc_trdev(size);
		else
L
Linus Torvalds 已提交
922
#endif
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
			dev_lec[i] = alloc_etherdev(size);
		if (!dev_lec[i])
			return -ENOMEM;
		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
		if (register_netdev(dev_lec[i])) {
			free_netdev(dev_lec[i]);
			return -EINVAL;
		}

		priv = dev_lec[i]->priv;
		priv->is_trdev = is_trdev;
		lec_init(dev_lec[i]);
	} else {
		priv = dev_lec[i]->priv;
		if (priv->lecd)
			return -EADDRINUSE;
	}
	lec_arp_init(priv);
	priv->itfnum = i;	/* LANE2 addition */
	priv->lecd = vcc;
	vcc->dev = &lecatm_dev;
	vcc_insert_socket(sk_atm(vcc));

	vcc->proto_data = dev_lec[i];
	set_bit(ATM_VF_META, &vcc->flags);
	set_bit(ATM_VF_READY, &vcc->flags);

	/* Set default values to these variables */
	priv->maximum_unknown_frame_count = 1;
	priv->max_unknown_frame_time = (1 * HZ);
	priv->vcc_timeout_period = (1200 * HZ);
	priv->max_retry_count = 1;
	priv->aging_time = (300 * HZ);
	priv->forward_delay_time = (15 * HZ);
	priv->topology_change = 0;
	priv->arp_response_time = (1 * HZ);
	priv->flush_timeout = (4 * HZ);
	priv->path_switching_delay = (6 * HZ);

	if (dev_lec[i]->flags & IFF_UP) {
		netif_start_queue(dev_lec[i]);
	}
	__module_get(THIS_MODULE);
	return i;
L
Linus Torvalds 已提交
967 968 969
}

#ifdef CONFIG_PROC_FS
970
static char *lec_arp_get_status_string(unsigned char status)
L
Linus Torvalds 已提交
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
{
	static char *lec_arp_status_string[] = {
		"ESI_UNKNOWN       ",
		"ESI_ARP_PENDING   ",
		"ESI_VC_PENDING    ",
		"<Undefined>       ",
		"ESI_FLUSH_PENDING ",
		"ESI_FORWARD_DIRECT"
	};

	if (status > ESI_FORWARD_DIRECT)
		status = 3;	/* ESI_UNDEFINED */
	return lec_arp_status_string[status];
}

static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
{
	int i;

	for (i = 0; i < ETH_ALEN; i++)
		seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff);
	seq_printf(seq, " ");
	for (i = 0; i < ATM_ESA_LEN; i++)
		seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff);
	seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status),
		   entry->flags & 0xffff);
	if (entry->vcc)
		seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
	else
1000
		seq_printf(seq, "        ");
L
Linus Torvalds 已提交
1001 1002 1003
	if (entry->recv_vcc) {
		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
			   entry->recv_vcc->vci);
1004 1005
	}
	seq_putc(seq, '\n');
L
Linus Torvalds 已提交
1006 1007 1008 1009 1010
}

struct lec_state {
	unsigned long flags;
	struct lec_priv *locked;
1011
	struct hlist_node *node;
L
Linus Torvalds 已提交
1012 1013 1014 1015 1016 1017
	struct net_device *dev;
	int itf;
	int arp_table;
	int misc_table;
};

1018
static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
L
Linus Torvalds 已提交
1019 1020
			  loff_t *l)
{
1021 1022
	struct hlist_node *e = state->node;
	struct lec_arp_table *tmp;
L
Linus Torvalds 已提交
1023 1024

	if (!e)
1025
		e = tbl->first;
J
Joe Perches 已提交
1026
	if (e == SEQ_START_TOKEN) {
1027
		e = tbl->first;
L
Linus Torvalds 已提交
1028 1029
		--*l;
	}
1030 1031

	hlist_for_each_entry_from(tmp, e, next) {
L
Linus Torvalds 已提交
1032 1033 1034
		if (--*l < 0)
			break;
	}
1035 1036
	state->node = e;

L
Linus Torvalds 已提交
1037 1038 1039 1040
	return (*l < 0) ? state : NULL;
}

static void *lec_arp_walk(struct lec_state *state, loff_t *l,
1041
			  struct lec_priv *priv)
L
Linus Torvalds 已提交
1042 1043 1044 1045 1046
{
	void *v = NULL;
	int p;

	for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
1047
		v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
L
Linus Torvalds 已提交
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
		if (v)
			break;
	}
	state->arp_table = p;
	return v;
}

static void *lec_misc_walk(struct lec_state *state, loff_t *l,
			   struct lec_priv *priv)
{
1058 1059 1060 1061
	struct hlist_head *lec_misc_tables[] = {
		&priv->lec_arp_empty_ones,
		&priv->lec_no_forward,
		&priv->mcast_fwds
L
Linus Torvalds 已提交
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
	};
	void *v = NULL;
	int q;

	for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {
		v = lec_tbl_walk(state, lec_misc_tables[q], l);
		if (v)
			break;
	}
	state->misc_table = q;
	return v;
}

static void *lec_priv_walk(struct lec_state *state, loff_t *l,
			   struct lec_priv *priv)
{
	if (!state->locked) {
		state->locked = priv;
		spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
	}
1082
	if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
L
Linus Torvalds 已提交
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
		spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
		state->locked = NULL;
		/* Partial state reset for the next time we get called */
		state->arp_table = state->misc_table = 0;
	}
	return state->locked;
}

static void *lec_itf_walk(struct lec_state *state, loff_t *l)
{
	struct net_device *dev;
	void *v;

	dev = state->dev ? state->dev : dev_lec[state->itf];
	v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL;
	if (!v && dev) {
		dev_put(dev);
		/* Partial state reset for the next time we get called */
		dev = NULL;
	}
	state->dev = dev;
	return v;
}

static void *lec_get_idx(struct lec_state *state, loff_t l)
{
	void *v = NULL;

	for (; state->itf < MAX_LEC_ITF; state->itf++) {
		v = lec_itf_walk(state, &l);
		if (v)
			break;
	}
1116
	return v;
L
Linus Torvalds 已提交
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
}

static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct lec_state *state = seq->private;

	state->itf = 0;
	state->dev = NULL;
	state->locked = NULL;
	state->arp_table = 0;
	state->misc_table = 0;
J
Joe Perches 已提交
1128
	state->node = SEQ_START_TOKEN;
L
Linus Torvalds 已提交
1129

J
Joe Perches 已提交
1130
	return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
L
Linus Torvalds 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
}

static void lec_seq_stop(struct seq_file *seq, void *v)
{
	struct lec_state *state = seq->private;

	if (state->dev) {
		spin_unlock_irqrestore(&state->locked->lec_arp_lock,
				       state->flags);
		dev_put(state->dev);
	}
}

static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct lec_state *state = seq->private;

	v = lec_get_idx(state, 1);
	*pos += !!PTR_ERR(v);
	return v;
}

static int lec_seq_show(struct seq_file *seq, void *v)
{
1155 1156 1157
	static char lec_banner[] = "Itf  MAC          ATM destination"
	    "                          Status            Flags "
	    "VPI/VCI Recv VPI/VCI\n";
L
Linus Torvalds 已提交
1158

J
Joe Perches 已提交
1159
	if (v == SEQ_START_TOKEN)
L
Linus Torvalds 已提交
1160 1161 1162
		seq_puts(seq, lec_banner);
	else {
		struct lec_state *state = seq->private;
1163
		struct net_device *dev = state->dev;
1164
		struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);
L
Linus Torvalds 已提交
1165 1166

		seq_printf(seq, "%s ", dev->name);
1167
		lec_info(seq, entry);
L
Linus Torvalds 已提交
1168 1169 1170 1171
	}
	return 0;
}

1172
static const struct seq_operations lec_seq_ops = {
1173 1174 1175 1176
	.start = lec_seq_start,
	.next = lec_seq_next,
	.stop = lec_seq_stop,
	.show = lec_seq_show,
L
Linus Torvalds 已提交
1177 1178 1179 1180
};

static int lec_seq_open(struct inode *inode, struct file *file)
{
1181
	return seq_open_private(file, &lec_seq_ops, sizeof(struct lec_state));
L
Linus Torvalds 已提交
1182 1183
}

1184
static const struct file_operations lec_seq_fops = {
1185 1186 1187 1188
	.owner = THIS_MODULE,
	.open = lec_seq_open,
	.read = seq_read,
	.llseek = seq_lseek,
1189
	.release = seq_release_private,
L
Linus Torvalds 已提交
1190 1191 1192 1193 1194 1195 1196
};
#endif

static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct atm_vcc *vcc = ATM_SD(sock);
	int err = 0;
1197

L
Linus Torvalds 已提交
1198
	switch (cmd) {
1199 1200 1201 1202 1203 1204 1205 1206
	case ATMLEC_CTRL:
	case ATMLEC_MCAST:
	case ATMLEC_DATA:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		break;
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
1207 1208 1209
	}

	switch (cmd) {
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
	case ATMLEC_CTRL:
		err = lecd_attach(vcc, (int)arg);
		if (err >= 0)
			sock->state = SS_CONNECTED;
		break;
	case ATMLEC_MCAST:
		err = lec_mcast_attach(vcc, (int)arg);
		break;
	case ATMLEC_DATA:
		err = lec_vcc_attach(vcc, (void __user *)arg);
		break;
L
Linus Torvalds 已提交
1221 1222 1223 1224 1225 1226
	}

	return err;
}

static struct atm_ioctl lane_ioctl_ops = {
1227 1228
	.owner = THIS_MODULE,
	.ioctl = lane_ioctl,
L
Linus Torvalds 已提交
1229 1230 1231 1232 1233 1234 1235
};

static int __init lane_module_init(void)
{
#ifdef CONFIG_PROC_FS
	struct proc_dir_entry *p;

1236
	p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops);
1237 1238 1239 1240
	if (!p) {
		printk(KERN_ERR "Unable to initialize /proc/net/atm/lec\n");
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
1241 1242 1243
#endif

	register_atm_ioctl(&lane_ioctl_ops);
1244 1245
	printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
	return 0;
L
Linus Torvalds 已提交
1246 1247 1248 1249
}

static void __exit lane_module_cleanup(void)
{
1250 1251
	int i;
	struct lec_priv *priv;
L
Linus Torvalds 已提交
1252 1253 1254 1255 1256

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

1257 1258 1259
	for (i = 0; i < MAX_LEC_ITF; i++) {
		if (dev_lec[i] != NULL) {
			priv = (struct lec_priv *)dev_lec[i]->priv;
L
Linus Torvalds 已提交
1260
			unregister_netdev(dev_lec[i]);
1261 1262 1263 1264
			free_netdev(dev_lec[i]);
			dev_lec[i] = NULL;
		}
	}
L
Linus Torvalds 已提交
1265

1266
	return;
L
Linus Torvalds 已提交
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
}

module_init(lane_module_init);
module_exit(lane_module_cleanup);

/*
 * LANE2: 3.1.3, LE_RESOLVE.request
 * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
 * If sizeoftlvs == NULL the default TLVs associated with with this
 * lec will be used.
 * If dst_mac == NULL, targetless LE_ARP will be sent
 */
static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
1280
			 u8 **tlvs, u32 *sizeoftlvs)
L
Linus Torvalds 已提交
1281 1282
{
	unsigned long flags;
1283 1284 1285 1286
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
	struct lec_arp_table *table;
	struct sk_buff *skb;
	int retval;
L
Linus Torvalds 已提交
1287

1288
	if (force == 0) {
L
Linus Torvalds 已提交
1289
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
1290
		table = lec_arp_find(priv, dst_mac);
L
Linus Torvalds 已提交
1291
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1292 1293 1294
		if (table == NULL)
			return -1;

1295
		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
1296 1297 1298 1299 1300 1301 1302
		if (*tlvs == NULL)
			return -1;

		*sizeoftlvs = table->sizeoftlvs;

		return 0;
	}
L
Linus Torvalds 已提交
1303 1304 1305

	if (sizeoftlvs == NULL)
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
1306

L
Linus Torvalds 已提交
1307 1308 1309 1310 1311
	else {
		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
		if (skb == NULL)
			return -1;
		skb->len = *sizeoftlvs;
1312
		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
L
Linus Torvalds 已提交
1313 1314
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
	}
1315 1316
	return retval;
}
L
Linus Torvalds 已提交
1317 1318 1319 1320 1321 1322 1323 1324

/*
 * LANE2: 3.1.4, LE_ASSOCIATE.request
 * Associate the *tlvs with the *lan_dst address.
 * Will overwrite any previous association
 * Returns 1 for success, 0 for failure (out of memory)
 *
 */
1325 1326
static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
			       u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1327
{
1328 1329 1330 1331 1332 1333 1334 1335 1336
	int retval;
	struct sk_buff *skb;
	struct lec_priv *priv = (struct lec_priv *)dev->priv;

	if (compare_ether_addr(lan_dst, dev->dev_addr))
		return (0);	/* not our mac address */

	kfree(priv->tlvs);	/* NULL if there was no previous association */

1337
	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1338 1339 1340 1341 1342 1343 1344 1345
	if (priv->tlvs == NULL)
		return (0);
	priv->sizeoftlvs = sizeoftlvs;

	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
	if (skb == NULL)
		return 0;
	skb->len = sizeoftlvs;
1346
	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
1347 1348 1349 1350 1351 1352 1353 1354
	retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
	if (retval != 0)
		printk("lec.c: lane2_associate_req() failed\n");
	/*
	 * If the previous association has changed we must
	 * somehow notify other LANE entities about the change
	 */
	return (1);
L
Linus Torvalds 已提交
1355 1356 1357 1358 1359 1360
}

/*
 * LANE2: 3.1.5, LE_ASSOCIATE.indication
 *
 */
1361 1362
static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
				u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1363 1364
{
#if 0
1365
	int i = 0;
L
Linus Torvalds 已提交
1366 1367
#endif
	struct lec_priv *priv = (struct lec_priv *)dev->priv;
1368 1369 1370 1371 1372 1373 1374
#if 0				/*
				 * Why have the TLVs in LE_ARP entries
				 * since we do not use them? When you
				 * uncomment this code, make sure the
				 * TLVs get freed when entry is killed
				 */
	struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
L
Linus Torvalds 已提交
1375

1376 1377
	if (entry == NULL)
		return;		/* should not happen */
L
Linus Torvalds 已提交
1378

1379
	kfree(entry->tlvs);
L
Linus Torvalds 已提交
1380

1381
	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1382 1383 1384
	if (entry->tlvs == NULL)
		return;
	entry->sizeoftlvs = sizeoftlvs;
L
Linus Torvalds 已提交
1385 1386
#endif
#if 0
1387 1388 1389 1390 1391 1392
	printk("lec.c: lane2_associate_ind()\n");
	printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
	while (i < sizeoftlvs)
		printk("%02x ", tlvs[i++]);

	printk("\n");
L
Linus Torvalds 已提交
1393 1394
#endif

1395 1396 1397 1398 1399 1400
	/* tell MPOA about the TLVs we saw */
	if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
		priv->lane2_ops->associate_indicator(dev, mac_addr,
						     tlvs, sizeoftlvs);
	}
	return;
L
Linus Torvalds 已提交
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
}

/*
 * Here starts what used to lec_arpc.c
 *
 * lec_arpc.c was added here when making
 * lane client modular. October 1997
 */

#include <linux/types.h>
#include <linux/timer.h>
#include <asm/param.h>
#include <asm/atomic.h>
#include <linux/inetdevice.h>
#include <net/route.h>

#if 0
1418
#define pr_debug(format,args...)
L
Linus Torvalds 已提交
1419
/*
1420
#define pr_debug printk
L
Linus Torvalds 已提交
1421 1422 1423 1424 1425 1426
*/
#endif
#define DEBUG_ARP_TABLE 0

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

D
David Howells 已提交
1427
static void lec_arp_check_expire(struct work_struct *work);
L
Linus Torvalds 已提交
1428 1429
static void lec_arp_expire_arp(unsigned long data);

1430
/*
L
Linus Torvalds 已提交
1431 1432 1433 1434 1435 1436 1437 1438
 * Arp table funcs
 */

#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))

/*
 * Initialization of arp-cache
 */
1439
static void lec_arp_init(struct lec_priv *priv)
L
Linus Torvalds 已提交
1440
{
1441
	unsigned short i;
L
Linus Torvalds 已提交
1442

1443
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1444
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1445
	}
1446 1447 1448
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
	INIT_HLIST_HEAD(&priv->lec_no_forward);
	INIT_HLIST_HEAD(&priv->mcast_fwds);
L
Linus Torvalds 已提交
1449
	spin_lock_init(&priv->lec_arp_lock);
D
David Howells 已提交
1450
	INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
1451
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1452 1453
}

1454
static void lec_arp_clear_vccs(struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1455
{
1456
	if (entry->vcc) {
L
Linus Torvalds 已提交
1457 1458
		struct atm_vcc *vcc = entry->vcc;
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1459
		struct net_device *dev = (struct net_device *)vcc->proto_data;
L
Linus Torvalds 已提交
1460

1461
		vcc->pop = vpriv->old_pop;
L
Linus Torvalds 已提交
1462 1463 1464 1465
		if (vpriv->xoff)
			netif_wake_queue(dev);
		kfree(vpriv);
		vcc->user_back = NULL;
1466
		vcc->push = entry->old_push;
L
Linus Torvalds 已提交
1467
		vcc_release_async(vcc, -EPIPE);
1468
		entry->vcc = NULL;
1469 1470 1471
	}
	if (entry->recv_vcc) {
		entry->recv_vcc->push = entry->old_recv_push;
L
Linus Torvalds 已提交
1472
		vcc_release_async(entry->recv_vcc, -EPIPE);
1473 1474
		entry->recv_vcc = NULL;
	}
L
Linus Torvalds 已提交
1475 1476 1477 1478 1479 1480
}

/*
 * Insert entry to lec_arp_table
 * LANE2: Add to the end of the list to satisfy 8.1.13
 */
1481
static inline void
1482
lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1483
{
1484
	struct hlist_head *tmp;
1485

1486 1487
	tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
	hlist_add_head(&entry->next, tmp);
1488

1489
	pr_debug("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1490 1491 1492
		0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1],
		0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3],
		0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]);
L
Linus Torvalds 已提交
1493 1494 1495 1496 1497
}

/*
 * Remove entry from lec_arp_table
 */
1498 1499
static int
lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
L
Linus Torvalds 已提交
1500
{
1501 1502 1503
	struct hlist_node *node;
	struct lec_arp_table *entry;
	int i, remove_vcc = 1;
1504 1505 1506 1507

	if (!to_remove) {
		return -1;
	}
1508 1509

	hlist_del(&to_remove->next);
1510 1511
	del_timer(&to_remove->timer);

1512
	/* If this is the only MAC connected to this VCC, also tear down the VCC */
1513 1514 1515 1516
	if (to_remove->status >= ESI_FLUSH_PENDING) {
		/*
		 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
		 */
1517 1518 1519 1520
		for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
			hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
				if (memcmp(to_remove->atm_addr,
					   entry->atm_addr, ATM_ESA_LEN) == 0) {
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
					remove_vcc = 0;
					break;
				}
			}
		}
		if (remove_vcc)
			lec_arp_clear_vccs(to_remove);
	}
	skb_queue_purge(&to_remove->tx_wait);	/* FIXME: good place for this? */

1531
	pr_debug("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1532 1533 1534 1535
		0xff & to_remove->mac_addr[0], 0xff & to_remove->mac_addr[1],
		0xff & to_remove->mac_addr[2], 0xff & to_remove->mac_addr[3],
		0xff & to_remove->mac_addr[4], 0xff & to_remove->mac_addr[5]);
	return 0;
L
Linus Torvalds 已提交
1536 1537 1538
}

#if DEBUG_ARP_TABLE
1539
static char *get_status_string(unsigned char st)
L
Linus Torvalds 已提交
1540
{
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554
	switch (st) {
	case ESI_UNKNOWN:
		return "ESI_UNKNOWN";
	case ESI_ARP_PENDING:
		return "ESI_ARP_PENDING";
	case ESI_VC_PENDING:
		return "ESI_VC_PENDING";
	case ESI_FLUSH_PENDING:
		return "ESI_FLUSH_PENDING";
	case ESI_FORWARD_DIRECT:
		return "ESI_FORWARD_DIRECT";
	default:
		return "<UNKNOWN>";
	}
L
Linus Torvalds 已提交
1555 1556
}

1557
static void dump_arp_table(struct lec_priv *priv)
L
Linus Torvalds 已提交
1558
{
1559
	struct hlist_node *node;
1560
	struct lec_arp_table *rulla;
1561 1562
	char buf[256];
	int i, j, offset;
1563 1564 1565

	printk("Dump %p:\n", priv);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1566 1567 1568
		hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
			offset = 0;
			offset += sprintf(buf, "%d: %p\n", i, rulla);
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
			offset += sprintf(buf + offset, "Mac:");
			for (j = 0; j < ETH_ALEN; j++) {
				offset += sprintf(buf + offset,
						  "%2.2x ",
						  rulla->mac_addr[j] & 0xff);
			}
			offset += sprintf(buf + offset, "Atm:");
			for (j = 0; j < ATM_ESA_LEN; j++) {
				offset += sprintf(buf + offset,
						  "%2.2x ",
						  rulla->atm_addr[j] & 0xff);
			}
			offset += sprintf(buf + offset,
					  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
					  rulla->vcc ? rulla->vcc->vpi : 0,
					  rulla->vcc ? rulla->vcc->vci : 0,
					  rulla->recv_vcc ? rulla->recv_vcc->
					  vpi : 0,
					  rulla->recv_vcc ? rulla->recv_vcc->
					  vci : 0, rulla->last_used,
					  rulla->timestamp, rulla->no_tries);
			offset +=
			    sprintf(buf + offset,
				    "Flags:%x, Packets_flooded:%x, Status: %s ",
				    rulla->flags, rulla->packets_flooded,
				    get_status_string(rulla->status));
1595
			printk("%s\n", buf);
1596 1597
		}
	}
1598 1599

	if (!hlist_empty(&priv->lec_no_forward))
1600
		printk("No forward\n");
1601
	hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
1625
		printk("%s\n", buf);
1626
	}
1627 1628

	if (!hlist_empty(&priv->lec_arp_empty_ones))
1629
		printk("Empty ones\n");
1630
	hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
		printk("%s", buf);
	}

1657
	if (!hlist_empty(&priv->mcast_fwds))
1658
		printk("Multicast Forward VCCs\n");
1659
	hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
1683
		printk("%s\n", buf);
1684
	}
L
Linus Torvalds 已提交
1685 1686

}
1687 1688 1689
#else
#define dump_arp_table(priv) do { } while (0)
#endif
L
Linus Torvalds 已提交
1690 1691 1692 1693

/*
 * Destruction of arp-cache
 */
1694
static void lec_arp_destroy(struct lec_priv *priv)
L
Linus Torvalds 已提交
1695 1696
{
	unsigned long flags;
1697 1698
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1699 1700
	int i;

1701
	cancel_rearming_delayed_work(&priv->lec_arp_work);
L
Linus Torvalds 已提交
1702

1703 1704 1705
	/*
	 * Remove all entries
	 */
L
Linus Torvalds 已提交
1706 1707

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1708
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1709
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
1710
			lec_arp_remove(priv, entry);
1711
			lec_arp_put(entry);
1712
		}
1713
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1714
	}
1715 1716

	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
1717 1718
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1719
		hlist_del(&entry->next);
1720
		lec_arp_put(entry);
1721
	}
1722 1723 1724
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);

	hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
1725 1726
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1727
		hlist_del(&entry->next);
1728
		lec_arp_put(entry);
1729
	}
1730 1731 1732
	INIT_HLIST_HEAD(&priv->lec_no_forward);

	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
1733 1734
		/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
		lec_arp_clear_vccs(entry);
1735
		hlist_del(&entry->next);
1736
		lec_arp_put(entry);
1737
	}
1738
	INIT_HLIST_HEAD(&priv->mcast_fwds);
1739
	priv->mcast_vcc = NULL;
L
Linus Torvalds 已提交
1740 1741 1742
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

1743
/*
L
Linus Torvalds 已提交
1744 1745
 * Find entry by mac_address
 */
1746 1747
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
					  unsigned char *mac_addr)
L
Linus Torvalds 已提交
1748
{
1749 1750 1751
	struct hlist_node *node;
	struct hlist_head *head;
	struct lec_arp_table *entry;
1752

1753
	pr_debug("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1754 1755 1756
		mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
		mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);

1757 1758 1759 1760
	head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
	hlist_for_each_entry(entry, node, head, next) {
		if (!compare_ether_addr(mac_addr, entry->mac_addr)) {
			return entry;
1761 1762 1763
		}
	}
	return NULL;
L
Linus Torvalds 已提交
1764 1765
}

1766 1767
static struct lec_arp_table *make_entry(struct lec_priv *priv,
					unsigned char *mac_addr)
L
Linus Torvalds 已提交
1768
{
1769 1770 1771 1772 1773 1774 1775 1776
	struct lec_arp_table *to_return;

	to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
	if (!to_return) {
		printk("LEC: Arp entry kmalloc failed\n");
		return NULL;
	}
	memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1777
	INIT_HLIST_NODE(&to_return->next);
1778 1779
	setup_timer(&to_return->timer, lec_arp_expire_arp,
			(unsigned long)to_return);
1780 1781 1782
	to_return->last_used = jiffies;
	to_return->priv = priv;
	skb_queue_head_init(&to_return->tx_wait);
1783
	atomic_set(&to_return->usage, 1);
1784
	return to_return;
L
Linus Torvalds 已提交
1785 1786
}

1787 1788
/* Arp sent timer expired */
static void lec_arp_expire_arp(unsigned long data)
L
Linus Torvalds 已提交
1789
{
1790 1791 1792 1793
	struct lec_arp_table *entry;

	entry = (struct lec_arp_table *)data;

1794
	pr_debug("lec_arp_expire_arp\n");
1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
	if (entry->status == ESI_ARP_PENDING) {
		if (entry->no_tries <= entry->priv->max_retry_count) {
			if (entry->is_rdesc)
				send_to_lecd(entry->priv, l_rdesc_arp_xmt,
					     entry->mac_addr, NULL, NULL);
			else
				send_to_lecd(entry->priv, l_arp_xmt,
					     entry->mac_addr, NULL, NULL);
			entry->no_tries++;
		}
		mod_timer(&entry->timer, jiffies + (1 * HZ));
	}
L
Linus Torvalds 已提交
1807 1808
}

1809 1810
/* Unknown/unused vcc expire, remove associated entry */
static void lec_arp_expire_vcc(unsigned long data)
L
Linus Torvalds 已提交
1811 1812
{
	unsigned long flags;
1813 1814
	struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
	struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
L
Linus Torvalds 已提交
1815

1816
	del_timer(&to_remove->timer);
L
Linus Torvalds 已提交
1817

1818
	pr_debug("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
1819 1820 1821
		to_remove, priv,
		to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
		to_remove->vcc ? to_remove->recv_vcc->vci : 0);
L
Linus Torvalds 已提交
1822 1823

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1824
	hlist_del(&to_remove->next);
L
Linus Torvalds 已提交
1825 1826
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1827
	lec_arp_clear_vccs(to_remove);
1828
	lec_arp_put(to_remove);
L
Linus Torvalds 已提交
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
}

/*
 * Expire entries.
 * 1. Re-set timer
 * 2. For each entry, delete entries that have aged past the age limit.
 * 3. For each entry, depending on the status of the entry, perform
 *    the following maintenance.
 *    a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
 *       tick_count is above the max_unknown_frame_time, clear
 *       the tick_count to zero and clear the packets_flooded counter
 *       to zero. This supports the packet rate limit per address
 *       while flooding unknowns.
 *    b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
 *       than or equal to the path_switching_delay, change the status
 *       to ESI_FORWARD_DIRECT. This causes the flush period to end
 *       regardless of the progress of the flush protocol.
 */
D
David Howells 已提交
1847
static void lec_arp_check_expire(struct work_struct *work)
L
Linus Torvalds 已提交
1848 1849
{
	unsigned long flags;
D
David Howells 已提交
1850 1851
	struct lec_priv *priv =
		container_of(work, struct lec_priv, lec_arp_work.work);
1852 1853
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1854 1855 1856 1857
	unsigned long now;
	unsigned long time_to_check;
	int i;

1858
	pr_debug("lec_arp_check_expire %p\n", priv);
L
Linus Torvalds 已提交
1859
	now = jiffies;
1860
restart:
L
Linus Torvalds 已提交
1861
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1862
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1863
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
1864
			if ((entry->flags) & LEC_REMOTE_FLAG &&
L
Linus Torvalds 已提交
1865 1866 1867 1868 1869
			    priv->topology_change)
				time_to_check = priv->forward_delay_time;
			else
				time_to_check = priv->aging_time;

1870
			pr_debug("About to expire: %lx - %lx > %lx\n",
1871 1872 1873 1874
				now, entry->last_used, time_to_check);
			if (time_after(now, entry->last_used + time_to_check)
			    && !(entry->flags & LEC_PERMANENT_FLAG)
			    && !(entry->mac_addr[0] & 0x01)) {	/* LANE2: 7.1.20 */
L
Linus Torvalds 已提交
1875
				/* Remove entry */
1876
				pr_debug("LEC:Entry timed out\n");
L
Linus Torvalds 已提交
1877
				lec_arp_remove(priv, entry);
1878
				lec_arp_put(entry);
L
Linus Torvalds 已提交
1879 1880 1881
			} else {
				/* Something else */
				if ((entry->status == ESI_VC_PENDING ||
1882
				     entry->status == ESI_ARP_PENDING)
L
Linus Torvalds 已提交
1883
				    && time_after_eq(now,
1884 1885 1886
						     entry->timestamp +
						     priv->
						     max_unknown_frame_time)) {
L
Linus Torvalds 已提交
1887 1888 1889
					entry->timestamp = jiffies;
					entry->packets_flooded = 0;
					if (entry->status == ESI_VC_PENDING)
1890 1891 1892 1893
						send_to_lecd(priv, l_svc_setup,
							     entry->mac_addr,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
1894
				}
1895 1896 1897 1898
				if (entry->status == ESI_FLUSH_PENDING
				    &&
				    time_after_eq(now, entry->timestamp +
						  priv->path_switching_delay)) {
L
Linus Torvalds 已提交
1899
					struct sk_buff *skb;
1900
					struct atm_vcc *vcc = entry->vcc;
L
Linus Torvalds 已提交
1901

1902 1903 1904 1905
					lec_arp_hold(entry);
					spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
					while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
						lec_send(vcc, skb, entry->priv);
L
Linus Torvalds 已提交
1906
					entry->last_used = jiffies;
1907
					entry->status = ESI_FORWARD_DIRECT;
1908 1909
					lec_arp_put(entry);
					goto restart;
L
Linus Torvalds 已提交
1910 1911 1912 1913 1914 1915
				}
			}
		}
	}
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1916
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1917
}
1918

L
Linus Torvalds 已提交
1919 1920
/*
 * Try to find vcc where mac_address is attached.
1921
 *
L
Linus Torvalds 已提交
1922
 */
1923 1924 1925
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
				       unsigned char *mac_to_find, int is_rdesc,
				       struct lec_arp_table **ret_entry)
L
Linus Torvalds 已提交
1926 1927
{
	unsigned long flags;
1928
	struct lec_arp_table *entry;
L
Linus Torvalds 已提交
1929 1930
	struct atm_vcc *found;

1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943
	if (mac_to_find[0] & 0x01) {
		switch (priv->lane_version) {
		case 1:
			return priv->mcast_vcc;
			break;
		case 2:	/* LANE2 wants arp for multicast addresses */
			if (!compare_ether_addr(mac_to_find, bus_mac))
				return priv->mcast_vcc;
			break;
		default:
			break;
		}
	}
L
Linus Torvalds 已提交
1944 1945

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1946 1947 1948 1949 1950 1951
	entry = lec_arp_find(priv, mac_to_find);

	if (entry) {
		if (entry->status == ESI_FORWARD_DIRECT) {
			/* Connection Ok */
			entry->last_used = jiffies;
1952
			lec_arp_hold(entry);
1953 1954
			*ret_entry = entry;
			found = entry->vcc;
L
Linus Torvalds 已提交
1955
			goto out;
1956 1957 1958
		}
		/*
		 * If the LE_ARP cache entry is still pending, reset count to 0
1959 1960 1961 1962 1963
		 * so another LE_ARP request can be made for this frame.
		 */
		if (entry->status == ESI_ARP_PENDING) {
			entry->no_tries = 0;
		}
1964 1965 1966 1967 1968 1969 1970 1971 1972 1973
		/*
		 * Data direct VC not yet set up, check to see if the unknown
		 * frame count is greater than the limit. If the limit has
		 * not been reached, allow the caller to send packet to
		 * BUS.
		 */
		if (entry->status != ESI_FLUSH_PENDING &&
		    entry->packets_flooded <
		    priv->maximum_unknown_frame_count) {
			entry->packets_flooded++;
1974
			pr_debug("LEC_ARP: Flooding..\n");
1975
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1976
			goto out;
1977 1978 1979
		}
		/*
		 * We got here because entry->status == ESI_FLUSH_PENDING
L
Linus Torvalds 已提交
1980 1981 1982
		 * or BUS flood limit was reached for an entry which is
		 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
		 */
1983
		lec_arp_hold(entry);
1984
		*ret_entry = entry;
1985
		pr_debug("lec: entry->status %d entry->vcc %p\n", entry->status,
1986 1987 1988 1989 1990
			entry->vcc);
		found = NULL;
	} else {
		/* No matching entry was found */
		entry = make_entry(priv, mac_to_find);
1991
		pr_debug("LEC_ARP: Making entry\n");
1992 1993
		if (!entry) {
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1994
			goto out;
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
		}
		lec_arp_add(priv, entry);
		/* We want arp-request(s) to be sent */
		entry->packets_flooded = 1;
		entry->status = ESI_ARP_PENDING;
		entry->no_tries = 1;
		entry->last_used = entry->timestamp = jiffies;
		entry->is_rdesc = is_rdesc;
		if (entry->is_rdesc)
			send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL,
				     NULL);
		else
			send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
		entry->timer.expires = jiffies + (1 * HZ);
		entry->timer.function = lec_arp_expire_arp;
		add_timer(&entry->timer);
		found = priv->mcast_vcc;
	}
L
Linus Torvalds 已提交
2013 2014 2015 2016 2017 2018 2019

out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
	return found;
}

static int
2020 2021
lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
		unsigned long permanent)
L
Linus Torvalds 已提交
2022 2023
{
	unsigned long flags;
2024 2025
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
2026
	int i;
L
Linus Torvalds 已提交
2027

2028
	pr_debug("lec_addr_delete\n");
L
Linus Torvalds 已提交
2029
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2030
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2031
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
2032 2033 2034
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
			    && (permanent ||
				!(entry->flags & LEC_PERMANENT_FLAG))) {
L
Linus Torvalds 已提交
2035
				lec_arp_remove(priv, entry);
2036
				lec_arp_put(entry);
2037
			}
L
Linus Torvalds 已提交
2038
			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2039 2040 2041
			return 0;
		}
	}
L
Linus Torvalds 已提交
2042
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2043
	return -1;
L
Linus Torvalds 已提交
2044 2045 2046
}

/*
2047
 * Notifies:  Response to arp_request (atm_addr != NULL)
L
Linus Torvalds 已提交
2048 2049 2050
 */
static void
lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
2051 2052
	       unsigned char *atm_addr, unsigned long remoteflag,
	       unsigned int targetless_le_arp)
L
Linus Torvalds 已提交
2053 2054
{
	unsigned long flags;
2055
	struct hlist_node *node, *next;
2056 2057
	struct lec_arp_table *entry, *tmp;
	int i;
L
Linus Torvalds 已提交
2058

2059 2060
	pr_debug("lec:%s", (targetless_le_arp) ? "targetless " : " ");
	pr_debug("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2061 2062
		mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
		mac_addr[4], mac_addr[5]);
L
Linus Torvalds 已提交
2063 2064

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2065 2066 2067 2068 2069 2070
	entry = lec_arp_find(priv, mac_addr);
	if (entry == NULL && targetless_le_arp)
		goto out;	/*
				 * LANE2: ignore targetless LE_ARPs for which
				 * we have no entry in the cache. 7.1.30
				 */
2071 2072 2073 2074
	if (!hlist_empty(&priv->lec_arp_empty_ones)) {
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
			if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
				hlist_del(&entry->next);
2075
				del_timer(&entry->timer);
2076 2077 2078 2079 2080 2081 2082 2083 2084
				tmp = lec_arp_find(priv, mac_addr);
				if (tmp) {
					del_timer(&tmp->timer);
					tmp->status = ESI_FORWARD_DIRECT;
					memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
					tmp->vcc = entry->vcc;
					tmp->old_push = entry->old_push;
					tmp->last_used = jiffies;
					del_timer(&entry->timer);
2085
					lec_arp_put(entry);
2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096
					entry = tmp;
				} else {
					entry->status = ESI_FORWARD_DIRECT;
					memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
					entry->last_used = jiffies;
					lec_arp_add(priv, entry);
				}
				if (remoteflag)
					entry->flags |= LEC_REMOTE_FLAG;
				else
					entry->flags &= ~LEC_REMOTE_FLAG;
2097
				pr_debug("After update\n");
2098 2099
				dump_arp_table(priv);
				goto out;
2100 2101 2102
			}
		}
	}
2103

2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115
	entry = lec_arp_find(priv, mac_addr);
	if (!entry) {
		entry = make_entry(priv, mac_addr);
		if (!entry)
			goto out;
		entry->status = ESI_UNKNOWN;
		lec_arp_add(priv, entry);
		/* Temporary, changes before end of function */
	}
	memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
	del_timer(&entry->timer);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2116
		hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {
2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138
			if (entry != tmp &&
			    !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
				/* Vcc to this host exists */
				if (tmp->status > ESI_VC_PENDING) {
					/*
					 * ESI_FLUSH_PENDING,
					 * ESI_FORWARD_DIRECT
					 */
					entry->vcc = tmp->vcc;
					entry->old_push = tmp->old_push;
				}
				entry->status = tmp->status;
				break;
			}
		}
	}
	if (remoteflag)
		entry->flags |= LEC_REMOTE_FLAG;
	else
		entry->flags &= ~LEC_REMOTE_FLAG;
	if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
		entry->status = ESI_VC_PENDING;
2139
		send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2140
	}
2141
	pr_debug("After update2\n");
2142
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2143 2144 2145 2146 2147
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

/*
2148
 * Notifies: Vcc setup ready
L
Linus Torvalds 已提交
2149 2150 2151
 */
static void
lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
2152 2153
	      struct atm_vcc *vcc,
	      void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
L
Linus Torvalds 已提交
2154 2155
{
	unsigned long flags;
2156
	struct hlist_node *node;
2157 2158
	struct lec_arp_table *entry;
	int i, found_entry = 0;
L
Linus Torvalds 已提交
2159 2160

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2161 2162
	if (ioc_data->receive == 2) {
		/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
L
Linus Torvalds 已提交
2163

2164
		pr_debug("LEC_ARP: Attaching mcast forward\n");
L
Linus Torvalds 已提交
2165
#if 0
2166 2167 2168
		entry = lec_arp_find(priv, bus_mac);
		if (!entry) {
			printk("LEC_ARP: Multicast entry not found!\n");
L
Linus Torvalds 已提交
2169
			goto out;
2170 2171 2172 2173
		}
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
L
Linus Torvalds 已提交
2174
#endif
2175 2176
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2177
			goto out;
2178 2179 2180 2181
		del_timer(&entry->timer);
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
2182
		hlist_add_head(&entry->next, &priv->mcast_fwds);
2183 2184 2185 2186 2187 2188
		goto out;
	} else if (ioc_data->receive == 1) {
		/*
		 * Vcc which we don't want to make default vcc,
		 * attach it anyway.
		 */
2189
		pr_debug
2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
		    ("LEC_ARP:Attaching data direct, not default: "
		     "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
		     ioc_data->atm_addr[0], ioc_data->atm_addr[1],
		     ioc_data->atm_addr[2], ioc_data->atm_addr[3],
		     ioc_data->atm_addr[4], ioc_data->atm_addr[5],
		     ioc_data->atm_addr[6], ioc_data->atm_addr[7],
		     ioc_data->atm_addr[8], ioc_data->atm_addr[9],
		     ioc_data->atm_addr[10], ioc_data->atm_addr[11],
		     ioc_data->atm_addr[12], ioc_data->atm_addr[13],
		     ioc_data->atm_addr[14], ioc_data->atm_addr[15],
		     ioc_data->atm_addr[16], ioc_data->atm_addr[17],
		     ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2204
			goto out;
2205 2206 2207 2208 2209 2210 2211
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		memset(entry->mac_addr, 0, ETH_ALEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
		entry->status = ESI_UNKNOWN;
		entry->timer.expires = jiffies + priv->vcc_timeout_period;
		entry->timer.function = lec_arp_expire_vcc;
2212
		hlist_add_head(&entry->next, &priv->lec_no_forward);
2213
		add_timer(&entry->timer);
L
Linus Torvalds 已提交
2214 2215
		dump_arp_table(priv);
		goto out;
2216
	}
2217
	pr_debug
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
	    ("LEC_ARP:Attaching data direct, default: "
	     "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
	     ioc_data->atm_addr[0], ioc_data->atm_addr[1],
	     ioc_data->atm_addr[2], ioc_data->atm_addr[3],
	     ioc_data->atm_addr[4], ioc_data->atm_addr[5],
	     ioc_data->atm_addr[6], ioc_data->atm_addr[7],
	     ioc_data->atm_addr[8], ioc_data->atm_addr[9],
	     ioc_data->atm_addr[10], ioc_data->atm_addr[11],
	     ioc_data->atm_addr[12], ioc_data->atm_addr[13],
	     ioc_data->atm_addr[14], ioc_data->atm_addr[15],
	     ioc_data->atm_addr[16], ioc_data->atm_addr[17],
	     ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2231
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2232 2233 2234
			if (memcmp
			    (ioc_data->atm_addr, entry->atm_addr,
			     ATM_ESA_LEN) == 0) {
2235 2236
				pr_debug("LEC_ARP: Attaching data direct\n");
				pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252
					entry->vcc ? entry->vcc->vci : 0,
					entry->recv_vcc ? entry->recv_vcc->
					vci : 0);
				found_entry = 1;
				del_timer(&entry->timer);
				entry->vcc = vcc;
				entry->old_push = old_push;
				if (entry->status == ESI_VC_PENDING) {
					if (priv->maximum_unknown_frame_count
					    == 0)
						entry->status =
						    ESI_FORWARD_DIRECT;
					else {
						entry->timestamp = jiffies;
						entry->status =
						    ESI_FLUSH_PENDING;
L
Linus Torvalds 已提交
2253
#if 0
2254 2255 2256 2257
						send_to_lecd(priv, l_flush_xmt,
							     NULL,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
2258
#endif
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
					}
				} else {
					/*
					 * They were forming a connection
					 * to us, and we to them. Our
					 * ATM address is numerically lower
					 * than theirs, so we make connection
					 * we formed into default VCC (8.1.11).
					 * Connection they made gets torn
					 * down. This might confuse some
					 * clients. Can be changed if
					 * someone reports trouble...
					 */
					;
				}
			}
		}
	}
	if (found_entry) {
2278
		pr_debug("After vcc was added\n");
2279
		dump_arp_table(priv);
L
Linus Torvalds 已提交
2280
		goto out;
2281 2282 2283 2284 2285 2286 2287
	}
	/*
	 * Not found, snatch address from first data packet that arrives
	 * from this vcc
	 */
	entry = make_entry(priv, bus_mac);
	if (!entry)
L
Linus Torvalds 已提交
2288
		goto out;
2289 2290 2291 2292 2293
	entry->vcc = vcc;
	entry->old_push = old_push;
	memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
	memset(entry->mac_addr, 0, ETH_ALEN);
	entry->status = ESI_UNKNOWN;
2294
	hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
2295 2296 2297
	entry->timer.expires = jiffies + priv->vcc_timeout_period;
	entry->timer.function = lec_arp_expire_vcc;
	add_timer(&entry->timer);
2298
	pr_debug("After vcc was added\n");
L
Linus Torvalds 已提交
2299 2300 2301 2302 2303
	dump_arp_table(priv);
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2304
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
L
Linus Torvalds 已提交
2305 2306
{
	unsigned long flags;
2307
	struct hlist_node *node;
2308 2309
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2310

2311
	pr_debug("LEC:lec_flush_complete %lx\n", tran_id);
2312
restart:
2313 2314
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2315
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2316 2317 2318
			if (entry->flush_tran_id == tran_id
			    && entry->status == ESI_FLUSH_PENDING) {
				struct sk_buff *skb;
2319
				struct atm_vcc *vcc = entry->vcc;
2320

2321 2322 2323 2324 2325
				lec_arp_hold(entry);
				spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
				while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
					lec_send(vcc, skb, entry->priv);
				entry->last_used = jiffies;
2326
				entry->status = ESI_FORWARD_DIRECT;
2327
				lec_arp_put(entry);
2328
				pr_debug("LEC_ARP: Flushed\n");
2329
				goto restart;
2330 2331 2332
			}
		}
	}
L
Linus Torvalds 已提交
2333
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2334
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2335 2336 2337 2338
}

static void
lec_set_flush_tran_id(struct lec_priv *priv,
2339
		      unsigned char *atm_addr, unsigned long tran_id)
L
Linus Torvalds 已提交
2340 2341
{
	unsigned long flags;
2342
	struct hlist_node *node;
2343 2344
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2345 2346

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2347
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
2348
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2349 2350
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
				entry->flush_tran_id = tran_id;
2351
				pr_debug("Set flush transaction id to %lx for %p\n",
2352
					tran_id, entry);
2353
			}
2354
		}
L
Linus Torvalds 已提交
2355 2356 2357
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2358
static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2359 2360
{
	unsigned long flags;
2361 2362 2363 2364
	unsigned char mac_addr[] = {
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
	};
	struct lec_arp_table *to_add;
L
Linus Torvalds 已提交
2365 2366
	struct lec_vcc_priv *vpriv;
	int err = 0;
2367

L
Linus Torvalds 已提交
2368 2369 2370 2371 2372
	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
2373
	vcc->pop = lec_pop;
L
Linus Torvalds 已提交
2374
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2375 2376
	to_add = make_entry(priv, mac_addr);
	if (!to_add) {
L
Linus Torvalds 已提交
2377 2378
		vcc->pop = vpriv->old_pop;
		kfree(vpriv);
2379
		err = -ENOMEM;
L
Linus Torvalds 已提交
2380
		goto out;
2381 2382 2383 2384 2385 2386 2387 2388 2389
	}
	memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
	to_add->status = ESI_FORWARD_DIRECT;
	to_add->flags |= LEC_PERMANENT_FLAG;
	to_add->vcc = vcc;
	to_add->old_push = vcc->push;
	vcc->push = lec_push;
	priv->mcast_vcc = vcc;
	lec_arp_add(priv, to_add);
L
Linus Torvalds 已提交
2390 2391
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2392
	return err;
L
Linus Torvalds 已提交
2393 2394
}

2395
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2396 2397
{
	unsigned long flags;
2398 2399
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
2400
	int i;
L
Linus Torvalds 已提交
2401

2402
	pr_debug("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
2403
	dump_arp_table(priv);
2404

L
Linus Torvalds 已提交
2405
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2406

2407
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2408
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
2409 2410
			if (vcc == entry->vcc) {
				lec_arp_remove(priv, entry);
2411
				lec_arp_put(entry);
2412 2413 2414 2415 2416 2417 2418
				if (priv->mcast_vcc == vcc) {
					priv->mcast_vcc = NULL;
				}
			}
		}
	}

2419 2420
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
		if (entry->vcc == vcc) {
2421 2422
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2423
			hlist_del(&entry->next);
2424
			lec_arp_put(entry);
2425 2426 2427
		}
	}

2428
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
2429 2430 2431
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2432
			hlist_del(&entry->next);
2433
			lec_arp_put(entry);
2434 2435 2436
		}
	}

2437
	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
2438 2439 2440
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2441
			hlist_del(&entry->next);
2442
			lec_arp_put(entry);
2443 2444
		}
	}
L
Linus Torvalds 已提交
2445 2446 2447 2448 2449 2450 2451

	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
	dump_arp_table(priv);
}

static void
lec_arp_check_empties(struct lec_priv *priv,
2452
		      struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
2453
{
2454
	unsigned long flags;
2455 2456
	struct hlist_node *node, *next;
	struct lec_arp_table *entry, *tmp;
2457 2458
	struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
	unsigned char *src;
L
Linus Torvalds 已提交
2459
#ifdef CONFIG_TR
2460
	struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
L
Linus Torvalds 已提交
2461

2462 2463 2464
	if (priv->is_trdev)
		src = tr_hdr->h_source;
	else
L
Linus Torvalds 已提交
2465
#endif
2466
		src = hdr->h_source;
L
Linus Torvalds 已提交
2467 2468

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2469 2470 2471 2472 2473 2474 2475 2476 2477
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
		if (vcc == entry->vcc) {
			del_timer(&entry->timer);
			memcpy(entry->mac_addr, src, ETH_ALEN);
			entry->status = ESI_FORWARD_DIRECT;
			entry->last_used = jiffies;
			/* We might have got an entry */
			if ((tmp = lec_arp_find(priv, src))) {
				lec_arp_remove(priv, tmp);
2478
				lec_arp_put(tmp);
2479 2480 2481 2482
			}
			hlist_del(&entry->next);
			lec_arp_add(priv, entry);
			goto out;
2483 2484
		}
	}
2485
	pr_debug("LEC_ARP: Arp_check_empties: entry not found!\n");
L
Linus Torvalds 已提交
2486 2487 2488
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
2489

L
Linus Torvalds 已提交
2490
MODULE_LICENSE("GPL");