mips: cache: Bulletproof the code against cornercases
Subsystems (3)
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.
--- arch/mips/lib/cache.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/mips/lib/cache.c +8 -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 ; +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
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.
--- drivers/usb/host/ehci-generic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/host/ehci-generic.c +3 -1
@@ -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
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.Signed-off-by Marek Vasut <[email protected]>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
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.Signed-off-by Marek Vasut <[email protected]>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: Usemap_physmemin 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: Usemap_physmemin 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
PATCH 3/5 usb: ehci: Implement V2P mapping
In reply to Marek VasutCertain 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.
--- drivers/usb/host/ehci-hcd.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/usb/host/ehci-hcd.c +9 -10
@@ -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
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 -j8In 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-)
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 +makeO=/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?
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 +makeO=/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:
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_tpa; 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
@@ -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:
If you have one you don't need ... ;-)
Signature · 2 lines
Best regards, Marek Vasut
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_tpa; 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.
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_tpa; 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
PATCH 4/5 usb: ehci: Clear USBMODE_BE on LE MMIO
In reply to Marek VasutIf the USB EHCI is configured for little endian MMIO, make sure to clear the USBMODE_BE flag from the USBMODE register.
--- drivers/usb/host/ehci-hcd.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/host/ehci-hcd.c +2 -0
@@ -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
PATCH 5/5 usb: ehci: Be explicit about the BE IO accessors
In reply to Marek VasutAdd explicit cpu_to_be32()/be32_to_cpu() conversion to BE EHCI I/O accessors to align them with their LE counterpart. No functional change.
--- drivers/usb/host/ehci.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/usb/host/ehci.h +3 -2
@@ -102,8 +102,9 @@ struct usb_linux_config_descriptor { } __attribute__ ((packed));#if definedCONFIG_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
PATCH 1/5 mips: cache: Bulletproof the code against cornercases
In reply to Marek VasutAm 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.Signed-off-by Marek Vasut <[email protected]>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
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
-0while (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)
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.Signed-off-by Marek Vasut <[email protected]>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@@ -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
-0while (1 ) {arch/mips/lib/cache.c +4
-0mips_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
-0while (1 ) {mips_cache (HIT_INVALIDATE_D , addr);if (addr == aend)
Best regards,
Marek Vasut
PATCH 1/5 mips: cache: Bulletproof the code against cornercases
In reply to Marek Vasut2016-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
Signed-off-by Marek Vasut <[email protected]>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
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.Signed-off-by Marek Vasut <[email protected]>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
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.Signed-off-by Marek Vasut <[email protected]>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
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.Signed-off-by Marek Vasut <[email protected]>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