diff options
author | Samuel Ortiz <samuel@sortiz.org> | 2007-01-15 22:37:25 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-01-23 23:25:49 -0500 |
commit | 3958fb34ef18529c1e4a3eca44b7aaf94d4f4697 (patch) | |
tree | e7ed13bfae551ed43e530148293e889998768c35 /drivers/net/irda | |
parent | 9d0f7d29f38d4f7bf66d38d448a7d23e0bed9074 (diff) |
[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: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/irda')
-rw-r--r-- | drivers/net/irda/irda-usb.c | 43 | ||||
-rw-r--r-- | drivers/net/irda/irda-usb.h | 1 |
2 files changed, 21 insertions, 23 deletions
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 3ca1082ec776..80cbf3f80432 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c | |||
@@ -441,25 +441,13 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
441 | goto drop; | 441 | goto drop; |
442 | } | 442 | } |
443 | 443 | ||
444 | /* Make sure there is room for IrDA-USB header. The actual | 444 | memcpy(self->tx_buff + self->header_length, skb->data, skb->len); |
445 | * allocation will be done lower in skb_push(). | ||
446 | * Also, we don't use directly skb_cow(), because it require | ||
447 | * headroom >= 16, which force unnecessary copies - Jean II */ | ||
448 | if (skb_headroom(skb) < self->header_length) { | ||
449 | IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); | ||
450 | if (skb_cow(skb, self->header_length)) { | ||
451 | IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); | ||
452 | goto drop; | ||
453 | } | ||
454 | } | ||
455 | 445 | ||
456 | /* Change setting for next frame */ | 446 | /* Change setting for next frame */ |
457 | |||
458 | if (self->capability & IUC_STIR421X) { | 447 | if (self->capability & IUC_STIR421X) { |
459 | __u8 turnaround_time; | 448 | __u8 turnaround_time; |
460 | __u8* frame; | 449 | __u8* frame = self->tx_buff; |
461 | turnaround_time = get_turnaround_time( skb ); | 450 | turnaround_time = get_turnaround_time( skb ); |
462 | frame= skb_push(skb, self->header_length); | ||
463 | irda_usb_build_header(self, frame, 0); | 451 | irda_usb_build_header(self, frame, 0); |
464 | frame[2] = turnaround_time; | 452 | frame[2] = turnaround_time; |
465 | if ((skb->len != 0) && | 453 | if ((skb->len != 0) && |
@@ -472,17 +460,17 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
472 | frame[1] = 0; | 460 | frame[1] = 0; |
473 | } | 461 | } |
474 | } else { | 462 | } else { |
475 | irda_usb_build_header(self, skb_push(skb, self->header_length), 0); | 463 | irda_usb_build_header(self, self->tx_buff, 0); |
476 | } | 464 | } |
477 | 465 | ||
478 | /* FIXME: Make macro out of this one */ | 466 | /* FIXME: Make macro out of this one */ |
479 | ((struct irda_skb_cb *)skb->cb)->context = self; | 467 | ((struct irda_skb_cb *)skb->cb)->context = self; |
480 | 468 | ||
481 | usb_fill_bulk_urb(urb, self->usbdev, | 469 | usb_fill_bulk_urb(urb, self->usbdev, |
482 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), | 470 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), |
483 | skb->data, IRDA_SKB_MAX_MTU, | 471 | self->tx_buff, skb->len + self->header_length, |
484 | write_bulk_callback, skb); | 472 | write_bulk_callback, skb); |
485 | urb->transfer_buffer_length = skb->len; | 473 | |
486 | /* This flag (URB_ZERO_PACKET) indicates that what we send is not | 474 | /* This flag (URB_ZERO_PACKET) indicates that what we send is not |
487 | * a continuous stream of data but separate packets. | 475 | * a continuous stream of data but separate packets. |
488 | * In this case, the USB layer will insert an empty USB frame (TD) | 476 | * 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 | /* Remove the speed buffer */ | 1443 | /* Remove the speed buffer */ |
1456 | kfree(self->speed_buff); | 1444 | kfree(self->speed_buff); |
1457 | self->speed_buff = NULL; | 1445 | self->speed_buff = NULL; |
1446 | |||
1447 | kfree(self->tx_buff); | ||
1448 | self->tx_buff = NULL; | ||
1458 | } | 1449 | } |
1459 | 1450 | ||
1460 | /********************** USB CONFIG SUBROUTINES **********************/ | 1451 | /********************** USB CONFIG SUBROUTINES **********************/ |
@@ -1753,9 +1744,14 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1753 | 1744 | ||
1754 | memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); | 1745 | memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); |
1755 | 1746 | ||
1747 | self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length, | ||
1748 | GFP_KERNEL); | ||
1749 | if (self->tx_buff == NULL) | ||
1750 | goto err_out_4; | ||
1751 | |||
1756 | ret = irda_usb_open(self); | 1752 | ret = irda_usb_open(self); |
1757 | if (ret) | 1753 | if (ret) |
1758 | goto err_out_4; | 1754 | goto err_out_5; |
1759 | 1755 | ||
1760 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); | 1756 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); |
1761 | usb_set_intfdata(intf, self); | 1757 | usb_set_intfdata(intf, self); |
@@ -1766,14 +1762,14 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1766 | self->needspatch = (ret < 0); | 1762 | self->needspatch = (ret < 0); |
1767 | if (self->needspatch) { | 1763 | if (self->needspatch) { |
1768 | IRDA_ERROR("STIR421X: Couldn't upload patch\n"); | 1764 | IRDA_ERROR("STIR421X: Couldn't upload patch\n"); |
1769 | goto err_out_5; | 1765 | goto err_out_6; |
1770 | } | 1766 | } |
1771 | 1767 | ||
1772 | /* replace IrDA class descriptor with what patched device is now reporting */ | 1768 | /* replace IrDA class descriptor with what patched device is now reporting */ |
1773 | irda_desc = irda_usb_find_class_desc (self->usbintf); | 1769 | irda_desc = irda_usb_find_class_desc (self->usbintf); |
1774 | if (irda_desc == NULL) { | 1770 | if (irda_desc == NULL) { |
1775 | ret = -ENODEV; | 1771 | ret = -ENODEV; |
1776 | goto err_out_5; | 1772 | goto err_out_6; |
1777 | } | 1773 | } |
1778 | if (self->irda_desc) | 1774 | if (self->irda_desc) |
1779 | kfree (self->irda_desc); | 1775 | kfree (self->irda_desc); |
@@ -1782,9 +1778,10 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1782 | } | 1778 | } |
1783 | 1779 | ||
1784 | return 0; | 1780 | return 0; |
1785 | 1781 | err_out_6: | |
1786 | err_out_5: | ||
1787 | unregister_netdev(self->netdev); | 1782 | unregister_netdev(self->netdev); |
1783 | err_out_5: | ||
1784 | kfree(self->tx_buff); | ||
1788 | err_out_4: | 1785 | err_out_4: |
1789 | kfree(self->speed_buff); | 1786 | kfree(self->speed_buff); |
1790 | err_out_3: | 1787 | err_out_3: |
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index 6b2271f18e77..e846c38224a3 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h | |||
@@ -156,6 +156,7 @@ struct irda_usb_cb { | |||
156 | struct irlap_cb *irlap; /* The link layer we are binded to */ | 156 | struct irlap_cb *irlap; /* The link layer we are binded to */ |
157 | struct qos_info qos; | 157 | struct qos_info qos; |
158 | char *speed_buff; /* Buffer for speed changes */ | 158 | char *speed_buff; /* Buffer for speed changes */ |
159 | char *tx_buff; | ||
159 | 160 | ||
160 | struct timeval stamp; | 161 | struct timeval stamp; |
161 | struct timeval now; | 162 | struct timeval now; |