From 32aee8415dac5ef71d53cacc28e25a8d312cc47b Mon Sep 17 00:00:00 2001
From: Roberto Vargas <roberto.vargas@arm.com>
Date: Mon, 13 Nov 2017 13:41:58 +0000
Subject: [PATCH] scmi: Optimize bakery locks when HW_ASSISTED_COHERENCY is
 enabled

When HW_ASSISTED_COHERENCY is enabled we can use spinlocks
instead of using the more complex and slower bakery algorithm.

Change-Id: I9d791a70050d599241169b9160a67e57d5506564
Signed-off-by: Roberto Vargas <roberto.vargas@arm.com>
---
 bl31/bl31.ld.S                          |  9 ++++++++-
 include/plat/arm/common/plat_arm.h      |  9 +++++++++
 plat/arm/css/drivers/scmi/scmi.h        | 10 +++++++++-
 plat/arm/css/drivers/scmi/scmi_common.c | 18 +++++++++++++++---
 plat/arm/css/drivers/scp/css_pm_scmi.c  |  4 ++--
 5 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 66cb3f30e..81e7ba3a3 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -188,8 +188,15 @@ SECTIONS
         __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(. - __BAKERY_LOCK_START__);
         . = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1));
         __BAKERY_LOCK_END__ = .;
+
+	/*
+	 * If BL31 doesn't use any bakery lock then __PERCPU_BAKERY_LOCK_SIZE__
+	 * will be zero. For this reason, the only two valid values for
+	 * __PERCPU_BAKERY_LOCK_SIZE__ are 0 or the platform defined value
+	 * PLAT_PERCPU_BAKERY_LOCK_SIZE.
+	 */
 #ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
-    ASSERT(__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE,
+    ASSERT((__PERCPU_BAKERY_LOCK_SIZE__ == 0) || (__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE),
         "PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements");
 #endif
 #endif
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index d543894d7..848f4eea8 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -11,6 +11,7 @@
 #include <cassert.h>
 #include <cpu_data.h>
 #include <stdint.h>
+#include <spinlock.h>
 #include <tzc_common.h>
 #include <utils_def.h>
 
@@ -80,6 +81,14 @@ void arm_setup_romlib(void);
  */
 #define ARM_INSTANTIATE_LOCK	static DEFINE_BAKERY_LOCK(arm_lock)
 #define ARM_LOCK_GET_INSTANCE	(&arm_lock)
+
+#if !HW_ASSISTED_COHERENCY
+#define ARM_SCMI_INSTANTIATE_LOCK	DEFINE_BAKERY_LOCK(arm_scmi_lock)
+#else
+#define ARM_SCMI_INSTANTIATE_LOCK	spinlock_t arm_scmi_lock
+#endif
+#define ARM_SCMI_LOCK_GET_INSTANCE	(&arm_scmi_lock)
+
 /*
  * These are wrapper macros to the Coherent Memory Bakery Lock API.
  */
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index 723fd06ed..71a8c2d02 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -10,6 +10,7 @@
 #include <bakery_lock.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <spinlock.h>
 
 /* Supported SCMI Protocol Versions */
 #define SCMI_AP_CORE_PROTO_VER			MAKE_SCMI_VERSION(1, 0)
@@ -116,13 +117,20 @@ typedef struct scmi_channel_plat_info {
 	void *cookie;
 } scmi_channel_plat_info_t;
 
+
+#if HW_ASSISTED_COHERENCY
+typedef spinlock_t scmi_lock_t;
+#else
+typedef bakery_lock_t scmi_lock_t;
+#endif
+
 /*
  * Structure to represent an SCMI channel.
  */
 typedef struct scmi_channel {
 	scmi_channel_plat_info_t *info;
 	 /* The lock for channel access */
-	bakery_lock_t *lock;
+	scmi_lock_t *lock;
 	/* Indicate whether the channel is initialized */
 	int is_initialized;
 } scmi_channel_t;
diff --git a/plat/arm/css/drivers/scmi/scmi_common.c b/plat/arm/css/drivers/scmi/scmi_common.c
index 8482d219c..b34178ec3 100644
--- a/plat/arm/css/drivers/scmi/scmi_common.c
+++ b/plat/arm/css/drivers/scmi/scmi_common.c
@@ -10,13 +10,25 @@
 #include "scmi.h"
 #include "scmi_private.h"
 
+
+#if HW_ASSISTED_COHERENCY
+#define scmi_lock_init(lock)
+#define scmi_lock_get(lock)		spin_lock(lock)
+#define scmi_lock_release(lock)		spin_unlock(lock)
+#else
+#define scmi_lock_init(lock)		bakery_lock_init(lock)
+#define scmi_lock_get(lock)		bakery_lock_get(lock)
+#define scmi_lock_release(lock)		bakery_lock_release(lock)
+#endif
+
+
 /*
  * Private helper function to get exclusive access to SCMI channel.
  */
 void scmi_get_channel(scmi_channel_t *ch)
 {
 	assert(ch->lock);
-	bakery_lock_get(ch->lock);
+	scmi_lock_get(ch->lock);
 
 	/* Make sure any previous command has finished */
 	assert(SCMI_IS_CHANNEL_FREE(
@@ -68,7 +80,7 @@ void scmi_put_channel(scmi_channel_t *ch)
 			((mailbox_mem_t *)(ch->info->scmi_mbx_mem))->status));
 
 	assert(ch->lock);
-	bakery_lock_release(ch->lock);
+	scmi_lock_release(ch->lock);
 }
 
 /*
@@ -152,7 +164,7 @@ void *scmi_init(scmi_channel_t *ch)
 
 	assert(ch->lock);
 
-	bakery_lock_init(ch->lock);
+	scmi_lock_init(ch->lock);
 
 	ch->is_initialized = 1;
 
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index d280101d6..9297e9fe4 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -71,7 +71,7 @@ static void *scmi_handle;
 /* The SCMI channel global object */
 static scmi_channel_t channel;
 
-ARM_INSTANTIATE_LOCK;
+ARM_SCMI_INSTANTIATE_LOCK;
 
 /*
  * Helper function to suspend a CPU power domain and its parent power domains
@@ -331,7 +331,7 @@ static int scmi_ap_core_init(scmi_channel_t *ch)
 void __init plat_arm_pwrc_setup(void)
 {
 	channel.info = &plat_css_scmi_plat_info;
-	channel.lock = ARM_LOCK_GET_INSTANCE;
+	channel.lock = ARM_SCMI_LOCK_GET_INSTANCE;
 	scmi_handle = scmi_init(&channel);
 	if (scmi_handle == NULL) {
 		ERROR("SCMI Initialization failed\n");
-- 
GitLab