[Skiboot] [PATCH v2 3/9] opal-msg: Enhance opal-get-msg API
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Tue Apr 9 21:49:23 AEST 2019
Linux uses opal_get_msg (OPAL_GET_MSG) API to get OPAL messages. This interface
supports upto 8 params (64 bytes). We have a requirement to send bigger data to
Linux. This patch enhances OPAL to send bigger data to Linux.
- Linux will use "opal-msg-size" device tree property to allocate memory for
OPAL messages (Previous patch increased "opal-msg-size" to 64K).
- Replaced `reserved` field in "struct opal_msg" with `size`. So that Linux
side opal_get_msg user can detect actual data size.
- If buffer size < actual message size, then opal_get_msg will copy partial
data and return OPAL_PARTIAL to Linux.
- Add new internal function (opal_queue_msg_buf()) to queue opal_msg with
bigger data.
Cc: Jeremy Kerr <jk at ozlabs.org>
Cc: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Cc: Oliver O'Halloran <oohall at gmail.com>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
core/opal-msg.c | 72 ++++++++++++++++++++++++++++++++++++------
core/test/run-msg.c | 2 +-
doc/opal-api/opal-messages.rst | 2 +-
include/opal-api.h | 2 +-
include/opal-msg.h | 9 ++++++
5 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/core/opal-msg.c b/core/opal-msg.c
index d3dd2ae3c..a34cc29c0 100644
--- a/core/opal-msg.c
+++ b/core/opal-msg.c
@@ -34,12 +34,18 @@ 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, int status),
- size_t num_params, const u64 *params)
+static int __opal_queue_msg(enum opal_msg_type msg_type, void *data,
+ void (*consumed)(void *data, int status),
+ size_t params_size, const void *params_data)
{
struct opal_msg_entry *entry;
+ if ((params_size + OPAL_MSG_HDR_SIZE) > OPAL_MSG_SIZE) {
+ prlog(PR_DEBUG, "param_size (0x%x) > opal_msg param size (0x%x)\n",
+ (u32)params_size, (u32)(OPAL_MSG_SIZE - OPAL_MSG_HDR_SIZE));
+ return OPAL_PARAMETER;
+ }
+
lock(&opal_msg_lock);
entry = list_pop(&msg_free_list, struct opal_msg_entry, link);
@@ -56,12 +62,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_data;
+ } else {
+ memcpy(entry->msg.params, params_data, 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,8 +80,29 @@ int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
return 0;
}
+int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
+ void (*consumed)(void *data, int status),
+ 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_buf(enum opal_msg_type msg_type, void *data,
+ void (*consumed)(void *data, int status),
+ size_t params_size, const void *params_data)
+{
+ return __opal_queue_msg(msg_type, data,
+ consumed, params_size, params_data);
+}
+
static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
{
+ int rc = OPAL_SUCCESS;
+ int params_size;
+ uint64_t msg_size;
+ struct opal_msg *msg = (struct opal_msg *)buffer;
struct opal_msg_entry *entry;
void (*callback)(void *data, int status);
void *data;
@@ -92,7 +121,30 @@ static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
return OPAL_RESOURCE;
}
- memcpy(buffer, &entry->msg, sizeof(entry->msg));
+ /* Check whether params[0] contains address or actual data */
+ if (be32_to_cpu(entry->msg.size) > OPAL_MSG_FIXED_PARAMS_SIZE) {
+
+ params_size = be32_to_cpu(entry->msg.size);
+ msg_size = OPAL_MSG_HDR_SIZE + params_size;
+
+ if (size < msg_size) {
+ /* Send partial data to Linux */
+ params_size = size - OPAL_MSG_HDR_SIZE;
+ prlog(PR_NOTICE, "Sending partial data [msg_type :"
+ " 0x%x, param_size : 0x%x, buf_size : 0x%x]\n",
+ be32_to_cpu(entry->msg.msg_type),
+ be32_to_cpu(entry->msg.size), params_size);
+ rc = OPAL_PARTIAL;
+ }
+
+ msg->msg_type = entry->msg.msg_type;
+ msg->size = cpu_to_be32(params_size);
+ memcpy((void *)msg->params,
+ (void *)entry->msg.params[0], params_size);
+ } else {
+ memcpy(buffer, &entry->msg, sizeof(entry->msg));
+ }
+
callback = entry->consumed;
data = entry->data;
@@ -103,9 +155,9 @@ static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
unlock(&opal_msg_lock);
if (callback)
- callback(data, OPAL_SUCCESS);
+ callback(data, rc);
- return OPAL_SUCCESS;
+ return rc;
}
opal_call(OPAL_GET_MSG, opal_get_msg, 2);
diff --git a/core/test/run-msg.c b/core/test/run-msg.c
index 08e1a019b..839074d61 100644
--- a/core/test/run-msg.c
+++ b/core/test/run-msg.c
@@ -135,7 +135,7 @@ int main(void)
assert(list_count(&msg_free_list) == --nfree);
r = opal_get_msg(m_ptr, sizeof(m));
- assert(r == 0);
+ assert(r == OPAL_PARTIAL);
assert(list_count(&msg_pending_list) == --npending);
assert(list_count(&msg_free_list) == ++nfree);
diff --git a/doc/opal-api/opal-messages.rst b/doc/opal-api/opal-messages.rst
index e4e813aad..25acaec2c 100644
--- a/doc/opal-api/opal-messages.rst
+++ b/doc/opal-api/opal-messages.rst
@@ -11,7 +11,7 @@ An opal_msg is: ::
struct opal_msg {
__be32 msg_type;
- __be32 reserved;
+ __be32 size;
__be64 params[8];
};
diff --git a/include/opal-api.h b/include/opal-api.h
index 36aaf54e5..c8d04167a 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -553,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 9be70334d..462d66da1 100644
--- a/include/opal-msg.h
+++ b/include/opal-msg.h
@@ -30,6 +30,11 @@
/* Max size of struct opal_msg */
#define OPAL_MSG_SIZE (64 * 1024)
+/* opal_msg fixed parameters size */
+#define OPAL_MSG_HDR_SIZE (offsetof(struct opal_msg, params))
+#define OPAL_MSG_FIXED_PARAMS_SIZE \
+ (sizeof(struct opal_msg) - OPAL_MSG_HDR_SIZE)
+
int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
void (*consumed)(void *data, int status),
size_t num_params, const u64 *params);
@@ -39,6 +44,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_buf(enum opal_msg_type msg_type, void *data,
+ void (*consumed)(void *data, int status),
+ size_t params_size, const void *params_data);
+
void opal_init_msg(void);
#endif /* __OPALMSG_H */
--
2.14.3
More information about the Skiboot
mailing list