mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* Subject: [PATCH 1/1] nvme: add erase operation through sanitize command
@ 2025-01-16 10:52 Renaud Barbier
  2025-01-21  8:32 ` Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Renaud Barbier @ 2025-01-16 10:52 UTC (permalink / raw)
  To: Barebox List

Based on Linux nvme sanitize command and kernel driver, add the storage
low level block erase. This operation erases the entire device, any
user-specified size smaller than the storage size will result in an error.

Signed-off-by: Renaud Barbier <renaud.barbier@ametek.com>
---
 drivers/nvme/host/core.c | 82 ++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/pci.c  |  2 +
 include/nvme/types.h     | 38 +++++++++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 include/nvme/types.h

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 33a592caeb..fcc2167763 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <common.h>
+#include <nvme/types.h>
 
 #include "nvme.h"
 
@@ -64,6 +65,72 @@ nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
 	return ret;
 }
 
+static int
+nvme_sanitize_poll_log(struct nvme_ctrl *ctrl)
+{
+	struct nvme_sanitize_log_page *sanitize_log;
+	int log_size = sizeof(*sanitize_log);
+	uint64_t start = get_time_ns();
+	struct nvme_command c = { 0 };
+	uint32_t numd = (log_size >> 2) - 1;
+	uint16_t numdl = numd & 0xffff;
+	int ret;
+
+	sanitize_log = kmalloc(log_size, GFP_KERNEL);
+	if (!sanitize_log)
+		return -ENOMEM;
+
+	memset(sanitize_log, 0, log_size);
+
+	c.common.opcode = nvme_admin_get_log_page;
+	c.common.cdw10[0] = (numdl << 16) | NVME_LOG_LID_SANITIZE;
+	/* Poll the sanitize log for operation completion */
+	do {
+		ret = nvme_submit_sync_cmd(ctrl, &c, sanitize_log, log_size);
+		if (ret) {
+			dev_err(ctrl->dev, "Retrieving log failed\n");
+			goto out;
+		}
+
+		if ((sanitize_log->sstat & 0x3) == 3) {
+			dev_err(ctrl->dev, "Erase failed\n");
+			ret = -EIO;
+			goto out;
+		} else if (sanitize_log->sstat & 1) {
+			ret = 0;
+			goto out;
+		}
+		sanitize_log->sstat = 0;
+
+		mdelay(1000);
+	} while (!is_timeout(start, 30 * SECOND));
+	ret = -ETIME;
+out:
+	if (sanitize_log)
+		free(sanitize_log);
+	return ret;
+}
+
+/* Perform a low level block erase of the whole NVME device */
+static int
+nvme_sanitize_nvm(struct nvme_ctrl *ctrl)
+{
+	struct nvme_command c = { 0 };
+	int ret;
+
+	/* Input arguments based on what the kernel sets up for the cmd */
+	c.common.opcode = nvme_admin_sanitize_nvm;
+	c.common.cdw10[0] = NVME_SANITIZE_SANACT_START_BLOCK_ERASE;
+	ret = nvme_submit_sync_cmd(ctrl, &c, NULL, 0);
+	if (ret) {
+		dev_err(ctrl->dev,
+			"Failed to trigger the sanitize block erase command\n");
+		return -EINVAL;
+	}
+
+	return nvme_sanitize_poll_log(ctrl);
+}
+
 int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
 {
 	u32 q_count = (*count - 1) | ((*count - 1) << 16);
@@ -324,11 +391,26 @@ static int __maybe_unused nvme_block_device_flush(struct block_device *blk)
 				      0, 0, NVME_QID_IO);
 }
 
+static int __maybe_unused
+nvme_block_device_erase(struct block_device *blk, sector_t block,
+			blkcnt_t num_blocks)
+{
+	struct nvme_ns *ns = to_nvme_ns(blk);
+
+	if (block != 0 || num_blocks != blk->num_blocks) {
+		dev_err(ns->ctrl->dev, "The whole device must be erased\n");
+		return -ENOSYS;
+	}
+
+	return nvme_sanitize_nvm(ns->ctrl);
+}
+
 static struct block_device_ops nvme_block_device_ops = {
 	.read = nvme_block_device_read,
 #ifdef CONFIG_BLOCK_WRITE
 	.write = nvme_block_device_write,
 	.flush = nvme_block_device_flush,
+	.erase = nvme_block_device_erase,
 #endif
 };
 
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index e74a43b9aa..543be9a235 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -400,10 +400,12 @@ static int nvme_pci_submit_sync_cmd(struct nvme_ctrl *ctrl,
 		case nvme_admin_create_cq:
 		case nvme_admin_delete_sq:
 		case nvme_admin_delete_cq:
+		case nvme_admin_sanitize_nvm:
 		case nvme_admin_set_features:
 			dma_dir = DMA_TO_DEVICE;
 			break;
 		case nvme_admin_identify:
+		case nvme_admin_get_log_page:
 			dma_dir = DMA_FROM_DEVICE;
 			break;
 		default:
diff --git a/include/nvme/types.h b/include/nvme/types.h
new file mode 100644
index 0000000000..7b5aad1ca5
--- /dev/null
+++ b/include/nvme/types.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * This file is part of libnvme.
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ *
+ * Authors: Keith Busch <keith.busch@wdc.com>
+ *          Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
+ */
+#ifndef _LIBNVME_H
+#define _LIBNVME_H
+
+enum nvme_sanitize_sanact {
+	NVME_SANITIZE_SANACT_EXIT_FAILURE                       = 1,
+	NVME_SANITIZE_SANACT_START_BLOCK_ERASE                  = 2,
+	NVME_SANITIZE_SANACT_START_OVERWRITE                    = 3,
+	NVME_SANITIZE_SANACT_START_CRYPTO_ERASE                 = 4,
+	NVME_SANITIZE_SANACT_EXIT_MEDIA_VERIF                   = 5,
+};
+
+struct nvme_sanitize_log_page {
+	__le16  sprog;
+	__le16  sstat;
+	__le32  scdw10;
+	__le32  eto;
+	__le32  etbe;
+	__le32  etce;
+	__le32  etond;
+	__le32  etbend;
+	__le32  etcend;
+	__le32  etpvds;
+	__u8    ssi;
+	__u8    rsvd37[475];
+};
+
+enum nvme_cmd_get_log_lid {
+	NVME_LOG_LID_SANITIZE					= 0x81,
+};
+#endif /* _LIBNVME_TYPES_H */
-- 
2.34.1




^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Subject: [PATCH 1/1] nvme: add erase operation through sanitize command
  2025-01-16 10:52 Subject: [PATCH 1/1] nvme: add erase operation through sanitize command Renaud Barbier
@ 2025-01-21  8:32 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2025-01-21  8:32 UTC (permalink / raw)
  To: Barebox List, Renaud Barbier


On Thu, 16 Jan 2025 10:52:02 +0000, Renaud Barbier wrote:
> Based on Linux nvme sanitize command and kernel driver, add the storage
> low level block erase. This operation erases the entire device, any
> user-specified size smaller than the storage size will result in an error.
> 
> 

Applied, thanks!

[1/1] Subject: [PATCH 1/1] nvme: add erase operation through sanitize command
      https://git.pengutronix.de/cgit/barebox/commit/?id=3fd6cf7ca245 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-01-21  8:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-16 10:52 Subject: [PATCH 1/1] nvme: add erase operation through sanitize command Renaud Barbier
2025-01-21  8:32 ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox