/*
  * refill rx queue
  */
-static int bcm_enet_refill_rx(struct net_device *dev)
+static int bcm_enet_refill_rx(struct net_device *dev, bool napi_mode)
 {
        struct bcm_enet_priv *priv;
 
 
        while (priv->rx_desc_count < priv->rx_ring_size) {
                struct bcm_enet_desc *desc;
-               struct sk_buff *skb;
-               dma_addr_t p;
                int desc_idx;
                u32 len_stat;
 
                desc_idx = priv->rx_dirty_desc;
                desc = &priv->rx_desc_cpu[desc_idx];
 
-               if (!priv->rx_skb[desc_idx]) {
-                       if (priv->enet_is_sw)
-                               skb = netdev_alloc_skb_ip_align(dev, priv->rx_skb_size);
+               if (!priv->rx_buf[desc_idx]) {
+                       void *buf;
+
+                       if (likely(napi_mode))
+                               buf = napi_alloc_frag(priv->rx_frag_size);
                        else
-                               skb = netdev_alloc_skb(dev, priv->rx_skb_size);
-                       if (!skb)
+                               buf = netdev_alloc_frag(priv->rx_frag_size);
+                       if (unlikely(!buf))
                                break;
-                       priv->rx_skb[desc_idx] = skb;
-                       p = dma_map_single(&priv->pdev->dev, skb->data,
-                                          priv->rx_skb_size,
-                                          DMA_FROM_DEVICE);
-                       desc->address = p;
+                       priv->rx_buf[desc_idx] = buf;
+                       desc->address = dma_map_single(&priv->pdev->dev,
+                                                      buf + priv->rx_buf_offset,
+                                                      priv->rx_buf_size,
+                                                      DMA_FROM_DEVICE);
                }
 
-               len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
+               len_stat = priv->rx_buf_size << DMADESC_LENGTH_SHIFT;
                len_stat |= DMADESC_OWNER_MASK;
                if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
                        len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift);
        struct net_device *dev = priv->net_dev;
 
        spin_lock(&priv->rx_lock);
-       bcm_enet_refill_rx(dev);
+       bcm_enet_refill_rx(dev, false);
        spin_unlock(&priv->rx_lock);
 }
 
                int desc_idx;
                u32 len_stat;
                unsigned int len;
+               void *buf;
 
                desc_idx = priv->rx_curr_desc;
                desc = &priv->rx_desc_cpu[desc_idx];
                }
 
                /* valid packet */
-               skb = priv->rx_skb[desc_idx];
+               buf = priv->rx_buf[desc_idx];
                len = (len_stat & DMADESC_LENGTH_MASK) >> DMADESC_LENGTH_SHIFT;
                /* don't include FCS */
                len -= 4;
 
                if (len < copybreak) {
-                       struct sk_buff *nskb;
-
-                       nskb = napi_alloc_skb(&priv->napi, len);
-                       if (!nskb) {
+                       skb = napi_alloc_skb(&priv->napi, len);
+                       if (unlikely(!skb)) {
                                /* forget packet, just rearm desc */
                                dev->stats.rx_dropped++;
                                continue;
 
                        dma_sync_single_for_cpu(kdev, desc->address,
                                                len, DMA_FROM_DEVICE);
-                       memcpy(nskb->data, skb->data, len);
+                       memcpy(skb->data, buf + priv->rx_buf_offset, len);
                        dma_sync_single_for_device(kdev, desc->address,
                                                   len, DMA_FROM_DEVICE);
-                       skb = nskb;
                } else {
-                       dma_unmap_single(&priv->pdev->dev, desc->address,
-                                        priv->rx_skb_size, DMA_FROM_DEVICE);
-                       priv->rx_skb[desc_idx] = NULL;
+                       dma_unmap_single(kdev, desc->address,
+                                        priv->rx_buf_size, DMA_FROM_DEVICE);
+                       priv->rx_buf[desc_idx] = NULL;
+
+                       skb = build_skb(buf, priv->rx_frag_size);
+                       if (unlikely(!skb)) {
+                               skb_free_frag(buf);
+                               dev->stats.rx_dropped++;
+                               continue;
+                       }
+                       skb_reserve(skb, priv->rx_buf_offset);
                }
 
                skb_put(skb, len);
        netif_receive_skb_list(&rx_list);
 
        if (processed || !priv->rx_desc_count) {
-               bcm_enet_refill_rx(dev);
+               bcm_enet_refill_rx(dev, true);
 
                /* kick rx dma */
                enet_dmac_writel(priv, priv->dma_chan_en_mask,
                priv->pause_tx ? "tx" : "off");
 }
 
-static void bcm_enet_free_rx_skb_ring(struct device *kdev, struct bcm_enet_priv *priv)
+static void bcm_enet_free_rx_buf_ring(struct device *kdev, struct bcm_enet_priv *priv)
 {
        int i;
 
        for (i = 0; i < priv->rx_ring_size; i++) {
                struct bcm_enet_desc *desc;
 
-               if (!priv->rx_skb[i])
+               if (!priv->rx_buf[i])
                        continue;
 
                desc = &priv->rx_desc_cpu[i];
-               dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
+               dma_unmap_single(kdev, desc->address, priv->rx_buf_size,
                                 DMA_FROM_DEVICE);
-               kfree_skb(priv->rx_skb[i]);
+               skb_free_frag(priv->rx_buf[i]);
        }
-       kfree(priv->rx_skb);
+       kfree(priv->rx_buf);
 }
 
 /*
        priv->tx_curr_desc = 0;
        spin_lock_init(&priv->tx_lock);
 
-       /* init & fill rx ring with skbs */
-       priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+       /* init & fill rx ring with buffers */
+       priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
                               GFP_KERNEL);
-       if (!priv->rx_skb) {
+       if (!priv->rx_buf) {
                ret = -ENOMEM;
                goto out_free_tx_skb;
        }
                enet_dmac_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
                                ENETDMAC_BUFALLOC, priv->rx_chan);
 
-       if (bcm_enet_refill_rx(dev)) {
-               dev_err(kdev, "cannot allocate rx skb queue\n");
+       if (bcm_enet_refill_rx(dev, false)) {
+               dev_err(kdev, "cannot allocate rx buffer queue\n");
                ret = -ENOMEM;
                goto out;
        }
        return 0;
 
 out:
-       bcm_enet_free_rx_skb_ring(kdev, priv);
+       bcm_enet_free_rx_buf_ring(kdev, priv);
 
 out_free_tx_skb:
        kfree(priv->tx_skb);
        /* force reclaim of all tx buffers */
        bcm_enet_tx_reclaim(dev, 1);
 
-       /* free the rx skb ring */
-       bcm_enet_free_rx_skb_ring(kdev, priv);
+       /* free the rx buffer ring */
+       bcm_enet_free_rx_buf_ring(kdev, priv);
 
        /* free remaining allocated memory */
        kfree(priv->tx_skb);
         * align rx buffer size to dma burst len, account FCS since
         * it's appended
         */
-       priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
+       priv->rx_buf_size = ALIGN(actual_mtu + ETH_FCS_LEN,
                                  priv->dma_maxburst * 4);
 
+       priv->rx_frag_size = SKB_DATA_ALIGN(priv->rx_buf_offset + priv->rx_buf_size) +
+                                           SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
        dev->mtu = new_mtu;
        return 0;
 }
 
        priv->enet_is_sw = false;
        priv->dma_maxburst = BCMENET_DMA_MAXBURST;
+       priv->rx_buf_offset = NET_SKB_PAD;
 
        ret = bcm_enet_change_mtu(dev, dev->mtu);
        if (ret)
        priv->tx_skb = kcalloc(priv->tx_ring_size, sizeof(struct sk_buff *),
                               GFP_KERNEL);
        if (!priv->tx_skb) {
-               dev_err(kdev, "cannot allocate rx skb queue\n");
+               dev_err(kdev, "cannot allocate tx skb queue\n");
                ret = -ENOMEM;
                goto out_free_tx_ring;
        }
        priv->tx_curr_desc = 0;
        spin_lock_init(&priv->tx_lock);
 
-       /* init & fill rx ring with skbs */
-       priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+       /* init & fill rx ring with buffers */
+       priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
                               GFP_KERNEL);
-       if (!priv->rx_skb) {
-               dev_err(kdev, "cannot allocate rx skb queue\n");
+       if (!priv->rx_buf) {
+               dev_err(kdev, "cannot allocate rx buffer queue\n");
                ret = -ENOMEM;
                goto out_free_tx_skb;
        }
        enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
                        ENETDMA_BUFALLOC_REG(priv->rx_chan));
 
-       if (bcm_enet_refill_rx(dev)) {
-               dev_err(kdev, "cannot allocate rx skb queue\n");
+       if (bcm_enet_refill_rx(dev, false)) {
+               dev_err(kdev, "cannot allocate rx buffer queue\n");
                ret = -ENOMEM;
                goto out;
        }
        return 0;
 
 out:
-       bcm_enet_free_rx_skb_ring(kdev, priv);
+       bcm_enet_free_rx_buf_ring(kdev, priv);
 
 out_free_tx_skb:
        kfree(priv->tx_skb);
        /* force reclaim of all tx buffers */
        bcm_enet_tx_reclaim(dev, 1);
 
-       /* free the rx skb ring */
-       bcm_enet_free_rx_skb_ring(kdev, priv);
+       /* free the rx buffer ring */
+       bcm_enet_free_rx_buf_ring(kdev, priv);
 
        /* free remaining allocated memory */
        kfree(priv->tx_skb);
        priv->rx_ring_size = BCMENET_DEF_RX_DESC;
        priv->tx_ring_size = BCMENET_DEF_TX_DESC;
        priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
+       priv->rx_buf_offset = NET_SKB_PAD + NET_IP_ALIGN;
 
        pd = dev_get_platdata(&pdev->dev);
        if (pd) {