Merge tag 'mtd/for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
[sfrench/cifs-2.6.git] / drivers / mtd / nand / raw / nand_base.c
index f64e3b6605c68305c1628ef82cada3ee95229a18..c24e5e2ba130fee1867884e5d1cddc8187a6775e 100644 (file)
@@ -683,7 +683,12 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
        if (ret)
                return ret;
 
-       timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
+       /*
+        * +1 below is necessary because if we are now in the last fraction
+        * of jiffy and msecs_to_jiffies is 1 then we will wait only that
+        * small jiffy fraction - possibly leading to false timeout
+        */
+       timeout_ms = jiffies + msecs_to_jiffies(timeout_ms) + 1;
        do {
                ret = nand_read_data_op(chip, &status, sizeof(status), true);
                if (ret)
@@ -4321,16 +4326,22 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 /**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
  * @mtd: MTD device structure
+ *
+ * Returns 0 for success or negative error code otherwise.
  */
 static int nand_suspend(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd_to_nand(mtd);
+       int ret = 0;
 
        mutex_lock(&chip->lock);
-       chip->suspended = 1;
+       if (chip->suspend)
+               ret = chip->suspend(chip);
+       if (!ret)
+               chip->suspended = 1;
        mutex_unlock(&chip->lock);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -4342,11 +4353,14 @@ static void nand_resume(struct mtd_info *mtd)
        struct nand_chip *chip = mtd_to_nand(mtd);
 
        mutex_lock(&chip->lock);
-       if (chip->suspended)
+       if (chip->suspended) {
+               if (chip->resume)
+                       chip->resume(chip);
                chip->suspended = 0;
-       else
+       } else {
                pr_err("%s called for a chip which is not in suspended state\n",
                        __func__);
+       }
        mutex_unlock(&chip->lock);
 }
 
@@ -4360,6 +4374,38 @@ static void nand_shutdown(struct mtd_info *mtd)
        nand_suspend(mtd);
 }
 
+/**
+ * nand_lock - [MTD Interface] Lock the NAND flash
+ * @mtd: MTD device structure
+ * @ofs: offset byte address
+ * @len: number of bytes to lock (must be a multiple of block/page size)
+ */
+static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+
+       if (!chip->lock_area)
+               return -ENOTSUPP;
+
+       return chip->lock_area(chip, ofs, len);
+}
+
+/**
+ * nand_unlock - [MTD Interface] Unlock the NAND flash
+ * @mtd: MTD device structure
+ * @ofs: offset byte address
+ * @len: number of bytes to unlock (must be a multiple of block/page size)
+ */
+static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+
+       if (!chip->unlock_area)
+               return -ENOTSUPP;
+
+       return chip->unlock_area(chip, ofs, len);
+}
+
 /* Set default functions */
 static void nand_set_defaults(struct nand_chip *chip)
 {
@@ -5591,8 +5637,7 @@ static int nand_scan_tail(struct nand_chip *chip)
                }
                if (!ecc->read_page)
                        ecc->read_page = nand_read_page_hwecc_oob_first;
-               /* fall through */
-
+               fallthrough;
        case NAND_ECC_HW:
                /* Use standard hwecc read page function? */
                if (!ecc->read_page)
@@ -5611,8 +5656,7 @@ static int nand_scan_tail(struct nand_chip *chip)
                        ecc->read_subpage = nand_read_subpage;
                if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
                        ecc->write_subpage = nand_write_subpage_hwecc;
-               /* fall through */
-
+               fallthrough;
        case NAND_ECC_HW_SYNDROME:
                if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
                    (!ecc->read_page ||
@@ -5649,8 +5693,7 @@ static int nand_scan_tail(struct nand_chip *chip)
                        ecc->size, mtd->writesize);
                ecc->mode = NAND_ECC_SOFT;
                ecc->algo = NAND_ECC_HAMMING;
-               /* fall through */
-
+               fallthrough;
        case NAND_ECC_SOFT:
                ret = nand_set_ecc_soft_ops(chip);
                if (ret) {
@@ -5786,8 +5829,8 @@ static int nand_scan_tail(struct nand_chip *chip)
        mtd->_read_oob = nand_read_oob;
        mtd->_write_oob = nand_write_oob;
        mtd->_sync = nand_sync;
-       mtd->_lock = NULL;
-       mtd->_unlock = NULL;
+       mtd->_lock = nand_lock;
+       mtd->_unlock = nand_unlock;
        mtd->_suspend = nand_suspend;
        mtd->_resume = nand_resume;
        mtd->_reboot = nand_shutdown;
@@ -5907,6 +5950,8 @@ void nand_cleanup(struct nand_chip *chip)
            chip->ecc.algo == NAND_ECC_BCH)
                nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
 
+       nanddev_cleanup(&chip->base);
+
        /* Free bad block table memory */
        kfree(chip->bbt);
        kfree(chip->data_buf);