
Hi all
Sorry in advance for cross-posting but this is a problem that affects both the boot loader and the kernel.
In my 8xx board we use u-boot in order to boot linux.
My troubles began when for dpram conflict reasons we moved from using a console on an SMC to a max3100 SPI/UART converter chip.
I was still using the SMC console in u-boot, but when tried to use this chip as a driver for the boot console and removing the CPM console, strange panics appeared in the ethernet driver.
After some interesting debugging sessions the problem was discovered to be this:
The u-boot loader upon finishing the decompression of the kernel image it just jumps into the kernel without resetting the CP. The kernel however resets the CP only when configured to apply a u-patch. The UART in the CP is still active however, and the descriptors in dpram end up overlapping.
The attached patch fixes the common problem by performing the CP reset every time.
This is only a bandaid however, because under network load at the time of booting, i.e. broadcast packets or rebooting after a crash and another end sending non TCP packets, we still crash. It is still possible for a packet to be received and placed in memory by DMA before the kernel reaching the point where the ethernet controller is initialized.
[boot jumps into kernel ] [kernel starts executing ] <--- incoming packet write in memory XXX possible corruption XXX
[init ethernet controller]
The proper way to address the problem is for the loader to stop any DMA capable peripherals before executing the kernel.
The fix for my case is a simple reset of the CP, but I believe that this is a problem that should be looked upon by the maintainers.
IMHO it is good practice for the kernel too to issue a reset to it's peripherals as soon as possible in order to minimize the chances of that happening.
Regards
Pantelis
--- commproc-orig.c Tue Jun 17 15:12:27 2003 +++ commproc.c Tue Jun 17 15:13:31 2003 @@ -115,7 +115,6 @@ imp = (immap_t *)IMAP_ADDR; commproc = (cpm8xx_t *)&imp->im_cpm;
-#ifdef CONFIG_UCODE_PATCH /* Perform a reset. */ commproc->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG); @@ -124,6 +123,7 @@ */ while (commproc->cp_cpcr & CPM_CR_FLG);
+#ifdef CONFIG_UCODE_PATCH cpm_load_patch(imp); #endif