forked from Minki/linux
mtd: rawnand: brcmnand: When oops in progress use pio and interrupt polling
If mtd_oops is in progress, switch to polling during NAND command completion instead of relying on DMA/interrupts so that the mtd_oops buffer can be completely written in the assigned NAND partition. Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
parent
9f897bfdd8
commit
c1ac2dc34b
@ -151,6 +151,7 @@ struct brcmnand_controller {
|
||||
u32 nand_cs_nand_xor;
|
||||
u32 corr_stat_threshold;
|
||||
u32 flash_dma_mode;
|
||||
bool pio_poll_mode;
|
||||
};
|
||||
|
||||
struct brcmnand_cfg {
|
||||
@ -815,6 +816,20 @@ static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
|
||||
return ctrl->flash_dma_base;
|
||||
}
|
||||
|
||||
static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
if (ctrl->pio_poll_mode)
|
||||
return;
|
||||
|
||||
if (has_flash_dma(ctrl)) {
|
||||
ctrl->flash_dma_base = 0;
|
||||
disable_irq(ctrl->dma_irq);
|
||||
}
|
||||
|
||||
disable_irq(ctrl->irq);
|
||||
ctrl->pio_poll_mode = true;
|
||||
}
|
||||
|
||||
static inline bool flash_dma_buf_ok(const void *buf)
|
||||
{
|
||||
return buf && !is_vmalloc_addr(buf) &&
|
||||
@ -1229,15 +1244,42 @@ static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat,
|
||||
/* intentionally left blank */
|
||||
}
|
||||
|
||||
static bool brcmstb_nand_wait_for_completion(struct nand_chip *chip)
|
||||
{
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
bool err = false;
|
||||
int sts;
|
||||
|
||||
if (mtd->oops_panic_write) {
|
||||
/* switch to interrupt polling and PIO mode */
|
||||
disable_ctrl_irqs(ctrl);
|
||||
sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
|
||||
NAND_CTRL_RDY, 0);
|
||||
err = (sts < 0) ? true : false;
|
||||
} else {
|
||||
unsigned long timeo = msecs_to_jiffies(
|
||||
NAND_POLL_STATUS_TIMEOUT_MS);
|
||||
/* wait for completion interrupt */
|
||||
sts = wait_for_completion_timeout(&ctrl->done, timeo);
|
||||
err = (sts <= 0) ? true : false;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmnand_waitfunc(struct nand_chip *chip)
|
||||
{
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
unsigned long timeo = msecs_to_jiffies(100);
|
||||
bool err = false;
|
||||
|
||||
dev_dbg(ctrl->dev, "wait on native cmd %d\n", ctrl->cmd_pending);
|
||||
if (ctrl->cmd_pending &&
|
||||
wait_for_completion_timeout(&ctrl->done, timeo) <= 0) {
|
||||
if (ctrl->cmd_pending)
|
||||
err = brcmstb_nand_wait_for_completion(chip);
|
||||
|
||||
if (err) {
|
||||
u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START)
|
||||
>> brcmnand_cmd_shift(ctrl);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user