2020-05-18 20:06:44

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 0/7] Introduce features and debugfs/sysfs entries for MHI

Introduce independent bus and device voting mechanism for clients and save
hardware information from BHI.
Allow reading and modifying some MHI variables for debug, test, and
informational purposes using debugfs.
Read values for device specific hardware information to be used by OEMs in
factory testing such as serial number and PK hash using sysfs.

This set of patches was tested on arm64 and x86.

v3:
-Add patch to check for pending packets in suspend as a dependency for the
independent voting mechanism introduction
-Include register dump entry for debugfs to dump MHI, BHI, and BHIe registers
-Update commit message for the debugfs patch
-Updated Documentation/ABI with the required info for sysfs
-Updated debugfs patch to include a new KConfig entry and dependencies
-Updated reviewed-by for some patches

v2:
-Added a new debugfs.c file for specific debugfs entries and code
-Updated commit text and addressed some comments for voting change
-Made sure sysfs is only used for serial number and OEM PK hash usage

Bhaumik Bhatt (7):
bus: mhi: core: Abort suspends due to outgoing pending packets
bus: mhi: core: Introduce independent voting mechanism
bus: mhi: core: Use generic name field for an MHI device
bus: mhi: core: Introduce helper function to check device state
bus: mhi: core: Introduce debugfs entries and counters for MHI
bus: mhi: core: Read and save device hardware information from BHI
bus: mhi: core: Introduce sysfs entries for MHI

Documentation/ABI/stable/sysfs-bus-mhi | 25 ++
MAINTAINERS | 1 +
drivers/bus/mhi/Kconfig | 8 +
drivers/bus/mhi/core/Makefile | 5 +-
drivers/bus/mhi/core/boot.c | 17 +-
drivers/bus/mhi/core/debugfs.c | 501 +++++++++++++++++++++++++++++++++
drivers/bus/mhi/core/init.c | 80 +++++-
drivers/bus/mhi/core/internal.h | 29 ++
drivers/bus/mhi/core/main.c | 6 +-
drivers/bus/mhi/core/pm.c | 79 ++++--
include/linux/mhi.h | 39 ++-
11 files changed, 745 insertions(+), 45 deletions(-)
create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi
create mode 100644 drivers/bus/mhi/core/debugfs.c

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2020-05-18 20:06:49

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 7/7] bus: mhi: core: Introduce sysfs entries for MHI

Introduce sysfs entries to enable userspace clients the ability to read
the serial number and the OEM PK Hash values obtained from BHI. OEMs
need to read these device-specific hardware information values through
userspace for factory testing purposes and cannot be exposed via degbufs
as it may remain disabled for performance reasons. Also, update the
documentation for ABI to include these entries.

Signed-off-by: Bhaumik Bhatt <[email protected]>
---
Documentation/ABI/stable/sysfs-bus-mhi | 25 ++++++++++++++++
MAINTAINERS | 1 +
drivers/bus/mhi/core/init.c | 53 ++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+)
create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi

diff --git a/Documentation/ABI/stable/sysfs-bus-mhi b/Documentation/ABI/stable/sysfs-bus-mhi
new file mode 100644
index 0000000..65ef711
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-bus-mhi
@@ -0,0 +1,25 @@
+What: /sys/bus/mhi/devices/.../serialnumber
+Date: May 2020
+KernelVersion: 5.8
+Contact: Bhaumik Bhatt <[email protected]>
+Description:
+ The file holds the serial number of the endpoint device obtained
+ using a BHI (Boot Host Interface) register read after at least
+ one attempt to power up the device has been done. If read
+ without having the device power on at least once, the file will
+ read all 0's.
+Users: Any userspace application or clients interested in the device
+ hardware information.
+
+What: /sys/bus/mhi/devices/.../oem_pk_hash
+Date: May 2020
+KernelVersion: 5.8
+Contact: Bhaumik Bhatt <[email protected]>
+Description:
+ The file holds the OEM PK Hash value of the endpoint device
+ obtained using a BHI (Boot Host Interface) register read after
+ at least one attempt to power up the device has been done. If
+ read without having the device power on at least once, the file
+ will read all 0's.
+Users: Any userspace application or clients interested in the device
+ hardware information.
diff --git a/MAINTAINERS b/MAINTAINERS
index e64e5db..5e49316 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11018,6 +11018,7 @@ M: Hemant Kumar <[email protected]>
L: [email protected]
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git
+F: Documentation/ABI/stable/sysfs-bus-mhi
F: Documentation/mhi/
F: drivers/bus/mhi/
F: include/linux/mhi.h
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 83ad544..9b6a5173 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -76,6 +76,56 @@ const char *to_mhi_pm_state_str(enum mhi_pm_state state)
return mhi_pm_state_str[index];
}

+static ssize_t serial_number_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mhi_device *mhi_dev = to_mhi_device(dev);
+ struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+
+ return snprintf(buf, PAGE_SIZE, "Serial Number:%u\n",
+ mhi_cntrl->serial_number);
+}
+static DEVICE_ATTR_RO(serial_number);
+
+static ssize_t oem_pk_hash_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mhi_device *mhi_dev = to_mhi_device(dev);
+ struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+ int i, cnt = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++)
+ cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
+ "OEMPKHASH[%d]:0x%x\n", i,
+ mhi_cntrl->oem_pk_hash[i]);
+
+ return cnt;
+}
+static DEVICE_ATTR_RO(oem_pk_hash);
+
+static struct attribute *mhi_sysfs_attrs[] = {
+ &dev_attr_serial_number.attr,
+ &dev_attr_oem_pk_hash.attr,
+ NULL,
+};
+
+static const struct attribute_group mhi_sysfs_group = {
+ .attrs = mhi_sysfs_attrs,
+};
+
+static int mhi_create_sysfs(struct mhi_controller *mhi_cntrl)
+{
+ return sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj,
+ &mhi_sysfs_group);
+}
+
+static void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl)
+{
+ sysfs_remove_group(&mhi_cntrl->mhi_dev->dev.kobj, &mhi_sysfs_group);
+}
+
/* MHI protocol requires the transfer ring to be aligned with ring length */
static int mhi_alloc_aligned_ring(struct mhi_controller *mhi_cntrl,
struct mhi_ring *ring,
@@ -917,6 +967,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
mhi_cntrl->mhi_dev = mhi_dev;

mhi_create_debugfs(mhi_cntrl);
+ if (mhi_create_sysfs(mhi_cntrl))
+ dev_err(mhi_cntrl->cntrl_dev, "Failed to create sysfs entries\n");

return 0;

@@ -940,6 +992,7 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan;
unsigned int i;

+ mhi_destroy_sysfs(mhi_cntrl);
mhi_destroy_debugfs(mhi_cntrl);

kfree(mhi_cntrl->mhi_cmd);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-18 20:07:06

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 3/7] bus: mhi: core: Use generic name field for an MHI device

An MHI device is not necessarily associated with only channels as we can
have one associated with the controller itself. Hence, the chan_name
field within the mhi_device structure should instead be replaced with a
generic name to accurately reflect any type of MHI device.

Signed-off-by: Bhaumik Bhatt <[email protected]>
Reviewed-by: Jeffrey Hugo <[email protected]>
---
drivers/bus/mhi/core/init.c | 5 +++--
drivers/bus/mhi/core/main.c | 6 +++---
include/linux/mhi.h | 8 ++++----
3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index b7b5f7f..0d39779 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -904,6 +904,7 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
mhi_dev->dev_type = MHI_DEVICE_CONTROLLER;
mhi_dev->mhi_cntrl = mhi_cntrl;
dev_set_name(&mhi_dev->dev, "%s", dev_name(mhi_cntrl->cntrl_dev));
+ mhi_dev->name = dev_name(mhi_cntrl->cntrl_dev);

/* Init wakeup source */
device_init_wakeup(&mhi_dev->dev, true);
@@ -1252,7 +1253,7 @@ static int mhi_uevent(struct device *dev, struct kobj_uevent_env *env)
struct mhi_device *mhi_dev = to_mhi_device(dev);

return add_uevent_var(env, "MODALIAS=" MHI_DEVICE_MODALIAS_FMT,
- mhi_dev->chan_name);
+ mhi_dev->name);
}

static int mhi_match(struct device *dev, struct device_driver *drv)
@@ -1269,7 +1270,7 @@ static int mhi_match(struct device *dev, struct device_driver *drv)
return 0;

for (id = mhi_drv->id_table; id->chan[0]; id++)
- if (!strcmp(mhi_dev->chan_name, id->chan)) {
+ if (!strcmp(mhi_dev->name, id->chan)) {
mhi_dev->id = id;
return 1;
}
diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
index 1f622ce..bafc12a 100644
--- a/drivers/bus/mhi/core/main.c
+++ b/drivers/bus/mhi/core/main.c
@@ -249,7 +249,7 @@ int mhi_destroy_device(struct device *dev, void *data)
put_device(&mhi_dev->dl_chan->mhi_dev->dev);

dev_dbg(&mhi_cntrl->mhi_dev->dev, "destroy device for chan:%s\n",
- mhi_dev->chan_name);
+ mhi_dev->name);

/* Notify the client and remove the device from MHI bus */
device_del(dev);
@@ -327,10 +327,10 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
}

/* Channel name is same for both UL and DL */
- mhi_dev->chan_name = mhi_chan->name;
+ mhi_dev->name = mhi_chan->name;
dev_set_name(&mhi_dev->dev, "%s_%s",
dev_name(mhi_cntrl->cntrl_dev),
- mhi_dev->chan_name);
+ mhi_dev->name);

/* Init wakeup source if available */
if (mhi_dev->dl_chan && mhi_dev->dl_chan->wake_capable)
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 10fcb52..9b7bf28 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -439,10 +439,10 @@ struct mhi_controller {
};

/**
- * struct mhi_device - Structure representing a MHI device which binds
- * to channels
+ * struct mhi_device - Structure representing an MHI device which binds
+ * to channels or is associated with controllers
* @id: Pointer to MHI device ID struct
- * @chan_name: Name of the channel to which the device binds
+ * @name: Name of the associated MHI device
* @mhi_cntrl: Controller the device belongs to
* @ul_chan: UL channel for the device
* @dl_chan: DL channel for the device
@@ -454,7 +454,7 @@ struct mhi_controller {
*/
struct mhi_device {
const struct mhi_device_id *id;
- const char *chan_name;
+ const char *name;
struct mhi_controller *mhi_cntrl;
struct mhi_chan *ul_chan;
struct mhi_chan *dl_chan;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-18 20:07:17

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

Allow independent votes from clients such that they can choose to vote
for either the device or the bus or both. This helps in cases where the
device supports autonomous low power mode wherein it can move to M2
state without the need to notify the host. Clients can also vote only to
keep the underlying bus active without having the device in M0 state to
support offload use cases.

Signed-off-by: Bhaumik Bhatt <[email protected]>
---
drivers/bus/mhi/core/init.c | 15 ++++++----
drivers/bus/mhi/core/pm.c | 73 +++++++++++++++++++++++++++++++++------------
include/linux/mhi.h | 21 ++++++++-----
3 files changed, 77 insertions(+), 32 deletions(-)

diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index e43a190..b7b5f7f 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -1062,7 +1062,8 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)
dev->release = mhi_release_device;
dev->parent = mhi_cntrl->cntrl_dev;
mhi_dev->mhi_cntrl = mhi_cntrl;
- mhi_dev->dev_wake = 0;
+ atomic_set(&mhi_dev->dev_vote, 0);
+ atomic_set(&mhi_dev->bus_vote, 0);

return mhi_dev;
}
@@ -1079,7 +1080,7 @@ static int mhi_driver_probe(struct device *dev)
int ret;

/* Bring device out of LPM */
- ret = mhi_device_get_sync(mhi_dev);
+ ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE);
if (ret)
return ret;

@@ -1139,14 +1140,14 @@ static int mhi_driver_probe(struct device *dev)
if (dl_chan && dl_chan->auto_start)
mhi_prepare_channel(mhi_cntrl, dl_chan);

- mhi_device_put(mhi_dev);
+ mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);

return ret;

exit_probe:
mhi_unprepare_from_transfer(mhi_dev);

- mhi_device_put(mhi_dev);
+ mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);

return ret;
}
@@ -1215,8 +1216,10 @@ static int mhi_driver_remove(struct device *dev)
}

read_lock_bh(&mhi_cntrl->pm_lock);
- while (mhi_dev->dev_wake)
- mhi_device_put(mhi_dev);
+ while (atomic_read(&mhi_dev->dev_vote))
+ mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);
+ while (atomic_read(&mhi_dev->bus_vote))
+ mhi_device_put(mhi_dev, MHI_VOTE_BUS);
read_unlock_bh(&mhi_cntrl->pm_lock);

return 0;
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index 661d704..4c9812a 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -675,7 +675,8 @@ void mhi_pm_st_worker(struct work_struct *work)
int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
{
struct mhi_chan *itr, *tmp;
- struct device *dev = &mhi_cntrl->mhi_dev->dev;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+ struct device *dev = &mhi_dev->dev;
enum mhi_pm_state new_state;
int ret;

@@ -687,7 +688,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)

/* Return busy if there are any pending resources */
if (atomic_read(&mhi_cntrl->dev_wake) ||
- atomic_read(&mhi_cntrl->pending_pkts))
+ atomic_read(&mhi_cntrl->pending_pkts) ||
+ atomic_read(&mhi_dev->bus_vote))
return -EBUSY;

/* Take MHI out of M2 state */
@@ -714,7 +716,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
write_lock_irq(&mhi_cntrl->pm_lock);

if (atomic_read(&mhi_cntrl->dev_wake) ||
- atomic_read(&mhi_cntrl->pending_pkts)) {
+ atomic_read(&mhi_cntrl->pending_pkts) ||
+ atomic_read(&mhi_dev->bus_vote)) {
write_unlock_irq(&mhi_cntrl->pm_lock);
return -EBUSY;
}
@@ -1109,42 +1112,74 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
}
EXPORT_SYMBOL_GPL(mhi_force_rddm_mode);

-void mhi_device_get(struct mhi_device *mhi_dev)
+void mhi_device_get(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

- mhi_dev->dev_wake++;
- read_lock_bh(&mhi_cntrl->pm_lock);
- mhi_cntrl->wake_get(mhi_cntrl, true);
- read_unlock_bh(&mhi_cntrl->pm_lock);
+ if (vote & MHI_VOTE_DEVICE) {
+ atomic_inc(&mhi_dev->dev_vote);
+ read_lock_bh(&mhi_cntrl->pm_lock);
+ mhi_cntrl->wake_get(mhi_cntrl, true);
+ read_unlock_bh(&mhi_cntrl->pm_lock);
+ }
+
+ if (vote & MHI_VOTE_BUS) {
+ atomic_inc(&mhi_dev->bus_vote);
+ mhi_cntrl->runtime_get(mhi_cntrl);
+ }
}
EXPORT_SYMBOL_GPL(mhi_device_get);

-int mhi_device_get_sync(struct mhi_device *mhi_dev)
+int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
int ret;

+ /* bring device out of low power modes regardless of the type of vote */
ret = __mhi_device_get_sync(mhi_cntrl);
- if (!ret)
- mhi_dev->dev_wake++;
+ if (ret)
+ return ret;
+
+ if (vote & MHI_VOTE_DEVICE) {
+ atomic_inc(&mhi_dev->dev_vote);
+ } else {
+ /* remove device vote as it was not requested */
+ read_lock_bh(&mhi_cntrl->pm_lock);
+ mhi_cntrl->wake_put(mhi_cntrl, false);
+ read_unlock_bh(&mhi_cntrl->pm_lock);
+ }
+
+ if (vote & MHI_VOTE_BUS) {
+ atomic_inc(&mhi_dev->bus_vote);
+ mhi_cntrl->runtime_get(mhi_cntrl);
+ }

return ret;
}
EXPORT_SYMBOL_GPL(mhi_device_get_sync);

-void mhi_device_put(struct mhi_device *mhi_dev)
+void mhi_device_put(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

- mhi_dev->dev_wake--;
- read_lock_bh(&mhi_cntrl->pm_lock);
- if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) {
- mhi_cntrl->runtime_get(mhi_cntrl);
- mhi_cntrl->runtime_put(mhi_cntrl);
+ if (vote & MHI_VOTE_DEVICE) {
+ atomic_dec(&mhi_dev->dev_vote);
+ read_lock_bh(&mhi_cntrl->pm_lock);
+ if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) {
+ mhi_cntrl->runtime_get(mhi_cntrl);
+ mhi_cntrl->runtime_put(mhi_cntrl);
+ }
+ mhi_cntrl->wake_put(mhi_cntrl, false);
+ read_unlock_bh(&mhi_cntrl->pm_lock);
}

- mhi_cntrl->wake_put(mhi_cntrl, false);
- read_unlock_bh(&mhi_cntrl->pm_lock);
+ if (vote & MHI_VOTE_BUS) {
+ atomic_dec(&mhi_dev->bus_vote);
+ mhi_cntrl->runtime_put(mhi_cntrl);
+
+ /* notify controller that all bus votes are removed */
+ if (!atomic_read(&mhi_dev->bus_vote))
+ mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_IDLE);
+ }
}
EXPORT_SYMBOL_GPL(mhi_device_put);
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index b008914..10fcb52 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -16,6 +16,9 @@
#include <linux/wait.h>
#include <linux/workqueue.h>

+#define MHI_VOTE_BUS BIT(0) /* do not disable the mhi bus */
+#define MHI_VOTE_DEVICE BIT(1) /* prevent mhi device from entering lpm */
+
struct mhi_chan;
struct mhi_event;
struct mhi_ctxt;
@@ -459,7 +462,8 @@ struct mhi_device {
enum mhi_device_type dev_type;
int ul_chan_id;
int dl_chan_id;
- u32 dev_wake;
+ atomic_t dev_vote;
+ atomic_t bus_vote;
};

/**
@@ -644,23 +648,26 @@ void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl,
enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl);

/**
- * mhi_device_get - Disable device low power mode
+ * mhi_device_get - Disable device and/or bus low power mode
* @mhi_dev: Device associated with the channel
+ * @vote: requested vote (bus, device or both)
*/
-void mhi_device_get(struct mhi_device *mhi_dev);
+void mhi_device_get(struct mhi_device *mhi_dev, int vote);

/**
- * mhi_device_get_sync - Disable device low power mode. Synchronously
+ * mhi_device_get_sync - Disable device and/or bus low power mode. Synchronously
* take the controller out of suspended state
* @mhi_dev: Device associated with the channel
+ * @vote: requested vote (bus, device or both)
*/
-int mhi_device_get_sync(struct mhi_device *mhi_dev);
+int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote);

/**
- * mhi_device_put - Re-enable device low power mode
+ * mhi_device_put - Re-enable device and/or bus low power mode
* @mhi_dev: Device associated with the channel
+ * @vote: vote(s) to remove (bus, device or both)
*/
-void mhi_device_put(struct mhi_device *mhi_dev);
+void mhi_device_put(struct mhi_device *mhi_dev, int vote);

/**
* mhi_prepare_for_transfer - Setup channel for data transfer
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-18 20:08:57

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 5/7] bus: mhi: core: Introduce debugfs entries and counters for MHI

Introduce debugfs entries to show state, register, channel, and event
ring information. Add MHI state counters to keep track of the state
changes on the device. Also, allow the host to trigger a device reset,
issue bus or device votes, and change the MHI timeout to help in debug.

Signed-off-by: Bhaumik Bhatt <[email protected]>
---
drivers/bus/mhi/Kconfig | 8 +
drivers/bus/mhi/core/Makefile | 5 +-
drivers/bus/mhi/core/debugfs.c | 501 ++++++++++++++++++++++++++++++++++++++++
drivers/bus/mhi/core/init.c | 7 +
drivers/bus/mhi/core/internal.h | 24 ++
drivers/bus/mhi/core/pm.c | 4 +
include/linux/mhi.h | 4 +
7 files changed, 550 insertions(+), 3 deletions(-)
create mode 100644 drivers/bus/mhi/core/debugfs.c

diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig
index a8bd9bd..6a217ff 100644
--- a/drivers/bus/mhi/Kconfig
+++ b/drivers/bus/mhi/Kconfig
@@ -12,3 +12,11 @@ config MHI_BUS
communication protocol used by the host processors to control
and communicate with modem devices over a high speed peripheral
bus or shared memory.
+
+config MHI_BUS_DEBUG
+ bool "Debugfs support for the MHI bus"
+ depends on MHI_BUS && DEBUG_FS
+ help
+ Enable debugfs support for use with the MHI transport. Allows
+ reading and/or modifying some values within the MHI controller
+ for debug and test purposes.
diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile
index 66e2700..460a548 100644
--- a/drivers/bus/mhi/core/Makefile
+++ b/drivers/bus/mhi/core/Makefile
@@ -1,3 +1,2 @@
-obj-$(CONFIG_MHI_BUS) := mhi.o
-
-mhi-y := init.o main.o pm.o boot.o
+obj-$(CONFIG_MHI_BUS) := init.o main.o pm.o boot.o
+obj-$(CONFIG_MHI_BUS_DEBUG) += debugfs.o
diff --git a/drivers/bus/mhi/core/debugfs.c b/drivers/bus/mhi/core/debugfs.c
new file mode 100644
index 0000000..b37de83
--- /dev/null
+++ b/drivers/bus/mhi/core/debugfs.c
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mhi.h>
+#include "internal.h"
+
+static int mhi_debugfs_states_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+
+ /* states */
+ seq_printf(m, "PM state:%s Device:%s MHI state:%s EE:%s wake:%s\n",
+ to_mhi_pm_state_str(mhi_cntrl->pm_state),
+ mhi_is_active(mhi_cntrl) ? "Active" : "Inactive",
+ TO_MHI_STATE_STR(mhi_cntrl->dev_state),
+ TO_MHI_EXEC_STR(mhi_cntrl->ee),
+ mhi_cntrl->wake_set ? "true" : "false");
+
+ /* counters */
+ seq_printf(m, "M0:%u M2:%u M3:%u M3_Fast:%u", mhi_cntrl->M0,
+ mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->M3_fast);
+
+ seq_printf(m, " device wake:%u pending packets:%u\n",
+ atomic_read(&mhi_cntrl->dev_wake),
+ atomic_read(&mhi_cntrl->pending_pkts));
+
+ return 0;
+}
+
+static int mhi_debugfs_events_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_event *mhi_event;
+ struct mhi_event_ctxt *er_ctxt;
+ int i;
+
+ if (!mhi_is_active(mhi_cntrl)) {
+ seq_puts(m, "Device not ready\n");
+ return -ENODEV;
+ }
+
+ er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt;
+ mhi_event = mhi_cntrl->mhi_event;
+ for (i = 0; i < mhi_cntrl->total_ev_rings;
+ i++, er_ctxt++, mhi_event++) {
+ struct mhi_ring *ring = &mhi_event->ring;
+
+ if (mhi_event->offload_ev) {
+ seq_printf(m, "Index:%d is an offload event ring\n", i);
+ continue;
+ }
+
+ seq_printf(m, "Index:%d intmod count:%lu time:%lu",
+ i, (er_ctxt->intmod & EV_CTX_INTMODC_MASK) >>
+ EV_CTX_INTMODC_SHIFT,
+ (er_ctxt->intmod & EV_CTX_INTMODT_MASK) >>
+ EV_CTX_INTMODT_SHIFT);
+
+ seq_printf(m, " base:0x%0llx len:0x%llx", er_ctxt->rbase,
+ er_ctxt->rlen);
+
+ seq_printf(m,
+ " rp:0x%llx wp:0x%llx local rp:0x%llx db:0x%llx\n",
+ er_ctxt->rp, er_ctxt->wp, (u64)ring->rp,
+ mhi_event->db_cfg.db_val);
+ }
+
+ return 0;
+}
+
+static int mhi_debugfs_channels_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_chan *mhi_chan;
+ struct mhi_chan_ctxt *chan_ctxt;
+ int i;
+
+ if (!mhi_is_active(mhi_cntrl)) {
+ seq_puts(m, "Device not ready\n");
+ return -ENODEV;
+ }
+
+ mhi_chan = mhi_cntrl->mhi_chan;
+ chan_ctxt = mhi_cntrl->mhi_ctxt->chan_ctxt;
+ for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) {
+ struct mhi_ring *ring = &mhi_chan->tre_ring;
+
+ if (mhi_chan->offload_ch) {
+ seq_printf(m, "%s(%u) is an offload channel\n",
+ mhi_chan->name, mhi_chan->chan);
+ continue;
+ }
+
+ if (!mhi_chan->mhi_dev)
+ continue;
+
+ seq_printf(m,
+ "%s(%u) state:0x%lx brstmode:0x%lx pollcfg:0x%lx",
+ mhi_chan->name, mhi_chan->chan, (chan_ctxt->chcfg &
+ CHAN_CTX_CHSTATE_MASK) >> CHAN_CTX_CHSTATE_SHIFT,
+ (chan_ctxt->chcfg & CHAN_CTX_BRSTMODE_MASK) >>
+ CHAN_CTX_BRSTMODE_SHIFT, (chan_ctxt->chcfg &
+ CHAN_CTX_POLLCFG_MASK) >> CHAN_CTX_POLLCFG_SHIFT);
+
+ seq_printf(m, " type:0x%x event ring:%u", chan_ctxt->chtype,
+ chan_ctxt->erindex);
+
+ seq_printf(m, " base:0x%llx len:0x%llx wp:0x%llx",
+ chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->wp);
+
+ seq_printf(m, " local rp:0x%llx local wp:0x%llx db:0x%llx\n",
+ (u64)ring->rp, (u64)ring->wp,
+ mhi_chan->db_cfg.db_val);
+ }
+
+ return 0;
+}
+
+static int mhi_device_votes_show(struct device *dev, void *data)
+{
+ struct mhi_device *mhi_dev;
+
+ if (dev->bus != &mhi_bus_type)
+ return 0;
+
+ mhi_dev = to_mhi_device(dev);
+
+ seq_printf((struct seq_file *)data, "%s: device:%u, bus:%u\n",
+ mhi_dev->name, atomic_read(&mhi_dev->dev_vote),
+ atomic_read(&mhi_dev->bus_vote));
+
+ return 0;
+}
+
+static int mhi_debugfs_votes_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+
+ if (!mhi_is_active(mhi_cntrl)) {
+ seq_puts(m, "Device not ready\n");
+ return -ENODEV;
+ }
+
+ device_for_each_child(mhi_cntrl->cntrl_dev, m, mhi_device_votes_show);
+
+ return 0;
+}
+
+static int mhi_debugfs_regdump_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+ enum mhi_state state;
+ enum mhi_ee_type ee;
+ int i, ret = -EIO;
+ u32 val;
+ void __iomem *mhi_base = mhi_cntrl->regs;
+ void __iomem *bhi_base = mhi_cntrl->bhi;
+ void __iomem *bhie_base = mhi_cntrl->bhie;
+ void __iomem *wake_db = mhi_cntrl->wake_db;
+ struct {
+ const char *name;
+ int offset;
+ void __iomem *base;
+ } debug_regs[] = {
+ { "MHI_CTRL", MHICTRL, mhi_base},
+ { "MHI_STATUS", MHISTATUS, mhi_base},
+ { "MHI_WAKE_DB", 0, wake_db},
+ { "BHI_EXECENV", BHI_EXECENV, bhi_base},
+ { "BHI_STATUS", BHI_STATUS, bhi_base},
+ { "BHI_ERRCODE", BHI_ERRCODE, bhi_base},
+ { "BHI_ERRDBG1", BHI_ERRDBG1, bhi_base},
+ { "BHI_ERRDBG2", BHI_ERRDBG2, bhi_base},
+ { "BHI_ERRDBG3", BHI_ERRDBG3, bhi_base},
+ { "BHIE_TXVEC_DB", BHIE_TXVECDB_OFFS, bhie_base},
+ { "BHIE_TXVEC_STATUS", BHIE_TXVECSTATUS_OFFS, bhie_base},
+ { "BHIE_RXVEC_DB", BHIE_RXVECDB_OFFS, bhie_base},
+ { "BHIE_RXVEC_STATUS", BHIE_RXVECSTATUS_OFFS, bhie_base},
+ { NULL },
+ };
+
+ if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
+ return ret;
+
+ seq_printf(m, "Host PM state:%s Device state:%s EE:%s\n",
+ to_mhi_pm_state_str(mhi_cntrl->pm_state),
+ TO_MHI_STATE_STR(mhi_cntrl->dev_state),
+ TO_MHI_EXEC_STR(mhi_cntrl->ee));
+
+ state = mhi_get_mhi_state(mhi_cntrl);
+ ee = mhi_get_exec_env(mhi_cntrl);
+ seq_printf(m, "Device EE:%s state:%s\n", TO_MHI_EXEC_STR(ee),
+ TO_MHI_STATE_STR(state));
+
+ for (i = 0; debug_regs[i].name; i++) {
+ ret = mhi_read_reg(mhi_cntrl, debug_regs[i].base,
+ debug_regs[i].offset, &val);
+ if (ret)
+ continue;
+
+ seq_printf(m, "%s:0x%x\n", debug_regs[i].name, val);
+ }
+
+ return 0;
+}
+
+static int mhi_debugfs_bus_vote_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+
+ if (!mhi_is_active(mhi_cntrl)) {
+ seq_puts(m, "Device not ready\n");
+ return -ENODEV;
+ }
+
+ seq_printf(m, "Votes: %d\n%s\n", atomic_read(&mhi_dev->bus_vote),
+ "Usage: echo get/put > bus_vote for vote/unvote");
+
+ return 0;
+}
+
+static ssize_t mhi_debugfs_bus_vote_write(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+ char buf[32];
+ int ret = -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (!strncmp(buf, "get", 3)) {
+ ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_BUS);
+ } else if (!strncmp(buf, "put", 3)) {
+ mhi_device_put(mhi_dev, MHI_VOTE_BUS);
+ ret = 0;
+ }
+
+ return ret ? ret : count;
+}
+
+static int mhi_debugfs_device_vote_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+
+ if (!mhi_is_active(mhi_cntrl)) {
+ seq_puts(m, "Device not ready\n");
+ return -ENODEV;
+ }
+
+ seq_printf(m,
+ "Votes: %d\n%s\n", atomic_read(&mhi_dev->dev_vote),
+ "Usage: echo get/put > device_vote for vote/unvote");
+
+ return 0;
+}
+
+static ssize_t mhi_debugfs_device_vote_write(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ struct mhi_controller *mhi_cntrl = m->private;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+ char buf[32];
+ int ret = -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (!strncmp(buf, "get", 3)) {
+ ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE);
+ } else if (!strncmp(buf, "put", 3)) {
+ mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);
+ ret = 0;
+ }
+
+ return ret ? ret : count;
+}
+
+static int mhi_debugfs_timeout_ms_show(struct seq_file *m, void *d)
+{
+ struct mhi_controller *mhi_cntrl = m->private;
+
+ seq_printf(m, "%u ms\n", mhi_cntrl->timeout_ms);
+
+ return 0;
+}
+
+static ssize_t mhi_debugfs_timeout_ms_write(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ struct mhi_controller *mhi_cntrl = m->private;
+ u32 timeout_ms;
+
+ if (kstrtou32_from_user(ubuf, count, 0, &timeout_ms))
+ return -EINVAL;
+
+ mhi_cntrl->timeout_ms = timeout_ms;
+
+ return count;
+}
+
+static int mhi_debugfs_trigger_reset(void *data, u64 val)
+{
+ struct mhi_controller *mhi_cntrl = data;
+ struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
+ struct device *dev = &mhi_dev->dev;
+ enum mhi_pm_state cur_state;
+ int ret = -EIO;
+
+ if (!mhi_is_active(mhi_cntrl))
+ return -ENODEV;
+
+ if (!val)
+ return -EINVAL;
+
+ ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE);
+ if (ret) {
+ dev_err(dev, "Device did not enter M0 state, MHI:%s, PM:%s\n",
+ TO_MHI_STATE_STR(mhi_cntrl->dev_state),
+ to_mhi_pm_state_str(mhi_cntrl->pm_state));
+ return ret;
+ }
+
+ if (mhi_cntrl->rddm_image) {
+ ret = mhi_force_rddm_mode(mhi_cntrl);
+ goto exit_mhi_trigger_reset;
+ }
+
+ write_lock_irq(&mhi_cntrl->pm_lock);
+ cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT);
+ write_unlock_irq(&mhi_cntrl->pm_lock);
+
+ if (cur_state != MHI_PM_SYS_ERR_DETECT)
+ goto exit_mhi_trigger_reset;
+
+ mhi_pm_sys_err_handler(mhi_cntrl);
+ ret = 0;
+
+exit_mhi_trigger_reset:
+ mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);
+
+ return ret;
+}
+
+static int mhi_debugfs_states_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_states_show, inode->i_private);
+}
+
+static int mhi_debugfs_events_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_events_show, inode->i_private);
+}
+
+static int mhi_debugfs_channels_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_channels_show, inode->i_private);
+}
+
+static int mhi_debugfs_votes_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_votes_show, inode->i_private);
+}
+
+static int mhi_debugfs_regdump_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_regdump_show, inode->i_private);
+}
+
+static int mhi_debugfs_bus_vote_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_bus_vote_show, inode->i_private);
+}
+
+static int mhi_debugfs_device_vote_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_device_vote_show, inode->i_private);
+}
+
+static int mhi_debugfs_timeout_ms_open(struct inode *inode, struct file *fp)
+{
+ return single_open(fp, mhi_debugfs_timeout_ms_show, inode->i_private);
+}
+
+static const struct file_operations debugfs_states_fops = {
+ .open = mhi_debugfs_states_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_events_fops = {
+ .open = mhi_debugfs_events_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_channels_fops = {
+ .open = mhi_debugfs_channels_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_votes_fops = {
+ .open = mhi_debugfs_votes_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_regdump_fops = {
+ .open = mhi_debugfs_regdump_open,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_bus_vote_fops = {
+ .open = mhi_debugfs_bus_vote_open,
+ .write = mhi_debugfs_bus_vote_write,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_device_vote_fops = {
+ .open = mhi_debugfs_device_vote_open,
+ .write = mhi_debugfs_device_vote_write,
+ .release = single_release,
+ .read = seq_read,
+};
+
+static const struct file_operations debugfs_timeout_ms_fops = {
+ .open = mhi_debugfs_timeout_ms_open,
+ .write = mhi_debugfs_timeout_ms_write,
+ .release = single_release,
+ .read = seq_read,
+};
+
+DEFINE_DEBUGFS_ATTRIBUTE(debugfs_reset_fops, NULL,
+ mhi_debugfs_trigger_reset, "%llu\n");
+
+static struct dentry *mhi_debugfs_root;
+
+void mhi_create_debugfs(struct mhi_controller *mhi_cntrl)
+{
+ if (IS_ERR_OR_NULL(mhi_debugfs_root))
+ return;
+
+ mhi_cntrl->debugfs_dentry =
+ debugfs_create_dir(dev_name(mhi_cntrl->cntrl_dev),
+ mhi_debugfs_root);
+ if (IS_ERR_OR_NULL(mhi_cntrl->debugfs_dentry))
+ return;
+
+ debugfs_create_file("states", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_states_fops);
+ debugfs_create_file("events", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_events_fops);
+ debugfs_create_file("channels", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_channels_fops);
+ debugfs_create_file("votes", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_votes_fops);
+ debugfs_create_file("regdump", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_regdump_fops);
+ debugfs_create_file("bus_vote", 0644, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_bus_vote_fops);
+ debugfs_create_file("device_vote", 0644, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_device_vote_fops);
+ debugfs_create_file("timeout_ms", 0644, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_timeout_ms_fops);
+ debugfs_create_file("reset", 0444, mhi_cntrl->debugfs_dentry,
+ mhi_cntrl, &debugfs_reset_fops);
+}
+
+void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl)
+{
+ debugfs_remove_recursive(mhi_cntrl->debugfs_dentry);
+ mhi_cntrl->debugfs_dentry = NULL;
+}
+
+void mhi_debugfs_init(void)
+{
+ mhi_debugfs_root = debugfs_create_dir(mhi_bus_type.name, NULL);
+}
+
+void mhi_debugfs_exit(void)
+{
+ debugfs_remove_recursive(mhi_debugfs_root);
+}
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 0d39779..83ad544 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -4,6 +4,7 @@
*
*/

+#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
@@ -915,6 +916,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,

mhi_cntrl->mhi_dev = mhi_dev;

+ mhi_create_debugfs(mhi_cntrl);
+
return 0;

error_add_dev:
@@ -937,6 +940,8 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan;
unsigned int i;

+ mhi_destroy_debugfs(mhi_cntrl);
+
kfree(mhi_cntrl->mhi_cmd);
kfree(mhi_cntrl->mhi_event);

@@ -1287,11 +1292,13 @@ struct bus_type mhi_bus_type = {

static int __init mhi_init(void)
{
+ mhi_debugfs_init();
return bus_register(&mhi_bus_type);
}

static void __exit mhi_exit(void)
{
+ mhi_debugfs_exit();
bus_unregister(&mhi_bus_type);
}

diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h
index 2f18be7..798aa483 100644
--- a/drivers/bus/mhi/core/internal.h
+++ b/drivers/bus/mhi/core/internal.h
@@ -570,6 +570,30 @@ struct mhi_chan {
/* Default MHI timeout */
#define MHI_TIMEOUT_MS (1000)

+/* debugfs related functions */
+#ifdef CONFIG_MHI_BUS_DEBUG
+void mhi_create_debugfs(struct mhi_controller *mhi_cntrl);
+void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl);
+void mhi_debugfs_init(void);
+void mhi_debugfs_exit(void);
+#else
+static inline void mhi_create_debugfs(struct mhi_controller *mhi_cntrl)
+{
+}
+
+static inline void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl)
+{
+}
+
+static inline void mhi_debugfs_init(void)
+{
+}
+
+static inline void mhi_debugfs_exit(void)
+{
+}
+#endif
+
struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl);

int mhi_destroy_device(struct device *dev, void *data);
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index 4c9812a..783e3d5 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -256,6 +256,7 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
dev_err(dev, "Unable to transition to M0 state\n");
return -EIO;
}
+ mhi_cntrl->M0++;

/* Wake up the device */
read_lock_bh(&mhi_cntrl->pm_lock);
@@ -326,6 +327,8 @@ void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl)
mhi_cntrl->dev_state = MHI_STATE_M2;

write_unlock_irq(&mhi_cntrl->pm_lock);
+
+ mhi_cntrl->M2++;
wake_up_all(&mhi_cntrl->state_event);

/* If there are any pending resources, exit M2 immediately */
@@ -362,6 +365,7 @@ int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl)
return -EIO;
}

+ mhi_cntrl->M3++;
wake_up_all(&mhi_cntrl->state_event);

return 0;
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 9b7bf28..026a624 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -291,6 +291,7 @@ struct mhi_controller_config {
* @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI
* controller (required)
* @mhi_dev: MHI device instance for the controller
+ * @debugfs_dentry: MHI controller debugfs directory
* @regs: Base address of MHI MMIO register space (required)
* @bhi: Points to base of MHI BHI register space
* @bhie: Points to base of MHI BHIe register space
@@ -329,6 +330,7 @@ struct mhi_controller_config {
* @dev_state: MHI device state
* @dev_wake: Device wakeup count
* @pending_pkts: Pending packets for the controller
+ * @M0, M2, M3, M3_fast: Counters to track number of device MHI state changes
* @transition_list: List of MHI state transitions
* @transition_lock: Lock for protecting MHI state transition list
* @wlock: Lock for protecting device wakeup
@@ -367,6 +369,7 @@ struct mhi_controller_config {
struct mhi_controller {
struct device *cntrl_dev;
struct mhi_device *mhi_dev;
+ struct dentry *debugfs_dentry;
void __iomem *regs;
void __iomem *bhi;
void __iomem *bhie;
@@ -408,6 +411,7 @@ struct mhi_controller {
enum mhi_state dev_state;
atomic_t dev_wake;
atomic_t pending_pkts;
+ u32 M0, M2, M3, M3_fast;
struct list_head transition_list;
spinlock_t transition_lock;
spinlock_t wlock;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-18 20:09:07

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 1/7] bus: mhi: core: Abort suspends due to outgoing pending packets

Add the missing check to abort suspends if a client has pending outgoing
packets to send to the device. This allows better utilization of the MHI
bus wherein clients on the host are not left waiting for longer suspend
or resume cycles to finish for data transfers.

Signed-off-by: Bhaumik Bhatt <[email protected]>
---
drivers/bus/mhi/core/pm.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index 7960980..661d704 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -686,7 +686,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
return -EIO;

/* Return busy if there are any pending resources */
- if (atomic_read(&mhi_cntrl->dev_wake))
+ if (atomic_read(&mhi_cntrl->dev_wake) ||
+ atomic_read(&mhi_cntrl->pending_pkts))
return -EBUSY;

/* Take MHI out of M2 state */
@@ -712,7 +713,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)

write_lock_irq(&mhi_cntrl->pm_lock);

- if (atomic_read(&mhi_cntrl->dev_wake)) {
+ if (atomic_read(&mhi_cntrl->dev_wake) ||
+ atomic_read(&mhi_cntrl->pending_pkts)) {
write_unlock_irq(&mhi_cntrl->pm_lock);
return -EBUSY;
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-18 20:09:16

by Bhaumik Bhatt

[permalink] [raw]
Subject: [PATCH v3 6/7] bus: mhi: core: Read and save device hardware information from BHI

Device hardware specific information such as serial number and the OEM
PK hash can be read using BHI and saved on host to identify the
endpoint.

Signed-off-by: Bhaumik Bhatt <[email protected]>
Reviewed-by: Jeffrey Hugo <[email protected]>
---
drivers/bus/mhi/core/boot.c | 17 ++++++++++++++++-
include/linux/mhi.h | 6 ++++++
2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/core/boot.c
index 0b38014..24422f5 100644
--- a/drivers/bus/mhi/core/boot.c
+++ b/drivers/bus/mhi/core/boot.c
@@ -392,13 +392,28 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
void *buf;
dma_addr_t dma_addr;
size_t size;
- int ret;
+ int i, ret;

if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
dev_err(dev, "Device MHI is not in valid state\n");
return;
}

+ /* save hardware info from BHI */
+ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_SERIALNU,
+ &mhi_cntrl->serial_number);
+ if (ret)
+ dev_err(dev, "Could not capture serial number via BHI\n");
+
+ for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) {
+ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i),
+ &mhi_cntrl->oem_pk_hash[i]);
+ if (ret) {
+ dev_err(dev, "Could not capture OEM PK HASH via BHI\n");
+ break;
+ }
+ }
+
/* If device is in pass through, do reset to ready state transition */
if (mhi_cntrl->ee == MHI_EE_PTHRU)
goto fw_load_ee_pthru;
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 026a624..42e4d1e 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -19,6 +19,8 @@
#define MHI_VOTE_BUS BIT(0) /* do not disable the mhi bus */
#define MHI_VOTE_DEVICE BIT(1) /* prevent mhi device from entering lpm */

+#define MHI_MAX_OEM_PK_HASH_SEGMENTS 16
+
struct mhi_chan;
struct mhi_event;
struct mhi_ctxt;
@@ -318,6 +320,8 @@ struct mhi_controller_config {
* @device_number: MHI controller device number
* @major_version: MHI controller major revision number
* @minor_version: MHI controller minor revision number
+ * @serial_number: MHI controller serial number obtained from BHI
+ * @oem_pk_hash: MHI controller OEM PK Hash obtained from BHI
* @mhi_event: MHI event ring configurations table
* @mhi_cmd: MHI command ring configurations table
* @mhi_ctxt: MHI device context, shared memory between host and device
@@ -397,6 +401,8 @@ struct mhi_controller {
u32 device_number;
u32 major_version;
u32 minor_version;
+ u32 serial_number;
+ u32 oem_pk_hash[MHI_MAX_OEM_PK_HASH_SEGMENTS];

struct mhi_event *mhi_event;
struct mhi_cmd *mhi_cmd;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-05-20 16:51:07

by Jeffrey Hugo

[permalink] [raw]
Subject: Re: [PATCH v3 1/7] bus: mhi: core: Abort suspends due to outgoing pending packets

On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
> Add the missing check to abort suspends if a client has pending outgoing
> packets to send to the device. This allows better utilization of the MHI
> bus wherein clients on the host are not left waiting for longer suspend
> or resume cycles to finish for data transfers.
>
> Signed-off-by: Bhaumik Bhatt <[email protected]>
> ---

Reviewed-by: Jeffrey Hugo <[email protected]>

--
Jeffrey Hugo
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2020-05-20 16:56:41

by Jeffrey Hugo

[permalink] [raw]
Subject: Re: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
> Allow independent votes from clients such that they can choose to vote
> for either the device or the bus or both. This helps in cases where the
> device supports autonomous low power mode wherein it can move to M2
> state without the need to notify the host. Clients can also vote only to
> keep the underlying bus active without having the device in M0 state to
> support offload use cases.
>
> Signed-off-by: Bhaumik Bhatt <[email protected]>
> ---

I wonder, why doesn't this fit with runtimePM?
--
Jeffrey Hugo
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2020-05-20 18:47:15

by Bhaumik Bhatt

[permalink] [raw]
Subject: Re: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

On 2020-05-20 09:54, Jeffrey Hugo wrote:
> On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
>> Allow independent votes from clients such that they can choose to vote
>> for either the device or the bus or both. This helps in cases where
>> the
>> device supports autonomous low power mode wherein it can move to M2
>> state without the need to notify the host. Clients can also vote only
>> to
>> keep the underlying bus active without having the device in M0 state
>> to
>> support offload use cases.
>>
>> Signed-off-by: Bhaumik Bhatt <[email protected]>
>> ---
>
> I wonder, why doesn't this fit with runtimePM?
Hi Jeff,

Can you elaborate?

In short, with this patch, MHI just wants to give controller the option
to
choose the vote type so we can implement autonomous low power mode
entries
on both host and device.

Let us know if you need some more information.

Thanks,
Bhaumik

2020-05-20 19:11:41

by Jeffrey Hugo

[permalink] [raw]
Subject: Re: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

On 5/20/2020 12:43 PM, [email protected] wrote:
> On 2020-05-20 09:54, Jeffrey Hugo wrote:
>> On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
>>> Allow independent votes from clients such that they can choose to vote
>>> for either the device or the bus or both. This helps in cases where the
>>> device supports autonomous low power mode wherein it can move to M2
>>> state without the need to notify the host. Clients can also vote only to
>>> keep the underlying bus active without having the device in M0 state to
>>> support offload use cases.
>>>
>>> Signed-off-by: Bhaumik Bhatt <[email protected]>
>>> ---
>>
>> I wonder, why doesn't this fit with runtimePM?
> Hi Jeff,
>
> Can you elaborate?
>
> In short, with this patch, MHI just wants to give controller the option to
> choose the vote type so we can implement autonomous low power mode entries
> on both host and device.

So, you are attempting to manage the power mode of the device. The
standard mechanism to do so in Linux is runtime pm.

https://elixir.bootlin.com/linux/latest/source/Documentation/driver-api/pm/devices.rst

I'm no runtime pm expert, but it feels like your whole voting mechanism,
etc is just reimplemeting that. Reimplementing the wheel, when its been
a standard thing that the majority of the kernel uses is not usually
acceptable.

IMO, you need some sort of justification why runtime pm is not
applicable for you, because I'm willing to bet Mani/Greg are going to
ask the same.

--
Jeffrey Hugo
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2020-05-20 19:48:34

by Bhaumik Bhatt

[permalink] [raw]
Subject: Re: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

On 2020-05-20 12:06, Jeffrey Hugo wrote:
> On 5/20/2020 12:43 PM, [email protected] wrote:
>> On 2020-05-20 09:54, Jeffrey Hugo wrote:
>>> On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
>>>> Allow independent votes from clients such that they can choose to
>>>> vote
>>>> for either the device or the bus or both. This helps in cases where
>>>> the
>>>> device supports autonomous low power mode wherein it can move to M2
>>>> state without the need to notify the host. Clients can also vote
>>>> only to
>>>> keep the underlying bus active without having the device in M0 state
>>>> to
>>>> support offload use cases.
>>>>
>>>> Signed-off-by: Bhaumik Bhatt <[email protected]>
>>>> ---
>>>
>>> I wonder, why doesn't this fit with runtimePM?
>> Hi Jeff,
>>
>> Can you elaborate?
>>
>> In short, with this patch, MHI just wants to give controller the
>> option to
>> choose the vote type so we can implement autonomous low power mode
>> entries
>> on both host and device.
>
> So, you are attempting to manage the power mode of the device. The
> standard mechanism to do so in Linux is runtime pm.
>
> https://elixir.bootlin.com/linux/latest/source/Documentation/driver-api/pm/devices.rst
>
> I'm no runtime pm expert, but it feels like your whole voting
> mechanism, etc is just reimplemeting that. Reimplementing the wheel,
> when its been a standard thing that the majority of the kernel uses is
> not usually acceptable.
>
> IMO, you need some sort of justification why runtime pm is not
> applicable for you, because I'm willing to bet Mani/Greg are going to
> ask the same.
I think we can look at the patch as simply expanding the scope of what
already exists.

The client here has been calling mhi_device_get/put/sync APIs to gain
device vote and with
new features yet to come in, this introductory change is only
re-purposing what voting
means going forward. i.e. allowing individual bus and device votes.

If you're suggesting using runtimePM APIs to replace the newly
introduced bus vote, it
would be kind of overkill here IMO. Is that what you were getting at?
Because currently,
we just have controllers use runtimePM and provide callbacks to them.

If you have ideas, we can discuss them.

2020-05-20 20:43:24

by Jeffrey Hugo

[permalink] [raw]
Subject: Re: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism

On 5/20/2020 1:44 PM, [email protected] wrote:
> On 2020-05-20 12:06, Jeffrey Hugo wrote:
>> On 5/20/2020 12:43 PM, [email protected] wrote:
>>> On 2020-05-20 09:54, Jeffrey Hugo wrote:
>>>> On 5/18/2020 2:03 PM, Bhaumik Bhatt wrote:
>>>>> Allow independent votes from clients such that they can choose to vote
>>>>> for either the device or the bus or both. This helps in cases where
>>>>> the
>>>>> device supports autonomous low power mode wherein it can move to M2
>>>>> state without the need to notify the host. Clients can also vote
>>>>> only to
>>>>> keep the underlying bus active without having the device in M0
>>>>> state to
>>>>> support offload use cases.
>>>>>
>>>>> Signed-off-by: Bhaumik Bhatt <[email protected]>
>>>>> ---
>>>>
>>>> I wonder, why doesn't this fit with runtimePM?
>>> Hi Jeff,
>>>
>>> Can you elaborate?
>>>
>>> In short, with this patch, MHI just wants to give controller the
>>> option to
>>> choose the vote type so we can implement autonomous low power mode
>>> entries
>>> on both host and device.
>>
>> So, you are attempting to manage the power mode of the device.  The
>> standard mechanism to do so in Linux is runtime pm.
>>
>> https://elixir.bootlin.com/linux/latest/source/Documentation/driver-api/pm/devices.rst
>>
>>
>> I'm no runtime pm expert, but it feels like your whole voting
>> mechanism, etc is just reimplemeting that.  Reimplementing the wheel,
>> when its been a standard thing that the majority of the kernel uses is
>> not usually acceptable.
>>
>> IMO, you need some sort of justification why runtime pm is not
>> applicable for you, because I'm willing to bet Mani/Greg are going to
>> ask the same.
> I think we can look at the patch as simply expanding the scope of what
> already exists.
>
> The client here has been calling mhi_device_get/put/sync APIs to gain
> device vote and with
> new features yet to come in, this introductory change is only
> re-purposing what voting
> means going forward. i.e. allowing individual bus and device votes.
>
> If you're suggesting using runtimePM APIs to replace the newly
> introduced bus vote, it
> would be kind of overkill here IMO. Is that what you were getting at?
> Because currently,
> we just have controllers use runtimePM and provide callbacks to them.
>
> If you have ideas, we can discuss them.

Ultimately, yes I think I am suggesting replacing this API with the
runtime pm API.

As near as I can tell, if I'm a device driver on some other bus, and I
want to keep my device alive because I'm doing a DMA to it or something,
I would call pm_runtime_get(), and when I have confirmation my activity
is done, I would use pm_runtime_put().

As near as I can tell, this is already plumbed into the bus framework,
such that the MHI bus would get a callback when the device driver does
that. In the MHI bus callback, you would be able to route the request
as needed.

So, with this API (that has no consumers currently), I call
pm_runtime_get() and also mhi_device_get()?

--
Jeffrey Hugo
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2020-05-21 13:25:39

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 0/7] Introduce features and debugfs/sysfs entries for MHI

Hi,

On Mon, May 18, 2020 at 01:03:54PM -0700, Bhaumik Bhatt wrote:
> Introduce independent bus and device voting mechanism for clients and save
> hardware information from BHI.
> Allow reading and modifying some MHI variables for debug, test, and
> informational purposes using debugfs.
> Read values for device specific hardware information to be used by OEMs in
> factory testing such as serial number and PK hash using sysfs.
>

I think this series is not yet ready. So will not merge any patches in this
series for 5.8.

Or let me know if there are any independent patches which should get merged.
I'm planning to send the final 5.8 series to Greg by Friday.

Thanks,
Mani

> This set of patches was tested on arm64 and x86.
>
> v3:
> -Add patch to check for pending packets in suspend as a dependency for the
> independent voting mechanism introduction
> -Include register dump entry for debugfs to dump MHI, BHI, and BHIe registers
> -Update commit message for the debugfs patch
> -Updated Documentation/ABI with the required info for sysfs
> -Updated debugfs patch to include a new KConfig entry and dependencies
> -Updated reviewed-by for some patches
>
> v2:
> -Added a new debugfs.c file for specific debugfs entries and code
> -Updated commit text and addressed some comments for voting change
> -Made sure sysfs is only used for serial number and OEM PK hash usage
>
> Bhaumik Bhatt (7):
> bus: mhi: core: Abort suspends due to outgoing pending packets
> bus: mhi: core: Introduce independent voting mechanism
> bus: mhi: core: Use generic name field for an MHI device
> bus: mhi: core: Introduce helper function to check device state
> bus: mhi: core: Introduce debugfs entries and counters for MHI
> bus: mhi: core: Read and save device hardware information from BHI
> bus: mhi: core: Introduce sysfs entries for MHI
>
> Documentation/ABI/stable/sysfs-bus-mhi | 25 ++
> MAINTAINERS | 1 +
> drivers/bus/mhi/Kconfig | 8 +
> drivers/bus/mhi/core/Makefile | 5 +-
> drivers/bus/mhi/core/boot.c | 17 +-
> drivers/bus/mhi/core/debugfs.c | 501 +++++++++++++++++++++++++++++++++
> drivers/bus/mhi/core/init.c | 80 +++++-
> drivers/bus/mhi/core/internal.h | 29 ++
> drivers/bus/mhi/core/main.c | 6 +-
> drivers/bus/mhi/core/pm.c | 79 ++++--
> include/linux/mhi.h | 39 ++-
> 11 files changed, 745 insertions(+), 45 deletions(-)
> create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi
> create mode 100644 drivers/bus/mhi/core/debugfs.c
>
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project

2020-05-21 15:34:09

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 0/7] Introduce features and debugfs/sysfs entries for MHI

On Thu, May 21, 2020 at 06:53:18PM +0530, Manivannan Sadhasivam wrote:
> Hi,
>
> On Mon, May 18, 2020 at 01:03:54PM -0700, Bhaumik Bhatt wrote:
> > Introduce independent bus and device voting mechanism for clients and save
> > hardware information from BHI.
> > Allow reading and modifying some MHI variables for debug, test, and
> > informational purposes using debugfs.
> > Read values for device specific hardware information to be used by OEMs in
> > factory testing such as serial number and PK hash using sysfs.
> >
>
> I think this series is not yet ready. So will not merge any patches in this
> series for 5.8.
>
> Or let me know if there are any independent patches which should get merged.
> I'm planning to send the final 5.8 series to Greg by Friday.
>

Sorry. I just realised that we are running out of time as we are ending rc6. So
I've sent the 5.8 series to Greg.

Thanks,
Mani

> Thanks,
> Mani
>
> > This set of patches was tested on arm64 and x86.
> >
> > v3:
> > -Add patch to check for pending packets in suspend as a dependency for the
> > independent voting mechanism introduction
> > -Include register dump entry for debugfs to dump MHI, BHI, and BHIe registers
> > -Update commit message for the debugfs patch
> > -Updated Documentation/ABI with the required info for sysfs
> > -Updated debugfs patch to include a new KConfig entry and dependencies
> > -Updated reviewed-by for some patches
> >
> > v2:
> > -Added a new debugfs.c file for specific debugfs entries and code
> > -Updated commit text and addressed some comments for voting change
> > -Made sure sysfs is only used for serial number and OEM PK hash usage
> >
> > Bhaumik Bhatt (7):
> > bus: mhi: core: Abort suspends due to outgoing pending packets
> > bus: mhi: core: Introduce independent voting mechanism
> > bus: mhi: core: Use generic name field for an MHI device
> > bus: mhi: core: Introduce helper function to check device state
> > bus: mhi: core: Introduce debugfs entries and counters for MHI
> > bus: mhi: core: Read and save device hardware information from BHI
> > bus: mhi: core: Introduce sysfs entries for MHI
> >
> > Documentation/ABI/stable/sysfs-bus-mhi | 25 ++
> > MAINTAINERS | 1 +
> > drivers/bus/mhi/Kconfig | 8 +
> > drivers/bus/mhi/core/Makefile | 5 +-
> > drivers/bus/mhi/core/boot.c | 17 +-
> > drivers/bus/mhi/core/debugfs.c | 501 +++++++++++++++++++++++++++++++++
> > drivers/bus/mhi/core/init.c | 80 +++++-
> > drivers/bus/mhi/core/internal.h | 29 ++
> > drivers/bus/mhi/core/main.c | 6 +-
> > drivers/bus/mhi/core/pm.c | 79 ++++--
> > include/linux/mhi.h | 39 ++-
> > 11 files changed, 745 insertions(+), 45 deletions(-)
> > create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi
> > create mode 100644 drivers/bus/mhi/core/debugfs.c
> >
> > --
> > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> > a Linux Foundation Collaborative Project

2020-05-21 19:35:53

by Bhaumik Bhatt

[permalink] [raw]
Subject: Re: [PATCH v3 0/7] Introduce features and debugfs/sysfs entries for MHI

On 2020-05-21 06:23, Manivannan Sadhasivam wrote:
> Hi,
>
> On Mon, May 18, 2020 at 01:03:54PM -0700, Bhaumik Bhatt wrote:
>> Introduce independent bus and device voting mechanism for clients and
>> save
>> hardware information from BHI.
>> Allow reading and modifying some MHI variables for debug, test, and
>> informational purposes using debugfs.
>> Read values for device specific hardware information to be used by
>> OEMs in
>> factory testing such as serial number and PK hash using sysfs.
>>
>
> I think this series is not yet ready. So will not merge any patches in
> this
> series for 5.8.
>
> Or let me know if there are any independent patches which should get
> merged.
> I'm planning to send the final 5.8 series to Greg by Friday.
>
> Thanks,
> Mani
>
>> This set of patches was tested on arm64 and x86.
>>
>> v3:
>> -Add patch to check for pending packets in suspend as a dependency for
>> the
>> independent voting mechanism introduction
>> -Include register dump entry for debugfs to dump MHI, BHI, and BHIe
>> registers
>> -Update commit message for the debugfs patch
>> -Updated Documentation/ABI with the required info for sysfs
>> -Updated debugfs patch to include a new KConfig entry and dependencies
>> -Updated reviewed-by for some patches
>>
>> v2:
>> -Added a new debugfs.c file for specific debugfs entries and code
>> -Updated commit text and addressed some comments for voting change
>> -Made sure sysfs is only used for serial number and OEM PK hash usage
>>
>> Bhaumik Bhatt (7):
>> bus: mhi: core: Abort suspends due to outgoing pending packets
>> bus: mhi: core: Introduce independent voting mechanism
>> bus: mhi: core: Use generic name field for an MHI device
>> bus: mhi: core: Introduce helper function to check device state
>> bus: mhi: core: Introduce debugfs entries and counters for MHI
>> bus: mhi: core: Read and save device hardware information from BHI
>> bus: mhi: core: Introduce sysfs entries for MHI
>>
>> Documentation/ABI/stable/sysfs-bus-mhi | 25 ++
>> MAINTAINERS | 1 +
>> drivers/bus/mhi/Kconfig | 8 +
>> drivers/bus/mhi/core/Makefile | 5 +-
>> drivers/bus/mhi/core/boot.c | 17 +-
>> drivers/bus/mhi/core/debugfs.c | 501
>> +++++++++++++++++++++++++++++++++
>> drivers/bus/mhi/core/init.c | 80 +++++-
>> drivers/bus/mhi/core/internal.h | 29 ++
>> drivers/bus/mhi/core/main.c | 6 +-
>> drivers/bus/mhi/core/pm.c | 79 ++++--
>> include/linux/mhi.h | 39 ++-
>> 11 files changed, 745 insertions(+), 45 deletions(-)
>> create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi
>> create mode 100644 drivers/bus/mhi/core/debugfs.c
>>
>> --
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
>> Forum,
>> a Linux Foundation Collaborative Project
Hi Mani,

These are patches already reviewed, small and important and good to go:

bus: mhi: core: Abort suspends due to outgoing pending packets
bus: mhi: core: Use generic name field for an MHI device
bus: mhi: core: Introduce helper function to check device state
bus: mhi: core: Read and save device hardware information from BHI

Please let us know if you have any concerns.

Thanks,
Bhaumik

2020-05-25 06:40:08

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] bus: mhi: core: Introduce debugfs entries and counters for MHI

On Mon, May 18, 2020 at 01:03:59PM -0700, Bhaumik Bhatt wrote:
> +void mhi_create_debugfs(struct mhi_controller *mhi_cntrl)
> +{
> + if (IS_ERR_OR_NULL(mhi_debugfs_root))
> + return;

Why? Should not matter.

> + mhi_cntrl->debugfs_dentry =
> + debugfs_create_dir(dev_name(mhi_cntrl->cntrl_dev),
> + mhi_debugfs_root);
> + if (IS_ERR_OR_NULL(mhi_cntrl->debugfs_dentry))
> + return;

No need for this check either, just call debugfs and keep on moving :)

thanks,

greg k-h