* [PATCH] mtd: rawnand: use longest matching pattern
@ 2019-04-19 7:47 Stefan Agner
2019-05-20 14:31 ` Miquel Raynal
0 siblings, 1 reply; 2+ messages in thread
From: Stefan Agner @ 2019-04-19 7:47 UTC (permalink / raw)
To: bbrezillon, miquel.raynal
Cc: richard, dwmw2, computersforpeace, marek.vasut, linux-mtd,
linux-kernel, Stefan Agner, Sascha Hauer, Boris Brezillon
Sometimes the exec_op parser does not choose the optimal pattern if
multiple patterns with optional elements are available. Since the stack
automatically splits operations in multiple exec_op calls, a non-optimal
pattern gets broken up into multiple calls. E.g. an OOB read using the
vf610 driver:
nand: executing subop:
nand: ->CMD [0x00]
nand: ->ADDR [5 cyc: 00 08 ea 94 02]
nand: ->CMD [0x30]
nand: ->WAITRDY [max 200000 ms]
nand: DATA_IN [64 B]
nand: executing subop:
nand: CMD [0x00]
nand: ADDR [5 cyc: 00 08 ea 94 02]
nand: CMD [0x30]
nand: WAITRDY [max 200000 ms]
nand: ->DATA_IN [64 B]
However, the vf610 driver has a pattern which can execute the complete
command in a single go...
This patch makes sure that the longest matching pattern is chosen
instead of the first (potentially only partial) match. With this
change the vf610 reads the OOB in a single exec_op call:
nand: executing subop:
nand: ->CMD [0x00]
nand: ->ADDR [5 cyc: 00 08 c0 1d 00]
nand: ->CMD [0x30]
nand: ->WAITRDY [max 200000 ms]
nand: ->DATA_IN [64 B]
Reported-by: Sascha Hauer <s.hauer@pengutronix.de>
Suggested-by: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
drivers/mtd/nand/raw/nand_base.c | 50 +++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index ddd396e93e32..ebf219c05853 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -2131,6 +2131,22 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
}
#endif
+static int nand_op_parser_cmp_ctx(const struct nand_op_parser_ctx *a,
+ const struct nand_op_parser_ctx *b)
+{
+ if (a->subop.ninstrs < b->subop.ninstrs)
+ return -1;
+ else if (a->subop.ninstrs > b->subop.ninstrs)
+ return 1;
+
+ if (a->subop.last_instr_end_off < b->subop.last_instr_end_off)
+ return -1;
+ else if (a->subop.last_instr_end_off > b->subop.last_instr_end_off)
+ return 1;
+
+ return 0;
+}
+
/**
* nand_op_parser_exec_op - exec_op parser
* @chip: the NAND chip
@@ -2165,32 +2181,40 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
unsigned int i;
while (ctx.subop.instrs < op->instrs + op->ninstrs) {
- int ret;
+ const struct nand_op_parser_pattern *pattern;
+ struct nand_op_parser_ctx best_ctx;
+ int ret, best_pattern = -1;
for (i = 0; i < parser->npatterns; i++) {
- const struct nand_op_parser_pattern *pattern;
+ struct nand_op_parser_ctx test_ctx = ctx;
pattern = &parser->patterns[i];
- if (!nand_op_parser_match_pat(pattern, &ctx))
+ if (!nand_op_parser_match_pat(pattern, &test_ctx))
continue;
- nand_op_parser_trace(&ctx);
-
- if (check_only)
- break;
-
- ret = pattern->exec(chip, &ctx.subop);
- if (ret)
- return ret;
+ if (best_pattern >= 0 &&
+ nand_op_parser_cmp_ctx(&test_ctx, &best_ctx) <= 0)
+ continue;
- break;
+ best_pattern = i;
+ best_ctx = test_ctx;
}
- if (i == parser->npatterns) {
+ if (best_pattern < 0) {
pr_debug("->exec_op() parser: pattern not found!\n");
return -ENOTSUPP;
}
+ ctx = best_ctx;
+ nand_op_parser_trace(&ctx);
+
+ if (!check_only) {
+ pattern = &parser->patterns[best_pattern];
+ ret = pattern->exec(chip, &ctx.subop);
+ if (ret)
+ return ret;
+ }
+
/*
* Update the context structure by pointing to the start of the
* next subop.
--
2.21.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] mtd: rawnand: use longest matching pattern
2019-04-19 7:47 [PATCH] mtd: rawnand: use longest matching pattern Stefan Agner
@ 2019-05-20 14:31 ` Miquel Raynal
0 siblings, 0 replies; 2+ messages in thread
From: Miquel Raynal @ 2019-05-20 14:31 UTC (permalink / raw)
To: Stefan Agner
Cc: bbrezillon, richard, dwmw2, computersforpeace, marek.vasut,
linux-mtd, linux-kernel, Sascha Hauer, Boris Brezillon
Hi Stefan,
Stefan Agner <stefan@agner.ch> wrote on Fri, 19 Apr 2019 09:47:17 +0200:
> Sometimes the exec_op parser does not choose the optimal pattern if
> multiple patterns with optional elements are available. Since the stack
> automatically splits operations in multiple exec_op calls, a non-optimal
> pattern gets broken up into multiple calls. E.g. an OOB read using the
> vf610 driver:
> nand: executing subop:
> nand: ->CMD [0x00]
> nand: ->ADDR [5 cyc: 00 08 ea 94 02]
> nand: ->CMD [0x30]
> nand: ->WAITRDY [max 200000 ms]
> nand: DATA_IN [64 B]
> nand: executing subop:
> nand: CMD [0x00]
> nand: ADDR [5 cyc: 00 08 ea 94 02]
> nand: CMD [0x30]
> nand: WAITRDY [max 200000 ms]
> nand: ->DATA_IN [64 B]
>
> However, the vf610 driver has a pattern which can execute the complete
> command in a single go...
>
> This patch makes sure that the longest matching pattern is chosen
> instead of the first (potentially only partial) match. With this
> change the vf610 reads the OOB in a single exec_op call:
> nand: executing subop:
> nand: ->CMD [0x00]
> nand: ->ADDR [5 cyc: 00 08 c0 1d 00]
> nand: ->CMD [0x30]
> nand: ->WAITRDY [max 200000 ms]
> nand: ->DATA_IN [64 B]
>
> Reported-by: Sascha Hauer <s.hauer@pengutronix.de>
> Suggested-by: Boris Brezillon <boris.brezillon@collabora.com>
> Tested-by: Stefan Agner <stefan@agner.ch>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
Applied, thanks.
Miquèl
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-05-20 14:31 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-19 7:47 [PATCH] mtd: rawnand: use longest matching pattern Stefan Agner
2019-05-20 14:31 ` Miquel Raynal
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).