Message ID | 20220417111622.621650-1-huobean@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,RESENT] mmc-utils: Add General command CMD56 read support | expand |
On Sun, 2022-04-17 at 13:16 +0200, Bean Huo wrote: > From: Bean Huo <beanhuo@micron.com> > > We can use GEN_CMD (CMD56) to read a data block with vendor-specific > format and meaning, which is very helpful and useful for customers to > analyze device health. This patch is to add support for this command. > > At the same time, in order to make CMD56 universal, let more users of > mmc-utils can benefit from this. We will allow the user to enter > [arg] > for special commands. Because some eMMC vendors provide an additional > set of commands beyond the GEN_CMD (CMD56) definition in the JEDEC > specification. These additional commands are implemented using > generic > CMD56 commands, and they return a wealth of useful information about > the > state of the NAND device. For these special purposes, the [31:1]stuff > bits in the CMD56 argument are used. You can refer to Micron eMMC > "TN-FC-32: e·MMC Device Health Report" as an example. > > I didn't add data parsing, just print the raw data as it is vendor- > specific. > > Signed-off-by: Bean Huo <beanhuo@micron.com> > Acked-by: Avri Altman <Avri.Altman@wdc.com> > Tested-by: Rossler Jakob (Nokia - DE/Ulm) <jakob.rossler@nokia.com> > --- Hi Ullf, Would you be willing to merge this patch into your mmc-utils git repo? Kind regards, Bean
On Fri, 22 Apr 2022 at 21:41, Bean Huo <huobean@gmail.com> wrote: > > On Sun, 2022-04-17 at 13:16 +0200, Bean Huo wrote: > > From: Bean Huo <beanhuo@micron.com> > > > > We can use GEN_CMD (CMD56) to read a data block with vendor-specific > > format and meaning, which is very helpful and useful for customers to > > analyze device health. This patch is to add support for this command. > > > > At the same time, in order to make CMD56 universal, let more users of > > mmc-utils can benefit from this. We will allow the user to enter > > [arg] > > for special commands. Because some eMMC vendors provide an additional > > set of commands beyond the GEN_CMD (CMD56) definition in the JEDEC > > specification. These additional commands are implemented using > > generic > > CMD56 commands, and they return a wealth of useful information about > > the > > state of the NAND device. For these special purposes, the [31:1]stuff > > bits in the CMD56 argument are used. You can refer to Micron eMMC > > "TN-FC-32: e·MMC Device Health Report" as an example. > > > > I didn't add data parsing, just print the raw data as it is vendor- > > specific. > > > > Signed-off-by: Bean Huo <beanhuo@micron.com> > > Acked-by: Avri Altman <Avri.Altman@wdc.com> > > Tested-by: Rossler Jakob (Nokia - DE/Ulm) <jakob.rossler@nokia.com> > > --- > > Hi Ullf, > > Would you be willing to merge this patch into your mmc-utils git repo? Certainly! My apologies for the delay! Applied to mmc-utils.git master, thanks! Kind regards Uffe
diff --git a/mmc.c b/mmc.c index eb2638b12271..6c563879cf1a 100644 --- a/mmc.c +++ b/mmc.c @@ -237,6 +237,14 @@ static struct Command commands[] = { "secure-trim1 | secure-trim2 | trim \n", NULL }, + { do_general_cmd_read, -1, + "gen_cmd read", "<device> [arg]\n" + "Send GEN_CMD (CMD56) to read vendor-specific format/meaning data from <device>\n\n" + "NOTE!: [arg] is optional and defaults to 0x1. If [arg] is specified, then [arg]\n" + "must be a 32-bit hexadecimal number, prefixed with 0x/0X. And bit0 in [arg] must\n" + "be 1.", + NULL + }, { 0, 0, 0, 0 } }; diff --git a/mmc.h b/mmc.h index 25d6864ac76f..b621374a1ed1 100644 --- a/mmc.h +++ b/mmc.h @@ -41,6 +41,8 @@ [1] Discard Enable [0] Identify Write Blocks for Erase (or TRIM Enable) R1b */ +#define MMC_GEN_CMD 56 /* adtc [31:1] stuff bits. + [0]: RD/WR1 R1 */ #define R1_OUT_OF_RANGE (1 << 31) /* er, c */ #define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ diff --git a/mmc_cmds.c b/mmc_cmds.c index 49d3e324d266..bb0f0226bf23 100644 --- a/mmc_cmds.c +++ b/mmc_cmds.c @@ -2981,3 +2981,60 @@ out: return ret; #endif } + +int do_general_cmd_read(int nargs, char **argv) +{ + int dev_fd; + char *device; + char *endptr; + __u8 buf[512]; + __u32 arg = 0x01; + int ret = -EINVAL, i; + struct mmc_ioc_cmd idata; + + if (nargs != 2 && nargs != 3) { + fprintf(stderr, "Usage: gen_cmd read </path/to/mmcblkX> [arg]\n"); + exit(1); + } + + device = argv[1]; + dev_fd = open(device, O_RDWR); + if (dev_fd < 0) { + perror("device open failed"); + exit(1); + } + + /* arg is specified */ + if (nargs == 3) { + arg = strtol(argv[2], &endptr, 16); + if (errno != 0 || *endptr != '\0' || !(arg & 0x1)) { + fprintf(stderr, "Wrong ARG, it should be Hex number and bit0 must be 1\n"); + goto out; + } + } + + memset(&idata, 0, sizeof(idata)); + idata.write_flag = 0; + idata.opcode = MMC_GEN_CMD; + idata.arg = arg; + idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + idata.blksz = 512; + idata.blocks = 1; + mmc_ioc_cmd_set_data(idata, buf); + + ret = ioctl(dev_fd, MMC_IOC_CMD, &idata); + if (ret) { + perror("ioctl"); + goto out; + } + + printf("Data:\n"); + for (i = 0; i < 512; i++) { + printf("%2x ", buf[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } +out: + close(dev_fd); + return ret; +} diff --git a/mmc_cmds.h b/mmc_cmds.h index 8331ab2373fd..0f7c0041f753 100644 --- a/mmc_cmds.h +++ b/mmc_cmds.h @@ -46,3 +46,4 @@ int do_read_scr(int argc, char **argv); int do_read_cid(int argc, char **argv); int do_read_csd(int argc, char **argv); int do_erase(int nargs, char **argv); +int do_general_cmd_read(int nargs, char **argv);