Message ID | 20180426154134.8270-10-sam.lefebvre@essensium.com |
---|---|
State | Changes Requested |
Delegated to: | Boris Brezillon |
Headers | show |
Series | [01/13] mtd: nand: gpmi: drop dma_ops_type | expand |
On Thu, 26 Apr 2018 17:41:30 +0200 Sam Lefebvre <sam.lefebvre@essensium.com> wrote: > To improve nand performance, the BCH interrupt bit must be polled > before waiting for occurence. This avoids an unnecessary context switch. > > Signed-off-by: Sam Lefebvre <sam.lefebvre@essensium.com> > --- > drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 17 +++++++++++++++-- > 1 file changed, 15 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > index 60bc1bac7741..28a2cf106ddc 100644 > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c > @@ -503,18 +503,31 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this, > * Actually, we must wait for two interrupts : > * [1] firstly the DMA interrupt and > * [2] secondly the BCH interrupt. > + * To improve performance, we first poll for the BCH > + * interrupt. > */ > int start_dma_with_bch_irq(struct gpmi_nand_data *this, > struct dma_async_tx_descriptor *desc) > { > struct completion *bch_c = &this->bch_done; > + struct resources *r = &this->resources; > unsigned long timeout; > > - /* Prepare to receive an interrupt from the BCH block. */ > - init_completion(bch_c); > + /* Disable interrupt */ > + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN, r->bch_regs + HW_BCH_CTRL_CLR); I'd prefer to have it disabled in the probe function. > > /* start the DMA */ > start_dma_without_bch_irq(this, desc); > + if (readl(r->bch_regs + HW_BCH_CTRL) & BM_BCH_CTRL_COMPLETE_IRQ) { > + writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR); > + return 0; > + } > + > + /* Prepare to receive an interrupt from the BCH block. */ > + init_completion(bch_c); > + > + /* Re-enable interrupt */ > + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN, r->bch_regs + HW_BCH_CTRL_SET); > > /* Wait for the interrupt from the BCH block. */ > timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000)); And then you can disable it here, so that the interrupt is only active when we need it.
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 60bc1bac7741..28a2cf106ddc 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -503,18 +503,31 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this, * Actually, we must wait for two interrupts : * [1] firstly the DMA interrupt and * [2] secondly the BCH interrupt. + * To improve performance, we first poll for the BCH + * interrupt. */ int start_dma_with_bch_irq(struct gpmi_nand_data *this, struct dma_async_tx_descriptor *desc) { struct completion *bch_c = &this->bch_done; + struct resources *r = &this->resources; unsigned long timeout; - /* Prepare to receive an interrupt from the BCH block. */ - init_completion(bch_c); + /* Disable interrupt */ + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN, r->bch_regs + HW_BCH_CTRL_CLR); /* start the DMA */ start_dma_without_bch_irq(this, desc); + if (readl(r->bch_regs + HW_BCH_CTRL) & BM_BCH_CTRL_COMPLETE_IRQ) { + writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR); + return 0; + } + + /* Prepare to receive an interrupt from the BCH block. */ + init_completion(bch_c); + + /* Re-enable interrupt */ + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN, r->bch_regs + HW_BCH_CTRL_SET); /* Wait for the interrupt from the BCH block. */ timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
To improve nand performance, the BCH interrupt bit must be polled before waiting for occurence. This avoids an unnecessary context switch. Signed-off-by: Sam Lefebvre <sam.lefebvre@essensium.com> --- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)