The USB ethernet driver in linux-2.5.8-pre1/drivers/usb/rtl8150.c 
unnecessarily copies all transmitted and received packets.  The following
patch eliminates copying of both transmitted and received packets.
I am running the resulting driver now and it seems to be fine.

        A couple of hours ago, I sent an earlier patch just to do
the elimination of the copying from transmitted packets.  Please ignore
that patch and use this one against pristine linux-2.5.8-pre1.  That
patch had a minor error in it, where it called dev_kfree_skb in a place
where it should have called dev_kfree_skb_irq, resulting in a bunch of
warning messages.  I have put "(v2)" in the subject line of this
message to avoid confusion about which is the latest patch.

-- 
Adam J. Richter     __     ______________   4880 Stevens Creek Blvd, Suite 104
[EMAIL PROTECTED]     \ /                  San Jose, California 95129-1034
+1 408 261-6630         | g g d r a s i l   United States of America
fax +1 408 261-6631      "Free Software For The Rest Of Us."
--- linux-2.5.8-pre1/drivers/usb/rtl8150.c      Wed Apr  3 23:38:31 2002
+++ linux/drivers/usb/rtl8150.c Fri Apr  5 05:07:29 2002
@@ -90,11 +90,11 @@
        struct net_device_stats stats;
        struct net_device       *netdev;
        struct urb              *rx_urb, *tx_urb, *intr_urb, *ctrl_urb;
+       struct sk_buff          *tx_skb;
+       struct sk_buff          *rx_skb;
        struct usb_ctrlrequest  dr;
        int                     intr_interval;
        u16                     rx_creg;
-       u8                      rx_buff[RTL8150_MAX_MTU];
-       u8                      tx_buff[RTL8150_MAX_MTU];
        u8                      intr_buff[8];
        u8                      phy;
 };
@@ -302,12 +302,11 @@
        usb_unlink_urb(dev->ctrl_urb);
 }
 
-
 static void read_bulk_callback(struct urb *urb)
 {
        rtl8150_t       *dev;
        unsigned        pkt_len, res;
-       struct sk_buff  *skb;
+       struct sk_buff  *new_skb;
        struct net_device *netdev;
        u16             rx_stat;
 
@@ -335,22 +334,25 @@
        }
 
        res = urb->actual_length;
-       rx_stat = le16_to_cpu(*(short*)(dev->rx_buff + res - 4));
+       rx_stat = le16_to_cpu(*(short*)(urb->transfer_buffer + res - 4));
        pkt_len = res - 4;
 
-       if (!(skb = dev_alloc_skb(pkt_len + 2))) 
+       if (!(new_skb = dev_alloc_skb(RTL8150_MAX_MTU + 4))) 
                goto goon;
-       skb->dev = netdev;
-       skb_reserve(skb, 2);
-       eth_copy_and_sum(skb, dev->rx_buff, pkt_len, 0);
-       skb_put(skb, pkt_len);
-       skb->protocol = eth_type_trans(skb, netdev);
-       netif_rx(skb);
+
+       skb_put(dev->rx_skb, pkt_len);
+       dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev);
+       netif_rx(dev->rx_skb);
+
+       new_skb->dev = netdev;
+       skb_reserve(new_skb, 2);
+       dev->rx_skb = new_skb;
        dev->stats.rx_packets++;
        dev->stats.rx_bytes += pkt_len;
 goon:
        FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
-                     dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+                     dev->rx_skb->data, RTL8150_MAX_MTU + 4,
+                     read_bulk_callback, dev);
        if ((res=usb_submit_urb(dev->rx_urb, GFP_ATOMIC)))
                warn("%s: Rx urb submission failed %d", netdev->name, res);
 }
@@ -363,6 +365,7 @@
        dev = urb->context;
        if (!dev)
                return;
+       dev_kfree_skb_irq(dev->tx_skb);
        if (!netif_device_present(dev->netdev))
                return;
        if (urb->status)
@@ -479,10 +482,9 @@
        dev = netdev->priv;
        count = (skb->len < 60) ? 60 : skb->len;
        count = (count & 0x3f) ? count : count + 1;
-       memcpy(dev->tx_buff, skb->data, skb->len);
+       dev->tx_skb = skb;
        FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev,2),
-                     dev->tx_buff, RTL8150_MAX_MTU, write_bulk_callback, dev);
-       dev->tx_urb->transfer_buffer_length = count;
+                     skb->data, count, write_bulk_callback, dev);
 
        if ((res = usb_submit_urb(dev->tx_urb, GFP_KERNEL))) {
                warn("failed tx_urb %d\n", res);
@@ -493,7 +495,6 @@
                dev->stats.tx_bytes += skb->len;
                netdev->trans_start = jiffies;
        }
-       dev_kfree_skb(skb);
 
        return 0;
 }
@@ -510,10 +511,13 @@
        }
 
        down(&dev->sem);
+
        FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
-                       dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+                     dev->rx_skb->data, RTL8150_MAX_MTU + 4,
+                     read_bulk_callback, dev);
        if ((res=usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
                warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
+
        FILL_INT_URB(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev,3),
                        dev->intr_buff, sizeof(dev->intr_buff), intr_callback,
                        dev, dev->intr_interval);
@@ -708,15 +712,20 @@
        netdev->mtu = RTL8150_MTU;
        dev->intr_interval = 100;       /* 100ms */
 
-       if (rtl8150_reset(dev) || !alloc_all_urbs(dev)) {
+       if ((dev->rx_skb = dev_alloc_skb(RTL8150_MAX_MTU + 2)) == NULL ||
+           rtl8150_reset(dev) || !alloc_all_urbs(dev)) {
                err("couldn't reset the device");
                free_all_urbs(dev);
+               if (dev->rx_skb != NULL)
+                       dev_kfree_skb(dev->rx_skb);
                unregister_netdev(dev->netdev);
                kfree(netdev);
                kfree(dev);
                dev = NULL;
                goto exit;
        }
+       dev->rx_skb->dev = netdev;
+       skb_reserve(dev->rx_skb, 2);
 
        set_ethernet_addr(dev);
        info("%s: rtl8150 is detected", netdev->name);
@@ -734,6 +743,7 @@
        unregister_netdev(dev->netdev);
        unlink_all_urbs(dev);
        free_all_urbs(dev);
+       dev_kfree_skb(dev->rx_skb);
        kfree(dev->netdev);
        kfree(dev);
        dev->netdev = NULL;

Reply via email to