Commit 6c76a432 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

[PATCH] : irda-usb Rx path cleanup + no clear_halt

	o [CORRECT] Don't do usb_clear_halt() on USB control pipe
	o [FEATURE] Cleanup and simplify the USB Rx path
parent 4f5e7c1d
...@@ -402,7 +402,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -402,7 +402,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
usb_fill_bulk_urb(urb, self->usbdev, usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
skb->data, IRDA_USB_MAX_MTU, skb->data, IRDA_SKB_MAX_MTU,
write_bulk_callback, skb); write_bulk_callback, skb);
urb->transfer_buffer_length = skb->len; urb->transfer_buffer_length = skb->len;
/* Note : unlink *must* be Asynchronous because of the code in /* Note : unlink *must* be Asynchronous because of the code in
...@@ -442,6 +442,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -442,6 +442,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* would be lost in the noise - Jean II */ * would be lost in the noise - Jean II */
diff += IU_USB_MIN_RTT; diff += IU_USB_MIN_RTT;
#endif /* 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) if (diff < 0)
diff += 1000000; diff += 1000000;
...@@ -701,30 +704,11 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc ...@@ -701,30 +704,11 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
IRDA_DEBUG(2, "%s()\n", __FUNCTION__); IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Check that we have an urb */ /* This should never happen */
if (!urb) { ASSERT(skb != NULL, return;);
WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__); ASSERT(urb != NULL, return;);
return;
}
/* Allocate new skb if it has not been recycled */ /* Save ourselves in the skb */
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);
/* Save ourselves */
cb = (struct irda_skb_cb *) skb->cb; cb = (struct irda_skb_cb *) skb->cb;
cb->context = self; cb->context = self;
...@@ -758,8 +742,10 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) ...@@ -758,8 +742,10 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
struct sk_buff *skb = (struct sk_buff *) urb->context; struct sk_buff *skb = (struct sk_buff *) urb->context;
struct irda_usb_cb *self; struct irda_usb_cb *self;
struct irda_skb_cb *cb; 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); IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
/* Find ourselves */ /* Find ourselves */
...@@ -808,39 +794,56 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) ...@@ -808,39 +794,56 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
*/ */
do_gettimeofday(&self->stamp); do_gettimeofday(&self->stamp);
/* Fix skb, and remove USB-IrDA header */ /* Check if we need to copy the data to a new skb or not.
skb_put(skb, urb->actual_length); * For most frames, we use ZeroCopy and pass the already
skb_pull(skb, USB_IRDA_HEADER); * 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;
}
/* Don't waste a lot of memory on small IrDA frames */ /* Make sure IP header get aligned (IrDA header is 5 bytes) */
if (skb->len < RX_COPY_THRESHOLD) { /* But IrDA-USB header is 1 byte. Jean II */
new = dev_alloc_skb(skb->len+1); //skb_reserve(newskb, USB_IRDA_HEADER - 1);
if (!new) {
self->stats.rx_dropped++;
goto done;
}
/* Make sure IP header get aligned (IrDA header is 5 bytes) */ if(docopy) {
skb_reserve(new, 1);
/* Copy packet, so we can recycle the original */ /* Copy packet, so we can recycle the original */
memcpy(skb_put(new, skb->len), skb->data, skb->len); memcpy(newskb->data, skb->data, urb->actual_length);
/* We will cleanup the skb in irda_usb_submit() */ /* 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 { } else {
/* Deliver the original skb */ /* We are using ZeroCopy. Deliver old skb */
new = skb; dataskb = skb;
skb = NULL; /* And hook the new skb to the URB */
skb = newskb;
} }
self->stats.rx_bytes += new->len; /* Set proper length on skb & remove USB-IrDA header */
self->stats.rx_packets++; skb_put(dataskb, urb->actual_length);
skb_pull(dataskb, USB_IRDA_HEADER);
/* Ask the networking layer to queue the packet for the IrDA stack */ /* Ask the networking layer to queue the packet for the IrDA stack */
new->dev = self->netdev; dataskb->dev = self->netdev;
new->mac.raw = new->data; dataskb->mac.raw = dataskb->data;
new->protocol = htons(ETH_P_IRDA); dataskb->protocol = htons(ETH_P_IRDA);
netif_rx(new); netif_rx(dataskb);
self->netdev->last_rx = jiffies;
/* Keep stats up to date */
self->stats.rx_bytes += dataskb->len;
self->stats.rx_packets++;
self->netdev->last_rx = jiffies;
done: done:
/* Note : at this point, the URB we've just received (urb) /* Note : at this point, the URB we've just received (urb)
...@@ -973,8 +976,17 @@ static int irda_usb_net_open(struct net_device *netdev) ...@@ -973,8 +976,17 @@ static int irda_usb_net_open(struct net_device *netdev)
/* Now that we can pass data to IrLAP, allow the USB layer /* Now that we can pass data to IrLAP, allow the USB layer
* to send us some data... */ * to send us some data... */
for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) {
irda_usb_submit(self, NULL, self->rx_urb[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 !!! */ /* Ready to play !!! */
return 0; return 0;
...@@ -1167,9 +1179,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self) ...@@ -1167,9 +1179,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
spin_lock_init(&self->lock); spin_lock_init(&self->lock);
irda_usb_init_qos(self); 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 */ /* Allocate the buffer for speed changes */
/* Don't change this buffer size and allocation without doing /* Don't change this buffer size and allocation without doing
...@@ -1228,8 +1237,6 @@ static inline int irda_usb_close(struct irda_usb_cb *self) ...@@ -1228,8 +1237,6 @@ static inline int irda_usb_close(struct irda_usb_cb *self)
self->netdev = NULL; self->netdev = NULL;
rtnl_unlock(); rtnl_unlock();
} }
/* Delete all pending skbs */
hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any);
/* Remove the speed buffer */ /* Remove the speed buffer */
if (self->speed_buff != NULL) { if (self->speed_buff != NULL) {
kfree(self->speed_buff); kfree(self->speed_buff);
...@@ -1492,8 +1499,10 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1492,8 +1499,10 @@ static int irda_usb_probe(struct usb_interface *intf,
case 0: case 0:
break; break;
case -EPIPE: /* -EPIPE = -32 */ case -EPIPE: /* -EPIPE = -32 */
usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); /* Martin Diehl says if we get a -EPIPE we should
IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__); * 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; break;
default: default:
IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret); IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment