summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/ipmi.c36
-rw-r--r--hw/bt.c66
-rw-r--r--include/bt.h6
-rw-r--r--include/ipmi.h3
4 files changed, 64 insertions, 47 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index 30ea78aa..1f9dd5f0 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -35,7 +35,7 @@ static void ipmi_process_storage_resp(struct ipmi_msg *msg)
* I couldn't find any mention of endianess in the IPMI spec,
* but ipmitool seemed to assume little endian?
*/
- memcpy(&new_time, msg->resp_data, 4);
+ memcpy(&new_time, msg->data, 4);
time = le32_to_cpu(new_time);
break;
@@ -48,39 +48,37 @@ static void ipmi_process_storage_resp(struct ipmi_msg *msg)
}
}
-static uint32_t time_result;
static int64_t ipmi_get_sel_time(void)
{
- struct ipmi_msg *msg = malloc(sizeof(struct ipmi_msg));
+ struct ipmi_msg *msg;
+ static uint32_t time_result;
+ msg = bt_alloc_ipmi_msg(0, 4);
if (!msg)
return OPAL_HARDWARE;
msg->cmd = IPMI_GET_SEL_TIME_CMD;
msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
- msg->req_data = NULL;
- msg->req_data_len = 0;
- msg->resp_data = (uint8_t *) &time_result;
- msg->resp_data_len = 4;
+
if (bt_add_ipmi_msg_wait(msg))
return -1;
+ memcpy(&time_result, msg->data, sizeof(time_result));
+
return time_result;
}
static int64_t ipmi_set_sel_time(uint32_t tv)
{
- struct ipmi_msg *msg = malloc(sizeof(struct ipmi_msg));
+ struct ipmi_msg *msg;
+ msg = bt_alloc_ipmi_msg(sizeof(tv), 0);
if (!msg)
return OPAL_HARDWARE;
msg->cmd = IPMI_SET_SEL_TIME_CMD;
msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
- msg->req_data = (uint8_t *) &tv;
- msg->req_data_len = 4;
- msg->resp_data = NULL;
- msg->resp_data_len = 0;
+ memcpy(msg->data, &tv, sizeof(tv));
return bt_add_ipmi_msg_wait(msg);
}
@@ -141,28 +139,24 @@ static void ipmi_cmd_done(struct ipmi_msg *msg)
}
out:
- free(msg);
+ bt_free_ipmi_msg(msg);
}
-static uint8_t chassis_control;
int64_t ipmi_opal_chassis_control(uint64_t request)
{
- struct ipmi_msg *msg = zalloc(sizeof(struct ipmi_msg));
+ struct ipmi_msg *msg;
+ uint8_t chassis_control = request;
+ msg = bt_alloc_ipmi_msg(sizeof(chassis_control), 0);
if (!msg)
return OPAL_HARDWARE;
if (request > IPMI_CHASSIS_SOFT_SHUTDOWN)
return OPAL_PARAMETER;
- chassis_control = request;
-
msg->cmd = IPMI_CHASSIS_CONTROL_CMD;
msg->netfn = IPMI_NETFN_CHASSIS_REQUEST;
- msg->req_data = (uint8_t *)&chassis_control;
- msg->req_data_len = sizeof(chassis_control);
- msg->resp_data = NULL;
- msg->resp_data_len = 0;
+ msg->data[0] = chassis_control;
prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
request);
diff --git a/hw/bt.c b/hw/bt.c
index 85ae6b41..da925973 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -62,9 +62,9 @@ const char *state_str[] = {
struct bt_msg {
struct list_node link;
- struct ipmi_msg *ipmi_msg;
uint8_t seq;
uint8_t lun;
+ struct ipmi_msg ipmi_msg;
};
struct bt {
@@ -114,14 +114,10 @@ static inline void bt_set_state(enum bt_states next_state)
static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
- struct bt_msg *bt_msg = malloc(sizeof(struct bt_msg));
-
- if (!bt_msg)
- return -1;
+ struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
bt_msg->lun = 0;
bt_msg->seq = ipmi_seq++;
- bt_msg->ipmi_msg = ipmi_msg;
list_add_tail(&bt.msgq, &bt_msg->link);
return 0;
@@ -143,7 +139,7 @@ static bool bt_try_send_msg(void)
if (!bt_msg)
return true;
- ipmi_msg = bt_msg->ipmi_msg;
+ ipmi_msg = &bt_msg->ipmi_msg;
if (!bt_idle()) {
prerror("BT: Interface in an unexpected state, attempting reset\n");
@@ -168,7 +164,7 @@ static bool bt_try_send_msg(void)
/* Byte 5:N - Data */
for (i = 0; i < ipmi_msg->req_data_len; i++)
- bt_outb(ipmi_msg->req_data[i], BT_HOST2BMC);
+ bt_outb(ipmi_msg->data[i], BT_HOST2BMC);
bt_setmask(BT_CTRL_H2B_ATN, BT_CTRL);
bt_set_state(BT_STATE_RESP_WAIT);
@@ -205,7 +201,7 @@ static bool bt_get_resp(void)
return false;
}
- ipmi_msg = bt_msg->ipmi_msg;
+ ipmi_msg = &bt_msg->ipmi_msg;
bt_setmask(BT_CTRL_H_BUSY, BT_CTRL);
bt_clearmask(BT_CTRL_B2H_ATN, BT_CTRL);
bt_setmask(BT_CTRL_CLR_RD_PTR, BT_CTRL);
@@ -242,7 +238,7 @@ static bool bt_get_resp(void)
/* Byte 6:N - Data */
for (i = 0; i < resp_len; i++)
- ipmi_msg->resp_data[i] = bt_inb(BT_HOST2BMC);
+ ipmi_msg->data[i] = bt_inb(BT_HOST2BMC);
bt_clearmask(BT_CTRL_H_BUSY, BT_CTRL);
if (cc != IPMI_CC_NO_ERROR) {
@@ -260,12 +256,6 @@ static bool bt_get_resp(void)
if (bt.ipmi_cmd_done)
bt.ipmi_cmd_done(ipmi_msg);
- /*
- * The IPMI layer should have freed any data it allocated for the IPMI
- * message in the completion function above.
- */
- free(bt_msg);
-
/* Immediately send the next message */
return false;
}
@@ -317,6 +307,35 @@ static bool bt_wait_state(enum bt_states state)
}
/*
+ * Allocate a BT-IPMI message and return the IPMI message struct. Allocates
+ * enough space for the request and response data.
+ */
+struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
+{
+ struct bt_msg *bt_msg;
+
+ bt_msg = malloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
+ if (!bt_msg)
+ return NULL;
+
+ bt_msg->ipmi_msg.req_data_len = request_size;
+ bt_msg->ipmi_msg.resp_data_len = response_size;
+ bt_msg->ipmi_msg.data = (uint8_t *) (bt_msg + 1);
+
+ return &bt_msg->ipmi_msg;
+}
+
+/*
+ * Free a previously allocated BT-IPMI message.
+ */
+void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
+{
+ struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
+
+ free(bt_msg);
+}
+
+/*
* Add an ipmi message to the queue and wait for a response.
*/
int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
@@ -351,18 +370,17 @@ out:
return ret;
}
+/*
+ * Remove a message from the queue. The memory allocated for the ipmi message
+ * will need to be freed by the caller with bt_free_ipmi_msg() as it will no
+ * longer be in the queue of messages.
+ */
void bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
- struct bt_msg *bt_msg;
- struct bt_msg *next;
+ struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
- list_for_each_safe(&bt.msgq, bt_msg, next, link) {
- if (bt_msg->ipmi_msg == ipmi_msg) {
- list_del(&bt_msg->link);
- break;
- }
- }
+ list_del(&bt_msg->link);
unlock(&bt.lock);
}
diff --git a/include/bt.h b/include/bt.h
index 4eac355b..5f8a91ee 100644
--- a/include/bt.h
+++ b/include/bt.h
@@ -22,6 +22,12 @@
/* Initialise the BT interface */
void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *));
+/* Allocate an BT-IPMI message */
+struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size);
+
+/* Free a BT-IPMI message */
+void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg);
+
/* Add an IPMI message to the BT queue and wait for a resposne */
int bt_add_ipmi_msg_wait(struct ipmi_msg *msg);
diff --git a/include/ipmi.h b/include/ipmi.h
index 96387b92..6181c53a 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -91,10 +91,9 @@ struct ipmi_msg {
uint8_t netfn;
uint8_t cmd;
uint8_t cc;
- uint8_t *req_data;
uint8_t req_data_len;
- uint8_t *resp_data;
uint8_t resp_data_len;
+ uint8_t *data;
};
/* Initialise the IPMI interface */
OpenPOWER on IntegriCloud