Skip to content

Commit

Permalink
mtd: mxc_nand: fix truncate of unaligned oob copying
Browse files Browse the repository at this point in the history
Copy to/from oob io area might not be aligned to 4 bytes. When 8 bit ECC is
used, the buffer size is 26. Add memcpy16_{to,from}io, and use them to avoid
truncating the buffer. Prefer memcpy32_{to,from}io when the buffer is properly
aligned for better performance.

Reviewed-by: Sascha Hauer <[email protected]>
Acked-by: Uwe Kleine-König <[email protected]>
Signed-off-by: Baruch Siach <[email protected]>
Signed-off-by: Brian Norris <[email protected]>
  • Loading branch information
baruchsiach authored and computersforpeace committed May 20, 2015
1 parent 7e7e473 commit 0d17fc3
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions drivers/mtd/nand/mxc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,44 @@ static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
*t++ = __raw_readl(s++);
}

static void memcpy16_fromio(void *trg, const void __iomem *src, size_t size)
{
int i;
u16 *t = trg;
const __iomem u16 *s = src;

/* We assume that src (IO) is always 32bit aligned */
if (PTR_ALIGN(trg, 4) == trg && IS_ALIGNED(size, 4)) {
memcpy32_fromio(trg, src, size);
return;
}

for (i = 0; i < (size >> 1); i++)
*t++ = __raw_readw(s++);
}

static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
{
/* __iowrite32_copy use 32bit size values so divide by 4 */
__iowrite32_copy(trg, src, size / 4);
}

static void memcpy16_toio(void __iomem *trg, const void *src, int size)
{
int i;
__iomem u16 *t = trg;
const u16 *s = src;

/* We assume that trg (IO) is always 32bit aligned */
if (PTR_ALIGN(src, 4) == src && IS_ALIGNED(size, 4)) {
memcpy32_toio(trg, src, size);
return;
}

for (i = 0; i < (size >> 1); i++)
__raw_writew(*s++, t++);
}

static int check_int_v3(struct mxc_nand_host *host)
{
uint32_t tmp;
Expand Down Expand Up @@ -832,22 +864,22 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)

if (bfrom) {
for (i = 0; i < num_chunks - 1; i++)
memcpy32_fromio(d + i * oob_chunk_size,
memcpy16_fromio(d + i * oob_chunk_size,
s + i * sparebuf_size,
oob_chunk_size);

/* the last chunk */
memcpy32_fromio(d + i * oob_chunk_size,
memcpy16_fromio(d + i * oob_chunk_size,
s + i * sparebuf_size,
host->used_oobsize - i * oob_chunk_size);
} else {
for (i = 0; i < num_chunks - 1; i++)
memcpy32_toio(&s[i * sparebuf_size],
memcpy16_toio(&s[i * sparebuf_size],
&d[i * oob_chunk_size],
oob_chunk_size);

/* the last chunk */
memcpy32_toio(&s[oob_chunk_size * sparebuf_size],
memcpy16_toio(&s[oob_chunk_size * sparebuf_size],
&d[i * oob_chunk_size],
host->used_oobsize - i * oob_chunk_size);
}
Expand Down

0 comments on commit 0d17fc3

Please sign in to comment.