From dad3ba0f0bb5ee2e87881c9f3a7ecfb8db384b2b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 9 Dec 2014 22:25:25 -0700 Subject: [PATCH] net: rtl8169: Properly align buffers 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 Signed-off-by: Simon Glass Signed-off-by: Tom Warren --- drivers/net/rtl8169.c | 63 +++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 955b2e1bfc..fc8c31ee5e 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -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; } -- 2.30.2