[PATCH] sky2: receive buffer alignment
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>
This commit is contained in:
Родитель
0547993820
Коммит
82788c7a47
|
@ -75,6 +75,7 @@
|
||||||
#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
|
#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
|
||||||
#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
|
#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
|
||||||
#define RX_DEF_PENDING RX_MAX_PENDING
|
#define RX_DEF_PENDING RX_MAX_PENDING
|
||||||
|
#define RX_SKB_ALIGN 8
|
||||||
|
|
||||||
#define TX_RING_SIZE 512
|
#define TX_RING_SIZE 512
|
||||||
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
|
#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
|
#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.
|
* Allocate and setup receiver buffer pool.
|
||||||
* In case of 64 bit dma, there are 2X as many list elements
|
* In case of 64 bit dma, there are 2X as many list elements
|
||||||
* available as ring entries
|
* available as ring entries
|
||||||
* and need to reserve one list element so we don't wrap around.
|
* 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)
|
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++) {
|
for (i = 0; i < sky2->rx_pending; i++) {
|
||||||
struct ring_info *re = sky2->rx_ring + 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)
|
if (!re->skb)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
|
||||||
|
@ -1713,7 +1729,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
|
||||||
} else {
|
} else {
|
||||||
struct sk_buff *nskb;
|
struct sk_buff *nskb;
|
||||||
|
|
||||||
nskb = dev_alloc_skb(sky2->rx_bufsize);
|
nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
|
||||||
if (!nskb)
|
if (!nskb)
|
||||||
goto resubmit;
|
goto resubmit;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче