]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
xilinx_emacps: Fix handling of skb fragments (1/3)
authorThomas Betker <thomas.betker@rohde-schwarz.com>
Sat, 6 Apr 2013 09:56:39 +0000 (11:56 +0200)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 15 Apr 2013 09:50:10 +0000 (11:50 +0200)
xemacps_clean_rings() needs to know the fragment length for unmapping
a Tx skb fragment -- skb->len is only correct for the first fragment.

For this, we add a field 'len' to 'struct ring_info'. We employ this
field for Rx packets as well, if only to avoid using the constant
XEMACPS_RX_BUF_SIZE everywhere.

Note: We also fix a minor issue with the tx_bytes statistics counter in
xemacps_tx_poll(); it was found when dropping the 'leninbd' variable
(which is no longer needed).

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/net/ethernet/xilinx/xilinx_emacps.c

index e787e86d82cb84b044393ee1833cc6ca7164ed2e..999eeb2bbfd9c9b14734627fa5dca23288b174a2 100644 (file)
@@ -489,6 +489,7 @@ MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 };
 struct ring_info {
        struct sk_buff *skb;
        dma_addr_t mapping;
+       size_t len;
 };
 
 /* DMA buffer descriptor structure. Each BD is two words */
@@ -1154,7 +1155,7 @@ static int xemacps_rx(struct net_local *lp, int budget)
                skb = lp->rx_skb[lp->rx_bd_ci].skb;
                dma_unmap_single(lp->ndev->dev.parent,
                                lp->rx_skb[lp->rx_bd_ci].mapping,
-                               XEMACPS_RX_BUF_SIZE,
+                               lp->rx_skb[lp->rx_bd_ci].len,
                                DMA_FROM_DEVICE);
 
                /* setup received skb and send it upstream */
@@ -1205,6 +1206,7 @@ static int xemacps_rx(struct net_local *lp, int budget)
                                        | (new_skb_baddr);
                lp->rx_skb[lp->rx_bd_ci].skb = new_skb;
                lp->rx_skb[lp->rx_bd_ci].mapping = new_skb_baddr;
+               lp->rx_skb[lp->rx_bd_ci].len = XEMACPS_RX_BUF_SIZE;
 
                cur_p->ctrl = 0;
                cur_p->addr &= (~XEMACPS_RXBUF_NEW_MASK);
@@ -1272,7 +1274,6 @@ static void xemacps_tx_poll(unsigned long data)
        struct net_local *lp = netdev_priv(ndev);
        u32 regval;
        u32 len = 0;
-       u32 leninbd = 0;
        unsigned int bdcount = 0;
        unsigned int bdpartialcount = 0;
        unsigned int sop = 0;
@@ -1328,8 +1329,7 @@ static void xemacps_tx_poll(unsigned long data)
                rp = &lp->tx_skb[lp->tx_bd_ci];
                skb = rp->skb;
 
-               leninbd = cur_p->ctrl & XEMACPS_TXBUF_LEN_MASK;
-               len += leninbd;
+               len += (cur_p->ctrl & XEMACPS_TXBUF_LEN_MASK);
 
 #ifdef CONFIG_XILINX_PS_EMAC_HWTSTAMP
                if ((lp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON) &&
@@ -1350,7 +1350,7 @@ static void xemacps_tx_poll(unsigned long data)
                }
 #endif /* CONFIG_XILINX_PS_EMAC_HWTSTAMP */
 
-               dma_unmap_single(&lp->pdev->dev, rp->mapping, leninbd,
+               dma_unmap_single(&lp->pdev->dev, rp->mapping, rp->len,
                        DMA_TO_DEVICE);
                if (skb != NULL)
                        dev_kfree_skb(skb);
@@ -1362,6 +1362,7 @@ static void xemacps_tx_poll(unsigned long data)
                        if (!(cur_p->ctrl & XEMACPS_TXBUF_ERR_MASK)) {
                                lp->stats.tx_packets++;
                                lp->stats.tx_bytes += len;
+                               len = 0;
                        }
                }
 
@@ -1440,7 +1441,7 @@ static void xemacps_clean_rings(struct net_local *lp)
                if (lp->rx_skb && lp->rx_skb[i].skb) {
                        dma_unmap_single(lp->ndev->dev.parent,
                                         lp->rx_skb[i].mapping,
-                                        XEMACPS_RX_BUF_SIZE,
+                                        lp->rx_skb[i].len,
                                         DMA_FROM_DEVICE);
 
                        dev_kfree_skb(lp->rx_skb[i].skb);
@@ -1453,7 +1454,7 @@ static void xemacps_clean_rings(struct net_local *lp)
                if (lp->tx_skb && lp->tx_skb[i].skb) {
                        dma_unmap_single(lp->ndev->dev.parent,
                                         lp->tx_skb[i].mapping,
-                                        lp->tx_skb[i].skb->len,
+                                        lp->tx_skb[i].len,
                                         DMA_TO_DEVICE);
 
                        dev_kfree_skb(lp->tx_skb[i].skb);
@@ -1548,6 +1549,7 @@ static int xemacps_descriptor_init(struct net_local *lp)
                                        | (new_skb_baddr);
                lp->rx_skb[i].skb = new_skb;
                lp->rx_skb[i].mapping = new_skb_baddr;
+               lp->rx_skb[i].len = XEMACPS_RX_BUF_SIZE;
                wmb();
        }
        cur_p = &lp->rx_bd[XEMACPS_RECV_BD_CNT - 1];
@@ -2057,6 +2059,7 @@ static int xemacps_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                else
                        lp->tx_skb[lp->tx_bd_tail].skb = NULL;
                lp->tx_skb[lp->tx_bd_tail].mapping = mapping;
+               lp->tx_skb[lp->tx_bd_tail].len = len;
                cur_p->addr = mapping;
 
                /* Preserve only critical status bits.  Packet is NOT to be