Commit 3958fb34 authored by Samuel Ortiz's avatar Samuel Ortiz Committed by David S. Miller

[IrDA]: irda-usb TX path optimization (was Re: IrDA spams logfiles - since 2.6.19)

Since we stop using dev_alloc_skb on the IrDA TX frame, we constantly run
into the case of the skb headroom being 0, and thus we call skb_cow for
every IrDA TX frame.
This patch uses a local buffer and memcpy the skb to it, saving us a
kmalloc for each of those IrDA TX frames.
Signed-off-by: default avatarSamuel Ortiz <samuel@sortiz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9d0f7d29
...@@ -441,25 +441,13 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -441,25 +441,13 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
goto drop; goto drop;
} }
/* Make sure there is room for IrDA-USB header. The actual memcpy(self->tx_buff + self->header_length, skb->data, skb->len);
* allocation will be done lower in skb_push().
* Also, we don't use directly skb_cow(), because it require
* headroom >= 16, which force unnecessary copies - Jean II */
if (skb_headroom(skb) < self->header_length) {
IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
if (skb_cow(skb, self->header_length)) {
IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
goto drop;
}
}
/* Change setting for next frame */ /* Change setting for next frame */
if (self->capability & IUC_STIR421X) { if (self->capability & IUC_STIR421X) {
__u8 turnaround_time; __u8 turnaround_time;
__u8* frame; __u8* frame = self->tx_buff;
turnaround_time = get_turnaround_time( skb ); turnaround_time = get_turnaround_time( skb );
frame= skb_push(skb, self->header_length);
irda_usb_build_header(self, frame, 0); irda_usb_build_header(self, frame, 0);
frame[2] = turnaround_time; frame[2] = turnaround_time;
if ((skb->len != 0) && if ((skb->len != 0) &&
...@@ -472,7 +460,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -472,7 +460,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
frame[1] = 0; frame[1] = 0;
} }
} else { } else {
irda_usb_build_header(self, skb_push(skb, self->header_length), 0); irda_usb_build_header(self, self->tx_buff, 0);
} }
/* FIXME: Make macro out of this one */ /* FIXME: Make macro out of this one */
...@@ -480,9 +468,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -480,9 +468,9 @@ 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_SKB_MAX_MTU, self->tx_buff, skb->len + self->header_length,
write_bulk_callback, skb); write_bulk_callback, skb);
urb->transfer_buffer_length = skb->len;
/* This flag (URB_ZERO_PACKET) indicates that what we send is not /* This flag (URB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets. * a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD) * In this case, the USB layer will insert an empty USB frame (TD)
...@@ -1455,6 +1443,9 @@ static inline void irda_usb_close(struct irda_usb_cb *self) ...@@ -1455,6 +1443,9 @@ static inline void irda_usb_close(struct irda_usb_cb *self)
/* Remove the speed buffer */ /* Remove the speed buffer */
kfree(self->speed_buff); kfree(self->speed_buff);
self->speed_buff = NULL; self->speed_buff = NULL;
kfree(self->tx_buff);
self->tx_buff = NULL;
} }
/********************** USB CONFIG SUBROUTINES **********************/ /********************** USB CONFIG SUBROUTINES **********************/
...@@ -1753,9 +1744,14 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1753,9 +1744,14 @@ static int irda_usb_probe(struct usb_interface *intf,
memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length,
GFP_KERNEL);
if (self->tx_buff == NULL)
goto err_out_4;
ret = irda_usb_open(self); ret = irda_usb_open(self);
if (ret) if (ret)
goto err_out_4; goto err_out_5;
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self); usb_set_intfdata(intf, self);
...@@ -1766,14 +1762,14 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1766,14 +1762,14 @@ static int irda_usb_probe(struct usb_interface *intf,
self->needspatch = (ret < 0); self->needspatch = (ret < 0);
if (self->needspatch) { if (self->needspatch) {
IRDA_ERROR("STIR421X: Couldn't upload patch\n"); IRDA_ERROR("STIR421X: Couldn't upload patch\n");
goto err_out_5; goto err_out_6;
} }
/* replace IrDA class descriptor with what patched device is now reporting */ /* replace IrDA class descriptor with what patched device is now reporting */
irda_desc = irda_usb_find_class_desc (self->usbintf); irda_desc = irda_usb_find_class_desc (self->usbintf);
if (irda_desc == NULL) { if (irda_desc == NULL) {
ret = -ENODEV; ret = -ENODEV;
goto err_out_5; goto err_out_6;
} }
if (self->irda_desc) if (self->irda_desc)
kfree (self->irda_desc); kfree (self->irda_desc);
...@@ -1782,9 +1778,10 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1782,9 +1778,10 @@ static int irda_usb_probe(struct usb_interface *intf,
} }
return 0; return 0;
err_out_6:
err_out_5:
unregister_netdev(self->netdev); unregister_netdev(self->netdev);
err_out_5:
kfree(self->tx_buff);
err_out_4: err_out_4:
kfree(self->speed_buff); kfree(self->speed_buff);
err_out_3: err_out_3:
......
...@@ -156,6 +156,7 @@ struct irda_usb_cb { ...@@ -156,6 +156,7 @@ struct irda_usb_cb {
struct irlap_cb *irlap; /* The link layer we are binded to */ struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; struct qos_info qos;
char *speed_buff; /* Buffer for speed changes */ char *speed_buff; /* Buffer for speed changes */
char *tx_buff;
struct timeval stamp; struct timeval stamp;
struct timeval now; struct timeval now;
......
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