summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2025-01-10 15:45:25 +0100
committerMiquel Raynal <miquel.raynal@bootlin.com>2025-01-15 19:23:56 +0100
commit666c299be696f02c3354da104295fb94b8f65d25 (patch)
tree67d1dddbc5edbd7b49daf3ddfd091bff7a02b697
parent7ce0d16d5802bfde4209e52ee8ad644ca1eab423 (diff)
mtd: spinand: Enhance the logic when picking a variant
Currently the best variant picked in the first one in the list provided in the manufacturer driver. This worked well while all operations where performed at the same speed, but with the introduction of DTR transfers and per operation maximum frequencies, this no longer works correctly. Let's continue iterating over all the alternatives, even if we find a match, keeping a reference over the theoretically fastest operation. Only at the end we can tell which variant is the best. This logic happening only once at boot, the extra computing needed compared to the previous version is acceptable wrt. the expected improvements. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-rw-r--r--drivers/mtd/nand/spi/core.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 8af13c1c5110..da4713692674 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1213,10 +1213,13 @@ spinand_select_op_variant(struct spinand_device *spinand,
const struct spinand_op_variants *variants)
{
struct nand_device *nand = spinand_to_nand(spinand);
+ const struct spi_mem_op *best_variant = NULL;
+ u64 best_op_duration_ns = ULLONG_MAX;
unsigned int i;
for (i = 0; i < variants->nops; i++) {
struct spi_mem_op op = variants->ops[i];
+ u64 op_duration_ns = 0;
unsigned int nbytes;
int ret;
@@ -1235,13 +1238,17 @@ spinand_select_op_variant(struct spinand_device *spinand,
break;
nbytes -= op.data.nbytes;
+
+ op_duration_ns += spi_mem_calc_op_duration(&op);
}
- if (!nbytes)
- return &variants->ops[i];
+ if (!nbytes && op_duration_ns < best_op_duration_ns) {
+ best_op_duration_ns = op_duration_ns;
+ best_variant = &variants->ops[i];
+ }
}
- return NULL;
+ return best_variant;
}
/**