All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available
Date: Tue, 26 Aug 2014 17:34:27 +0200	[thread overview]
Message-ID: <1409067268-956-40-git-send-email-thierry.reding@gmail.com> (raw)
In-Reply-To: <1409067268-956-1-git-send-email-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

To work around potential issues with explicit cache maintenance of the
RX and TX descriptor rings, allocate them from a pool of uncached memory
if the architecture supports it.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- if non-cached memory is not available, use memalign() for more
  consistent descriptor allocations
- allow rtl_init() to fail

 drivers/net/rtl8169.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 60 insertions(+), 11 deletions(-)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index d81ee8af1cc1..22ad70719937 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -41,6 +41,7 @@
  * Modified to use le32_to_cpu and cpu_to_le32 properly
  */
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <net.h>
 #include <netdev.h>
@@ -290,16 +291,15 @@ struct RxDesc {
  * 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.
+ *
+ * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause
+ * the driver allocate descriptors from a pool of non-cached memory.
  */
 #if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 #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 */
-DEFINE_ALIGN_BUFFER(struct RxDesc, rx_ring, NUM_RX_DESC, RTL8169_ALIGN);
+#endif
 
 /*
  * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
@@ -418,34 +418,71 @@ match:
 }
 
 /*
+ * TX and RX descriptors are 16 bytes. This causes problems with the cache
+ * maintenance on CPUs where the cache-line size exceeds the size of these
+ * descriptors. What will happen is that when the driver receives a packet
+ * it will be immediately requeued for the hardware to reuse. The CPU will
+ * therefore need to flush the cache-line containing the descriptor, which
+ * will cause all other descriptors in the same cache-line to be flushed
+ * along with it. If one of those descriptors had been written to by the
+ * device those changes (and the associated packet) will be lost.
+ *
+ * To work around this, we make use of non-cached memory if available. If
+ * descriptors are mapped uncached there's no need to manually flush them
+ * or invalidate them.
+ *
+ * Note that this only applies to descriptors. The packet data buffers do
+ * not have the same constraints since they are 1536 bytes large, so they
+ * are unlikely to share cache-lines.
+ */
+static void *rtl_alloc_descs(unsigned int num)
+{
+	size_t size = num * RTL8169_DESC_SIZE;
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+	return (void *)noncached_alloc(size, RTL8169_ALIGN);
+#else
+	return memalign(RTL8169_ALIGN, size);
+#endif
+}
+
+/*
  * Cache maintenance functions. These are simple wrappers around the more
  * general purpose flush_cache() and invalidate_dcache_range() functions.
  */
 
 static void rtl_inval_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
 	unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
 	invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
 	unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
 	invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_buffer(void *buf, size_t size)
@@ -911,10 +948,16 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
 	}
 
-	tpc->TxDescArray = tx_ring;
-	tpc->RxDescArray = rx_ring;
 
-	return 1;
+	tpc->RxDescArray = rtl_alloc_descs(NUM_RX_DESC);
+	if (!tpc->RxDescArray)
+		return -ENOMEM;
+
+	tpc->TxDescArray = rtl_alloc_descs(NUM_TX_DESC);
+	if (!tpc->TxDescArray)
+		return -ENOMEM;
+
+	return 0;
 }
 
 int rtl8169_initialize(bd_t *bis)
@@ -928,6 +971,7 @@ int rtl8169_initialize(bd_t *bis)
 	while(1){
 		unsigned int region;
 		u16 device;
+		int err;
 
 		/* Find RTL8169 */
 		if ((devno = pci_find_devices(supported, idx++)) < 0)
@@ -966,9 +1010,14 @@ int rtl8169_initialize(bd_t *bis)
 		dev->send = rtl_send;
 		dev->recv = rtl_recv;
 
-		eth_register (dev);
+		err = rtl_init(dev, bis);
+		if (err < 0) {
+			printf(pr_fmt("failed to initialize card: %d\n"), err);
+			free(dev);
+			continue;
+		}
 
-		rtl_init(dev, bis);
+		eth_register (dev);
 
 		card_number++;
 	}
-- 
2.0.4

  parent reply	other threads:[~2014-08-26 15:34 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
2014-08-26 17:04   ` Stephen Warren
2014-08-27  7:01     ` Thierry Reding
2014-08-27 17:41       ` Stephen Warren
2014-08-28 10:38         ` Thierry Reding
2014-09-17  0:44           ` [U-Boot] [U-Boot, v2, " Tom Rini
2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
2014-08-27  7:37     ` Thierry Reding
2014-08-27 15:24       ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:01     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2015-03-25 23:23       ` Simon Glass
2015-07-14 19:48         ` Simon Glass
2015-07-15 11:17           ` Thierry Reding
2015-07-15 11:35             ` Albert ARIBAUD
2015-07-15 11:52               ` Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev() Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
2014-08-27  4:52   ` Heiko Schocher
2014-08-27  5:12     ` Thierry Reding
2014-08-27  5:26       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
2014-08-27  5:21   ` Heiko Schocher
2014-08-27  6:21     ` Thierry Reding
2014-08-27  7:07       ` Heiko Schocher
2014-08-27  8:51         ` Thierry Reding
2014-08-27  9:56           ` Heiko Schocher
2014-08-27 11:41             ` Thierry Reding
2014-08-27 19:10               ` Simon Glass
2014-08-28  9:53                 ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
2014-09-02 19:24   ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
2014-08-27  5:26   ` Heiko Schocher
2014-08-27  6:28     ` Thierry Reding
2014-08-27  7:18       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
2014-08-27 18:56   ` Simon Glass
2014-11-08  8:30   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
2014-08-27 18:57   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
2014-08-27 18:58   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
2014-08-27 19:07   ` Simon Glass
2014-10-24 19:11   ` Stephen Warren
2014-11-12 15:49     ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
2014-11-12 23:37   ` Nobuhiro Iwamatsu
2014-08-26 15:34 ` Thierry Reding [this message]
2014-08-26 15:34 ` [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g Thierry Reding
2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
2014-09-11 16:17   ` Stephen Warren
2014-09-11 19:20     ` Simon Glass
2014-09-18  8:43       ` Albert ARIBAUD
2014-09-18 18:01         ` Simon Glass
2014-10-23  3:07   ` Simon Glass
2014-10-23  8:11     ` Thierry Reding
2014-10-23 18:33       ` Simon Glass
2014-09-28 22:48 ` Simon Glass
2014-09-29  8:11   ` Thierry Reding
2014-09-29 13:54     ` Simon Glass
2014-10-06 12:24     ` Heiko Schocher
2014-10-26 19:07 ` Albert ARIBAUD
2014-10-26 19:29   ` Albert ARIBAUD
2014-10-27 23:55   ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1409067268-956-40-git-send-email-thierry.reding@gmail.com \
    --to=thierry.reding@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.