[PATCH] commands: mmc_extcsd: split background operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The current implementation of the  `mmc_extcsd -b` subcommand enables
manual background operations and automatic background operations if
available, which is unexpected and can be problematic:

With the eMMC JEDEC Standard 4.41 eMMCs gained support for decoupling
internal maintenance operations from foreground operations like read and
write commands. This is feature is called background operations. This
allows the host to manually trigger these maintenance operations e.g.
during idle times.

The advantages are reduced latencies during regular reads and writes. If
the host doesn't schedule these maintenance operations the standard
suggest[1] that they will be executed during foreground operations once
the maintenance level `critical` is reached. Thus enabling manual
background operations is a safe opt-in which resorts to maintenance
during foreground operations, even if the host isn't aware of the
enablement and doesn't start them at all.

With JEDEC standard 5.1 eMMCs gained support for schedueling these
background operations autonomously at their own will. This *not* a safe
opt-in as it needs support from the host:

> When AUTO_EN bit is set, the host should keep the device power active.

As there is no register to query the current status of a background
operation, the safe way seems to issue a power off notification and wait
for completion. This might not be implemented by the host.

This commit refactors the `mmc_extcsd -b` subcommand to only set the
`MANUAL_EN` bit, which is a safe default.

To still allow the enablement of  automatic background operations the
new `mmc_extcsd -B` subcommand is introduced which sets `MANUAL_EN` and
`AUTO_EN` bits.

[1]: See JEDEC Standard No. 84-B51, Page 93, 6.6.25 Background
Operations

Signed-off-by: Stefan Kerkmann <s.kerkmann@xxxxxxxxxxxxxx>
---
 commands/Kconfig      |  9 ++++++---
 commands/mmc_extcsd.c | 20 +++++++++++++++-----
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/commands/Kconfig b/commands/Kconfig
index 4a04868611..c186568fae 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -325,14 +325,17 @@ config CMD_MMC_EXTCSD
 	help
 	  Read or write the extended CSD register of a MMC device.
 
-	  Usage: mmc_extcsd dev [-r | -i index [-r | -v value -y]]
-
+	  Usage: mmc_extcsd dev [-r | -b | -B | -i index [-r | -v value [-y]]]
+	  
 	  Options:
 		  -i      field index of the register
 		  -r      print the register as raw data
 		  -v      value which will be written
 		  -y      don't request when writing to one time programmable fields
-		  __CAUTION__: this could damage the device!
+			  __CAUTION__: this could damage the device!
+		  -b      set bkops-enable (EXT_CSD_BKOPS_EN[163])
+		  -B      set bkops-enable and auto-enable (EXT_CSD_BKOPS_EN[163])
+			  __WARNING__: this is a write-once setting!
 
 config CMD_POLLER
 	tristate
diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c
index 993a6dd12b..7fa6235a4d 100644
--- a/commands/mmc_extcsd.c
+++ b/commands/mmc_extcsd.c
@@ -2379,7 +2379,7 @@ static int do_mmc_extcsd(int argc, char *argv[])
 	if (argc < 2)
 		return COMMAND_ERROR_USAGE;
 
-	while ((opt = getopt(argc, argv, "i:v:yrb")) > 0)
+	while ((opt = getopt(argc, argv, "i:v:yrbB")) > 0)
 		switch (opt) {
 		case 'i':
 			index = simple_strtoul(optarg, NULL, 0);
@@ -2401,6 +2401,13 @@ static int do_mmc_extcsd(int argc, char *argv[])
 			write_operation = 1;
 			always_write = 1;
 			break;
+		case 'B':
+			set_bkops_en = 1;
+			index = EXT_CSD_BKOPS_EN;
+			value = BIT(0) | BIT(1);
+			write_operation = 1;
+			always_write = 1;
+			break;
 		}
 
 	if (optind == argc)
@@ -2431,13 +2438,15 @@ static int do_mmc_extcsd(int argc, char *argv[])
 	}
 
 	if (set_bkops_en) {
-		if (dst[index]) {
+		if (dst[index] == value) {
 			printf("Abort: EXT_CSD [%u] already set to %#02x!\n",
 			       index, dst[index]);
 			goto error_with_mem;
 		}
-		if (dst[EXT_CSD_REV] >= 7)
-			value |= BIT(1);	/* set AUTO_EN bit too */
+
+		if (value & BIT(1)) {
+			pr_notice("Enabling automatic background operations, this needs support from the OS.\n");
+		}
 	}
 
 	if (write_operation)
@@ -2486,13 +2495,14 @@ BAREBOX_CMD_HELP_OPT("-v", "value which will be written")
 BAREBOX_CMD_HELP_OPT("-y", "don't request when writing to one time programmable fields")
 BAREBOX_CMD_HELP_OPT("",   "__CAUTION__: this could damage the device!")
 BAREBOX_CMD_HELP_OPT("-b", "set bkops-enable (EXT_CSD_BKOPS_EN[163])")
+BAREBOX_CMD_HELP_OPT("-B", "set bkops-enable and auto-enable (EXT_CSD_BKOPS_EN[163])")
 BAREBOX_CMD_HELP_OPT("",   "__WARNING__: this is a write-once setting!")
 BAREBOX_CMD_HELP_END
 
 BAREBOX_CMD_START(mmc_extcsd)
 	.cmd		= do_mmc_extcsd,
 	BAREBOX_CMD_DESC("Read/write the extended CSD register.")
-	BAREBOX_CMD_OPTS("dev [-r | -b | -i index [-r | -v value [-y]]]")
+	BAREBOX_CMD_OPTS("dev [-r | -b | -B | -i index [-r | -v value [-y]]]")
 	BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
 	BAREBOX_CMD_HELP(cmd_mmc_extcsd_help)
 BAREBOX_CMD_END

---
base-commit: a7e9f7f096b030962513eeea0e91e96f6e13ea40
change-id: 20241023-feature-emmc-background-ops-7451a7ec69c7

Best regards,
-- 
Stefan Kerkmann <s.kerkmann@xxxxxxxxxxxxxx>





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux