[PATCH] sky2: receive buffer alignment
authorStephen Hemminger <shemminger@osdl.org>
Tue, 17 Jan 2006 21:43:10 +0000 (13:43 -0800)
committerJeff Garzik <jgarzik@pobox.com>
Wed, 18 Jan 2006 00:27:28 +0000 (19:27 -0500)
Need to make sure that sky2 receive buffers are 64 bit
aligned. Also, don't need to start off with GFP_ATOMIC
on initial setup.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
drivers/net/sky2.c

index f5d697c0c0315e6fa0594a4bb216a5ab89b234e1..99627524514453f0449a0ba0b3100deb23702564 100644 (file)
@@ -75,6 +75,7 @@
 #define RX_LE_BYTES            (RX_LE_SIZE*sizeof(struct sky2_rx_le))
 #define RX_MAX_PENDING         (RX_LE_SIZE/2 - 2)
 #define RX_DEF_PENDING         RX_MAX_PENDING
+#define RX_SKB_ALIGN           8
 
 #define TX_RING_SIZE           512
 #define TX_DEF_PENDING         (TX_RING_SIZE - 1)
@@ -904,16 +905,31 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 }
 #endif
 
+/*
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned. ALso alloc_skb() won't align properly if slab
+ * debugging is enabled.
+ */
+static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+       if (likely(skb)) {
+               unsigned long p = (unsigned long) skb->data;
+               skb_reserve(skb,
+                       ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+       }
+
+       return skb;
+}
+
 /*
  * Allocate and setup receiver buffer pool.
  * In case of 64 bit dma, there are 2X as many list elements
  * available as ring entries
  * and need to reserve one list element so we don't wrap around.
- *
- * It appears the hardware has a bug in the FIFO logic that
- * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned.  This means we can't use skb_reserve to align
- * the IP header.
  */
 static int sky2_rx_start(struct sky2_port *sky2)
 {
@@ -929,7 +945,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
        for (i = 0; i < sky2->rx_pending; i++) {
                struct ring_info *re = sky2->rx_ring + i;
 
-               re->skb = dev_alloc_skb(sky2->rx_bufsize);
+               re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
                if (!re->skb)
                        goto nomem;
 
@@ -1713,7 +1729,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
        } else {
                struct sk_buff *nskb;
 
-               nskb = dev_alloc_skb(sky2->rx_bufsize);
+               nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
                if (!nskb)
                        goto resubmit;