[PATCH v5 0/2] mmc: support crash logging to MMC block devices

2021-01-20 Thread 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-bbudire...@marvell.com/T/#t
v2: 
https://lore.kernel.org/linux-mmc/6762a763-5284-04dc-e636-486c74ded...@alum.wpi.edu/T/#u
v3: 
https://lore.kernel.org/linux-mmc/20201207115753.21728-1-bbudire...@marvell.com/T/#t
v4: 
https://lore.kernel.org/linux-mmc/20201223144033.32571-1-bbudire...@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



[PATCH v5 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write

2021-01-20 Thread 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 
---
 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(>mmc_serializer);
+#else
down(>mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+   if (!host->pstore)
+   up(>mmc_serializer);
+#else
up(>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



RE: [EXT] Re: [PATCH v4 1/2] mmc: Support kmsg dumper based on pstore/blk

2021-01-20 Thread Bhaskara Budiredla
Thanks Kees for the quick response.
Just I have submitted those changes through patch v5.

- Bhaskara


>-Original Message-
>From: Kees Cook 
>Sent: Wednesday, January 20, 2021 1:01 AM
>To: Bhaskara Budiredla 
>Cc: Ulf Hansson ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List 
>Subject: Re: [EXT] Re: [PATCH v4 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Tue, Jan 19, 2021 at 04:11:31AM +, Bhaskara Budiredla wrote:
>> Do you see any issues to ACK this if the mmc pstore registration is
>> through register_pstore_blk()?
>> As Uffe said, eMMC would need to go through
>> psblk_generic_blk_read()/write() instead of mmcpstore_read()/write().
>
>I would be fine with that; yes.
>
>--
>Kees Cook


[PATCH v5 1/2] mmc: Support kmsg dumper based on pstore/blk

2021-01-20 Thread 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 
---
 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(>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(_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,
+

RE: [EXT] Re: [PATCH v4 1/2] mmc: Support kmsg dumper based on pstore/blk

2021-01-18 Thread Bhaskara Budiredla
Hi Kees,

Do you see any issues to ACK this if the mmc pstore
registration is through register_pstore_blk()?
As Uffe said, eMMC would need to go through
psblk_generic_blk_read()/write() instead of
mmcpstore_read()/write().

Thanks,
Bhaskara

>-Original Message-
>From: Ulf Hansson 
>Sent: Wednesday, January 13, 2021 5:16 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List 
>Subject: [EXT] Re: [PATCH v4 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>External Email
>
>--
>On Wed, 23 Dec 2020 at 15:41, Bhaskara Budiredla
> 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.
>>
>> Signed-off-by: Bhaskara Budiredla 
>
>Just to make it clear, to avoid confusions.
>
>I will not consider to pick this up, as long as the *non-panic* read/write
>support is implemented through pstore specific callbacks.
>Instead those requests should go through the regular block I/O path, as like
>any other file system.
>
>Kind regards
>Ulf Hansson
>
>> ---
>>  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 | 310
>+++
>>  include/linux/mmc/core.h |   5 +
>>  include/linux/mmc/host.h |  12 ++
>>  8 files changed, 413 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
>> 8d3df0be0355..ed012a91e3a3 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_

[PATCH v4 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-23 Thread 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 
---
 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 | 310 +++
 include/linux/mmc/core.h |   5 +
 include/linux/mmc/host.h |  12 ++
 8 files changed, 413 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 8d3df0be0355..ed012a91e3a3 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(>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(_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,
+   c

[PATCH v4 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write

2020-12-23 Thread 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 
---
 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(>mmc_serializer);
+#else
down(>mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+   if (!host->pstore)
+   up(>mmc_serializer);
+#else
up(>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



[PATCH v4 0/2] mmc: support crash logging to MMC block devices

2020-12-23 Thread Bhaskara Budiredla
This patch introduces to mmcpstore.

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-bbudire...@marvell.com/T/#t
v2: 
https://lore.kernel.org/linux-mmc/6762a763-5284-04dc-e636-486c74ded...@alum.wpi.edu/T/#u
v3: 
https://lore.kernel.org/linux-mmc/20201207115753.21728-1-bbudire...@marvell.com/T/#t

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   | 310 +
 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, 493 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/core/mmcpstore.c

-- 
2.17.1



RE: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-17 Thread Bhaskara Budiredla


>-Original Message-
>From: Ulf Hansson 
>Sent: Thursday, December 17, 2020 10:42 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List ; Christoph Hellwig
>
>Subject: Re: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Thu, 17 Dec 2020 at 12:36, Bhaskara Budiredla 
>wrote:
>>
>>
>> [...]
>>
>> >> >> An extra check can be added to see if host was runtime suspended
>> >> >> ahead of panic write attempt.
>> >> >
>> >> >What if that is the case, should we just return an error?
>> >> >
>> >> Yes.
>> >>
>> >> >Moreover, even the device belonging to the mmc card can be runtime
>> >> >suspended too. So if that is the case, we should return an error too?
>> >> >
>> >>
>> >> Yes, same here.
>> >>
>>
>> Please comment if returning error is sufficient here or can there be
>> an attempt to wake the device through either of the atomic activation calls:
>> pm_runtime_get(),  pm_request_resume()?
>
>Hmm, I would start with playing with the below. mmc_claim_host supports
>also nested claims.
>
>mmc_claim_host(host)  - this will call pm_runtime_get_sync(host)
>mmc_get_card(card, NULL) - this will call can
>pm_runtime_get_sync(card)) and also try to claim the host
>

As you suggested I am creating a parallel path that avoids wait queue 
to claim the host. The *_sync()* routines could sleep, I can't use them
as part of panic write. 


>Kind regards
>Uffe

Thanks,
Bhaskara


RE: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-17 Thread Bhaskara Budiredla

[...]

>> >> An extra check can be added to see if host was runtime suspended
>> >> ahead of panic write attempt.
>> >
>> >What if that is the case, should we just return an error?
>> >
>> Yes.
>>
>> >Moreover, even the device belonging to the mmc card can be runtime
>> >suspended too. So if that is the case, we should return an error too?
>> >
>>
>> Yes, same here.
>>

Please comment if returning error is sufficient here or
can there be an attempt to wake the device through either of the atomic 
activation calls:
pm_runtime_get(),  pm_request_resume()? 


Thanks,
Bhaskara



RE: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-16 Thread Bhaskara Budiredla


>-Original Message-
>From: Ulf Hansson 
>Sent: Wednesday, December 16, 2020 3:27 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List ; Christoph Hellwig
>
>Subject: Re: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>[...]
>
>> >> >
>> >> >It looks like the above I/O read/write interface for pstore is
>> >> >intended to be used when the platform is up and running and not
>> >> >during a
>> >panic, correct?
>> >> >
>> >> >If so, I don't get why it can't use the regular block interface,
>> >> >as any other file system does, for example?
>> >> >
>> >>
>> >> The pstore read and write operations are used as part of pstore
>> >> file system mounting to retrieve the stored logs from MMC platform
>> >> backend and to manage pstore read/write counters. Sleeping would be
>> >> allowed during this time. Whereas, pstore PANIC write will be
>> >> called if there happens
>> >a crash in the system. Sleeping is NOT allowed at this time.
>> >>
>> >> It seems you are mixing the sleeping paths of the mmcpstore with
>> >> that of
>> >atomic path.
>> >
>> >No, I am not mixing them, but questioning them.
>> >
>> >For the non atomic path, I don't understand why the pstore file
>> >system mounting, etc, deserves to be managed through its own specific
>ops?
>> >Are there any specific reasons for this that I am missing?
>> >
>>
>> Seems generic way is undergoing some changes. Kees already ACKed the
>> mmcpstore registration through block device registration.
>>
>> >In principle, for non atomic path, I would rather see that the pstore
>> >file system should be able to be mounted on top of any generic block
>> >device partition - without requiring the block device driver to implement
>specific pstore ops.
>> >
>>
>> Scope to answer this is out of mmcpstore driver. Pstore/blk driver
>> have to answer this.
>
>Yep, I am open to discuss this more.
>
>>
>> >>
>> >>
>> >> >> +
>> >> >> +static void mmcpstore_panic_write_req(const char *buf,
>> >> >> +   unsigned int nsects, unsigned int sect_offset) {
>> >> >> +   struct mmcpstore_context *cxt = _cxt;
>> >> >> +   struct mmc_request *mrq = cxt->mrq;
>> >> >> +   struct mmc_card *card = cxt->card;
>> >> >> +   struct mmc_host *host = card->host;
>> >> >> +   struct scatterlist sg;
>> >> >> +   u32 opcode;
>> >> >> +
>> >> >> +   opcode = (nsects > 1) ? MMC_WRITE_MULTIPLE_BLOCK :
>> >> >MMC_WRITE_BLOCK;
>> >> >> +   mmc_prep_req(mrq, sect_offset, nsects, , opcode,
>> >> >MMC_DATA_WRITE);
>> >> >> +   sg_init_one(, buf, (nsects << SECTOR_SHIFT));
>> >> >> +   mmc_set_data_timeout(mrq->data, cxt->card);
>> >> >> +
>> >> >> +   mmc_claim_host(host);
>> >> >
>> >> >So, this will use several locks, which may be a problem, right?
>> >> >
>> >>
>> >> No, as said above locks are present on host driver will be dropped
>> >> in CONFIG_MMC_PSTORE path.
>> >
>> >Please have a look at the code implementing mmc_claim_host(). It's
>> >not just a simple spin_lock, but there is also a wait_queue and
>> >runtime PM being managed from there.
>> >
>> >>
>> >> >Moreover, if there is an ongoing I/O request (or any other active
>> >> >command/request for that matter), then the host is already claimed
>> >> >by the mmc core. Normally, we would then wait for that request to
>> >> >be completed, to trigger the release of the host and then allow us
>> >> >to claim it
>> >here.
>> >> >
>> >> >However, because of the kernel panic, I assume it's quite likely
>> >> >that any ongoing request will not be completed at all, as IRQs may
>> >> >not work, for example.
>> >> >
>> >> >In other words, we may be hanging here forever waiting to claim the
>host.
>> >> >Unless we are lucky, b

RE: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-15 Thread Bhaskara Budiredla


>-Original Message-
>From: Ulf Hansson 
>Sent: Tuesday, December 15, 2020 5:13 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List ; Christoph Hellwig
>
>Subject: Re: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Tue, 15 Dec 2020 at 07:52, Bhaskara Budiredla 
>wrote:
>>
>>
>>
>> >-Original Message-
>> >From: Ulf Hansson 
>> >Sent: Friday, December 11, 2020 5:02 PM
>> >To: Bhaskara Budiredla 
>> >Cc: Kees Cook ; Colin Cross
>> >; Tony Luck ; Sunil Kovvuri
>> >Goutham ; linux-...@vger.kernel.org; Linux
>> >Kernel Mailing List ; Christoph Hellwig
>> >
>> >Subject: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on
>> >pstore/blk
>> >
>> >External Email
>> >
>> >-
>> >-
>> >+ Christoph
>> >
>> >On Mon, 7 Dec 2020 at 12:58, Bhaskara Budiredla
>> >
>> >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.
>> >
>> >Apologies for the delay. I have tried to give this some more
>> >thinking, more comments below.
>> >
>> >[...]
>> >
>> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> >> index
>> >> d42037f0f10d..7682b267f1d5 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);
>> >
>> >So, the host driver should through this callback, be able to
>> >terminate any ongoing requests/commands - and also try to make sure
>> >that the (e)MMC/SD card remains in the data transfer state. Moreover,
>> >no locks and no IRQs must be used to manage this, right?
>> >
>>
>> Yes, that's correct.
>>
>> >Have you really tried if this works for real?
>> >
>>
>> Yes, it's a working solution. Patch were submitted after testing.
>>
>> >> +   mmc_start_request(host, mrq);
>> >
>> >This looks like the wrong approach to me, as it will try to re-use
>> >the regular request based path, where the host driver is allowed to
>> >use locks, IRQs, DMAs, etc, etc.
>> >
>>
>> No. The locks on host driver will be dropped in CONFIG_MMC_PSTORE path.
>> Similarly, the IRQs will be replaced with polling subroutines during
>> panic write. Please take a look at patch 2/2 which does this for cavium host
>driver.
>
>Yes, but why is removing the locks okay for the other regular request case?
>
>I assume the locks are there for a reason, right?
>
Sorry, it was my mistake. The locks will not be applied to panic write case
in CONFIG_MMC_PSTORE path. They will continue to exist for regular
read/write path..

For quick reference, copying 

RE: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-14 Thread Bhaskara Budiredla


>-Original Message-
>From: Ulf Hansson 
>Sent: Friday, December 11, 2020 5:02 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List ; Christoph Hellwig
>
>Subject: [EXT] Re: [PATCH 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>External Email
>
>--
>+ Christoph
>
>On Mon, 7 Dec 2020 at 12:58, Bhaskara Budiredla 
>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.
>
>Apologies for the delay. I have tried to give this some more thinking, more
>comments below.
>
>[...]
>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
>> d42037f0f10d..7682b267f1d5 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);
>
>So, the host driver should through this callback, be able to terminate any
>ongoing requests/commands - and also try to make sure that the (e)MMC/SD
>card remains in the data transfer state. Moreover, no locks and no IRQs must
>be used to manage this, right?
>

Yes, that's correct. 

>Have you really tried if this works for real?
>

Yes, it's a working solution. Patch were submitted after testing.

>> +   mmc_start_request(host, mrq);
>
>This looks like the wrong approach to me, as it will try to re-use the regular
>request based path, where the host driver is allowed to use locks, IRQs,
>DMAs, etc, etc.
>

No. The locks on host driver will be dropped in CONFIG_MMC_PSTORE path.
Similarly, the IRQs will be replaced with polling subroutines during panic
write. Please take a look at patch 2/2 which does this for cavium host driver. 

>I would suggest inventing a new separate request path and a new host ops, to
>deal with these kinds of requests.
>

The polling and cleanup host operations are the ones invented for this purpose.
Polling to replace IRQs and cleanup to terminate ongoing requests/commands.

>In this way, the below part with host->ops->req_completion_poll, can
>probably be removed. Instead we may just wait for the request to return
>from the new request path.
>

This is not possible unless CPU itself does the mmc write (through some block 
interface?).
If the answer is block interface, sleeping cannot be avoided as part of it. 
Do you really think DMA can be avoided for MMC panic writes?  

>> +
>> +   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
>> diff --git a/drivers/mmc/core/mmcpstore.c
>> b/drivers/mmc/core/mmcpstore.c new file mode 100644 index
>> ..1113eae0756c
>> --- /dev/null
>> +++ b/drivers/mmc/core/mmcpstore.c
>> @@ -0,0 +1,302 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * MMC pstore support based on pstore/blk
>> + *
>> + * Copyright (c) 2020 Marvell.
>> + * Author: Bhaskara Budiredla   */
>&

[PATCH 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write

2020-12-07 Thread 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 
---
 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(>mmc_serializer);
+#else
down(>mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+   if (!host->pstore)
+   up(>mmc_serializer);
+#else
up(>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



[PATCH 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-07 Thread 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 
---
 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  |  24 +++
 drivers/mmc/core/mmcpstore.c | 302 +++
 include/linux/mmc/core.h |   4 +
 include/linux/mmc/host.h |  12 ++
 8 files changed, 384 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 8d3df0be0355..ed012a91e3a3 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(>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(_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,
+   c

[PATCH v3 0/2] mmc: support crash logging to MMC block devices

2020-12-07 Thread Bhaskara Budiredla
This patch introduces to mmcpstore.

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-bbudire...@marvell.com/T/#t
v2: 
https://lore.kernel.org/linux-mmc/6762a763-5284-04dc-e636-486c74ded...@alum.wpi.edu/T/#u

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|  24 +++
 drivers/mmc/core/mmcpstore.c   | 302 +
 drivers/mmc/host/cavium-thunderx.c |  10 +
 drivers/mmc/host/cavium.c  |  67 +++
 drivers/mmc/host/cavium.h  |   3 +
 include/linux/mmc/core.h   |   4 +
 include/linux/mmc/host.h   |  12 ++
 11 files changed, 464 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/core/mmcpstore.c

-- 
2.17.1



RE: [EXT] Re: [PATCH v2 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-02 Thread Bhaskara Budiredla



>-Original Message-
>From: Kees Cook 
>Sent: Thursday, December 3, 2020 1:02 AM
>To: Bhaskara Budiredla 
>Cc: ulf.hans...@linaro.org; ccr...@android.com; tony.l...@intel.com; Sunil
>Kovvuri Goutham ; linux-...@vger.kernel.org;
>linux-kernel@vger.kernel.org; outgoing2/-cover-letter.patch@mx0b-
>0016f401.pphosted.com
>Subject: Re: [EXT] Re: [PATCH v2 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Wed, Dec 02, 2020 at 06:36:21AM +, Bhaskara Budiredla wrote:
>> >From: Kees Cook  On Mon, Nov 23, 2020 at
>> >04:49:24PM +0530, Bhaskara Budiredla wrote:
>> >Why isn't this just written as:
>> >
>> >config MMC_PSTORE
>> >bool "Log panic/oops to a MMC buffer"
>> >depends on MMC_BLOCK
>> >select PSTORE_BLK
>> >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.
>> >
>>
>> The idea was to compile MMC_PSTORE as part of MMC_BLOCK driver,
>> provided it is optionally enabled.
>> The above arrangement compiles MMC_PSTORE as module: if
>> (CONFIG_MMC_PSTORE_BACKEND == y && CONFIG_MMC_BLOCK == m)
>> as static: if (CONFIG_MMC_PSTORE_BACKEND == y &&
>CONFIG_MMC_BLOCK == y)
>
>Ah, okay. If it's a tri-state, wouldn't it track CONFIG_MMC_BLOCK's state? As
>in, does this work:
>

Yes, it's a tri-state but not compiled as a separate driver. 

>config MMC_PSTORE
>   tristate "Log panic/oops to a MMC buffer"
>   depends on MMC_BLOCK
>   select PSTORE_BLK
>   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.
>

No, this will cause problems for MMC_PSTORE=m and MMC_BLOCK=y
MMC_PSTORE automatically have to be selected as module or static
based on MMC_BLOCK selection. There were couple of function calls
from the code in MMC_BLOCK to MMC_PSTORE. Uffe prefers them
to be unconditional calls (as per discussion in v1).  

>> >> + if (strncmp(cxt->dev_name, disk_name, strlen(disk_name)))
>> >> + return;
>> >
>> >Why isn't this just strcmp()?
>>
>> The mmc disk name (disk_name) doesn't include the partition number.
>> strncmp is restricted to something like /dev/mmcblk0, it doesn't cover full
>/dev/mmcblk0pn.
>> The partition number check is carried out in the next statement.
>
>Okay, gotcha; thanks!
>
>> >> + dev->flags = PSTORE_FLAGS_DMESG;
>> >
>> >Can't this support more than just DMESG? I don't see anything specific to
>that.
>> >This is using pstore/zone ultimately, which can support whatever
>> >frontends it needs to.
>>
>> Yes, as of now the support is only for DMESG. We will extend this to
>> other frontends on need basis.
>
>Okay -- I assume this has mostly to do with not having erasure (below).
>
>> >> + dev->erase = NULL;
>> >
>> >No way to remove the records?
>>
>> Yes, at this time, no removal of records.
>
>Okay. (I think this might be worth mentioning in docs somewhere.)
>

Would it be sufficient to add corresponding notes to the commit message? 

>--
>Kees Cook


RE: [EXT] Re: [PATCH v2 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-12-01 Thread Bhaskara Budiredla



>-Original Message-
>From: Kees Cook 
>Sent: Wednesday, December 2, 2020 1:56 AM
>To: Bhaskara Budiredla 
>Cc: ulf.hans...@linaro.org; ccr...@android.com; tony.l...@intel.com; Sunil
>Kovvuri Goutham ; linux-...@vger.kernel.org;
>linux-kernel@vger.kernel.org; outgoing2/-cover-letter.patch@mx0b-
>0016f401.pphosted.com
>Subject: [EXT] Re: [PATCH v2 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>External Email
>
>--
>On Mon, Nov 23, 2020 at 04:49:24PM +0530, Bhaskara Budiredla 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
>> subroutines to write kmsg panic/oops logs through mmcpstore.
>>
>> Signed-off-by: Bhaskara Budiredla 
>> ---
>>  drivers/mmc/core/Kconfig |  15 +-
>>  drivers/mmc/core/Makefile|   1 +
>>  drivers/mmc/core/block.c |  19 +++
>>  drivers/mmc/core/block.h |   9 ++
>>  drivers/mmc/core/core.c  |  24 +++
>>  drivers/mmc/core/mmcpstore.c | 302
>+++
>>  include/linux/mmc/core.h |   4 +
>>  include/linux/mmc/host.h |  12 ++
>>  8 files changed, 385 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..505450a6ea2b 100644
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/mmc/core/Kconfig
>> @@ -34,9 +34,23 @@ 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
>> +default n
>
>"default n" is redundant and can be dropped.

Yes, I have removed it.

>
>> +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
>
>I don't understand why this is separate?
>
>> +
>>  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 +94,3 @@ config MMC_TEST
>>
>>This driver is only of interest to those developing or
>>testing a host driver. Most people should say N here.
>> -
>
>Why isn't this just written as:
>
>config MMC_PSTORE
>   bool "Log panic/oops to a MMC buffer"
>   depends on MMC_BLOCK
>   select PSTORE_BLK
>   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.
>

The idea was to compile MMC_PSTORE as part of MMC_BLOCK driver,
provided it is optionally enabled.
The above arrangement compiles MMC_PSTORE 
as module: if (CONFIG_MMC_PSTORE_BACKEND == y && CONFIG_MMC_BLOCK == m)
as static: if (CONFIG_MMC_PSTORE_BACKEND == y && CONFIG_MMC_BLOCK == y)

>
>
>
>> 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
>> 8d3df0be0355..ed012a91e3a3 100644
>> --- a/drivers/mmc/core/block.c
>> +++

RE: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-11-25 Thread Bhaskara Budiredla
Sure, I will tune to those discussions and would wait for that.
- Bhaskara

>-Original Message-
>From: Christoph Hellwig 
>Sent: Tuesday, November 24, 2020 9:49 PM
>To: Ulf Hansson 
>Cc: Bhaskara Budiredla ; Kees Cook
>; Colin Cross ; Tony Luck
>; Sunil Kovvuri Goutham ;
>linux-...@vger.kernel.org; Linux Kernel Mailing List ker...@vger.kernel.org>; Christoph Hellwig 
>Subject: Re: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>On Tue, Nov 24, 2020 at 03:40:21PM +0100, Ulf Hansson wrote:
>> It looks like Christoph is planning for some rewrite of the pstore
>> code, so let's see what that means in regards to this.
>
>Here is what I posted last month:
>
>https://urldefense.proofpoint.com/v2/url?u=http-
>3A__git.infradead.org_users_hch_misc.git_shortlog_refs_heads_pstore=
>DwIBAg=nKjWec2b6R0mOyPaz7xtfQ=9P_lSljSO7KnQNkCGsgu9x_Op4ms
>tSdqWN3Olr4bUv0=q8IjbcWL5TERE5I_titSsMtZA2l6QrRmBgu0lc8wpko=
>T6P9lsMAsulOHqb4szJ553K0z2eYB5Tliq7UqFMth-g=
>
>Kees wanted to chime in with a few thing he'd like to see done differently,
>but I've not seen the actual comments yet.
>
>In respect to the eMMC support what I've done should mostly just work, it
>would have to adopt to the slightly different registration interface and just 
>call
>register_pstore_device() with its own ops.


RE: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-11-23 Thread Bhaskara Budiredla


>-Original Message-
>From: Ulf Hansson 
>Sent: Monday, November 23, 2020 5:49 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List 
>Subject: Re: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>[...]
>
>> >
>> >As I said above, I would like to avoid host specific deployments from
>> >being needed. Is there a way we can avoid this?
>> >
>>
>> I don't see an alternative.
>
>Well, if not, can you please explain why?
>

The solution has to be polling based as panic write runs with interrupts 
disabled.
I am not sure if there is a way to write a polling function that works of all 
kinds
of host/dma drivers. That’s the reason I have provided hooks to define host
specific deployments. If you have better ideas, please help. 

>[...]
>
>> >> +
>> >> +void mmcpstore_card_set(struct mmc_card *card, const char
>> >> +*disk_name) {
>> >> +   struct mmcpstore_context *cxt = _cxt;
>> >> +   struct pstore_blk_config *conf = >conf;
>> >> +   struct pstore_device_info *dev = >dev;
>> >> +   struct block_device *bdev;
>> >> +   struct mmc_command *stop;
>> >> +   struct mmc_command *cmd;
>> >> +   struct mmc_request *mrq;
>> >> +   struct mmc_data *data;
>> >> +   int ret;
>> >> +
>> >> +   if (!conf->device[0])
>> >> +   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, >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;
>> >> +
>> >> +   cxt->sub = kmalloc(conf->kmsg_size, GFP_KERNEL);
>> >> +   if (!cxt->sub)
>> >> +   goto out;
>> >> +
>> >> +   mrq = kzalloc(sizeof(struct mmc_request), GFP_KERNEL);
>> >> +   if (!mrq)
>> >> +   goto free_sub;
>> >> +
>> >> +   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;
>> >> +
>> >> +   dev->total_size = cxt->size;
>> >> +   dev->flags = PSTORE_FLAGS_DMESG;
>> >> +   dev->read = mmcpstore_read;
>> >> +   dev->write = mmcpstore_write;
>> >> +   dev->erase = NULL;
>> >> +   dev->panic_write = mmcpstore_panic_write;
>> >> +
>> >> +   ret = register_pstore_device(>dev);
>> 

[PATCH v2 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-11-23 Thread 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
subroutines to write kmsg panic/oops logs through mmcpstore.

Signed-off-by: Bhaskara Budiredla 
---
 drivers/mmc/core/Kconfig |  15 +-
 drivers/mmc/core/Makefile|   1 +
 drivers/mmc/core/block.c |  19 +++
 drivers/mmc/core/block.h |   9 ++
 drivers/mmc/core/core.c  |  24 +++
 drivers/mmc/core/mmcpstore.c | 302 +++
 include/linux/mmc/core.h |   4 +
 include/linux/mmc/host.h |  12 ++
 8 files changed, 385 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..505450a6ea2b 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -34,9 +34,23 @@ 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
+   default n
+   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 +94,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 8d3df0be0355..ed012a91e3a3 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(>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(_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) {}
+#en

[PATCH v2 2/2] mmc: cavium: Add MMC polling method to support kmsg panic/oops write

2020-11-23 Thread 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 
---
 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(>mmc_serializer);
+#else
down(>mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+   if (!host->pstore)
+   up(>mmc_serializer);
+#else
up(>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



RE: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-11-22 Thread Bhaskara Budiredla
Big thanks Uffe, my answers in line to yours.

>-Original Message-
>From: Ulf Hansson 
>Sent: Friday, November 20, 2020 6:51 PM
>To: Bhaskara Budiredla 
>Cc: Kees Cook ; Colin Cross
>; Tony Luck ; Sunil Kovvuri
>Goutham ; linux-...@vger.kernel.org; Linux
>Kernel Mailing List 
>Subject: [EXT] Re: [PATCH v1 1/2] mmc: Support kmsg dumper based on
>pstore/blk
>
>External Email
>
>--
>On Thu, 12 Nov 2020 at 07:24, Bhaskara Budiredla
> wrote:
>>
>> This patch introduces to mmcpstore. The functioning of mmcpstore is 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
>> subroutines to write kmsg panic/oops logs through mmcpstore.
>
>I don't like that changes to host drivers are needed to support this, but
>perhaps there is no other good way!?

Yes, I couldn't think of a better way as polling functionality is host specific.

>
>>
>> Signed-off-by: Bhaskara Budiredla 
>> ---
>>  drivers/mmc/core/Kconfig |   7 +
>>  drivers/mmc/core/Makefile|   1 +
>>  drivers/mmc/core/block.c |  20 +++
>>  drivers/mmc/core/block.h |   3 +
>>  drivers/mmc/core/core.c  |  24 +++
>>  drivers/mmc/core/mmcpstore.c | 318
>+++
>>  include/linux/mmc/card.h |   4 +
>>  include/linux/mmc/core.h |   4 +
>>  include/linux/mmc/host.h |   6 +
>>  9 files changed, 387 insertions(+)
>>  create mode 100644 drivers/mmc/core/mmcpstore.c
>>
>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index
>> c12fe13e4b14..cafb367c482d 100644
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/mmc/core/Kconfig
>> @@ -81,3 +81,10 @@ config MMC_TEST
>>   This driver is only of interest to those developing or
>>   testing a host driver. Most people should say N here.
>>
>> +config MMC_PSTORE
>> +   bool "Log panic/oops to a MMC buffer"
>> +   depends on PSTORE
>> +   depends on PSTORE_BLK
>> +   help
>> + Backend driver to store the kmsg crash dumps to a user specified
>MMC
>> + device. The driver is based on pstore/blk.
>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>> index 95ffe008ebdf..5f4230b79ac6 100644
>> --- a/drivers/mmc/core/Makefile
>> +++ b/drivers/mmc/core/Makefile
>> @@ -17,4 +17,5 @@ mmc_core-$(CONFIG_DEBUG_FS)   += debugfs.o
>>  obj-$(CONFIG_MMC_BLOCK)+= mmc_block.o
>>  mmc_block-objs := block.o queue.o
>>  obj-$(CONFIG_MMC_TEST) += mmc_test.o
>> +obj-$(CONFIG_MMC_PSTORE)   += mmcpstore.o
>>  obj-$(CONFIG_SDIO_UART)+= sdio_uart.o
>> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index
>> 8d3df0be0355..f11c21d60b67 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 */
>>
>> +#ifdef 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(>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,11 @@
>> static int mmc_blk_probe(struct mmc_card *card)
>> goto out;
>> }
>>
>> +#ifdef CONFIG_MMC_PSTORE
>
>Avoid using ifdefs in common functions like these, please. I think it's more
>clean to add a stub function and then just call it unconditionally here.

Sure, will do this.

>
>> + 

[PATCH v1 1/2] mmc: Support kmsg dumper based on pstore/blk

2020-11-11 Thread Bhaskara Budiredla
This patch introduces to mmcpstore. The functioning of mmcpstore is
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
subroutines to write kmsg panic/oops logs through mmcpstore.

Signed-off-by: Bhaskara Budiredla 
---
 drivers/mmc/core/Kconfig |   7 +
 drivers/mmc/core/Makefile|   1 +
 drivers/mmc/core/block.c |  20 +++
 drivers/mmc/core/block.h |   3 +
 drivers/mmc/core/core.c  |  24 +++
 drivers/mmc/core/mmcpstore.c | 318 +++
 include/linux/mmc/card.h |   4 +
 include/linux/mmc/core.h |   4 +
 include/linux/mmc/host.h |   6 +
 9 files changed, 387 insertions(+)
 create mode 100644 drivers/mmc/core/mmcpstore.c

diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index c12fe13e4b14..cafb367c482d 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -81,3 +81,10 @@ config MMC_TEST
  This driver is only of interest to those developing or
  testing a host driver. Most people should say N here.
 
+config MMC_PSTORE
+   bool "Log panic/oops to a MMC buffer"
+   depends on PSTORE
+   depends on PSTORE_BLK
+   help
+ Backend driver to store the kmsg crash dumps to a user specified MMC
+ device. The driver is based on pstore/blk.
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 95ffe008ebdf..5f4230b79ac6 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -17,4 +17,5 @@ mmc_core-$(CONFIG_DEBUG_FS)   += debugfs.o
 obj-$(CONFIG_MMC_BLOCK)+= mmc_block.o
 mmc_block-objs := block.o queue.o
 obj-$(CONFIG_MMC_TEST) += mmc_test.o
+obj-$(CONFIG_MMC_PSTORE)   += mmcpstore.o
 obj-$(CONFIG_SDIO_UART)+= sdio_uart.o
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 8d3df0be0355..f11c21d60b67 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 */
 
+#ifdef 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(>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,11 @@ static int mmc_blk_probe(struct mmc_card *card)
goto out;
}
 
+#ifdef CONFIG_MMC_PSTORE
+   if (mmc_card_mmc(card) || mmc_card_sd(card))
+   mmcpstore_card_set(card, md->disk->disk_name);
+#endif
+
/* Add two debugfs entries */
mmc_blk_add_debugfs(card, md);
 
diff --git a/drivers/mmc/core/block.h b/drivers/mmc/core/block.h
index 31153f656f41..2a2b81635508 100644
--- a/drivers/mmc/core/block.h
+++ b/drivers/mmc/core/block.h
@@ -16,5 +16,8 @@ void mmc_blk_mq_recovery(struct mmc_queue *mq);
 struct work_struct;
 
 void mmc_blk_mq_complete_work(struct work_struct *work);
+#ifdef CONFIG_MMC_PSTORE
+sector_t mmc_blk_get_part(struct mmc_card *card, int part_num, sector_t *size);
+#endif
 
 #endif
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d42037f0f10d..7cc3d81f6a9a 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);
 
+
+#ifdef 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 new MMC custom command request for a host, and
+ * wait for the command to complete based on request data 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);
+   }
+}
+#endif
+
 /**
  * mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is done
  * @host: MMC hos

[PATCH v1 2/2] mmc:cavium: Add MMC polling method to support kmsg panic/oops write

2020-11-11 Thread 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 
---
 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..efd3422939af 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)
 {
+#ifdef CONFIG_MMC_PSTORE
+   if (!host->pstore)
+   down(>mmc_serializer);
+#else
down(>mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#ifdef CONFIG_MMC_PSTORE
+   if (!host->pstore)
+   up(>mmc_serializer);
+#else
up(>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..8f62f6612ac0 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);
 }
 
+#ifdef 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,
+#ifdef 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;
 
+#ifdef 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..b72dea9a81eb 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;
 
+#ifdef CONFIG_MMC_PSTORE
+   bool pstore;
+#endif
struct gpio_desc *global_pwr_gpiod;
atomic_t shared_power_users;
 
-- 
2.17.1



[PATCH v1 0/2] mmc: support crash logging to MMC block devices

2020-11-11 Thread Bhaskara Budiredla
This patch introduces to mmcpstore.

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   |   7 +
 drivers/mmc/core/Makefile  |   1 +
 drivers/mmc/core/block.c   |  20 ++
 drivers/mmc/core/block.h   |   3 +
 drivers/mmc/core/core.c|  24 +++
 drivers/mmc/core/mmcpstore.c   | 318 +
 drivers/mmc/host/cavium-thunderx.c |  10 +
 drivers/mmc/host/cavium.c  |  67 ++
 drivers/mmc/host/cavium.h  |   3 +
 include/linux/mmc/card.h   |   4 +
 include/linux/mmc/core.h   |   4 +
 include/linux/mmc/host.h   |   6 +
 12 files changed, 467 insertions(+)
 create mode 100644 drivers/mmc/core/mmcpstore.c

-- 
2.17.1