--- zzzz-none-000/linux-4.4.271/drivers/mtd/nand/nand_base.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/drivers/mtd/nand/nand_base.c 2023-04-19 10:22:29.000000000 +0000 @@ -92,6 +92,26 @@ .length = 78} } }; +static struct nand_ecclayout nand_oob_256 = { + .eccbytes = 96, + .eccpos = { + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255}, + .oobfree = { + {.offset = 2, + .length = 158} } +}; + static int nand_get_device(struct mtd_info *mtd, int new_state); static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, @@ -134,6 +154,13 @@ { struct nand_chip *chip = mtd->priv; + /* AVM */ +#ifdef CONFIG_TFFS_PANIC_LOG + /* We never release device in panic. */ + if (chip->ecc.get_tffs_panic_state && + unlikely(chip->ecc.get_tffs_panic_state(mtd))) + return; +#endif /* Release the controller and the chip */ spin_lock(&chip->controller->lock); chip->controller->active = NULL; @@ -317,9 +344,9 @@ * * Check, if the block is bad. */ -static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) { - int page, chipnr, res = 0, i = 0; + int page, res = 0, i = 0; struct nand_chip *chip = mtd->priv; u16 bad; @@ -328,15 +355,6 @@ page = (int)(ofs >> chip->page_shift) & chip->pagemask; - if (getchip) { - chipnr = (int)(ofs >> chip->chip_shift); - - nand_get_device(mtd, FL_READING); - - /* Select the NAND device */ - chip->select_chip(mtd, chipnr); - } - do { if (chip->options & NAND_BUSWIDTH_16) { chip->cmdfunc(mtd, NAND_CMD_READOOB, @@ -361,11 +379,6 @@ i++; } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); - if (getchip) { - chip->select_chip(mtd, -1); - nand_release_device(mtd); - } - return res; } @@ -394,7 +407,11 @@ } else { ops.len = ops.ooblen = 1; } - ops.mode = MTD_OPS_PLACE_OOB; + + if (unlikely(chip->bbt_options & NAND_BBT_ACCESS_BBM_RAW)) + ops.mode = MTD_OPS_RAW; + else + ops.mode = MTD_OPS_PLACE_OOB; /* Write to first/last page(s) if necessary */ if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) @@ -503,19 +520,17 @@ * nand_block_checkbad - [GENERIC] Check if a block is marked bad * @mtd: MTD device structure * @ofs: offset from device start - * @getchip: 0, if the chip is already selected * @allowbbt: 1, if its allowed to access the bbt area * * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. */ -static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, - int allowbbt) +static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) { struct nand_chip *chip = mtd->priv; if (!chip->bbt) - return chip->block_bad(mtd, ofs, getchip); + return chip->block_bad(mtd, ofs); /* Return info from the table */ return nand_isbad_bbt(mtd, ofs, allowbbt); @@ -841,6 +856,19 @@ spinlock_t *lock = &chip->controller->lock; wait_queue_head_t *wq = &chip->controller->wq; DECLARE_WAITQUEUE(wait, current); + + /* AVM */ +#if IS_ENABLED(CONFIG_TFFS_PANIC_LOG) && IS_ENABLED(CONFIG_TFFS_DEV_MTDNAND) + WARN_ONCE(!chip->ecc.get_tffs_panic_state, + "NAND: get_tffs_panic_state not set!\n"); + + /* Either now or never. */ + if (chip->ecc.get_tffs_panic_state && + unlikely(chip->ecc.get_tffs_panic_state(mtd))) { + panic_nand_get_device(chip, mtd, new_state); + return 0; + } +#endif retry: spin_lock(lock); @@ -917,7 +945,16 @@ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + + /* AVM */ +#ifdef CONFIG_TFFS_PANIC_LOG + if (in_interrupt() || oops_in_progress || ( + chip->ecc.get_tffs_panic_state && + unlikely(chip->ecc.get_tffs_panic_state(mtd)) + )) +#else if (in_interrupt() || oops_in_progress) +#endif panic_nand_wait(mtd, chip, timeo); else { timeo = jiffies + msecs_to_jiffies(timeo); @@ -1673,6 +1710,25 @@ return chip->setup_read_retry(mtd, retry_mode); } +static int get_read_page_count(struct mtd_info *mtd, + struct mtd_oob_ops *ops, loff_t to, uint32_t oob_per_page) +{ + struct nand_chip *chip = mtd->priv; + uint32_t start_page, end_page; + + if (ops->datbuf != NULL) { + start_page = to >> chip->page_shift; + end_page = (to + ops->len - 1) >> chip->page_shift; + return end_page - start_page + 1; + } else { + if (oob_per_page == 0) + return 0; + return (ops->ooblen + oob_per_page - 1) / oob_per_page; + } + + return 0; +} + /** * nand_do_read_ops - [INTERN] Read data with ECC * @mtd: MTD device structure @@ -1693,7 +1749,7 @@ mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; - int use_bufpoi; + int use_bufpoi, num_pages, req_pages; unsigned int max_bitflips = 0; int retry_mode = 0; bool ecc_fail = false; @@ -1710,11 +1766,61 @@ oob = ops->oobbuf; oob_required = oob ? 1 : 0; + if (readlen > mtd->writesize) + num_pages = get_read_page_count(mtd, ops, from, max_oobsize); + else + num_pages = 1; + pr_debug("Total no of pages :%d\n",num_pages); + req_pages = num_pages; + while (1) { unsigned int ecc_failures = mtd->ecc_stats.failed; - +#if IS_ENABLED(CONFIG_PAGE_SCOPE_MULTI_PAGE_READ) + int rem = 0; + if (num_pages == MAX_MULTI_PAGE) { + /* fully multi page alinged page */ + rem = (readlen % mtd->writesize); + req_pages = MAX_MULTI_PAGE; + bytes = (req_pages * mtd->writesize); + if (rem) { + req_pages = MAX_MULTI_PAGE - 1; + bytes = readlen; + } + aligned = (bytes == (mtd->writesize * req_pages)); + } else if (num_pages > MAX_MULTI_PAGE) { + req_pages = MAX_MULTI_PAGE; + bytes = (MAX_MULTI_PAGE * mtd->writesize); + if (num_pages == MAX_MULTI_PAGE + 1) { + rem = (readlen % mtd->writesize); + if (rem) { + req_pages = MAX_MULTI_PAGE - 1; + bytes = readlen; + } + } + aligned = (bytes == (mtd->writesize * MAX_MULTI_PAGE)); + } else if (num_pages > 1 && num_pages < MAX_MULTI_PAGE) { + /* this check, to not break the page scope read */ + req_pages = num_pages; + bytes = readlen; + rem = (readlen % mtd->writesize); + aligned = (bytes == (mtd->writesize * req_pages)); + if (rem) { + if (col != 0) { + req_pages = 1; + bytes = min(mtd->writesize - col, readlen); + aligned = (bytes == mtd->writesize); + } + } + } else if (num_pages == 1 || num_pages == 0) { + bytes = min(mtd->writesize - col, readlen); + aligned = (bytes == mtd->writesize); + } else { + pr_info("Wrong number of pages:%d\n", num_pages); + } +#else bytes = min(mtd->writesize - col, readlen); aligned = (bytes == mtd->writesize); +#endif if (!aligned) use_bufpoi = 1; @@ -1747,6 +1853,11 @@ ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi, page); +#if IS_ENABLED(CONFIG_PAGE_SCOPE_MULTI_PAGE_READ) + else if (num_pages > 1) + ret = chip->ecc.read_multi_page(mtd, chip, bufpoi, + oob_required, page, req_pages); +#endif else ret = chip->ecc.read_page(mtd, chip, bufpoi, oob_required, page); @@ -1826,14 +1937,25 @@ retry_mode = 0; } +#if IS_ENABLED(CONFIG_PAGE_SCOPE_MULTI_PAGE_READ) + if (!readlen || (int)readlen < 0) + break; +#else if (!readlen) break; - +#endif /* For subsequent reads align to page boundary */ col = 0; /* Increment page address */ +#if IS_ENABLED(CONFIG_PAGE_SCOPE_MULTI_PAGE_READ) + num_pages -= req_pages; + if (num_pages == 0) + realpage++; + else + realpage += req_pages; +#else realpage++; - +#endif page = realpage & chip->pagemask; /* Check, if we cross a chip boundary */ if (!page) { @@ -2929,7 +3051,7 @@ while (len) { /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << - chip->page_shift, 0, allowbbt)) { + chip->page_shift, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", __func__, page); instr->state = MTD_ERASE_FAILED; @@ -3016,7 +3138,20 @@ */ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) { - return nand_block_checkbad(mtd, offs, 1, 0); + struct nand_chip *chip = mtd_to_nand(mtd); + int chipnr = (int)(offs >> chip->chip_shift); + int ret; + + /* Select the NAND device */ + nand_get_device(mtd, FL_READING); + chip->select_chip(mtd, chipnr); + + ret = nand_block_checkbad(mtd, offs, 0); + + chip->select_chip(mtd, -1); + nand_release_device(mtd); + + return ret; } /** @@ -3752,7 +3887,13 @@ maf_id == NAND_MFR_AMD || maf_id == NAND_MFR_MACRONIX)) || (mtd->writesize == 2048 && - maf_id == NAND_MFR_MICRON)) + maf_id == NAND_MFR_MICRON) || + (mtd->writesize == 2048 && + maf_id == NAND_MFR_GIGA) || + (mtd->writesize == 2048 && + maf_id == NAND_MFR_MACRONIX) || + (mtd->writesize == 2048 && + maf_id == NAND_MFR_WINBOND)) chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; } @@ -3933,7 +4074,7 @@ *maf_id, *dev_id); if (chip->onfi_version) - pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + pr_info("ONFI %d-Compliant %s %s\n", chip->onfi_version, nand_manuf_ids[maf_idx].name, chip->onfi_params.model); else if (chip->jedec_version) pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, @@ -4098,14 +4239,18 @@ struct nand_chip *chip = mtd->priv; struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_buffers *nbuf; + int page_count = 1; /* New bad blocks should be marked in OOB, flash-based BBT, or both */ BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && !(chip->bbt_options & NAND_BBT_USE_FLASH)); - +#if IS_ENABLED(CONFIG_PAGE_SCOPE_MULTI_PAGE_READ) + page_count = (MAX_MULTI_PAGE + 1); +#endif if (!(chip->options & NAND_OWN_BUFFERS)) { - nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize - + mtd->oobsize * 3, GFP_KERNEL); + + nbuf = kzalloc(page_count * (sizeof(*nbuf) + mtd->writesize + + mtd->oobsize * 3), GFP_KERNEL); if (!nbuf) return -ENOMEM; nbuf->ecccalc = (uint8_t *)(nbuf + 1); @@ -4138,6 +4283,9 @@ case 128: ecc->layout = &nand_oob_128; break; + case 256: + ecc->layout = &nand_oob_256; + break; default: pr_warn("No oob scheme defined for oobsize %d\n", mtd->oobsize);