All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/2] mmc: support crash logging to MMC block devices
@ 2021-01-20 12:10 Bhaskara Budiredla
  2021-01-20 12:10 ` [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk Bhaskara Budiredla
  2021-01-20 12:10 ` [PATCH v5 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write Bhaskara Budiredla
  0 siblings, 2 replies; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-01-20 12:10 UTC (permalink / raw)
  To: ulf.hansson, keescook, ccross, tony.luck, sgoutham
  Cc: linux-mmc, linux-kernel, Bhaskara Budiredla

This patch introduces to mmcpstore.

v5:
 - Implement non-panic read/write support through pstore callbacks

v4:
 - Fix claiming host if host was already held or
   if the device claiming host is not runtime active

v3:
 - Justify new host ops requirement through commit msg
 - Remove 'default n' in Kconfig

v2:
 - Fix modpost issue with ARCH=sh
 - Fix usage of ifdefs in common functions
 - Add justification of new APIs to mmc_host_ops
 - Compile mmcpstore as part of mmc blk

v1: https://lore.kernel.org/linux-mmc/20201112062422.32212-1-bbudiredla@marvell.com/T/#t
v2: https://lore.kernel.org/linux-mmc/6762a763-5284-04dc-e636-486c74dedd34@alum.wpi.edu/T/#u
v3: https://lore.kernel.org/linux-mmc/20201207115753.21728-1-bbudiredla@marvell.com/T/#t
v4: https://lore.kernel.org/linux-mmc/20201223144033.32571-1-bbudiredla@marvell.com/T/#md9fce2de5b6aaa66e8ff7cb04d138a548426a8e3

Bhaskara Budiredla (2):
  mmc: Support kmsg dumper based on pstore/blk
  mmc: cavium: Add MMC polling method to support kmsg panic/oops write

 drivers/mmc/core/Kconfig           |  14 +-
 drivers/mmc/core/Makefile          |   1 +
 drivers/mmc/core/block.c           |  19 +++
 drivers/mmc/core/block.h           |   9 ++
 drivers/mmc/core/core.c            |  44 ++++++
 drivers/mmc/core/mmcpstore.c       | 227 +++++++++++++++++++++++++++++
 drivers/mmc/host/cavium-thunderx.c |  10 ++
 drivers/mmc/host/cavium.c          |  67 +++++++++
 drivers/mmc/host/cavium.h          |   3 +
 include/linux/mmc/core.h           |   5 +
 include/linux/mmc/host.h           |  12 ++
 11 files changed, 410 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/core/mmcpstore.c

-- 
2.17.1


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

* [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-01-20 12:10 [PATCH v5 0/2] mmc: support crash logging to MMC block devices Bhaskara Budiredla
@ 2021-01-20 12:10 ` Bhaskara Budiredla
  2021-01-20 15:06   ` Ulf Hansson
  2021-01-20 16:11     ` kernel test robot
  2021-01-20 12:10 ` [PATCH v5 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write Bhaskara Budiredla
  1 sibling, 2 replies; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-01-20 12:10 UTC (permalink / raw)
  To: ulf.hansson, keescook, ccross, tony.luck, sgoutham
  Cc: linux-mmc, linux-kernel, Bhaskara Budiredla

This patch introduces to mmcpstore. The functioning of mmcpstore
is similar to mtdpstore. mmcpstore works on FTL based flash devices
whereas mtdpstore works on raw flash devices. When the system crashes,
mmcpstore stores the kmsg panic and oops logs to a user specified
MMC device.

It collects the details about the host MMC device through pstore/blk
"blkdev" parameter. The user can specify the MMC device in many ways
by checking in Documentation/admin-guide/pstore-blk.rst.

The individual mmc host drivers have to define suitable polling and
cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
These new host operations are needed as pstore panic write runs with
interrupts disabled.

Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
---
 drivers/mmc/core/Kconfig     |  14 ++-
 drivers/mmc/core/Makefile    |   1 +
 drivers/mmc/core/block.c     |  19 +++
 drivers/mmc/core/block.h     |   9 ++
 drivers/mmc/core/core.c      |  44 +++++++
 drivers/mmc/core/mmcpstore.c | 227 +++++++++++++++++++++++++++++++++++
 include/linux/mmc/core.h     |   5 +
 include/linux/mmc/host.h     |  12 ++
 8 files changed, 330 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/core/mmcpstore.c

diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index c12fe13e4b14..4c651da4f2d2 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
 	  This driver can also be built as a module. If so, the module
 	  will be called pwrseq_simple.
 
+config MMC_PSTORE_BACKEND
+	bool "Log panic/oops to a MMC buffer"
+	depends on MMC_BLOCK
+	help
+	  This option will let you create platform backend to store kmsg
+	  crash dumps to a user specified MMC device. This is primarily
+	  based on pstore/blk.
+
+config MMC_PSTORE
+	tristate
+	select PSTORE_BLK
+
 config MMC_BLOCK
 	tristate "MMC block device driver"
 	depends on BLOCK
+	select MMC_PSTORE if MMC_PSTORE_BACKEND=y
 	default y
 	help
 	  Say Y here to enable the MMC block device driver support.
@@ -80,4 +93,3 @@ config MMC_TEST
 
 	  This driver is only of interest to those developing or
 	  testing a host driver. Most people should say N here.
-
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 95ffe008ebdf..7cb9a3af4827 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)	+= pwrseq_emmc.o
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
 obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
 mmc_block-objs			:= block.o queue.o
+mmc_block-$(CONFIG_MMC_PSTORE)	+= mmcpstore.o
 obj-$(CONFIG_MMC_TEST)		+= mmc_test.o
 obj-$(CONFIG_SDIO_UART)		+= sdio_uart.o
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 42e27a298218..6592722cd7b2 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card,
 
 #endif /* CONFIG_DEBUG_FS */
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size)
+{
+	struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+	struct gendisk *disk = md->disk;
+	struct disk_part_tbl *part_tbl = disk->part_tbl;
+
+	if (part_num < 0 || part_num >= part_tbl->len)
+		return 0;
+
+	*size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
+	return part_tbl->part[part_num]->start_sect;
+}
+#endif
+
 static int mmc_blk_probe(struct mmc_card *card)
 {
 	struct mmc_blk_data *md, *part_md;
@@ -2913,6 +2928,9 @@ static int mmc_blk_probe(struct mmc_card *card)
 			goto out;
 	}
 
+	if (mmc_card_mmc(card) || mmc_card_sd(card))
+		mmcpstore_card_set(card, md->disk->disk_name);
+
 	/* Add two debugfs entries */
 	mmc_blk_add_debugfs(card, md);
 
@@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
 	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
 	unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
 	bus_unregister(&mmc_rpmb_bus_type);
+	unregister_mmcpstore();
 }
 
 module_init(mmc_blk_init);
diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
index 31153f656f41..2a4ee5568194 100644
--- a/drivers/mmc/core/block.h
+++ b/drivers/mmc/core/block.h
@@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue *mq);
 struct work_struct;
 
 void mmc_blk_mq_complete_work(struct work_struct *work);
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size);
+void mmcpstore_card_set(struct mmc_card *card, const char *disk_name);
+void unregister_mmcpstore(void);
+#else
+static inline void mmcpstore_card_set(struct mmc_card *card,
+					const char *disk_name) {}
+static inline void unregister_mmcpstore(void) {}
+#endif
 
 #endif
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 19f1ee57fb34..7ad7ff1cab8c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_cqe_recovery);
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+/**
+ *	mmc_wait_for_pstore_req - initiate a blocking mmc request
+ *	@host: MMC host to start command
+ *	@mrq: MMC request to start
+ *
+ *	Start a blocking MMC request for a host and wait for the request
+ *	to complete that is based on polling and timeout.
+ */
+void mmc_wait_for_pstore_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+	unsigned int timeout;
+
+	host->ops->req_cleanup_pending(host);
+	mmc_start_request(host, mrq);
+
+	if (mrq->data) {
+		timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
+		host->ops->req_completion_poll(host, timeout);
+	}
+}
+EXPORT_SYMBOL(mmc_wait_for_pstore_req);
+#endif
+
 /**
  *	mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is done
  *	@host: MMC host
@@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx,
 }
 EXPORT_SYMBOL(__mmc_claim_host);
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+/**
+ *	mmc_claim_host_async - claim host in atomic context
+ *	@host: mmc host to claim
+ *
+ *	This routine may be called in panic/oops scenarios.
+ *	Return zero with host claim success, else busy status.
+ */
+int mmc_claim_host_async(struct mmc_host *host)
+{
+	if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
+		host->claimed = 1;
+		return 0;
+	}
+
+	return -EBUSY;
+}
+EXPORT_SYMBOL(mmc_claim_host_async);
+#endif
+
 /**
  *	mmc_release_host - release a host
  *	@host: mmc host to release
diff --git a/drivers/mmc/core/mmcpstore.c b/drivers/mmc/core/mmcpstore.c
new file mode 100644
index 000000000000..f783ea215f18
--- /dev/null
+++ b/drivers/mmc/core/mmcpstore.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMC pstore support based on pstore/blk
+ *
+ * Copyright (c) 2020 Marvell.
+ * Author: Bhaskara Budiredla <bbudiredla@marvell.com>
+ */
+
+#define pr_fmt(fmt) "mmcpstore: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pstore_blk.h>
+#include <linux/blkdev.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/scatterlist.h>
+#include "block.h"
+#include "card.h"
+#include "core.h"
+
+static struct mmcpstore_context {
+	char dev_name[BDEVNAME_SIZE];
+	int partno;
+	sector_t start_sect;
+	sector_t size;
+	struct pstore_blk_config conf;
+	struct pstore_blk_info info;
+
+	struct mmc_card	*card;
+	struct mmc_request *mrq;
+} oops_cxt;
+
+static void mmc_prep_req(struct mmc_request *mrq,
+		unsigned int sect_offset, unsigned int nsects,
+		struct scatterlist *sg, u32 opcode, unsigned int flags)
+{
+	mrq->cmd->opcode = opcode;
+	mrq->cmd->arg = sect_offset;
+	mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	if (nsects == 1) {
+		mrq->stop = NULL;
+	} else {
+		mrq->stop->opcode = MMC_STOP_TRANSMISSION;
+		mrq->stop->arg = 0;
+		mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
+	}
+
+	mrq->data->blksz = SECTOR_SIZE;
+	mrq->data->blocks = nsects;
+	mrq->data->flags = flags;
+	mrq->data->sg = sg;
+	mrq->data->sg_len = 1;
+}
+
+static int mmcpstore_panic_write_req(const char *buf,
+		unsigned int nsects, unsigned int sect_offset)
+{
+	struct mmcpstore_context *cxt = &oops_cxt;
+	struct mmc_request *mrq = cxt->mrq;
+	struct mmc_card *card = cxt->card;
+	struct mmc_host *host = card->host;
+	struct scatterlist sg;
+	u32 opcode;
+	int ret;
+
+	opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK : MMC_WRITE_BLOCK;
+	mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode, MMC_DATA_WRITE);
+	sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
+	mmc_set_data_timeout(mrq->data, cxt->card);
+
+	ret = mmc_claim_host_async(host);
+	if (ret)
+		return ret;
+
+	mmc_wait_for_pstore_req(host, mrq);
+	return 0;
+}
+
+static int mmcpstore_panic_write(const char *buf, sector_t off, sector_t sects)
+{
+	struct mmcpstore_context *cxt = &oops_cxt;
+	int ret;
+
+	ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct block_device *mmcpstore_open_backend(const char *device)
+{
+	struct block_device *bdev;
+	dev_t devt;
+
+	bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
+	if (IS_ERR(bdev)) {
+		devt = name_to_dev_t(device);
+		if (devt == 0)
+			return ERR_PTR(-ENODEV);
+
+		bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
+		if (IS_ERR(bdev))
+			return bdev;
+	}
+
+	return bdev;
+}
+
+static void mmcpstore_close_backend(struct block_device *bdev)
+{
+	if (!bdev)
+		return;
+	blkdev_put(bdev, FMODE_READ);
+}
+
+void mmcpstore_card_set(struct mmc_card *card, const char *disk_name)
+{
+	struct mmcpstore_context *cxt = &oops_cxt;
+	struct pstore_blk_config *conf = &cxt->conf;
+	struct pstore_blk_info *info = &cxt->info;
+	struct block_device *bdev;
+	struct mmc_command *stop;
+	struct mmc_command *cmd;
+	struct mmc_request *mrq;
+	struct mmc_data *data;
+	int ret;
+
+	ret = pstore_blk_get_config(conf);
+	if (!conf->device[0]) {
+		pr_debug("psblk backend is empty\n");
+		return;
+	}
+
+	/* Multiple backend devices not allowed */
+	if (cxt->dev_name[0])
+		return;
+
+	bdev =  mmcpstore_open_backend(conf->device);
+	if (IS_ERR(bdev)) {
+		pr_err("%s failed to open with %ld\n",
+				conf->device, PTR_ERR(bdev));
+		return;
+	}
+
+	bdevname(bdev, cxt->dev_name);
+	cxt->partno = bdev->bd_part->partno;
+	mmcpstore_close_backend(bdev);
+
+	if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
+		return;
+
+	cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
+	if (!cxt->start_sect) {
+		pr_err("Non-existent partition %d selected\n", cxt->partno);
+		return;
+	}
+
+	/* Check for host mmc panic write polling function definitions */
+	if (!card->host->ops->req_cleanup_pending ||
+			!card->host->ops->req_completion_poll)
+		return;
+
+	cxt->card = card;
+
+	mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
+	if (!mrq)
+		goto out;
+
+	cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
+	if (!cmd)
+		goto free_mrq;
+
+	stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
+	if (!stop)
+		goto free_cmd;
+
+	data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
+	if (!data)
+		goto free_stop;
+
+	mrq->cmd = cmd;
+	mrq->data = data;
+	mrq->stop = stop;
+	cxt->mrq = mrq;
+
+	info->major = MMC_BLOCK_MAJOR;
+	info->flags = PSTORE_FLAGS_DMESG;
+	info->panic_write = mmcpstore_panic_write;
+	ret = register_pstore_blk(info);
+	if (ret) {
+		pr_err("%s registering with psblk failed (%d)\n",
+				cxt->dev_name, ret);
+		goto free_data;
+	}
+
+	pr_info("%s registered as psblk backend\n", cxt->dev_name);
+	return;
+
+free_data:
+	kfree(data);
+free_stop:
+	kfree(stop);
+free_cmd:
+	kfree(cmd);
+free_mrq:
+	kfree(mrq);
+out:
+	return;
+}
+
+void unregister_mmcpstore(void)
+{
+	struct mmcpstore_context *cxt = &oops_cxt;
+
+	unregister_pstore_blk(MMC_BLOCK_MAJOR);
+	kfree(cxt->mrq->data);
+	kfree(cxt->mrq->stop);
+	kfree(cxt->mrq->cmd);
+	kfree(cxt->mrq);
+	cxt->card = NULL;
+}
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 29aa50711626..53840a361b5a 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -166,6 +166,11 @@ struct mmc_request {
 
 struct mmc_card;
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+void mmc_wait_for_pstore_req(struct mmc_host *host, struct mmc_request *mrq);
+int mmc_claim_host_async(struct mmc_host *host);
+#endif
+
 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq);
 int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
 		int retries);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 01bba36545c5..ba9001498e03 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -178,6 +178,18 @@ struct mmc_host_ops {
 
 	/* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */
 	int	(*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios);
+
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	/*
+	 * The following two APIs are introduced to support mmcpstore
+	 * functionality. Cleanup API to terminate the ongoing and
+	 * pending requests before a panic write post, and polling API
+	 * to ensure that write succeeds before the Kernel dies.
+	 */
+	void	(*req_cleanup_pending)(struct mmc_host *host);
+	int	(*req_completion_poll)(struct mmc_host *host,
+				       unsigned long timeout);
+#endif
 };
 
 struct mmc_cqe_ops {
-- 
2.17.1


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

* [PATCH v5 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write
  2021-01-20 12:10 [PATCH v5 0/2] mmc: support crash logging to MMC block devices Bhaskara Budiredla
  2021-01-20 12:10 ` [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk Bhaskara Budiredla
@ 2021-01-20 12:10 ` Bhaskara Budiredla
  1 sibling, 0 replies; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-01-20 12:10 UTC (permalink / raw)
  To: ulf.hansson, keescook, ccross, tony.luck, sgoutham
  Cc: linux-mmc, linux-kernel, Bhaskara Budiredla

To enable the writing of panic and oops logs, a cavium specific MMC
polling method is defined and thereby ensure the functioning of mmcpstore.

Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
---
 drivers/mmc/host/cavium-thunderx.c | 10 +++++
 drivers/mmc/host/cavium.c          | 67 ++++++++++++++++++++++++++++++
 drivers/mmc/host/cavium.h          |  3 ++
 3 files changed, 80 insertions(+)

diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c
index 76013bbbcff3..83f25dd6820a 100644
--- a/drivers/mmc/host/cavium-thunderx.c
+++ b/drivers/mmc/host/cavium-thunderx.c
@@ -19,12 +19,22 @@
 
 static void thunder_mmc_acquire_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	if (!host->pstore)
+		down(&host->mmc_serializer);
+#else
 	down(&host->mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	if (!host->pstore)
+		up(&host->mmc_serializer);
+#else
 	up(&host->mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_int_enable(struct cvm_mmc_host *host, u64 val)
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
index c5da3aaee334..708bec9d0345 100644
--- a/drivers/mmc/host/cavium.c
+++ b/drivers/mmc/host/cavium.c
@@ -510,6 +510,66 @@ irqreturn_t cvm_mmc_interrupt(int irq, void *dev_id)
 	return IRQ_RETVAL(emm_int != 0);
 }
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+static int cvm_req_completion_poll(struct mmc_host *host, unsigned long msecs)
+{
+	struct cvm_mmc_slot *slot = mmc_priv(host);
+	struct cvm_mmc_host *cvm_host = slot->host;
+	u64 emm_int;
+
+	while (msecs) {
+		emm_int = readq(cvm_host->base + MIO_EMM_INT(cvm_host));
+
+		if (emm_int & MIO_EMM_INT_DMA_DONE)
+			return 0;
+		else if (emm_int & MIO_EMM_INT_DMA_ERR)
+			return -EIO;
+		mdelay(1);
+		msecs--;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void cvm_req_cleanup_pending(struct mmc_host *host)
+{
+	struct cvm_mmc_slot *slot = mmc_priv(host);
+	struct cvm_mmc_host *cvm_host = slot->host;
+	u64 fifo_cfg;
+	u64 dma_cfg;
+	u64 emm_int;
+
+	cvm_host->pstore = 1;
+
+	/* Clear pending DMA FIFO queue */
+	fifo_cfg = readq(cvm_host->dma_base + MIO_EMM_DMA_FIFO_CFG(cvm_host));
+	if (FIELD_GET(MIO_EMM_DMA_FIFO_CFG_COUNT, fifo_cfg))
+		writeq(MIO_EMM_DMA_FIFO_CFG_CLR,
+			cvm_host->dma_base + MIO_EMM_DMA_FIFO_CFG(cvm_host));
+
+	/* Clear ongoing DMA, if there is any */
+	dma_cfg = readq(cvm_host->dma_base + MIO_EMM_DMA_CFG(cvm_host));
+	if (dma_cfg & MIO_EMM_DMA_CFG_EN) {
+		dma_cfg |= MIO_EMM_DMA_CFG_CLR;
+		writeq(dma_cfg, cvm_host->dma_base +
+				MIO_EMM_DMA_CFG(cvm_host));
+		do {
+			dma_cfg = readq(cvm_host->dma_base +
+					MIO_EMM_DMA_CFG(cvm_host));
+		} while (dma_cfg & MIO_EMM_DMA_CFG_EN);
+	}
+
+	/* Clear pending DMA interrupts */
+	emm_int = readq(cvm_host->base + MIO_EMM_INT(cvm_host));
+	if (emm_int)
+		writeq(emm_int, cvm_host->base + MIO_EMM_INT(cvm_host));
+
+	/* Clear prepared and yet to be fired DMA requests */
+	cvm_host->current_req = NULL;
+	cvm_host->dma_active = false;
+}
+#endif
+
 /*
  * Program DMA_CFG and if needed DMA_ADR.
  * Returns 0 on error, DMA address otherwise.
@@ -901,6 +961,10 @@ static const struct mmc_host_ops cvm_mmc_ops = {
 	.set_ios        = cvm_mmc_set_ios,
 	.get_ro		= mmc_gpio_get_ro,
 	.get_cd		= mmc_gpio_get_cd,
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	.req_cleanup_pending = cvm_req_cleanup_pending,
+	.req_completion_poll = cvm_req_completion_poll,
+#endif
 };
 
 static void cvm_mmc_set_clock(struct cvm_mmc_slot *slot, unsigned int clock)
@@ -1058,6 +1122,9 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
 	slot->bus_id = id;
 	slot->cached_rca = 1;
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	host->pstore = 0;
+#endif
 	host->acquire_bus(host);
 	host->slot[id] = slot;
 	cvm_mmc_switch_to(slot);
diff --git a/drivers/mmc/host/cavium.h b/drivers/mmc/host/cavium.h
index f3eea5eaa678..248a5a6e3522 100644
--- a/drivers/mmc/host/cavium.h
+++ b/drivers/mmc/host/cavium.h
@@ -75,6 +75,9 @@ struct cvm_mmc_host {
 	spinlock_t irq_handler_lock;
 	struct semaphore mmc_serializer;
 
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+	bool pstore;
+#endif
 	struct gpio_desc *global_pwr_gpiod;
 	atomic_t shared_power_users;
 
-- 
2.17.1


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

* Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-01-20 12:10 ` [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk Bhaskara Budiredla
@ 2021-01-20 15:06   ` Ulf Hansson
  2021-06-05 10:31     ` [EXT] " Bhaskara Budiredla
  2021-01-20 16:11     ` kernel test robot
  1 sibling, 1 reply; 14+ messages in thread
From: Ulf Hansson @ 2021-01-20 15:06 UTC (permalink / raw)
  To: Bhaskara Budiredla, Kees Cook
  Cc: Colin Cross, Tony Luck, Sunil Kovvuri Goutham, linux-mmc,
	Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

+ linux-block, Jens, Christoph

On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla <bbudiredla@marvell.com> wrote:
>
> This patch introduces to mmcpstore. The functioning of mmcpstore
> is similar to mtdpstore. mmcpstore works on FTL based flash devices
> whereas mtdpstore works on raw flash devices. When the system crashes,
> mmcpstore stores the kmsg panic and oops logs to a user specified
> MMC device.
>
> It collects the details about the host MMC device through pstore/blk
> "blkdev" parameter. The user can specify the MMC device in many ways
> by checking in Documentation/admin-guide/pstore-blk.rst.
>
> The individual mmc host drivers have to define suitable polling and
> cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
> These new host operations are needed as pstore panic write runs with
> interrupts disabled.

Okay, let me again try to clarify on how I see this to move this forward.

1)
In my opinion, pstore shouldn't be using callbacks for *regular* I/O
read/writes. It's upside-down of how the storage stack is designed to
work.

Instead, pstore should be implemented as a regular filesystem, that
can be mounted on top of a regular block device partition. In this
way, the lower layer block device drivers (as mmc), don't need special
support for pstore, the regular I/O block read/write path will just
work as is.

2)
When it comes to supporting *panic* writes for pstore, things become a
bit more complicated. For sure some adaptations are needed in each
block device driver to support this.

However, the current method means relying on the lower level block
device driver to figure out the pstore partition. Based on that, it
should then register itself for pstore support and hook up callbacks
for the corresponding block device driver instance, at least that is
what it looks like to me. Again, I think this is upside-down from the
storage stack perspective. The partition to use for pstore, should be
based upon its file system mount point.

Furthermore, I think the responsibility for lower layer block device
drivers should instead be to just "register/announce" themselves as
capable of supporting "panic writes", if they can. Exactly how to best
do this, probably needs to be discussed further with the block device
people, I think. I have looped in Jens and Christoph, perhaps they can
share their opinion in this.

That said, it looks to me that pstore needs more work before it's
ready to be adopted for generic support in block device drivers.

Kind regards
Uffe

>
> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
> ---
>  drivers/mmc/core/Kconfig     |  14 ++-
>  drivers/mmc/core/Makefile    |   1 +
>  drivers/mmc/core/block.c     |  19 +++
>  drivers/mmc/core/block.h     |   9 ++
>  drivers/mmc/core/core.c      |  44 +++++++
>  drivers/mmc/core/mmcpstore.c | 227 +++++++++++++++++++++++++++++++++++
>  include/linux/mmc/core.h     |   5 +
>  include/linux/mmc/host.h     |  12 ++
>  8 files changed, 330 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/mmc/core/mmcpstore.c
>
> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
> index c12fe13e4b14..4c651da4f2d2 100644
> --- a/drivers/mmc/core/Kconfig
> +++ b/drivers/mmc/core/Kconfig
> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
>           This driver can also be built as a module. If so, the module
>           will be called pwrseq_simple.
>
> +config MMC_PSTORE_BACKEND
> +       bool "Log panic/oops to a MMC buffer"
> +       depends on MMC_BLOCK
> +       help
> +         This option will let you create platform backend to store kmsg
> +         crash dumps to a user specified MMC device. This is primarily
> +         based on pstore/blk.
> +
> +config MMC_PSTORE
> +       tristate
> +       select PSTORE_BLK
> +
>  config MMC_BLOCK
>         tristate "MMC block device driver"
>         depends on BLOCK
> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
>         default y
>         help
>           Say Y here to enable the MMC block device driver support.
> @@ -80,4 +93,3 @@ config MMC_TEST
>
>           This driver is only of interest to those developing or
>           testing a host driver. Most people should say N here.
> -
> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
> index 95ffe008ebdf..7cb9a3af4827 100644
> --- a/drivers/mmc/core/Makefile
> +++ b/drivers/mmc/core/Makefile
> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     += pwrseq_emmc.o
>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>  mmc_block-objs                 := block.o queue.o
> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 42e27a298218..6592722cd7b2 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card,
>
>  #endif /* CONFIG_DEBUG_FS */
>
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size)
> +{
> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
> +       struct gendisk *disk = md->disk;
> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
> +
> +       if (part_num < 0 || part_num >= part_tbl->len)
> +               return 0;
> +
> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
> +       return part_tbl->part[part_num]->start_sect;
> +}
> +#endif
> +
>  static int mmc_blk_probe(struct mmc_card *card)
>  {
>         struct mmc_blk_data *md, *part_md;
> @@ -2913,6 +2928,9 @@ static int mmc_blk_probe(struct mmc_card *card)
>                         goto out;
>         }
>
> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
> +               mmcpstore_card_set(card, md->disk->disk_name);
> +
>         /* Add two debugfs entries */
>         mmc_blk_add_debugfs(card, md);
>
> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
>         bus_unregister(&mmc_rpmb_bus_type);
> +       unregister_mmcpstore();
>  }
>
>  module_init(mmc_blk_init);
> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
> index 31153f656f41..2a4ee5568194 100644
> --- a/drivers/mmc/core/block.h
> +++ b/drivers/mmc/core/block.h
> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue *mq);
>  struct work_struct;
>
>  void mmc_blk_mq_complete_work(struct work_struct *work);
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size);
> +void mmcpstore_card_set(struct mmc_card *card, const char *disk_name);
> +void unregister_mmcpstore(void);
> +#else
> +static inline void mmcpstore_card_set(struct mmc_card *card,
> +                                       const char *disk_name) {}
> +static inline void unregister_mmcpstore(void) {}
> +#endif
>
>  #endif
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 19f1ee57fb34..7ad7ff1cab8c 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)
>  }
>  EXPORT_SYMBOL(mmc_cqe_recovery);
>
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +/**
> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
> + *     @host: MMC host to start command
> + *     @mrq: MMC request to start
> + *
> + *     Start a blocking MMC request for a host and wait for the request
> + *     to complete that is based on polling and timeout.
> + */
> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct mmc_request *mrq)
> +{
> +       unsigned int timeout;
> +
> +       host->ops->req_cleanup_pending(host);
> +       mmc_start_request(host, mrq);
> +
> +       if (mrq->data) {
> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
> +               host->ops->req_completion_poll(host, timeout);
> +       }
> +}
> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
> +#endif
> +
>  /**
>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is done
>   *     @host: MMC host
> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx,
>  }
>  EXPORT_SYMBOL(__mmc_claim_host);
>
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +/**
> + *     mmc_claim_host_async - claim host in atomic context
> + *     @host: mmc host to claim
> + *
> + *     This routine may be called in panic/oops scenarios.
> + *     Return zero with host claim success, else busy status.
> + */
> +int mmc_claim_host_async(struct mmc_host *host)
> +{
> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
> +               host->claimed = 1;
> +               return 0;
> +       }
> +
> +       return -EBUSY;
> +}
> +EXPORT_SYMBOL(mmc_claim_host_async);
> +#endif
> +
>  /**
>   *     mmc_release_host - release a host
>   *     @host: mmc host to release
> diff --git a/drivers/mmc/core/mmcpstore.c b/drivers/mmc/core/mmcpstore.c
> new file mode 100644
> index 000000000000..f783ea215f18
> --- /dev/null
> +++ b/drivers/mmc/core/mmcpstore.c
> @@ -0,0 +1,227 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MMC pstore support based on pstore/blk
> + *
> + * Copyright (c) 2020 Marvell.
> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>
> + */
> +
> +#define pr_fmt(fmt) "mmcpstore: " fmt
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pstore_blk.h>
> +#include <linux/blkdev.h>
> +#include <linux/mount.h>
> +#include <linux/slab.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/card.h>
> +#include <linux/scatterlist.h>
> +#include "block.h"
> +#include "card.h"
> +#include "core.h"
> +
> +static struct mmcpstore_context {
> +       char dev_name[BDEVNAME_SIZE];
> +       int partno;
> +       sector_t start_sect;
> +       sector_t size;
> +       struct pstore_blk_config conf;
> +       struct pstore_blk_info info;
> +
> +       struct mmc_card *card;
> +       struct mmc_request *mrq;
> +} oops_cxt;
> +
> +static void mmc_prep_req(struct mmc_request *mrq,
> +               unsigned int sect_offset, unsigned int nsects,
> +               struct scatterlist *sg, u32 opcode, unsigned int flags)
> +{
> +       mrq->cmd->opcode = opcode;
> +       mrq->cmd->arg = sect_offset;
> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> +
> +       if (nsects == 1) {
> +               mrq->stop = NULL;
> +       } else {
> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
> +               mrq->stop->arg = 0;
> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
> +       }
> +
> +       mrq->data->blksz = SECTOR_SIZE;
> +       mrq->data->blocks = nsects;
> +       mrq->data->flags = flags;
> +       mrq->data->sg = sg;
> +       mrq->data->sg_len = 1;
> +}
> +
> +static int mmcpstore_panic_write_req(const char *buf,
> +               unsigned int nsects, unsigned int sect_offset)
> +{
> +       struct mmcpstore_context *cxt = &oops_cxt;
> +       struct mmc_request *mrq = cxt->mrq;
> +       struct mmc_card *card = cxt->card;
> +       struct mmc_host *host = card->host;
> +       struct scatterlist sg;
> +       u32 opcode;
> +       int ret;
> +
> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK : MMC_WRITE_BLOCK;
> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode, MMC_DATA_WRITE);
> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
> +       mmc_set_data_timeout(mrq->data, cxt->card);
> +
> +       ret = mmc_claim_host_async(host);
> +       if (ret)
> +               return ret;
> +
> +       mmc_wait_for_pstore_req(host, mrq);
> +       return 0;
> +}
> +
> +static int mmcpstore_panic_write(const char *buf, sector_t off, sector_t sects)
> +{
> +       struct mmcpstore_context *cxt = &oops_cxt;
> +       int ret;
> +
> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static struct block_device *mmcpstore_open_backend(const char *device)
> +{
> +       struct block_device *bdev;
> +       dev_t devt;
> +
> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
> +       if (IS_ERR(bdev)) {
> +               devt = name_to_dev_t(device);
> +               if (devt == 0)
> +                       return ERR_PTR(-ENODEV);
> +
> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
> +               if (IS_ERR(bdev))
> +                       return bdev;
> +       }
> +
> +       return bdev;
> +}
> +
> +static void mmcpstore_close_backend(struct block_device *bdev)
> +{
> +       if (!bdev)
> +               return;
> +       blkdev_put(bdev, FMODE_READ);
> +}
> +
> +void mmcpstore_card_set(struct mmc_card *card, const char *disk_name)
> +{
> +       struct mmcpstore_context *cxt = &oops_cxt;
> +       struct pstore_blk_config *conf = &cxt->conf;
> +       struct pstore_blk_info *info = &cxt->info;
> +       struct block_device *bdev;
> +       struct mmc_command *stop;
> +       struct mmc_command *cmd;
> +       struct mmc_request *mrq;
> +       struct mmc_data *data;
> +       int ret;
> +
> +       ret = pstore_blk_get_config(conf);
> +       if (!conf->device[0]) {
> +               pr_debug("psblk backend is empty\n");
> +               return;
> +       }
> +
> +       /* Multiple backend devices not allowed */
> +       if (cxt->dev_name[0])
> +               return;
> +
> +       bdev =  mmcpstore_open_backend(conf->device);
> +       if (IS_ERR(bdev)) {
> +               pr_err("%s failed to open with %ld\n",
> +                               conf->device, PTR_ERR(bdev));
> +               return;
> +       }
> +
> +       bdevname(bdev, cxt->dev_name);
> +       cxt->partno = bdev->bd_part->partno;
> +       mmcpstore_close_backend(bdev);
> +
> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
> +               return;
> +
> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
> +       if (!cxt->start_sect) {
> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
> +               return;
> +       }
> +
> +       /* Check for host mmc panic write polling function definitions */
> +       if (!card->host->ops->req_cleanup_pending ||
> +                       !card->host->ops->req_completion_poll)
> +               return;
> +
> +       cxt->card = card;
> +
> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
> +       if (!mrq)
> +               goto out;
> +
> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> +       if (!cmd)
> +               goto free_mrq;
> +
> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> +       if (!stop)
> +               goto free_cmd;
> +
> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
> +       if (!data)
> +               goto free_stop;
> +
> +       mrq->cmd = cmd;
> +       mrq->data = data;
> +       mrq->stop = stop;
> +       cxt->mrq = mrq;
> +
> +       info->major = MMC_BLOCK_MAJOR;
> +       info->flags = PSTORE_FLAGS_DMESG;
> +       info->panic_write = mmcpstore_panic_write;
> +       ret = register_pstore_blk(info);
> +       if (ret) {
> +               pr_err("%s registering with psblk failed (%d)\n",
> +                               cxt->dev_name, ret);
> +               goto free_data;
> +       }
> +
> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
> +       return;
> +
> +free_data:
> +       kfree(data);
> +free_stop:
> +       kfree(stop);
> +free_cmd:
> +       kfree(cmd);
> +free_mrq:
> +       kfree(mrq);
> +out:
> +       return;
> +}
> +
> +void unregister_mmcpstore(void)
> +{
> +       struct mmcpstore_context *cxt = &oops_cxt;
> +
> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
> +       kfree(cxt->mrq->data);
> +       kfree(cxt->mrq->stop);
> +       kfree(cxt->mrq->cmd);
> +       kfree(cxt->mrq);
> +       cxt->card = NULL;
> +}
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 29aa50711626..53840a361b5a 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -166,6 +166,11 @@ struct mmc_request {
>
>  struct mmc_card;
>
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct mmc_request *mrq);
> +int mmc_claim_host_async(struct mmc_host *host);
> +#endif
> +
>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq);
>  int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
>                 int retries);
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 01bba36545c5..ba9001498e03 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -178,6 +178,18 @@ struct mmc_host_ops {
>
>         /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */
>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios);
> +
> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> +       /*
> +        * The following two APIs are introduced to support mmcpstore
> +        * functionality. Cleanup API to terminate the ongoing and
> +        * pending requests before a panic write post, and polling API
> +        * to ensure that write succeeds before the Kernel dies.
> +        */
> +       void    (*req_cleanup_pending)(struct mmc_host *host);
> +       int     (*req_completion_poll)(struct mmc_host *host,
> +                                      unsigned long timeout);
> +#endif
>  };
>
>  struct mmc_cqe_ops {
> --
> 2.17.1
>

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

* Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-01-20 12:10 ` [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk Bhaskara Budiredla
@ 2021-01-20 16:11     ` kernel test robot
  2021-01-20 16:11     ` kernel test robot
  1 sibling, 0 replies; 14+ messages in thread
From: kernel test robot @ 2021-01-20 16:11 UTC (permalink / raw)
  To: Bhaskara Budiredla, ulf.hansson, keescook, ccross, tony.luck, sgoutham
  Cc: kbuild-all, linux-mmc, linux-kernel, Bhaskara Budiredla

[-- Attachment #1: Type: text/plain, Size: 4718 bytes --]

Hi Bhaskara,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.11-rc4 next-20210120]
[cannot apply to kees/for-next/pstore]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Bhaskara-Budiredla/mmc-support-crash-logging-to-MMC-block-devices/20210120-214535
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 45dfb8a5659ad286c28fa59008271dbc4e5e3f2d
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/69795d684b516b397dbfd2aec66d5e22645c03d9
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Bhaskara-Budiredla/mmc-support-crash-logging-to-MMC-block-devices/20210120-214535
        git checkout 69795d684b516b397dbfd2aec66d5e22645c03d9
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/mmc/core/block.c: In function 'mmc_blk_get_part':
>> drivers/mmc/core/block.c:2883:34: error: 'struct block_device' has no member named 'nr_sects'
    2883 |  *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
         |                                  ^~
>> drivers/mmc/core/block.c:2884:35: error: 'struct block_device' has no member named 'start_sect'; did you mean 'bd_start_sect'?
    2884 |  return part_tbl->part[part_num]->start_sect;
         |                                   ^~~~~~~~~~
         |                                   bd_start_sect
   drivers/mmc/core/block.c:2885:1: error: control reaches end of non-void function [-Werror=return-type]
    2885 | }
         | ^
   cc1: some warnings being treated as errors
--
>> drivers/mmc/core/mmcpstore.c:31:25: error: field 'info' has incomplete type
      31 |  struct pstore_blk_info info;
         |                         ^~~~
   drivers/mmc/core/mmcpstore.c: In function 'mmcpstore_card_set':
>> drivers/mmc/core/mmcpstore.c:152:22: error: 'struct block_device' has no member named 'bd_part'; did you mean 'bd_partno'?
     152 |  cxt->partno = bdev->bd_part->partno;
         |                      ^~~~~~~
         |                      bd_partno
>> drivers/mmc/core/mmcpstore.c:192:6: error: dereferencing pointer to incomplete type 'struct pstore_blk_info'
     192 |  info->major = MMC_BLOCK_MAJOR;
         |      ^~
>> drivers/mmc/core/mmcpstore.c:195:8: error: implicit declaration of function 'register_pstore_blk'; did you mean 'register_pstore_zone'? [-Werror=implicit-function-declaration]
     195 |  ret = register_pstore_blk(info);
         |        ^~~~~~~~~~~~~~~~~~~
         |        register_pstore_zone
   drivers/mmc/core/mmcpstore.c: In function 'unregister_mmcpstore':
>> drivers/mmc/core/mmcpstore.c:221:2: error: implicit declaration of function 'unregister_pstore_blk'; did you mean 'unregister_pstore_zone'? [-Werror=implicit-function-declaration]
     221 |  unregister_pstore_blk(MMC_BLOCK_MAJOR);
         |  ^~~~~~~~~~~~~~~~~~~~~
         |  unregister_pstore_zone
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for SND_ATMEL_SOC_PDC
   Depends on SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && HAS_DMA
   Selected by
   - SND_ATMEL_SOC_SSC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC
   - SND_ATMEL_SOC_SSC_PDC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && ATMEL_SSC


vim +2883 drivers/mmc/core/block.c

  2872	
  2873	#if IS_ENABLED(CONFIG_MMC_PSTORE)
  2874	sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size)
  2875	{
  2876		struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
  2877		struct gendisk *disk = md->disk;
  2878		struct disk_part_tbl *part_tbl = disk->part_tbl;
  2879	
  2880		if (part_num < 0 || part_num >= part_tbl->len)
  2881			return 0;
  2882	
> 2883		*size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
> 2884		return part_tbl->part[part_num]->start_sect;
  2885	}
  2886	#endif
  2887	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 54001 bytes --]

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

* Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
@ 2021-01-20 16:11     ` kernel test robot
  0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2021-01-20 16:11 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4815 bytes --]

Hi Bhaskara,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.11-rc4 next-20210120]
[cannot apply to kees/for-next/pstore]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Bhaskara-Budiredla/mmc-support-crash-logging-to-MMC-block-devices/20210120-214535
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 45dfb8a5659ad286c28fa59008271dbc4e5e3f2d
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/69795d684b516b397dbfd2aec66d5e22645c03d9
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Bhaskara-Budiredla/mmc-support-crash-logging-to-MMC-block-devices/20210120-214535
        git checkout 69795d684b516b397dbfd2aec66d5e22645c03d9
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/mmc/core/block.c: In function 'mmc_blk_get_part':
>> drivers/mmc/core/block.c:2883:34: error: 'struct block_device' has no member named 'nr_sects'
    2883 |  *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
         |                                  ^~
>> drivers/mmc/core/block.c:2884:35: error: 'struct block_device' has no member named 'start_sect'; did you mean 'bd_start_sect'?
    2884 |  return part_tbl->part[part_num]->start_sect;
         |                                   ^~~~~~~~~~
         |                                   bd_start_sect
   drivers/mmc/core/block.c:2885:1: error: control reaches end of non-void function [-Werror=return-type]
    2885 | }
         | ^
   cc1: some warnings being treated as errors
--
>> drivers/mmc/core/mmcpstore.c:31:25: error: field 'info' has incomplete type
      31 |  struct pstore_blk_info info;
         |                         ^~~~
   drivers/mmc/core/mmcpstore.c: In function 'mmcpstore_card_set':
>> drivers/mmc/core/mmcpstore.c:152:22: error: 'struct block_device' has no member named 'bd_part'; did you mean 'bd_partno'?
     152 |  cxt->partno = bdev->bd_part->partno;
         |                      ^~~~~~~
         |                      bd_partno
>> drivers/mmc/core/mmcpstore.c:192:6: error: dereferencing pointer to incomplete type 'struct pstore_blk_info'
     192 |  info->major = MMC_BLOCK_MAJOR;
         |      ^~
>> drivers/mmc/core/mmcpstore.c:195:8: error: implicit declaration of function 'register_pstore_blk'; did you mean 'register_pstore_zone'? [-Werror=implicit-function-declaration]
     195 |  ret = register_pstore_blk(info);
         |        ^~~~~~~~~~~~~~~~~~~
         |        register_pstore_zone
   drivers/mmc/core/mmcpstore.c: In function 'unregister_mmcpstore':
>> drivers/mmc/core/mmcpstore.c:221:2: error: implicit declaration of function 'unregister_pstore_blk'; did you mean 'unregister_pstore_zone'? [-Werror=implicit-function-declaration]
     221 |  unregister_pstore_blk(MMC_BLOCK_MAJOR);
         |  ^~~~~~~~~~~~~~~~~~~~~
         |  unregister_pstore_zone
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for SND_ATMEL_SOC_PDC
   Depends on SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && HAS_DMA
   Selected by
   - SND_ATMEL_SOC_SSC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC
   - SND_ATMEL_SOC_SSC_PDC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && ATMEL_SSC


vim +2883 drivers/mmc/core/block.c

  2872	
  2873	#if IS_ENABLED(CONFIG_MMC_PSTORE)
  2874	sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size)
  2875	{
  2876		struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
  2877		struct gendisk *disk = md->disk;
  2878		struct disk_part_tbl *part_tbl = disk->part_tbl;
  2879	
  2880		if (part_num < 0 || part_num >= part_tbl->len)
  2881			return 0;
  2882	
> 2883		*size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
> 2884		return part_tbl->part[part_num]->start_sect;
  2885	}
  2886	#endif
  2887	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 54001 bytes --]

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

* RE: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-01-20 15:06   ` Ulf Hansson
@ 2021-06-05 10:31     ` Bhaskara Budiredla
  2021-06-07 11:17       ` Ulf Hansson
  0 siblings, 1 reply; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-06-05 10:31 UTC (permalink / raw)
  To: Ulf Hansson, Kees Cook
  Cc: Colin Cross, Tony Luck, Sunil Kovvuri Goutham, linux-mmc,
	Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

Hi Uffe,

With due respect to pstore/blk subsystem changes we have been waiting since long time to see Christoph patches taken.
But unfortunately it is still finding at that same stage only. Can you please take up my patch in the current form
(which is based on current pstore/blk framework) instead of waiting indefinitely. If pstore/blk comes up with the changes
that has been discussed by you previously, I will further submit the corresponding changes for eMMC devices.

Thanks,
Bhaskara

>-----Original Message-----
>From: Ulf Hansson <ulf.hansson@linaro.org>
>Sent: Wednesday, January 20, 2021 8:36 PM
>To: Bhaskara Budiredla <bbudiredla@marvell.com>; Kees Cook
><keescook@chromium.org>
>Cc: Colin Cross <ccross@android.com>; Tony Luck <tony.luck@intel.com>;
>Sunil Kovvuri Goutham <sgoutham@marvell.com>; linux-
>mmc@vger.kernel.org; Linux Kernel Mailing List <linux-
>kernel@vger.kernel.org>; linux-block <linux-block@vger.kernel.org>; Jens
>Axboe <axboe@kernel.dk>; Christoph Hellwig <hch@lst.de>
>Subject: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>External Email
>
>----------------------------------------------------------------------
>+ linux-block, Jens, Christoph
>
>On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla
><bbudiredla@marvell.com> wrote:
>>
>> This patch introduces to mmcpstore. The functioning of mmcpstore is
>> similar to mtdpstore. mmcpstore works on FTL based flash devices
>> whereas mtdpstore works on raw flash devices. When the system crashes,
>> mmcpstore stores the kmsg panic and oops logs to a user specified MMC
>> device.
>>
>> It collects the details about the host MMC device through pstore/blk
>> "blkdev" parameter. The user can specify the MMC device in many ways
>> by checking in Documentation/admin-guide/pstore-blk.rst.
>>
>> The individual mmc host drivers have to define suitable polling and
>> cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
>> These new host operations are needed as pstore panic write runs with
>> interrupts disabled.
>
>Okay, let me again try to clarify on how I see this to move this forward.
>
>1)
>In my opinion, pstore shouldn't be using callbacks for *regular* I/O
>read/writes. It's upside-down of how the storage stack is designed to work.
>
>Instead, pstore should be implemented as a regular filesystem, that can be
>mounted on top of a regular block device partition. In this way, the lower
>layer block device drivers (as mmc), don't need special support for pstore, the
>regular I/O block read/write path will just work as is.
>
>2)
>When it comes to supporting *panic* writes for pstore, things become a bit
>more complicated. For sure some adaptations are needed in each block device
>driver to support this.
>
>However, the current method means relying on the lower level block device
>driver to figure out the pstore partition. Based on that, it should then register
>itself for pstore support and hook up callbacks for the corresponding block
>device driver instance, at least that is what it looks like to me. Again, I think
>this is upside-down from the storage stack perspective. The partition to use
>for pstore, should be based upon its file system mount point.
>
>Furthermore, I think the responsibility for lower layer block device drivers
>should instead be to just "register/announce" themselves as capable of
>supporting "panic writes", if they can. Exactly how to best do this, probably
>needs to be discussed further with the block device people, I think. I have
>looped in Jens and Christoph, perhaps they can share their opinion in this.
>
>That said, it looks to me that pstore needs more work before it's ready to be
>adopted for generic support in block device drivers.
>
>Kind regards
>Uffe
>
>>
>> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
>> ---
>>  drivers/mmc/core/Kconfig     |  14 ++-
>>  drivers/mmc/core/Makefile    |   1 +
>>  drivers/mmc/core/block.c     |  19 +++
>>  drivers/mmc/core/block.h     |   9 ++
>>  drivers/mmc/core/core.c      |  44 +++++++
>>  drivers/mmc/core/mmcpstore.c | 227
>+++++++++++++++++++++++++++++++++++
>>  include/linux/mmc/core.h     |   5 +
>>  include/linux/mmc/host.h     |  12 ++
>>  8 files changed, 330 insertions(+), 1 deletion(-)  create mode 100644
>> drivers/mmc/core/mmcpstore.c
>>
>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index
>> c12fe13e4b14..4c651da4f2d2 100644
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/mmc/core/Kconfig
>> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
>>           This driver can also be built as a module. If so, the module
>>           will be called pwrseq_simple.
>>
>> +config MMC_PSTORE_BACKEND
>> +       bool "Log panic/oops to a MMC buffer"
>> +       depends on MMC_BLOCK
>> +       help
>> +         This option will let you create platform backend to store kmsg
>> +         crash dumps to a user specified MMC device. This is primarily
>> +         based on pstore/blk.
>> +
>> +config MMC_PSTORE
>> +       tristate
>> +       select PSTORE_BLK
>> +
>>  config MMC_BLOCK
>>         tristate "MMC block device driver"
>>         depends on BLOCK
>> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
>>         default y
>>         help
>>           Say Y here to enable the MMC block device driver support.
>> @@ -80,4 +93,3 @@ config MMC_TEST
>>
>>           This driver is only of interest to those developing or
>>           testing a host driver. Most people should say N here.
>> -
>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>> index 95ffe008ebdf..7cb9a3af4827 100644
>> --- a/drivers/mmc/core/Makefile
>> +++ b/drivers/mmc/core/Makefile
>> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     += pwrseq_emmc.o
>>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>>  mmc_block-objs                 := block.o queue.o
>> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
>>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
>>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
>> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index
>> 42e27a298218..6592722cd7b2 100644
>> --- a/drivers/mmc/core/block.c
>> +++ b/drivers/mmc/core/block.c
>> @@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct
>> mmc_card *card,
>>
>>  #endif /* CONFIG_DEBUG_FS */
>>
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
>> +sector_t *size) {
>> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
>> +       struct gendisk *disk = md->disk;
>> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
>> +
>> +       if (part_num < 0 || part_num >= part_tbl->len)
>> +               return 0;
>> +
>> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
>> +       return part_tbl->part[part_num]->start_sect;
>> +}
>> +#endif
>> +
>>  static int mmc_blk_probe(struct mmc_card *card)  {
>>         struct mmc_blk_data *md, *part_md; @@ -2913,6 +2928,9 @@
>> static int mmc_blk_probe(struct mmc_card *card)
>>                         goto out;
>>         }
>>
>> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
>> +               mmcpstore_card_set(card, md->disk->disk_name);
>> +
>>         /* Add two debugfs entries */
>>         mmc_blk_add_debugfs(card, md);
>>
>> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
>>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
>>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
>>         bus_unregister(&mmc_rpmb_bus_type);
>> +       unregister_mmcpstore();
>>  }
>>
>>  module_init(mmc_blk_init);
>> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h index
>> 31153f656f41..2a4ee5568194 100644
>> --- a/drivers/mmc/core/block.h
>> +++ b/drivers/mmc/core/block.h
>> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue
>*mq);
>> struct work_struct;
>>
>>  void mmc_blk_mq_complete_work(struct work_struct *work);
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
>> +sector_t *size); void mmcpstore_card_set(struct mmc_card *card, const
>> +char *disk_name); void unregister_mmcpstore(void); #else static
>> +inline void mmcpstore_card_set(struct mmc_card *card,
>> +                                       const char *disk_name) {}
>> +static inline void unregister_mmcpstore(void) {} #endif
>>
>>  #endif
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
>> 19f1ee57fb34..7ad7ff1cab8c 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)  }
>> EXPORT_SYMBOL(mmc_cqe_recovery);
>>
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +/**
>> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
>> + *     @host: MMC host to start command
>> + *     @mrq: MMC request to start
>> + *
>> + *     Start a blocking MMC request for a host and wait for the request
>> + *     to complete that is based on polling and timeout.
>> + */
>> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> +mmc_request *mrq) {
>> +       unsigned int timeout;
>> +
>> +       host->ops->req_cleanup_pending(host);
>> +       mmc_start_request(host, mrq);
>> +
>> +       if (mrq->data) {
>> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
>> +               host->ops->req_completion_poll(host, timeout);
>> +       }
>> +}
>> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
>> +#endif
>> +
>>  /**
>>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is
>done
>>   *     @host: MMC host
>> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host,
>> struct mmc_ctx *ctx,  }  EXPORT_SYMBOL(__mmc_claim_host);
>>
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +/**
>> + *     mmc_claim_host_async - claim host in atomic context
>> + *     @host: mmc host to claim
>> + *
>> + *     This routine may be called in panic/oops scenarios.
>> + *     Return zero with host claim success, else busy status.
>> + */
>> +int mmc_claim_host_async(struct mmc_host *host) {
>> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
>> +               host->claimed = 1;
>> +               return 0;
>> +       }
>> +
>> +       return -EBUSY;
>> +}
>> +EXPORT_SYMBOL(mmc_claim_host_async);
>> +#endif
>> +
>>  /**
>>   *     mmc_release_host - release a host
>>   *     @host: mmc host to release
>> diff --git a/drivers/mmc/core/mmcpstore.c
>> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
>> 000000000000..f783ea215f18
>> --- /dev/null
>> +++ b/drivers/mmc/core/mmcpstore.c
>> @@ -0,0 +1,227 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * MMC pstore support based on pstore/blk
>> + *
>> + * Copyright (c) 2020 Marvell.
>> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>  */
>> +
>> +#define pr_fmt(fmt) "mmcpstore: " fmt
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pstore_blk.h>
>> +#include <linux/blkdev.h>
>> +#include <linux/mount.h>
>> +#include <linux/slab.h>
>> +#include <linux/mmc/mmc.h>
>> +#include <linux/mmc/host.h>
>> +#include <linux/mmc/card.h>
>> +#include <linux/scatterlist.h>
>> +#include "block.h"
>> +#include "card.h"
>> +#include "core.h"
>> +
>> +static struct mmcpstore_context {
>> +       char dev_name[BDEVNAME_SIZE];
>> +       int partno;
>> +       sector_t start_sect;
>> +       sector_t size;
>> +       struct pstore_blk_config conf;
>> +       struct pstore_blk_info info;
>> +
>> +       struct mmc_card *card;
>> +       struct mmc_request *mrq;
>> +} oops_cxt;
>> +
>> +static void mmc_prep_req(struct mmc_request *mrq,
>> +               unsigned int sect_offset, unsigned int nsects,
>> +               struct scatterlist *sg, u32 opcode, unsigned int
>> +flags) {
>> +       mrq->cmd->opcode = opcode;
>> +       mrq->cmd->arg = sect_offset;
>> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>> +
>> +       if (nsects == 1) {
>> +               mrq->stop = NULL;
>> +       } else {
>> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
>> +               mrq->stop->arg = 0;
>> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
>> +       }
>> +
>> +       mrq->data->blksz = SECTOR_SIZE;
>> +       mrq->data->blocks = nsects;
>> +       mrq->data->flags = flags;
>> +       mrq->data->sg = sg;
>> +       mrq->data->sg_len = 1;
>> +}
>> +
>> +static int mmcpstore_panic_write_req(const char *buf,
>> +               unsigned int nsects, unsigned int sect_offset) {
>> +       struct mmcpstore_context *cxt = &oops_cxt;
>> +       struct mmc_request *mrq = cxt->mrq;
>> +       struct mmc_card *card = cxt->card;
>> +       struct mmc_host *host = card->host;
>> +       struct scatterlist sg;
>> +       u32 opcode;
>> +       int ret;
>> +
>> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
>MMC_WRITE_BLOCK;
>> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode,
>MMC_DATA_WRITE);
>> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
>> +       mmc_set_data_timeout(mrq->data, cxt->card);
>> +
>> +       ret = mmc_claim_host_async(host);
>> +       if (ret)
>> +               return ret;
>> +
>> +       mmc_wait_for_pstore_req(host, mrq);
>> +       return 0;
>> +}
>> +
>> +static int mmcpstore_panic_write(const char *buf, sector_t off,
>> +sector_t sects) {
>> +       struct mmcpstore_context *cxt = &oops_cxt;
>> +       int ret;
>> +
>> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return 0;
>> +}
>> +
>> +static struct block_device *mmcpstore_open_backend(const char
>> +*device) {
>> +       struct block_device *bdev;
>> +       dev_t devt;
>> +
>> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
>> +       if (IS_ERR(bdev)) {
>> +               devt = name_to_dev_t(device);
>> +               if (devt == 0)
>> +                       return ERR_PTR(-ENODEV);
>> +
>> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
>> +               if (IS_ERR(bdev))
>> +                       return bdev;
>> +       }
>> +
>> +       return bdev;
>> +}
>> +
>> +static void mmcpstore_close_backend(struct block_device *bdev) {
>> +       if (!bdev)
>> +               return;
>> +       blkdev_put(bdev, FMODE_READ);
>> +}
>> +
>> +void mmcpstore_card_set(struct mmc_card *card, const char *disk_name)
>> +{
>> +       struct mmcpstore_context *cxt = &oops_cxt;
>> +       struct pstore_blk_config *conf = &cxt->conf;
>> +       struct pstore_blk_info *info = &cxt->info;
>> +       struct block_device *bdev;
>> +       struct mmc_command *stop;
>> +       struct mmc_command *cmd;
>> +       struct mmc_request *mrq;
>> +       struct mmc_data *data;
>> +       int ret;
>> +
>> +       ret = pstore_blk_get_config(conf);
>> +       if (!conf->device[0]) {
>> +               pr_debug("psblk backend is empty\n");
>> +               return;
>> +       }
>> +
>> +       /* Multiple backend devices not allowed */
>> +       if (cxt->dev_name[0])
>> +               return;
>> +
>> +       bdev =  mmcpstore_open_backend(conf->device);
>> +       if (IS_ERR(bdev)) {
>> +               pr_err("%s failed to open with %ld\n",
>> +                               conf->device, PTR_ERR(bdev));
>> +               return;
>> +       }
>> +
>> +       bdevname(bdev, cxt->dev_name);
>> +       cxt->partno = bdev->bd_part->partno;
>> +       mmcpstore_close_backend(bdev);
>> +
>> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
>> +               return;
>> +
>> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
>> +       if (!cxt->start_sect) {
>> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
>> +               return;
>> +       }
>> +
>> +       /* Check for host mmc panic write polling function definitions */
>> +       if (!card->host->ops->req_cleanup_pending ||
>> +                       !card->host->ops->req_completion_poll)
>> +               return;
>> +
>> +       cxt->card = card;
>> +
>> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
>> +       if (!mrq)
>> +               goto out;
>> +
>> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> +       if (!cmd)
>> +               goto free_mrq;
>> +
>> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> +       if (!stop)
>> +               goto free_cmd;
>> +
>> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
>> +       if (!data)
>> +               goto free_stop;
>> +
>> +       mrq->cmd = cmd;
>> +       mrq->data = data;
>> +       mrq->stop = stop;
>> +       cxt->mrq = mrq;
>> +
>> +       info->major = MMC_BLOCK_MAJOR;
>> +       info->flags = PSTORE_FLAGS_DMESG;
>> +       info->panic_write = mmcpstore_panic_write;
>> +       ret = register_pstore_blk(info);
>> +       if (ret) {
>> +               pr_err("%s registering with psblk failed (%d)\n",
>> +                               cxt->dev_name, ret);
>> +               goto free_data;
>> +       }
>> +
>> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
>> +       return;
>> +
>> +free_data:
>> +       kfree(data);
>> +free_stop:
>> +       kfree(stop);
>> +free_cmd:
>> +       kfree(cmd);
>> +free_mrq:
>> +       kfree(mrq);
>> +out:
>> +       return;
>> +}
>> +
>> +void unregister_mmcpstore(void)
>> +{
>> +       struct mmcpstore_context *cxt = &oops_cxt;
>> +
>> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
>> +       kfree(cxt->mrq->data);
>> +       kfree(cxt->mrq->stop);
>> +       kfree(cxt->mrq->cmd);
>> +       kfree(cxt->mrq);
>> +       cxt->card = NULL;
>> +}
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index
>> 29aa50711626..53840a361b5a 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -166,6 +166,11 @@ struct mmc_request {
>>
>>  struct mmc_card;
>>
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> +mmc_request *mrq); int mmc_claim_host_async(struct mmc_host *host);
>> +#endif
>> +
>>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request
>> *mrq);  int mmc_wait_for_cmd(struct mmc_host *host, struct
>mmc_command *cmd,
>>                 int retries);
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index
>> 01bba36545c5..ba9001498e03 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -178,6 +178,18 @@ struct mmc_host_ops {
>>
>>         /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */
>>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios);
>> +
>> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> +       /*
>> +        * The following two APIs are introduced to support mmcpstore
>> +        * functionality. Cleanup API to terminate the ongoing and
>> +        * pending requests before a panic write post, and polling API
>> +        * to ensure that write succeeds before the Kernel dies.
>> +        */
>> +       void    (*req_cleanup_pending)(struct mmc_host *host);
>> +       int     (*req_completion_poll)(struct mmc_host *host,
>> +                                      unsigned long timeout); #endif
>>  };
>>
>>  struct mmc_cqe_ops {
>> --
>> 2.17.1
>>

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

* Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-05 10:31     ` [EXT] " Bhaskara Budiredla
@ 2021-06-07 11:17       ` Ulf Hansson
  2021-06-07 12:37         ` Bhaskara Budiredla
  2021-06-08 16:14         ` Christoph Hellwig
  0 siblings, 2 replies; 14+ messages in thread
From: Ulf Hansson @ 2021-06-07 11:17 UTC (permalink / raw)
  To: Bhaskara Budiredla
  Cc: Kees Cook, Colin Cross, Tony Luck, Sunil Kovvuri Goutham,
	linux-mmc, Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

On Sat, 5 Jun 2021 at 12:31, Bhaskara Budiredla <bbudiredla@marvell.com> wrote:
>
> Hi Uffe,
>
> With due respect to pstore/blk subsystem changes we have been waiting since long time to see Christoph patches taken.

What patches are you referring to?

> But unfortunately it is still finding at that same stage only. Can you please take up my patch in the current form
> (which is based on current pstore/blk framework) instead of waiting indefinitely. If pstore/blk comes up with the changes
> that has been discussed by you previously, I will further submit the corresponding changes for eMMC devices.

No, I am sorry, but that's not the way it works.

If you really want to move things forward, I would suggest that you
try to implement something along the lines of what I have suggested.
Another option is to post an RFD/RFC so as solution can be discussed
with the relevant people.

Kind regards
Uffe

>
> Thanks,
> Bhaskara
>
> >-----Original Message-----
> >From: Ulf Hansson <ulf.hansson@linaro.org>
> >Sent: Wednesday, January 20, 2021 8:36 PM
> >To: Bhaskara Budiredla <bbudiredla@marvell.com>; Kees Cook
> ><keescook@chromium.org>
> >Cc: Colin Cross <ccross@android.com>; Tony Luck <tony.luck@intel.com>;
> >Sunil Kovvuri Goutham <sgoutham@marvell.com>; linux-
> >mmc@vger.kernel.org; Linux Kernel Mailing List <linux-
> >kernel@vger.kernel.org>; linux-block <linux-block@vger.kernel.org>; Jens
> >Axboe <axboe@kernel.dk>; Christoph Hellwig <hch@lst.de>
> >Subject: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
> >pstore/blk
> >
> >External Email
> >
> >----------------------------------------------------------------------
> >+ linux-block, Jens, Christoph
> >
> >On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla
> ><bbudiredla@marvell.com> wrote:
> >>
> >> This patch introduces to mmcpstore. The functioning of mmcpstore is
> >> similar to mtdpstore. mmcpstore works on FTL based flash devices
> >> whereas mtdpstore works on raw flash devices. When the system crashes,
> >> mmcpstore stores the kmsg panic and oops logs to a user specified MMC
> >> device.
> >>
> >> It collects the details about the host MMC device through pstore/blk
> >> "blkdev" parameter. The user can specify the MMC device in many ways
> >> by checking in Documentation/admin-guide/pstore-blk.rst.
> >>
> >> The individual mmc host drivers have to define suitable polling and
> >> cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
> >> These new host operations are needed as pstore panic write runs with
> >> interrupts disabled.
> >
> >Okay, let me again try to clarify on how I see this to move this forward.
> >
> >1)
> >In my opinion, pstore shouldn't be using callbacks for *regular* I/O
> >read/writes. It's upside-down of how the storage stack is designed to work.
> >
> >Instead, pstore should be implemented as a regular filesystem, that can be
> >mounted on top of a regular block device partition. In this way, the lower
> >layer block device drivers (as mmc), don't need special support for pstore, the
> >regular I/O block read/write path will just work as is.
> >
> >2)
> >When it comes to supporting *panic* writes for pstore, things become a bit
> >more complicated. For sure some adaptations are needed in each block device
> >driver to support this.
> >
> >However, the current method means relying on the lower level block device
> >driver to figure out the pstore partition. Based on that, it should then register
> >itself for pstore support and hook up callbacks for the corresponding block
> >device driver instance, at least that is what it looks like to me. Again, I think
> >this is upside-down from the storage stack perspective. The partition to use
> >for pstore, should be based upon its file system mount point.
> >
> >Furthermore, I think the responsibility for lower layer block device drivers
> >should instead be to just "register/announce" themselves as capable of
> >supporting "panic writes", if they can. Exactly how to best do this, probably
> >needs to be discussed further with the block device people, I think. I have
> >looped in Jens and Christoph, perhaps they can share their opinion in this.
> >
> >That said, it looks to me that pstore needs more work before it's ready to be
> >adopted for generic support in block device drivers.
> >
> >Kind regards
> >Uffe
> >
> >>
> >> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
> >> ---
> >>  drivers/mmc/core/Kconfig     |  14 ++-
> >>  drivers/mmc/core/Makefile    |   1 +
> >>  drivers/mmc/core/block.c     |  19 +++
> >>  drivers/mmc/core/block.h     |   9 ++
> >>  drivers/mmc/core/core.c      |  44 +++++++
> >>  drivers/mmc/core/mmcpstore.c | 227
> >+++++++++++++++++++++++++++++++++++
> >>  include/linux/mmc/core.h     |   5 +
> >>  include/linux/mmc/host.h     |  12 ++
> >>  8 files changed, 330 insertions(+), 1 deletion(-)  create mode 100644
> >> drivers/mmc/core/mmcpstore.c
> >>
> >> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index
> >> c12fe13e4b14..4c651da4f2d2 100644
> >> --- a/drivers/mmc/core/Kconfig
> >> +++ b/drivers/mmc/core/Kconfig
> >> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
> >>           This driver can also be built as a module. If so, the module
> >>           will be called pwrseq_simple.
> >>
> >> +config MMC_PSTORE_BACKEND
> >> +       bool "Log panic/oops to a MMC buffer"
> >> +       depends on MMC_BLOCK
> >> +       help
> >> +         This option will let you create platform backend to store kmsg
> >> +         crash dumps to a user specified MMC device. This is primarily
> >> +         based on pstore/blk.
> >> +
> >> +config MMC_PSTORE
> >> +       tristate
> >> +       select PSTORE_BLK
> >> +
> >>  config MMC_BLOCK
> >>         tristate "MMC block device driver"
> >>         depends on BLOCK
> >> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
> >>         default y
> >>         help
> >>           Say Y here to enable the MMC block device driver support.
> >> @@ -80,4 +93,3 @@ config MMC_TEST
> >>
> >>           This driver is only of interest to those developing or
> >>           testing a host driver. Most people should say N here.
> >> -
> >> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
> >> index 95ffe008ebdf..7cb9a3af4827 100644
> >> --- a/drivers/mmc/core/Makefile
> >> +++ b/drivers/mmc/core/Makefile
> >> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     += pwrseq_emmc.o
> >>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
> >>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
> >>  mmc_block-objs                 := block.o queue.o
> >> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
> >>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
> >>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
> >> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index
> >> 42e27a298218..6592722cd7b2 100644
> >> --- a/drivers/mmc/core/block.c
> >> +++ b/drivers/mmc/core/block.c
> >> @@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct
> >> mmc_card *card,
> >>
> >>  #endif /* CONFIG_DEBUG_FS */
> >>
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
> >> +sector_t *size) {
> >> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
> >> +       struct gendisk *disk = md->disk;
> >> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
> >> +
> >> +       if (part_num < 0 || part_num >= part_tbl->len)
> >> +               return 0;
> >> +
> >> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
> >> +       return part_tbl->part[part_num]->start_sect;
> >> +}
> >> +#endif
> >> +
> >>  static int mmc_blk_probe(struct mmc_card *card)  {
> >>         struct mmc_blk_data *md, *part_md; @@ -2913,6 +2928,9 @@
> >> static int mmc_blk_probe(struct mmc_card *card)
> >>                         goto out;
> >>         }
> >>
> >> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
> >> +               mmcpstore_card_set(card, md->disk->disk_name);
> >> +
> >>         /* Add two debugfs entries */
> >>         mmc_blk_add_debugfs(card, md);
> >>
> >> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
> >>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
> >>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
> >>         bus_unregister(&mmc_rpmb_bus_type);
> >> +       unregister_mmcpstore();
> >>  }
> >>
> >>  module_init(mmc_blk_init);
> >> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h index
> >> 31153f656f41..2a4ee5568194 100644
> >> --- a/drivers/mmc/core/block.h
> >> +++ b/drivers/mmc/core/block.h
> >> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue
> >*mq);
> >> struct work_struct;
> >>
> >>  void mmc_blk_mq_complete_work(struct work_struct *work);
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
> >> +sector_t *size); void mmcpstore_card_set(struct mmc_card *card, const
> >> +char *disk_name); void unregister_mmcpstore(void); #else static
> >> +inline void mmcpstore_card_set(struct mmc_card *card,
> >> +                                       const char *disk_name) {}
> >> +static inline void unregister_mmcpstore(void) {} #endif
> >>
> >>  #endif
> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
> >> 19f1ee57fb34..7ad7ff1cab8c 100644
> >> --- a/drivers/mmc/core/core.c
> >> +++ b/drivers/mmc/core/core.c
> >> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)  }
> >> EXPORT_SYMBOL(mmc_cqe_recovery);
> >>
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +/**
> >> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
> >> + *     @host: MMC host to start command
> >> + *     @mrq: MMC request to start
> >> + *
> >> + *     Start a blocking MMC request for a host and wait for the request
> >> + *     to complete that is based on polling and timeout.
> >> + */
> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
> >> +mmc_request *mrq) {
> >> +       unsigned int timeout;
> >> +
> >> +       host->ops->req_cleanup_pending(host);
> >> +       mmc_start_request(host, mrq);
> >> +
> >> +       if (mrq->data) {
> >> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
> >> +               host->ops->req_completion_poll(host, timeout);
> >> +       }
> >> +}
> >> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
> >> +#endif
> >> +
> >>  /**
> >>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is
> >done
> >>   *     @host: MMC host
> >> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host,
> >> struct mmc_ctx *ctx,  }  EXPORT_SYMBOL(__mmc_claim_host);
> >>
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +/**
> >> + *     mmc_claim_host_async - claim host in atomic context
> >> + *     @host: mmc host to claim
> >> + *
> >> + *     This routine may be called in panic/oops scenarios.
> >> + *     Return zero with host claim success, else busy status.
> >> + */
> >> +int mmc_claim_host_async(struct mmc_host *host) {
> >> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
> >> +               host->claimed = 1;
> >> +               return 0;
> >> +       }
> >> +
> >> +       return -EBUSY;
> >> +}
> >> +EXPORT_SYMBOL(mmc_claim_host_async);
> >> +#endif
> >> +
> >>  /**
> >>   *     mmc_release_host - release a host
> >>   *     @host: mmc host to release
> >> diff --git a/drivers/mmc/core/mmcpstore.c
> >> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
> >> 000000000000..f783ea215f18
> >> --- /dev/null
> >> +++ b/drivers/mmc/core/mmcpstore.c
> >> @@ -0,0 +1,227 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * MMC pstore support based on pstore/blk
> >> + *
> >> + * Copyright (c) 2020 Marvell.
> >> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>  */
> >> +
> >> +#define pr_fmt(fmt) "mmcpstore: " fmt
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/module.h>
> >> +#include <linux/pstore_blk.h>
> >> +#include <linux/blkdev.h>
> >> +#include <linux/mount.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/mmc/mmc.h>
> >> +#include <linux/mmc/host.h>
> >> +#include <linux/mmc/card.h>
> >> +#include <linux/scatterlist.h>
> >> +#include "block.h"
> >> +#include "card.h"
> >> +#include "core.h"
> >> +
> >> +static struct mmcpstore_context {
> >> +       char dev_name[BDEVNAME_SIZE];
> >> +       int partno;
> >> +       sector_t start_sect;
> >> +       sector_t size;
> >> +       struct pstore_blk_config conf;
> >> +       struct pstore_blk_info info;
> >> +
> >> +       struct mmc_card *card;
> >> +       struct mmc_request *mrq;
> >> +} oops_cxt;
> >> +
> >> +static void mmc_prep_req(struct mmc_request *mrq,
> >> +               unsigned int sect_offset, unsigned int nsects,
> >> +               struct scatterlist *sg, u32 opcode, unsigned int
> >> +flags) {
> >> +       mrq->cmd->opcode = opcode;
> >> +       mrq->cmd->arg = sect_offset;
> >> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> >> +
> >> +       if (nsects == 1) {
> >> +               mrq->stop = NULL;
> >> +       } else {
> >> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
> >> +               mrq->stop->arg = 0;
> >> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
> >> +       }
> >> +
> >> +       mrq->data->blksz = SECTOR_SIZE;
> >> +       mrq->data->blocks = nsects;
> >> +       mrq->data->flags = flags;
> >> +       mrq->data->sg = sg;
> >> +       mrq->data->sg_len = 1;
> >> +}
> >> +
> >> +static int mmcpstore_panic_write_req(const char *buf,
> >> +               unsigned int nsects, unsigned int sect_offset) {
> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> +       struct mmc_request *mrq = cxt->mrq;
> >> +       struct mmc_card *card = cxt->card;
> >> +       struct mmc_host *host = card->host;
> >> +       struct scatterlist sg;
> >> +       u32 opcode;
> >> +       int ret;
> >> +
> >> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
> >MMC_WRITE_BLOCK;
> >> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode,
> >MMC_DATA_WRITE);
> >> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
> >> +       mmc_set_data_timeout(mrq->data, cxt->card);
> >> +
> >> +       ret = mmc_claim_host_async(host);
> >> +       if (ret)
> >> +               return ret;
> >> +
> >> +       mmc_wait_for_pstore_req(host, mrq);
> >> +       return 0;
> >> +}
> >> +
> >> +static int mmcpstore_panic_write(const char *buf, sector_t off,
> >> +sector_t sects) {
> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> +       int ret;
> >> +
> >> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
> >> +       if (ret)
> >> +               return ret;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static struct block_device *mmcpstore_open_backend(const char
> >> +*device) {
> >> +       struct block_device *bdev;
> >> +       dev_t devt;
> >> +
> >> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
> >> +       if (IS_ERR(bdev)) {
> >> +               devt = name_to_dev_t(device);
> >> +               if (devt == 0)
> >> +                       return ERR_PTR(-ENODEV);
> >> +
> >> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
> >> +               if (IS_ERR(bdev))
> >> +                       return bdev;
> >> +       }
> >> +
> >> +       return bdev;
> >> +}
> >> +
> >> +static void mmcpstore_close_backend(struct block_device *bdev) {
> >> +       if (!bdev)
> >> +               return;
> >> +       blkdev_put(bdev, FMODE_READ);
> >> +}
> >> +
> >> +void mmcpstore_card_set(struct mmc_card *card, const char *disk_name)
> >> +{
> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> +       struct pstore_blk_config *conf = &cxt->conf;
> >> +       struct pstore_blk_info *info = &cxt->info;
> >> +       struct block_device *bdev;
> >> +       struct mmc_command *stop;
> >> +       struct mmc_command *cmd;
> >> +       struct mmc_request *mrq;
> >> +       struct mmc_data *data;
> >> +       int ret;
> >> +
> >> +       ret = pstore_blk_get_config(conf);
> >> +       if (!conf->device[0]) {
> >> +               pr_debug("psblk backend is empty\n");
> >> +               return;
> >> +       }
> >> +
> >> +       /* Multiple backend devices not allowed */
> >> +       if (cxt->dev_name[0])
> >> +               return;
> >> +
> >> +       bdev =  mmcpstore_open_backend(conf->device);
> >> +       if (IS_ERR(bdev)) {
> >> +               pr_err("%s failed to open with %ld\n",
> >> +                               conf->device, PTR_ERR(bdev));
> >> +               return;
> >> +       }
> >> +
> >> +       bdevname(bdev, cxt->dev_name);
> >> +       cxt->partno = bdev->bd_part->partno;
> >> +       mmcpstore_close_backend(bdev);
> >> +
> >> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
> >> +               return;
> >> +
> >> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
> >> +       if (!cxt->start_sect) {
> >> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
> >> +               return;
> >> +       }
> >> +
> >> +       /* Check for host mmc panic write polling function definitions */
> >> +       if (!card->host->ops->req_cleanup_pending ||
> >> +                       !card->host->ops->req_completion_poll)
> >> +               return;
> >> +
> >> +       cxt->card = card;
> >> +
> >> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
> >> +       if (!mrq)
> >> +               goto out;
> >> +
> >> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> >> +       if (!cmd)
> >> +               goto free_mrq;
> >> +
> >> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> >> +       if (!stop)
> >> +               goto free_cmd;
> >> +
> >> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
> >> +       if (!data)
> >> +               goto free_stop;
> >> +
> >> +       mrq->cmd = cmd;
> >> +       mrq->data = data;
> >> +       mrq->stop = stop;
> >> +       cxt->mrq = mrq;
> >> +
> >> +       info->major = MMC_BLOCK_MAJOR;
> >> +       info->flags = PSTORE_FLAGS_DMESG;
> >> +       info->panic_write = mmcpstore_panic_write;
> >> +       ret = register_pstore_blk(info);
> >> +       if (ret) {
> >> +               pr_err("%s registering with psblk failed (%d)\n",
> >> +                               cxt->dev_name, ret);
> >> +               goto free_data;
> >> +       }
> >> +
> >> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
> >> +       return;
> >> +
> >> +free_data:
> >> +       kfree(data);
> >> +free_stop:
> >> +       kfree(stop);
> >> +free_cmd:
> >> +       kfree(cmd);
> >> +free_mrq:
> >> +       kfree(mrq);
> >> +out:
> >> +       return;
> >> +}
> >> +
> >> +void unregister_mmcpstore(void)
> >> +{
> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> +
> >> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
> >> +       kfree(cxt->mrq->data);
> >> +       kfree(cxt->mrq->stop);
> >> +       kfree(cxt->mrq->cmd);
> >> +       kfree(cxt->mrq);
> >> +       cxt->card = NULL;
> >> +}
> >> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index
> >> 29aa50711626..53840a361b5a 100644
> >> --- a/include/linux/mmc/core.h
> >> +++ b/include/linux/mmc/core.h
> >> @@ -166,6 +166,11 @@ struct mmc_request {
> >>
> >>  struct mmc_card;
> >>
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
> >> +mmc_request *mrq); int mmc_claim_host_async(struct mmc_host *host);
> >> +#endif
> >> +
> >>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request
> >> *mrq);  int mmc_wait_for_cmd(struct mmc_host *host, struct
> >mmc_command *cmd,
> >>                 int retries);
> >> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index
> >> 01bba36545c5..ba9001498e03 100644
> >> --- a/include/linux/mmc/host.h
> >> +++ b/include/linux/mmc/host.h
> >> @@ -178,6 +178,18 @@ struct mmc_host_ops {
> >>
> >>         /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */
> >>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios);
> >> +
> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> +       /*
> >> +        * The following two APIs are introduced to support mmcpstore
> >> +        * functionality. Cleanup API to terminate the ongoing and
> >> +        * pending requests before a panic write post, and polling API
> >> +        * to ensure that write succeeds before the Kernel dies.
> >> +        */
> >> +       void    (*req_cleanup_pending)(struct mmc_host *host);
> >> +       int     (*req_completion_poll)(struct mmc_host *host,
> >> +                                      unsigned long timeout); #endif
> >>  };
> >>
> >>  struct mmc_cqe_ops {
> >> --
> >> 2.17.1
> >>

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

* RE: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-07 11:17       ` Ulf Hansson
@ 2021-06-07 12:37         ` Bhaskara Budiredla
  2021-06-07 14:07           ` Ulf Hansson
  2021-06-08 17:31           ` Kees Cook
  2021-06-08 16:14         ` Christoph Hellwig
  1 sibling, 2 replies; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-06-07 12:37 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Kees Cook, Colin Cross, Tony Luck, Sunil Kovvuri Goutham,
	linux-mmc, Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

[...]
>What patches are you referring to?

I was referring to this patch.
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/pstore

Thanks,
Bhaskara

>-----Original Message-----
>From: Ulf Hansson <ulf.hansson@linaro.org>
>Sent: Monday, June 7, 2021 4:47 PM
>To: Bhaskara Budiredla <bbudiredla@marvell.com>
>Cc: Kees Cook <keescook@chromium.org>; Colin Cross
><ccross@android.com>; Tony Luck <tony.luck@intel.com>; Sunil Kovvuri
>Goutham <sgoutham@marvell.com>; linux-mmc@vger.kernel.org; Linux
>Kernel Mailing List <linux-kernel@vger.kernel.org>; linux-block <linux-
>block@vger.kernel.org>; Jens Axboe <axboe@kernel.dk>; Christoph Hellwig
><hch@lst.de>
>Subject: Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Sat, 5 Jun 2021 at 12:31, Bhaskara Budiredla <bbudiredla@marvell.com>
>wrote:
>>
>> Hi Uffe,
>>
>> With due respect to pstore/blk subsystem changes we have been waiting
>since long time to see Christoph patches taken.
>
>What patches are you referring to?
>
>> But unfortunately it is still finding at that same stage only. Can you
>> please take up my patch in the current form (which is based on current
>> pstore/blk framework) instead of waiting indefinitely. If pstore/blk comes up
>with the changes that has been discussed by you previously, I will further
>submit the corresponding changes for eMMC devices.
>
>No, I am sorry, but that's not the way it works.
>
>If you really want to move things forward, I would suggest that you try to
>implement something along the lines of what I have suggested.
>Another option is to post an RFD/RFC so as solution can be discussed with the
>relevant people.
>
>Kind regards
>Uffe
>
>>
>> Thanks,
>> Bhaskara
>>
>> >-----Original Message-----
>> >From: Ulf Hansson <ulf.hansson@linaro.org>
>> >Sent: Wednesday, January 20, 2021 8:36 PM
>> >To: Bhaskara Budiredla <bbudiredla@marvell.com>; Kees Cook
>> ><keescook@chromium.org>
>> >Cc: Colin Cross <ccross@android.com>; Tony Luck
>> ><tony.luck@intel.com>; Sunil Kovvuri Goutham <sgoutham@marvell.com>;
>> >linux- mmc@vger.kernel.org; Linux Kernel Mailing List <linux-
>> >kernel@vger.kernel.org>; linux-block <linux-block@vger.kernel.org>;
>> >Jens Axboe <axboe@kernel.dk>; Christoph Hellwig <hch@lst.de>
>> >Subject: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
>> >pstore/blk
>> >
>> >External Email
>> >
>> >---------------------------------------------------------------------
>> >-
>> >+ linux-block, Jens, Christoph
>> >
>> >On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla
>> ><bbudiredla@marvell.com> wrote:
>> >>
>> >> This patch introduces to mmcpstore. The functioning of mmcpstore is
>> >> similar to mtdpstore. mmcpstore works on FTL based flash devices
>> >> whereas mtdpstore works on raw flash devices. When the system
>> >> crashes, mmcpstore stores the kmsg panic and oops logs to a user
>> >> specified MMC device.
>> >>
>> >> It collects the details about the host MMC device through
>> >> pstore/blk "blkdev" parameter. The user can specify the MMC device
>> >> in many ways by checking in Documentation/admin-guide/pstore-blk.rst.
>> >>
>> >> The individual mmc host drivers have to define suitable polling and
>> >> cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
>> >> These new host operations are needed as pstore panic write runs
>> >> with interrupts disabled.
>> >
>> >Okay, let me again try to clarify on how I see this to move this forward.
>> >
>> >1)
>> >In my opinion, pstore shouldn't be using callbacks for *regular* I/O
>> >read/writes. It's upside-down of how the storage stack is designed to work.
>> >
>> >Instead, pstore should be implemented as a regular filesystem, that
>> >can be mounted on top of a regular block device partition. In this
>> >way, the lower layer block device drivers (as mmc), don't need
>> >special support for pstore, the regular I/O block read/write path will just
>work as is.
>> >
>> >2)
>> >When it comes to supporting *panic* writes for pstore, things become
>> >a bit more complicated. For sure some adaptations are needed in each
>> >block device driver to support this.
>> >
>> >However, the current method means relying on the lower level block
>> >device driver to figure out the pstore partition. Based on that, it
>> >should then register itself for pstore support and hook up callbacks
>> >for the corresponding block device driver instance, at least that is
>> >what it looks like to me. Again, I think this is upside-down from the
>> >storage stack perspective. The partition to use for pstore, should be based
>upon its file system mount point.
>> >
>> >Furthermore, I think the responsibility for lower layer block device
>> >drivers should instead be to just "register/announce" themselves as
>> >capable of supporting "panic writes", if they can. Exactly how to
>> >best do this, probably needs to be discussed further with the block
>> >device people, I think. I have looped in Jens and Christoph, perhaps they
>can share their opinion in this.
>> >
>> >That said, it looks to me that pstore needs more work before it's
>> >ready to be adopted for generic support in block device drivers.
>> >
>> >Kind regards
>> >Uffe
>> >
>> >>
>> >> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
>> >> ---
>> >>  drivers/mmc/core/Kconfig     |  14 ++-
>> >>  drivers/mmc/core/Makefile    |   1 +
>> >>  drivers/mmc/core/block.c     |  19 +++
>> >>  drivers/mmc/core/block.h     |   9 ++
>> >>  drivers/mmc/core/core.c      |  44 +++++++
>> >>  drivers/mmc/core/mmcpstore.c | 227
>> >+++++++++++++++++++++++++++++++++++
>> >>  include/linux/mmc/core.h     |   5 +
>> >>  include/linux/mmc/host.h     |  12 ++
>> >>  8 files changed, 330 insertions(+), 1 deletion(-)  create mode
>> >> 100644 drivers/mmc/core/mmcpstore.c
>> >>
>> >> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>> >> index
>> >> c12fe13e4b14..4c651da4f2d2 100644
>> >> --- a/drivers/mmc/core/Kconfig
>> >> +++ b/drivers/mmc/core/Kconfig
>> >> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
>> >>           This driver can also be built as a module. If so, the module
>> >>           will be called pwrseq_simple.
>> >>
>> >> +config MMC_PSTORE_BACKEND
>> >> +       bool "Log panic/oops to a MMC buffer"
>> >> +       depends on MMC_BLOCK
>> >> +       help
>> >> +         This option will let you create platform backend to store kmsg
>> >> +         crash dumps to a user specified MMC device. This is primarily
>> >> +         based on pstore/blk.
>> >> +
>> >> +config MMC_PSTORE
>> >> +       tristate
>> >> +       select PSTORE_BLK
>> >> +
>> >>  config MMC_BLOCK
>> >>         tristate "MMC block device driver"
>> >>         depends on BLOCK
>> >> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
>> >>         default y
>> >>         help
>> >>           Say Y here to enable the MMC block device driver support.
>> >> @@ -80,4 +93,3 @@ config MMC_TEST
>> >>
>> >>           This driver is only of interest to those developing or
>> >>           testing a host driver. Most people should say N here.
>> >> -
>> >> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>> >> index 95ffe008ebdf..7cb9a3af4827 100644
>> >> --- a/drivers/mmc/core/Makefile
>> >> +++ b/drivers/mmc/core/Makefile
>> >> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     +=
>pwrseq_emmc.o
>> >>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>> >>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>> >>  mmc_block-objs                 := block.o queue.o
>> >> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
>> >>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
>> >>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
>> >> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
>> >> index
>> >> 42e27a298218..6592722cd7b2 100644
>> >> --- a/drivers/mmc/core/block.c
>> >> +++ b/drivers/mmc/core/block.c
>> >> @@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct
>> >> mmc_card *card,
>> >>
>> >>  #endif /* CONFIG_DEBUG_FS */
>> >>
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
>> >> +sector_t *size) {
>> >> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
>> >> +       struct gendisk *disk = md->disk;
>> >> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
>> >> +
>> >> +       if (part_num < 0 || part_num >= part_tbl->len)
>> >> +               return 0;
>> >> +
>> >> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
>> >> +       return part_tbl->part[part_num]->start_sect;
>> >> +}
>> >> +#endif
>> >> +
>> >>  static int mmc_blk_probe(struct mmc_card *card)  {
>> >>         struct mmc_blk_data *md, *part_md; @@ -2913,6 +2928,9 @@
>> >> static int mmc_blk_probe(struct mmc_card *card)
>> >>                         goto out;
>> >>         }
>> >>
>> >> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
>> >> +               mmcpstore_card_set(card, md->disk->disk_name);
>> >> +
>> >>         /* Add two debugfs entries */
>> >>         mmc_blk_add_debugfs(card, md);
>> >>
>> >> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
>> >>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
>> >>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
>> >>         bus_unregister(&mmc_rpmb_bus_type);
>> >> +       unregister_mmcpstore();
>> >>  }
>> >>
>> >>  module_init(mmc_blk_init);
>> >> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
>> >> index
>> >> 31153f656f41..2a4ee5568194 100644
>> >> --- a/drivers/mmc/core/block.h
>> >> +++ b/drivers/mmc/core/block.h
>> >> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue
>> >*mq);
>> >> struct work_struct;
>> >>
>> >>  void mmc_blk_mq_complete_work(struct work_struct *work);
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
>> >> +sector_t *size); void mmcpstore_card_set(struct mmc_card *card,
>> >> +const char *disk_name); void unregister_mmcpstore(void); #else
>> >> +static inline void mmcpstore_card_set(struct mmc_card *card,
>> >> +                                       const char *disk_name) {}
>> >> +static inline void unregister_mmcpstore(void) {} #endif
>> >>
>> >>  #endif
>> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> >> index 19f1ee57fb34..7ad7ff1cab8c 100644
>> >> --- a/drivers/mmc/core/core.c
>> >> +++ b/drivers/mmc/core/core.c
>> >> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)
>}
>> >> EXPORT_SYMBOL(mmc_cqe_recovery);
>> >>
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +/**
>> >> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
>> >> + *     @host: MMC host to start command
>> >> + *     @mrq: MMC request to start
>> >> + *
>> >> + *     Start a blocking MMC request for a host and wait for the request
>> >> + *     to complete that is based on polling and timeout.
>> >> + */
>> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> >> +mmc_request *mrq) {
>> >> +       unsigned int timeout;
>> >> +
>> >> +       host->ops->req_cleanup_pending(host);
>> >> +       mmc_start_request(host, mrq);
>> >> +
>> >> +       if (mrq->data) {
>> >> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
>> >> +               host->ops->req_completion_poll(host, timeout);
>> >> +       }
>> >> +}
>> >> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
>> >> +#endif
>> >> +
>> >>  /**
>> >>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is
>> >done
>> >>   *     @host: MMC host
>> >> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host,
>> >> struct mmc_ctx *ctx,  }  EXPORT_SYMBOL(__mmc_claim_host);
>> >>
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +/**
>> >> + *     mmc_claim_host_async - claim host in atomic context
>> >> + *     @host: mmc host to claim
>> >> + *
>> >> + *     This routine may be called in panic/oops scenarios.
>> >> + *     Return zero with host claim success, else busy status.
>> >> + */
>> >> +int mmc_claim_host_async(struct mmc_host *host) {
>> >> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
>> >> +               host->claimed = 1;
>> >> +               return 0;
>> >> +       }
>> >> +
>> >> +       return -EBUSY;
>> >> +}
>> >> +EXPORT_SYMBOL(mmc_claim_host_async);
>> >> +#endif
>> >> +
>> >>  /**
>> >>   *     mmc_release_host - release a host
>> >>   *     @host: mmc host to release
>> >> diff --git a/drivers/mmc/core/mmcpstore.c
>> >> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
>> >> 000000000000..f783ea215f18
>> >> --- /dev/null
>> >> +++ b/drivers/mmc/core/mmcpstore.c
>> >> @@ -0,0 +1,227 @@
>> >> +// SPDX-License-Identifier: GPL-2.0
>> >> +/*
>> >> + * MMC pstore support based on pstore/blk
>> >> + *
>> >> + * Copyright (c) 2020 Marvell.
>> >> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>  */
>> >> +
>> >> +#define pr_fmt(fmt) "mmcpstore: " fmt
>> >> +
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/module.h>
>> >> +#include <linux/pstore_blk.h>
>> >> +#include <linux/blkdev.h>
>> >> +#include <linux/mount.h>
>> >> +#include <linux/slab.h>
>> >> +#include <linux/mmc/mmc.h>
>> >> +#include <linux/mmc/host.h>
>> >> +#include <linux/mmc/card.h>
>> >> +#include <linux/scatterlist.h>
>> >> +#include "block.h"
>> >> +#include "card.h"
>> >> +#include "core.h"
>> >> +
>> >> +static struct mmcpstore_context {
>> >> +       char dev_name[BDEVNAME_SIZE];
>> >> +       int partno;
>> >> +       sector_t start_sect;
>> >> +       sector_t size;
>> >> +       struct pstore_blk_config conf;
>> >> +       struct pstore_blk_info info;
>> >> +
>> >> +       struct mmc_card *card;
>> >> +       struct mmc_request *mrq;
>> >> +} oops_cxt;
>> >> +
>> >> +static void mmc_prep_req(struct mmc_request *mrq,
>> >> +               unsigned int sect_offset, unsigned int nsects,
>> >> +               struct scatterlist *sg, u32 opcode, unsigned int
>> >> +flags) {
>> >> +       mrq->cmd->opcode = opcode;
>> >> +       mrq->cmd->arg = sect_offset;
>> >> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>> >> +
>> >> +       if (nsects == 1) {
>> >> +               mrq->stop = NULL;
>> >> +       } else {
>> >> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
>> >> +               mrq->stop->arg = 0;
>> >> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
>> >> +       }
>> >> +
>> >> +       mrq->data->blksz = SECTOR_SIZE;
>> >> +       mrq->data->blocks = nsects;
>> >> +       mrq->data->flags = flags;
>> >> +       mrq->data->sg = sg;
>> >> +       mrq->data->sg_len = 1;
>> >> +}
>> >> +
>> >> +static int mmcpstore_panic_write_req(const char *buf,
>> >> +               unsigned int nsects, unsigned int sect_offset) {
>> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> +       struct mmc_request *mrq = cxt->mrq;
>> >> +       struct mmc_card *card = cxt->card;
>> >> +       struct mmc_host *host = card->host;
>> >> +       struct scatterlist sg;
>> >> +       u32 opcode;
>> >> +       int ret;
>> >> +
>> >> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
>> >MMC_WRITE_BLOCK;
>> >> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode,
>> >MMC_DATA_WRITE);
>> >> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
>> >> +       mmc_set_data_timeout(mrq->data, cxt->card);
>> >> +
>> >> +       ret = mmc_claim_host_async(host);
>> >> +       if (ret)
>> >> +               return ret;
>> >> +
>> >> +       mmc_wait_for_pstore_req(host, mrq);
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static int mmcpstore_panic_write(const char *buf, sector_t off,
>> >> +sector_t sects) {
>> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> +       int ret;
>> >> +
>> >> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
>> >> +       if (ret)
>> >> +               return ret;
>> >> +
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static struct block_device *mmcpstore_open_backend(const char
>> >> +*device) {
>> >> +       struct block_device *bdev;
>> >> +       dev_t devt;
>> >> +
>> >> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
>> >> +       if (IS_ERR(bdev)) {
>> >> +               devt = name_to_dev_t(device);
>> >> +               if (devt == 0)
>> >> +                       return ERR_PTR(-ENODEV);
>> >> +
>> >> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
>> >> +               if (IS_ERR(bdev))
>> >> +                       return bdev;
>> >> +       }
>> >> +
>> >> +       return bdev;
>> >> +}
>> >> +
>> >> +static void mmcpstore_close_backend(struct block_device *bdev) {
>> >> +       if (!bdev)
>> >> +               return;
>> >> +       blkdev_put(bdev, FMODE_READ); }
>> >> +
>> >> +void mmcpstore_card_set(struct mmc_card *card, const char
>> >> +*disk_name) {
>> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> +       struct pstore_blk_config *conf = &cxt->conf;
>> >> +       struct pstore_blk_info *info = &cxt->info;
>> >> +       struct block_device *bdev;
>> >> +       struct mmc_command *stop;
>> >> +       struct mmc_command *cmd;
>> >> +       struct mmc_request *mrq;
>> >> +       struct mmc_data *data;
>> >> +       int ret;
>> >> +
>> >> +       ret = pstore_blk_get_config(conf);
>> >> +       if (!conf->device[0]) {
>> >> +               pr_debug("psblk backend is empty\n");
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       /* Multiple backend devices not allowed */
>> >> +       if (cxt->dev_name[0])
>> >> +               return;
>> >> +
>> >> +       bdev =  mmcpstore_open_backend(conf->device);
>> >> +       if (IS_ERR(bdev)) {
>> >> +               pr_err("%s failed to open with %ld\n",
>> >> +                               conf->device, PTR_ERR(bdev));
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       bdevname(bdev, cxt->dev_name);
>> >> +       cxt->partno = bdev->bd_part->partno;
>> >> +       mmcpstore_close_backend(bdev);
>> >> +
>> >> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
>> >> +               return;
>> >> +
>> >> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
>> >> +       if (!cxt->start_sect) {
>> >> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       /* Check for host mmc panic write polling function definitions */
>> >> +       if (!card->host->ops->req_cleanup_pending ||
>> >> +                       !card->host->ops->req_completion_poll)
>> >> +               return;
>> >> +
>> >> +       cxt->card = card;
>> >> +
>> >> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
>> >> +       if (!mrq)
>> >> +               goto out;
>> >> +
>> >> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> >> +       if (!cmd)
>> >> +               goto free_mrq;
>> >> +
>> >> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> >> +       if (!stop)
>> >> +               goto free_cmd;
>> >> +
>> >> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
>> >> +       if (!data)
>> >> +               goto free_stop;
>> >> +
>> >> +       mrq->cmd = cmd;
>> >> +       mrq->data = data;
>> >> +       mrq->stop = stop;
>> >> +       cxt->mrq = mrq;
>> >> +
>> >> +       info->major = MMC_BLOCK_MAJOR;
>> >> +       info->flags = PSTORE_FLAGS_DMESG;
>> >> +       info->panic_write = mmcpstore_panic_write;
>> >> +       ret = register_pstore_blk(info);
>> >> +       if (ret) {
>> >> +               pr_err("%s registering with psblk failed (%d)\n",
>> >> +                               cxt->dev_name, ret);
>> >> +               goto free_data;
>> >> +       }
>> >> +
>> >> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
>> >> +       return;
>> >> +
>> >> +free_data:
>> >> +       kfree(data);
>> >> +free_stop:
>> >> +       kfree(stop);
>> >> +free_cmd:
>> >> +       kfree(cmd);
>> >> +free_mrq:
>> >> +       kfree(mrq);
>> >> +out:
>> >> +       return;
>> >> +}
>> >> +
>> >> +void unregister_mmcpstore(void)
>> >> +{
>> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> +
>> >> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
>> >> +       kfree(cxt->mrq->data);
>> >> +       kfree(cxt->mrq->stop);
>> >> +       kfree(cxt->mrq->cmd);
>> >> +       kfree(cxt->mrq);
>> >> +       cxt->card = NULL;
>> >> +}
>> >> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> >> index 29aa50711626..53840a361b5a 100644
>> >> --- a/include/linux/mmc/core.h
>> >> +++ b/include/linux/mmc/core.h
>> >> @@ -166,6 +166,11 @@ struct mmc_request {
>> >>
>> >>  struct mmc_card;
>> >>
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> >> +mmc_request *mrq); int mmc_claim_host_async(struct mmc_host
>> >> +*host); #endif
>> >> +
>> >>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request
>> >> *mrq);  int mmc_wait_for_cmd(struct mmc_host *host, struct
>> >mmc_command *cmd,
>> >>                 int retries);
>> >> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> >> index
>> >> 01bba36545c5..ba9001498e03 100644
>> >> --- a/include/linux/mmc/host.h
>> >> +++ b/include/linux/mmc/host.h
>> >> @@ -178,6 +178,18 @@ struct mmc_host_ops {
>> >>
>> >>         /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP.
>*/
>> >>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios
>*ios);
>> >> +
>> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> +       /*
>> >> +        * The following two APIs are introduced to support mmcpstore
>> >> +        * functionality. Cleanup API to terminate the ongoing and
>> >> +        * pending requests before a panic write post, and polling API
>> >> +        * to ensure that write succeeds before the Kernel dies.
>> >> +        */
>> >> +       void    (*req_cleanup_pending)(struct mmc_host *host);
>> >> +       int     (*req_completion_poll)(struct mmc_host *host,
>> >> +                                      unsigned long timeout);
>> >> +#endif
>> >>  };
>> >>
>> >>  struct mmc_cqe_ops {
>> >> --
>> >> 2.17.1
>> >>

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

* Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-07 12:37         ` Bhaskara Budiredla
@ 2021-06-07 14:07           ` Ulf Hansson
  2021-06-07 16:28             ` Bhaskara Budiredla
  2021-06-08 17:31           ` Kees Cook
  1 sibling, 1 reply; 14+ messages in thread
From: Ulf Hansson @ 2021-06-07 14:07 UTC (permalink / raw)
  To: Bhaskara Budiredla
  Cc: Kees Cook, Colin Cross, Tony Luck, Sunil Kovvuri Goutham,
	linux-mmc, Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

On Mon, 7 Jun 2021 at 14:37, Bhaskara Budiredla <bbudiredla@marvell.com> wrote:
>
> [...]
> >What patches are you referring to?
>
> I was referring to this patch.
> http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/pstore

Alright. I didn't know about these, thanks for the pointer. Looks like
a big step in the right direction.

I guess Christoph simply has been busy with other things. Perhaps you
should ask if you can help and pick up from where he left the series?

Kind regards
Uffe

>
> Thanks,
> Bhaskara
>
> >-----Original Message-----
> >From: Ulf Hansson <ulf.hansson@linaro.org>
> >Sent: Monday, June 7, 2021 4:47 PM
> >To: Bhaskara Budiredla <bbudiredla@marvell.com>
> >Cc: Kees Cook <keescook@chromium.org>; Colin Cross
> ><ccross@android.com>; Tony Luck <tony.luck@intel.com>; Sunil Kovvuri
> >Goutham <sgoutham@marvell.com>; linux-mmc@vger.kernel.org; Linux
> >Kernel Mailing List <linux-kernel@vger.kernel.org>; linux-block <linux-
> >block@vger.kernel.org>; Jens Axboe <axboe@kernel.dk>; Christoph Hellwig
> ><hch@lst.de>
> >Subject: Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
> >pstore/blk
> >
> >On Sat, 5 Jun 2021 at 12:31, Bhaskara Budiredla <bbudiredla@marvell.com>
> >wrote:
> >>
> >> Hi Uffe,
> >>
> >> With due respect to pstore/blk subsystem changes we have been waiting
> >since long time to see Christoph patches taken.
> >
> >What patches are you referring to?
> >
> >> But unfortunately it is still finding at that same stage only. Can you
> >> please take up my patch in the current form (which is based on current
> >> pstore/blk framework) instead of waiting indefinitely. If pstore/blk comes up
> >with the changes that has been discussed by you previously, I will further
> >submit the corresponding changes for eMMC devices.
> >
> >No, I am sorry, but that's not the way it works.
> >
> >If you really want to move things forward, I would suggest that you try to
> >implement something along the lines of what I have suggested.
> >Another option is to post an RFD/RFC so as solution can be discussed with the
> >relevant people.
> >
> >Kind regards
> >Uffe
> >
> >>
> >> Thanks,
> >> Bhaskara
> >>
> >> >-----Original Message-----
> >> >From: Ulf Hansson <ulf.hansson@linaro.org>
> >> >Sent: Wednesday, January 20, 2021 8:36 PM
> >> >To: Bhaskara Budiredla <bbudiredla@marvell.com>; Kees Cook
> >> ><keescook@chromium.org>
> >> >Cc: Colin Cross <ccross@android.com>; Tony Luck
> >> ><tony.luck@intel.com>; Sunil Kovvuri Goutham <sgoutham@marvell.com>;
> >> >linux- mmc@vger.kernel.org; Linux Kernel Mailing List <linux-
> >> >kernel@vger.kernel.org>; linux-block <linux-block@vger.kernel.org>;
> >> >Jens Axboe <axboe@kernel.dk>; Christoph Hellwig <hch@lst.de>
> >> >Subject: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
> >> >pstore/blk
> >> >
> >> >External Email
> >> >
> >> >---------------------------------------------------------------------
> >> >-
> >> >+ linux-block, Jens, Christoph
> >> >
> >> >On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla
> >> ><bbudiredla@marvell.com> wrote:
> >> >>
> >> >> This patch introduces to mmcpstore. The functioning of mmcpstore is
> >> >> similar to mtdpstore. mmcpstore works on FTL based flash devices
> >> >> whereas mtdpstore works on raw flash devices. When the system
> >> >> crashes, mmcpstore stores the kmsg panic and oops logs to a user
> >> >> specified MMC device.
> >> >>
> >> >> It collects the details about the host MMC device through
> >> >> pstore/blk "blkdev" parameter. The user can specify the MMC device
> >> >> in many ways by checking in Documentation/admin-guide/pstore-blk.rst.
> >> >>
> >> >> The individual mmc host drivers have to define suitable polling and
> >> >> cleanup subroutines to write kmsg panic/oops logs through mmcpstore.
> >> >> These new host operations are needed as pstore panic write runs
> >> >> with interrupts disabled.
> >> >
> >> >Okay, let me again try to clarify on how I see this to move this forward.
> >> >
> >> >1)
> >> >In my opinion, pstore shouldn't be using callbacks for *regular* I/O
> >> >read/writes. It's upside-down of how the storage stack is designed to work.
> >> >
> >> >Instead, pstore should be implemented as a regular filesystem, that
> >> >can be mounted on top of a regular block device partition. In this
> >> >way, the lower layer block device drivers (as mmc), don't need
> >> >special support for pstore, the regular I/O block read/write path will just
> >work as is.
> >> >
> >> >2)
> >> >When it comes to supporting *panic* writes for pstore, things become
> >> >a bit more complicated. For sure some adaptations are needed in each
> >> >block device driver to support this.
> >> >
> >> >However, the current method means relying on the lower level block
> >> >device driver to figure out the pstore partition. Based on that, it
> >> >should then register itself for pstore support and hook up callbacks
> >> >for the corresponding block device driver instance, at least that is
> >> >what it looks like to me. Again, I think this is upside-down from the
> >> >storage stack perspective. The partition to use for pstore, should be based
> >upon its file system mount point.
> >> >
> >> >Furthermore, I think the responsibility for lower layer block device
> >> >drivers should instead be to just "register/announce" themselves as
> >> >capable of supporting "panic writes", if they can. Exactly how to
> >> >best do this, probably needs to be discussed further with the block
> >> >device people, I think. I have looped in Jens and Christoph, perhaps they
> >can share their opinion in this.
> >> >
> >> >That said, it looks to me that pstore needs more work before it's
> >> >ready to be adopted for generic support in block device drivers.
> >> >
> >> >Kind regards
> >> >Uffe
> >> >
> >> >>
> >> >> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
> >> >> ---
> >> >>  drivers/mmc/core/Kconfig     |  14 ++-
> >> >>  drivers/mmc/core/Makefile    |   1 +
> >> >>  drivers/mmc/core/block.c     |  19 +++
> >> >>  drivers/mmc/core/block.h     |   9 ++
> >> >>  drivers/mmc/core/core.c      |  44 +++++++
> >> >>  drivers/mmc/core/mmcpstore.c | 227
> >> >+++++++++++++++++++++++++++++++++++
> >> >>  include/linux/mmc/core.h     |   5 +
> >> >>  include/linux/mmc/host.h     |  12 ++
> >> >>  8 files changed, 330 insertions(+), 1 deletion(-)  create mode
> >> >> 100644 drivers/mmc/core/mmcpstore.c
> >> >>
> >> >> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
> >> >> index
> >> >> c12fe13e4b14..4c651da4f2d2 100644
> >> >> --- a/drivers/mmc/core/Kconfig
> >> >> +++ b/drivers/mmc/core/Kconfig
> >> >> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
> >> >>           This driver can also be built as a module. If so, the module
> >> >>           will be called pwrseq_simple.
> >> >>
> >> >> +config MMC_PSTORE_BACKEND
> >> >> +       bool "Log panic/oops to a MMC buffer"
> >> >> +       depends on MMC_BLOCK
> >> >> +       help
> >> >> +         This option will let you create platform backend to store kmsg
> >> >> +         crash dumps to a user specified MMC device. This is primarily
> >> >> +         based on pstore/blk.
> >> >> +
> >> >> +config MMC_PSTORE
> >> >> +       tristate
> >> >> +       select PSTORE_BLK
> >> >> +
> >> >>  config MMC_BLOCK
> >> >>         tristate "MMC block device driver"
> >> >>         depends on BLOCK
> >> >> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
> >> >>         default y
> >> >>         help
> >> >>           Say Y here to enable the MMC block device driver support.
> >> >> @@ -80,4 +93,3 @@ config MMC_TEST
> >> >>
> >> >>           This driver is only of interest to those developing or
> >> >>           testing a host driver. Most people should say N here.
> >> >> -
> >> >> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
> >> >> index 95ffe008ebdf..7cb9a3af4827 100644
> >> >> --- a/drivers/mmc/core/Makefile
> >> >> +++ b/drivers/mmc/core/Makefile
> >> >> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     +=
> >pwrseq_emmc.o
> >> >>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
> >> >>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
> >> >>  mmc_block-objs                 := block.o queue.o
> >> >> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
> >> >>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
> >> >>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
> >> >> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> >> >> index
> >> >> 42e27a298218..6592722cd7b2 100644
> >> >> --- a/drivers/mmc/core/block.c
> >> >> +++ b/drivers/mmc/core/block.c
> >> >> @@ -2870,6 +2870,21 @@ static void mmc_blk_remove_debugfs(struct
> >> >> mmc_card *card,
> >> >>
> >> >>  #endif /* CONFIG_DEBUG_FS */
> >> >>
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
> >> >> +sector_t *size) {
> >> >> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
> >> >> +       struct gendisk *disk = md->disk;
> >> >> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
> >> >> +
> >> >> +       if (part_num < 0 || part_num >= part_tbl->len)
> >> >> +               return 0;
> >> >> +
> >> >> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
> >> >> +       return part_tbl->part[part_num]->start_sect;
> >> >> +}
> >> >> +#endif
> >> >> +
> >> >>  static int mmc_blk_probe(struct mmc_card *card)  {
> >> >>         struct mmc_blk_data *md, *part_md; @@ -2913,6 +2928,9 @@
> >> >> static int mmc_blk_probe(struct mmc_card *card)
> >> >>                         goto out;
> >> >>         }
> >> >>
> >> >> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
> >> >> +               mmcpstore_card_set(card, md->disk->disk_name);
> >> >> +
> >> >>         /* Add two debugfs entries */
> >> >>         mmc_blk_add_debugfs(card, md);
> >> >>
> >> >> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
> >> >>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
> >> >>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
> >> >>         bus_unregister(&mmc_rpmb_bus_type);
> >> >> +       unregister_mmcpstore();
> >> >>  }
> >> >>
> >> >>  module_init(mmc_blk_init);
> >> >> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
> >> >> index
> >> >> 31153f656f41..2a4ee5568194 100644
> >> >> --- a/drivers/mmc/core/block.h
> >> >> +++ b/drivers/mmc/core/block.h
> >> >> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue
> >> >*mq);
> >> >> struct work_struct;
> >> >>
> >> >>  void mmc_blk_mq_complete_work(struct work_struct *work);
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +sector_t mmc_blk_get_part(struct mmc_card *card, int part_num,
> >> >> +sector_t *size); void mmcpstore_card_set(struct mmc_card *card,
> >> >> +const char *disk_name); void unregister_mmcpstore(void); #else
> >> >> +static inline void mmcpstore_card_set(struct mmc_card *card,
> >> >> +                                       const char *disk_name) {}
> >> >> +static inline void unregister_mmcpstore(void) {} #endif
> >> >>
> >> >>  #endif
> >> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> >> >> index 19f1ee57fb34..7ad7ff1cab8c 100644
> >> >> --- a/drivers/mmc/core/core.c
> >> >> +++ b/drivers/mmc/core/core.c
> >> >> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host *host)
> >}
> >> >> EXPORT_SYMBOL(mmc_cqe_recovery);
> >> >>
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +/**
> >> >> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
> >> >> + *     @host: MMC host to start command
> >> >> + *     @mrq: MMC request to start
> >> >> + *
> >> >> + *     Start a blocking MMC request for a host and wait for the request
> >> >> + *     to complete that is based on polling and timeout.
> >> >> + */
> >> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
> >> >> +mmc_request *mrq) {
> >> >> +       unsigned int timeout;
> >> >> +
> >> >> +       host->ops->req_cleanup_pending(host);
> >> >> +       mmc_start_request(host, mrq);
> >> >> +
> >> >> +       if (mrq->data) {
> >> >> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
> >> >> +               host->ops->req_completion_poll(host, timeout);
> >> >> +       }
> >> >> +}
> >> >> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
> >> >> +#endif
> >> >> +
> >> >>  /**
> >> >>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is
> >> >done
> >> >>   *     @host: MMC host
> >> >> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host *host,
> >> >> struct mmc_ctx *ctx,  }  EXPORT_SYMBOL(__mmc_claim_host);
> >> >>
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +/**
> >> >> + *     mmc_claim_host_async - claim host in atomic context
> >> >> + *     @host: mmc host to claim
> >> >> + *
> >> >> + *     This routine may be called in panic/oops scenarios.
> >> >> + *     Return zero with host claim success, else busy status.
> >> >> + */
> >> >> +int mmc_claim_host_async(struct mmc_host *host) {
> >> >> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
> >> >> +               host->claimed = 1;
> >> >> +               return 0;
> >> >> +       }
> >> >> +
> >> >> +       return -EBUSY;
> >> >> +}
> >> >> +EXPORT_SYMBOL(mmc_claim_host_async);
> >> >> +#endif
> >> >> +
> >> >>  /**
> >> >>   *     mmc_release_host - release a host
> >> >>   *     @host: mmc host to release
> >> >> diff --git a/drivers/mmc/core/mmcpstore.c
> >> >> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
> >> >> 000000000000..f783ea215f18
> >> >> --- /dev/null
> >> >> +++ b/drivers/mmc/core/mmcpstore.c
> >> >> @@ -0,0 +1,227 @@
> >> >> +// SPDX-License-Identifier: GPL-2.0
> >> >> +/*
> >> >> + * MMC pstore support based on pstore/blk
> >> >> + *
> >> >> + * Copyright (c) 2020 Marvell.
> >> >> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>  */
> >> >> +
> >> >> +#define pr_fmt(fmt) "mmcpstore: " fmt
> >> >> +
> >> >> +#include <linux/kernel.h>
> >> >> +#include <linux/module.h>
> >> >> +#include <linux/pstore_blk.h>
> >> >> +#include <linux/blkdev.h>
> >> >> +#include <linux/mount.h>
> >> >> +#include <linux/slab.h>
> >> >> +#include <linux/mmc/mmc.h>
> >> >> +#include <linux/mmc/host.h>
> >> >> +#include <linux/mmc/card.h>
> >> >> +#include <linux/scatterlist.h>
> >> >> +#include "block.h"
> >> >> +#include "card.h"
> >> >> +#include "core.h"
> >> >> +
> >> >> +static struct mmcpstore_context {
> >> >> +       char dev_name[BDEVNAME_SIZE];
> >> >> +       int partno;
> >> >> +       sector_t start_sect;
> >> >> +       sector_t size;
> >> >> +       struct pstore_blk_config conf;
> >> >> +       struct pstore_blk_info info;
> >> >> +
> >> >> +       struct mmc_card *card;
> >> >> +       struct mmc_request *mrq;
> >> >> +} oops_cxt;
> >> >> +
> >> >> +static void mmc_prep_req(struct mmc_request *mrq,
> >> >> +               unsigned int sect_offset, unsigned int nsects,
> >> >> +               struct scatterlist *sg, u32 opcode, unsigned int
> >> >> +flags) {
> >> >> +       mrq->cmd->opcode = opcode;
> >> >> +       mrq->cmd->arg = sect_offset;
> >> >> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> >> >> +
> >> >> +       if (nsects == 1) {
> >> >> +               mrq->stop = NULL;
> >> >> +       } else {
> >> >> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
> >> >> +               mrq->stop->arg = 0;
> >> >> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
> >> >> +       }
> >> >> +
> >> >> +       mrq->data->blksz = SECTOR_SIZE;
> >> >> +       mrq->data->blocks = nsects;
> >> >> +       mrq->data->flags = flags;
> >> >> +       mrq->data->sg = sg;
> >> >> +       mrq->data->sg_len = 1;
> >> >> +}
> >> >> +
> >> >> +static int mmcpstore_panic_write_req(const char *buf,
> >> >> +               unsigned int nsects, unsigned int sect_offset) {
> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> >> +       struct mmc_request *mrq = cxt->mrq;
> >> >> +       struct mmc_card *card = cxt->card;
> >> >> +       struct mmc_host *host = card->host;
> >> >> +       struct scatterlist sg;
> >> >> +       u32 opcode;
> >> >> +       int ret;
> >> >> +
> >> >> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
> >> >MMC_WRITE_BLOCK;
> >> >> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode,
> >> >MMC_DATA_WRITE);
> >> >> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
> >> >> +       mmc_set_data_timeout(mrq->data, cxt->card);
> >> >> +
> >> >> +       ret = mmc_claim_host_async(host);
> >> >> +       if (ret)
> >> >> +               return ret;
> >> >> +
> >> >> +       mmc_wait_for_pstore_req(host, mrq);
> >> >> +       return 0;
> >> >> +}
> >> >> +
> >> >> +static int mmcpstore_panic_write(const char *buf, sector_t off,
> >> >> +sector_t sects) {
> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> >> +       int ret;
> >> >> +
> >> >> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect + off);
> >> >> +       if (ret)
> >> >> +               return ret;
> >> >> +
> >> >> +       return 0;
> >> >> +}
> >> >> +
> >> >> +static struct block_device *mmcpstore_open_backend(const char
> >> >> +*device) {
> >> >> +       struct block_device *bdev;
> >> >> +       dev_t devt;
> >> >> +
> >> >> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
> >> >> +       if (IS_ERR(bdev)) {
> >> >> +               devt = name_to_dev_t(device);
> >> >> +               if (devt == 0)
> >> >> +                       return ERR_PTR(-ENODEV);
> >> >> +
> >> >> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
> >> >> +               if (IS_ERR(bdev))
> >> >> +                       return bdev;
> >> >> +       }
> >> >> +
> >> >> +       return bdev;
> >> >> +}
> >> >> +
> >> >> +static void mmcpstore_close_backend(struct block_device *bdev) {
> >> >> +       if (!bdev)
> >> >> +               return;
> >> >> +       blkdev_put(bdev, FMODE_READ); }
> >> >> +
> >> >> +void mmcpstore_card_set(struct mmc_card *card, const char
> >> >> +*disk_name) {
> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> >> +       struct pstore_blk_config *conf = &cxt->conf;
> >> >> +       struct pstore_blk_info *info = &cxt->info;
> >> >> +       struct block_device *bdev;
> >> >> +       struct mmc_command *stop;
> >> >> +       struct mmc_command *cmd;
> >> >> +       struct mmc_request *mrq;
> >> >> +       struct mmc_data *data;
> >> >> +       int ret;
> >> >> +
> >> >> +       ret = pstore_blk_get_config(conf);
> >> >> +       if (!conf->device[0]) {
> >> >> +               pr_debug("psblk backend is empty\n");
> >> >> +               return;
> >> >> +       }
> >> >> +
> >> >> +       /* Multiple backend devices not allowed */
> >> >> +       if (cxt->dev_name[0])
> >> >> +               return;
> >> >> +
> >> >> +       bdev =  mmcpstore_open_backend(conf->device);
> >> >> +       if (IS_ERR(bdev)) {
> >> >> +               pr_err("%s failed to open with %ld\n",
> >> >> +                               conf->device, PTR_ERR(bdev));
> >> >> +               return;
> >> >> +       }
> >> >> +
> >> >> +       bdevname(bdev, cxt->dev_name);
> >> >> +       cxt->partno = bdev->bd_part->partno;
> >> >> +       mmcpstore_close_backend(bdev);
> >> >> +
> >> >> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
> >> >> +               return;
> >> >> +
> >> >> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt->size);
> >> >> +       if (!cxt->start_sect) {
> >> >> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
> >> >> +               return;
> >> >> +       }
> >> >> +
> >> >> +       /* Check for host mmc panic write polling function definitions */
> >> >> +       if (!card->host->ops->req_cleanup_pending ||
> >> >> +                       !card->host->ops->req_completion_poll)
> >> >> +               return;
> >> >> +
> >> >> +       cxt->card = card;
> >> >> +
> >> >> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
> >> >> +       if (!mrq)
> >> >> +               goto out;
> >> >> +
> >> >> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> >> >> +       if (!cmd)
> >> >> +               goto free_mrq;
> >> >> +
> >> >> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
> >> >> +       if (!stop)
> >> >> +               goto free_cmd;
> >> >> +
> >> >> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
> >> >> +       if (!data)
> >> >> +               goto free_stop;
> >> >> +
> >> >> +       mrq->cmd = cmd;
> >> >> +       mrq->data = data;
> >> >> +       mrq->stop = stop;
> >> >> +       cxt->mrq = mrq;
> >> >> +
> >> >> +       info->major = MMC_BLOCK_MAJOR;
> >> >> +       info->flags = PSTORE_FLAGS_DMESG;
> >> >> +       info->panic_write = mmcpstore_panic_write;
> >> >> +       ret = register_pstore_blk(info);
> >> >> +       if (ret) {
> >> >> +               pr_err("%s registering with psblk failed (%d)\n",
> >> >> +                               cxt->dev_name, ret);
> >> >> +               goto free_data;
> >> >> +       }
> >> >> +
> >> >> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
> >> >> +       return;
> >> >> +
> >> >> +free_data:
> >> >> +       kfree(data);
> >> >> +free_stop:
> >> >> +       kfree(stop);
> >> >> +free_cmd:
> >> >> +       kfree(cmd);
> >> >> +free_mrq:
> >> >> +       kfree(mrq);
> >> >> +out:
> >> >> +       return;
> >> >> +}
> >> >> +
> >> >> +void unregister_mmcpstore(void)
> >> >> +{
> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
> >> >> +
> >> >> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
> >> >> +       kfree(cxt->mrq->data);
> >> >> +       kfree(cxt->mrq->stop);
> >> >> +       kfree(cxt->mrq->cmd);
> >> >> +       kfree(cxt->mrq);
> >> >> +       cxt->card = NULL;
> >> >> +}
> >> >> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> >> >> index 29aa50711626..53840a361b5a 100644
> >> >> --- a/include/linux/mmc/core.h
> >> >> +++ b/include/linux/mmc/core.h
> >> >> @@ -166,6 +166,11 @@ struct mmc_request {
> >> >>
> >> >>  struct mmc_card;
> >> >>
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
> >> >> +mmc_request *mrq); int mmc_claim_host_async(struct mmc_host
> >> >> +*host); #endif
> >> >> +
> >> >>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request
> >> >> *mrq);  int mmc_wait_for_cmd(struct mmc_host *host, struct
> >> >mmc_command *cmd,
> >> >>                 int retries);
> >> >> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> >> >> index
> >> >> 01bba36545c5..ba9001498e03 100644
> >> >> --- a/include/linux/mmc/host.h
> >> >> +++ b/include/linux/mmc/host.h
> >> >> @@ -178,6 +178,18 @@ struct mmc_host_ops {
> >> >>
> >> >>         /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP.
> >*/
> >> >>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios
> >*ios);
> >> >> +
> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
> >> >> +       /*
> >> >> +        * The following two APIs are introduced to support mmcpstore
> >> >> +        * functionality. Cleanup API to terminate the ongoing and
> >> >> +        * pending requests before a panic write post, and polling API
> >> >> +        * to ensure that write succeeds before the Kernel dies.
> >> >> +        */
> >> >> +       void    (*req_cleanup_pending)(struct mmc_host *host);
> >> >> +       int     (*req_completion_poll)(struct mmc_host *host,
> >> >> +                                      unsigned long timeout);
> >> >> +#endif
> >> >>  };
> >> >>
> >> >>  struct mmc_cqe_ops {
> >> >> --
> >> >> 2.17.1
> >> >>

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

* RE: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-07 14:07           ` Ulf Hansson
@ 2021-06-07 16:28             ` Bhaskara Budiredla
  0 siblings, 0 replies; 14+ messages in thread
From: Bhaskara Budiredla @ 2021-06-07 16:28 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Kees Cook, Colin Cross, Tony Luck, Sunil Kovvuri Goutham,
	linux-mmc, Linux Kernel Mailing List, linux-block, Jens Axboe,
	Christoph Hellwig

Hi Christoph,

Could you please share the current state of your work @https://urldefense.proofpoint.com/v2/url?u=http-3A__git.infradead.org_
and provide some direction on Uffe's comments?

Thanks,
Bhaskara


>-----Original Message-----
>From: Ulf Hansson <ulf.hansson@linaro.org>
>Sent: Monday, June 7, 2021 7:38 PM
>To: Bhaskara Budiredla <bbudiredla@marvell.com>
>Cc: Kees Cook <keescook@chromium.org>; Colin Cross
><ccross@android.com>; Tony Luck <tony.luck@intel.com>; Sunil Kovvuri
>Goutham <sgoutham@marvell.com>; linux-mmc@vger.kernel.org; Linux
>Kernel Mailing List <linux-kernel@vger.kernel.org>; linux-block <linux-
>block@vger.kernel.org>; Jens Axboe <axboe@kernel.dk>; Christoph Hellwig
><hch@lst.de>
>Subject: Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Mon, 7 Jun 2021 at 14:37, Bhaskara Budiredla <bbudiredla@marvell.com>
>wrote:
>>
>> [...]
>> >What patches are you referring to?
>>
>> I was referring to this patch.
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__git.infradead.org_
>>
>users_hch_misc.git_shortlog_refs_heads_pstore&d=DwIBaQ&c=nKjWec2b6R0
>mO
>>
>yPaz7xtfQ&r=9P_lSljSO7KnQNkCGsgu9x_Op4mstSdqWN3Olr4bUv0&m=fl42xU
>Yo4DOO
>> I8uNNOE4Av-fan25pMik8lX5H4G0694&s=tTmGbewO2pg-
>_9D0vAb_GNucJuZAjJCFkuSz
>> 6whJGho&e=
>
>Alright. I didn't know about these, thanks for the pointer. Looks like a big step
>in the right direction.
>
>I guess Christoph simply has been busy with other things. Perhaps you should
>ask if you can help and pick up from where he left the series?
>
>Kind regards
>Uffe
>
>>
>> Thanks,
>> Bhaskara
>>
>> >-----Original Message-----
>> >From: Ulf Hansson <ulf.hansson@linaro.org>
>> >Sent: Monday, June 7, 2021 4:47 PM
>> >To: Bhaskara Budiredla <bbudiredla@marvell.com>
>> >Cc: Kees Cook <keescook@chromium.org>; Colin Cross
>> ><ccross@android.com>; Tony Luck <tony.luck@intel.com>; Sunil Kovvuri
>> >Goutham <sgoutham@marvell.com>; linux-mmc@vger.kernel.org; Linux
>> >Kernel Mailing List <linux-kernel@vger.kernel.org>; linux-block
>> ><linux- block@vger.kernel.org>; Jens Axboe <axboe@kernel.dk>;
>> >Christoph Hellwig <hch@lst.de>
>> >Subject: Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based
>> >on pstore/blk
>> >
>> >On Sat, 5 Jun 2021 at 12:31, Bhaskara Budiredla
>> ><bbudiredla@marvell.com>
>> >wrote:
>> >>
>> >> Hi Uffe,
>> >>
>> >> With due respect to pstore/blk subsystem changes we have been
>> >> waiting
>> >since long time to see Christoph patches taken.
>> >
>> >What patches are you referring to?
>> >
>> >> But unfortunately it is still finding at that same stage only. Can
>> >> you please take up my patch in the current form (which is based on
>> >> current pstore/blk framework) instead of waiting indefinitely. If
>> >> pstore/blk comes up
>> >with the changes that has been discussed by you previously, I will
>> >further submit the corresponding changes for eMMC devices.
>> >
>> >No, I am sorry, but that's not the way it works.
>> >
>> >If you really want to move things forward, I would suggest that you
>> >try to implement something along the lines of what I have suggested.
>> >Another option is to post an RFD/RFC so as solution can be discussed
>> >with the relevant people.
>> >
>> >Kind regards
>> >Uffe
>> >
>> >>
>> >> Thanks,
>> >> Bhaskara
>> >>
>> >> >-----Original Message-----
>> >> >From: Ulf Hansson <ulf.hansson@linaro.org>
>> >> >Sent: Wednesday, January 20, 2021 8:36 PM
>> >> >To: Bhaskara Budiredla <bbudiredla@marvell.com>; Kees Cook
>> >> ><keescook@chromium.org>
>> >> >Cc: Colin Cross <ccross@android.com>; Tony Luck
>> >> ><tony.luck@intel.com>; Sunil Kovvuri Goutham
>> >> ><sgoutham@marvell.com>;
>> >> >linux- mmc@vger.kernel.org; Linux Kernel Mailing List <linux-
>> >> >kernel@vger.kernel.org>; linux-block
>> >> ><linux-block@vger.kernel.org>; Jens Axboe <axboe@kernel.dk>;
>> >> >Christoph Hellwig <hch@lst.de>
>> >> >Subject: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based
>> >> >on pstore/blk
>> >> >
>> >> >External Email
>> >> >
>> >> >------------------------------------------------------------------
>> >> >---
>> >> >-
>> >> >+ linux-block, Jens, Christoph
>> >> >
>> >> >On Wed, 20 Jan 2021 at 13:11, Bhaskara Budiredla
>> >> ><bbudiredla@marvell.com> wrote:
>> >> >>
>> >> >> This patch introduces to mmcpstore. The functioning of mmcpstore
>> >> >> is similar to mtdpstore. mmcpstore works on FTL based flash
>> >> >> devices whereas mtdpstore works on raw flash devices. When the
>> >> >> system crashes, mmcpstore stores the kmsg panic and oops logs to
>> >> >> a user specified MMC device.
>> >> >>
>> >> >> It collects the details about the host MMC device through
>> >> >> pstore/blk "blkdev" parameter. The user can specify the MMC
>> >> >> device in many ways by checking in Documentation/admin-
>guide/pstore-blk.rst.
>> >> >>
>> >> >> The individual mmc host drivers have to define suitable polling
>> >> >> and cleanup subroutines to write kmsg panic/oops logs through
>mmcpstore.
>> >> >> These new host operations are needed as pstore panic write runs
>> >> >> with interrupts disabled.
>> >> >
>> >> >Okay, let me again try to clarify on how I see this to move this forward.
>> >> >
>> >> >1)
>> >> >In my opinion, pstore shouldn't be using callbacks for *regular*
>> >> >I/O read/writes. It's upside-down of how the storage stack is designed
>to work.
>> >> >
>> >> >Instead, pstore should be implemented as a regular filesystem,
>> >> >that can be mounted on top of a regular block device partition. In
>> >> >this way, the lower layer block device drivers (as mmc), don't
>> >> >need special support for pstore, the regular I/O block read/write
>> >> >path will just
>> >work as is.
>> >> >
>> >> >2)
>> >> >When it comes to supporting *panic* writes for pstore, things
>> >> >become a bit more complicated. For sure some adaptations are
>> >> >needed in each block device driver to support this.
>> >> >
>> >> >However, the current method means relying on the lower level block
>> >> >device driver to figure out the pstore partition. Based on that,
>> >> >it should then register itself for pstore support and hook up
>> >> >callbacks for the corresponding block device driver instance, at
>> >> >least that is what it looks like to me. Again, I think this is
>> >> >upside-down from the storage stack perspective. The partition to
>> >> >use for pstore, should be based
>> >upon its file system mount point.
>> >> >
>> >> >Furthermore, I think the responsibility for lower layer block
>> >> >device drivers should instead be to just "register/announce"
>> >> >themselves as capable of supporting "panic writes", if they can.
>> >> >Exactly how to best do this, probably needs to be discussed
>> >> >further with the block device people, I think. I have looped in
>> >> >Jens and Christoph, perhaps they
>> >can share their opinion in this.
>> >> >
>> >> >That said, it looks to me that pstore needs more work before it's
>> >> >ready to be adopted for generic support in block device drivers.
>> >> >
>> >> >Kind regards
>> >> >Uffe
>> >> >
>> >> >>
>> >> >> Signed-off-by: Bhaskara Budiredla <bbudiredla@marvell.com>
>> >> >> ---
>> >> >>  drivers/mmc/core/Kconfig     |  14 ++-
>> >> >>  drivers/mmc/core/Makefile    |   1 +
>> >> >>  drivers/mmc/core/block.c     |  19 +++
>> >> >>  drivers/mmc/core/block.h     |   9 ++
>> >> >>  drivers/mmc/core/core.c      |  44 +++++++
>> >> >>  drivers/mmc/core/mmcpstore.c | 227
>> >> >+++++++++++++++++++++++++++++++++++
>> >> >>  include/linux/mmc/core.h     |   5 +
>> >> >>  include/linux/mmc/host.h     |  12 ++
>> >> >>  8 files changed, 330 insertions(+), 1 deletion(-)  create mode
>> >> >> 100644 drivers/mmc/core/mmcpstore.c
>> >> >>
>> >> >> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>> >> >> index
>> >> >> c12fe13e4b14..4c651da4f2d2 100644
>> >> >> --- a/drivers/mmc/core/Kconfig
>> >> >> +++ b/drivers/mmc/core/Kconfig
>> >> >> @@ -34,9 +34,22 @@ config PWRSEQ_SIMPLE
>> >> >>           This driver can also be built as a module. If so, the module
>> >> >>           will be called pwrseq_simple.
>> >> >>
>> >> >> +config MMC_PSTORE_BACKEND
>> >> >> +       bool "Log panic/oops to a MMC buffer"
>> >> >> +       depends on MMC_BLOCK
>> >> >> +       help
>> >> >> +         This option will let you create platform backend to store kmsg
>> >> >> +         crash dumps to a user specified MMC device. This is primarily
>> >> >> +         based on pstore/blk.
>> >> >> +
>> >> >> +config MMC_PSTORE
>> >> >> +       tristate
>> >> >> +       select PSTORE_BLK
>> >> >> +
>> >> >>  config MMC_BLOCK
>> >> >>         tristate "MMC block device driver"
>> >> >>         depends on BLOCK
>> >> >> +       select MMC_PSTORE if MMC_PSTORE_BACKEND=y
>> >> >>         default y
>> >> >>         help
>> >> >>           Say Y here to enable the MMC block device driver support.
>> >> >> @@ -80,4 +93,3 @@ config MMC_TEST
>> >> >>
>> >> >>           This driver is only of interest to those developing or
>> >> >>           testing a host driver. Most people should say N here.
>> >> >> -
>> >> >> diff --git a/drivers/mmc/core/Makefile
>> >> >> b/drivers/mmc/core/Makefile index 95ffe008ebdf..7cb9a3af4827
>> >> >> 100644
>> >> >> --- a/drivers/mmc/core/Makefile
>> >> >> +++ b/drivers/mmc/core/Makefile
>> >> >> @@ -16,5 +16,6 @@ obj-$(CONFIG_PWRSEQ_EMMC)     +=
>> >pwrseq_emmc.o
>> >> >>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>> >> >>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>> >> >>  mmc_block-objs                 := block.o queue.o
>> >> >> +mmc_block-$(CONFIG_MMC_PSTORE) += mmcpstore.o
>> >> >>  obj-$(CONFIG_MMC_TEST)         += mmc_test.o
>> >> >>  obj-$(CONFIG_SDIO_UART)                += sdio_uart.o
>> >> >> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
>> >> >> index
>> >> >> 42e27a298218..6592722cd7b2 100644
>> >> >> --- a/drivers/mmc/core/block.c
>> >> >> +++ b/drivers/mmc/core/block.c
>> >> >> @@ -2870,6 +2870,21 @@ static void
>mmc_blk_remove_debugfs(struct
>> >> >> mmc_card *card,
>> >> >>
>> >> >>  #endif /* CONFIG_DEBUG_FS */
>> >> >>
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE) sector_t
>> >> >> +mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t
>> >> >> +*size) {
>> >> >> +       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
>> >> >> +       struct gendisk *disk = md->disk;
>> >> >> +       struct disk_part_tbl *part_tbl = disk->part_tbl;
>> >> >> +
>> >> >> +       if (part_num < 0 || part_num >= part_tbl->len)
>> >> >> +               return 0;
>> >> >> +
>> >> >> +       *size = part_tbl->part[part_num]->nr_sects << SECTOR_SHIFT;
>> >> >> +       return part_tbl->part[part_num]->start_sect;
>> >> >> +}
>> >> >> +#endif
>> >> >> +
>> >> >>  static int mmc_blk_probe(struct mmc_card *card)  {
>> >> >>         struct mmc_blk_data *md, *part_md; @@ -2913,6 +2928,9 @@
>> >> >> static int mmc_blk_probe(struct mmc_card *card)
>> >> >>                         goto out;
>> >> >>         }
>> >> >>
>> >> >> +       if (mmc_card_mmc(card) || mmc_card_sd(card))
>> >> >> +               mmcpstore_card_set(card, md->disk->disk_name);
>> >> >> +
>> >> >>         /* Add two debugfs entries */
>> >> >>         mmc_blk_add_debugfs(card, md);
>> >> >>
>> >> >> @@ -3060,6 +3078,7 @@ static void __exit mmc_blk_exit(void)
>> >> >>         unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
>> >> >>         unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
>> >> >>         bus_unregister(&mmc_rpmb_bus_type);
>> >> >> +       unregister_mmcpstore();
>> >> >>  }
>> >> >>
>> >> >>  module_init(mmc_blk_init);
>> >> >> diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
>> >> >> index
>> >> >> 31153f656f41..2a4ee5568194 100644
>> >> >> --- a/drivers/mmc/core/block.h
>> >> >> +++ b/drivers/mmc/core/block.h
>> >> >> @@ -16,5 +16,14 @@ void mmc_blk_mq_recovery(struct mmc_queue
>> >> >*mq);
>> >> >> struct work_struct;
>> >> >>
>> >> >>  void mmc_blk_mq_complete_work(struct work_struct *work);
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE) sector_t
>> >> >> +mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t
>> >> >> +*size); void mmcpstore_card_set(struct mmc_card *card, const
>> >> >> +char *disk_name); void unregister_mmcpstore(void); #else static
>> >> >> +inline void mmcpstore_card_set(struct mmc_card *card,
>> >> >> +                                       const char *disk_name)
>> >> >> +{} static inline void unregister_mmcpstore(void) {} #endif
>> >> >>
>> >> >>  #endif
>> >> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> >> >> index 19f1ee57fb34..7ad7ff1cab8c 100644
>> >> >> --- a/drivers/mmc/core/core.c
>> >> >> +++ b/drivers/mmc/core/core.c
>> >> >> @@ -569,6 +569,30 @@ int mmc_cqe_recovery(struct mmc_host
>*host)
>> >}
>> >> >> EXPORT_SYMBOL(mmc_cqe_recovery);
>> >> >>
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> >> +/**
>> >> >> + *     mmc_wait_for_pstore_req - initiate a blocking mmc request
>> >> >> + *     @host: MMC host to start command
>> >> >> + *     @mrq: MMC request to start
>> >> >> + *
>> >> >> + *     Start a blocking MMC request for a host and wait for the request
>> >> >> + *     to complete that is based on polling and timeout.
>> >> >> + */
>> >> >> +void mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> >> >> +mmc_request *mrq) {
>> >> >> +       unsigned int timeout;
>> >> >> +
>> >> >> +       host->ops->req_cleanup_pending(host);
>> >> >> +       mmc_start_request(host, mrq);
>> >> >> +
>> >> >> +       if (mrq->data) {
>> >> >> +               timeout = mrq->data->timeout_ns / NSEC_PER_MSEC;
>> >> >> +               host->ops->req_completion_poll(host, timeout);
>> >> >> +       }
>> >> >> +}
>> >> >> +EXPORT_SYMBOL(mmc_wait_for_pstore_req);
>> >> >> +#endif
>> >> >> +
>> >> >>  /**
>> >> >>   *     mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request
>is
>> >> >done
>> >> >>   *     @host: MMC host
>> >> >> @@ -817,6 +841,26 @@ int __mmc_claim_host(struct mmc_host
>*host,
>> >> >> struct mmc_ctx *ctx,  }  EXPORT_SYMBOL(__mmc_claim_host);
>> >> >>
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> >> +/**
>> >> >> + *     mmc_claim_host_async - claim host in atomic context
>> >> >> + *     @host: mmc host to claim
>> >> >> + *
>> >> >> + *     This routine may be called in panic/oops scenarios.
>> >> >> + *     Return zero with host claim success, else busy status.
>> >> >> + */
>> >> >> +int mmc_claim_host_async(struct mmc_host *host) {
>> >> >> +       if (!host->claimed && pm_runtime_active(mmc_dev(host))) {
>> >> >> +               host->claimed = 1;
>> >> >> +               return 0;
>> >> >> +       }
>> >> >> +
>> >> >> +       return -EBUSY;
>> >> >> +}
>> >> >> +EXPORT_SYMBOL(mmc_claim_host_async);
>> >> >> +#endif
>> >> >> +
>> >> >>  /**
>> >> >>   *     mmc_release_host - release a host
>> >> >>   *     @host: mmc host to release
>> >> >> diff --git a/drivers/mmc/core/mmcpstore.c
>> >> >> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
>> >> >> 000000000000..f783ea215f18
>> >> >> --- /dev/null
>> >> >> +++ b/drivers/mmc/core/mmcpstore.c
>> >> >> @@ -0,0 +1,227 @@
>> >> >> +// SPDX-License-Identifier: GPL-2.0
>> >> >> +/*
>> >> >> + * MMC pstore support based on pstore/blk
>> >> >> + *
>> >> >> + * Copyright (c) 2020 Marvell.
>> >> >> + * Author: Bhaskara Budiredla <bbudiredla@marvell.com>  */
>> >> >> +
>> >> >> +#define pr_fmt(fmt) "mmcpstore: " fmt
>> >> >> +
>> >> >> +#include <linux/kernel.h>
>> >> >> +#include <linux/module.h>
>> >> >> +#include <linux/pstore_blk.h>
>> >> >> +#include <linux/blkdev.h>
>> >> >> +#include <linux/mount.h>
>> >> >> +#include <linux/slab.h>
>> >> >> +#include <linux/mmc/mmc.h>
>> >> >> +#include <linux/mmc/host.h>
>> >> >> +#include <linux/mmc/card.h>
>> >> >> +#include <linux/scatterlist.h>
>> >> >> +#include "block.h"
>> >> >> +#include "card.h"
>> >> >> +#include "core.h"
>> >> >> +
>> >> >> +static struct mmcpstore_context {
>> >> >> +       char dev_name[BDEVNAME_SIZE];
>> >> >> +       int partno;
>> >> >> +       sector_t start_sect;
>> >> >> +       sector_t size;
>> >> >> +       struct pstore_blk_config conf;
>> >> >> +       struct pstore_blk_info info;
>> >> >> +
>> >> >> +       struct mmc_card *card;
>> >> >> +       struct mmc_request *mrq; } oops_cxt;
>> >> >> +
>> >> >> +static void mmc_prep_req(struct mmc_request *mrq,
>> >> >> +               unsigned int sect_offset, unsigned int nsects,
>> >> >> +               struct scatterlist *sg, u32 opcode, unsigned int
>> >> >> +flags) {
>> >> >> +       mrq->cmd->opcode = opcode;
>> >> >> +       mrq->cmd->arg = sect_offset;
>> >> >> +       mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>> >> >> +
>> >> >> +       if (nsects == 1) {
>> >> >> +               mrq->stop = NULL;
>> >> >> +       } else {
>> >> >> +               mrq->stop->opcode = MMC_STOP_TRANSMISSION;
>> >> >> +               mrq->stop->arg = 0;
>> >> >> +               mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
>> >> >> +       }
>> >> >> +
>> >> >> +       mrq->data->blksz = SECTOR_SIZE;
>> >> >> +       mrq->data->blocks = nsects;
>> >> >> +       mrq->data->flags = flags;
>> >> >> +       mrq->data->sg = sg;
>> >> >> +       mrq->data->sg_len = 1;
>> >> >> +}
>> >> >> +
>> >> >> +static int mmcpstore_panic_write_req(const char *buf,
>> >> >> +               unsigned int nsects, unsigned int sect_offset) {
>> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> >> +       struct mmc_request *mrq = cxt->mrq;
>> >> >> +       struct mmc_card *card = cxt->card;
>> >> >> +       struct mmc_host *host = card->host;
>> >> >> +       struct scatterlist sg;
>> >> >> +       u32 opcode;
>> >> >> +       int ret;
>> >> >> +
>> >> >> +       opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
>> >> >MMC_WRITE_BLOCK;
>> >> >> +       mmc_prep_req(mrq, sect_offset, nsects, &sg, opcode,
>> >> >MMC_DATA_WRITE);
>> >> >> +       sg_init_one(&sg, buf, (nsects << SECTOR_SHIFT));
>> >> >> +       mmc_set_data_timeout(mrq->data, cxt->card);
>> >> >> +
>> >> >> +       ret = mmc_claim_host_async(host);
>> >> >> +       if (ret)
>> >> >> +               return ret;
>> >> >> +
>> >> >> +       mmc_wait_for_pstore_req(host, mrq);
>> >> >> +       return 0;
>> >> >> +}
>> >> >> +
>> >> >> +static int mmcpstore_panic_write(const char *buf, sector_t off,
>> >> >> +sector_t sects) {
>> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> >> +       int ret;
>> >> >> +
>> >> >> +       ret = mmcpstore_panic_write_req(buf, sects, cxt->start_sect +
>off);
>> >> >> +       if (ret)
>> >> >> +               return ret;
>> >> >> +
>> >> >> +       return 0;
>> >> >> +}
>> >> >> +
>> >> >> +static struct block_device *mmcpstore_open_backend(const char
>> >> >> +*device) {
>> >> >> +       struct block_device *bdev;
>> >> >> +       dev_t devt;
>> >> >> +
>> >> >> +       bdev = blkdev_get_by_path(device, FMODE_READ, NULL);
>> >> >> +       if (IS_ERR(bdev)) {
>> >> >> +               devt = name_to_dev_t(device);
>> >> >> +               if (devt == 0)
>> >> >> +                       return ERR_PTR(-ENODEV);
>> >> >> +
>> >> >> +               bdev = blkdev_get_by_dev(devt, FMODE_READ, NULL);
>> >> >> +               if (IS_ERR(bdev))
>> >> >> +                       return bdev;
>> >> >> +       }
>> >> >> +
>> >> >> +       return bdev;
>> >> >> +}
>> >> >> +
>> >> >> +static void mmcpstore_close_backend(struct block_device *bdev) {
>> >> >> +       if (!bdev)
>> >> >> +               return;
>> >> >> +       blkdev_put(bdev, FMODE_READ); }
>> >> >> +
>> >> >> +void mmcpstore_card_set(struct mmc_card *card, const char
>> >> >> +*disk_name) {
>> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> >> +       struct pstore_blk_config *conf = &cxt->conf;
>> >> >> +       struct pstore_blk_info *info = &cxt->info;
>> >> >> +       struct block_device *bdev;
>> >> >> +       struct mmc_command *stop;
>> >> >> +       struct mmc_command *cmd;
>> >> >> +       struct mmc_request *mrq;
>> >> >> +       struct mmc_data *data;
>> >> >> +       int ret;
>> >> >> +
>> >> >> +       ret = pstore_blk_get_config(conf);
>> >> >> +       if (!conf->device[0]) {
>> >> >> +               pr_debug("psblk backend is empty\n");
>> >> >> +               return;
>> >> >> +       }
>> >> >> +
>> >> >> +       /* Multiple backend devices not allowed */
>> >> >> +       if (cxt->dev_name[0])
>> >> >> +               return;
>> >> >> +
>> >> >> +       bdev =  mmcpstore_open_backend(conf->device);
>> >> >> +       if (IS_ERR(bdev)) {
>> >> >> +               pr_err("%s failed to open with %ld\n",
>> >> >> +                               conf->device, PTR_ERR(bdev));
>> >> >> +               return;
>> >> >> +       }
>> >> >> +
>> >> >> +       bdevname(bdev, cxt->dev_name);
>> >> >> +       cxt->partno = bdev->bd_part->partno;
>> >> >> +       mmcpstore_close_backend(bdev);
>> >> >> +
>> >> >> +       if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
>> >> >> +               return;
>> >> >> +
>> >> >> +       cxt->start_sect = mmc_blk_get_part(card, cxt->partno, &cxt-
>>size);
>> >> >> +       if (!cxt->start_sect) {
>> >> >> +               pr_err("Non-existent partition %d selected\n", cxt->partno);
>> >> >> +               return;
>> >> >> +       }
>> >> >> +
>> >> >> +       /* Check for host mmc panic write polling function definitions */
>> >> >> +       if (!card->host->ops->req_cleanup_pending ||
>> >> >> +                       !card->host->ops->req_completion_poll)
>> >> >> +               return;
>> >> >> +
>> >> >> +       cxt->card = card;
>> >> >> +
>> >> >> +       mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
>> >> >> +       if (!mrq)
>> >> >> +               goto out;
>> >> >> +
>> >> >> +       cmd = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> >> >> +       if (!cmd)
>> >> >> +               goto free_mrq;
>> >> >> +
>> >> >> +       stop = kzalloc(sizeof(struct mmc_command), GFP_KERNEL);
>> >> >> +       if (!stop)
>> >> >> +               goto free_cmd;
>> >> >> +
>> >> >> +       data = kzalloc(sizeof(struct mmc_data), GFP_KERNEL);
>> >> >> +       if (!data)
>> >> >> +               goto free_stop;
>> >> >> +
>> >> >> +       mrq->cmd = cmd;
>> >> >> +       mrq->data = data;
>> >> >> +       mrq->stop = stop;
>> >> >> +       cxt->mrq = mrq;
>> >> >> +
>> >> >> +       info->major = MMC_BLOCK_MAJOR;
>> >> >> +       info->flags = PSTORE_FLAGS_DMESG;
>> >> >> +       info->panic_write = mmcpstore_panic_write;
>> >> >> +       ret = register_pstore_blk(info);
>> >> >> +       if (ret) {
>> >> >> +               pr_err("%s registering with psblk failed (%d)\n",
>> >> >> +                               cxt->dev_name, ret);
>> >> >> +               goto free_data;
>> >> >> +       }
>> >> >> +
>> >> >> +       pr_info("%s registered as psblk backend\n", cxt->dev_name);
>> >> >> +       return;
>> >> >> +
>> >> >> +free_data:
>> >> >> +       kfree(data);
>> >> >> +free_stop:
>> >> >> +       kfree(stop);
>> >> >> +free_cmd:
>> >> >> +       kfree(cmd);
>> >> >> +free_mrq:
>> >> >> +       kfree(mrq);
>> >> >> +out:
>> >> >> +       return;
>> >> >> +}
>> >> >> +
>> >> >> +void unregister_mmcpstore(void) {
>> >> >> +       struct mmcpstore_context *cxt = &oops_cxt;
>> >> >> +
>> >> >> +       unregister_pstore_blk(MMC_BLOCK_MAJOR);
>> >> >> +       kfree(cxt->mrq->data);
>> >> >> +       kfree(cxt->mrq->stop);
>> >> >> +       kfree(cxt->mrq->cmd);
>> >> >> +       kfree(cxt->mrq);
>> >> >> +       cxt->card = NULL;
>> >> >> +}
>> >> >> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> >> >> index 29aa50711626..53840a361b5a 100644
>> >> >> --- a/include/linux/mmc/core.h
>> >> >> +++ b/include/linux/mmc/core.h
>> >> >> @@ -166,6 +166,11 @@ struct mmc_request {
>> >> >>
>> >> >>  struct mmc_card;
>> >> >>
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE) void
>> >> >> +mmc_wait_for_pstore_req(struct mmc_host *host, struct
>> >> >> +mmc_request *mrq); int mmc_claim_host_async(struct mmc_host
>> >> >> +*host); #endif
>> >> >> +
>> >> >>  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request
>> >> >> *mrq);  int mmc_wait_for_cmd(struct mmc_host *host, struct
>> >> >mmc_command *cmd,
>> >> >>                 int retries);
>> >> >> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> >> >> index
>> >> >> 01bba36545c5..ba9001498e03 100644
>> >> >> --- a/include/linux/mmc/host.h
>> >> >> +++ b/include/linux/mmc/host.h
>> >> >> @@ -178,6 +178,18 @@ struct mmc_host_ops {
>> >> >>
>> >> >>         /* Initialize an SD express card, mandatory for
>MMC_CAP2_SD_EXP.
>> >*/
>> >> >>         int     (*init_sd_express)(struct mmc_host *host, struct mmc_ios
>> >*ios);
>> >> >> +
>> >> >> +#if IS_ENABLED(CONFIG_MMC_PSTORE)
>> >> >> +       /*
>> >> >> +        * The following two APIs are introduced to support mmcpstore
>> >> >> +        * functionality. Cleanup API to terminate the ongoing and
>> >> >> +        * pending requests before a panic write post, and polling API
>> >> >> +        * to ensure that write succeeds before the Kernel dies.
>> >> >> +        */
>> >> >> +       void    (*req_cleanup_pending)(struct mmc_host *host);
>> >> >> +       int     (*req_completion_poll)(struct mmc_host *host,
>> >> >> +                                      unsigned long timeout);
>> >> >> +#endif
>> >> >>  };
>> >> >>
>> >> >>  struct mmc_cqe_ops {
>> >> >> --
>> >> >> 2.17.1
>> >> >>

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

* Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-07 11:17       ` Ulf Hansson
  2021-06-07 12:37         ` Bhaskara Budiredla
@ 2021-06-08 16:14         ` Christoph Hellwig
  2021-06-08 17:33           ` Kees Cook
  1 sibling, 1 reply; 14+ messages in thread
From: Christoph Hellwig @ 2021-06-08 16:14 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Bhaskara Budiredla, Kees Cook, Colin Cross, Tony Luck,
	Sunil Kovvuri Goutham, linux-mmc, Linux Kernel Mailing List,
	linux-block, Jens Axboe, Christoph Hellwig

Given that Kees was unwilling to take the series to unbreak the pstore
block support I've sent a patch to Jens to mark it broken and thus
effectively disable it.  We can't really let this spread any further.

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

* Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-07 12:37         ` Bhaskara Budiredla
  2021-06-07 14:07           ` Ulf Hansson
@ 2021-06-08 17:31           ` Kees Cook
  1 sibling, 0 replies; 14+ messages in thread
From: Kees Cook @ 2021-06-08 17:31 UTC (permalink / raw)
  To: Bhaskara Budiredla, Jens Axboe, Christoph Hellwig
  Cc: Ulf Hansson, Colin Cross, Tony Luck, Sunil Kovvuri Goutham,
	linux-mmc, Linux Kernel Mailing List, linux-block

On Mon, Jun 07, 2021 at 12:37:07PM +0000, Bhaskara Budiredla wrote:
> [...]
> >What patches are you referring to?
> 
> I was referring to this patch.
> http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/pstore

I applied the first three:
https://lore.kernel.org/lkml/160685706687.2724892.9289969466453217944.b4-ty@chromium.org/

and explained my aversion to the others. Christoph never replied to my
notes on patch 8/9:
https://lore.kernel.org/lkml/202012011149.5650B9796@keescook/

-Kees

-- 
Kees Cook

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

* Re: [EXT] Re: [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk
  2021-06-08 16:14         ` Christoph Hellwig
@ 2021-06-08 17:33           ` Kees Cook
  0 siblings, 0 replies; 14+ messages in thread
From: Kees Cook @ 2021-06-08 17:33 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Ulf Hansson, Bhaskara Budiredla, Colin Cross, Tony Luck,
	Sunil Kovvuri Goutham, linux-mmc, Linux Kernel Mailing List,
	linux-block, Jens Axboe

On Tue, Jun 08, 2021 at 06:14:22PM +0200, Christoph Hellwig wrote:
> Given that Kees was unwilling to take the series to unbreak the pstore
> block support I've sent a patch to Jens to mark it broken and thus
> effectively disable it.  We can't really let this spread any further.

Hmm? You never replied to my concerns:
https://lore.kernel.org/lkml/202012011149.5650B9796@keescook/

-- 
Kees Cook

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

end of thread, other threads:[~2021-06-08 17:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-20 12:10 [PATCH v5 0/2] mmc: support crash logging to MMC block devices Bhaskara Budiredla
2021-01-20 12:10 ` [PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk Bhaskara Budiredla
2021-01-20 15:06   ` Ulf Hansson
2021-06-05 10:31     ` [EXT] " Bhaskara Budiredla
2021-06-07 11:17       ` Ulf Hansson
2021-06-07 12:37         ` Bhaskara Budiredla
2021-06-07 14:07           ` Ulf Hansson
2021-06-07 16:28             ` Bhaskara Budiredla
2021-06-08 17:31           ` Kees Cook
2021-06-08 16:14         ` Christoph Hellwig
2021-06-08 17:33           ` Kees Cook
2021-01-20 16:11   ` kernel test robot
2021-01-20 16:11     ` kernel test robot
2021-01-20 12:10 ` [PATCH v5 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write Bhaskara Budiredla

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.