Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
[linux-drm-fsl-dcu.git] / drivers / net / ethernet / freescale / fec_main.c
index b2793b91cc553e41e80170ac791d10b83f0e776d..4cbebf3d80eb1492d847f1ad8a9888e2a6c17b97 100644 (file)
@@ -386,7 +386,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
         */
        bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
                        FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-
+       if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+               bdp->cbd_bufaddr = 0;
+               fep->tx_skbuff[index] = NULL;
+               dev_kfree_skb_any(skb);
+               if (net_ratelimit())
+                       netdev_err(ndev, "Tx DMA memory map failed\n");
+               return NETDEV_TX_OK;
+       }
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
         */
@@ -861,6 +868,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
        struct  bufdesc_ex *ebdp = NULL;
        bool    vlan_packet_rcvd = false;
        u16     vlan_tag;
+       int     index = 0;
 
 #ifdef CONFIG_M532x
        flush_cache_all();
@@ -916,10 +924,15 @@ fec_enet_rx(struct net_device *ndev, int budget)
                ndev->stats.rx_packets++;
                pkt_len = bdp->cbd_datlen;
                ndev->stats.rx_bytes += pkt_len;
-               data = (__u8*)__va(bdp->cbd_bufaddr);
 
-               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-                               FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+               if (fep->bufdesc_ex)
+                       index = (struct bufdesc_ex *)bdp -
+                               (struct bufdesc_ex *)fep->rx_bd_base;
+               else
+                       index = bdp - fep->rx_bd_base;
+               data = fep->rx_skbuff[index]->data;
+               dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
+                                       FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 
                if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
                        swap_buffer(data, pkt_len);
@@ -999,8 +1012,8 @@ fec_enet_rx(struct net_device *ndev, int budget)
                        napi_gro_receive(&fep->napi, skb);
                }
 
-               bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
-                               FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+               dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
+                                       FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 rx_processing_done:
                /* Clear the status flags for this buffer */
                status &= ~BD_ENET_RX_STATS;
@@ -1719,6 +1732,12 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 
                bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
                                FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+                       fec_enet_free_buffers(ndev);
+                       if (net_ratelimit())
+                               netdev_err(ndev, "Rx DMA memory map failed\n");
+                       return -ENOMEM;
+               }
                bdp->cbd_sc = BD_ENET_RX_EMPTY;
 
                if (fep->bufdesc_ex) {