2021-06-09 14:38:49

by Sibi Sankar

[permalink] [raw]
Subject: [PATCH v4 0/2] soc: qcom: aoss: Expose send for generic usecase

The patch series exposes functions to enable drivers to send their own
messages to AOSS (Always on Subsystem). It also adds a debugfs node for
qmp so messages can be sent to aoss for debugging and testing purposes.

V4:
* Fix compilation error due to missing qmp_put
* Minor typos [s/tarcks/tracks]

V3:
* Remove devm memory allocation
* Use refcount for qmp handle
* Update qmp_get/qmp_put/qmp_remove function with refcount logic

Deepak Kumar Singh (2):
soc: qcom: aoss: Expose send for generic usecase
soc: qcom: aoss: Add debugfs entry

drivers/soc/qcom/qcom_aoss.c | 109 ++++++++++++++++++++++++++++++++++++-
include/linux/soc/qcom/qcom_aoss.h | 36 ++++++++++++
2 files changed, 143 insertions(+), 2 deletions(-)
create mode 100644 include/linux/soc/qcom/qcom_aoss.h

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


2021-06-09 14:39:42

by Sibi Sankar

[permalink] [raw]
Subject: [PATCH v4 2/2] soc: qcom: aoss: Add debugfs entry

From: Deepak Kumar Singh <[email protected]>

It can be useful to control the different power states of various
parts of hardware for device testing. Add a debugfs node for qmp so
messages can be sent to aoss for debugging and testing purposes.

Signed-off-by: Chris Lew <[email protected]>
Signed-off-by: Deepak Kumar Singh <[email protected]>
Signed-off-by: Sibi Sankar <[email protected]>
---
drivers/soc/qcom/qcom_aoss.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index e8f48760bac8..998ee7605eb2 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/power/qcom-aoss-qmp.h>
#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mailbox_client.h>
@@ -89,6 +90,9 @@ struct qmp {
struct clk_hw qdss_clk;
struct genpd_onecell_data pd_data;
struct qmp_cooling_device *cooling_devs;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ struct dentry *debugfs_file;
+#endif /* CONFIG_DEBUG_FS */
};

struct qmp_pd {
@@ -575,6 +579,32 @@ void qmp_put(struct qmp *qmp)
}
EXPORT_SYMBOL(qmp_put);

+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static ssize_t aoss_dbg_write(struct file *file, const char __user *userstr,
+ size_t len, loff_t *pos)
+{
+ struct qmp *qmp = file->private_data;
+ char buf[QMP_MSG_LEN] = {};
+ int ret;
+
+ if (!len || len >= QMP_MSG_LEN)
+ return len;
+
+ ret = copy_from_user(buf, userstr, len);
+ if (ret)
+ return len;
+
+ ret = qmp_send(qmp, buf, QMP_MSG_LEN);
+
+ return ret ? ret : len;
+}
+
+static const struct file_operations aoss_dbg_fops = {
+ .open = simple_open,
+ .write = aoss_dbg_write,
+};
+#endif /* CONFIG_DEBUG_FS */
+
static int qmp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -632,6 +662,11 @@ static int qmp_probe(struct platform_device *pdev)

atomic_set(&qmp->orphan, 0);

+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ qmp->debugfs_file = debugfs_create_file("aoss_send_message", 0220, NULL,
+ qmp, &aoss_dbg_fops);
+#endif /* CONFIG_DEBUG_FS */
+
return 0;

err_remove_qdss_clk:
@@ -649,6 +684,10 @@ static int qmp_remove(struct platform_device *pdev)
{
struct qmp *qmp = platform_get_drvdata(pdev);

+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ debugfs_remove(qmp->debugfs_file);
+#endif /* CONFIG_DEBUG_FS */
+
qmp_qdss_clk_remove(qmp);
qmp_pd_remove(qmp);
qmp_cooling_devices_remove(qmp);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2021-06-09 17:18:48

by Sibi Sankar

[permalink] [raw]
Subject: [PATCH v4 1/2] soc: qcom: aoss: Expose send for generic usecase

From: Deepak Kumar Singh <[email protected]>

Not all upcoming usecases will have an interface to allow the aoss
driver to hook onto. Expose the send api and create a get function to
enable drivers to send their own messages to aoss.

Signed-off-by: Chris Lew <[email protected]>
Signed-off-by: Deepak Kumar Singh <[email protected]>
Reviewed-by: Bjorn Andersson <[email protected]>
Signed-off-by: Sibi Sankar <[email protected]>
---

v4:
* Fix compilation error due to missing qmp_put
* Minor typos [s/tarcks/tracks]

drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++--
include/linux/soc/qcom/qcom_aoss.h | 36 ++++++++++++++++++++
2 files changed, 104 insertions(+), 2 deletions(-)
create mode 100644 include/linux/soc/qcom/qcom_aoss.h

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 934fcc4d2b05..e8f48760bac8 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -8,10 +8,12 @@
#include <linux/io.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/thermal.h>
#include <linux/slab.h>
+#include <linux/soc/qcom/qcom_aoss.h>

#define QMP_DESC_MAGIC 0x0
#define QMP_DESC_VERSION 0x4
@@ -61,6 +63,7 @@ struct qmp_cooling_device {
* @mbox_chan: mailbox channel used to ring the doorbell on transmit
* @offset: offset within @msgram where messages should be written
* @size: maximum size of the messages to be transmitted
+ * @orphan: tracks whether qmp handle is valid
* @event: wait_queue for synchronization with the IRQ
* @tx_lock: provides synchronization between multiple callers of qmp_send()
* @qdss_clk: QDSS clock hw struct
@@ -76,6 +79,8 @@ struct qmp {

size_t offset;
size_t size;
+ atomic_t orphan;
+ struct kref refcount;

wait_queue_head_t event;

@@ -223,11 +228,17 @@ static bool qmp_message_empty(struct qmp *qmp)
*
* Return: 0 on success, negative errno on failure
*/
-static int qmp_send(struct qmp *qmp, const void *data, size_t len)
+int qmp_send(struct qmp *qmp, const void *data, size_t len)
{
long time_left;
int ret;

+ if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data))
+ return -EINVAL;
+
+ if (atomic_read(&qmp->orphan))
+ return -EINVAL;
+
if (WARN_ON(len + sizeof(u32) > qmp->size))
return -EINVAL;

@@ -261,6 +272,7 @@ static int qmp_send(struct qmp *qmp, const void *data, size_t len)

return ret;
}
+EXPORT_SYMBOL(qmp_send);

static int qmp_qdss_clk_prepare(struct clk_hw *hw)
{
@@ -515,6 +527,54 @@ static void qmp_cooling_devices_remove(struct qmp *qmp)
thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
}

+/**
+ * qmp_get() - get a qmp handle from a device
+ * @dev: client device pointer
+ *
+ * Return: handle to qmp device on success, ERR_PTR() on failure
+ */
+struct qmp *qmp_get(struct device *dev)
+{
+ struct platform_device *pdev;
+ struct device_node *np;
+ struct qmp *qmp;
+
+ if (!dev || !dev->of_node)
+ return ERR_PTR(-EINVAL);
+
+ np = of_parse_phandle(dev->of_node, "qcom,qmp", 0);
+ if (!np)
+ return ERR_PTR(-ENODEV);
+
+ pdev = of_find_device_by_node(np);
+ of_node_put(np);
+ if (!pdev)
+ return ERR_PTR(-EINVAL);
+
+ qmp = platform_get_drvdata(pdev);
+ platform_device_put(pdev);
+
+ if (qmp)
+ kref_get(&qmp->refcount);
+
+ return qmp ? qmp : ERR_PTR(-EPROBE_DEFER);
+}
+EXPORT_SYMBOL(qmp_get);
+
+static void qmp_handle_release(struct kref *ref)
+{
+ struct qmp *qmp = container_of(ref, struct qmp, refcount);
+
+ kfree(qmp);
+}
+
+void qmp_put(struct qmp *qmp)
+{
+ if (!IS_ERR_OR_NULL(qmp))
+ kref_put(&qmp->refcount, qmp_handle_release);
+}
+EXPORT_SYMBOL(qmp_put);
+
static int qmp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)
int irq;
int ret;

- qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL);
+ qmp = kzalloc(sizeof(*qmp), GFP_KERNEL);
if (!qmp)
return -ENOMEM;

qmp->dev = &pdev->dev;
init_waitqueue_head(&qmp->event);
mutex_init(&qmp->tx_lock);
+ kref_init(&qmp->refcount);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
qmp->msgram = devm_ioremap_resource(&pdev->dev, res);
@@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, qmp);

+ atomic_set(&qmp->orphan, 0);
+
return 0;

err_remove_qdss_clk:
@@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)
qmp_close(qmp);
err_free_mbox:
mbox_free_channel(qmp->mbox_chan);
+ kfree(qmp);

return ret;
}
@@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)
qmp_cooling_devices_remove(qmp);

qmp_close(qmp);
+ atomic_set(&qmp->orphan, 1);
mbox_free_channel(qmp->mbox_chan);
+ kref_put(&qmp->refcount, qmp_handle_release);

return 0;
}
diff --git a/include/linux/soc/qcom/qcom_aoss.h b/include/linux/soc/qcom/qcom_aoss.h
new file mode 100644
index 000000000000..725c9d12fd11
--- /dev/null
+++ b/include/linux/soc/qcom/qcom_aoss.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __QCOM_AOSS_H__
+#define __QCOM_AOSS_H__
+
+#include <linux/err.h>
+#include <linux/device.h>
+
+struct qmp;
+
+#if IS_ENABLED(CONFIG_QCOM_AOSS_QMP)
+
+int qmp_send(struct qmp *qmp, const void *data, size_t len);
+struct qmp *qmp_get(struct device *dev);
+void qmp_put(struct qmp *qmp);
+
+#else
+
+static inline int qmp_send(struct qmp *qmp, const void *data, size_t len)
+{
+ return -ENODEV;
+}
+
+static inline struct qmp *qmp_get(struct device *dev)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void qmp_put(struct qmp *qmp) { }
+
+#endif
+
+#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2021-07-21 06:38:31

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v4 1/2] soc: qcom: aoss: Expose send for generic usecase

Quoting Sibi Sankar (2021-06-09 04:18:51)
> From: Deepak Kumar Singh <[email protected]>
>
> Not all upcoming usecases will have an interface to allow the aoss
> driver to hook onto. Expose the send api and create a get function to
> enable drivers to send their own messages to aoss.
>
> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Reviewed-by: Bjorn Andersson <[email protected]>
> Signed-off-by: Sibi Sankar <[email protected]>
> ---
>
> v4:
> * Fix compilation error due to missing qmp_put
> * Minor typos [s/tarcks/tracks]
>
> drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++--
> include/linux/soc/qcom/qcom_aoss.h | 36 ++++++++++++++++++++
> 2 files changed, 104 insertions(+), 2 deletions(-)
> create mode 100644 include/linux/soc/qcom/qcom_aoss.h
>
> diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
> index 934fcc4d2b05..e8f48760bac8 100644
> --- a/drivers/soc/qcom/qcom_aoss.c
> +++ b/drivers/soc/qcom/qcom_aoss.c
> @@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)
> int irq;
> int ret;
>
> - qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL);
> + qmp = kzalloc(sizeof(*qmp), GFP_KERNEL);
> if (!qmp)
> return -ENOMEM;
>
> qmp->dev = &pdev->dev;
> init_waitqueue_head(&qmp->event);
> mutex_init(&qmp->tx_lock);
> + kref_init(&qmp->refcount);
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> qmp->msgram = devm_ioremap_resource(&pdev->dev, res);
> @@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, qmp);
>
> + atomic_set(&qmp->orphan, 0);
> +
> return 0;
>
> err_remove_qdss_clk:
> @@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)
> qmp_close(qmp);
> err_free_mbox:
> mbox_free_channel(qmp->mbox_chan);
> + kfree(qmp);
>
> return ret;
> }
> @@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)
> qmp_cooling_devices_remove(qmp);
>
> qmp_close(qmp);
> + atomic_set(&qmp->orphan, 1);

This looks odd. Why are we letting the device be removed while it is in
use by other drivers? Can't we pin the device with get_device() so it
can't be removed and then prevent the driver from being removed until
all the consumer drivers drop the reference, i.e. suppress sysfs unbind?

Otherwise it looks like a generic problem that all provider devices,
clks, regulators, gpios, etc. have to deal with and thus this
hand-rolled mechanism can't be right.

> mbox_free_channel(qmp->mbox_chan);
> + kref_put(&qmp->refcount, qmp_handle_release);
>
> return 0;
> }

2021-07-23 09:53:18

by Deepak Kumar Singh

[permalink] [raw]
Subject: Re: [PATCH v4 1/2] soc: qcom: aoss: Expose send for generic usecase


On 7/21/2021 12:07 PM, Stephen Boyd wrote:
> Quoting Sibi Sankar (2021-06-09 04:18:51)
>> From: Deepak Kumar Singh <[email protected]>
>>
>> Not all upcoming usecases will have an interface to allow the aoss
>> driver to hook onto. Expose the send api and create a get function to
>> enable drivers to send their own messages to aoss.
>>
>> Signed-off-by: Chris Lew <[email protected]>
>> Signed-off-by: Deepak Kumar Singh <[email protected]>
>> Reviewed-by: Bjorn Andersson <[email protected]>
>> Signed-off-by: Sibi Sankar <[email protected]>
>> ---
>>
>> v4:
>> * Fix compilation error due to missing qmp_put
>> * Minor typos [s/tarcks/tracks]
>>
>> drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++--
>> include/linux/soc/qcom/qcom_aoss.h | 36 ++++++++++++++++++++
>> 2 files changed, 104 insertions(+), 2 deletions(-)
>> create mode 100644 include/linux/soc/qcom/qcom_aoss.h
>>
>> diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
>> index 934fcc4d2b05..e8f48760bac8 100644
>> --- a/drivers/soc/qcom/qcom_aoss.c
>> +++ b/drivers/soc/qcom/qcom_aoss.c
>> @@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)
>> int irq;
>> int ret;
>>
>> - qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL);
>> + qmp = kzalloc(sizeof(*qmp), GFP_KERNEL);
>> if (!qmp)
>> return -ENOMEM;
>>
>> qmp->dev = &pdev->dev;
>> init_waitqueue_head(&qmp->event);
>> mutex_init(&qmp->tx_lock);
>> + kref_init(&qmp->refcount);
>>
>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> qmp->msgram = devm_ioremap_resource(&pdev->dev, res);
>> @@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)
>>
>> platform_set_drvdata(pdev, qmp);
>>
>> + atomic_set(&qmp->orphan, 0);
>> +
>> return 0;
>>
>> err_remove_qdss_clk:
>> @@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)
>> qmp_close(qmp);
>> err_free_mbox:
>> mbox_free_channel(qmp->mbox_chan);
>> + kfree(qmp);
>>
>> return ret;
>> }
>> @@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)
>> qmp_cooling_devices_remove(qmp);
>>
>> qmp_close(qmp);
>> + atomic_set(&qmp->orphan, 1);
> This looks odd. Why are we letting the device be removed while it is in
> use by other drivers? Can't we pin the device with get_device() so it
> can't be removed and then prevent the driver from being removed until
> all the consumer drivers drop the reference, i.e. suppress sysfs unbind?
>
> Otherwise it looks like a generic problem that all provider devices,
> clks, regulators, gpios, etc. have to deal with and thus this
> hand-rolled mechanism can't be right.

As per my earlier discussion with Bjorn, device could be unbound using
sysfs, in which case

remove() is called irrespective of whether any client driver is holding
struct device reference

or not. That's why i have added separate refcount for qmp handle and
marking it invalid if

qmp_remove() is called.

>> mbox_free_channel(qmp->mbox_chan);
>> + kref_put(&qmp->refcount, qmp_handle_release);
>>
>> return 0;
>> }

2021-07-23 19:31:05

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v4 1/2] soc: qcom: aoss: Expose send for generic usecase

Quoting Deepak Kumar Singh (2021-07-23 02:51:50)
>
> On 7/21/2021 12:07 PM, Stephen Boyd wrote:
> > Quoting Sibi Sankar (2021-06-09 04:18:51)
> >> From: Deepak Kumar Singh <[email protected]>
> >>
> >> Not all upcoming usecases will have an interface to allow the aoss
> >> driver to hook onto. Expose the send api and create a get function to
> >> enable drivers to send their own messages to aoss.
> >>
> >> Signed-off-by: Chris Lew <[email protected]>
> >> Signed-off-by: Deepak Kumar Singh <[email protected]>
> >> Reviewed-by: Bjorn Andersson <[email protected]>
> >> Signed-off-by: Sibi Sankar <[email protected]>
> >> ---
> >>
> >> v4:
> >> * Fix compilation error due to missing qmp_put
> >> * Minor typos [s/tarcks/tracks]
> >>
> >> drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++--
> >> include/linux/soc/qcom/qcom_aoss.h | 36 ++++++++++++++++++++
> >> 2 files changed, 104 insertions(+), 2 deletions(-)
> >> create mode 100644 include/linux/soc/qcom/qcom_aoss.h
> >>
> >> diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
> >> index 934fcc4d2b05..e8f48760bac8 100644
> >> --- a/drivers/soc/qcom/qcom_aoss.c
> >> +++ b/drivers/soc/qcom/qcom_aoss.c
> >> @@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)
> >> int irq;
> >> int ret;
> >>
> >> - qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL);
> >> + qmp = kzalloc(sizeof(*qmp), GFP_KERNEL);
> >> if (!qmp)
> >> return -ENOMEM;
> >>
> >> qmp->dev = &pdev->dev;
> >> init_waitqueue_head(&qmp->event);
> >> mutex_init(&qmp->tx_lock);
> >> + kref_init(&qmp->refcount);
> >>
> >> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> qmp->msgram = devm_ioremap_resource(&pdev->dev, res);
> >> @@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)
> >>
> >> platform_set_drvdata(pdev, qmp);
> >>
> >> + atomic_set(&qmp->orphan, 0);
> >> +
> >> return 0;
> >>
> >> err_remove_qdss_clk:
> >> @@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)
> >> qmp_close(qmp);
> >> err_free_mbox:
> >> mbox_free_channel(qmp->mbox_chan);
> >> + kfree(qmp);
> >>
> >> return ret;
> >> }
> >> @@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)
> >> qmp_cooling_devices_remove(qmp);
> >>
> >> qmp_close(qmp);
> >> + atomic_set(&qmp->orphan, 1);
> > This looks odd. Why are we letting the device be removed while it is in
> > use by other drivers? Can't we pin the device with get_device() so it
> > can't be removed and then prevent the driver from being removed until
> > all the consumer drivers drop the reference, i.e. suppress sysfs unbind?
> >
> > Otherwise it looks like a generic problem that all provider devices,
> > clks, regulators, gpios, etc. have to deal with and thus this
> > hand-rolled mechanism can't be right.
>
> As per my earlier discussion with Bjorn, device could be unbound using
> sysfs, in which case
>
> remove() is called irrespective of whether any client driver is holding
> struct device reference
>
> or not. That's why i have added separate refcount for qmp handle and
> marking it invalid if
>
> qmp_remove() is called.
>

We have struct device_driver::suppress_bind_attrs for that. Can you set
it?

2021-08-04 21:11:18

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] soc: qcom: aoss: Add debugfs entry

On Wed 09 Jun 06:18 CDT 2021, Sibi Sankar wrote:

> From: Deepak Kumar Singh <[email protected]>
>
> It can be useful to control the different power states of various
> parts of hardware for device testing. Add a debugfs node for qmp so
> messages can be sent to aoss for debugging and testing purposes.
>

I thought I replied to this patch, but can't find the reply...

> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Signed-off-by: Sibi Sankar <[email protected]>
> ---
> drivers/soc/qcom/qcom_aoss.c | 39 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 39 insertions(+)
>
> diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
> index e8f48760bac8..998ee7605eb2 100644
> --- a/drivers/soc/qcom/qcom_aoss.c
> +++ b/drivers/soc/qcom/qcom_aoss.c
> @@ -4,6 +4,7 @@
> */
> #include <dt-bindings/power/qcom-aoss-qmp.h>
> #include <linux/clk-provider.h>
> +#include <linux/debugfs.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> #include <linux/mailbox_client.h>
> @@ -89,6 +90,9 @@ struct qmp {
> struct clk_hw qdss_clk;
> struct genpd_onecell_data pd_data;
> struct qmp_cooling_device *cooling_devs;
> +#if IS_ENABLED(CONFIG_DEBUG_FS)
> + struct dentry *debugfs_file;
> +#endif /* CONFIG_DEBUG_FS */
> };
>
> struct qmp_pd {
> @@ -575,6 +579,32 @@ void qmp_put(struct qmp *qmp)
> }
> EXPORT_SYMBOL(qmp_put);
>
> +#if IS_ENABLED(CONFIG_DEBUG_FS)
> +static ssize_t aoss_dbg_write(struct file *file, const char __user *userstr,
> + size_t len, loff_t *pos)
> +{
> + struct qmp *qmp = file->private_data;
> + char buf[QMP_MSG_LEN] = {};
> + int ret;
> +
> + if (!len || len >= QMP_MSG_LEN)
> + return len;
> +
> + ret = copy_from_user(buf, userstr, len);
> + if (ret)
> + return len;
> +
> + ret = qmp_send(qmp, buf, QMP_MSG_LEN);
> +
> + return ret ? ret : len;
> +}
> +
> +static const struct file_operations aoss_dbg_fops = {
> + .open = simple_open,
> + .write = aoss_dbg_write,
> +};
> +#endif /* CONFIG_DEBUG_FS */
> +
> static int qmp_probe(struct platform_device *pdev)
> {
> struct resource *res;
> @@ -632,6 +662,11 @@ static int qmp_probe(struct platform_device *pdev)
>
> atomic_set(&qmp->orphan, 0);
>
> +#if IS_ENABLED(CONFIG_DEBUG_FS)
> + qmp->debugfs_file = debugfs_create_file("aoss_send_message", 0220, NULL,
> + qmp, &aoss_dbg_fops);
> +#endif /* CONFIG_DEBUG_FS */

You shouldn't need the guards, debugfs_create_file() is stubbed if
CONFIG_DEBUG_FS isn't set, so it's better to just rely on that.

Regards,
Bjorn

> +
> return 0;
>
> err_remove_qdss_clk:
> @@ -649,6 +684,10 @@ static int qmp_remove(struct platform_device *pdev)
> {
> struct qmp *qmp = platform_get_drvdata(pdev);
>
> +#if IS_ENABLED(CONFIG_DEBUG_FS)
> + debugfs_remove(qmp->debugfs_file);
> +#endif /* CONFIG_DEBUG_FS */
> +
> qmp_qdss_clk_remove(qmp);
> qmp_pd_remove(qmp);
> qmp_cooling_devices_remove(qmp);
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>