diff options
Diffstat (limited to 'arch/arm/mach-apple/rtkit.c')
-rw-r--r-- | arch/arm/mach-apple/rtkit.c | 234 |
1 files changed, 182 insertions, 52 deletions
diff --git a/arch/arm/mach-apple/rtkit.c b/arch/arm/mach-apple/rtkit.c index b8f4771e5e7..f3561543a35 100644 --- a/arch/arm/mach-apple/rtkit.c +++ b/arch/arm/mach-apple/rtkit.c @@ -11,6 +11,7 @@ #include <linux/apple-mailbox.h> #include <linux/bitfield.h> #include <linux/errno.h> +#include <linux/sizes.h> #include <linux/types.h> #define APPLE_RTKIT_EP_MGMT 0 @@ -18,6 +19,7 @@ #define APPLE_RTKIT_EP_SYSLOG 2 #define APPLE_RTKIT_EP_DEBUG 3 #define APPLE_RTKIT_EP_IOREPORT 4 +#define APPLE_RTKIT_EP_OSLOG 8 #define APPLE_RTKIT_EP_TRACEKIT 10 /* Messages for management endpoint. */ @@ -36,6 +38,7 @@ #define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6 #define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK 7 +#define APPLE_RTKIT_MGMT_SET_AP_PWR_STATE 11 #define APPLE_RTKIT_MGMT_EPMAP 8 #define APPLE_RTKIT_MGMT_EPMAP_LAST BIT(51) @@ -45,6 +48,11 @@ #define APPLE_RTKIT_MGMT_EPMAP_REPLY 8 #define APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE BIT(0) +#define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56) +#define APPLE_RTKIT_OSLOG_BUFFER_REQUEST 1 +#define APPLE_RTKIT_OSLOG_SIZE GENMASK_ULL(55, 36) +#define APPLE_RTKIT_OSLOG_IOVA GENMASK_ULL(35, 0) + #define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11 #define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12 @@ -64,6 +72,10 @@ struct apple_rtkit { struct apple_rtkit_buffer syslog_buffer; struct apple_rtkit_buffer crashlog_buffer; struct apple_rtkit_buffer ioreport_buffer; + struct apple_rtkit_buffer oslog_buffer; + + int iop_pwr; + int ap_pwr; }; struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie, @@ -93,6 +105,17 @@ void apple_rtkit_free(struct apple_rtkit *rtk) rtk->shmem_destroy(rtk->cookie, &rtk->crashlog_buffer); if (rtk->ioreport_buffer.buffer) rtk->shmem_destroy(rtk->cookie, &rtk->ioreport_buffer); + if (rtk->oslog_buffer.buffer) + rtk->shmem_destroy(rtk->cookie, &rtk->oslog_buffer); + } else { + if (rtk->syslog_buffer.buffer) + free(rtk->syslog_buffer.buffer); + if (rtk->crashlog_buffer.buffer) + free(rtk->crashlog_buffer.buffer); + if (rtk->ioreport_buffer.buffer) + free(rtk->ioreport_buffer.buffer); + if (rtk->oslog_buffer.buffer) + free(rtk->oslog_buffer.buffer); } free(rtk); } @@ -100,16 +123,8 @@ void apple_rtkit_free(struct apple_rtkit *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; @@ -120,14 +135,33 @@ static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct ap case APPLE_RTKIT_EP_IOREPORT: buf = &rtk->ioreport_buffer; break; + case APPLE_RTKIT_EP_OSLOG: + buf = &rtk->oslog_buffer; + break; default: printf("%s: unexpected endpoint %d\n", __func__, endpoint); return -1; } + switch (endpoint) { + case APPLE_RTKIT_EP_OSLOG: + buf->size = FIELD_GET(APPLE_RTKIT_OSLOG_SIZE, msg->msg0); + buf->dva = FIELD_GET(APPLE_RTKIT_OSLOG_IOVA, msg->msg0 << 12); + break; + default: + buf->size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg->msg0) << 12; + buf->dva = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg->msg0); + break; + } + + if (buf->size == 0) { + printf("%s: unexpected request for buffer without size\n", __func__); + return -1; + } + buf->dva = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg->msg0); - buf->size = num_4kpages << 12; - buf->is_mapped = false; + buf->is_mapped = !!buf->dva; + buf->endpoint = endpoint; if (rtk->shmem_setup) { ret = rtk->shmem_setup(rtk->cookie, buf); @@ -136,13 +170,27 @@ static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct ap endpoint); return ret; } + } else if (!buf->is_mapped){ + buf->buffer = memalign(SZ_16K, ALIGN(buf->size, SZ_16K)); + if (!buf->buffer) + return -ENOMEM; + + buf->dva = (u64)buf->buffer; } 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; + /* oslog uses different fields */ + if (endpoint == APPLE_RTKIT_EP_OSLOG) { + msg->msg0 = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, + APPLE_RTKIT_OSLOG_BUFFER_REQUEST); + msg->msg0 |= FIELD_PREP(APPLE_RTKIT_OSLOG_SIZE, buf->size); + msg->msg0 |= FIELD_PREP(APPLE_RTKIT_OSLOG_IOVA, buf->dva >> 12); + } else { + msg->msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, + APPLE_RTKIT_BUFFER_REQUEST); + msg->msg0 |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, buf->size >> 12); + msg->msg0 |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, buf->dva); + } return mbox_send(rtk->chan, msg); } @@ -150,6 +198,89 @@ static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct ap return 0; } +int apple_rtkit_poll(struct apple_rtkit *rtk, ulong timeout) +{ + struct apple_mbox_msg msg; + int ret; + int endpoint; + int msgtype; + + ret = mbox_recv(rtk->chan, &msg, timeout); + if (ret < 0) + return ret; + + endpoint = msg.msg1; + msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0); + + if (endpoint == APPLE_RTKIT_EP_CRASHLOG || + endpoint == APPLE_RTKIT_EP_SYSLOG || + endpoint == APPLE_RTKIT_EP_IOREPORT) { + if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) { + ret = rtkit_handle_buf_req(rtk, endpoint, &msg); + if (ret < 0) + return ret; + return 0; + } + } + + if (endpoint == APPLE_RTKIT_EP_OSLOG) { + msgtype = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg.msg0); + + if (msgtype == APPLE_RTKIT_OSLOG_BUFFER_REQUEST) { + ret = rtkit_handle_buf_req(rtk, endpoint, &msg); + if (ret < 0) + return ret; + return 0; + } else { + /* Ignore */ + return 0; + } + } + + 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; + return 0; + } + } + + if (endpoint == APPLE_RTKIT_EP_SYSLOG) { + /* Ignore init */ + if (msgtype == 0x8) + return 0; + + /* Ack logs */ + if (msgtype == 0x5) { + ret = mbox_send(rtk->chan, &msg); + if (ret < 0) + return ret; + return 0; + } + } + + if (endpoint != APPLE_RTKIT_EP_MGMT) { + printf("%s: unexpected endpoint %d\n", __func__, endpoint); + return -EINVAL; + } + + switch (msgtype) { + case APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK: + rtk->iop_pwr = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0); + return 0; + case APPLE_RTKIT_MGMT_SET_AP_PWR_STATE: + rtk->ap_pwr = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0); + return 0; + default: + printf("%s: unexpected message type %d\n", __func__, msgtype); + + /* Just ignore it */ + return 0; + } +} + int apple_rtkit_boot(struct apple_rtkit *rtk) { struct apple_mbox_msg msg; @@ -157,7 +288,7 @@ int apple_rtkit_boot(struct apple_rtkit *rtk) int nendpoints = 0; int endpoint; int min_ver, max_ver, want_ver; - int msgtype, pwrstate; + int msgtype; u64 reply; u32 bitmap, base; int i, ret; @@ -276,46 +407,37 @@ wait_epmap: return ret; } - pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP; - while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) { - ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); + rtk->iop_pwr = APPLE_RTKIT_PWR_STATE_SLEEP; + rtk->ap_pwr = APPLE_RTKIT_PWR_STATE_QUIESCED; + + while (rtk->iop_pwr != APPLE_RTKIT_PWR_STATE_ON) { + ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US); if (ret < 0) return ret; + } - endpoint = msg.msg1; - msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0); - - if (endpoint == APPLE_RTKIT_EP_CRASHLOG || - endpoint == APPLE_RTKIT_EP_SYSLOG || - endpoint == APPLE_RTKIT_EP_IOREPORT) { - if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) { - ret = rtkit_handle_buf_req(rtk, endpoint, &msg); - if (ret < 0) - return ret; - continue; - } - } + return 0; +} - 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; - } - } +int apple_rtkit_set_ap_power(struct apple_rtkit *rtk, int pwrstate) +{ + struct apple_mbox_msg msg; + int ret; - if (endpoint != APPLE_RTKIT_EP_MGMT) { - printf("%s: unexpected endpoint %d\n", __func__, endpoint); - return -EINVAL; - } - if (msgtype != APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK) { - printf("%s: unexpected message type %d\n", __func__, msgtype); - return -EINVAL; - } + if (rtk->ap_pwr == pwrstate) + return 0; - pwrstate = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0); + msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_AP_PWR_STATE) | + FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate); + msg.msg1 = APPLE_RTKIT_EP_MGMT; + ret = mbox_send(rtk->chan, &msg); + if (ret < 0) + return ret; + + while (rtk->ap_pwr != pwrstate) { + ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US); + if (ret < 0) + return ret; } return 0; @@ -326,6 +448,12 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate) struct apple_mbox_msg msg; int ret; + if (rtk->ap_pwr != APPLE_RTKIT_PWR_STATE_QUIESCED) { + ret = apple_rtkit_set_ap_power(rtk, APPLE_RTKIT_PWR_STATE_QUIESCED); + if (ret < 0) + return ret; + } + 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; @@ -333,9 +461,11 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate) if (ret < 0) return ret; - ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); - if (ret < 0) - return ret; + while (rtk->iop_pwr != pwrstate) { + ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US); + if (ret < 0) + return ret; + } return 0; } |