mtd: nand: Make sure drivers not supporting SET/GET_FEATURES return -ENOTSUPP
authorBoris Brezillon <boris.brezillon@free-electrons.com>
Fri, 26 May 2017 15:10:15 +0000 (17:10 +0200)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Tue, 30 May 2017 06:59:26 +0000 (08:59 +0200)
A lot of drivers are providing their own ->cmdfunc(), and most of the
time this implementation does not support all possible NAND operations.
But since ->cmdfunc() cannot return an error code, the core has no way
to know that the operation it requested is not supported.

This is a problem we cannot address for all kind of operations with the
current design, but we can prevent these silent failures for the
GET/SET FEATURES operation by overloading the default
->onfi_{set,get}_features() methods with one returning -ENOTSUPP.

Reported-by: Chris Packham <Chris.Packham@alliedtelesis.co.nz>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Chris Packham <Chris.Packham@alliedtelesis.co.nz>
15 files changed:
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/docg4.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/hisi504_nand.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/qcom_nandc.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/nand/vf610_nfc.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
include/linux/mtd/nand.h

index f1da4ea88f2c01c4d28ae98a96df96b1a49eb3ef..54bac5b73f0ab39886ff2babe16f2a6c1bb49d4b 100644 (file)
@@ -392,6 +392,8 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
        b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
        b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
        b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
+       b47n->nand_chip.onfi_set_features = nand_onfi_get_set_features_notsupp;
+       b47n->nand_chip.onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        nand_chip->chip_delay = 50;
        b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
index d40c32d311d8f9cb95ca20fd07cee000d7b69956..2fd733eba0a30fdc6bdbfb30ecbcc5de8a104775 100644 (file)
@@ -654,6 +654,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
        cafe->nand.read_buf = cafe_read_buf;
        cafe->nand.write_buf = cafe_write_buf;
        cafe->nand.select_chip = cafe_select_chip;
+       cafe->nand.onfi_set_features = nand_onfi_get_set_features_notsupp;
+       cafe->nand.onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        cafe->nand.chip_delay = 0;
 
index 16634df2e39a77ae1e34f68a7b4af0c642232b1e..b3c99d98fdee990ebde3f35b96cf65633c8e82b4 100644 (file)
@@ -1531,6 +1531,8 @@ int denali_init(struct denali_nand_info *denali)
        chip->cmdfunc = denali_cmdfunc;
        chip->read_byte = denali_read_byte;
        chip->waitfunc = denali_waitfunc;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        /*
         * scan for NAND devices attached to the controller
index 7af2a3cd949eee9377a22a510cc15605cd1adf74..a27a84fbfb840bcb87bd039216d50ade7e2683bd 100644 (file)
@@ -1260,6 +1260,8 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
        nand->read_buf = docg4_read_buf;
        nand->write_buf = docg4_write_buf16;
        nand->erase = docg4_erase_block;
+       nand->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       nand->onfi_get_features = nand_onfi_get_set_features_notsupp;
        nand->ecc.read_page = docg4_read_page;
        nand->ecc.write_page = docg4_write_page;
        nand->ecc.read_page_raw = docg4_read_page_raw;
index 113f76e599372d3d09526bdb4f95a3620ea45681..b9ac16f05057c5b01785b8b74453ce44d955ff1a 100644 (file)
@@ -775,6 +775,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
        chip->select_chip = fsl_elbc_select_chip;
        chip->cmdfunc = fsl_elbc_cmdfunc;
        chip->waitfunc = fsl_elbc_wait;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        chip->bbt_td = &bbt_main_descr;
        chip->bbt_md = &bbt_mirror_descr;
index d1570f512f0bbad5c07c9903528c125e412c029a..89e14daeaba697f5559fcaa7c6d30cc013c126c1 100644 (file)
@@ -831,6 +831,8 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
        chip->select_chip = fsl_ifc_select_chip;
        chip->cmdfunc = fsl_ifc_cmdfunc;
        chip->waitfunc = fsl_ifc_wait;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        chip->bbt_td = &bbt_main_descr;
        chip->bbt_md = &bbt_mirror_descr;
index e40364eeb556bd23e0341a8a089d85047282acd1..530caa80b1b6935a62654949e32aac25f0aa3904 100644 (file)
@@ -764,6 +764,8 @@ static int hisi_nfc_probe(struct platform_device *pdev)
        chip->write_buf         = hisi_nfc_write_buf;
        chip->read_buf          = hisi_nfc_read_buf;
        chip->chip_delay        = HINFC504_CHIP_DELAY;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        hisi_nfc_host_init(host);
 
index 6d6eaed2d20c281321df7e3245ab525866eeca80..0e86fb6277c3ae7c5f111bafead23c18f676ffa3 100644 (file)
@@ -708,6 +708,8 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        chip->read_buf = mpc5121_nfc_read_buf;
        chip->write_buf = mpc5121_nfc_write_buf;
        chip->select_chip = mpc5121_nfc_select_chip;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
        chip->bbt_options = NAND_BBT_USE_FLASH;
        chip->ecc.mode = NAND_ECC_SOFT;
        chip->ecc.algo = NAND_ECC_HAMMING;
index 0b3b1a88091a7bcdc3b4867e1a6a9e98bd6daed6..ed08e3946727edfacf8d345b7e22a847e9bd6920 100644 (file)
@@ -3420,6 +3420,25 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
        return 0;
 }
 
+/**
+ * nand_onfi_get_set_features_notsupp - set/get features stub returning
+ *                                     -ENOTSUPP
+ * @mtd: MTD device structure
+ * @chip: nand chip info structure
+ * @addr: feature address.
+ * @subfeature_param: the subfeature parameters, a four bytes array.
+ *
+ * Should be used by NAND controller drivers that do not support the SET/GET
+ * FEATURES operations.
+ */
+int nand_onfi_get_set_features_notsupp(struct mtd_info *mtd,
+                                      struct nand_chip *chip, int addr,
+                                      u8 *subfeature_param)
+{
+       return -ENOTSUPP;
+}
+EXPORT_SYMBOL(nand_onfi_get_set_features_notsupp);
+
 /**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
  * @mtd: MTD device structure
index 649ba8200832d5ba3d237327fd3861d9844c2149..74dae4bbdac8f73efa4b8c7dc88d724fcd172c6c 100644 (file)
@@ -1812,6 +1812,8 @@ static int alloc_nand_resource(struct platform_device *pdev)
                chip->write_buf         = pxa3xx_nand_write_buf;
                chip->options           |= NAND_NO_SUBPAGE_WRITE;
                chip->cmdfunc           = nand_cmdfunc;
+               chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+               chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
        }
 
        nand_hw_control_init(chip->controller);
index 57d483ac5765a8aa889da61042aa5c75b64404a0..88af7145a51a2cb62280f94d9f380f80c982445e 100644 (file)
@@ -2008,6 +2008,8 @@ static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
        chip->read_byte         = qcom_nandc_read_byte;
        chip->read_buf          = qcom_nandc_read_buf;
        chip->write_buf         = qcom_nandc_write_buf;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        /*
         * the bad block marker is readable only when we read the last codeword
index 442ce619b3b6d5cb8a65e2f8740e30e01e750aed..891ac7b993050d7d8f5f92d51fe2c37bdf96d1c0 100644 (file)
@@ -1183,6 +1183,8 @@ static int flctl_probe(struct platform_device *pdev)
        nand->read_buf = flctl_read_buf;
        nand->select_chip = flctl_select_chip;
        nand->cmdfunc = flctl_cmdfunc;
+       nand->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       nand->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        if (pdata->flcmncr_val & SEL_16BIT)
                nand->options |= NAND_BUSWIDTH_16;
index 3ea4bb19e12d9de9a52ba8c1479ea925d250e9eb..744ab10e896218124c20486a201f8e6c88c9ac08 100644 (file)
@@ -703,6 +703,8 @@ static int vf610_nfc_probe(struct platform_device *pdev)
        chip->read_buf = vf610_nfc_read_buf;
        chip->write_buf = vf610_nfc_write_buf;
        chip->select_chip = vf610_nfc_select_chip;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        chip->options |= NAND_NO_SUBPAGE_WRITE;
 
index e389009fca42c0caa447dc8f9b37360e3565a456..a4e3ae8f0c85fb441cb528425347b9bae6562d20 100644 (file)
@@ -915,6 +915,8 @@ static int spinand_probe(struct spi_device *spi_nand)
        chip->waitfunc  = spinand_wait;
        chip->options   |= NAND_CACHEPRG;
        chip->select_chip = spinand_select_chip;
+       chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
+       chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
 
        mtd = nand_to_mtd(chip);
 
index 7a01d2eb74430e3b6f73667cabb5a983e6d0d638..28f7dd9177e924ada131e4ad8ec1224fae3920f9 100644 (file)
@@ -1259,6 +1259,11 @@ int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page);
 int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
                           int page);
 
+/* Stub used by drivers that do not support GET/SET FEATURES operations */
+int nand_onfi_get_set_features_notsupp(struct mtd_info *mtd,
+                                      struct nand_chip *chip, int addr,
+                                      u8 *subfeature_param);
+
 /* Default read_page_raw implementation */
 int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                       uint8_t *buf, int oob_required, int page);