Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Wait queue spinlock corruption and false completion due to concurrent complete() and init_completion() after a timeout.
--
commit c6cd2e78faa74b2944e87ef8eeedc8e3e99b27b5
Author: James Hilliard <james.hilliard1@gmail.com>
mtd: rawnand: sunxi: avoid duplicate chip setup before page commands
The page helpers invoke exec_op(), which selects the chip and programs
its timing and spare-area registers. Remove the identical setup directly
before those helpers in the read callbacks and PIO write callbacks.
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index dc5b3814657e7..0d829103b144b 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -1743,8 +1743,6 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
> int ret, i, cur_off = 0;
> bool erased_chunk_found = false;
>
> - sunxi_nfc_select_chip(nand, nand->cur_cs);
> -
> ret = nand_read_page_op(nand, page, 0, NULL, 0);
> if (ret)
> return ret;
[ ... ]
While reviewing this code, I noticed a separate issue in sunxi_nfc_wait_events():
drivers/mtd/nand/raw/sunxi_nand.c:sunxi_nfc_wait_events() {
...
if (!use_polling) {
init_completion(&nfc->complete);
...
}
[Severity: High]
This isn't a bug introduced by this patch, but is a pre-existing issue. Can
this lead to wait queue spinlock corruption and false completions?
If a NAND operation times out in sunxi_nfc_wait_events(), CPU A clears the
interrupt enable register and returns -ETIMEDOUT.
Concurrently, if the IRQ handler is delayed, CPU B executing
sunxi_nfc_interrupt() may read the active status before CPU A clears it, but
get preempted before calling complete().
CPU A then starts a new NAND operation and re-enters sunxi_nfc_wait_events():
drivers/mtd/nand/raw/sunxi_nand.c:sunxi_nfc_wait_events() {
...
if (!use_polling) {
init_completion(&nfc->complete);
...
}
When CPU B resumes and calls complete(), wouldn't it access and modify the
lock concurrently, causing lock corruption?
Furthermore, wouldn't it set the completion flag for the new command, causing
it to return prematurely and process garbage data?
Since there is no structural prevention like synchronize_irq() or
disable_irq() on the timeout path, does this need to be addressed?
@@ -1743,8 +1743,6 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
int ret, i, cur_off = 0;
bool erased_chunk_found = false;
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_read_page_op(nand, page, 0, NULL, 0);
if (ret)
return ret;
@@ -1793,8 +1791,6 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf,
{
int ret;
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_read_page_op(nand, page, 0, NULL, 0);
if (ret)
return ret;
@@ -1823,8 +1819,6 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand,
if (sunxi_nand->randomized_oob)
return sunxi_nfc_hw_ecc_read_page(nand, bufpoi, false, page);
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_read_page_op(nand, page, 0, NULL, 0);
if (ret)
return ret;
@@ -1865,8 +1859,6 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand,
if (to_sunxi_nand(nand)->randomized_oob)
return sunxi_nfc_hw_ecc_read_page_dma(nand, buf, false, page);
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_read_page_op(nand, page, 0, NULL, 0);
if (ret)
return ret;
@@ -1890,8 +1882,6 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret = 0, i, cur_off = 0;
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0);
if (ret)
return ret;
@@ -1935,8 +1925,6 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand,
struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret = 0, i, cur_off = 0;
- sunxi_nfc_select_chip(nand, nand->cur_cs);
-
ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0);
if (ret)
return ret;