Skip to content

Commit

Permalink
opal-msg: Enhance opal-get-msg API
Browse files Browse the repository at this point in the history
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 variable "extended" to "opal_msg_entry" structure to keep track
  of messages that has more than 64byte data. We will allocate separate
  memory for these messages and once kernel consumes message we will
  release that memory.

Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Cc: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Acked-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
Vasant Hegde authored and stewartsmith committed Jun 3, 2019
1 parent 66d0ad6 commit b6fce51
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 25 deletions.
66 changes: 48 additions & 18 deletions core/opal-msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
struct opal_msg_entry {
struct list_node link;
void (*consumed)(void *data, int status);
bool extended;
void *data;
struct opal_msg msg;
};
Expand All @@ -39,44 +40,56 @@ int _opal_queue_msg(enum opal_msg_type msg_type, void *data,
size_t params_size, const void *params)
{
struct opal_msg_entry *entry;
uint64_t entry_size;

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);
if (!entry) {
prerror("No available node in the free list, allocating\n");
entry = zalloc(sizeof(struct opal_msg_entry));
if (params_size > OPAL_MSG_FIXED_PARAMS_SIZE) {
entry_size = sizeof(struct opal_msg_entry) + params_size;
entry_size -= OPAL_MSG_FIXED_PARAMS_SIZE;
entry = zalloc(entry_size);
if (entry)
entry->extended = true;
} else {
entry = list_pop(&msg_free_list, struct opal_msg_entry, link);
if (!entry) {
prerror("Allocation failed\n");
unlock(&opal_msg_lock);
return OPAL_RESOURCE;
prerror("No available node in the free list, allocating\n");
entry = zalloc(sizeof(struct opal_msg_entry));
}
}
if (!entry) {
prerror("Allocation failed\n");
unlock(&opal_msg_lock);
return OPAL_RESOURCE;
}

entry->consumed = consumed;
entry->data = data;
entry->msg.msg_type = cpu_to_be32(msg_type);

if (params_size > OPAL_MSG_FIXED_PARAMS_SIZE) {
prerror("Discarding extra parameters\n");
params_size = OPAL_MSG_FIXED_PARAMS_SIZE;
}
entry->msg.size = cpu_to_be32(params_size);
memcpy(entry->msg.params, params, params_size);

list_add_tail(&msg_pending_list, &entry->link);
opal_update_pending_evt(OPAL_EVENT_MSG_PENDING,
OPAL_EVENT_MSG_PENDING);

unlock(&opal_msg_lock);

return 0;
return OPAL_SUCCESS;
}

static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
{
struct opal_msg_entry *entry;
void (*callback)(void *data, int status);
void *data;
uint64_t msg_size;
int rc = OPAL_SUCCESS;

if (size < sizeof(struct opal_msg) || !buffer)
return OPAL_PARAMETER;
Expand All @@ -92,20 +105,37 @@ static int64_t opal_get_msg(uint64_t *buffer, uint64_t size)
return OPAL_RESOURCE;
}

memcpy(buffer, &entry->msg, sizeof(entry->msg));
msg_size = OPAL_MSG_HDR_SIZE + be32_to_cpu(entry->msg.size);
if (size < msg_size) {
/* Send partial data to Linux */
prlog(PR_NOTICE, "Sending partial data [msg_type : 0x%x, "
"msg_size : 0x%x, buf_size : 0x%x]\n",
be32_to_cpu(entry->msg.msg_type),
(u32)msg_size, (u32)size);

entry->msg.size = cpu_to_be32(size - OPAL_MSG_HDR_SIZE);
msg_size = size;
rc = OPAL_PARTIAL;
}

memcpy((void *)buffer, (void *)&entry->msg, msg_size);
callback = entry->consumed;
data = entry->data;

list_add(&msg_free_list, &entry->link);
if (entry->extended)
free(entry);
else
list_add(&msg_free_list, &entry->link);

if (list_empty(&msg_pending_list))
opal_update_pending_evt(OPAL_EVENT_MSG_PENDING, 0);

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);

Expand Down
6 changes: 3 additions & 3 deletions core/test/run-msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,13 @@ int main(void)
assert(r == 0);

assert(list_count(&msg_pending_list) == ++npending);
assert(list_count(&msg_free_list) == --nfree);
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);
assert(list_count(&msg_free_list) == nfree);

assert(m.params[0] == 0);
assert(m.params[1] == 1);
Expand Down
7 changes: 4 additions & 3 deletions doc/opal-api/opal-messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ An opal_msg is: ::

struct opal_msg {
__be32 msg_type;
__be32 reserved;
__be32 size;
__be64 params[8];
};

Expand All @@ -21,8 +21,9 @@ define all eight parameters, the value in the undefined parameters is
undefined, although can safely be memcpy()d or otherwise moved.

In the device tree, there's an opal-msg-size property of the OPAL node that
says the size of a struct opal-msg. In the future, OPAL may support larger
messages. See ``OPAL_GET_MESSAGE`` documentation for details.
says the size of a struct opal-msg. Kernel will use this property to allocate
memory for opal_msg structure. See ``OPAL_GET_MESSAGE`` documentation for
details.
::

ibm,opal {
Expand Down
2 changes: 1 addition & 1 deletion include/opal-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ enum opal_msg_type {

struct opal_msg {
__be32 msg_type;
__be32 reserved;
__be32 size;
__be64 params[8];
};

Expand Down

0 comments on commit b6fce51

Please sign in to comment.