static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed) { struct net_device *netdev = priv->netdev; struct ftmac100_rxdes *rxdes; struct sk_buff *skb; struct page *page; dma_addr_t map; int length; rxdes = ftmac100_rx_locate_first_segment(priv); if (!rxdes) return false; if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) { ftmac100_rx_drop_packet(priv); return true; } /* * It is impossible to get multi-segment packets * because we always provide big enough receive buffers. */ if (unlikely(!ftmac100_rxdes_last_segment(rxdes))) BUG(); /* start processing */ skb = netdev_alloc_skb_ip_align(netdev, 128); if (unlikely(!skb)) { if (net_ratelimit()) netdev_err(netdev, "rx skb alloc failed\n"); ftmac100_rx_drop_packet(priv); return true; } if (unlikely(ftmac100_rxdes_multicast(rxdes))) netdev->stats.multicast++; map = ftmac100_rxdes_get_dma_addr(rxdes); dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); length = ftmac100_rxdes_frame_length(rxdes); page = ftmac100_rxdes_get_page(rxdes); skb_fill_page_desc(skb, 0, page, 0, length); skb->len += length; skb->data_len += length; if (length > 128) { skb->truesize += PAGE_SIZE; /* We pull the minimum amount into linear part */ __pskb_pull_tail(skb, ETH_HLEN); } else { /* Small frames are copied into linear part to free one page */ __pskb_pull_tail(skb, length); } ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC); ftmac100_rx_pointer_advance(priv); skb->protocol = eth_type_trans(skb, netdev); netdev->stats.rx_packets++; netdev->stats.rx_bytes += skb->len; /* push packet to protocol stack */ netif_receive_skb(skb); (*processed)++; return true; }
static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed) { struct net_device *netdev = priv->netdev; struct ftmac100_rxdes *rxdes; struct sk_buff *skb; struct page *page; dma_addr_t map; int length; rxdes = ftmac100_rx_locate_first_segment(priv); if (!rxdes) return false; if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) { ftmac100_rx_drop_packet(priv); return true; } /* */ if (unlikely(!ftmac100_rxdes_last_segment(rxdes))) BUG(); /* */ skb = netdev_alloc_skb_ip_align(netdev, 128); if (unlikely(!skb)) { if (net_ratelimit()) netdev_err(netdev, "rx skb alloc failed\n"); ftmac100_rx_drop_packet(priv); return true; } if (unlikely(ftmac100_rxdes_multicast(rxdes))) netdev->stats.multicast++; map = ftmac100_rxdes_get_dma_addr(rxdes); dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE); length = ftmac100_rxdes_frame_length(rxdes); page = ftmac100_rxdes_get_page(rxdes); skb_fill_page_desc(skb, 0, page, 0, length); skb->len += length; skb->data_len += length; /* */ if (length > 64) skb->truesize += PAGE_SIZE; __pskb_pull_tail(skb, min(length, 64)); ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC); ftmac100_rx_pointer_advance(priv); skb->protocol = eth_type_trans(skb, netdev); netdev->stats.rx_packets++; netdev->stats.rx_bytes += skb->len; /* */ netif_receive_skb(skb); (*processed)++; return true; }