Skip to contentSkip to conversation

mips: cache: Bulletproof the code against cornercases

PATCH New Marek Vasut 4 participants 19 messages Jan 27, 2016 – Feb 26, 2016

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)
arch/mips/lib/cache.c +8 -0
index bf8ff59..7482005 100644
@@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop)
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+
 	while (1) {
 		mips_cache(HIT_WRITEBACK_INV_D, addr);
 		if (addr == aend)
@@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+
 	while (1) {
 		mips_cache(HIT_INVALIDATE_D, addr);
 		if (addr == aend)
Signature · 1 line
2.1.4
#1 lore raw

PATCH 2/5 usb: ehci: Use map_physmem in ehci-generic

Some architectures, like MIPS, require remapping of the registers. Add the map_physmem() call to handle it.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
Cc Masahiro Yamada <[email protected]>
Cc Alexey Brodkin <[email protected]>
---
 drivers/usb/host/ehci-generic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/host/ehci-generic.c +3 -1
index 1292caa..6d58ef8 100644
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <asm/io.h>
 #include <dm.h>
 #include "ehci.h"
 
@@ -19,9 +20,10 @@ struct generic_ehci {
 
 static int ehci_usb_probe(struct udevice *dev)
 {
-	struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev);
+	struct ehci_hccr *hccr;
 	struct ehci_hcor *hcor;
 
+	hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE);
 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
Signature · 1 line
2.1.4
#2 lore raw

PATCH 2/5 usb: ehci: Use map_physmem in ehci-generic

Hi Marek,

Quoted 9 lines · Marek Vasut

Some architectures, like MIPS, require remapping of the registers. Add the map_physmem() call to handle it.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
Cc Masahiro Yamada <[email protected]>
Cc Alexey Brodkin <[email protected]>

---

Probably I'm missing something but I cannot apply it
on top of current master:
------------------------->8----------------------
Applying: mips: cache: Bulletproof the code against cornercases
Applying: usb: ehci: Use map_physmem in ehci-generic
error: patch failed: drivers/usb/host/ehci-generic.c:5
error: drivers/usb/host/ehci-generic.c: patch does not apply Patch failed at 0002 usb: ehci: Use map_physmem in ehci-generic The copy of the patch that failed is found in:
/home/abrodkin/Projects/sources/git/u-boot/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort" ------------------------->8----------------------

Note I'm applying entire series but not that only patch.

-Alexey

#3 lore raw

PATCH 2/5 usb: ehci: Use map_physmem in ehci-generic

Quoted 1 line · Alexey Brodkin

Hi Marek,

Hi,

Quoted 26 lines · Marek Vasut
Quoted 9 lines

Some architectures, like MIPS, require remapping of the registers. Add the map_physmem() call to handle it.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
Cc Masahiro Yamada <[email protected]>
Cc Alexey Brodkin <[email protected]>

---

Probably I'm missing something but I cannot apply it
on top of current master:
------------------------->8----------------------
Applying: mips: cache: Bulletproof the code against cornercases
Applying: usb: ehci: Use map_physmem in ehci-generic
error: patch failed: drivers/usb/host/ehci-generic.c:5
error: drivers/usb/host/ehci-generic.c: patch does not apply Patch failed at 0002 usb: ehci: Use map_physmem in ehci-generic The copy of the patch that failed is found in:
/home/abrodkin/Projects/sources/git/u-boot/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort" ------------------------->8----------------------

Quoted 1 line

Note I'm applying entire series but not that only patch.

Probably because of 4feefdcfe916113ac6e1837ea22857f25fe1771c , that's easy to fix though.

Best regards,
Marek Vasut

#4 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

In reply to Marek Vasut

Certain processor architectures, like MIPS, require that the USB structures and transfer buffers are passed with their PA to the USB controller. If VA is passed, the USB will not work. Add the necessary virt_to_phys() calls into the USB EHCI code to make it work.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 drivers/usb/host/ehci-hcd.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/usb/host/ehci-hcd.c +9 -10
index c664b16..b3eb08d 100644
@@ -245,7 +245,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 
 	idx = 0;
 	while (idx < QT_BUFFER_CNT) {
-		td->qt_buffer[idx] = cpu_to_hc32(addr);
+		td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
 		td->qt_buffer_hi[idx] = 0;
 		next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1);
 		delta = next - addr;
@@ -398,7 +398,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	 *   qh_overlay.qt_next ...... 13-10 H
 	 * - qh_overlay.qt_altnext
 	 */
-	qh->qh_link = cpu_to_hc32((unsigned long)&ctrl->qh_list | QH_LINK_TYPE_QH);
+	qh->qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH);
 	c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
 	maxpacket = usb_maxpacket(dev, pipe);
 	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
@@ -415,7 +415,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
 
 	tdp = &qh->qh_overlay.qt_next;
-
 	if (req != NULL) {
 		/*
 		 * Setup request qTD (3.5 in ehci-r10.pdf)
@@ -438,7 +437,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 			goto fail;
 		}
 		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+		*tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
 		tdp = &qtd[qtd_counter++].qt_next;
 		toggle = 1;
 	}
@@ -497,7 +496,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 				goto fail;
 			}
 			/* Update previous qTD! */
-			*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+			*tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
 			tdp = &qtd[qtd_counter++].qt_next;
 			/*
 			 * Data toggle has to be adjusted since the qTD transfer
@@ -528,11 +527,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
 		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
+		*tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
 		tdp = &qtd[qtd_counter++].qt_next;
 	}
 
-	ctrl->qh_list.qh_link = cpu_to_hc32((unsigned long)qh | QH_LINK_TYPE_QH);
+	ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(qh) | QH_LINK_TYPE_QH);
 
 	/* Flush dcache */
 	flush_dcache_range((unsigned long)&ctrl->qh_list,
@@ -542,7 +541,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 			   ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
 
 	/* Set async. queue head pointer. */
-	ehci_writel(&ctrl->hcor->or_asynclistaddr, (unsigned long)&ctrl->qh_list);
+	ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(&ctrl->qh_list));
 
 	usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
 	ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
@@ -989,7 +988,7 @@ static int ehci_common_init(struct ehci_ctrl *ctrl, uint tweaks)
 
 	/* Set head of reclaim list */
 	memset(qh_list, 0, sizeof(*qh_list));
-	qh_list->qh_link = cpu_to_hc32((unsigned long)qh_list | QH_LINK_TYPE_QH);
+	qh_list->qh_link = cpu_to_hc32(virt_to_phys(qh_list) | QH_LINK_TYPE_QH);
 	qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
 						QH_ENDPT1_EPS(USB_SPEED_HIGH));
 	qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -1001,7 +1000,7 @@ static int ehci_common_init(struct ehci_ctrl *ctrl, uint tweaks)
 			   ALIGN_END_ADDR(struct QH, qh_list, 1));
 
 	/* Set async. queue head pointer. */
-	ehci_writel(&ctrl->hcor->or_asynclistaddr, (unsigned long)qh_list);
+	ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(qh_list));
 
 	/*
 	 * Set up periodic list
Signature · 1 line
2.1.4
#5 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

Quoted 5 lines · Marek Vasut

Certain processor architectures, like MIPS, require that the USB structures and transfer buffers are passed with their PA to the USB controller. If VA is passed, the USB will not work. Add the necessary virt_to_phys() calls into the USB EHCI code to make it work.

FYI, this causes some cast size warnings, e.g.:

Quoted 17 lines
(quoted diff) +2 -0
+make O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180 -s p2371-2180_defconfig
+make O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180 -s -j8

In file included from ../arch/arm/include/asm/byteorder.h:29:0,

                 from ../include/compiler.h:125,
                 from ../include/image.h:19,
                 from ../include/common.h:88,
                 from ../drivers/usb/host/ehci-hcd.c:10:
../drivers/usb/host/ehci-hcd.c: In function ?ehci_td_buffer?:
../drivers/usb/host/ehci-hcd.c:248:49: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                                                 ^
../include/linux/byteorder/little_endian.h:34:51: note: in definition of macro ?__cpu_to_le32?
 #define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
                                                   ^
../drivers/usb/host/ehci-hcd.c:248:24: note: in expansion of macro ?cpu_to_hc32?
   td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                        ^

(This is a 64-bit ARM platform, so I had CROSS_COMPILE=aarch64-linux-gnu-)

#6 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

Quoted 27 lines · Stephen Warren
Quoted 5 lines · Marek Vasut

Certain processor architectures, like MIPS, require that the USB structures and transfer buffers are passed with their PA to the USB controller. If VA is passed, the USB will not work. Add the necessary virt_to_phys() calls into the USB EHCI code to make it work.

FYI, this causes some cast size warnings, e.g.:

Quoted 18 lines

+make O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180

(quoted diff) +1 -1
-s p2371-2180_defconfig
+make

O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180 -s -j8
In file included from ../arch/arm/include/asm/byteorder.h:29:0,

                 from ../include/compiler.h:125,
                 from ../include/image.h:19,
                 from ../include/common.h:88,
                 from ../drivers/usb/host/ehci-hcd.c:10:
../drivers/usb/host/ehci-hcd.c: In function ?ehci_td_buffer?:
../drivers/usb/host/ehci-hcd.c:248:49: warning: cast to pointer from
integer of different size [-Wint-to-pointer-cast]
   td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                                                 ^

../include/linux/byteorder/little_endian.h:34:51: note: in definition of macro ?__cpu_to_le32?

Quoted 8 lines
Quoted 6 lines
 #define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
                                                   ^
../drivers/usb/host/ehci-hcd.c:248:24: note: in expansion of macro
?cpu_to_hc32?
   td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                        ^

(This is a 64-bit ARM platform, so I had CROSS_COMPILE=aarch64-linux-gnu-)

Tom reported this to me too, sorry :-(

Do you have an idea how to fix this too? I am now installing arm64 toolchain.

Do you know about some nice arm64 board with USB for testing?

#7 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

Quoted 37 lines · Marek Vasut
Quoted 27 lines · Stephen Warren
Quoted 5 lines · Marek Vasut

Certain processor architectures, like MIPS, require that the USB structures and transfer buffers are passed with their PA to the USB controller. If VA is passed, the USB will not work. Add the necessary virt_to_phys() calls into the USB EHCI code to make it work.

FYI, this causes some cast size warnings, e.g.:

Quoted 18 lines

+make O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180

(quoted diff) +1 -1
-s p2371-2180_defconfig
+make

O=/home/swarren/shared/git_wa/tegra-uboot-flasher/u-boot/build-p2371-2180 -s -j8
In file included from ../arch/arm/include/asm/byteorder.h:29:0,

                  from ../include/compiler.h:125,
                  from ../include/image.h:19,
                  from ../include/common.h:88,
                  from ../drivers/usb/host/ehci-hcd.c:10:
../drivers/usb/host/ehci-hcd.c: In function ?ehci_td_buffer?:
../drivers/usb/host/ehci-hcd.c:248:49: warning: cast to pointer from
integer of different size [-Wint-to-pointer-cast]
    td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                                                  ^

../include/linux/byteorder/little_endian.h:34:51: note: in definition of macro ?__cpu_to_le32?

Quoted 8 lines
Quoted 6 lines
  #define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
                                                    ^
../drivers/usb/host/ehci-hcd.c:248:24: note: in expansion of macro
?cpu_to_hc32?
    td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
                         ^

(This is a 64-bit ARM platform, so I had CROSS_COMPILE=aarch64-linux-gnu-)

Quoted 4 lines

Tom reported this to me too, sorry :-(

Do you have an idea how to fix this too? I am now installing arm64 toolchain.

I haven't looked at it yet. I've seen similar problems in the bast handled by casting between integer types before casting to pointers e.g. something like the following guess:

uint32_t pa;
void *p = (void *)(uintptr_t)pa;

Quoted 1 line

Do you know about some nice arm64 board with USB for testing?

There's always the Jetson TX1; it is the p2371-2180 that I was building above:

http://www.nvidia.com/object/jetson-tx1-dev-kit.html

#8 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

On 02/26/2016 07:16 PM, Stephen Warren wrote:

Hi!

[...]

Quoted 10 lines
Quoted 4 lines

Tom reported this to me too, sorry :-(

Do you have an idea how to fix this too? I am now installing arm64
toolchain.

I haven't looked at it yet. I've seen similar problems in the bast handled by casting between integer types before casting to pointers e.g. something like the following guess:

uint32_t pa; void *p = (void *)(uintptr_t)pa;

I just tried this, it should do the trick. Can you give it a spin ?

drivers/usb/host/ehci-hcd.c +1 -1
index 8f259be..0113c6c 100644
@@ -237,7 +237,7 @@ static int ehci_shutdown(struct ehci_ctrl *ctrl)
 static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 {
        uint32_t delta, next;
-       uint32_t addr = (unsigned long)buf;
+       unsigned long addr = (unsigned long)buf;
        int idx;
 
        if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))

I am a bit worried about the u32 values all around the place. If the buffer would be above 4GiB, we might have a problem.

Quoted 6 lines
Quoted 1 line

Do you know about some nice arm64 board with USB for testing?

There's always the Jetson TX1; it is the p2371-2180 that I was building above:

http://www.nvidia.com/object/jetson-tx1-dev-kit.html

If you have one you don't need ... ;-)

Signature · 2 lines
Best regards,
Marek Vasut
#9 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

Quoted 11 lines · Marek Vasut

On 02/26/2016 07:16 PM, Stephen Warren wrote:

Hi!

[...]

Quoted 5 lines
Quoted 4 lines

Tom reported this to me too, sorry :-(

Do you have an idea how to fix this too? I am now installing arm64
toolchain.

Quoted 7 lines
Quoted 5 lines

I haven't looked at it yet. I've seen similar problems in the bast handled by casting between integer types before casting to pointers e.g. something like the following guess:

uint32_t pa; void *p = (void *)(uintptr_t)pa;

I just tried this, it should do the trick. Can you give it a spin ?

That does the trick, thanks.

#10 lore raw

PATCH 3/5 usb: ehci: Implement V2P mapping

Quoted 16 lines · Stephen Warren
Quoted 15 lines · Marek Vasut

On 02/26/2016 07:16 PM, Stephen Warren wrote:

Hi!

[...]

Quoted 9 lines
Quoted 4 lines

Tom reported this to me too, sorry :-(

Do you have an idea how to fix this too? I am now installing arm64
toolchain.

I haven't looked at it yet. I've seen similar problems in the bast handled by casting between integer types before casting to pointers e.g. something like the following guess:

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

uint32_t pa; void *p = (void *)(uintptr_t)pa;

I just tried this, it should do the trick. Can you give it a spin ?

That does the trick, thanks.

Thanks! I'll finish buildman builds (I set it up, finally, yay!) and submit a proper patch.

Signature · 2 lines
Best regards,
Marek Vasut
#11 lore raw

PATCH 4/5 usb: ehci: Clear USBMODE_BE on LE MMIO

In reply to Marek Vasut

If the USB EHCI is configured for little endian MMIO, make sure to clear the USBMODE_BE flag from the USBMODE register.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 drivers/usb/host/ehci-hcd.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/usb/host/ehci-hcd.c +2 -0
index b3eb08d..8f259be 100644
@@ -134,6 +134,8 @@ static void ehci_set_usbmode(struct ehci_ctrl *ctrl)
 	tmp |= USBMODE_CM_HC;
 #if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
 	tmp |= USBMODE_BE;
+#else
+	tmp &= ~USBMODE_BE;
 #endif
 	ehci_writel(reg_ptr, tmp);
 }
Signature · 1 line
2.1.4
#12 lore raw

PATCH 5/5 usb: ehci: Be explicit about the BE IO accessors

In reply to Marek Vasut

Add explicit cpu_to_be32()/be32_to_cpu() conversion to BE EHCI I/O accessors to align them with their LE counterpart. No functional change.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 drivers/usb/host/ehci.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/usb/host/ehci.h +3 -2
index b41c04a..826b3fe 100644
@@ -102,8 +102,9 @@ struct usb_linux_config_descriptor {
 } __attribute__ ((packed));
 
 #if defined CONFIG_EHCI_DESC_BIG_ENDIAN
-#define	ehci_readl(x)		(*((volatile u32 *)(x)))
-#define ehci_writel(a, b)	(*((volatile u32 *)(a)) = ((volatile u32)b))
+#define ehci_readl(x)		cpu_to_be32((*((volatile u32 *)(x))))
+#define ehci_writel(a, b)	(*((volatile u32 *)(a)) = \
+					cpu_to_be32(((volatile u32)b)))
 #else
 #define ehci_readl(x)		cpu_to_le32((*((volatile u32 *)(x))))
 #define ehci_writel(a, b)	(*((volatile u32 *)(a)) = \
Signature · 1 line
2.1.4
#13 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

In reply to Marek Vasut

Am 27.01.2016 um 03:13 schrieb Marek Vasut:

Quoted 25 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)
arch/mips/lib/cache.c +0 -0
index bf8ff59..7482005 100644

arch/mips/lib/cache.c void flush_dcache_range(ulong start_addr, ulong stop) · line 101

Quoted 7 lines
arch/mips/lib/cache.c +4 -0
@@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop)
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+

you could additionally move the initialization of addr and aend behind this check like it's done in flush_cache()? That would save some CPU cycles.

Quoted 15 lines
arch/mips/lib/cache.c +4 -0
 	while (1) {
 		mips_cache(HIT_WRITEBACK_INV_D, addr);
 		if (addr == aend)
@@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+
 	while (1) {
 		mips_cache(HIT_INVALIDATE_D, addr);
 		if (addr == aend)
#14 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

Quoted 32 lines · Daniel Schwierzeck

Am 27.01.2016 um 03:13 schrieb Marek Vasut:

Quoted 31 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>

---

 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)
arch/mips/lib/cache.c +0 -0
index bf8ff59..7482005 100644
@@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop)
 
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
Quoted 8 lines

arch/mips/lib/cache.c void flush_dcache_range(ulong start_addr, ulong stop) · line 101

Quoted 4 lines
arch/mips/lib/cache.c +4 -0
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+

you could additionally move the initialization of addr and aend behind this check like it's done in flush_cache()? That would save some CPU cycles.

The compiler would do the reordering anyway, it's not volatile so it's placement would not save any cycles.

Quoted 16 lines
Quoted 16 lines
arch/mips/lib/cache.c +0 -0
 	while (1) {
 
arch/mips/lib/cache.c +4 -0
 		mips_cache(HIT_WRITEBACK_INV_D, addr);
 		if (addr == aend)
@@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong
 stop)
 
 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
 
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (start_addr == stop)
+		return;
+
 
Quoted 4 lines

arch/mips/lib/cache.c void invalidate_dcache_range(ulong start_addr, ulong stop) · line 122

Quoted 4 lines
arch/mips/lib/cache.c +0 -0
 	while (1) {
 
 		mips_cache(HIT_INVALIDATE_D, addr);
 		if (addr == aend)

Best regards,
Marek Vasut

#15 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

In reply to Marek Vasut

2016-01-27 3:13 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 13 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Quoted 7 lines
Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>
---
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)

applied to u-boot-mips, thanks

Signature · 1 line
- Daniel
#16 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

Quoted 20 lines · Daniel Schwierzeck

2016-01-27 3:13 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 19 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>

---

Quoted 4 lines
Quoted 2 lines
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)

applied to u-boot-mips, thanks

Thanks! I'll pick the remaining four, ok ?

Best regards,
Marek Vasut

#17 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

2016-02-01 22:31 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 21 lines · Daniel Schwierzeck
Quoted 20 lines

2016-01-27 3:13 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 19 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>

---

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)

applied to u-boot-mips, thanks

Thanks! I'll pick the remaining four, ok ?

fine with me. I don't want to break USB ;)

Signature · 1 line
- Daniel
#18 lore raw

PATCH 1/5 mips: cache: Bulletproof the code against cornercases

Quoted 23 lines · Daniel Schwierzeck

2016-02-01 22:31 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 22 lines · Daniel Schwierzeck
Quoted 21 lines

2016-01-27 3:13 GMT+01:00 Marek Vasut <[email protected]>:

Quoted 20 lines

This patch makes sure that the flush/invalidate_dcache_range() functions can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0); This call is valid and is happily produced by USB EHCI code for example. The expected behavior of the cache function(s) in this case is that they will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will result in a hard CPU hang. This is because under such conditions, where the start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop will then try to iterate over the entire address space, which in itself is wrong. But iterating over the entire address space might also hit some odd address which will cause bus hang. The later happens on the Atheros MIPS.

Cc Daniel Schwierzeck <[email protected]>
Cc Hans de Goede <[email protected]>

---

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
 arch/mips/lib/cache.c | 8 ++++++++
 1 file changed, 8 insertions(+)

applied to u-boot-mips, thanks

Thanks! I'll pick the remaining four, ok ?

fine with me. I don't want to break USB ;)

;-)

Best regards,
Marek Vasut