aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ipmi.c2
-rw-r--r--hw/bt.c79
-rw-r--r--hw/ipmi/ipmi-power.c2
-rw-r--r--hw/ipmi/ipmi-rtc.c39
-rw-r--r--include/ipmi.h3
5 files changed, 52 insertions, 73 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index 90d8aaf..488e7e9 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -63,7 +63,7 @@ struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
return msg;
}
-int ipmi_sync_queue_msg(struct ipmi_msg *msg)
+int ipmi_queue_msg(struct ipmi_msg *msg)
{
/* Here we could choose which interface to use if we want to support
multiple interfaces. */
diff --git a/hw/bt.c b/hw/bt.c
index 882d72c..ec67154 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -116,8 +116,10 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
bt_msg->lun = 0;
+ lock(&bt.lock);
bt_msg->seq = ipmi_seq++;
list_add_tail(&bt.msgq, &bt_msg->link);
+ unlock(&bt.lock);
return 0;
}
@@ -134,15 +136,19 @@ static bool bt_try_send_msg(void)
struct bt_msg *bt_msg;
struct ipmi_msg *ipmi_msg;
+ lock(&bt.lock);
bt_msg = list_top(&bt.msgq, struct bt_msg, link);
- if (!bt_msg)
+ if (!bt_msg) {
+ unlock(&bt.lock);
return true;
+ }
ipmi_msg = &bt_msg->ipmi_msg;
if (!bt_idle()) {
prerror("BT: Interface in an unexpected state, attempting reset\n");
bt_reset_interface();
+ unlock(&bt.lock);
return false;
}
@@ -167,6 +173,8 @@ static bool bt_try_send_msg(void)
bt_setmask(BT_CTRL_H2B_ATN, BT_CTRL);
bt_set_state(BT_STATE_RESP_WAIT);
+ unlock(&bt.lock);
+
return true;
}
@@ -188,8 +196,11 @@ static bool bt_get_resp(void)
uint8_t cc = IPMI_CC_NO_ERROR;
/* Wait for BMC to signal response */
- if (!(bt_inb(BT_CTRL) & BT_CTRL_B2H_ATN))
+ lock(&bt.lock);
+ if (!(bt_inb(BT_CTRL) & BT_CTRL_B2H_ATN)) {
+ unlock(&bt.lock);
return true;
+ }
bt_msg = list_top(&bt.msgq, struct bt_msg, link);
if (!bt_msg) {
@@ -197,6 +208,7 @@ static bool bt_get_resp(void)
prlog(PR_INFO, "BT: Nobody cared about a response to an BT/IPMI message\n");
bt_flush_msg();
bt_set_state(BT_STATE_B_BUSY);
+ unlock(&bt.lock);
return false;
}
@@ -248,6 +260,7 @@ static bool bt_get_resp(void)
/* Make sure the other side is idle before we move to the idle state */
bt_set_state(BT_STATE_B_BUSY);
list_del(&bt_msg->link);
+ unlock(&bt.lock);
/*
* Call the IPMI layer to finish processing the message.
@@ -258,7 +271,7 @@ static bool bt_get_resp(void)
return false;
}
-static void bt_poll(void)
+static void bt_poll(void *data __unused)
{
bool ret = true;
@@ -284,27 +297,6 @@ static void bt_poll(void)
}
/*
- * Crank the state machine to wait for a specific state. Returns true on
- * success and false if there is a timeout.
- */
-static bool bt_wait_state(enum bt_states state)
-{
- int timeout;
- struct timespec ts;
-
- ts.tv_sec = 0;
- ts.tv_nsec = 100000;
- for (timeout = POLL_TIMEOUT; timeout > 0; timeout--) {
- if (bt.state == state)
- return true;
- bt_poll();
- nanosleep(&ts, NULL);
- }
-
- return false;
-}
-
-/*
* Allocate an ipmi message and bt container and return the ipmi
* message struct. Allocates enough space for the request and response
* data.
@@ -335,41 +327,6 @@ static void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
}
/*
- * Add an ipmi message to the queue and wait for a response.
- */
-static int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
-{
- int ret = 0;
-
- /*
- * TODO: We may need finer grained locks if we start using an
- * asynchronous operation model, but this should be fine for the moment.
- */
- lock(&bt.lock);
- if (!bt_wait_state(BT_STATE_IDLE)) {
- ret = -1;
- goto out;
- }
-
- if (bt_add_ipmi_msg(msg)) {
- ret = -1;
- goto out;
- }
-
- /* Make sure we get out of the idle state */
- bt_poll();
-
- if (!bt_wait_state(BT_STATE_IDLE)) {
- ret = -1;
- goto out;
- }
-
-out:
- unlock(&bt.lock);
- 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.
@@ -387,7 +344,7 @@ static int bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
struct ipmi_backend bt_backend = {
.alloc_msg = bt_alloc_ipmi_msg,
.free_msg = bt_free_ipmi_msg,
- .queue_msg = bt_add_ipmi_msg_wait,
+ .queue_msg = bt_add_ipmi_msg,
.dequeue_msg = bt_del_ipmi_msg,
};
@@ -422,5 +379,7 @@ void bt_init(void)
bt_set_state(BT_STATE_B_BUSY);
list_head_init(&bt.msgq);
+ opal_add_poller(bt_poll, NULL);
+
ipmi_register_backend(&bt_backend);
}
diff --git a/hw/ipmi/ipmi-power.c b/hw/ipmi/ipmi-power.c
index ac37d14..c8589c1 100644
--- a/hw/ipmi/ipmi-power.c
+++ b/hw/ipmi/ipmi-power.c
@@ -36,5 +36,5 @@ int64_t ipmi_opal_chassis_control(uint64_t request)
prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
request);
- return ipmi_sync_queue_msg(msg);
+ return ipmi_queue_msg(msg);
}
diff --git a/hw/ipmi/ipmi-rtc.c b/hw/ipmi/ipmi-rtc.c
index 5ddfced..7ac33ff 100644
--- a/hw/ipmi/ipmi-rtc.c
+++ b/hw/ipmi/ipmi-rtc.c
@@ -24,15 +24,17 @@
/* Sane default (2014/01/01) */
static time_t time = 1388494800;
+static enum {idle, waiting, updated} time_status;
+
static void get_sel_time_complete(struct ipmi_msg *msg)
{
uint32_t result;
memcpy(&result, msg->data, 4);
time = le32_to_cpu(result);
+ time_status = updated;
}
-
static int64_t ipmi_get_sel_time(void)
{
struct ipmi_msg *msg;
@@ -42,7 +44,7 @@ static int64_t ipmi_get_sel_time(void)
if (!msg)
return OPAL_HARDWARE;
- return ipmi_sync_queue_msg(msg);
+ return ipmi_queue_msg(msg);
}
static int64_t ipmi_set_sel_time(uint32_t tv)
@@ -54,20 +56,37 @@ static int64_t ipmi_set_sel_time(uint32_t tv)
if (!msg)
return OPAL_HARDWARE;
- return ipmi_sync_queue_msg(msg);
+ return ipmi_queue_msg(msg);
}
+void bt_poll(void *data __unused);
static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d,
uint64_t *h_m_s_m)
{
struct tm tm;
-
- if (ipmi_get_sel_time() < 0)
- return OPAL_HARDWARE;
-
- gmtime_r(&time, &tm);
- tm_to_datetime(&tm, y_m_d, h_m_s_m);
- return OPAL_SUCCESS;
+ int ret = 0;
+
+ switch(time_status) {
+ case idle:
+ if (ipmi_get_sel_time() < 0)
+ return OPAL_HARDWARE;
+ time_status = waiting;
+ ret = OPAL_BUSY_EVENT;
+ break;
+
+ case waiting:
+ ret = OPAL_BUSY_EVENT;
+ break;
+
+ case updated:
+ gmtime_r(&time, &tm);
+ tm_to_datetime(&tm, y_m_d, h_m_s_m);
+ time_status = idle;
+ ret = OPAL_SUCCESS;
+ break;
+ }
+
+ return ret;
}
static int64_t ipmi_opal_rtc_write(uint32_t year_month_day,
diff --git a/include/ipmi.h b/include/ipmi.h
index 78eb5cd..643dbf4 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -129,7 +129,8 @@ struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
void *user_data, void *req_data, size_t req_size,
size_t resp_size);
-int ipmi_sync_queue_msg(struct ipmi_msg *msg);
+/* Add an ipmi message to the queue */
+int ipmi_queue_msg(struct ipmi_msg *msg);
/* Process a completed message */
void ipmi_cmd_done(struct ipmi_msg *msg);