[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