[Skiboot] [PATCH 2/7] opal-msg: Add get_opal_msg2

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Thu Mar 28 22:18:16 AEDT 2019


Linux uses get_opal_msg (GET_OPAL_MSG) API to get OPAL messages. This interface
supports upto 8 params (64 bytes). Also OPAL doesn't return actual message.

We have a requirement to send bigger data to Linux. Hence this patch introduces
new API - GET_OPAL_MSG2.

- get_opal_msg2(uint64_t *buffer, uint64_t *size)
  Linux will allocate and send buffer and buffer size to OPAL.
  OPAL copies opal_msg to buffer and updates size with actual message size.

- Replaced `reserved` feild in "struct opal_msg" with `size`. So that Linux
  side get_opal_msg2 user can detect message data size. We don't need to
  change existing opal message notifier in Linux.

- This patch introduces new variable (opal_msg2_supported) to detect whether
  Linux supports new API or not. So that we can support both get_opal_msg
  and get_opal_msg2 (like new petitboot kernel and old host linux kernel).

- We will queue opal message with > 64 bytes of data, only if Linux supports
  new API.

- Add new internal function (opal_queue_msg_extended()) to queue opal_msg with
  bigger data.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 core/opal-msg.c                    | 91 +++++++++++++++++++++++++++++++++-----
 doc/opal-api/opal-get-msg2-170.rst | 30 +++++++++++++
 include/opal-api.h                 |  5 ++-
 include/opal-msg.h                 |  8 ++++
 4 files changed, 120 insertions(+), 14 deletions(-)
 create mode 100644 doc/opal-api/opal-get-msg2-170.rst

diff --git a/core/opal-msg.c b/core/opal-msg.c
index 19714670e..98489c28b 100644
--- a/core/opal-msg.c
+++ b/core/opal-msg.c
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2013-2019 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,12 +34,27 @@ static LIST_HEAD(msg_pending_list);
 
 static struct lock opal_msg_lock = LOCK_UNLOCKED;
 
-int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
-		    void (*consumed)(void *data), size_t num_params,
-		    const u64 *params)
+static bool opal_msg2_supported;
+
+static int __opal_queue_msg(enum opal_msg_type msg_type, void *data,
+			    void (*consumed)(void *data), size_t params_size,
+			    const void *params)
 {
 	struct opal_msg_entry *entry;
 
+	/* Check whether opal_get_msg2 is supported by kernel */
+	if (!opal_msg2_supported &&
+	    params_size > OPAL_MSG_FIXED_PARAMS_SIZE) {
+		prerror("Discarding extra parameters\n");
+		params_size = OPAL_MSG_FIXED_PARAMS_SIZE;
+	}
+
+	if ((params_size + offsetof(struct opal_msg, params)) > OPAL_MSG_SIZE) {
+		prlog(PR_DEBUG, "Message size (0x%x) > opal-msg-size (0x%x)\n",
+		      (u32)params_size, (u32)OPAL_MSG_SIZE);
+		return OPAL_PARAMETER;
+	}
+
 	lock(&opal_msg_lock);
 
 	entry = list_pop(&msg_free_list, struct opal_msg_entry, link);
@@ -56,12 +71,14 @@ int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
 	entry->consumed = consumed;
 	entry->data = data;
 	entry->msg.msg_type = cpu_to_be32(msg_type);
+	entry->msg.size = cpu_to_be32(params_size);
 
-	if (num_params > ARRAY_SIZE(entry->msg.params)) {
-		prerror("Discarding extra parameters\n");
-		num_params = ARRAY_SIZE(entry->msg.params);
+	if (params_size > OPAL_MSG_FIXED_PARAMS_SIZE) {
+		/* msg.params[0] contains address of data */
+		entry->msg.params[0] = (uint64_t)params;
+	} else {
+		memcpy(entry->msg.params, params, params_size);
 	}
-	memcpy(entry->msg.params, params, num_params*sizeof(u64));
 
 	list_add_tail(&msg_pending_list, &entry->link);
 	opal_update_pending_evt(OPAL_EVENT_MSG_PENDING,
@@ -72,13 +89,32 @@ int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
 	return 0;
 }
 
-static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
+int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
+		    void (*consumed)(void *data), size_t num_params,
+		    const u64 *params)
 {
+	/* Convert num_params to actual size */
+	return __opal_queue_msg(msg_type, data, consumed,
+				(num_params * sizeof(u64)), params);
+}
+
+int opal_queue_msg_extended(enum opal_msg_type msg_type, void *data,
+			    void (*consumed)(void *data), size_t msg_size,
+			    const void *msg_data)
+{
+	return __opal_queue_msg(msg_type, data, consumed, msg_size, msg_data);
+}
+
+static int64_t __opal_get_msg(uint64_t *buffer, uint64_t *size)
+{
+	int rc = OPAL_SUCCESS;
+	int msg_size;
+	struct opal_msg *msg = (struct opal_msg *)buffer;
 	struct opal_msg_entry *entry;
 	void (*callback)(void *data);
 	void *data;
 
-	if (size < sizeof(struct opal_msg) || !buffer)
+	if (*size < sizeof(struct opal_msg) || !buffer)
 		return OPAL_PARAMETER;
 
 	if (!opal_addr_valid(buffer))
@@ -92,7 +128,25 @@ static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
 		return OPAL_RESOURCE;
 	}
 
-	memcpy(buffer, &entry->msg, sizeof(entry->msg));
+	msg_size = offsetof(struct opal_msg, params) +
+				be32_to_cpu(entry->msg.size);
+	/* check whether params[0] contains address or actual data */
+	if (be32_to_cpu(entry->msg.size) > OPAL_MSG_FIXED_PARAMS_SIZE) {
+		if (*size < msg_size) {
+			/* Send error message to Linux */
+			rc = OPAL_PARAMETER;
+		} else {
+			msg->msg_type = entry->msg.msg_type;
+			msg->size = entry->msg.size;
+			memcpy((void *)msg->params,
+			       (void *)entry->msg.params[0],
+			       be32_to_cpu(entry->msg.size));
+		}
+	} else {
+		memcpy(buffer, &entry->msg, sizeof(entry->msg));
+	}
+
+	*size = cpu_to_be64(msg_size);
 	callback = entry->consumed;
 	data = entry->data;
 
@@ -105,7 +159,20 @@ static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
 	if (callback)
 		callback(data);
 
-	return OPAL_SUCCESS;
+	return rc;
+}
+
+static int64_t opal_get_msg2(uint64_t *buffer, uint64_t *size)
+{
+	opal_msg2_supported = true;
+	return __opal_get_msg(buffer, size);
+}
+opal_call(OPAL_GET_MSG2, opal_get_msg2, 2);
+
+static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
+{
+	opal_msg2_supported = false;
+	return __opal_get_msg(buffer, &size);
 }
 opal_call(OPAL_GET_MSG, opal_get_msg, 2);
 
diff --git a/doc/opal-api/opal-get-msg2-170.rst b/doc/opal-api/opal-get-msg2-170.rst
new file mode 100644
index 000000000..42af5e2b3
--- /dev/null
+++ b/doc/opal-api/opal-get-msg2-170.rst
@@ -0,0 +1,30 @@
+OPAL_GET_MSG2
+=============
+
+OPAL_GET_MSG2 will get the next pending OPAL Message (see :ref:`opal-messages`).
+
+Parameters: ::
+
+	buffer to copy message into
+	sizeof buffer to copy message into, OPAL will return actual message size
+
+The maximum size of an opal message is specified in the device tree passed
+to the host OS: ::
+
+  ibm,opal {
+            opal-msg-size = <0x10000>;
+  }
+
+A host OS *SHOULD* always supply a buffer to OPAL_GET_MSG2 of "opal-msg-size"
+bytes.
+
+Return values
+-------------
+OPAL_RESOURCE
+  no available message.
+
+OPAL_PARAMETER
+  buffer is NULL or size is < opal_msg fixed size (72 bytes).
+
+OPAL_SUCCESS
+  message successfully copied to buffer.
diff --git a/include/opal-api.h b/include/opal-api.h
index 73f86f9a5..8f88a973f 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -226,7 +226,8 @@
 #define OPAL_NX_COPROC_INIT			167
 #define OPAL_NPU_SET_RELAXED_ORDER		168
 #define OPAL_NPU_GET_RELAXED_ORDER		169
-#define OPAL_LAST				169
+#define OPAL_GET_MSG2				170
+#define OPAL_LAST				170
 
 #define QUIESCE_HOLD			1 /* Spin all calls at entry */
 #define QUIESCE_REJECT			2 /* Fail all calls with OPAL_BUSY */
@@ -552,7 +553,7 @@ enum opal_msg_type {
 
 struct opal_msg {
 	__be32 msg_type;
-	__be32 reserved;
+	__be32 size;
 	__be64 params[8];
 };
 
diff --git a/include/opal-msg.h b/include/opal-msg.h
index 86b6d616e..93b5ca3e8 100644
--- a/include/opal-msg.h
+++ b/include/opal-msg.h
@@ -30,6 +30,10 @@
 /* Max size of struct opal_msg */
 #define OPAL_MSG_SIZE		(64 * 1024)
 
+/* opal_msg fixed parameters size */
+#define OPAL_MSG_FIXED_PARAMS_SIZE	\
+	(sizeof(struct opal_msg) - offsetof(struct opal_msg, params))
+
 int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
 		    void (*consumed)(void *data), size_t num_params,
 		    const u64 *params);
@@ -39,6 +43,10 @@ int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
 			sizeof((u64[]) {__VA_ARGS__})/sizeof(u64), \
 			(u64[]) {__VA_ARGS__});
 
+int opal_queue_msg_extended(enum opal_msg_type msg_type, void *data,
+			    void (*consumed)(void *data), size_t msg_size,
+			    const void *msg_data);
+
 void opal_init_msg(void);
 
 #endif /* __OPALMSG_H */
-- 
2.14.3



More information about the Skiboot mailing list