linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/10] mhi: pci_generic: Misc improvements
@ 2020-12-29  8:43 Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper Loic Poulain
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

This series adjust some configuration values to ensure stability and
robustness of mhi pci devices (timeout, number of events, burst mode).

It also includes support for system sleep as well as a recovery procedure
that can be triggered when a PCI error is reported, either by PCI AER or by
the new health-check mechanism.

All these changes have been tested with Telit FN980m module

v2:
  - Cancel recovery work on suspend
v3:
  - enable doorbell_mode_switch for burst channel (HW)
  - Add mhi_initialize_controller helper patch
v4:
  - Delete hard reset on module unload, MHI reset is enough (Jeffrey)
  - Move soc reset support in MHI core (Jeffrey)
  - burst mode: enable doorbell_mode_switch for HW channels (Bhaumik)
  - Add diag channels
v5:
  - Remove useless call to mhi_initialize_controller in alloc_controller (hemant)
  - Add define for post reset timeout (hemant)
  - Fix static misses (hemant)
v6:
  - Add debug print in case of recovery success (Mani)
  - Return error code in case of resume failure (Mani)

Loic Poulain (10):
  mhi: Add mhi_controller_initialize helper
  bus: mhi: core: Add device hardware reset support
  mhi: pci-generic: Increase number of hardware events
  mhi: pci_generic: Enable burst mode for hardware channels
  mhi: pci_generic: Add support for reset
  mhi: pci_generic: Add suspend/resume/recovery procedure
  mhi: pci_generic: Add PCI error handlers
  mhi: pci_generic: Add health-check
  mhi: pci_generic: Increase controller timeout value
  mhi: pci_generic: Add diag channels

 drivers/bus/mhi/core/init.c   |   6 +
 drivers/bus/mhi/core/main.c   |   7 +
 drivers/bus/mhi/pci_generic.c | 357 +++++++++++++++++++++++++++++++++++++++---
 include/linux/mhi.h           |  13 ++
 4 files changed, 364 insertions(+), 19 deletions(-)

-- 
2.7.4


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

* [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  6:48   ` Manivannan Sadhasivam
  2020-12-29  8:43 ` [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support Loic Poulain
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

This function allows to initialize a mhi_controller structure.
Today, it only zeroing the structure.

Use this function from mhi_alloc_controller so that any further
initialization can be factorized in initalize function.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
---
 drivers/bus/mhi/core/init.c | 6 ++++++
 include/linux/mhi.h         | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 96cde9c..a75ab8c 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -1021,6 +1021,12 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
 }
 EXPORT_SYMBOL_GPL(mhi_unregister_controller);
 
+void mhi_initialize_controller(struct mhi_controller *mhi_cntrl)
+{
+	memset(mhi_cntrl, 0, sizeof(*mhi_cntrl));
+}
+EXPORT_SYMBOL_GPL(mhi_initialize_controller);
+
 struct mhi_controller *mhi_alloc_controller(void)
 {
 	struct mhi_controller *mhi_cntrl;
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 04cf7f3..2754742 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -537,6 +537,12 @@ struct mhi_driver {
 #define to_mhi_device(dev) container_of(dev, struct mhi_device, dev)
 
 /**
+ * mhi_initialize_controller - Initialize MHI Controller structure
+ * @mhi_cntrl: MHI controller structure to initialize
+ */
+void mhi_initialize_controller(struct mhi_controller *mhi_cntrl);
+
+/**
  * mhi_alloc_controller - Allocate the MHI Controller structure
  * Allocate the mhi_controller structure using zero initialized memory
  */
-- 
2.7.4


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

* [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  7:01   ` Manivannan Sadhasivam
  2020-12-29  8:43 ` [PATCH v6 03/10] mhi: pci-generic: Increase number of hardware events Loic Poulain
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

The MHI specification allows to perform a hard reset of the device
when writing to the SOC_RESET register. It can be used to completely
restart the device (e.g. in case of unrecoverable MHI error).

This is up to the MHI controller driver to determine when this hard
reset should be used, and in case of MHI errors, should be used as
a reset of last resort (after standard MHI stack reset).

This function is prefixed with 'mhi_reg' to highlight that this is
a stateless function, the MHI layer do nothing except triggering the
reset by writing into the right register, this is up to the caller
to ensure right mhi_controller state (e.g. unregister the controller
if necessary).

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
---
 drivers/bus/mhi/core/main.c | 7 +++++++
 include/linux/mhi.h         | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
index a353d1e..9f8ce15 100644
--- a/drivers/bus/mhi/core/main.c
+++ b/drivers/bus/mhi/core/main.c
@@ -142,6 +142,13 @@ enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl)
 }
 EXPORT_SYMBOL_GPL(mhi_get_mhi_state);
 
+void mhi_reg_soc_reset(struct mhi_controller *mhi_cntrl)
+{
+	mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET,
+		      MHI_SOC_RESET_REQ);
+}
+EXPORT_SYMBOL_GPL(mhi_reg_soc_reset);
+
 int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl,
 			 struct mhi_buf_info *buf_info)
 {
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 2754742..8b1bf80 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -687,6 +687,13 @@ enum mhi_ee_type mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
 enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl);
 
 /**
+ * mhi_reg_soc_reset - Trigger a device reset. This can be used as a last resort
+ *		       to reset and recover a device.
+ * @mhi_cntrl: MHI controller
+ */
+void mhi_reg_soc_reset(struct mhi_controller *mhi_cntrl);
+
+/**
  * mhi_device_get - Disable device low power mode
  * @mhi_dev: Device associated with the channel
  */
-- 
2.7.4


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

* [PATCH v6 03/10] mhi: pci-generic: Increase number of hardware events
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 04/10] mhi: pci_generic: Enable burst mode for hardware channels Loic Poulain
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

If the IPA (IP hardware accelerator) is starved of event ring elements,
the modem is crashing (SDX55). That can be prevented by setting a
larger number of events (i.e 2 x number of channel ring elements).

Tested with FN980m module.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 drivers/bus/mhi/pci_generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index e3df838..13a7e4f 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -91,7 +91,7 @@ struct mhi_pci_dev_info {
 
 #define MHI_EVENT_CONFIG_HW_DATA(ev_ring, ch_num) \
 	{					\
-		.num_elements = 128,		\
+		.num_elements = 256,		\
 		.irq_moderation_ms = 5,		\
 		.irq = (ev_ring) + 1,		\
 		.priority = 1,			\
-- 
2.7.4


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

* [PATCH v6 04/10] mhi: pci_generic: Enable burst mode for hardware channels
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (2 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 03/10] mhi: pci-generic: Increase number of hardware events Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 05/10] mhi: pci_generic: Add support for reset Loic Poulain
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

Hardware channels have a feature called burst mode that allows to
queue transfer ring element(s) (TRE) to a channel without ringing
the device doorbell. In that mode, the device is polling the channel
context for new elements. This reduces the frequency of host initiated
doorbells and increase throughput.

Create a new dedicated macro for hardware channels with burst enabled.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 drivers/bus/mhi/pci_generic.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 13a7e4f..077595c 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -76,6 +76,36 @@ struct mhi_pci_dev_info {
 		.offload_channel = false,	\
 	}
 
+#define MHI_CHANNEL_CONFIG_HW_UL(ch_num, ch_name, el_count, ev_ring) \
+	{						\
+		.num = ch_num,				\
+		.name = ch_name,			\
+		.num_elements = el_count,		\
+		.event_ring = ev_ring,			\
+		.dir = DMA_TO_DEVICE,			\
+		.ee_mask = BIT(MHI_EE_AMSS),		\
+		.pollcfg = 0,				\
+		.doorbell = MHI_DB_BRST_ENABLE,	\
+		.lpm_notify = false,			\
+		.offload_channel = false,		\
+		.doorbell_mode_switch = true,		\
+	}						\
+
+#define MHI_CHANNEL_CONFIG_HW_DL(ch_num, ch_name, el_count, ev_ring) \
+	{						\
+		.num = ch_num,				\
+		.name = ch_name,			\
+		.num_elements = el_count,		\
+		.event_ring = ev_ring,			\
+		.dir = DMA_FROM_DEVICE,			\
+		.ee_mask = BIT(MHI_EE_AMSS),		\
+		.pollcfg = 0,				\
+		.doorbell = MHI_DB_BRST_ENABLE,	\
+		.lpm_notify = false,			\
+		.offload_channel = false,		\
+		.doorbell_mode_switch = true,		\
+	}
+
 #define MHI_EVENT_CONFIG_DATA(ev_ring)		\
 	{					\
 		.num_elements = 128,		\
@@ -110,8 +140,8 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
 	MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
 	MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
 	MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
-	MHI_CHANNEL_CONFIG_UL(100, "IP_HW0", 128, 1),
-	MHI_CHANNEL_CONFIG_DL(101, "IP_HW0", 128, 2),
+	MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
+	MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
 };
 
 static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
-- 
2.7.4


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

* [PATCH v6 05/10] mhi: pci_generic: Add support for reset
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (3 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 04/10] mhi: pci_generic: Enable burst mode for hardware channels Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure Loic Poulain
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

Add support for resetting the device, reset can be triggered in case
of error or manually via sysfs (/sys/bus/pci/devices/*/reset).

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
---
 drivers/bus/mhi/pci_generic.c | 121 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 108 insertions(+), 13 deletions(-)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 077595c..2521cd4 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -8,6 +8,7 @@
  * Copyright (C) 2020 Linaro Ltd <loic.poulain@linaro.org>
  */
 
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/mhi.h>
 #include <linux/module.h>
@@ -15,6 +16,7 @@
 
 #define MHI_PCI_DEFAULT_BAR_NUM 0
 
+#define MHI_POST_RESET_DELAY_MS 500
 /**
  * struct mhi_pci_dev_info - MHI PCI device specific information
  * @config: MHI controller configuration
@@ -177,6 +179,16 @@ static const struct pci_device_id mhi_pci_id_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
 
+enum mhi_pci_device_status {
+	MHI_PCI_DEV_STARTED,
+};
+
+struct mhi_pci_device {
+	struct mhi_controller mhi_cntrl;
+	struct pci_saved_state *pci_state;
+	unsigned long status;
+};
+
 static int mhi_pci_read_reg(struct mhi_controller *mhi_cntrl,
 			    void __iomem *addr, u32 *out)
 {
@@ -196,6 +208,20 @@ static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl,
 	/* Nothing to do for now */
 }
 
+static bool mhi_pci_is_alive(struct mhi_controller *mhi_cntrl)
+{
+	struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
+	u16 vendor = 0;
+
+	if (pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor))
+		return false;
+
+	if (vendor == (u16) ~0 || vendor == 0)
+		return false;
+
+	return true;
+}
+
 static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
 			 unsigned int bar_num, u64 dma_mask)
 {
@@ -291,16 +317,20 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
 	const struct mhi_controller_config *mhi_cntrl_config;
+	struct mhi_pci_device *mhi_pdev;
 	struct mhi_controller *mhi_cntrl;
 	int err;
 
 	dev_dbg(&pdev->dev, "MHI PCI device found: %s\n", info->name);
 
-	mhi_cntrl = mhi_alloc_controller();
-	if (!mhi_cntrl)
+	mhi_pdev = devm_kzalloc(&pdev->dev, sizeof(*mhi_pdev), GFP_KERNEL);
+	if (!mhi_pdev)
 		return -ENOMEM;
 
 	mhi_cntrl_config = info->config;
+	mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	mhi_initialize_controller(mhi_cntrl);
 	mhi_cntrl->cntrl_dev = &pdev->dev;
 	mhi_cntrl->iova_start = 0;
 	mhi_cntrl->iova_stop = DMA_BIT_MASK(info->dma_data_width);
@@ -315,17 +345,21 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	err = mhi_pci_claim(mhi_cntrl, info->bar_num, DMA_BIT_MASK(info->dma_data_width));
 	if (err)
-		goto err_release;
+		return err;
 
 	err = mhi_pci_get_irqs(mhi_cntrl, mhi_cntrl_config);
 	if (err)
-		goto err_release;
+		return err;
+
+	pci_set_drvdata(pdev, mhi_pdev);
 
-	pci_set_drvdata(pdev, mhi_cntrl);
+	/* Have stored pci confspace at hand for restore in sudden PCI error */
+	pci_save_state(pdev);
+	mhi_pdev->pci_state = pci_store_saved_state(pdev);
 
 	err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);
 	if (err)
-		goto err_release;
+		return err;
 
 	/* MHI bus does not power up the controller by default */
 	err = mhi_prepare_for_power_up(mhi_cntrl);
@@ -340,33 +374,94 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto err_unprepare;
 	}
 
+	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
+
 	return 0;
 
 err_unprepare:
 	mhi_unprepare_after_power_down(mhi_cntrl);
 err_unregister:
 	mhi_unregister_controller(mhi_cntrl);
-err_release:
-	mhi_free_controller(mhi_cntrl);
 
 	return err;
 }
 
 static void mhi_pci_remove(struct pci_dev *pdev)
 {
-	struct mhi_controller *mhi_cntrl = pci_get_drvdata(pdev);
+	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
+		mhi_power_down(mhi_cntrl, true);
+		mhi_unprepare_after_power_down(mhi_cntrl);
+	}
 
-	mhi_power_down(mhi_cntrl, true);
-	mhi_unprepare_after_power_down(mhi_cntrl);
 	mhi_unregister_controller(mhi_cntrl);
-	mhi_free_controller(mhi_cntrl);
 }
 
+static void mhi_pci_reset_prepare(struct pci_dev *pdev)
+{
+	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	dev_info(&pdev->dev, "reset\n");
+
+	/* Clean up MHI state */
+	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
+		mhi_power_down(mhi_cntrl, false);
+		mhi_unprepare_after_power_down(mhi_cntrl);
+	}
+
+	/* cause internal device reset */
+	mhi_reg_soc_reset(mhi_cntrl);
+
+	/* Be sure device reset has been executed */
+	msleep(MHI_POST_RESET_DELAY_MS);
+}
+
+static void mhi_pci_reset_done(struct pci_dev *pdev)
+{
+	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+	int err;
+
+	/* Restore initial known working PCI state */
+	pci_load_saved_state(pdev, mhi_pdev->pci_state);
+	pci_restore_state(pdev);
+
+	/* Is device status available ? */
+	if (!mhi_pci_is_alive(mhi_cntrl)) {
+		dev_err(&pdev->dev, "reset failed\n");
+		return;
+	}
+
+	err = mhi_prepare_for_power_up(mhi_cntrl);
+	if (err) {
+		dev_err(&pdev->dev, "failed to prepare MHI controller\n");
+		return;
+	}
+
+	err = mhi_sync_power_up(mhi_cntrl);
+	if (err) {
+		dev_err(&pdev->dev, "failed to power up MHI controller\n");
+		mhi_unprepare_after_power_down(mhi_cntrl);
+		return;
+	}
+
+	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
+}
+
+static const struct pci_error_handlers mhi_pci_err_handler = {
+	.reset_prepare = mhi_pci_reset_prepare,
+	.reset_done = mhi_pci_reset_done,
+};
+
 static struct pci_driver mhi_pci_driver = {
 	.name		= "mhi-pci-generic",
 	.id_table	= mhi_pci_id_table,
 	.probe		= mhi_pci_probe,
-	.remove		= mhi_pci_remove
+	.remove		= mhi_pci_remove,
+	.err_handler	= &mhi_pci_err_handler,
 };
 module_pci_driver(mhi_pci_driver);
 
-- 
2.7.4


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

* [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (4 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 05/10] mhi: pci_generic: Add support for reset Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  7:05   ` Manivannan Sadhasivam
  2020-12-29  8:43 ` [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers Loic Poulain
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

Add support for system wide suspend/resume. During suspend, MHI
device controller must be put in M3 state and PCI bus in D3 state.

Add a recovery procedure allowing to reinitialize the device in case
of error during resume steps, which can happen if device loses power
(and so its context) while system suspend.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
---
 drivers/bus/mhi/pci_generic.c | 105 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 2521cd4..3297d95 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -13,6 +13,7 @@
 #include <linux/mhi.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 
 #define MHI_PCI_DEFAULT_BAR_NUM 0
 
@@ -186,6 +187,7 @@ enum mhi_pci_device_status {
 struct mhi_pci_device {
 	struct mhi_controller mhi_cntrl;
 	struct pci_saved_state *pci_state;
+	struct work_struct recovery_work;
 	unsigned long status;
 };
 
@@ -313,6 +315,50 @@ static void mhi_pci_runtime_put(struct mhi_controller *mhi_cntrl)
 	/* no PM for now */
 }
 
+static void mhi_pci_recovery_work(struct work_struct *work)
+{
+	struct mhi_pci_device *mhi_pdev = container_of(work, struct mhi_pci_device,
+						       recovery_work);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+	struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
+	int err;
+
+	dev_warn(&pdev->dev, "device recovery started\n");
+
+	/* Clean up MHI state */
+	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
+		mhi_power_down(mhi_cntrl, false);
+		mhi_unprepare_after_power_down(mhi_cntrl);
+	}
+
+	/* Check if we can recover without full reset */
+	pci_set_power_state(pdev, PCI_D0);
+	pci_load_saved_state(pdev, mhi_pdev->pci_state);
+	pci_restore_state(pdev);
+
+	if (!mhi_pci_is_alive(mhi_cntrl))
+		goto err_try_reset;
+
+	err = mhi_prepare_for_power_up(mhi_cntrl);
+	if (err)
+		goto err_try_reset;
+
+	err = mhi_sync_power_up(mhi_cntrl);
+	if (err)
+		goto err_unprepare;
+
+	dev_dbg(&pdev->dev, "Recovery completed\n");
+
+	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
+	return;
+
+err_unprepare:
+	mhi_unprepare_after_power_down(mhi_cntrl);
+err_try_reset:
+	if (pci_reset_function(pdev))
+		dev_err(&pdev->dev, "Recovery failed\n");
+}
+
 static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
@@ -327,6 +373,8 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (!mhi_pdev)
 		return -ENOMEM;
 
+	INIT_WORK(&mhi_pdev->recovery_work, mhi_pci_recovery_work);
+
 	mhi_cntrl_config = info->config;
 	mhi_cntrl = &mhi_pdev->mhi_cntrl;
 
@@ -391,6 +439,8 @@ static void mhi_pci_remove(struct pci_dev *pdev)
 	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
 	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
 
+	cancel_work_sync(&mhi_pdev->recovery_work);
+
 	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
 		mhi_power_down(mhi_cntrl, true);
 		mhi_unprepare_after_power_down(mhi_cntrl);
@@ -456,12 +506,67 @@ static const struct pci_error_handlers mhi_pci_err_handler = {
 	.reset_done = mhi_pci_reset_done,
 };
 
+static int  __maybe_unused mhi_pci_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	cancel_work_sync(&mhi_pdev->recovery_work);
+
+	/* Transition to M3 state */
+	mhi_pm_suspend(mhi_cntrl);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_wake_from_d3(pdev, true);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int __maybe_unused mhi_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+	int err;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_set_master(pdev);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_recovery;
+
+	/* Exit M3, transition to M0 state */
+	err = mhi_pm_resume(mhi_cntrl);
+	if (err) {
+		dev_err(&pdev->dev, "failed to resume device: %d\n", err);
+		goto err_recovery;
+	}
+
+	return 0;
+
+err_recovery:
+	/* The device may have loose power or crashed, try recovering it */
+	queue_work(system_long_wq, &mhi_pdev->recovery_work);
+
+	return err;
+}
+
+static const struct dev_pm_ops mhi_pci_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume)
+};
+
 static struct pci_driver mhi_pci_driver = {
 	.name		= "mhi-pci-generic",
 	.id_table	= mhi_pci_id_table,
 	.probe		= mhi_pci_probe,
 	.remove		= mhi_pci_remove,
 	.err_handler	= &mhi_pci_err_handler,
+	.driver.pm	= &mhi_pci_pm_ops
 };
 module_pci_driver(mhi_pci_driver);
 
-- 
2.7.4


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

* [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (5 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  7:18   ` Manivannan Sadhasivam
  2020-12-29  8:43 ` [PATCH v6 08/10] mhi: pci_generic: Add health-check Loic Poulain
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

In AER capable root complex, errors are reported to the host which
can then act accordingly and perform PCI recovering procedure.

This patch enables error reporting and implements error_detected,
slot_reset and resume callbacks.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
---
 drivers/bus/mhi/pci_generic.c | 50 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 3297d95..9fe1e30 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -8,6 +8,7 @@
  * Copyright (C) 2020 Linaro Ltd <loic.poulain@linaro.org>
  */
 
+#include <linux/aer.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/mhi.h>
@@ -405,6 +406,8 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	pci_save_state(pdev);
 	mhi_pdev->pci_state = pci_store_saved_state(pdev);
 
+	pci_enable_pcie_error_reporting(pdev);
+
 	err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);
 	if (err)
 		return err;
@@ -501,7 +504,54 @@ static void mhi_pci_reset_done(struct pci_dev *pdev)
 	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
 }
 
+static pci_ers_result_t mhi_pci_error_detected(struct pci_dev *pdev,
+					       pci_channel_state_t state)
+{
+	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	dev_err(&pdev->dev, "PCI error detected, state = %u\n", state);
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	/* Clean up MHI state */
+	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
+		mhi_power_down(mhi_cntrl, false);
+		mhi_unprepare_after_power_down(mhi_cntrl);
+	} else {
+		/* Nothing to do */
+		return PCI_ERS_RESULT_RECOVERED;
+	}
+
+	pci_disable_device(pdev);
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t mhi_pci_slot_reset(struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void mhi_pci_io_resume(struct pci_dev *pdev)
+{
+	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
+
+	dev_err(&pdev->dev, "PCI slot reset done\n");
+
+	queue_work(system_long_wq, &mhi_pdev->recovery_work);
+}
+
 static const struct pci_error_handlers mhi_pci_err_handler = {
+	.error_detected = mhi_pci_error_detected,
+	.slot_reset = mhi_pci_slot_reset,
+	.resume = mhi_pci_io_resume,
 	.reset_prepare = mhi_pci_reset_prepare,
 	.reset_done = mhi_pci_reset_done,
 };
-- 
2.7.4


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

* [PATCH v6 08/10] mhi: pci_generic: Add health-check
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (6 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value Loic Poulain
  2020-12-29  8:43 ` [PATCH v6 10/10] mhi: pci_generic: Add diag channels Loic Poulain
  9 siblings, 0 replies; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

If the modem crashes for any reason, we may not be able to detect
it at MHI level (MHI registers not reachable anymore).

This patch implements a health-check mechanism to check regularly
that device is alive (MHI layer can communicate with). If device
is not alive (because a crash or unexpected reset), the recovery
procedure is triggered.

Tested successfully with Telit FN980m module.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>
---
 drivers/bus/mhi/pci_generic.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 9fe1e30..812d54f 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -14,11 +14,15 @@
 #include <linux/mhi.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/timer.h>
 #include <linux/workqueue.h>
 
 #define MHI_PCI_DEFAULT_BAR_NUM 0
 
 #define MHI_POST_RESET_DELAY_MS 500
+
+#define HEALTH_CHECK_PERIOD (HZ * 2)
+
 /**
  * struct mhi_pci_dev_info - MHI PCI device specific information
  * @config: MHI controller configuration
@@ -189,6 +193,7 @@ struct mhi_pci_device {
 	struct mhi_controller mhi_cntrl;
 	struct pci_saved_state *pci_state;
 	struct work_struct recovery_work;
+	struct timer_list health_check_timer;
 	unsigned long status;
 };
 
@@ -326,6 +331,8 @@ static void mhi_pci_recovery_work(struct work_struct *work)
 
 	dev_warn(&pdev->dev, "device recovery started\n");
 
+	del_timer(&mhi_pdev->health_check_timer);
+
 	/* Clean up MHI state */
 	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
 		mhi_power_down(mhi_cntrl, false);
@@ -351,6 +358,7 @@ static void mhi_pci_recovery_work(struct work_struct *work)
 	dev_dbg(&pdev->dev, "Recovery completed\n");
 
 	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
+	mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
 	return;
 
 err_unprepare:
@@ -360,6 +368,21 @@ static void mhi_pci_recovery_work(struct work_struct *work)
 		dev_err(&pdev->dev, "Recovery failed\n");
 }
 
+static void health_check(struct timer_list *t)
+{
+	struct mhi_pci_device *mhi_pdev = from_timer(mhi_pdev, t, health_check_timer);
+	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+
+	if (!mhi_pci_is_alive(mhi_cntrl)) {
+		dev_err(mhi_cntrl->cntrl_dev, "Device died\n");
+		queue_work(system_long_wq, &mhi_pdev->recovery_work);
+		return;
+	}
+
+	/* reschedule in two seconds */
+	mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
+}
+
 static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
@@ -375,6 +398,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return -ENOMEM;
 
 	INIT_WORK(&mhi_pdev->recovery_work, mhi_pci_recovery_work);
+	timer_setup(&mhi_pdev->health_check_timer, health_check, 0);
 
 	mhi_cntrl_config = info->config;
 	mhi_cntrl = &mhi_pdev->mhi_cntrl;
@@ -427,6 +451,9 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
 
+	/* start health check */
+	mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
+
 	return 0;
 
 err_unprepare:
@@ -442,6 +469,7 @@ static void mhi_pci_remove(struct pci_dev *pdev)
 	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
 	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
 
+	del_timer(&mhi_pdev->health_check_timer);
 	cancel_work_sync(&mhi_pdev->recovery_work);
 
 	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
@@ -459,6 +487,8 @@ static void mhi_pci_reset_prepare(struct pci_dev *pdev)
 
 	dev_info(&pdev->dev, "reset\n");
 
+	del_timer(&mhi_pdev->health_check_timer);
+
 	/* Clean up MHI state */
 	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
 		mhi_power_down(mhi_cntrl, false);
@@ -502,6 +532,7 @@ static void mhi_pci_reset_done(struct pci_dev *pdev)
 	}
 
 	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
+	mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
 }
 
 static pci_ers_result_t mhi_pci_error_detected(struct pci_dev *pdev,
@@ -562,6 +593,7 @@ static int  __maybe_unused mhi_pci_suspend(struct device *dev)
 	struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
 	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
 
+	del_timer(&mhi_pdev->health_check_timer);
 	cancel_work_sync(&mhi_pdev->recovery_work);
 
 	/* Transition to M3 state */
@@ -597,6 +629,9 @@ static int __maybe_unused mhi_pci_resume(struct device *dev)
 		goto err_recovery;
 	}
 
+	/* Resume health check */
+	mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
+
 	return 0;
 
 err_recovery:
-- 
2.7.4


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

* [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (7 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 08/10] mhi: pci_generic: Add health-check Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  7:18   ` Manivannan Sadhasivam
  2020-12-29  8:43 ` [PATCH v6 10/10] mhi: pci_generic: Add diag channels Loic Poulain
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

On cold boot, device can take slightly more than 5 seconds to start.
Increase the timeout to prevent MHI power-up issues.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>
---
 drivers/bus/mhi/pci_generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index 812d54f..d4ad9c5 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -162,7 +162,7 @@ static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
 
 static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
 	.max_channels = 128,
-	.timeout_ms = 5000,
+	.timeout_ms = 8000,
 	.num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels),
 	.ch_cfg = modem_qcom_v1_mhi_channels,
 	.num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events),
-- 
2.7.4


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

* [PATCH v6 10/10] mhi: pci_generic: Add diag channels
  2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
                   ` (8 preceding siblings ...)
  2020-12-29  8:43 ` [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value Loic Poulain
@ 2020-12-29  8:43 ` Loic Poulain
  2020-12-31  7:20   ` Manivannan Sadhasivam
  9 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-29  8:43 UTC (permalink / raw)
  To: manivannan.sadhasivam; +Cc: linux-arm-msm, bbhatt, hemantk, Loic Poulain

Add support for Diag over MHI. Qualcomm Diag is the qualcomm
diagnostics interface that can be used to collect modem logs,
events, traces, etc. It can be used by tools such QPST or QXDM.

This patch adds the DIAG channels and a dedicated event ring.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
---
 drivers/bus/mhi/pci_generic.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index d4ad9c5..0947596 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -142,22 +142,26 @@ struct mhi_pci_dev_info {
 	}
 
 static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
+	MHI_CHANNEL_CONFIG_UL(4, "DIAG", 16, 1),
+	MHI_CHANNEL_CONFIG_DL(5, "DIAG", 16, 1),
 	MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0),
 	MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0),
 	MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
 	MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
 	MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
 	MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
-	MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
-	MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
+	MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
+	MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
 };
 
 static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
 	/* first ring is control+data ring */
 	MHI_EVENT_CONFIG_CTRL(0),
+	/* DIAG dedicated event ring */
+	MHI_EVENT_CONFIG_DATA(1),
 	/* Hardware channels request dedicated hardware event rings */
-	MHI_EVENT_CONFIG_HW_DATA(1, 100),
-	MHI_EVENT_CONFIG_HW_DATA(2, 101)
+	MHI_EVENT_CONFIG_HW_DATA(2, 100),
+	MHI_EVENT_CONFIG_HW_DATA(3, 101)
 };
 
 static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
-- 
2.7.4


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

* Re: [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper
  2020-12-29  8:43 ` [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper Loic Poulain
@ 2020-12-31  6:48   ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  6:48 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk, ath11k, kvalo

Hi Loic,

+ath11k, kalle

On Tue, Dec 29, 2020 at 09:43:42AM +0100, Loic Poulain wrote:
> This function allows to initialize a mhi_controller structure.
> Today, it only zeroing the structure.
> 
> Use this function from mhi_alloc_controller so that any further
> initialization can be factorized in initalize function.
> 

I know that this has been discussed in earlier revisions but I'm still not
convinced to have 2 APIs doing a similar job. Since we don't have any usecase
currently to initialize extra fields other than the struct, we should be using
the alloc_controller API.

If you want to have a devres managed allocation, then the API should be extended
as below:

struct mhi_controller *mhi_alloc_controller(struct device *dev)
{
	struct mhi_controller *mhi_cntrl;

	if (!dev)
		mhi_cntrl = kzalloc(sizeof(*mhi_cntrl), GFP_KERNEL);
	else
		mhi_cntrl = devm_kzalloc(dev, sizeof(*mhi_cntrl), GFP_KERNEL);

	return mhi_cntrl;		
}

In this case, the ath11k MHI controller also need to be adjusted but we can use
the same immutable branch way.

Thanks,
Mani

> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> ---
>  drivers/bus/mhi/core/init.c | 6 ++++++
>  include/linux/mhi.h         | 6 ++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
> index 96cde9c..a75ab8c 100644
> --- a/drivers/bus/mhi/core/init.c
> +++ b/drivers/bus/mhi/core/init.c
> @@ -1021,6 +1021,12 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
>  }
>  EXPORT_SYMBOL_GPL(mhi_unregister_controller);
>  
> +void mhi_initialize_controller(struct mhi_controller *mhi_cntrl)
> +{
> +	memset(mhi_cntrl, 0, sizeof(*mhi_cntrl));
> +}
> +EXPORT_SYMBOL_GPL(mhi_initialize_controller);
> +
>  struct mhi_controller *mhi_alloc_controller(void)
>  {
>  	struct mhi_controller *mhi_cntrl;
> diff --git a/include/linux/mhi.h b/include/linux/mhi.h
> index 04cf7f3..2754742 100644
> --- a/include/linux/mhi.h
> +++ b/include/linux/mhi.h
> @@ -537,6 +537,12 @@ struct mhi_driver {
>  #define to_mhi_device(dev) container_of(dev, struct mhi_device, dev)
>  
>  /**
> + * mhi_initialize_controller - Initialize MHI Controller structure
> + * @mhi_cntrl: MHI controller structure to initialize
> + */
> +void mhi_initialize_controller(struct mhi_controller *mhi_cntrl);
> +
> +/**
>   * mhi_alloc_controller - Allocate the MHI Controller structure
>   * Allocate the mhi_controller structure using zero initialized memory
>   */
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support
  2020-12-29  8:43 ` [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support Loic Poulain
@ 2020-12-31  7:01   ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  7:01 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk

On Tue, Dec 29, 2020 at 09:43:43AM +0100, Loic Poulain wrote:
> The MHI specification allows to perform a hard reset of the device
> when writing to the SOC_RESET register. It can be used to completely
> restart the device (e.g. in case of unrecoverable MHI error).
> 
> This is up to the MHI controller driver to determine when this hard
> reset should be used, and in case of MHI errors, should be used as
> a reset of last resort (after standard MHI stack reset).
> 
> This function is prefixed with 'mhi_reg' to highlight that this is
> a stateless function, the MHI layer do nothing except triggering the
> reset by writing into the right register, this is up to the caller
> to ensure right mhi_controller state (e.g. unregister the controller
> if necessary).
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> ---
>  drivers/bus/mhi/core/main.c | 7 +++++++
>  include/linux/mhi.h         | 7 +++++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
> index a353d1e..9f8ce15 100644
> --- a/drivers/bus/mhi/core/main.c
> +++ b/drivers/bus/mhi/core/main.c
> @@ -142,6 +142,13 @@ enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl)
>  }
>  EXPORT_SYMBOL_GPL(mhi_get_mhi_state);
>  
> +void mhi_reg_soc_reset(struct mhi_controller *mhi_cntrl)
> +{
> +	mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET,
> +		      MHI_SOC_RESET_REQ);

This will work for MHI devices designed as per the spec. But we do have few
devices like QCA6390 using some additional registers in the MHI space. So
ideally we'd need to add a callback to the mhi_cntrl struct for handling those
cases and call it here if present.

Thanks,
Mani

> +}
> +EXPORT_SYMBOL_GPL(mhi_reg_soc_reset);
> +
>  int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl,
>  			 struct mhi_buf_info *buf_info)
>  {
> diff --git a/include/linux/mhi.h b/include/linux/mhi.h
> index 2754742..8b1bf80 100644
> --- a/include/linux/mhi.h
> +++ b/include/linux/mhi.h
> @@ -687,6 +687,13 @@ enum mhi_ee_type mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
>  enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl);
>  
>  /**
> + * mhi_reg_soc_reset - Trigger a device reset. This can be used as a last resort
> + *		       to reset and recover a device.
> + * @mhi_cntrl: MHI controller
> + */
> +void mhi_reg_soc_reset(struct mhi_controller *mhi_cntrl);
> +
> +/**
>   * mhi_device_get - Disable device low power mode
>   * @mhi_dev: Device associated with the channel
>   */
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure
  2020-12-29  8:43 ` [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure Loic Poulain
@ 2020-12-31  7:05   ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  7:05 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk

On Tue, Dec 29, 2020 at 09:43:47AM +0100, Loic Poulain wrote:
> Add support for system wide suspend/resume. During suspend, MHI
> device controller must be put in M3 state and PCI bus in D3 state.
> 
> Add a recovery procedure allowing to reinitialize the device in case
> of error during resume steps, which can happen if device loses power
> (and so its context) while system suspend.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reviewed-by Hemant Kumar <hemantk@codeaurora.org>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Thanks,
Mani

> ---
>  drivers/bus/mhi/pci_generic.c | 105 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 105 insertions(+)
> 
> diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
> index 2521cd4..3297d95 100644
> --- a/drivers/bus/mhi/pci_generic.c
> +++ b/drivers/bus/mhi/pci_generic.c
> @@ -13,6 +13,7 @@
>  #include <linux/mhi.h>
>  #include <linux/module.h>
>  #include <linux/pci.h>
> +#include <linux/workqueue.h>
>  
>  #define MHI_PCI_DEFAULT_BAR_NUM 0
>  
> @@ -186,6 +187,7 @@ enum mhi_pci_device_status {
>  struct mhi_pci_device {
>  	struct mhi_controller mhi_cntrl;
>  	struct pci_saved_state *pci_state;
> +	struct work_struct recovery_work;
>  	unsigned long status;
>  };
>  
> @@ -313,6 +315,50 @@ static void mhi_pci_runtime_put(struct mhi_controller *mhi_cntrl)
>  	/* no PM for now */
>  }
>  
> +static void mhi_pci_recovery_work(struct work_struct *work)
> +{
> +	struct mhi_pci_device *mhi_pdev = container_of(work, struct mhi_pci_device,
> +						       recovery_work);
> +	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
> +	struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
> +	int err;
> +
> +	dev_warn(&pdev->dev, "device recovery started\n");
> +
> +	/* Clean up MHI state */
> +	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
> +		mhi_power_down(mhi_cntrl, false);
> +		mhi_unprepare_after_power_down(mhi_cntrl);
> +	}
> +
> +	/* Check if we can recover without full reset */
> +	pci_set_power_state(pdev, PCI_D0);
> +	pci_load_saved_state(pdev, mhi_pdev->pci_state);
> +	pci_restore_state(pdev);
> +
> +	if (!mhi_pci_is_alive(mhi_cntrl))
> +		goto err_try_reset;
> +
> +	err = mhi_prepare_for_power_up(mhi_cntrl);
> +	if (err)
> +		goto err_try_reset;
> +
> +	err = mhi_sync_power_up(mhi_cntrl);
> +	if (err)
> +		goto err_unprepare;
> +
> +	dev_dbg(&pdev->dev, "Recovery completed\n");
> +
> +	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
> +	return;
> +
> +err_unprepare:
> +	mhi_unprepare_after_power_down(mhi_cntrl);
> +err_try_reset:
> +	if (pci_reset_function(pdev))
> +		dev_err(&pdev->dev, "Recovery failed\n");
> +}
> +
>  static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  {
>  	const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
> @@ -327,6 +373,8 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	if (!mhi_pdev)
>  		return -ENOMEM;
>  
> +	INIT_WORK(&mhi_pdev->recovery_work, mhi_pci_recovery_work);
> +
>  	mhi_cntrl_config = info->config;
>  	mhi_cntrl = &mhi_pdev->mhi_cntrl;
>  
> @@ -391,6 +439,8 @@ static void mhi_pci_remove(struct pci_dev *pdev)
>  	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
>  	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
>  
> +	cancel_work_sync(&mhi_pdev->recovery_work);
> +
>  	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
>  		mhi_power_down(mhi_cntrl, true);
>  		mhi_unprepare_after_power_down(mhi_cntrl);
> @@ -456,12 +506,67 @@ static const struct pci_error_handlers mhi_pci_err_handler = {
>  	.reset_done = mhi_pci_reset_done,
>  };
>  
> +static int  __maybe_unused mhi_pci_suspend(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
> +	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
> +
> +	cancel_work_sync(&mhi_pdev->recovery_work);
> +
> +	/* Transition to M3 state */
> +	mhi_pm_suspend(mhi_cntrl);
> +
> +	pci_save_state(pdev);
> +	pci_disable_device(pdev);
> +	pci_wake_from_d3(pdev, true);
> +	pci_set_power_state(pdev, PCI_D3hot);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused mhi_pci_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
> +	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
> +	int err;
> +
> +	pci_set_power_state(pdev, PCI_D0);
> +	pci_restore_state(pdev);
> +	pci_set_master(pdev);
> +
> +	err = pci_enable_device(pdev);
> +	if (err)
> +		goto err_recovery;
> +
> +	/* Exit M3, transition to M0 state */
> +	err = mhi_pm_resume(mhi_cntrl);
> +	if (err) {
> +		dev_err(&pdev->dev, "failed to resume device: %d\n", err);
> +		goto err_recovery;
> +	}
> +
> +	return 0;
> +
> +err_recovery:
> +	/* The device may have loose power or crashed, try recovering it */
> +	queue_work(system_long_wq, &mhi_pdev->recovery_work);
> +
> +	return err;
> +}
> +
> +static const struct dev_pm_ops mhi_pci_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume)
> +};
> +
>  static struct pci_driver mhi_pci_driver = {
>  	.name		= "mhi-pci-generic",
>  	.id_table	= mhi_pci_id_table,
>  	.probe		= mhi_pci_probe,
>  	.remove		= mhi_pci_remove,
>  	.err_handler	= &mhi_pci_err_handler,
> +	.driver.pm	= &mhi_pci_pm_ops
>  };
>  module_pci_driver(mhi_pci_driver);
>  
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers
  2020-12-29  8:43 ` [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers Loic Poulain
@ 2020-12-31  7:18   ` Manivannan Sadhasivam
  2020-12-31  9:27     ` Loic Poulain
  0 siblings, 1 reply; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  7:18 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk

On Tue, Dec 29, 2020 at 09:43:48AM +0100, Loic Poulain wrote:
> In AER capable root complex, errors are reported to the host which
> can then act accordingly and perform PCI recovering procedure.
> 
> This patch enables error reporting and implements error_detected,
> slot_reset and resume callbacks.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
> ---
>  drivers/bus/mhi/pci_generic.c | 50 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
> index 3297d95..9fe1e30 100644
> --- a/drivers/bus/mhi/pci_generic.c
> +++ b/drivers/bus/mhi/pci_generic.c
> @@ -8,6 +8,7 @@
>   * Copyright (C) 2020 Linaro Ltd <loic.poulain@linaro.org>
>   */
>  
> +#include <linux/aer.h>
>  #include <linux/delay.h>
>  #include <linux/device.h>
>  #include <linux/mhi.h>
> @@ -405,6 +406,8 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	pci_save_state(pdev);
>  	mhi_pdev->pci_state = pci_store_saved_state(pdev);
>  
> +	pci_enable_pcie_error_reporting(pdev);
> +
>  	err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);
>  	if (err)
>  		return err;
> @@ -501,7 +504,54 @@ static void mhi_pci_reset_done(struct pci_dev *pdev)
>  	set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
>  }
>  
> +static pci_ers_result_t mhi_pci_error_detected(struct pci_dev *pdev,
> +					       pci_channel_state_t state)
> +{
> +	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
> +	struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
> +
> +	dev_err(&pdev->dev, "PCI error detected, state = %u\n", state);
> +
> +	if (state == pci_channel_io_perm_failure)
> +		return PCI_ERS_RESULT_DISCONNECT;
> +
> +	/* Clean up MHI state */
> +	if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
> +		mhi_power_down(mhi_cntrl, false);
> +		mhi_unprepare_after_power_down(mhi_cntrl);
> +	} else {
> +		/* Nothing to do */
> +		return PCI_ERS_RESULT_RECOVERED;
> +	}
> +
> +	pci_disable_device(pdev);
> +
> +	return PCI_ERS_RESULT_NEED_RESET;
> +}
> +
> +static pci_ers_result_t mhi_pci_slot_reset(struct pci_dev *pdev)
> +{
> +	if (pci_enable_device(pdev)) {
> +		dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n");
> +		return PCI_ERS_RESULT_DISCONNECT;
> +	}
> +

This callback will be called after PCI slot reset, so we should also be resetting
the device after enabling it.

Thanks,
Mani

> +	return PCI_ERS_RESULT_RECOVERED;
> +}
> +
> +static void mhi_pci_io_resume(struct pci_dev *pdev)
> +{
> +	struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
> +
> +	dev_err(&pdev->dev, "PCI slot reset done\n");
> +
> +	queue_work(system_long_wq, &mhi_pdev->recovery_work);
> +}
> +
>  static const struct pci_error_handlers mhi_pci_err_handler = {
> +	.error_detected = mhi_pci_error_detected,
> +	.slot_reset = mhi_pci_slot_reset,
> +	.resume = mhi_pci_io_resume,
>  	.reset_prepare = mhi_pci_reset_prepare,
>  	.reset_done = mhi_pci_reset_done,
>  };
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value
  2020-12-29  8:43 ` [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value Loic Poulain
@ 2020-12-31  7:18   ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  7:18 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk

On Tue, Dec 29, 2020 at 09:43:50AM +0100, Loic Poulain wrote:
> On cold boot, device can take slightly more than 5 seconds to start.
> Increase the timeout to prevent MHI power-up issues.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Thanks,
Mani

> ---
>  drivers/bus/mhi/pci_generic.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
> index 812d54f..d4ad9c5 100644
> --- a/drivers/bus/mhi/pci_generic.c
> +++ b/drivers/bus/mhi/pci_generic.c
> @@ -162,7 +162,7 @@ static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
>  
>  static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
>  	.max_channels = 128,
> -	.timeout_ms = 5000,
> +	.timeout_ms = 8000,
>  	.num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels),
>  	.ch_cfg = modem_qcom_v1_mhi_channels,
>  	.num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events),
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 10/10] mhi: pci_generic: Add diag channels
  2020-12-29  8:43 ` [PATCH v6 10/10] mhi: pci_generic: Add diag channels Loic Poulain
@ 2020-12-31  7:20   ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31  7:20 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, bbhatt, hemantk

On Tue, Dec 29, 2020 at 09:43:51AM +0100, Loic Poulain wrote:
> Add support for Diag over MHI. Qualcomm Diag is the qualcomm
> diagnostics interface that can be used to collect modem logs,
> events, traces, etc. It can be used by tools such QPST or QXDM.
> 
> This patch adds the DIAG channels and a dedicated event ring.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reviewed-by Hemant Kumar <hemantk@codeaurora.org>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Thanks,
Mani

> ---
>  drivers/bus/mhi/pci_generic.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
> index d4ad9c5..0947596 100644
> --- a/drivers/bus/mhi/pci_generic.c
> +++ b/drivers/bus/mhi/pci_generic.c
> @@ -142,22 +142,26 @@ struct mhi_pci_dev_info {
>  	}
>  
>  static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
> +	MHI_CHANNEL_CONFIG_UL(4, "DIAG", 16, 1),
> +	MHI_CHANNEL_CONFIG_DL(5, "DIAG", 16, 1),
>  	MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0),
>  	MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0),
>  	MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
>  	MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
>  	MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
>  	MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
> -	MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
> -	MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
> +	MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
> +	MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
>  };
>  
>  static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
>  	/* first ring is control+data ring */
>  	MHI_EVENT_CONFIG_CTRL(0),
> +	/* DIAG dedicated event ring */
> +	MHI_EVENT_CONFIG_DATA(1),
>  	/* Hardware channels request dedicated hardware event rings */
> -	MHI_EVENT_CONFIG_HW_DATA(1, 100),
> -	MHI_EVENT_CONFIG_HW_DATA(2, 101)
> +	MHI_EVENT_CONFIG_HW_DATA(2, 100),
> +	MHI_EVENT_CONFIG_HW_DATA(3, 101)
>  };
>  
>  static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
> -- 
> 2.7.4
> 

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

* Re: [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers
  2020-12-31  7:18   ` Manivannan Sadhasivam
@ 2020-12-31  9:27     ` Loic Poulain
  2020-12-31 11:14       ` Manivannan Sadhasivam
  0 siblings, 1 reply; 19+ messages in thread
From: Loic Poulain @ 2020-12-31  9:27 UTC (permalink / raw)
  To: Manivannan Sadhasivam; +Cc: linux-arm-msm, Bhaumik Bhatt, Hemant Kumar

Hi Mani,

On Thu, 31 Dec 2020 at 08:18, Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:
>
> On Tue, Dec 29, 2020 at 09:43:48AM +0100, Loic Poulain wrote:
> > In AER capable root complex, errors are reported to the host which
> > can then act accordingly and perform PCI recovering procedure.
> >
> > This patch enables error reporting and implements error_detected,
> > slot_reset and resume callbacks.
> >
> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
> > ---
> >  drivers/bus/mhi/pci_generic.c | 50 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 50 insertions(+)

> > +static pci_ers_result_t mhi_pci_slot_reset(struct pci_dev *pdev)
> > +{
> > +     if (pci_enable_device(pdev)) {
> > +             dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n");
> > +             return PCI_ERS_RESULT_DISCONNECT;
> > +     }
> > +
>
> This callback will be called after PCI slot reset, so we should also be resetting
> the device after enabling it.

Yes, but that is done in mhi_pci_io_resume.

From the PCI error recovery documentation, "drivers should not restart
normal I/O processing operations at this point (in slot_reset) If all
device drivers report success on this callback, the platform will call
resume() to complete the sequence, and let the driver restart normal
I/O processing."
The actual MHI PCI/recovery is then done in resume (mhi_pci_io_resume).

Regards,
Loic

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

* Re: [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers
  2020-12-31  9:27     ` Loic Poulain
@ 2020-12-31 11:14       ` Manivannan Sadhasivam
  0 siblings, 0 replies; 19+ messages in thread
From: Manivannan Sadhasivam @ 2020-12-31 11:14 UTC (permalink / raw)
  To: Loic Poulain; +Cc: linux-arm-msm, Bhaumik Bhatt, Hemant Kumar

On Thu, Dec 31, 2020 at 10:27:01AM +0100, Loic Poulain wrote:
> Hi Mani,
> 
> On Thu, 31 Dec 2020 at 08:18, Manivannan Sadhasivam
> <manivannan.sadhasivam@linaro.org> wrote:
> >
> > On Tue, Dec 29, 2020 at 09:43:48AM +0100, Loic Poulain wrote:
> > > In AER capable root complex, errors are reported to the host which
> > > can then act accordingly and perform PCI recovering procedure.
> > >
> > > This patch enables error reporting and implements error_detected,
> > > slot_reset and resume callbacks.
> > >
> > > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > > Reviewed-by Hemant Kumar <hemantk@codeaurora.org>
> > > ---
> > >  drivers/bus/mhi/pci_generic.c | 50 +++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 50 insertions(+)
> 
> > > +static pci_ers_result_t mhi_pci_slot_reset(struct pci_dev *pdev)
> > > +{
> > > +     if (pci_enable_device(pdev)) {
> > > +             dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n");
> > > +             return PCI_ERS_RESULT_DISCONNECT;
> > > +     }
> > > +
> >
> > This callback will be called after PCI slot reset, so we should also be resetting
> > the device after enabling it.
> 
> Yes, but that is done in mhi_pci_io_resume.
> 
> From the PCI error recovery documentation, "drivers should not restart
> normal I/O processing operations at this point (in slot_reset) If all
> device drivers report success on this callback, the platform will call
> resume() to complete the sequence, and let the driver restart normal
> I/O processing."
> The actual MHI PCI/recovery is then done in resume (mhi_pci_io_resume).
> 

If you read one paragraph above,

"This call gives drivers the chance to re-initialize the hardware
(re-download firmware, etc.).  At this point, the driver may assume
that the card is in a fresh state and is fully functional. The slot
is unfrozen and the driver has full access to PCI config space,
memory mapped I/O space and DMA."

So at the end of this call, the device is assumed to be functional (then only
PCI_ERS_RESULT_RECOVERED makes sense).

IMO, you should call mhi_pci_reset_prepare() in this callback and
mhi_pci_reset_done() in resume(). No need to schedule the recovery work.

Thanks,
Mani

> Regards,
> Loic

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

end of thread, other threads:[~2020-12-31 11:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-29  8:43 [PATCH v6 00/10] mhi: pci_generic: Misc improvements Loic Poulain
2020-12-29  8:43 ` [PATCH v6 01/10] mhi: Add mhi_controller_initialize helper Loic Poulain
2020-12-31  6:48   ` Manivannan Sadhasivam
2020-12-29  8:43 ` [PATCH v6 02/10] bus: mhi: core: Add device hardware reset support Loic Poulain
2020-12-31  7:01   ` Manivannan Sadhasivam
2020-12-29  8:43 ` [PATCH v6 03/10] mhi: pci-generic: Increase number of hardware events Loic Poulain
2020-12-29  8:43 ` [PATCH v6 04/10] mhi: pci_generic: Enable burst mode for hardware channels Loic Poulain
2020-12-29  8:43 ` [PATCH v6 05/10] mhi: pci_generic: Add support for reset Loic Poulain
2020-12-29  8:43 ` [PATCH v6 06/10] mhi: pci_generic: Add suspend/resume/recovery procedure Loic Poulain
2020-12-31  7:05   ` Manivannan Sadhasivam
2020-12-29  8:43 ` [PATCH v6 07/10] mhi: pci_generic: Add PCI error handlers Loic Poulain
2020-12-31  7:18   ` Manivannan Sadhasivam
2020-12-31  9:27     ` Loic Poulain
2020-12-31 11:14       ` Manivannan Sadhasivam
2020-12-29  8:43 ` [PATCH v6 08/10] mhi: pci_generic: Add health-check Loic Poulain
2020-12-29  8:43 ` [PATCH v6 09/10] mhi: pci_generic: Increase controller timeout value Loic Poulain
2020-12-31  7:18   ` Manivannan Sadhasivam
2020-12-29  8:43 ` [PATCH v6 10/10] mhi: pci_generic: Add diag channels Loic Poulain
2020-12-31  7:20   ` Manivannan Sadhasivam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).