diff -u -p linux/drivers/net/irda/irda-usb.d7.c linux/drivers/net/irda/irda-usb.c
--- linux/drivers/net/irda/irda-usb.d7.c	Thu Feb 20 11:01:20 2003
+++ linux/drivers/net/irda/irda-usb.c	Thu Feb 20 15:22:52 2003
@@ -402,7 +402,7 @@ static int irda_usb_hard_xmit(struct sk_
 
         usb_fill_bulk_urb(urb, self->usbdev, 
 		      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
-                      skb->data, IRDA_USB_MAX_MTU,
+                      skb->data, IRDA_SKB_MAX_MTU,
                       write_bulk_callback, skb);
 	urb->transfer_buffer_length = skb->len;
 	/* Note : unlink *must* be Asynchronous because of the code in 
@@ -442,6 +442,9 @@ static int irda_usb_hard_xmit(struct sk_
 			 * would be lost in the noise - Jean II */
 			diff += IU_USB_MIN_RTT;
 #endif /* IU_USB_MIN_RTT */
+			/* If the usec counter did wraparound, the diff will
+			 * go negative (tv_usec is a long), so we need to
+			 * correct it by one second. Jean II */
 			if (diff < 0)
 				diff += 1000000;
 
@@ -701,30 +704,11 @@ static void irda_usb_submit(struct irda_
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
-	/* Check that we have an urb */
-	if (!urb) {
-		WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__);
-		return;
-	}
-
-	/* Allocate new skb if it has not been recycled */
-	if (!skb) {
-		skb = dev_alloc_skb(IRDA_USB_MAX_MTU + 1);
-		if (!skb) {
-			/* If this ever happen, we are in deep s***.
-			 * Basically, the Rx path will stop... */
-			WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
-			return;
-		}
-	} else  {
-		/* Reset recycled skb */
-		skb->data = skb->tail = skb->head;
-		skb->len = 0;
-	}
-	/* Make sure IP header get aligned (IrDA header is 5 bytes ) */
-	skb_reserve(skb, 1);
+	/* This should never happen */
+	ASSERT(skb != NULL, return;);
+	ASSERT(urb != NULL, return;);
 
-	/* Save ourselves */
+	/* Save ourselves in the skb */
 	cb = (struct irda_skb_cb *) skb->cb;
 	cb->context = self;
 
@@ -758,8 +742,10 @@ static void irda_usb_receive(struct urb 
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
 	struct irda_usb_cb *self; 
 	struct irda_skb_cb *cb;
-	struct sk_buff *new;
-	
+	struct sk_buff *newskb;
+	struct sk_buff *dataskb;
+	int		docopy;
+
 	IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
 	
 	/* Find ourselves */
@@ -808,39 +794,56 @@ static void irda_usb_receive(struct urb 
 	 */
         do_gettimeofday(&self->stamp);
 
-	/* Fix skb, and remove USB-IrDA header */
-	skb_put(skb, urb->actual_length);
-	skb_pull(skb, USB_IRDA_HEADER);
-
-	/* Don't waste a lot of memory on small IrDA frames */
-	if (skb->len < RX_COPY_THRESHOLD) {
-		new = dev_alloc_skb(skb->len+1);
-		if (!new) {
-			self->stats.rx_dropped++;
-			goto done;  
-		}
+	/* Check if we need to copy the data to a new skb or not.
+	 * For most frames, we use ZeroCopy and pass the already
+	 * allocated skb up the stack.
+	 * If the frame is small, it is more efficient to copy it
+	 * to save memory (copy will be fast anyway - that's
+	 * called Rx-copy-break). Jean II */
+	docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
+
+	/* Allocate a new skb */
+	newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+	if (!newskb)  {
+		self->stats.rx_dropped++;
+		/* We could deliver the current skb, but this would stall
+		 * the Rx path. Better drop the packet... Jean II */
+		goto done;  
+	}
+
+	/* Make sure IP header get aligned (IrDA header is 5 bytes) */
+	/* But IrDA-USB header is 1 byte. Jean II */
+	//skb_reserve(newskb, USB_IRDA_HEADER - 1);
 
-		/* Make sure IP header get aligned (IrDA header is 5 bytes) */
-		skb_reserve(new, 1);
-		
+	if(docopy) {
 		/* Copy packet, so we can recycle the original */
-		memcpy(skb_put(new, skb->len), skb->data, skb->len);
-		/* We will cleanup the skb in irda_usb_submit() */
+		memcpy(newskb->data, skb->data, urb->actual_length);
+		/* Deliver this new skb */
+		dataskb = newskb;
+		/* And hook the old skb to the URB
+		 * Note : we don't need to "clean up" the old skb,
+		 * as we never touched it. Jean II */
 	} else {
-		/* Deliver the original skb */
-		new = skb;
-		skb = NULL;
+		/* We are using ZeroCopy. Deliver old skb */
+		dataskb = skb;
+		/* And hook the new skb to the URB */
+		skb = newskb;
 	}
-	
-	self->stats.rx_bytes += new->len;
-	self->stats.rx_packets++;
+
+	/* Set proper length on skb & remove USB-IrDA header */
+	skb_put(dataskb, urb->actual_length);
+	skb_pull(dataskb, USB_IRDA_HEADER);
 
 	/* Ask the networking layer to queue the packet for the IrDA stack */
-        new->dev = self->netdev;
-        new->mac.raw  = new->data;
-        new->protocol = htons(ETH_P_IRDA);
-        netif_rx(new);
-        self->netdev->last_rx = jiffies;
+	dataskb->dev = self->netdev;
+	dataskb->mac.raw  = dataskb->data;
+	dataskb->protocol = htons(ETH_P_IRDA);
+	netif_rx(dataskb);
+
+	/* Keep stats up to date */
+	self->stats.rx_bytes += dataskb->len;
+	self->stats.rx_packets++;
+	self->netdev->last_rx = jiffies;
 
 done:
 	/* Note : at this point, the URB we've just received (urb)
@@ -973,8 +976,17 @@ static int irda_usb_net_open(struct net_
 
 	/* Now that we can pass data to IrLAP, allow the USB layer
 	 * to send us some data... */
-	for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++)
-		irda_usb_submit(self, NULL, self->rx_urb[i]);
+	for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) {
+		struct sk_buff *skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+		if (!skb) {
+			/* If this ever happen, we are in deep s***.
+			 * Basically, we can't start the Rx path... */
+			WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
+			return -1;
+		}
+		//skb_reserve(newskb, USB_IRDA_HEADER - 1);
+		irda_usb_submit(self, skb, self->rx_urb[i]);
+	}
 
 	/* Ready to play !!! */
 	return 0;
@@ -1167,9 +1179,6 @@ static inline int irda_usb_open(struct i
 	spin_lock_init(&self->lock);
 
 	irda_usb_init_qos(self);
-	
-	/* Initialise list of skb beeing curently transmitted */
-	self->tx_list = hashbin_new(HB_NOLOCK);	/* unused */
 
 	/* Allocate the buffer for speed changes */
 	/* Don't change this buffer size and allocation without doing
@@ -1228,8 +1237,6 @@ static inline int irda_usb_close(struct 
 		self->netdev = NULL;
 		rtnl_unlock();
 	}
-	/* Delete all pending skbs */
-	hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any);
 	/* Remove the speed buffer */
 	if (self->speed_buff != NULL) {
 		kfree(self->speed_buff);
@@ -1492,8 +1499,10 @@ static int irda_usb_probe(struct usb_int
 		case 0:
 			break;
 		case -EPIPE:		/* -EPIPE = -32 */
-			usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
-			IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__);
+			/* Martin Diehl says if we get a -EPIPE we should
+			 * be fine and we don't need to do a usb_clear_halt().
+			 * - Jean II */
+			IRDA_DEBUG(0, "%s(), Received -EPIPE, ignoring...\n", __FUNCTION__);
 			break;
 		default:
 			IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret);
