linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
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/

  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).