Merge tag 'mtd/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
[sfrench/cifs-2.6.git] / drivers / mtd / nand / raw / nand_base.c
index 6eb131292eb2ce1316fb1c96e32b81e019ee9b27..91f046d4d452dbfd204ffc758969827b320d2dc0 100644 (file)
@@ -2111,35 +2111,7 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
                if (instr == &ctx->subop.instrs[0])
                        prefix = "    ->";
 
-               switch (instr->type) {
-               case NAND_OP_CMD_INSTR:
-                       pr_debug("%sCMD      [0x%02x]\n", prefix,
-                                instr->ctx.cmd.opcode);
-                       break;
-               case NAND_OP_ADDR_INSTR:
-                       pr_debug("%sADDR     [%d cyc: %*ph]\n", prefix,
-                                instr->ctx.addr.naddrs,
-                                instr->ctx.addr.naddrs < 64 ?
-                                instr->ctx.addr.naddrs : 64,
-                                instr->ctx.addr.addrs);
-                       break;
-               case NAND_OP_DATA_IN_INSTR:
-                       pr_debug("%sDATA_IN  [%d B%s]\n", prefix,
-                                instr->ctx.data.len,
-                                instr->ctx.data.force_8bit ?
-                                ", force 8-bit" : "");
-                       break;
-               case NAND_OP_DATA_OUT_INSTR:
-                       pr_debug("%sDATA_OUT [%d B%s]\n", prefix,
-                                instr->ctx.data.len,
-                                instr->ctx.data.force_8bit ?
-                                ", force 8-bit" : "");
-                       break;
-               case NAND_OP_WAITRDY_INSTR:
-                       pr_debug("%sWAITRDY  [max %d ms]\n", prefix,
-                                instr->ctx.waitrdy.timeout_ms);
-                       break;
-               }
+               nand_op_trace(prefix, instr);
 
                if (instr == &ctx->subop.instrs[ctx->subop.ninstrs - 1])
                        prefix = "      ";
@@ -2152,6 +2124,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
@@ -2186,32 +2174,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.