소스 검색

b44: GFP_DMA skb should not escape from driver

b44 chip has some hardware limitations, that need GFP_DMA bounce
buffers in some situations.

In order to not deplete DMA zone, we should keep allocated GFP_DMA skb
only for driver use. At rx time, we copy such skb to newly allocated
skb, reusing existing copybreak infrastructure.

On machines with low amount of memory, all skb meet the hardware limitation,
so no copy is needed. We detect this situation using a new device flag, set
to one if one GFP_DMA skb was ever allocated by b44_alloc_rx_skb().

Previously allocated skb, even outside from DMA zone will then be recycled,
to have minimal impact on DMA zone use.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Tested-by: Ionut Leonte <ionut.leonte@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Eric Dumazet 16 년 전
부모
커밋
a58c891a53
2개의 변경된 파일4개의 추가작업 그리고 2개의 파일을 삭제
  1. 3 1
      drivers/net/b44.c
  2. 1 1
      drivers/net/b44.h

+ 3 - 1
drivers/net/b44.c

@@ -679,6 +679,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
 			dev_kfree_skb_any(skb);
 			return -ENOMEM;
 		}
+		bp->force_copybreak = 1;
 	}
 
 	rh = (struct rx_header *) skb->data;
@@ -800,7 +801,7 @@ static int b44_rx(struct b44 *bp, int budget)
 		/* Omit CRC. */
 		len -= 4;
 
-		if (len > RX_COPY_THRESHOLD) {
+		if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) {
 			int skb_size;
 			skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
 			if (skb_size < 0)
@@ -2152,6 +2153,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
 	bp = netdev_priv(dev);
 	bp->sdev = sdev;
 	bp->dev = dev;
+	bp->force_copybreak = 0;
 
 	bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
 

+ 1 - 1
drivers/net/b44.h

@@ -395,7 +395,7 @@ struct b44 {
 	u32			rx_pending;
 	u32			tx_pending;
 	u8			phy_addr;
-
+	u8			force_copybreak;
 	struct mii_if_info	mii_if;
 };