firmware: arm_scmi: Make notify_priv really private
authorCristian Marussi <cristian.marussi@arm.com>
Tue, 16 Mar 2021 12:49:00 +0000 (12:49 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Tue, 30 Mar 2021 15:35:15 +0000 (16:35 +0100)
Notification private data is currently accessible via handle->notify_priv,
this data was indeed meant to be private to the notification core support
and not to be accessible by SCMI drivers. Make it private hiding it
inside instance descriptor struct scmi_info and accessible only via
dedicated helpers.

Link: https://lore.kernel.org/r/20210316124903.35011-36-cristian.marussi@arm.com
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/common.h
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/notify.c
include/linux/scmi_protocol.h

index c4a1262fb18d94e1192901d16f8516b8f884996d..c093f332cdcdc5fcf662140e2e3aec79f38be7ab 100644 (file)
@@ -343,4 +343,8 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
 bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
                     struct scmi_xfer *xfer);
 
+void scmi_notification_instance_data_set(const struct scmi_handle *handle,
+                                        void *priv);
+void *scmi_notification_instance_data_get(const struct scmi_handle *handle);
+
 #endif /* _SCMI_COMMON_H */
index 27213bf768c0b7bf23b02fba47d5a0e5ccb2b4ea..563a641310357b547c9d0e8a2409df56b5e6c29f 100644 (file)
@@ -113,6 +113,7 @@ struct scmi_protocol_instance {
  * @protocols_mtx: A mutex to protect protocols instances initialization.
  * @protocols_imp: List of protocols implemented, currently maximum of
  *     MAX_PROTOCOLS_IMP elements allocated by the base protocol
+ * @notify_priv: Pointer to private data structure specific to notifications.
  * @node: List head
  * @users: Number of users of this instance
  */
@@ -129,6 +130,7 @@ struct scmi_info {
        /* Ensure mutual exclusive access to protocols instance array */
        struct mutex protocols_mtx;
        u8 *protocols_imp;
+       void *notify_priv;
        struct list_head node;
        int users;
 };
@@ -170,6 +172,25 @@ static inline void scmi_dump_header_dbg(struct device *dev,
                hdr->id, hdr->seq, hdr->protocol_id);
 }
 
+void scmi_notification_instance_data_set(const struct scmi_handle *handle,
+                                        void *priv)
+{
+       struct scmi_info *info = handle_to_scmi_info(handle);
+
+       info->notify_priv = priv;
+       /* Ensure updated protocol private date are visible */
+       smp_wmb();
+}
+
+void *scmi_notification_instance_data_get(const struct scmi_handle *handle)
+{
+       struct scmi_info *info = handle_to_scmi_info(handle);
+
+       /* Ensure protocols_private_data has been updated */
+       smp_rmb();
+       return info->notify_priv;
+}
+
 /**
  * scmi_xfer_get() - Allocate one message
  *
index 023c93deb14bdb3708596bcbc143506a034885ac..9ca019dd0aeb6fb5c47dd4f8dd3cb5393f8690d6 100644 (file)
@@ -582,11 +582,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
        struct scmi_event_header eh;
        struct scmi_notify_instance *ni;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return 0;
-       ni = handle->notify_priv;
 
        r_evt = SCMI_GET_REVT(ni, proto_id, evt_id);
        if (!r_evt)
@@ -762,11 +760,9 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
            (!ee->num_sources && !ee->ops->get_num_sources))
                return -EINVAL;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return -ENOMEM;
-       ni = handle->notify_priv;
 
        /* num_sources cannot be <= 0 */
        if (ee->num_sources) {
@@ -846,12 +842,10 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle,
        struct scmi_notify_instance *ni;
        struct scmi_registered_events_desc *pd;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return;
 
-       ni = handle->notify_priv;
        pd = ni->registered_protocols[proto_id];
        if (!pd)
                return;
@@ -1354,11 +1348,9 @@ static int scmi_register_notifier(const struct scmi_handle *handle,
        struct scmi_event_handler *hndl;
        struct scmi_notify_instance *ni;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return -ENODEV;
-       ni = handle->notify_priv;
 
        evt_key = MAKE_HASH_KEY(proto_id, evt_id,
                                src_id ? *src_id : SRC_ID_MASK);
@@ -1402,11 +1394,9 @@ static int scmi_unregister_notifier(const struct scmi_handle *handle,
        struct scmi_event_handler *hndl;
        struct scmi_notify_instance *ni;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return -ENODEV;
-       ni = handle->notify_priv;
 
        evt_key = MAKE_HASH_KEY(proto_id, evt_id,
                                src_id ? *src_id : SRC_ID_MASK);
@@ -1681,8 +1671,8 @@ int scmi_notification_init(struct scmi_handle *handle)
 
        INIT_WORK(&ni->init_work, scmi_protocols_late_init);
 
+       scmi_notification_instance_data_set(handle, ni);
        handle->notify_ops = &notify_ops;
-       handle->notify_priv = ni;
        /* Ensure handle is up to date */
        smp_wmb();
 
@@ -1694,7 +1684,7 @@ int scmi_notification_init(struct scmi_handle *handle)
 
 err:
        dev_warn(handle->dev, "Initialization Failed.\n");
-       devres_release_group(handle->dev, NULL);
+       devres_release_group(handle->dev, gid);
        return -ENOMEM;
 }
 
@@ -1706,15 +1696,10 @@ void scmi_notification_exit(struct scmi_handle *handle)
 {
        struct scmi_notify_instance *ni;
 
-       /* Ensure notify_priv is updated */
-       smp_rmb();
-       if (!handle->notify_priv)
+       ni = scmi_notification_instance_data_get(handle);
+       if (!ni)
                return;
-       ni = handle->notify_priv;
-
-       handle->notify_priv = NULL;
-       /* Ensure handle is up to date */
-       smp_wmb();
+       scmi_notification_instance_data_set(handle, NULL);
 
        /* Destroy while letting pending work complete */
        destroy_workqueue(ni->notify_wq);
index 284dda52006e64b320809c5ca20b6b7c7a27fccc..114890bd7af0b8c07266884c175b817c9fa72ccb 100644 (file)
@@ -609,8 +609,6 @@ struct scmi_notify_ops {
  *                    operations and a dedicated protocol handler
  * @devm_protocol_put: devres managed method to release a protocol
  * @notify_ops: pointer to set of notifications related operations
- * @notify_priv: pointer to private data structure specific to notifications
- *     (for internal use only)
  */
 struct scmi_handle {
        struct device *dev;
@@ -622,7 +620,6 @@ struct scmi_handle {
        void (*devm_protocol_put)(struct scmi_device *sdev, u8 proto);
 
        const struct scmi_notify_ops *notify_ops;
-       void *notify_priv;
 };
 
 enum scmi_std_protocol {