From: Paul Mackerras <hidden> Date: 2009-08-17 23:01:34
On 32-bit systems with 64-bit PTEs, the PTEs have to be written in two
32-bit halves. On SMP we write the higher-order half and then the
lower-order half, with a write barrier between the two halves, but on
UP there was no particular ordering of the writes to the two halves.
This extends the ordering that we already do on SMP to the UP case as
well. The reason is that with the perf_counter subsystem potentially
accessing user memory at interrupt time to get stack traces, we have
to be careful not to create an incorrect but apparently valid PTE even
on UP.
Signed-off-by: Paul Mackerras <redacted>
---
arch/powerpc/include/asm/pgtable.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
@@ -104,8 +104,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,elsepte_update(ptep,~_PAGE_HASHPTE,pte_val(pte));-#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)-/* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we+#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)+/* Second case is 32-bit with 64-bit PTE. In this case, we*canjuststoreaslongaswedothetwohalvesintherightorder*withabarrierinbetween.Thisispossiblebecausewetakecare,*inthehashcode,topre-invalidateifthePTEwasalreadyhashed,
@@ -140,7 +140,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,#else/* Anything else just stores the PTE normally. That covers all 64-bit-*cases,and32-bitnon-hashwith64-bitPTEsinUPmode+*cases,and32-bitnon-hashwith32-bitPTEs.*/*ptep=pte;#endif
From: Paul Mackerras <hidden> Date: 2009-08-17 23:01:34
This provides a mechanism to allow the perf_counters code to access
user memory in a PMU interrupt routine. Such an access can cause
various kinds of interrupt: SLB miss, MMU hash table miss, segment
table miss, or TLB miss, depending on the processor. This commit
only deals with 64-bit classic/server processors, which use an MMU
hash table. 32-bit processors are already able to access user memory
at interrupt time. Since we don't soft-disable on 32-bit, we avoid
the possibility of reentering hash_page or the TLB miss handlers,
since they run with interrupts disabled.
On 64-bit processors, an SLB miss interrupt on a user address will
update the slb_cache and slb_cache_ptr fields in the paca. This is
OK except in the case where a PMU interrupt occurs in switch_slb,
which also accesses those fields. To prevent this, we hard-disable
interrupts in switch_slb. Interrupts are already soft-disabled at
this point, and will get hard-enabled when they get soft-enabled
later.
This also reworks slb_flush_and_rebolt: to avoid hard-disabling twice,
and to make sure that it clears the slb_cache_ptr when called from
other callers than switch_slb, the existing routine is renamed to
__slb_flush_and_rebolt, which is called by switch_slb and the new
version of slb_flush_and_rebolt.
Similarly, switch_stab (used on POWER3 and RS64 processors) gets a
hard_irq_disable() to protect the per-cpu variables used there and
in ste_allocate.
If a MMU hashtable miss interrupt occurs, normally we would call
hash_page to look up the Linux PTE for the address and create a HPTE.
However, hash_page is fairly complex and takes some locks, so to
avoid the possibility of deadlock, we check the preemption count
to see if we are in a (pseudo-)NMI handler, and if so, we don't call
hash_page but instead treat it like a bad access that will get
reported up through the exception table mechanism. An interrupt
whose handler runs even though the interrupt occurred when
soft-disabled (such as the PMU interrupt) is considered a pseudo-NMI
handler, which should use nmi_enter()/nmi_exit() rather than
irq_enter()/irq_exit().
Signed-off-by: Paul Mackerras <redacted>
---
arch/powerpc/kernel/asm-offsets.c | 2 +
arch/powerpc/kernel/exceptions-64s.S | 19 +++++++++++++++++
arch/powerpc/mm/slb.c | 37 +++++++++++++++++++++++----------
arch/powerpc/mm/stab.c | 11 +++++++++-
4 files changed, 57 insertions(+), 12 deletions(-)
@@ -729,6 +729,11 @@ BEGIN_FTR_SECTIONbne-do_ste_alloc/*Ifsohandleit*/END_FTR_SECTION_IFCLR(CPU_FTR_SLB)+clrrdir11,r1,THREAD_SHIFT+lwzr0,TI_PREEMPT(r11)/*Ifwe're in an "NMI" */+andis.r0,r0,NMI_MASK@h/*(i.e.anirqwhensoft-disabled)*/+bne77f/*thendon't call hash_page now */+/**OniSeries,wesoft-disableinterruptshere,then*hard-enableinterruptssothatthehash_pagecodecanspinon
@@ -833,6 +838,20 @@ handle_page_fault:bl.low_hash_faultb.ret_from_except+/*+*WecomehereasaresultofaDSIatapointwherewedon't want+*tocallhash_page,suchaswhenweareaccessingmemory (possibly+*usermemory)insideaPMUinterruptthatoccurredwhileinterrupts+*weresoft-disabled.Wewanttoinvoketheexceptionhandlerfor+*theaccess,orpanicifthereisn't a handler.+*/+77:bl.save_nvgprs+mrr4,r3+addir3,r1,STACK_FRAME_OVERHEAD+lir5,SIGSEGV+bl.bad_page_fault+b.ret_from_except+/*herewehaveasegmentmiss*/do_ste_alloc:bl.ste_allocate/*trytoinsertstabentry*/
@@ -92,15 +92,13 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize,:"memory");}-voidslb_flush_and_rebolt(void)+staticvoid__slb_flush_and_rebolt(void){/* If you change this make sure you change SLB_NUM_BOLTED*appropriatelytoo.*/unsignedlonglinear_llp,vmalloc_llp,lflags,vflags;unsignedlongksp_esid_data,ksp_vsid_data;-WARN_ON(!irqs_disabled());-linear_llp=mmu_psize_defs[mmu_linear_psize].sllp;vmalloc_llp=mmu_psize_defs[mmu_vmalloc_psize].sllp;lflags=SLB_VSID_KERNEL|linear_llp;
@@ -117,12 +115,6 @@ void slb_flush_and_rebolt(void)ksp_vsid_data=get_slb_shadow()->save_area[2].vsid;}-/*-*Wecan'ttakeaPMUexceptioninthefollowingcode,sohard-*disableinterrupts.-*/-hard_irq_disable();-/* We need to do this all in asm, so we're sure we don't touch*thestackbetweentheslbiaandreboltingit.*/asmvolatile("isync\n"
@@ -180,12 +187,20 @@ static inline int esids_match(unsigned long addr1, unsigned long addr2)/* Flush all user entries from the segment table of the current processor. */voidswitch_slb(structtask_struct*tsk,structmm_struct*mm){-unsignedlongoffset=get_paca()->slb_cache_ptr;+unsignedlongoffset;unsignedlongslbie_data=0;unsignedlongpc=KSTK_EIP(tsk);unsignedlongstack=KSTK_ESP(tsk);unsignedlongunmapped_base;+/*+*Weneedinterruptshard-disabledhere,notjustsoft-disabled,+*sothataPMUinterruptcan'toccur,whichmighttrytoaccess+*usermemory(togetastacktrace)andpossiblecauseanSLBmiss+*whichwouldupdatetheslb_cache/slb_cache_ptrfieldsinthePACA.+*/+hard_irq_disable();+offset=get_paca()->slb_cache_ptr;if(!cpu_has_feature(CPU_FTR_NO_SLBIE_B)&&offset<=SLB_CACHE_ENTRIES){inti;
From: Paul Mackerras <hidden> Date: 2009-08-17 23:01:34
This adds support for tracing callchains for powerpc, both 32-bit
and 64-bit, and both in the kernel and userspace, from PMU interrupt
context.
The first three entries stored for each callchain are the NIP (next
instruction pointer), LR (link register), and the contents of the LR
save area in the second stack frame (the first is ignored because the
ABI convention on powerpc is that functions save their return address
in their caller's stack frame). Because leaf functions don't have to
save their return address (LR value) and don't have to establish a
stack frame, it's possible for either or both of LR and the second
stack frame's LR save area to have valid return addresses in them.
This is basically impossible to disambiguate without either reading
the code or looking at auxiliary information such as CFI tables.
Since we don't want to do either of those things at interrupt time,
we store both LR and the second stack frame's LR save area.
Once we get past the second stack frame, there is no ambiguity; all
return addresses we get are reliable.
For kernel traces, we check whether they are valid kernel instruction
addresses and store zero instead if they are not (rather than
omitting them, which would make it impossible for userspace to know
which was which). We also store zero instead of the second stack
frame's LR save area value if it is the same as LR.
For kernel traces, we check for interrupt frames, and for user traces,
we check for signal frames. In each case, since we're starting a new
trace, we store a PERF_CONTEXT_KERNEL/USER marker so that userspace
knows that the next three entries are NIP, LR and the second stack fram=
e
for the interrupted context.
We read user memory with __get_user_inatomic. On 64-bit, if this
PMU interrupt occurred while interrupts are soft-disabled, and
there is no MMU hash table entry for the page, we will get an
-EFAULT return from __get_user_inatomic even if there is a valid
Linux PTE for the page, since hash_page isn't reentrant. Thus we
have code here to read the Linux PTE and access the page via the
kernel linear mapping. Since 64-bit doesn't use (or need) highmem
there is no need to do kmap_atomic. On 32-bit, we don't do soft
interrupt disabling, so this complication doesn't occur and there
is no need to fall back to reading the Linux PTE, since hash_page
(or the TLB miss handler) will get called automatically if necessary.
Note that we cannot get PMU interrupts in the interval during
context switch between switch_mm (which switches the user address
space) and switch_to (which actually changes current to the new
process). On 64-bit this is because interrupts are hard-disabled
in switch_mm and stay hard-disabled until they are soft-enabled
later, after switch_to has returned. So there is no possibility
of trying to do a user stack trace when the user address space is
not current's address space.
Signed-off-by: Paul Mackerras <redacted>
---
arch/powerpc/kernel/Makefile | 2 +-
arch/powerpc/kernel/perf_callchain.c | 527 ++++++++++++++++++++++++++=
++++++++
2 files changed, 528 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/kernel/perf_callchain.c
From: Kumar Gala <hidden> Date: 2009-08-18 00:00:28
On Aug 17, 2009, at 6:00 PM, Paul Mackerras wrote:
On 32-bit systems with 64-bit PTEs, the PTEs have to be written in two
32-bit halves. On SMP we write the higher-order half and then the
lower-order half, with a write barrier between the two halves, but on
UP there was no particular ordering of the writes to the two halves.
This extends the ordering that we already do on SMP to the UP case as
well. The reason is that with the perf_counter subsystem potentially
accessing user memory at interrupt time to get stack traces, we have
to be careful not to create an incorrect but apparently valid PTE even
on UP.
Signed-off-by: Paul Mackerras <redacted>
---
arch/powerpc/include/asm/pgtable.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
Just out of interest did you end up hitting this in testing?
- k
From: Paul Mackerras <hidden> Date: 2009-08-18 00:14:19
Kumar Gala writes:
On Aug 17, 2009, at 6:00 PM, Paul Mackerras wrote:
quoted
On 32-bit systems with 64-bit PTEs, the PTEs have to be written in two
32-bit halves. On SMP we write the higher-order half and then the
lower-order half, with a write barrier between the two halves, but on
UP there was no particular ordering of the writes to the two halves.
This extends the ordering that we already do on SMP to the UP case as
well. The reason is that with the perf_counter subsystem potentially
accessing user memory at interrupt time to get stack traces, we have
to be careful not to create an incorrect but apparently valid PTE even
on UP.
Signed-off-by: Paul Mackerras <redacted>
---
arch/powerpc/include/asm/pgtable.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
Just out of interest did you end up hitting this in testing?
No. Ben told me he wanted this change, so I did what I was told. :)
Paul.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2009-08-18 04:24:49
On Tue, 2009-08-18 at 09:00 +1000, Paul Mackerras wrote:
This provides a mechanism to allow the perf_counters code to access
user memory in a PMU interrupt routine. Such an access can cause
various kinds of interrupt: SLB miss, MMU hash table miss, segment
table miss, or TLB miss, depending on the processor. This commit
only deals with 64-bit classic/server processors, which use an MMU
hash table. 32-bit processors are already able to access user memory
at interrupt time. Since we don't soft-disable on 32-bit, we avoid
the possibility of reentering hash_page or the TLB miss handlers,
since they run with interrupts disabled.
.../...
Signed-off-by: Paul Mackerras <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2009-08-18 04:24:49
On Tue, 2009-08-18 at 09:00 +1000, Paul Mackerras wrote:
On 32-bit systems with 64-bit PTEs, the PTEs have to be written in two
32-bit halves. On SMP we write the higher-order half and then the
lower-order half, with a write barrier between the two halves, but on
UP there was no particular ordering of the writes to the two halves.
This extends the ordering that we already do on SMP to the UP case as
well. The reason is that with the perf_counter subsystem potentially
accessing user memory at interrupt time to get stack traces, we have
to be careful not to create an incorrect but apparently valid PTE even
on UP.
Signed-off-by: Paul Mackerras <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
@@ -104,8 +104,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,elsepte_update(ptep,~_PAGE_HASHPTE,pte_val(pte));-#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)-/* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we+#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)+/* Second case is 32-bit with 64-bit PTE. In this case, we*canjuststoreaslongaswedothetwohalvesintherightorder*withabarrierinbetween.Thisispossiblebecausewetakecare,*inthehashcode,topre-invalidateifthePTEwasalreadyhashed,
@@ -140,7 +140,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,#else/* Anything else just stores the PTE normally. That covers all 64-bit-*cases,and32-bitnon-hashwith64-bitPTEsinUPmode+*cases,and32-bitnon-hashwith32-bitPTEs.*/*ptep=pte;#endif
Hi All:
It seems that the ECC correction is broken on the Linux with the 4xx
NDFC driver.
It uses the SMC order when reading the ECC code. 2-1-3
static int ndfc_calculate_ecc(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
uint32_t ecc;
uint8_t *p = (uint8_t *)&ecc;
wmb();
ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
/* The NDFC uses Smart Media (SMC) bytes order */
ecc_code[0] = p[2];
ecc_code[1] = p[1];
ecc_code[2] = p[3];
return 0;
}
However, when in the correction function, the byte address order is
again reverses
causing incorrect byte location.
* performace it does not make any difference
*/
if (eccsize_mult == 1)
byte_addr = (addressbits[b0] << 4) +
addressbits[b1];
>>>> The above really should be byte_addr = (addressbits[b1] << 4) +
addressbits[b0];
else
byte_addr = (addressbits[b2 & 0x3] << 8) +
(addressbits[b1] << 4) +
addressbits[b0];
bit_addr = addressbits[b2 >> 2];
/* flip the bit */
buf[byte_addr] ^= (1 << bit_addr);
printk(KERN_INFO "Corrected b[0] 0x%x b[1]0x%x\n", b0, b1);
printk(KERN_INFO "cal ecc b[0] 0x%x b[1]0x%x\n",
calc_ecc[0] , calc_ecc[1]);
printk(KERN_INFO "read ecc b[0] 0x%x b[1]0x%x\n",
read_ecc[0] , read_ecc[1]);
return 1;
I see other boards using SMC as well, can someone comment on the change
I am proposing.
Should I change the correction algorithm or the calculate function? If
the later is preferred
it would mean the change must be pushed in both U-Boot and Linux.
Feng Kan
AMCC Software
From: Sean MacLennan <hidden> Date: 2009-08-20 04:38:59
On Wed, 19 Aug 2009 16:16:54 -0700
Feng Kan [off-list ref] wrote:
I see other boards using SMC as well, can someone comment on the
change I am proposing.
Should I change the correction algorithm or the calculate function?
If the later is preferred
it would mean the change must be pushed in both U-Boot and Linux.
Odds are the calculate function is wrong. The correction algo is used
by many nand drivers, I *assume* it is correct. The calculate function
was set to agree with u-boot (1.3.0).
Cheers,
Sean
P.S. Yes, I know the u-boot is an ancient version :(
From: Stefan Roese <sr@denx.de> Date: 2009-08-20 05:01:43
On Thursday 20 August 2009 06:38:51 Sean MacLennan wrote:
quoted
I see other boards using SMC as well, can someone comment on the
change I am proposing.
Should I change the correction algorithm or the calculate function?
If the later is preferred
it would mean the change must be pushed in both U-Boot and Linux.
Odds are the calculate function is wrong. The correction algo is used
by many nand drivers, I *assume* it is correct. The calculate function
was set to agree with u-boot (1.3.0).
Yes, it seems that you changed the order in the calculation function while
reworking the NDFC driver for arch/powerpc. So we should probably change this
order back to the original version. And change it in U-Boot as well.
BTW: I didn't see any problems with ECC so far with the current code. Feng,
how did you spot this problem?
Cheers,
Stefan
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de
From: Sean MacLennan <hidden> Date: 2009-08-20 19:36:51
On Thu, 20 Aug 2009 07:01:21 +0200
Stefan Roese [off-list ref] wrote:
On Thursday 20 August 2009 06:38:51 Sean MacLennan wrote:
quoted
quoted
I see other boards using SMC as well, can someone comment on the
change I am proposing.
Should I change the correction algorithm or the calculate
function? If the later is preferred
it would mean the change must be pushed in both U-Boot and Linux.
Odds are the calculate function is wrong. The correction algo is
used by many nand drivers, I *assume* it is correct. The calculate
function was set to agree with u-boot (1.3.0).
Yes, it seems that you changed the order in the calculation function
while reworking the NDFC driver for arch/powerpc. So we should
probably change this order back to the original version. And change
it in U-Boot as well.
BTW: I didn't see any problems with ECC so far with the current code.
Feng, how did you spot this problem?
Ok, I think I have reproduced the problem programmatically. Basically,
I force a one bit error with the following patch:
Basically I write a one bit error to the NAND, but calculate with the
correct bit. This assumes nand_calculate_ecc is correct.
I then added debugs to the correction to make sure it corrected
properly:
@@ -483,14 +483,20 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,byte_addr=(addressbits[b2&0x3]<<8)+(addressbits[b1]<<4)+addressbits[b0];bit_addr=addressbits[b2>>2];++printk("Single bit error: correct %08x => %08x\n",+buf[byte_addr],buf[byte_addr]^(1<<bit_addr));+/* flip the bit */buf[byte_addr]^=(1<<bit_addr);return1;}/* count nr of bits; use table lookup, faster than calculating it */-if((bitsperbyte[b0]+bitsperbyte[b1]+bitsperbyte[b2])==1)+if((bitsperbyte[b0]+bitsperbyte[b1]+bitsperbyte[b2])==1){+printk("ECC DATA BAD\n");// SAM DBGreturn1;/* error in ecc data; no action needed */+}printk(KERN_ERR"uncorrectable error : ");return-1;
With the current ndfc code, the error correction gets the bits wrong.
Switching it back to the original way and the correction is correct.
@@ -101,9 +101,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,wmb();ecc=in_be32(ndfc->ndfcbase+NDFC_ECC);-/* The NDFC uses Smart Media (SMC) bytes order */-ecc_code[0]=p[2];-ecc_code[1]=p[1];+ecc_code[0]=p[1];+ecc_code[1]=p[2];ecc_code[2]=p[3];return0;
Does anybody see a problem with my method of reproducing the bug? This
bug is deadly for our customers. I don't want to make the change unless
it is absolutely necessary.
Cheers,
Sean
bounces+vgallardo=3Damcc.com@lists.ozlabs.org] On Behalf Of Sean =
MacLennan
Sent: Thursday, August 20, 2009 12:37 PM
To: Stefan Roese
Cc: u-boot@lists.denx.de; Feng Kan; linux-mtd@lists.infradead.org; =
linuxppc-dev@ozlabs.org
Subject: Re: [U-Boot] NAND ECC Error with wrong SMC ording bug
=20
On Thu, 20 Aug 2009 07:01:21 +0200
Stefan Roese [off-list ref] wrote:
=20
quoted
On Thursday 20 August 2009 06:38:51 Sean MacLennan wrote:
quoted
quoted
I see other boards using SMC as well, can someone comment on the
change I am proposing.
Should I change the correction algorithm or the calculate
function? If the later is preferred
it would mean the change must be pushed in both U-Boot and =
Linux.
quoted
quoted
Odds are the calculate function is wrong. The correction algo is
used by many nand drivers, I *assume* it is correct. The calculate
function was set to agree with u-boot (1.3.0).
Yes, it seems that you changed the order in the calculation function
while reworking the NDFC driver for arch/powerpc. So we should
probably change this order back to the original version. And change
it in U-Boot as well.
BTW: I didn't see any problems with ECC so far with the current =
code.
quoted hunk
quoted
Feng, how did you spot this problem?
=20
Ok, I think I have reproduced the problem programmatically. Basically,
I force a one bit error with the following patch:
=20
*chip,
uint8_t *ecc_calc =3D chip->buffers->ecccalc;
const uint8_t *p =3D buf;
uint32_t *eccpos =3D chip->ecc.layout->eccpos;
+ static int count;
=20
for (i =3D 0; eccsteps; eccsteps--, i +=3D eccbytes, p +=3D eccsize) =
{
quoted hunk
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
- chip->write_buf(mtd, p, eccsize);
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+ if (count =3D=3D 0) {
+ count =3D 1;
+ printk("Corrupt one bit: %08x =3D> %08x\n",
+ *p, *p ^ 8);
+ *(uint8_t *)p ^=3D 8;
+ chip->write_buf(mtd, p, eccsize);
+ *(uint8_t *)p ^=3D 8;
+ nand_calculate_ecc(mtd, p, &ecc_calc[i]);
+ } else {
+ chip->write_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+ }
}
=20
for (i =3D 0; i < chip->ecc.total; i++)
=20
Basically I write a one bit error to the NAND, but calculate with the
correct bit. This assumes nand_calculate_ecc is correct.
=20
I then added debugs to the correction to make sure it corrected
properly:
=20
@@ -483,14 +483,20 @@ int nand_correct_data(struct mtd_info *mtd, =
unsigned char *buf,
byte_addr =3D (addressbits[b2 & 0x3] << 8) +
(addressbits[b1] << 4) + addressbits[b0];
bit_addr =3D addressbits[b2 >> 2];
+
+ printk("Single bit error: correct %08x =3D> %08x\n",
+ buf[byte_addr], buf[byte_addr] ^ (1 << bit_addr));
+
/* flip the bit */
buf[byte_addr] ^=3D (1 << bit_addr);
return 1;
=20
}
/* count nr of bits; use table lookup, faster than calculating it */
- if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) =3D=3D 1)
+ if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) =3D=3D 1) =
{
quoted hunk
+ printk("ECC DATA BAD\n"); // SAM DBG
return 1; /* error in ecc data; no action needed */
+ }
=20
printk(KERN_ERR "uncorrectable error : ");
return -1;
=20
With the current ndfc code, the error correction gets the bits wrong.
Switching it back to the original way and the correction is correct.
=20
@@ -101,9 +101,8 @@ static int ndfc_calculate_ecc(struct mtd_info =
*mtd,
=20
wmb();
ecc =3D in_be32(ndfc->ndfcbase + NDFC_ECC);
- /* The NDFC uses Smart Media (SMC) bytes order */
- ecc_code[0] =3D p[2];
- ecc_code[1] =3D p[1];
+ ecc_code[0] =3D p[1];
+ ecc_code[1] =3D p[2];
ecc_code[2] =3D p[3];
=20
return 0;
=20
Does anybody see a problem with my method of reproducing the bug? This
bug is deadly for our customers. I don't want to make the change =
unless
it is absolutely necessary.
=20
Cheers,
Sean
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
Hi Stefan:
We had a board with high number of correctable ECC errors. Which crashed
the jffs when it
was miss correcting the wrong byte location.
Do you want me to submit a patch for this, or do you prefer to do it. I
am submitting a patch
for linux right now.
Feng Kan
AMCC Software
On 08/19/2009 10:01 PM, Stefan Roese wrote:
On Thursday 20 August 2009 06:38:51 Sean MacLennan wrote:
quoted
quoted
I see other boards using SMC as well, can someone comment on the
change I am proposing.
Should I change the correction algorithm or the calculate function?
If the later is preferred
it would mean the change must be pushed in both U-Boot and Linux.
Odds are the calculate function is wrong. The correction algo is used
by many nand drivers, I *assume* it is correct. The calculate function
was set to agree with u-boot (1.3.0).
Yes, it seems that you changed the order in the calculation function while
reworking the NDFC driver for arch/powerpc. So we should probably change this
order back to the original version. And change it in U-Boot as well.
BTW: I didn't see any problems with ECC so far with the current code. Feng,
how did you spot this problem?
Cheers,
Stefan
--
DENX Software Engineering GmbH, MD: Wolfgang Denk& Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de
@@ -101,9 +101,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
=A0 =A0 =A0 =A0wmb();
=A0 =A0 =A0 =A0ecc =3D in_be32(ndfc->ndfcbase + NDFC_ECC);
- =A0 =A0 =A0 /* The NDFC uses Smart Media (SMC) bytes order */
- =A0 =A0 =A0 ecc_code[0] =3D p[2];
- =A0 =A0 =A0 ecc_code[1] =3D p[1];
+ =A0 =A0 =A0 ecc_code[0] =3D p[1];
+ =A0 =A0 =A0 ecc_code[1] =3D p[2];
=A0 =A0 =A0 =A0ecc_code[2] =3D p[3];
=A0 =A0 =A0 =A0return 0;
Does anybody see a problem with my method of reproducing the bug? This
bug is deadly for our customers. I don't want to make the change unless
it is absolutely necessary..
Just one question: did you enabled MTD_NAND_ECC_SMC in configs?
-vimal
@@ -101,9 +101,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,wmb();ecc=in_be32(ndfc->ndfcbase+NDFC_ECC);-/* The NDFC uses Smart Media (SMC) bytes order */-ecc_code[0]=p[2];-ecc_code[1]=p[1];+ecc_code[0]=p[1];+ecc_code[1]=p[2];ecc_code[2]=p[3];return0;
Does anybody see a problem with my method of reproducing the bug? This
bug is deadly for our customers. I don't want to make the change unless
it is absolutely necessary..
Just one question: did you enabled MTD_NAND_ECC_SMC in configs?
Yes, MTD_NAND_ECC_SMC is selected via Kconfig for this driver.
Cheers,
Stefan
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de
From: Victor Gallardo <hidden> Date: 2009-08-21 06:30:48
Hi Vimal,=0A=0A> > With the current ndfc code, the error correction gets th=
e bits wrong.=0A> > Switching it back to the original way and the correctio=
n is correct.=0A> >=0A> > diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mt=
d/nand/ndfc.c=0A> > index 89bf85a..497e175 100644=0A> > --- a/drivers/mtd/n=
and/ndfc.c=0A> > +++ b/drivers/mtd/nand/ndfc.c=0A> > @@ -101,9 +101,8 @@ st=
atic int ndfc_calculate_ecc(struct mtd_info *mtd,=0A> >=0A> > =A0 =A0 =A0 =
=A0wmb();=0A> > =A0 =A0 =A0 =A0ecc =3D in_be32(ndfc->ndfcbase + NDFC_ECC);=
=0A> > - =A0 =A0 =A0 /* The NDFC uses Smart Media (SMC) bytes order */=0A> =
[1];=0A> > + =A0 =A0 =A0 ecc_code[0] =3D p[1];=0A> > + =A0 =A0 =A0 ecc_code=
[1] =3D p[2];=0A> > =A0 =A0 =A0 =A0ecc_code[2] =3D p[3];=0A> >=0A> > =A0 =
=A0 =A0 =A0return 0;=0A> >=0A> > Does anybody see a problem with my method =
of reproducing the bug? This=0A> > bug is deadly for our customers. I don't=
want to make the change unless=0A> > it is absolutely necessary..=0A> =0A>=
Just one question: did you enabled MTD_NAND_ECC_SMC in configs?=0A=0AYes, =
it was set.=0A=0ABest Regards,=0A=0AVictor Gallardo
From: Stefan Roese <sr@denx.de> Date: 2009-08-21 07:59:41
Hi Feng,
On Friday 21 August 2009 01:42:42 Feng Kan wrote:
We had a board with high number of correctable ECC errors. Which crashed
the jffs when it
was miss correcting the wrong byte location.
OK, thanks.
Do you want me to submit a patch for this, or do you prefer to do it.
Sure, please go ahead and send a patch to fix this in U-Boot as well.
Thanks.
Cheers,
Stefan
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de