@@ -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);
@@ -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;
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@arm.com> --- 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(+)