diff options
-rw-r--r-- | core/ipmi.c | 2 | ||||
-rw-r--r-- | hw/bt.c | 79 | ||||
-rw-r--r-- | hw/ipmi/ipmi-power.c | 2 | ||||
-rw-r--r-- | hw/ipmi/ipmi-rtc.c | 39 | ||||
-rw-r--r-- | include/ipmi.h | 3 |
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. */ @@ -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); |