diff options
Diffstat (limited to 'arch/arm/mach-apple/rtkit.c')
-rw-r--r-- | arch/arm/mach-apple/rtkit.c | 161 |
1 files changed, 135 insertions, 26 deletions
diff --git a/arch/arm/mach-apple/rtkit.c b/arch/arm/mach-apple/rtkit.c index 2dcb8bdd3e4..a550b553b66 100644 --- a/arch/arm/mach-apple/rtkit.c +++ b/arch/arm/mach-apple/rtkit.c @@ -17,6 +17,7 @@ #define APPLE_RTKIT_EP_SYSLOG 2 #define APPLE_RTKIT_EP_DEBUG 3 #define APPLE_RTKIT_EP_IOREPORT 4 +#define APPLE_RTKIT_EP_TRACEKIT 10 /* Messages for management endpoint. */ #define APPLE_RTKIT_MGMT_TYPE GENMASK(59, 52) @@ -51,7 +52,104 @@ #define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK(51, 44) #define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK(41, 0) -int apple_rtkit_init(struct mbox_chan *chan) +#define TIMEOUT_1SEC_US 1000000 + +struct apple_rtkit { + struct mbox_chan *chan; + void *cookie; + apple_rtkit_shmem_setup shmem_setup; + apple_rtkit_shmem_destroy shmem_destroy; + + struct apple_rtkit_buffer syslog_buffer; + struct apple_rtkit_buffer crashlog_buffer; + struct apple_rtkit_buffer ioreport_buffer; +}; + +struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie, + apple_rtkit_shmem_setup shmem_setup, + apple_rtkit_shmem_destroy shmem_destroy) +{ + struct apple_rtkit *rtk; + + rtk = calloc(sizeof(*rtk), 1); + if (!rtk) + return NULL; + + rtk->chan = chan; + rtk->cookie = cookie; + rtk->shmem_setup = shmem_setup; + rtk->shmem_destroy = shmem_destroy; + + return rtk; +} + +void apple_rtkit_free(struct apple_rtkit *rtk) +{ + if (rtk->shmem_destroy) { + if (rtk->syslog_buffer.buffer) + rtk->shmem_destroy(rtk->cookie, &rtk->syslog_buffer); + if (rtk->crashlog_buffer.buffer) + rtk->shmem_destroy(rtk->cookie, &rtk->crashlog_buffer); + if (rtk->ioreport_buffer.buffer) + rtk->shmem_destroy(rtk->cookie, &rtk->ioreport_buffer); + } + free(rtk); +} + +static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct apple_mbox_msg *msg) +{ + struct apple_rtkit_buffer *buf; + size_t num_4kpages; + int ret; + + num_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg->msg0); + + if (num_4kpages == 0) { + printf("%s: unexpected request for buffer without size\n", __func__); + return -1; + } + + switch (endpoint) { + case APPLE_RTKIT_EP_CRASHLOG: + buf = &rtk->crashlog_buffer; + break; + case APPLE_RTKIT_EP_SYSLOG: + buf = &rtk->syslog_buffer; + break; + case APPLE_RTKIT_EP_IOREPORT: + buf = &rtk->ioreport_buffer; + break; + default: + printf("%s: unexpected endpoint %d\n", __func__, endpoint); + return -1; + } + + buf->dva = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg->msg0); + buf->size = num_4kpages << 12; + buf->is_mapped = false; + + if (rtk->shmem_setup) { + ret = rtk->shmem_setup(rtk->cookie, buf); + if (ret < 0) { + printf("%s: shmen_setup failed for endpoint %d\n", __func__, + endpoint); + return ret; + } + } + + if (!buf->is_mapped) { + msg->msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_BUFFER_REQUEST) | + FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, num_4kpages) | + FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, buf->dva); + msg->msg1 = endpoint; + + return mbox_send(rtk->chan, msg); + } + + return 0; +} + +int apple_rtkit_boot(struct apple_rtkit *rtk) { struct apple_mbox_msg msg; int endpoints[256]; @@ -67,12 +165,12 @@ int apple_rtkit_init(struct mbox_chan *chan) msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) | FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_ON); msg.msg1 = APPLE_RTKIT_EP_MGMT; - ret = mbox_send(chan, &msg); + ret = mbox_send(rtk->chan, &msg); if (ret < 0) return ret; /* Wait for protocol version negotiation message. */ - ret = mbox_recv(chan, &msg, 10000); + ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); if (ret < 0) return ret; @@ -108,13 +206,13 @@ int apple_rtkit_init(struct mbox_chan *chan) FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MINVER, want_ver) | FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MAXVER, want_ver); msg.msg1 = APPLE_RTKIT_EP_MGMT; - ret = mbox_send(chan, &msg); + ret = mbox_send(rtk->chan, &msg); if (ret < 0) return ret; wait_epmap: /* Wait for endpoint map message. */ - ret = mbox_recv(chan, &msg, 10000); + ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); if (ret < 0) return ret; @@ -145,7 +243,7 @@ wait_epmap: reply |= APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE; msg.msg0 = reply; msg.msg1 = APPLE_RTKIT_EP_MGMT; - ret = mbox_send(chan, &msg); + ret = mbox_send(rtk->chan, &msg); if (ret < 0) return ret; @@ -153,24 +251,33 @@ wait_epmap: goto wait_epmap; for (i = 0; i < nendpoints; i++) { - /* Don't start the syslog endpoint since we can't - easily handle its messages in U-Boot. */ - if (endpoints[i] == APPLE_RTKIT_EP_SYSLOG) + /* Start only necessary endpoints. The syslog endpoint is + * particularly noisy and its message can't easily be handled + * within U-Boot. + */ + switch (endpoints[i]) { + case APPLE_RTKIT_EP_MGMT: + case APPLE_RTKIT_EP_SYSLOG: + case APPLE_RTKIT_EP_DEBUG: + case APPLE_RTKIT_EP_TRACEKIT: continue; + default: + break; + } /* Request endpoint. */ msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_STARTEP) | FIELD_PREP(APPLE_RTKIT_MGMT_STARTEP_EP, endpoints[i]) | APPLE_RTKIT_MGMT_STARTEP_FLAG; msg.msg1 = APPLE_RTKIT_EP_MGMT; - ret = mbox_send(chan, &msg); + ret = mbox_send(rtk->chan, &msg); if (ret < 0) return ret; } pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP; while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) { - ret = mbox_recv(chan, &msg, 1000000); + ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); if (ret < 0) return ret; @@ -180,20 +287,22 @@ wait_epmap: if (endpoint == APPLE_RTKIT_EP_CRASHLOG || endpoint == APPLE_RTKIT_EP_SYSLOG || endpoint == APPLE_RTKIT_EP_IOREPORT) { - u64 addr = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg.msg0); - u64 size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg.msg0); - - if (msgtype == APPLE_RTKIT_BUFFER_REQUEST && addr != 0) + if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) { + ret = rtkit_handle_buf_req(rtk, endpoint, &msg); + if (ret < 0) + return ret; continue; + } + } - msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_BUFFER_REQUEST) | - FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, size) | - FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, addr); - msg.msg1 = endpoint; - ret = mbox_send(chan, &msg); - if (ret < 0) - return ret; - continue; + if (endpoint == APPLE_RTKIT_EP_IOREPORT) { + // these two messages have to be ack-ed for proper startup + if (msgtype == 0xc || msgtype == 0x8) { + ret = mbox_send(rtk->chan, &msg); + if (ret < 0) + return ret; + continue; + } } if (endpoint != APPLE_RTKIT_EP_MGMT) { @@ -211,7 +320,7 @@ wait_epmap: return 0; } -int apple_rtkit_shutdown(struct mbox_chan *chan, int pwrstate) +int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate) { struct apple_mbox_msg msg; int ret; @@ -219,11 +328,11 @@ int apple_rtkit_shutdown(struct mbox_chan *chan, int pwrstate) msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) | FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate); msg.msg1 = APPLE_RTKIT_EP_MGMT; - ret = mbox_send(chan, &msg); + ret = mbox_send(rtk->chan, &msg); if (ret < 0) return ret; - ret = mbox_recv(chan, &msg, 100000); + ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); if (ret < 0) return ret; |