[3.8.y.z extended stable] Patch "mtd: map: fixed bug in 64-bit systems" has been added to staging queue
Kamal Mostafa
kamal at canonical.com
Fri Dec 6 23:08:23 UTC 2013
This is a note to let you know that I have just added a patch titled
mtd: map: fixed bug in 64-bit systems
to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree
which can be found at:
http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue
This patch is scheduled to be released in version 3.8.13.14.
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Kamal
------
>From e35c5f4401577705a5c8b76d84e45a9ac742f67e Mon Sep 17 00:00:00 2001
From: Wang Haitao <wang.haitao1 at zte.com.cn>
Date: Thu, 22 Aug 2013 19:32:38 +0800
Subject: mtd: map: fixed bug in 64-bit systems
commit a4d62babf988fe5dfde24437fa135ef147bc7aa0 upstream.
Hardware:
CPU: XLP832,the 64-bit OS
NOR Flash:S29GL128S 128M
Software:
Kernel:2.6.32.41
Filesystem:JFFS2
When writing files, errors appear:
Write len 182 but return retlen 180
Write of 182 bytes at 0x072c815c failed. returned -5, retlen 180
Write len 186 but return retlen 184
Write of 186 bytes at 0x072caff4 failed. returned -5, retlen 184
These errors exist only in 64-bit systems,not in 32-bit systems. After analysis, we
found that the left shift operation is wrong in map_word_load_partial. For instance:
unsigned char buf[3] ={0x9e,0x3a,0xea};
map_bankwidth(map) is 4;
for (i=0; i < 3; i++) {
int bitpos;
bitpos = (map_bankwidth(map)-1-i)*8;
orig.x[0] &= ~(0xff << bitpos);
orig.x[0] |= buf[i] << bitpos;
}
The value of orig.x[0] is expected to be 0x9e3aeaff, but in this situation(64-bit
System) we'll get the wrong value of 0xffffffff9e3aeaff due to the 64-bit sign
extension:
buf[i] is defined as "unsigned char" and the left-shift operation will convert it
to the type of "signed int", so when left-shift buf[i] by 24 bits, the final result
will get the wrong value: 0xffffffff9e3aeaff.
If the left-shift bits are less than 24, then sign extension will not occur. Whereas
the bankwidth of the nor flash we used is 4, therefore this BUG emerges.
Signed-off-by: Pang Xunlei <pang.xunlei at zte.com.cn>
Signed-off-by: Zhang Yi <zhang.yi20 at zte.com.cn>
Signed-off-by: Lu Zhongjun <lu.zhongjun at zte.com.cn>
Signed-off-by: Brian Norris <computersforpeace at gmail.com>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
include/linux/mtd/map.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index f6eb433..d4f5f16 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -362,7 +362,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig
bitpos = (map_bankwidth(map)-1-i)*8;
#endif
orig.x[0] &= ~(0xff << bitpos);
- orig.x[0] |= buf[i-start] << bitpos;
+ orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
}
}
return orig;
@@ -381,7 +381,7 @@ static inline map_word map_word_ff(struct map_info *map)
if (map_bankwidth(map) < MAP_FF_LIMIT) {
int bw = 8 * map_bankwidth(map);
- r.x[0] = (1 << bw) - 1;
+ r.x[0] = (1UL << bw) - 1;
} else {
for (i=0; i<map_words(map); i++)
r.x[i] = ~0UL;
--
1.8.3.2
More information about the kernel-team
mailing list