net: rtl8169: Properly align buffers
authorThierry Reding <treding@nvidia.com>
Wed, 10 Dec 2014 05:25:25 +0000 (22:25 -0700)
committerTom Warren <twarren@nvidia.com>
Thu, 18 Dec 2014 20:21:41 +0000 (13:21 -0700)
RX and TX descriptor rings should be aligned to 256 byte boundaries. Use
the DEFINE_ALIGN_BUFFER() macro to define the buffers so that they don't
have to be manually aligned later on. Also make sure that the buffers do
align to cache-line boundaries in case the cache-line is higher than the
256 byte alignment requirements of the NIC.

Also add a warning if the cache-line size is larger than the descriptor
size, because the driver may discard changes to descriptors made by the
hardware when requeuing RX buffers.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Warren <twarren@nvidia.com>
drivers/net/rtl8169.c

index 955b2e1bfcab5271287928e021c2daeac7cb235c..fc8c31ee5ed22362a45f4ee10d03b6662df4a38a 100644 (file)
@@ -277,23 +277,41 @@ struct RxDesc {
        u32 buf_Haddr;
 };
 
-/* Define the TX Descriptor */
-static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256];
-/*     __attribute__ ((aligned(256))); */
+#define RTL8169_DESC_SIZE 16
 
-/* Create a static buffer of size RX_BUF_SZ for each
-TX Descriptor. All descriptors point to a
-part of this buffer */
-static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE];
+#if ARCH_DMA_MINALIGN > 256
+#  define RTL8169_ALIGN ARCH_DMA_MINALIGN
+#else
+#  define RTL8169_ALIGN 256
+#endif
+
+/*
+ * Warn if the cache-line size is larger than the descriptor size. In such
+ * cases the driver will likely fail because the CPU needs to flush the cache
+ * when requeuing RX buffers, therefore descriptors written by the hardware
+ * may be discarded.
+ */
+#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
+#warning cache-line size is larger than descriptor size
+#endif
+
+/* Define the TX Descriptor */
+DEFINE_ALIGN_BUFFER(struct TxDesc, tx_ring, NUM_TX_DESC, RTL8169_ALIGN);
 
 /* Define the RX Descriptor */
-static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256];
-  /*  __attribute__ ((aligned(256))); */
+DEFINE_ALIGN_BUFFER(struct RxDesc, rx_ring, NUM_RX_DESC, RTL8169_ALIGN);
 
-/* Create a static buffer of size RX_BUF_SZ for each
-RX Descriptor  All descriptors point to a
-part of this buffer */
-static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
+/*
+ * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, txb, NUM_TX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
+
+/*
+ * Create a static buffer of size RX_BUF_SZ for each RX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, rxb, NUM_RX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
 
 struct rtl8169_private {
        void *mmio_addr;        /* memory map physical address */
@@ -301,8 +319,6 @@ struct rtl8169_private {
        unsigned long cur_rx;   /* Index into the Rx descriptor buffer of next Rx pkt. */
        unsigned long cur_tx;   /* Index into the Tx descriptor buffer of next Rx pkt. */
        unsigned long dirty_tx;
-       unsigned char *TxDescArrays;    /* Index of Tx Descriptor buffer */
-       unsigned char *RxDescArrays;    /* Index of Rx Descriptor buffer */
        struct TxDesc *TxDescArray;     /* Index of 256-alignment Tx Descriptor buffer */
        struct RxDesc *RxDescArray;     /* Index of 256-alignment Rx Descriptor buffer */
        unsigned char *RxBufferRings;   /* Index of Rx Buffer  */
@@ -711,16 +727,6 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
        printf ("%s\n", __FUNCTION__);
 #endif
 
-       tpc->TxDescArrays = tx_ring;
-       /* Tx Desscriptor needs 256 bytes alignment; */
-       tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays +
-                                                             255) & ~255);
-
-       tpc->RxDescArrays = rx_ring;
-       /* Rx Desscriptor needs 256 bytes alignment; */
-       tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays +
-                                                             255) & ~255);
-
        rtl8169_init_ring(dev);
        rtl8169_hw_start(dev);
        /* Construct a perfect filter frame with the mac address as first match
@@ -762,10 +768,6 @@ static void rtl_halt(struct eth_device *dev)
 
        RTL_W32(RxMissed, 0);
 
-       tpc->TxDescArrays = NULL;
-       tpc->RxDescArrays = NULL;
-       tpc->TxDescArray = NULL;
-       tpc->RxDescArray = NULL;
        for (i = 0; i < NUM_RX_DESC; i++) {
                tpc->RxBufferRing[i] = NULL;
        }
@@ -910,6 +912,9 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
        }
 
+       tpc->TxDescArray = tx_ring;
+       tpc->RxDescArray = rx_ring;
+
        return 1;
 }