From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Sascha Hauer <s.hauer@pengutronix.de>
Cc: kernel@pengutronix.de, Boris Brezillon <bbrezillon@kernel.org>,
Richard Weinberger <richard@nod.at>,
Vinod Koul <vkoul@kernel.org>,
linux-mtd@lists.infradead.org, NXP Linux Team <linux-imx@nxp.com>,
Fabio Estevam <festevam@gmail.com>, Han Xu <han.xu@nxp.com>,
Shawn Guo <shawnguo@kernel.org>
Subject: Re: [PATCH 14/14] mtd: rawnand: gpmi: Implement exec_op
Date: Wed, 17 Apr 2019 12:33:55 +0200 [thread overview]
Message-ID: <20190417123355.529297e2@xps13> (raw)
In-Reply-To: <20190409113421.3037-15-s.hauer@pengutronix.de>
Hi Sascha,
Sascha Hauer <s.hauer@pengutronix.de> wrote on Tue, 9 Apr 2019
13:34:21 +0200:
> The gpmi driver performance suffers from nand operations being split
> in multiple small dma transfers. This has been forced by the nand layer
> in the former days, but now with exec_op we can use the controller as
> intended.
>
> With this patch gpmi_nfc_exec_op becomes the main entry point to nand
> operations. Here all instructions are collected and chained as separate
> DMA transfers. In the end whole chain is fired and waited to be
> finished. gpmi_nfc_exec_op only does the hardware operations, bad block
> marker swapping and buffer scrambling is done by the callers. It's worth
> noting that the nand_*_op functions always take the buffer lengths for
> the data that the nand chip actually transfers. When doing BCH we have
> to calculate the net data size from the raw data size in some places.
>
> This patch has been tested with 2048/64 and 2048/128 byte nand on
> i.MX6q. mtd_oobtest, mtd_subpagetest and mtd_speedtest run without
> errors. nandbiterrs, nandpagetest and nandsubpagetest userspace tests
> from mtdutils run without errors and UBIFS can successfully be mounted.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/dma/mxs-dma.c | 3 +
[...]
> +static int gpmi_nfc_exec_op(struct nand_chip *chip,
> + const struct nand_operation *op,
> + bool check_only)
> +{
> + const struct nand_op_instr *instr;
> + struct gpmi_nand_data *this = nand_get_controller_data(chip);
> + struct dma_async_tx_descriptor *desc = NULL;
> + int i, ret, buf_len = 0, nbufs = 0;
> + u8 cmd = 0;
> + void *buf_read = NULL;
> + const void *buf_write = NULL;
> + bool direct = false;
> + struct completion *completion;
> + unsigned long to;
> +
> + this->ntransfers = 0;
> + for (i = 0; i < GPMI_MAX_TRANSFERS; i++)
> + this->transfers[i].direction = DMA_NONE;
> +
> + ret = pm_runtime_get_sync(this->dev);
> + if (ret < 0)
> + return ret;
> +
> + /*
> + * This driver currently supports only one NAND chip. Plus, dies share
> + * the same configuration. So once timings have been applied on the
> + * controller side, they will not change anymore. When the time will
> + * come, the check on must_apply_timings will have to be dropped.
> + */
> + if (this->hw.must_apply_timings) {
> + this->hw.must_apply_timings = false;
> + gpmi_nfc_apply_timings(this);
> + }
> +
> + dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
> +
> + for (i = 0; i < op->ninstrs; i++) {
> + instr = &op->instrs[i];
> +
> + nand_op_trace(" ", instr);
> +
> + switch (instr->type) {
> + case NAND_OP_WAITRDY_INSTR:
> + desc = gpmi_chain_wait_ready(this);
> + break;
> + case NAND_OP_CMD_INSTR:
> + cmd = instr->ctx.cmd.opcode;
> +
> + /*
> + * When this command has an address cycle chain it
> + * together with the address cycle
> + */
> + if (i + 1 != op->ninstrs &&
> + op->instrs[i + 1].type == NAND_OP_ADDR_INSTR)
> + continue;
> +
> + desc = gpmi_chain_command(this, cmd, NULL, 0);
> +
> + break;
> + case NAND_OP_ADDR_INSTR:
> + desc = gpmi_chain_command(this, cmd, instr->ctx.addr.addrs,
> + instr->ctx.addr.naddrs);
> + break;
> + case NAND_OP_DATA_OUT_INSTR:
> + buf_write = instr->ctx.data.buf.out;
> + buf_len = instr->ctx.data.len;
> + nbufs++;
> +
> + desc = gpmi_chain_data_write(this, buf_write, buf_len);
> +
> + break;
> + case NAND_OP_DATA_IN_INSTR:
> + if (!instr->ctx.data.len)
> + break;
> + buf_read = instr->ctx.data.buf.in;
> + buf_len = instr->ctx.data.len;
> + nbufs++;
> +
> + desc = gpmi_chain_data_read(this, buf_read, buf_len,
> + &direct);
> + break;
> + }
So there is no limitation for the controller in terms of
address/data cycles that can be asserted in one go?
> +
> + if (!desc) {
> + ret = -ENXIO;
> + goto unmap;
> + }
> + }
> +
> + dev_dbg(this->dev, "%s setup done\n", __func__);
> +
> + if (nbufs > 1) {
> + dev_err(this->dev, "Multiple data instructions not supported\n");
> + ret = -EINVAL;
> + goto unmap;
> + }
> +
> + if (this->bch) {
> + writel(this->bch_flashlayout0,
> + this->resources.bch_regs + HW_BCH_FLASH0LAYOUT0);
> + writel(this->bch_flashlayout1,
> + this->resources.bch_regs + HW_BCH_FLASH0LAYOUT1);
> + }
> +
> + if (this->bch && buf_read) {
> + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
> + this->resources.bch_regs + HW_BCH_CTRL_SET);
> + completion = &this->bch_done;
> + } else {
> + desc->callback = dma_irq_callback;
> + desc->callback_param = this;
> + completion = &this->dma_done;
> + }
> +
> + init_completion(completion);
> +
> + dmaengine_submit(desc);
> + dma_async_issue_pending(get_dma_chan(this));
> +
> + to = wait_for_completion_timeout(completion, msecs_to_jiffies(1000));
> + if (!to) {
> + dev_err(this->dev, "DMA timeout, last DMA\n");
> + gpmi_dump_info(this);
> + ret = -ETIMEDOUT;
> + goto unmap;
> + }
> +
> + writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
> + this->resources.bch_regs + HW_BCH_CTRL_CLR);
> + gpmi_clear_bch(this);
> +
> + ret = 0;
> +
> +unmap:
> + for (i = 0; i < this->ntransfers; i++) {
> + struct gpmi_transfer *transfer = &this->transfers[i];
> +
> + if (transfer->direction != DMA_NONE)
> + dma_unmap_sg(this->dev, &transfer->sgl, 1,
> + transfer->direction);
> + }
> +
> + if (!ret && buf_read && !direct)
> + memcpy(buf_read, this->data_buffer_dma,
> + gpmi_raw_len_to_len(this, buf_len));
> +
> + this->bch = false;
> +
> + pm_runtime_mark_last_busy(this->dev);
> + pm_runtime_put_autosuspend(this->dev);
> +
> + return ret;
> +}
> +
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2019-04-17 10:34 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-09 11:34 [PATCH v2 00/14] Implement exec_op for GPMI nand driver Sascha Hauer
2019-04-09 11:34 ` [PATCH 01/14] mtd: rawnand: export nand operation tracer Sascha Hauer
2019-04-17 10:22 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 02/14] mtd: rawnand: fsmc: Use nand_op_trace for operation tracing Sascha Hauer
2019-04-17 10:22 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 03/14] mtd: rawnand: gpmi: move all driver code into single file Sascha Hauer
2019-04-17 10:23 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 04/14] mtd: rawnand: gpmi: remove unused variable Sascha Hauer
2019-04-17 10:24 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 05/14] mtd: rawnand: gpmi: Remove unnecessary variables Sascha Hauer
2019-04-17 10:24 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 06/14] mtd: rawnand: gpmi: read buf in nand_read_page_op Sascha Hauer
2019-04-17 10:25 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 07/14] mtd: rawnand: gpmi: remove unused parameters Sascha Hauer
2019-04-17 10:26 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 08/14] mtd: rawnand: gpmi: Drop unnecessary restoring of previous chipselection Sascha Hauer
2019-04-17 10:27 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 09/14] mtd: rawnand: gpmi: use runtime PM to manage clocks Sascha Hauer
2019-04-17 10:28 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 10/14] dma: mxs: Drop unnecessary flag Sascha Hauer
2019-04-17 8:16 ` Miquel Raynal
2019-04-23 5:21 ` Vinod Koul
2019-04-23 5:22 ` Vinod Koul
2019-04-09 11:34 ` [PATCH 11/14] mtd: rawnand: gpmi: drop " Sascha Hauer
2019-04-17 10:28 ` Miquel Raynal
2019-04-09 11:34 ` [PATCH 12/14] dma: mxs: Add header file to be shared with gpmi nand driver Sascha Hauer
2019-04-23 5:24 ` Vinod Koul
2019-04-09 11:34 ` [PATCH 13/14] dma: mxs: rename custom flag Sascha Hauer
2019-04-23 5:25 ` Vinod Koul
2019-04-09 11:34 ` [PATCH 14/14] mtd: rawnand: gpmi: Implement exec_op Sascha Hauer
2019-04-17 10:33 ` Miquel Raynal [this message]
2019-04-24 7:09 ` Sascha Hauer
2019-04-29 7:23 ` Miquel Raynal
2019-04-25 12:56 [PATCH v3 00/14] Implement exec_op for GPMI nand driver Sascha Hauer
2019-04-25 12:56 ` [PATCH 14/14] mtd: rawnand: gpmi: Implement exec_op Sascha Hauer
2019-05-21 7:06 [PATCH v4 00/14] Implement exec_op for GPMI nand driver Sascha Hauer
2019-05-21 7:06 ` [PATCH 14/14] mtd: rawnand: gpmi: Implement exec_op Sascha Hauer
2019-06-03 8:02 ` Miquel Raynal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190417123355.529297e2@xps13 \
--to=miquel.raynal@bootlin.com \
--cc=bbrezillon@kernel.org \
--cc=festevam@gmail.com \
--cc=han.xu@nxp.com \
--cc=kernel@pengutronix.de \
--cc=linux-imx@nxp.com \
--cc=linux-mtd@lists.infradead.org \
--cc=richard@nod.at \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).