From 2b6d2833cd1d8a43a837a45da65860ef086443dc Mon Sep 17 00:00:00 2001 From: Zhihao Cheng Date: Tue, 15 Jun 2021 17:39:05 +0800 Subject: mtd: mtd_blkdevs: Initialize rq.limits.discard_granularity Since commit b35fd7422c2f8("block: check queue's limits.discard_granularity in __blkdev_issue_discard()") checks rq.limits.discard_granularity in __blkdev_issue_discard(), we may get following warnings on formatted ftl: WARNING: CPU: 2 PID: 7313 at block/blk-lib.c:51 __blkdev_issue_discard+0x2a7/0x390 Reproducer: 1. ftl_format /dev/mtd0 2. modprobe ftl 3. mkfs.vfat /dev/ftla 4. mount -odiscard /dev/ftla temp 5. dd if=/dev/zero of=temp/tst bs=1M count=10 oflag=direct 6. dd if=/dev/zero of=temp/tst bs=1M count=10 oflag=direct Fix it by initializing rq.limits.discard_granularity if device supports discard operation. Signed-off-by: Zhihao Cheng Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210615093905.3473709-1-chengzhihao1@huawei.com --- drivers/mtd/mtd_blkdevs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 6ce4bc57f919..8f97a4fe6e93 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -419,6 +419,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) if (tr->discard) { blk_queue_flag_set(QUEUE_FLAG_DISCARD, new->rq); blk_queue_max_discard_sectors(new->rq, UINT_MAX); + new->rq->limits.discard_granularity = tr->blksize; } gd->queue = new->rq; -- cgit v1.2.3-70-g09d2 From 14f97f0b8e2b9950c028d0cb7311ffe26a3cc1c0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 17 Jun 2021 16:37:25 +0300 Subject: mtd: rawnand: Add a check in of_get_nand_secure_regions() Check for whether of_property_count_elems_of_size() returns a negative error code. Fixes: 13b89768275d ("mtd: rawnand: Add support for secure regions in NAND memory") Signed-off-by: Dan Carpenter Reviewed-by: Manivannan Sadhasivam Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/YMtQFXE0F1w7mUh+@mwanda --- drivers/mtd/nand/raw/nand_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 57a583149cc0..cbba46432e39 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5231,8 +5231,8 @@ static int of_get_nand_secure_regions(struct nand_chip *chip) int nr_elem, i, j; nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64)); - if (!nr_elem) - return 0; + if (nr_elem <= 0) + return nr_elem; chip->nr_secure_regions = nr_elem / 2; chip->secure_regions = kcalloc(chip->nr_secure_regions, sizeof(*chip->secure_regions), -- cgit v1.2.3-70-g09d2 From 962bf783ef65d15b0f8ca9c33342cf3b20bf0d2e Mon Sep 17 00:00:00 2001 From: Desmond Cheong Zhi Xi Date: Fri, 18 Jun 2021 00:09:04 +0800 Subject: mtd: break circular locks in register_mtd_blktrans Syzbot reported a circular locking dependency: https://syzkaller.appspot.com/bug?id=7bd106c28e846d1023d4ca915718b1a0905444cb This happens because of the following lock dependencies: 1. loop_ctl_mutex -> bdev->bd_mutex (when loop_control_ioctl calls loop_remove, which then calls del_gendisk; this also happens in loop_exit which eventually calls loop_remove) 2. bdev->bd_mutex -> mtd_table_mutex (when blkdev_get_by_dev calls __blkdev_get, which then calls blktrans_open) 3. mtd_table_mutex -> major_names_lock (when register_mtd_blktrans calls __register_blkdev) 4. major_names_lock -> loop_ctl_mutex (when blk_request_module calls loop_probe) Hence there's an overall dependency of: loop_ctl_mutex ----------> bdev->bd_mutex ^ | | | | v major_names_lock <--------- mtd_table_mutex We can break this circular dependency by holding mtd_table_mutex only for the required critical section in register_mtd_blktrans. This avoids the mtd_table_mutex -> major_names_lock dependency. Reported-and-tested-by: syzbot+6a8a0d93c91e8fbf2e80@syzkaller.appspotmail.com Co-developed-by: Christoph Hellwig Signed-off-by: Christoph Hellwig Signed-off-by: Desmond Cheong Zhi Xi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210617160904.570111-1-desmondcheongzx@gmail.com --- drivers/mtd/mtd_blkdevs.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 8f97a4fe6e93..31b208fb225e 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -526,14 +526,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) if (!blktrans_notifier.list.next) register_mtd_user(&blktrans_notifier); - - mutex_lock(&mtd_table_mutex); - ret = register_blkdev(tr->major, tr->name); if (ret < 0) { printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", tr->name, tr->major, ret); - mutex_unlock(&mtd_table_mutex); return ret; } @@ -543,12 +539,12 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) tr->blkshift = ffs(tr->blksize) - 1; INIT_LIST_HEAD(&tr->devs); - list_add(&tr->list, &blktrans_majors); + mutex_lock(&mtd_table_mutex); + list_add(&tr->list, &blktrans_majors); mtd_for_each_device(mtd) if (mtd->type != MTD_ABSENT) tr->add_mtd(tr, mtd); - mutex_unlock(&mtd_table_mutex); return 0; } -- cgit v1.2.3-70-g09d2 From e83862ee1b9b1668826683f432b041875ec0c819 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Jun 2021 16:42:07 +0300 Subject: mtd: mchp48l640: silence some uninitialized variable warnings Smatch complains that zero length read/writes will lead to an uninitalized return value. I don't know if that's possible, but it's nicer to return a zero literal anyway so let's do that. Fixes: 88d125026753 ("mtd: devices: add support for microchip 48l640 EERAM") Signed-off-by: Dan Carpenter Reviewed-by: Fabio Estevam Reviewed-by: Heiko Schocher Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/YMyir961W28TX5dT@mwanda --- drivers/mtd/devices/mchp48l640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c index efc2003bd13a..ad66b5aaf4e9 100644 --- a/drivers/mtd/devices/mchp48l640.c +++ b/drivers/mtd/devices/mchp48l640.c @@ -229,7 +229,7 @@ static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len, woff += ws; } - return ret; + return 0; } static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len, @@ -286,7 +286,7 @@ static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len, woff += ws; } - return ret; + return 0; }; static const struct mchp48_caps mchp48l640_caps = { -- cgit v1.2.3-70-g09d2 From 45bb1faa29effbd4ca4d581b32373f2eda309b95 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 7 Jul 2021 15:53:59 +0200 Subject: mtd: core: handle flashes without OTP gracefully There are flash drivers which registers the OTP callbacks although the flash doesn't support OTP regions and return -ENODATA for these callbacks if there is no OTP. If this happens, the probe of the whole flash will fail. Fix it by handling the ENODATA return code and skip the OTP region nvmem setup. Fixes: 4b361cfa8624 ("mtd: core: add OTP nvmem provider support") Reported-by: Guenter Roeck Signed-off-by: Michael Walle Tested-by: Guenter Roeck Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210707135359.32398-1-michael@walle.cc --- drivers/mtd/mtdcore.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index b5ccd3037788..c8fd7f758938 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -806,7 +806,9 @@ static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user) err: kfree(info); - return ret; + + /* ENODATA means there is no OTP region. */ + return ret == -ENODATA ? 0 : ret; } static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, -- cgit v1.2.3-70-g09d2 From 2394e628738933aa014093d93093030f6232946d Mon Sep 17 00:00:00 2001 From: Andreas Persson Date: Mon, 12 Jul 2021 09:54:52 +0200 Subject: mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards Erasing an AMD linear flash card (AM29F016D) crashes after the first sector has been erased. Likewise, writing to it crashes after two bytes have been written. The reason is a missing check for a null pointer - the cmdset_priv field is not set for this type of card. Fixes: 4844ef80305d ("mtd: cfi_cmdset_0002: Add support for polling status register") Signed-off-by: Andreas Persson Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/DB6P189MB05830B3530B8087476C5CFE4C1159@DB6P189MB0583.EURP189.PROD.OUTLOOK.COM --- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 3097e93787f7..a761134fd3be 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -119,7 +119,7 @@ static int cfi_use_status_reg(struct cfi_private *cfi) struct cfi_pri_amdstd *extp = cfi->cmdset_priv; u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ; - return extp->MinorVersion >= '5' && + return extp && extp->MinorVersion >= '5' && (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG; } -- cgit v1.2.3-70-g09d2 From 99dc4ad992bf156692b088fab4d98deab7cbd3e6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 12 Jul 2021 15:52:14 +0100 Subject: mtd: devices: mchp48l640: Fix memory leak on cmd The allocation for cmd is not being kfree'd on the return leading to a memory leak. Fix this by kfree'ing it. Addresses-Coverity: ("Resource leak") Fixes: 88d125026753 ("mtd: devices: add support for microchip 48l640 EERAM") Signed-off-by: Colin Ian King Reviewed-by: Heiko Schocher Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210712145214.101377-1-colin.king@canonical.com --- drivers/mtd/devices/mchp48l640.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c index ad66b5aaf4e9..99400d0fb8c1 100644 --- a/drivers/mtd/devices/mchp48l640.c +++ b/drivers/mtd/devices/mchp48l640.c @@ -255,6 +255,7 @@ static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len, if (!ret) *retlen += len; + kfree(cmd); return ret; fail: -- cgit v1.2.3-70-g09d2 From b7abb051682263e51866bc78762fd0083d64c5ed Mon Sep 17 00:00:00 2001 From: Desmond Cheong Zhi Xi Date: Sat, 17 Jul 2021 18:07:19 +0800 Subject: mtd: fix lock hierarchy in deregister_mtd_blktrans There is a lock hierarchy of major_names_lock --> mtd_table_mutex. One existing chain is as follows: 1. major_names_lock --> loop_ctl_mutex (when blk_request_module calls loop_probe) 2. loop_ctl_mutex --> bdev->bd_mutex (when loop_control_ioctl calls loop_remove, which then calls del_gendisk) 3. bdev->bd_mutex --> mtd_table_mutex (when blkdev_get_by_dev calls __blkdev_get, which then calls blktrans_open) Since unregister_blkdev grabs the major_names_lock, we need to call it outside the critical section for mtd_table_mutex, otherwise we invert the lock hierarchy. Reported-by: Hillf Danton Signed-off-by: Desmond Cheong Zhi Xi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210717100719.728829-1-desmondcheongzx@gmail.com --- drivers/mtd/mtd_blkdevs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 31b208fb225e..44bea3f65060 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -561,8 +561,8 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) list_for_each_entry_safe(dev, next, &tr->devs, list) tr->remove_dev(dev); - unregister_blkdev(tr->major, tr->name); mutex_unlock(&mtd_table_mutex); + unregister_blkdev(tr->major, tr->name); BUG_ON(!list_empty(&tr->devs)); return 0; -- cgit v1.2.3-70-g09d2 From b48027083a78b13356695555a05b0e085e378687 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 27 Jul 2021 11:58:13 +0530 Subject: mtd: rawnand: Fix probe failure due to of_get_nand_secure_regions() Due to 14f97f0b8e2b, the rawnand platforms without "secure-regions" property defined in DT fails to probe. The issue is, of_get_nand_secure_regions() errors out if of_property_count_elems_of_size() returns a negative error code. If the "secure-regions" property is not present in DT, then also we'll get -EINVAL from of_property_count_elems_of_size() but it should not be treated as an error for platforms not declaring "secure-regions" in DT. So fix this behaviour by checking for the existence of that property in DT and return 0 if it is not present. Fixes: 14f97f0b8e2b ("mtd: rawnand: Add a check in of_get_nand_secure_regions()") Reported-by: Martin Kaiser Signed-off-by: Manivannan Sadhasivam Reviewed-by: Martin Kaiser Tested-by: Martin Kaiser Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210727062813.32619-1-manivannan.sadhasivam@linaro.org --- drivers/mtd/nand/raw/nand_base.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index cbba46432e39..3d6c6e880520 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5228,8 +5228,14 @@ static bool of_get_nand_on_flash_bbt(struct device_node *np) static int of_get_nand_secure_regions(struct nand_chip *chip) { struct device_node *dn = nand_get_flash_node(chip); + struct property *prop; int nr_elem, i, j; + /* Only proceed if the "secure-regions" property is present in DT */ + prop = of_find_property(dn, "secure-regions", NULL); + if (!prop) + return 0; + nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64)); if (nr_elem <= 0) return nr_elem; -- cgit v1.2.3-70-g09d2