diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bc15940ce1bc..30e567a2d5a1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) | 64 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) |
65 | #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) | 65 | #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) |
66 | #define RX_DEF_PENDING RX_MAX_PENDING | 66 | #define RX_DEF_PENDING RX_MAX_PENDING |
67 | #define RX_SKB_ALIGN 8 | ||
68 | 67 | ||
69 | #define TX_RING_SIZE 512 | 68 | #define TX_RING_SIZE 512 |
70 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) | 69 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) |
@@ -1174,24 +1173,32 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp | |||
1174 | /* | 1173 | /* |
1175 | * Allocate an skb for receiving. If the MTU is large enough | 1174 | * Allocate an skb for receiving. If the MTU is large enough |
1176 | * make the skb non-linear with a fragment list of pages. | 1175 | * make the skb non-linear with a fragment list of pages. |
1177 | * | ||
1178 | * It appears the hardware has a bug in the FIFO logic that | ||
1179 | * cause it to hang if the FIFO gets overrun and the receive buffer | ||
1180 | * is not 64 byte aligned. The buffer returned from netdev_alloc_skb is | ||
1181 | * aligned except if slab debugging is enabled. | ||
1182 | */ | 1176 | */ |
1183 | static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2) | 1177 | static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2) |
1184 | { | 1178 | { |
1185 | struct sk_buff *skb; | 1179 | struct sk_buff *skb; |
1186 | unsigned long p; | ||
1187 | int i; | 1180 | int i; |
1188 | 1181 | ||
1189 | skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size + RX_SKB_ALIGN); | 1182 | if (sky2->hw->flags & SKY2_HW_FIFO_HANG_CHECK) { |
1190 | if (!skb) | 1183 | unsigned char *start; |
1191 | goto nomem; | 1184 | /* |
1192 | 1185 | * Workaround for a bug in FIFO that cause hang | |
1193 | p = (unsigned long) skb->data; | 1186 | * if the FIFO if the receive buffer is not 64 byte aligned. |
1194 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); | 1187 | * The buffer returned from netdev_alloc_skb is |
1188 | * aligned except if slab debugging is enabled. | ||
1189 | */ | ||
1190 | skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size + 8); | ||
1191 | if (!skb) | ||
1192 | goto nomem; | ||
1193 | start = PTR_ALIGN(skb->data, 8); | ||
1194 | skb_reserve(skb, start - skb->data); | ||
1195 | } else { | ||
1196 | skb = netdev_alloc_skb(sky2->netdev, | ||
1197 | sky2->rx_data_size + NET_IP_ALIGN); | ||
1198 | if (!skb) | ||
1199 | goto nomem; | ||
1200 | skb_reserve(skb, NET_IP_ALIGN); | ||
1201 | } | ||
1195 | 1202 | ||
1196 | for (i = 0; i < sky2->rx_nfrags; i++) { | 1203 | for (i = 0; i < sky2->rx_nfrags; i++) { |
1197 | struct page *page = alloc_page(GFP_ATOMIC); | 1204 | struct page *page = alloc_page(GFP_ATOMIC); |