summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-mtd8
-rw-r--r--Documentation/devicetree/bindings/mtd/partition.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.txt42
-rw-r--r--drivers/mtd/bcm47xxpart.c29
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c62
-rw-r--r--drivers/mtd/chips/cfi_probe.c42
-rw-r--r--drivers/mtd/cmdlinepart.c5
-rw-r--r--drivers/mtd/devices/docg3.c3
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/inftlmount.c23
-rw-r--r--drivers/mtd/maps/pismo.c1
-rw-r--r--drivers/mtd/mtdcore.c24
-rw-r--r--drivers/mtd/mtdcore.h1
-rw-r--r--drivers/mtd/mtdpart.c44
-rw-r--r--drivers/mtd/nand/raw/Kconfig8
-rw-r--r--drivers/mtd/nftlmount.c23
-rw-r--r--drivers/mtd/spi-nor/Kconfig2
17 files changed, 225 insertions, 96 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd
index f34e592301d1..3bc7c0a95c92 100644
--- a/Documentation/ABI/testing/sysfs-class-mtd
+++ b/Documentation/ABI/testing/sysfs-class-mtd
@@ -232,3 +232,11 @@ Description:
of the parent (another partition or a flash device) in bytes.
This attribute is absent on flash devices, so it can be used
to distinguish them from partitions.
+
+What: /sys/class/mtd/mtdX/oobavail
+Date: April 2018
+KernelVersion: 4.16
+Contact: linux-mtd@lists.infradead.org
+Description:
+ Number of bytes available for a client to place data into
+ the out of band area.
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
index 36f3b769a626..a8f382642ba9 100644
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ b/Documentation/devicetree/bindings/mtd/partition.txt
@@ -14,7 +14,7 @@ method is used for a given flash device. To describe the method there should be
a subnode of the flash device that is named 'partitions'. It must have a
'compatible' property, which is used to identify the method to use.
-We currently only document a binding for fixed layouts.
+Available bindings are listed in the "partitions" subdirectory.
Fixed Partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.txt b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.txt
new file mode 100644
index 000000000000..1d61a029395e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.txt
@@ -0,0 +1,42 @@
+Broadcom BCM47xx Partitions
+===========================
+
+Broadcom is one of hardware manufacturers providing SoCs (BCM47xx) used in
+home routers. Their BCM947xx boards using CFE bootloader have several partitions
+without any on-flash partition table. On some devices their sizes and/or
+meanings can also vary so fixed partitioning can't be used.
+
+Discovering partitions on these devices is possible thanks to having a special
+header and/or magic signature at the beginning of each of them. They are also
+block aligned which is important for determinig a size.
+
+Most of partitions use ASCII text based magic for determining a type. More
+complex partitions (like TRX with its HDR0 magic) may include extra header
+containing some details, including a length.
+
+A list of supported partitions includes:
+1) Bootloader with Broadcom's CFE (Common Firmware Environment)
+2) NVRAM with configuration/calibration data
+3) Device manufacturer's data with some default values (e.g. SSIDs)
+4) TRX firmware container which can hold up to 4 subpartitions
+5) Backup TRX firmware used after failed upgrade
+
+As mentioned earlier, role of some partitions may depend on extra configuration.
+For example both: main firmware and backup firmware use the same TRX format with
+the same header. To distinguish currently used firmware a CFE's environment
+variable "bootpartition" is used.
+
+
+Devices using Broadcom partitions described above should should have flash node
+with a subnode named "partitions" using following properties:
+
+Required properties:
+- compatible : (required) must be "brcm,bcm947xx-cfe-partitions"
+
+Example:
+
+flash@0 {
+ partitions {
+ compatible = "brcm,bcm947xx-cfe-partitions";
+ };
+};
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index fe2581d9d882..0f93d2239352 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -186,6 +186,8 @@ static int bcm47xxpart_parse(struct mtd_info *master,
/* TRX */
if (buf[0x000 / 4] == TRX_MAGIC) {
struct trx_header *trx;
+ uint32_t last_subpart;
+ uint32_t trx_size;
if (trx_num >= ARRAY_SIZE(trx_parts))
pr_warn("No enough space to store another TRX found at 0x%X\n",
@@ -195,11 +197,23 @@ static int bcm47xxpart_parse(struct mtd_info *master,
bcm47xxpart_add_part(&parts[curr_part++], "firmware",
offset, 0);
- /* Jump to the end of TRX */
+ /*
+ * Try to find TRX size. The "length" field isn't fully
+ * reliable as it could be decreased to make CRC32 cover
+ * only part of TRX data. It's commonly used as checksum
+ * can't cover e.g. ever-changing rootfs partition.
+ * Use offsets as helpers for assuming min TRX size.
+ */
trx = (struct trx_header *)buf;
- offset = roundup(offset + trx->length, blocksize);
- /* Next loop iteration will increase the offset */
- offset -= blocksize;
+ last_subpart = max3(trx->offset[0], trx->offset[1],
+ trx->offset[2]);
+ trx_size = max(trx->length, last_subpart + blocksize);
+
+ /*
+ * Skip the TRX data. Decrease offset by block size as
+ * the next loop iteration will increase it.
+ */
+ offset += roundup(trx_size, blocksize) - blocksize;
continue;
}
@@ -290,9 +304,16 @@ static int bcm47xxpart_parse(struct mtd_info *master,
return curr_part;
};
+static const struct of_device_id bcm47xxpart_of_match_table[] = {
+ { .compatible = "brcm,bcm947xx-cfe-partitions" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm47xxpart_of_match_table);
+
static struct mtd_part_parser bcm47xxpart_mtd_parser = {
.parse_fn = bcm47xxpart_parse,
.name = "bcm47xxpart",
+ .of_match_table = bcm47xxpart_of_match_table,
};
module_mtd_part_parser(bcm47xxpart_mtd_parser);
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 668e2cbc155b..78b69ccd0b65 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -42,10 +42,10 @@
#define AMD_BOOTLOC_BUG
#define FORCE_WORD_WRITE 0
-#define MAX_WORD_RETRIES 3
+#define MAX_RETRIES 3
-#define SST49LF004B 0x0060
-#define SST49LF040B 0x0050
+#define SST49LF004B 0x0060
+#define SST49LF040B 0x0050
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6
@@ -207,7 +207,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
if (cfi->cfiq->BufWriteTimeoutTyp) {
- pr_debug("Using buffer write method\n" );
+ pr_debug("Using buffer write method\n");
mtd->_write = cfi_amdstd_write_buffers;
}
}
@@ -1562,7 +1562,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
* depending of the conditions. The ' + 1' is to avoid having a
* timeout of 0 jiffies if HZ is smaller than 1000.
*/
- unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
+ unsigned long uWriteTimeout = (HZ / 1000) + 1;
int ret = 0;
map_word oldd;
int retry_cnt = 0;
@@ -1577,7 +1577,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
}
pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
- __func__, adr, datum.x[0] );
+ __func__, adr, datum.x[0]);
if (mode == FL_OTP_WRITE)
otp_enter(map, chip, adr, map_bankwidth(map));
@@ -1643,10 +1643,10 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
/* Did we succeed? */
if (!chip_good(map, adr, datum)) {
/* reset on all failures. */
- map_write( map, CMD(0xF0), chip->start );
+ map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
- if (++retry_cnt <= MAX_WORD_RETRIES)
+ if (++retry_cnt <= MAX_RETRIES)
goto retry;
ret = -EIO;
@@ -1821,7 +1821,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
datum = map_word_load(map, buf);
pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
- __func__, adr, datum.x[0] );
+ __func__, adr, datum.x[0]);
XIP_INVAL_CACHED_RANGE(map, adr, len);
ENABLE_VPP(map);
@@ -1879,7 +1879,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
if (time_after(jiffies, timeo) && !chip_ready(map, adr))
break;
- if (chip_ready(map, adr)) {
+ if (chip_good(map, adr, datum)) {
xip_enable(map, chip, adr);
goto op_done;
}
@@ -2105,7 +2105,7 @@ retry:
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
- if (++retry_cnt <= MAX_WORD_RETRIES)
+ if (++retry_cnt <= MAX_RETRIES)
goto retry;
ret = -EIO;
@@ -2240,6 +2240,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
unsigned long int adr;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+ int retry_cnt = 0;
adr = cfi->addr_unlock1;
@@ -2251,12 +2252,13 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
}
pr_debug("MTD %s(): ERASE 0x%.8lx\n",
- __func__, chip->start );
+ __func__, chip->start);
XIP_INVAL_CACHED_RANGE(map, adr, map->size);
ENABLE_VPP(map);
xip_disable(map, chip, adr);
+ retry:
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
@@ -2292,12 +2294,13 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
chip->erase_suspended = 0;
}
- if (chip_ready(map, adr))
+ if (chip_good(map, adr, map_word_ff(map)))
break;
if (time_after(jiffies, timeo)) {
printk(KERN_WARNING "MTD %s(): software timeout\n",
- __func__ );
+ __func__);
+ ret = -EIO;
break;
}
@@ -2305,12 +2308,15 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
UDELAY(map, chip, adr, 1000000/HZ);
}
/* Did we succeed? */
- if (!chip_good(map, adr, map_word_ff(map))) {
+ if (ret) {
/* reset on all failures. */
- map_write( map, CMD(0xF0), chip->start );
+ map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
- ret = -EIO;
+ if (++retry_cnt <= MAX_RETRIES) {
+ ret = 0;
+ goto retry;
+ }
}
chip->state = FL_READY;
@@ -2329,6 +2335,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+ int retry_cnt = 0;
adr += chip->start;
@@ -2340,12 +2347,13 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
}
pr_debug("MTD %s(): ERASE 0x%.8lx\n",
- __func__, adr );
+ __func__, adr);
XIP_INVAL_CACHED_RANGE(map, adr, len);
ENABLE_VPP(map);
xip_disable(map, chip, adr);
+ retry:
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
@@ -2381,15 +2389,13 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->erase_suspended = 0;
}
- if (chip_ready(map, adr)) {
- xip_enable(map, chip, adr);
+ if (chip_good(map, adr, map_word_ff(map)))
break;
- }
if (time_after(jiffies, timeo)) {
- xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n",
- __func__ );
+ __func__);
+ ret = -EIO;
break;
}
@@ -2397,15 +2403,19 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
UDELAY(map, chip, adr, 1000000/HZ);
}
/* Did we succeed? */
- if (!chip_good(map, adr, map_word_ff(map))) {
+ if (ret) {
/* reset on all failures. */
- map_write( map, CMD(0xF0), chip->start );
+ map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
- ret = -EIO;
+ if (++retry_cnt <= MAX_RETRIES) {
+ ret = 0;
+ goto retry;
+ }
}
chip->state = FL_READY;
+ xip_enable(map, chip, adr);
DISABLE_VPP(map);
put_chip(map, chip, adr);
mutex_unlock(&chip->mutex);
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index e8d0164498b0..cf426956454c 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -63,6 +63,30 @@ do { \
#endif
+/*
+ * This fixup occurs immediately after reading the CFI structure and can affect
+ * the number of chips detected, unlike cfi_fixup, which occurs after an
+ * mtd_info structure has been created for the chip.
+ */
+struct cfi_early_fixup {
+ uint16_t mfr;
+ uint16_t id;
+ void (*fixup)(struct cfi_private *cfi);
+};
+
+static void cfi_early_fixup(struct cfi_private *cfi,
+ const struct cfi_early_fixup *fixups)
+{
+ const struct cfi_early_fixup *f;
+
+ for (f = fixups; f->fixup; f++) {
+ if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
+ ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) {
+ f->fixup(cfi);
+ }
+ }
+}
+
/* check for QRY.
in: interleave,type,mode
ret: table index, <0 for error
@@ -151,6 +175,22 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
return 1;
}
+static void fixup_s70gl02gs_chips(struct cfi_private *cfi)
+{
+ /*
+ * S70GL02GS flash reports a single 256 MiB chip, but is really made up
+ * of two 128 MiB chips with 1024 sectors each.
+ */
+ cfi->cfiq->DevSize = 27;
+ cfi->cfiq->EraseRegionInfo[0] = 0x20003ff;
+ pr_warn("Bad S70GL02GS CFI data; adjust to detect 2 chips\n");
+}
+
+static const struct cfi_early_fixup cfi_early_fixup_table[] = {
+ { CFI_MFR_AMD, 0x4801, fixup_s70gl02gs_chips },
+ { },
+};
+
static int __xipram cfi_chip_setup(struct map_info *map,
struct cfi_private *cfi)
{
@@ -235,6 +275,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
+ cfi_early_fixup(cfi, cfi_early_fixup_table);
+
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8, cfi->mfr, cfi->id);
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index fbd5affc0acf..3ea44cff9b75 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -190,7 +190,10 @@ static struct mtd_partition * newpart(char *s,
extra_mem = (unsigned char *)(parts + *num_parts);
}
- /* enter this partition (offset will be calculated later if it is zero at this point) */
+ /*
+ * enter this partition (offset will be calculated later if it is
+ * OFFSET_CONTINUOUS at this point)
+ */
parts[this_part].size = size;
parts[this_part].offset = offset;
parts[this_part].mask_flags = mask_flags;
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index c594fe5eac08..802d8f159e90 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1470,8 +1470,7 @@ static struct docg3 *sysfs_dev2docg3(struct device *dev,
struct device_attribute *attr)
{
int floor;
- struct platform_device *pdev = to_platform_device(dev);
- struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
+ struct mtd_info **docg3_floors = dev_get_drvdata(dev);
floor = attr->attr.name[1] - '0';
if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index aaaeaae01e1d..3a6f450d1093 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -140,7 +140,7 @@ static int dataflash_waitready(struct spi_device *spi)
if (status & (1 << 7)) /* RDY/nBSY */
return status;
- msleep(3);
+ usleep_range(3000, 4000);
}
}
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index aab4f68bd36f..2d598412972d 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -334,28 +334,37 @@ static int memcmpb(void *a, int c, int n)
static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
int len, int check_oob)
{
- u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
struct mtd_info *mtd = inftl->mbd.mtd;
size_t retlen;
- int i;
+ int i, ret;
+ u8 *buf;
+
+ buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
+ if (!buf)
+ return -1;
+ ret = -1;
for (i = 0; i < len; i += SECTORSIZE) {
if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
- return -1;
+ goto out;
if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
- return -1;
+ goto out;
if (check_oob) {
if(inftl_read_oob(mtd, address, mtd->oobsize,
&retlen, &buf[SECTORSIZE]) < 0)
- return -1;
+ goto out;
if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
- return -1;
+ goto out;
}
address += SECTORSIZE;
}
- return 0;
+ ret = 0;
+
+out:
+ kfree(buf);
+ return ret;
}
/*
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index dc6df9abea0b..c065d7995c0a 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -265,7 +265,6 @@ MODULE_DEVICE_TABLE(i2c, pismo_id);
static struct i2c_driver pismo_driver = {
.driver = {
.name = "pismo",
- .owner = THIS_MODULE,
},
.probe = pismo_probe,
.remove = pismo_remove,
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 807d17d863b3..7b0d105627b1 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -210,6 +210,15 @@ static ssize_t mtd_oobsize_show(struct device *dev,
}
static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
+static ssize_t mtd_oobavail_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", mtd->oobavail);
+}
+static DEVICE_ATTR(oobavail, S_IRUGO, mtd_oobavail_show, NULL);
+
static ssize_t mtd_numeraseregions_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -327,6 +336,7 @@ static struct attribute *mtd_attrs[] = {
&dev_attr_writesize.attr,
&dev_attr_subpagesize.attr,
&dev_attr_oobsize.attr,
+ &dev_attr_oobavail.attr,
&dev_attr_numeraseregions.attr,
&dev_attr_name.attr,
&dev_attr_ecc_strength.attr,
@@ -690,7 +700,6 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
const struct mtd_partition *parts,
int nr_parts)
{
- struct mtd_partitions parsed = { };
int ret;
mtd_set_dev_defaults(mtd);
@@ -702,13 +711,10 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
}
/* Prefer parsed partitions over driver-provided fallback */
- ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
- if (!ret && parsed.nr_parts) {
- parts = parsed.parts;
- nr_parts = parsed.nr_parts;
- }
-
- if (nr_parts)
+ ret = parse_mtd_partitions(mtd, types, parser_data);
+ if (ret > 0)
+ ret = 0;
+ else if (nr_parts)
ret = add_mtd_partitions(mtd, parts, nr_parts);
else if (!device_is_registered(&mtd->dev))
ret = add_mtd_device(mtd);
@@ -734,8 +740,6 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
}
out:
- /* Cleanup any parsed partitions */
- mtd_part_parser_cleanup(&parsed);
if (ret && device_is_registered(&mtd->dev))
del_mtd_device(mtd);
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index 37accfd0400e..9887bda317cd 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -15,7 +15,6 @@ int del_mtd_partitions(struct mtd_info *);
struct mtd_partitions;
int parse_mtd_partitions(struct mtd_info *master, const char * const *types,
- struct mtd_partitions *pparts,
struct mtd_part_parser_data *data);
void mtd_part_parser_cleanup(struct mtd_partitions *parts);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 023516a63276..f8d3a015cdad 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -335,20 +335,7 @@ static inline void free_partition(struct mtd_part *p)
*/
static int mtd_parse_part(struct mtd_part *slave, const char *const *types)
{
- struct mtd_partitions parsed;
- int err;
-
- err = parse_mtd_partitions(&slave->mtd, types, &parsed, NULL);
- if (err)
- return err;
- else if (!parsed.nr_parts)
- return -ENOENT;
-
- err = add_mtd_partitions(&slave->mtd, parsed.parts, parsed.nr_parts);
-
- mtd_part_parser_cleanup(&parsed);
-
- return err;
+ return parse_mtd_partitions(&slave->mtd, types, NULL);
}
static struct mtd_part *allocate_partition(struct mtd_info *parent,
@@ -933,30 +920,27 @@ static int mtd_part_of_parse(struct mtd_info *master,
}
/**
- * parse_mtd_partitions - parse MTD partitions
+ * parse_mtd_partitions - parse and register MTD partitions
+ *
* @master: the master partition (describes whole MTD device)
* @types: names of partition parsers to try or %NULL
- * @pparts: info about partitions found is returned here
* @data: MTD partition parser-specific data
*
- * This function tries to find partition on MTD device @master. It uses MTD
- * partition parsers, specified in @types. However, if @types is %NULL, then
- * the default list of parsers is used. The default list contains only the
+ * This function tries to find & register partitions on MTD device @master. It
+ * uses MTD partition parsers, specified in @types. However, if @types is %NULL,
+ * then the default list of parsers is used. The default list contains only the
* "cmdlinepart" and "ofpart" parsers ATM.
* Note: If there are more then one parser in @types, the kernel only takes the
* partitions parsed out by the first parser.
*
* This function may return:
* o a negative error code in case of failure
- * o zero otherwise, and @pparts will describe the partitions, number of
- * partitions, and the parser which parsed them. Caller must release
- * resources with mtd_part_parser_cleanup() when finished with the returned
- * data.
+ * o number of found partitions otherwise
*/
int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
- struct mtd_partitions *pparts,
struct mtd_part_parser_data *data)
{
+ struct mtd_partitions pparts = { };
struct mtd_part_parser *parser;
int ret, err = 0;
@@ -970,7 +954,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
* handled in a separated function.
*/
if (!strcmp(*types, "ofpart")) {
- ret = mtd_part_of_parse(master, pparts);
+ ret = mtd_part_of_parse(master, &pparts);
} else {
pr_debug("%s: parsing partitions %s\n", master->name,
*types);
@@ -981,13 +965,17 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
parser ? parser->name : NULL);
if (!parser)
continue;
- ret = mtd_part_do_parse(parser, master, pparts, data);
+ ret = mtd_part_do_parse(parser, master, &pparts, data);
if (ret <= 0)
mtd_part_parser_put(parser);
}
/* Found partitions! */
- if (ret > 0)
- return 0;
+ if (ret > 0) {
+ err = add_mtd_partitions(master, pparts.parts,
+ pparts.nr_parts);
+ mtd_part_parser_cleanup(&pparts);
+ return err ? err : pparts.nr_parts;
+ }
/*
* Stash the first error we see; only report it if no parser
* succeeds
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 19a2b283fbbe..6871ff0fd300 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -46,7 +46,7 @@ config MTD_NAND_DENALI
config MTD_NAND_DENALI_PCI
tristate "Support Denali NAND controller on Intel Moorestown"
select MTD_NAND_DENALI
- depends on HAS_DMA && PCI
+ depends on PCI
help
Enable the driver for NAND flash on Intel Moorestown, using the
Denali NAND controller core.
@@ -152,7 +152,6 @@ config MTD_NAND_S3C2410_CLKSTOP
config MTD_NAND_TANGO
tristate "NAND Flash support for Tango chips"
depends on ARCH_TANGO || COMPILE_TEST
- depends on HAS_DMA
help
Enables the NAND Flash controller on Tango chips.
@@ -285,7 +284,7 @@ config MTD_NAND_MARVELL
tristate "NAND controller support on Marvell boards"
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
COMPILE_TEST
- depends on HAS_IOMEM && HAS_DMA
+ depends on HAS_IOMEM
help
This enables the NAND flash controller driver for Marvell boards,
including:
@@ -447,7 +446,6 @@ config MTD_NAND_SH_FLCTL
tristate "Support for NAND on Renesas SuperH FLCTL"
depends on SUPERH || COMPILE_TEST
depends on HAS_IOMEM
- depends on HAS_DMA
help
Several Renesas SuperH CPU has FLCTL. This option enables support
for NAND Flash using FLCTL.
@@ -515,7 +513,6 @@ config MTD_NAND_SUNXI
config MTD_NAND_HISI504
tristate "Support for NAND controller on Hisilicon SoC Hip04"
depends on ARCH_HISI || COMPILE_TEST
- depends on HAS_DMA
help
Enables support for NAND controller on Hisilicon SoC Hip04.
@@ -529,7 +526,6 @@ config MTD_NAND_QCOM
config MTD_NAND_MTK
tristate "Support for NAND controller on MTK SoCs"
depends on ARCH_MEDIATEK || COMPILE_TEST
- depends on HAS_DMA
help
Enables support for NAND controller on MTK SoCs.
This controller is found on mt27xx, mt81xx, mt65xx SoCs.
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index a6fbfa4e5799..6281da3dadac 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -272,28 +272,37 @@ static int memcmpb(void *a, int c, int n)
static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
int check_oob)
{
- u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
struct mtd_info *mtd = nftl->mbd.mtd;
size_t retlen;
- int i;
+ int i, ret;
+ u8 *buf;
+
+ buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
+ if (!buf)
+ return -1;
+ ret = -1;
for (i = 0; i < len; i += SECTORSIZE) {
if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
- return -1;
+ goto out;
if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
- return -1;
+ goto out;
if (check_oob) {
if(nftl_read_oob(mtd, address, mtd->oobsize,
&retlen, &buf[SECTORSIZE]) < 0)
- return -1;
+ goto out;
if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
- return -1;
+ goto out;
}
address += SECTORSIZE;
}
- return 0;
+ ret = 0;
+
+out:
+ kfree(buf);
+ return ret;
}
/* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89da88e59121..c493b8230a38 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -71,7 +71,7 @@ config SPI_FSL_QUADSPI
config SPI_HISI_SFC
tristate "Hisilicon SPI-NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST
- depends on HAS_IOMEM && HAS_DMA
+ depends on HAS_IOMEM
help
This enables support for hisilicon SPI-NOR flash controller.