On 7/27/2015 11:47 AM, David Laight wrote:

Renesas Ethernet AVB controller requires that all data are aligned on 4-byte
boundary.  While it's  easily achievable for  the RX  data with  the help of
skb_reserve() (we even align on 128-byte boundary as recommended by the manual),
we  can't  do the same with the TX data, and it always comes  unaligned from
the networking core. Originally we solved it an easy way, copying all packet
to  a  preallocated  aligned buffer; however, it's enough to copy only up to
3 first bytes from each packet, doing the transfer using 2 TX descriptors
instead of just 1. Here's an implementation of the new  TX algorithm that
significantly reduces the driver's memory requirements.

...
-       buffer = PTR_ALIGN(priv->tx_buffers[q][entry], RAVB_ALIGN);
-       memcpy(buffer, skb->data, skb->len);
-       desc = &priv->tx_ring[q][entry];
-       desc->ds_tagl = cpu_to_le16(skb->len);
-       dma_addr = dma_map_single(&ndev->dev, buffer, skb->len, DMA_TO_DEVICE);
+       buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
+                entry / NUM_TX_DESC * DPTR_ALIGN;

The above would be clearer if tx_align was char[DPTR_ALIGN][].

   tx_align is a pointer, not an array.

+       len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
+       memcpy(buffer, skb->data, len);

Does this imply there has been an skb_linearize() ???

Sure, I don't support S/G (and it seems problematic given how the DMA descriptors are handled by the h/w).

The old version didn't really need it (it was doing a copy anyway).

   It did since it copied the whole packet.

+       dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE);
        if (dma_mapping_error(&ndev->dev, dma_addr))
                goto drop;
+
+       desc = &priv->tx_ring[q][entry];
+       desc->ds_tagl = cpu_to_le16(len);
+       desc->dptr = cpu_to_le32(dma_addr);
+
+       buffer = skb->data + len;
+       len = skb->len - len;
+       dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE);
+       if (dma_mapping_error(&ndev->dev, dma_addr))
+               goto unmap;
+
+       desc++;
+       desc->ds_tagl = cpu_to_le16(len);

What happens if a fragment is less than DPTR_ALIGN bytes ???

It's always the case. If you mean a packet shorter than DPTR_ALIGN, it can happen due to call to skb_put_padto(skb, ETH_ZLEN).

Actually is looks like you relying on having a linear skb.

   Yes, and I was relying on it even before this patch.

        David

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to