cfi_cmdset_0001 unaligned write problems.
David Woodhouse
dwmw2 at infradead.org
Thu Oct 19 10:05:32 EDT 2000
Either this code is suspect or I need more caffeine. Probably both.
Scenario: Buswidth is 2. CPU is big-endian. Writing '5a' to an odd address.
/* If it's not bus-aligned, do the first byte write */
if (ofs & (CFIDEV_BUSWIDTH-1)) {
unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
int i = 0, n = 0;
u_char tmp_buf[4];
__u32 datum;
while (bus_ofs++ < ofs)
tmp_buf[i++] = 0xff;
while (len && i < CFIDEV_BUSWIDTH)
tmp_buf[i++] = buf[n++], len--;
while (i < CFIDEV_BUSWIDTH)
tmp_buf[i++] = 0xff;
// now tmp_buf is 0xff,0x5a,xx,yy
if (cfi_buswidth_is_2()) {
datum = *(__u16*)tmp_buf;
// now datum is 0xff5a (stored as 0,0,ff,5a)
} else if (cfi_buswidth_is_4()) {
datum = *(__u32*)tmp_buf;
} else {
return -EINVAL; /* should never happen, but be safe */
}
ret = do_write_oneword(map, &cfi->chips[chipnum],
ofs, datum);
// do_write_oneword writes 2 bytes at &datum, which is 0,0.
// What's more, it writes it to 'ofs' (and faults on the unaligned access)
// instead of to buf_ofs, which was presumably the intention.
if (ret)
return ret;
ofs += n;
buf += n;
(*retlen) += n;
if (ofs >> cfi->chipshift) {
chipnum ++;
ofs = 0;
if (chipnum == cfi->numchips)
return 0;
}
}
--
dwmw2
To unsubscribe, send "unsubscribe mtd" to majordomo at infradead.org
More information about the linux-mtd
mailing list