diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f5d697c0c031..996275245144 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) | 75 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) |
76 | #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) | 76 | #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) |
77 | #define RX_DEF_PENDING RX_MAX_PENDING | 77 | #define RX_DEF_PENDING RX_MAX_PENDING |
78 | #define RX_SKB_ALIGN 8 | ||
78 | 79 | ||
79 | #define TX_RING_SIZE 512 | 80 | #define TX_RING_SIZE 512 |
80 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) | 81 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) |
@@ -905,15 +906,30 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
905 | #endif | 906 | #endif |
906 | 907 | ||
907 | /* | 908 | /* |
909 | * It appears the hardware has a bug in the FIFO logic that | ||
910 | * cause it to hang if the FIFO gets overrun and the receive buffer | ||
911 | * is not aligned. ALso alloc_skb() won't align properly if slab | ||
912 | * debugging is enabled. | ||
913 | */ | ||
914 | static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | ||
915 | { | ||
916 | struct sk_buff *skb; | ||
917 | |||
918 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | ||
919 | if (likely(skb)) { | ||
920 | unsigned long p = (unsigned long) skb->data; | ||
921 | skb_reserve(skb, | ||
922 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
923 | } | ||
924 | |||
925 | return skb; | ||
926 | } | ||
927 | |||
928 | /* | ||
908 | * Allocate and setup receiver buffer pool. | 929 | * Allocate and setup receiver buffer pool. |
909 | * In case of 64 bit dma, there are 2X as many list elements | 930 | * In case of 64 bit dma, there are 2X as many list elements |
910 | * available as ring entries | 931 | * available as ring entries |
911 | * and need to reserve one list element so we don't wrap around. | 932 | * and need to reserve one list element so we don't wrap around. |
912 | * | ||
913 | * It appears the hardware has a bug in the FIFO logic that | ||
914 | * cause it to hang if the FIFO gets overrun and the receive buffer | ||
915 | * is not aligned. This means we can't use skb_reserve to align | ||
916 | * the IP header. | ||
917 | */ | 933 | */ |
918 | static int sky2_rx_start(struct sky2_port *sky2) | 934 | static int sky2_rx_start(struct sky2_port *sky2) |
919 | { | 935 | { |
@@ -929,7 +945,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
929 | for (i = 0; i < sky2->rx_pending; i++) { | 945 | for (i = 0; i < sky2->rx_pending; i++) { |
930 | struct ring_info *re = sky2->rx_ring + i; | 946 | struct ring_info *re = sky2->rx_ring + i; |
931 | 947 | ||
932 | re->skb = dev_alloc_skb(sky2->rx_bufsize); | 948 | re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL); |
933 | if (!re->skb) | 949 | if (!re->skb) |
934 | goto nomem; | 950 | goto nomem; |
935 | 951 | ||
@@ -1713,7 +1729,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2, | |||
1713 | } else { | 1729 | } else { |
1714 | struct sk_buff *nskb; | 1730 | struct sk_buff *nskb; |
1715 | 1731 | ||
1716 | nskb = dev_alloc_skb(sky2->rx_bufsize); | 1732 | nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC); |
1717 | if (!nskb) | 1733 | if (!nskb) |
1718 | goto resubmit; | 1734 | goto resubmit; |
1719 | 1735 | ||