--- ../../../linux-2.6.29.4/drivers/net/usb/asix.c 2009-05-19 07:52:34.000000000 +0800 +++ asix.c 2009-06-10 10:15:17.000000000 +0800 @@ -354,6 +354,85 @@ return 1; } +static struct sk_buff * +ax88772_tx_gather (struct usbnet *dev, struct sk_buff_head *q, + size_t *actual_len) +{ + struct sk_buff *skb = NULL, *skb_next = NULL; + int pkt_cnt; + u16 pkt_size; + u32 skb_len = 0; + + u32 packet_hdr; + u32 padbytes = 0xffff0000; + u8 padneeded = 0; + struct driver_info *info = dev->driver_info; + + pkt_cnt = skb_queue_len (q); + + *actual_len = 0; + for (skb_next = q->next; skb_next != (struct sk_buff *) q; + skb_next = skb_next->next){ + *actual_len += skb_next->len; + pkt_size = (skb_next->len + 4 + 1) & 0xFFFE; + skb_len += pkt_size; + } + + if ((skb_len % 512) == 0) { + skb_len += sizeof (padbytes); + padneeded = 1; + } + + if (pkt_cnt > 1){ + + skb = dev_alloc_skb (skb_len); + + if (!skb){ + + while (pkt_cnt--) { + skb_next = __skb_dequeue(q); + dev_kfree_skb_any (skb_next); + } + + devdbg (dev, "skb is NULL, len %d", skb_len); + return skb; + } + + while (pkt_cnt--) { + + skb_next = __skb_dequeue(q); + + packet_hdr = ((skb_next->len ^ 0x0000ffff) << 16) + + skb_next->len; + + le32_to_cpus(&packet_hdr); + memcpy (skb_put(skb, 4), &packet_hdr, 4); + memcpy (skb_put(skb, skb_next->len), skb_next->data, + skb_next->len); + if (skb->len & 1) + skb_put (skb, 1); + dev_kfree_skb_any (skb_next); + } + + if (padneeded) { + memcpy (skb_put(skb, sizeof (padbytes)), + &padbytes, sizeof (padbytes)); + } + + }else{ //only one packet to send + skb = __skb_dequeue(q); + + skb = info->tx_fixup (dev, skb, GFP_ATOMIC); + if (!skb) { + if (netif_msg_tx_err (dev)) + devdbg (dev, "can't tx_fixup skb"); + return skb; + } + } + + return skb; +} + static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { @@ -1011,6 +1090,7 @@ /* hard_mtu is still the default - the device does not support jumbo eth frames */ dev->rx_urb_size = 2048; + dev->tx_threshold = 16384; } return 0; @@ -1281,6 +1361,7 @@ /* hard_mtu is still the default - the device does not support jumbo eth frames */ dev->rx_urb_size = 2048; + dev->tx_threshold = 16384; } return 0; @@ -1337,6 +1418,7 @@ .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup, + .tx_gather = ax88772_tx_gather, }; static const struct driver_info ax88178_info = { @@ -1348,6 +1430,7 @@ .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup, + .tx_gather = ax88772_tx_gather, }; static const struct usb_device_id products [] = {