lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240522110909.10060-9-victorshihgli@gmail.com>
Date: Wed, 22 May 2024 19:08:54 +0800
From: Victor Shih <victorshihgli@...il.com>
To: ulf.hansson@...aro.org,
	adrian.hunter@...el.com
Cc: linux-mmc@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	benchuanggli@...il.com,
	HL.Liu@...esyslogic.com.tw,
	Greg.tu@...esyslogic.com.tw,
	takahiro.akashi@...aro.org,
	dlunev@...omium.org,
	Victor Shih <victorshihgli@...il.com>,
	Ben Chuang <ben.chuang@...esyslogic.com.tw>,
	Victor Shih <victor.shih@...esyslogic.com.tw>
Subject: [PATCH V16 08/23] mmc: core: Support UHS-II Auto Command Error Recovery

From: Victor Shih <victor.shih@...esyslogic.com.tw>

Add UHS-II Auto Command Error Recovery functionality
into the MMC request processing flow.

Signed-off-by: Ben Chuang <ben.chuang@...esyslogic.com.tw>
Signed-off-by: Victor Shih <victor.shih@...esyslogic.com.tw>
---

Updates in V16:
 - Separate the Error Recovery mechanism from patch#7 to patch#8.

---

 drivers/mmc/core/core.c    |  4 ++
 drivers/mmc/core/core.h    |  1 +
 drivers/mmc/core/sd_uhs2.c | 80 ++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/host.h   |  6 +++
 4 files changed, 91 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 68496c51a521..18642afc405f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -403,6 +403,10 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
 	while (1) {
 		wait_for_completion(&mrq->completion);
 
+		if (host->ops->get_cd(host))
+			if (mrq->cmd->error || (mrq->data && mrq->data->error))
+				mmc_sd_uhs2_error_recovery(host, mrq);
+
 		cmd = mrq->cmd;
 
 		if (!cmd->error || !cmd->retries ||
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 920323faa834..259d47c8bb19 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -82,6 +82,7 @@ int mmc_attach_mmc(struct mmc_host *host);
 int mmc_attach_sd(struct mmc_host *host);
 int mmc_attach_sdio(struct mmc_host *host);
 int mmc_attach_sd_uhs2(struct mmc_host *host);
+void mmc_sd_uhs2_error_recovery(struct mmc_host *mmc, struct mmc_request *mrq);
 
 /* Module parameters */
 extern bool use_spi_crc;
diff --git a/drivers/mmc/core/sd_uhs2.c b/drivers/mmc/core/sd_uhs2.c
index 85939a2582dc..d5acb4e6ccac 100644
--- a/drivers/mmc/core/sd_uhs2.c
+++ b/drivers/mmc/core/sd_uhs2.c
@@ -1324,3 +1324,83 @@ int mmc_attach_sd_uhs2(struct mmc_host *host)
 
 	return err;
 }
+
+static void sd_uhs2_abort_trans(struct mmc_host *mmc)
+{
+	struct mmc_request mrq = {};
+	struct mmc_command cmd = {0};
+	struct uhs2_command uhs2_cmd = {};
+	int err;
+
+	mrq.cmd = &cmd;
+	mmc->ongoing_mrq = &mrq;
+
+	uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD |
+			  mmc->card->uhs2_config.node_id;
+	uhs2_cmd.arg = ((UHS2_DEV_CMD_TRANS_ABORT & 0xFF) << 8) |
+			UHS2_NATIVE_CMD_WRITE |
+			(UHS2_DEV_CMD_TRANS_ABORT >> 8);
+
+	sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+	err = mmc_wait_for_cmd(mmc, &cmd, 0);
+
+	if (err)
+		pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+		       mmc_hostname(mmc), __func__, err);
+}
+
+static void sd_uhs2_abort_status_read(struct mmc_host *mmc)
+{
+	struct mmc_request mrq = {};
+	struct mmc_command cmd = {0};
+	struct uhs2_command uhs2_cmd = {};
+	int err;
+
+	mrq.cmd = &cmd;
+	mmc->ongoing_mrq = &mrq;
+
+	uhs2_cmd.header = UHS2_NATIVE_PACKET |
+			  UHS2_PACKET_TYPE_CCMD |
+			  mmc->card->uhs2_config.node_id;
+	uhs2_cmd.arg = ((UHS2_DEV_STATUS_REG & 0xFF) << 8) |
+			UHS2_NATIVE_CMD_READ |
+			UHS2_NATIVE_CMD_PLEN_4B |
+			(UHS2_DEV_STATUS_REG >> 8);
+
+	sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+	err = mmc_wait_for_cmd(mmc, &cmd, 0);
+
+	if (err)
+		pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+		       mmc_hostname(mmc), __func__, err);
+}
+
+void mmc_sd_uhs2_error_recovery(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	mmc->ops->uhs2_reset_cmd_data(mmc);
+
+	if (mrq->data) {
+		if (mrq->data->error && mmc_card_uhs2(mmc)) {
+			if (mrq->cmd) {
+				switch (mrq->cmd->error) {
+				case ETIMEDOUT:
+				case EILSEQ:
+				case EIO:
+					sd_uhs2_abort_trans(mmc);
+					sd_uhs2_abort_status_read(mmc);
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	} else {
+		if (mrq->cmd) {
+			switch (mrq->cmd->error) {
+			case ETIMEDOUT:
+				sd_uhs2_abort_trans(mmc);
+				break;
+			}
+		}
+	}
+}
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index fc9520b3bfa4..c914a58f7e1e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -271,6 +271,12 @@ struct mmc_host_ops {
 	 * negative errno in case of a failure or zero for success.
 	 */
 	int	(*uhs2_control)(struct mmc_host *host, enum sd_uhs2_operation op);
+
+	/*
+	 * The uhs2_reset_cmd_data callback is used to excute reset
+	 * when a auto command error occurs.
+	 */
+	void 	(*uhs2_reset_cmd_data)(struct mmc_host *host);
 };
 
 struct mmc_cqe_ops {
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ