aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorNeelesh Gupta <neelegup@linux.vnet.ibm.com>2015-03-07 10:34:16 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-10 14:18:29 +1100
commit963685d0a6318f161b27516b360898079c2b216e (patch)
tree646d22a3f87ce412fc7febe6145142ccb7a73f78 /hw
parent9fafe0668a06b5e9b87d5ebe5773bcbcde2cfe6c (diff)
downloadskiboot-963685d0a6318f161b27516b360898079c2b216e.zip
skiboot-963685d0a6318f161b27516b360898079c2b216e.tar.gz
skiboot-963685d0a6318f161b27516b360898079c2b216e.tar.bz2
fsp/rtc: Introduce the rtc write state machine
Similar to rtc read requests, have a state machine to handle the write transitions. Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com> Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/fsp/fsp-rtc.c118
1 files changed, 74 insertions, 44 deletions
diff --git a/hw/fsp/fsp-rtc.c b/hw/fsp/fsp-rtc.c
index 2c7a592..955521b 100644
--- a/hw/fsp/fsp-rtc.c
+++ b/hw/fsp/fsp-rtc.c
@@ -68,9 +68,10 @@ static enum {
} rtc_tod_state = RTC_TOD_INVALID;
/* State machine for getting an RTC request.
- * RTC_READ_NO_REQUEST -> RTC_READ_PENDING_REQUEST (one in flight)
- * RTC_READ_PENDING_REQUEST -> RTC_READ_REQUEST_AVAILABLE, when FSP responds
- * RTC_READ_REQUEST_AVAILABLE -> RTC_READ_NO_REQUEST,
+ * RTC_{READ/WRITE}_NO_REQUEST -> RTC_{READ/WRITE}_PENDING_REQUEST (one in flight)
+ * RTC_{READ/WRITE}_PENDING_REQUEST -> RTC_{READ/WRITE}_REQUEST_AVAILABLE,
+ * when FSP responds
+ * RTC_{READ/WRITE}_REQUEST_AVAILABLE -> RTC_{READ/WRITE}_NO_REQUEST,
* when OS retrieves it
*/
static enum {
@@ -79,7 +80,11 @@ static enum {
RTC_READ_REQUEST_AVAILABLE,
} rtc_read_request_state = RTC_READ_NO_REQUEST;
-static bool rtc_write_in_flight = false;
+static enum {
+ RTC_WRITE_NO_REQUEST,
+ RTC_WRITE_PENDING_REQUEST,
+ RTC_WRITE_REQUEST_AVAILABLE,
+} rtc_write_request_state = RTC_WRITE_NO_REQUEST;
static bool rtc_tod_cache_dirty = false;
@@ -200,9 +205,16 @@ static void fsp_rtc_process_read(struct fsp_msg *read_resp)
}
}
-static void opal_rtc_eval_events(void)
+static void opal_rtc_eval_events(bool read_write)
{
- bool request_available = (rtc_read_request_state == RTC_READ_REQUEST_AVAILABLE);
+ bool request_available;
+
+ if (read_write)
+ request_available = (rtc_read_request_state ==
+ RTC_READ_REQUEST_AVAILABLE);
+ else
+ request_available = (rtc_write_request_state ==
+ RTC_WRITE_REQUEST_AVAILABLE);
assert(lock_held_by_me(&rtc_lock));
opal_update_pending_evt(OPAL_EVENT_RTC,
@@ -214,12 +226,15 @@ static void fsp_rtc_req_complete(struct fsp_msg *msg)
lock(&rtc_lock);
prlog(PR_TRACE, "RTC completion %p\n", msg);
- if (fsp_msg_cmd(msg) == (FSP_CMD_READ_TOD & 0xffffff))
+ if (fsp_msg_cmd(msg) == (FSP_CMD_READ_TOD & 0xffffff)) {
fsp_rtc_process_read(msg->resp);
- else
- rtc_write_in_flight = false;
+ opal_rtc_eval_events(true);
+ } else {
+ assert(rtc_write_request_state == RTC_WRITE_PENDING_REQUEST);
+ rtc_write_request_state = RTC_WRITE_REQUEST_AVAILABLE;
+ opal_rtc_eval_events(false);
+ }
- opal_rtc_eval_events();
unlock(&rtc_lock);
fsp_freemsg(msg);
}
@@ -287,7 +302,7 @@ static int64_t fsp_opal_rtc_read(uint32_t *year_month_day,
prlog(PR_TRACE, "RTC read complete, state %d\n", rtc_tod_state);
rtc_read_request_state = RTC_READ_NO_REQUEST;
- opal_rtc_eval_events();
+ opal_rtc_eval_events(true);
if (rtc_tod_state == RTC_TOD_VALID) {
rtc_cache_get_datetime(year_month_day,
@@ -319,26 +334,15 @@ out:
return rc;
}
-static int64_t fsp_opal_rtc_write(uint32_t year_month_day,
- uint64_t hour_minute_second_millisecond)
+static int64_t fsp_rtc_send_write_request(uint32_t year_month_day,
+ uint64_t hour_minute_second_millisecond)
{
- struct fsp_msg *rtc_write_msg;
+ struct fsp_msg *msg;
uint32_t w0, w1, w2;
- int64_t rc;
struct tm tm;
- lock(&rtc_lock);
- if (rtc_tod_state == RTC_TOD_PERMANENT_ERROR) {
- rc = OPAL_HARDWARE;
- goto bail;
- }
-
- if (rtc_write_in_flight) {
- rc = OPAL_BUSY_EVENT;
- goto bail;
- }
-
- prlog(PR_TRACE, "Sending new write request...\n");
+ assert(lock_held_by_me(&rtc_lock));
+ assert(rtc_write_request_state == RTC_WRITE_NO_REQUEST);
/* Create a request and send it. Just like for read, we ignore
* the "millisecond" field which is probably supposed to be
@@ -348,31 +352,57 @@ static int64_t fsp_opal_rtc_write(uint32_t year_month_day,
w1 = (hour_minute_second_millisecond >> 32) & 0xffffff00;
w2 = 0;
- rtc_write_msg = fsp_mkmsg(FSP_CMD_WRITE_TOD, 3, w0, w1, w2);
- if (!rtc_write_msg) {
+ msg = fsp_mkmsg(FSP_CMD_WRITE_TOD, 3, w0, w1, w2);
+ if (!msg) {
prlog(PR_TRACE, " -> allocation failed !\n");
- rc = OPAL_INTERNAL_ERROR;
- goto bail;
+ return OPAL_INTERNAL_ERROR;
}
- prlog(PR_TRACE, " -> req at %p\n", rtc_write_msg);
+ prlog(PR_TRACE, " -> req at %p\n", msg);
if (fsp_in_reset) {
- datetime_to_tm(rtc_write_msg->data.words[0],
- (u64) rtc_write_msg->data.words[1] << 32, &tm);
+ datetime_to_tm(msg->data.words[0],
+ (u64) msg->data.words[1] << 32, &tm);
rtc_cache_update(&tm);
rtc_tod_cache_dirty = true;
- rc = OPAL_SUCCESS;
- fsp_freemsg(rtc_write_msg);
- goto bail;
- } else if (fsp_queue_msg(rtc_write_msg, fsp_rtc_req_complete)) {
+ fsp_freemsg(msg);
+ return OPAL_SUCCESS;
+ } else if (fsp_queue_msg(msg, fsp_rtc_req_complete)) {
prlog(PR_TRACE, " -> queueing failed !\n");
- rc = OPAL_INTERNAL_ERROR;
- fsp_freemsg(rtc_write_msg);
- goto bail;
+ fsp_freemsg(msg);
+ return OPAL_INTERNAL_ERROR;
}
- rc = OPAL_BUSY_EVENT;
- rtc_write_in_flight = true;
- bail:
+
+ rtc_write_request_state = RTC_WRITE_PENDING_REQUEST;
+
+ return OPAL_BUSY_EVENT;
+}
+
+static int64_t fsp_opal_rtc_write(uint32_t year_month_day,
+ uint64_t hour_minute_second_millisecond)
+{
+ int rc;
+
+ lock(&rtc_lock);
+ if (rtc_tod_state == RTC_TOD_PERMANENT_ERROR) {
+ rc = OPAL_HARDWARE;
+ goto out;
+ }
+
+ if (rtc_write_request_state == RTC_WRITE_NO_REQUEST) {
+ prlog(PR_TRACE, "Sending new RTC write request\n");
+ rc = fsp_rtc_send_write_request(year_month_day,
+ hour_minute_second_millisecond);
+ } else if (rtc_write_request_state == RTC_WRITE_PENDING_REQUEST) {
+ rc = OPAL_BUSY_EVENT;
+ } else {
+ assert(rtc_write_request_state == RTC_WRITE_REQUEST_AVAILABLE);
+ rtc_write_request_state = RTC_WRITE_NO_REQUEST;
+
+ opal_rtc_eval_events(false);
+ rc = OPAL_SUCCESS;
+ }
+
+out:
unlock(&rtc_lock);
return rc;
}