[RFC PATCH v2 08/13] firmware: arm_scmi: Enable notification core

From: Cristian Marussi
Date: Fri Feb 14 2020 - 10:37:02 EST


Initialize and enable SCMI Notifications core support during bus/driver
init and probe phases, so that protocols can start registering their
supported events during their initialization, and later users can start
enrolling their callbacks for the subset of events their interested in.

Signed-off-by: Cristian Marussi <cristian.marussi@xxxxxxx>
---
V1 --> V2
- added timestamping
- moved notification init/exit and using devres
---
drivers/firmware/arm_scmi/bus.c | 11 +++++++++++
drivers/firmware/arm_scmi/driver.c | 10 ++++++++++
2 files changed, 21 insertions(+)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index db55c43a2cbd..0761f306982f 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -14,6 +14,7 @@
#include <linux/device.h>

#include "common.h"
+#include "notify.h"

static DEFINE_IDA(scmi_bus_id);
static DEFINE_IDR(scmi_protocols);
@@ -90,11 +91,21 @@ static int scmi_dev_probe(struct device *dev)
return scmi_drv->probe(scmi_dev);
}

+static inline void scmi_protocol_events_cleanup(struct scmi_device *scmi_dev)
+{
+ if (scmi_stop_and_flush_protocol_events(scmi_dev->protocol_id))
+ scmi_unregister_protocol_events(scmi_dev->handle->dev,
+ scmi_dev->protocol_id);
+}
+
static int scmi_dev_remove(struct device *dev)
{
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
struct scmi_device *scmi_dev = to_scmi_dev(dev);

+ /* Release events resources allocated by scmi_protocol_init() */
+ scmi_protocol_events_cleanup(scmi_dev);
+
if (scmi_drv->remove)
scmi_drv->remove(scmi_dev);

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 868cc36a07c9..dc93d608c43c 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>

#include "common.h"
+#include "notify.h"

#define CREATE_TRACE_POINTS
#include <trace/events/scmi.h>
@@ -204,11 +205,13 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)

static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
{
+ u64 ts;
struct scmi_xfer *xfer;
struct device *dev = cinfo->dev;
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
struct scmi_xfers_info *minfo = &info->rx_minfo;

+ ts = ktime_get_boottime_ns();
xfer = scmi_xfer_get(cinfo->handle, minfo);
if (IS_ERR(xfer)) {
dev_err(dev, "failed to get free message slot (%ld)\n",
@@ -221,6 +224,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
scmi_dump_header_dbg(dev, &xfer->hdr);
info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size,
xfer);
+ scmi_notify(xfer->hdr.protocol_id, xfer->hdr.id, xfer->rx.buf,
+ xfer->rx.len, ts);

trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq,
@@ -771,6 +776,9 @@ static int scmi_probe(struct platform_device *pdev)
if (ret)
return ret;

+ if (scmi_notification_init(handle))
+ dev_err(dev, "SCMI Notifications NOT available.\n");
+
ret = scmi_base_protocol_init(handle);
if (ret) {
dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
@@ -813,6 +821,8 @@ static int scmi_remove(struct platform_device *pdev)
struct scmi_info *info = platform_get_drvdata(pdev);
struct idr *idr = &info->tx_idr;

+ scmi_notification_exit();
+
mutex_lock(&scmi_list_mutex);
if (info->users)
ret = -EBUSY;
--
2.17.1