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 c4a1262..c093f33 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 27213bf..563a641 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 023c93d..9ca019d 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 284dda5..114890b 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 {