Commit 36ec9fbf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-20120712' of git://git.infradead.org/linux-mtd

Pull late MTD fixes from David Woodhouse:
 - fix 'sparse warning fix' regression which totally breaks MXC NAND
 - fix GPMI NAND regression when used with UBI
 - update/correct sysfs documentation for new 'bitflip_threshold' field
 - fix nandsim build failure

* tag 'for-linus-20120712' of git://git.infradead.org/linux-mtd:
  mtd: nandsim: don't open code a do_div helper
  mtd: ABI documentation: clarification of bitflip_threshold
  mtd: gpmi-nand: fix read page when reading to vmalloced area
  mtd: mxc_nand: use 32bit copy functions
parents 7801dc33 596fd462
...@@ -142,13 +142,14 @@ KernelVersion: 3.4 ...@@ -142,13 +142,14 @@ KernelVersion: 3.4
Contact: linux-mtd@lists.infradead.org Contact: linux-mtd@lists.infradead.org
Description: Description:
This allows the user to examine and adjust the criteria by which This allows the user to examine and adjust the criteria by which
mtd returns -EUCLEAN from mtd_read(). If the maximum number of mtd returns -EUCLEAN from mtd_read() and mtd_read_oob(). If the
bit errors that were corrected on any single region comprising maximum number of bit errors that were corrected on any single
an ecc step (as reported by the driver) equals or exceeds this region comprising an ecc step (as reported by the driver) equals
value, -EUCLEAN is returned. Otherwise, absent an error, 0 is or exceeds this value, -EUCLEAN is returned. Otherwise, absent
returned. Higher layers (e.g., UBI) use this return code as an an error, 0 is returned. Higher layers (e.g., UBI) use this
indication that an erase block may be degrading and should be return code as an indication that an erase block may be
scrutinized as a candidate for being marked as bad. degrading and should be scrutinized as a candidate for being
marked as bad.
The initial value may be specified by the flash device driver. The initial value may be specified by the flash device driver.
If not, then the default value is ecc_strength. If not, then the default value is ecc_strength.
...@@ -167,7 +168,7 @@ Description: ...@@ -167,7 +168,7 @@ Description:
block degradation, but high enough to avoid the consequences of block degradation, but high enough to avoid the consequences of
a persistent return value of -EUCLEAN on devices where sticky a persistent return value of -EUCLEAN on devices where sticky
bitflips occur. Note that if bitflip_threshold exceeds bitflips occur. Note that if bitflip_threshold exceeds
ecc_strength, -EUCLEAN is never returned by mtd_read(). ecc_strength, -EUCLEAN is never returned by the read operations.
Conversely, if bitflip_threshold is zero, -EUCLEAN is always Conversely, if bitflip_threshold is zero, -EUCLEAN is always
returned, absent a hard error. returned, absent a hard error.
......
...@@ -920,12 +920,12 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -920,12 +920,12 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
*/ */
memset(chip->oob_poi, ~0, mtd->oobsize); memset(chip->oob_poi, ~0, mtd->oobsize);
chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
read_page_swap_end(this, buf, mtd->writesize,
this->payload_virt, this->payload_phys,
nfc_geo->payload_size,
payload_virt, payload_phys);
} }
read_page_swap_end(this, buf, mtd->writesize,
this->payload_virt, this->payload_phys,
nfc_geo->payload_size,
payload_virt, payload_phys);
exit_nfc: exit_nfc:
return ret; return ret;
} }
......
...@@ -273,6 +273,26 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { ...@@ -273,6 +273,26 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = {
static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL };
static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
{
int i;
u32 *t = trg;
const __iomem u32 *s = src;
for (i = 0; i < (size >> 2); i++)
*t++ = __raw_readl(s++);
}
static void memcpy32_toio(void __iomem *trg, const void *src, int size)
{
int i;
u32 __iomem *t = trg;
const u32 *s = src;
for (i = 0; i < (size >> 2); i++)
__raw_writel(*s++, t++);
}
static int check_int_v3(struct mxc_nand_host *host) static int check_int_v3(struct mxc_nand_host *host)
{ {
uint32_t tmp; uint32_t tmp;
...@@ -519,7 +539,7 @@ static void send_read_id_v3(struct mxc_nand_host *host) ...@@ -519,7 +539,7 @@ static void send_read_id_v3(struct mxc_nand_host *host)
wait_op_done(host, true); wait_op_done(host, true);
memcpy_fromio(host->data_buf, host->main_area0, 16); memcpy32_fromio(host->data_buf, host->main_area0, 16);
} }
/* Request the NANDFC to perform a read of the NAND device ID. */ /* Request the NANDFC to perform a read of the NAND device ID. */
...@@ -535,7 +555,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) ...@@ -535,7 +555,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host)
/* Wait for operation to complete */ /* Wait for operation to complete */
wait_op_done(host, true); wait_op_done(host, true);
memcpy_fromio(host->data_buf, host->main_area0, 16); memcpy32_fromio(host->data_buf, host->main_area0, 16);
if (this->options & NAND_BUSWIDTH_16) { if (this->options & NAND_BUSWIDTH_16) {
/* compress the ID info */ /* compress the ID info */
...@@ -797,16 +817,16 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) ...@@ -797,16 +817,16 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
if (bfrom) { if (bfrom) {
for (i = 0; i < n - 1; i++) for (i = 0; i < n - 1; i++)
memcpy_fromio(d + i * j, s + i * t, j); memcpy32_fromio(d + i * j, s + i * t, j);
/* the last section */ /* the last section */
memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
} else { } else {
for (i = 0; i < n - 1; i++) for (i = 0; i < n - 1; i++)
memcpy_toio(&s[i * t], &d[i * j], j); memcpy32_toio(&s[i * t], &d[i * j], j);
/* the last section */ /* the last section */
memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
} }
} }
...@@ -1070,7 +1090,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, ...@@ -1070,7 +1090,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
host->devtype_data->send_page(mtd, NFC_OUTPUT); host->devtype_data->send_page(mtd, NFC_OUTPUT);
memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize); memcpy32_fromio(host->data_buf, host->main_area0,
mtd->writesize);
copy_spare(mtd, true); copy_spare(mtd, true);
break; break;
...@@ -1086,7 +1107,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, ...@@ -1086,7 +1107,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
break; break;
case NAND_CMD_PAGEPROG: case NAND_CMD_PAGEPROG:
memcpy_toio(host->main_area0, host->data_buf, mtd->writesize); memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
copy_spare(mtd, false); copy_spare(mtd, false);
host->devtype_data->send_page(mtd, NFC_INPUT); host->devtype_data->send_page(mtd, NFC_INPUT);
host->devtype_data->send_cmd(host, command, true); host->devtype_data->send_cmd(host, command, true);
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/div64.h> #include <linux/math64.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -546,12 +546,6 @@ static char *get_partition_name(int i) ...@@ -546,12 +546,6 @@ static char *get_partition_name(int i)
return kstrdup(buf, GFP_KERNEL); return kstrdup(buf, GFP_KERNEL);
} }
static uint64_t divide(uint64_t n, uint32_t d)
{
do_div(n, d);
return n;
}
/* /*
* Initialize the nandsim structure. * Initialize the nandsim structure.
* *
...@@ -580,7 +574,7 @@ static int init_nandsim(struct mtd_info *mtd) ...@@ -580,7 +574,7 @@ static int init_nandsim(struct mtd_info *mtd)
ns->geom.oobsz = mtd->oobsize; ns->geom.oobsz = mtd->oobsize;
ns->geom.secsz = mtd->erasesize; ns->geom.secsz = mtd->erasesize;
ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz); ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz);
ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
ns->geom.secshift = ffs(ns->geom.secsz) - 1; ns->geom.secshift = ffs(ns->geom.secsz) - 1;
ns->geom.pgshift = chip->page_shift; ns->geom.pgshift = chip->page_shift;
...@@ -921,7 +915,7 @@ static int setup_wear_reporting(struct mtd_info *mtd) ...@@ -921,7 +915,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
if (!rptwear) if (!rptwear)
return 0; return 0;
wear_eb_count = divide(mtd->size, mtd->erasesize); wear_eb_count = div_u64(mtd->size, mtd->erasesize);
mem = wear_eb_count * sizeof(unsigned long); mem = wear_eb_count * sizeof(unsigned long);
if (mem / sizeof(unsigned long) != wear_eb_count) { if (mem / sizeof(unsigned long) != wear_eb_count) {
NS_ERR("Too many erase blocks for wear reporting\n"); NS_ERR("Too many erase blocks for wear reporting\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment