patch-2.2.10 linux/net/irda/irlan/irlan_eth.c

Next file: linux/net/irda/irlan/irlan_event.c
Previous file: linux/net/irda/irlan/irlan_common.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
@@ -6,13 +6,13 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Thu Apr 22 14:26:39 1999
+ * Modified at:   Mon May 31 19:57:08 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -29,6 +29,7 @@
 #include <linux/etherdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
+#include <linux/random.h>
 #include <net/arp.h>
 
 #include <net/irda/irda.h>
@@ -49,7 +50,7 @@
 	struct irmanager_event mgr_event;
 	struct irlan_cb *self;
 
-	DEBUG(0, __FUNCTION__"()\n");
+	DEBUG(2, __FUNCTION__"()\n");
 
 	ASSERT(dev != NULL, return -1;);
        
@@ -65,21 +66,26 @@
 	
 	ether_setup(dev);
 	
-	dev->tx_queue_len = TTP_MAX_QUEUE;
-
-#if 0
-	/*  
-	 *  OK, since we are emulating an IrLAN sever we will have to give
-	 *  ourself an ethernet address!
-	 *  FIXME: this must be more dynamically
+	/* 
+	 * Lets do all queueing in IrTTP instead of this device driver.
+	 * Queueing here as well can introduce some strange latency
+	 * problems, which we will avoid by setting the queue size to 0.
 	 */
-	dev->dev_addr[0] = 0x40;
-	dev->dev_addr[1] = 0x00;
-	dev->dev_addr[2] = 0x00;
-	dev->dev_addr[3] = 0x00;
-	dev->dev_addr[4] = 0x23;
-	dev->dev_addr[5] = 0x45;
-#endif
+	dev->tx_queue_len = 0;
+
+	if (self->provider.access_type == ACCESS_DIRECT) {
+		/*  
+		 * Since we are emulating an IrLAN sever we will have to
+		 * give ourself an ethernet address!  
+		 */
+		dev->dev_addr[0] = 0x40;
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x00;
+		dev->dev_addr[3] = 0x00;
+		get_random_bytes(dev->dev_addr+4, 1);
+		get_random_bytes(dev->dev_addr+5, 1);
+	}
+
 	/* 
 	 * Network device has now been registered, so tell irmanager about
 	 * it, so it can be configured with network parameters
@@ -109,7 +115,7 @@
 {
 	struct irlan_cb *self;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(dev != NULL, return -1;);
 
@@ -144,7 +150,7 @@
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 	
 	/* Stop device */
 	dev->tbusy = 1;
@@ -179,76 +185,58 @@
 int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irlan_cb *self;
+	int ret;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	self = (struct irlan_cb *) dev->priv;
 
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
-	/* Lock transmit buffer */
-	if (irda_lock((void *) &dev->tbusy) == FALSE) {
-		/*
-		 * If we get here, some higher level has decided we are broken.
-		 * There should really be a "kick me" function call instead.
-		 */
-		int tickssofar = jiffies - dev->trans_start; 
-		
-		if (tickssofar < 5) 
- 			return -EBUSY;
-		
- 		dev->tbusy = 0;
- 		dev->trans_start = jiffies;
-	}
-	
-	DEBUG(4, "Room left at head: %d\n", skb_headroom(skb));
-	DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb));
-	DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER);
+	/* Check if IrTTP can accept more frames */
+	if (dev->tbusy)
+		return -EBUSY;
 	
-	/* skb headroom large enough to contain IR-headers? */
-	if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) {
+	/* skb headroom large enough to contain all IrDA-headers? */
+	if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
 		struct sk_buff *new_skb = 
-			skb_realloc_headroom(skb, IRLAN_MAX_HEADER);
-		ASSERT(new_skb != NULL, return 0;);
-		ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;);
+			skb_realloc_headroom(skb, self->max_header_size);
 
-		/*  Free original skb, and use the new one */
+		/*  We have to free the original skb anyway */
 		dev_kfree_skb(skb);
+
+		/* Did the realloc succeed? */
+		if (new_skb == NULL)
+			return 0;
+
+		/* Use the new skb instead */
 		skb = new_skb;
 	} 
 
 	dev->trans_start = jiffies;
-	self->stats.tx_packets++;
-	self->stats.tx_bytes += skb->len; 
 
-	/*
-	 *  Now queue the packet in the transport layer
-	 *  FIXME: clean up the code below! DB
-	 */
-	if (self->use_udata) {
-		irttp_udata_request(self->tsap_data, skb);
-		dev->tbusy = 0;
-	
-		return 0;
-	}
+	/* Now queue the packet in the transport layer */
+	if (self->use_udata)
+		ret = irttp_udata_request(self->tsap_data, skb);
+	else
+		ret = irttp_data_request(self->tsap_data, skb);
 
-	if (irttp_data_request(self->tsap_data, skb) == -1) {
-		/*  
-		 *  IrTTPs tx queue is full, so we just have to drop the
-		 *  frame! You might think that we should just return -1
-		 *  and don't deallocate the frame, but that is dangerous
-		 *  since it's possible that we have replaced the original
-		 *  skb with a new one with larger headroom, and that would
-		 *  really confuse do_dev_queue_xmit() in dev.c! I have
-		 *  tried :-) DB
+	if (ret < 0) {
+		/*   
+		 * IrTTPs tx queue is full, so we just have to
+		 * drop the frame! You might think that we should
+		 * just return -1 and don't deallocate the frame,
+		 * but that is dangerous since it's possible that
+		 * we have replaced the original skb with a new
+		 * one with larger headroom, and that would really
+		 * confuse do_dev_queue_xmit() in dev.c! I have
+		 * tried :-) DB 
 		 */
 		dev_kfree_skb(skb);
-		++self->stats.tx_dropped;
-		
-		return 0;
+		self->stats.tx_dropped++;
+	} else {
+		self->stats.tx_packets++;
+		self->stats.tx_bytes += skb->len; 
 	}
-	dev->tbusy = 0; /* Finished! */
 	
 	return 0;
 }
@@ -282,11 +270,11 @@
 	skb->dev = &self->dev;
 	skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
 	
-	netif_rx(skb);   /* Eat it! */
-	
 	self->stats.rx_packets++;
 	self->stats.rx_bytes += skb->len; 
 
+	netif_rx(skb);   /* Eat it! */
+	
 	return 0;
 }
 
@@ -301,8 +289,6 @@
 	struct irlan_cb *self;
 	struct device *dev;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-
 	self = (struct irlan_cb *) instance;
 
 	ASSERT(self != NULL, return;);
@@ -314,26 +300,16 @@
 	
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(4, "IrLAN, stopping Ethernet layer\n");
-
 		dev->tbusy = 1;
 		break;
 	case FLOW_START:
-		/* 
-		 *  Tell upper layers that its time to transmit frames again
-		 */
-		DEBUG(4, "IrLAN, starting Ethernet layer\n");
-
+	default:
+		/* Tell upper layers that its time to transmit frames again */
 		dev->tbusy = 0;
 
-		/* 
-		 *  Ready to receive more frames, so schedule the network
-		 *  layer
-		 */
+		/* Schedule network layer */
 		mark_bh(NET_BH);		
 		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 
@@ -360,7 +336,7 @@
  *    Send gratuitous ARP to announce that we have changed
  *    hardware address, so that all peers updates their ARP tables
  */
-void irlan_etc_send_gratuitous_arp(struct device *dev) 
+void irlan_eth_send_gratuitous_arp(struct device *dev)
 {
 	struct in_device *in_dev;
 
@@ -373,7 +349,7 @@
 	in_dev = dev->ip_ptr;
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
 		 in_dev->ifa_list->ifa_address,
-		 &dev, 
+		 dev, 
 		 in_dev->ifa_list->ifa_address,
 		 NULL, dev->dev_addr, NULL);
 }
@@ -391,16 +367,21 @@
 
  	self = dev->priv; 
 
-	DEBUG(0, __FUNCTION__ "()\n");
-	return;
+	DEBUG(2, __FUNCTION__ "()\n");
+
  	ASSERT(self != NULL, return;); 
  	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	if (dev->flags&IFF_PROMISC) {
-		/* Enable promiscuous mode */
-		DEBUG(0, "Promiscous mode not implemented\n");
-		/* outw(MULTICAST|PROMISC, ioaddr); */
+	/* Check if data channel has been connected yet */
+	if (self->client.state != IRLAN_DATA) {
+		DEBUG(1, __FUNCTION__ "(), delaying!\n");
+		return;
 	}
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Enable promiscuous mode */
+		WARNING("Promiscous mode not implemented by IrLAN!\n");
+	} 
 	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
 		/* Disable promiscuous mode, use normal mode. */
 		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
@@ -420,13 +401,10 @@
 		irlan_set_multicast_filter(self, FALSE);
 	}
 
-	if (dev->flags & IFF_BROADCAST) {
-		DEBUG(4, __FUNCTION__ "(), Setting broadcast filter\n");
+	if (dev->flags & IFF_BROADCAST)
 		irlan_set_broadcast_filter(self, TRUE);
-	} else {
-		DEBUG(4, __FUNCTION__ "(), Clearing broadcast filter\n");
+	else
 		irlan_set_broadcast_filter(self, FALSE);
-	}
 }
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)