927 lines · c
1// SPDX-License-Identifier: GPL-2.0-only OR MIT2/*3 * Apple RTKit IPC library4 * Copyright (C) The Asahi Linux Contributors5 */6 7#include "rtkit-internal.h"8 9enum {10 APPLE_RTKIT_PWR_STATE_OFF = 0x00, /* power off, cannot be restarted */11 APPLE_RTKIT_PWR_STATE_SLEEP = 0x01, /* sleeping, can be restarted */12 APPLE_RTKIT_PWR_STATE_IDLE = 0x201, /* sleeping, retain state */13 APPLE_RTKIT_PWR_STATE_QUIESCED = 0x10, /* running but no communication */14 APPLE_RTKIT_PWR_STATE_ON = 0x20, /* normal operating state */15};16 17enum {18 APPLE_RTKIT_EP_MGMT = 0,19 APPLE_RTKIT_EP_CRASHLOG = 1,20 APPLE_RTKIT_EP_SYSLOG = 2,21 APPLE_RTKIT_EP_DEBUG = 3,22 APPLE_RTKIT_EP_IOREPORT = 4,23 APPLE_RTKIT_EP_OSLOG = 8,24};25 26#define APPLE_RTKIT_MGMT_TYPE GENMASK_ULL(59, 52)27 28enum {29 APPLE_RTKIT_MGMT_HELLO = 1,30 APPLE_RTKIT_MGMT_HELLO_REPLY = 2,31 APPLE_RTKIT_MGMT_STARTEP = 5,32 APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE = 6,33 APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK = 7,34 APPLE_RTKIT_MGMT_EPMAP = 8,35 APPLE_RTKIT_MGMT_EPMAP_REPLY = 8,36 APPLE_RTKIT_MGMT_SET_AP_PWR_STATE = 0xb,37 APPLE_RTKIT_MGMT_SET_AP_PWR_STATE_ACK = 0xb,38};39 40#define APPLE_RTKIT_MGMT_HELLO_MINVER GENMASK_ULL(15, 0)41#define APPLE_RTKIT_MGMT_HELLO_MAXVER GENMASK_ULL(31, 16)42 43#define APPLE_RTKIT_MGMT_EPMAP_LAST BIT_ULL(51)44#define APPLE_RTKIT_MGMT_EPMAP_BASE GENMASK_ULL(34, 32)45#define APPLE_RTKIT_MGMT_EPMAP_BITMAP GENMASK_ULL(31, 0)46 47#define APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE BIT_ULL(0)48 49#define APPLE_RTKIT_MGMT_STARTEP_EP GENMASK_ULL(39, 32)50#define APPLE_RTKIT_MGMT_STARTEP_FLAG BIT_ULL(1)51 52#define APPLE_RTKIT_MGMT_PWR_STATE GENMASK_ULL(15, 0)53 54#define APPLE_RTKIT_CRASHLOG_CRASH 155 56#define APPLE_RTKIT_BUFFER_REQUEST 157#define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK_ULL(51, 44)58#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK_ULL(43, 0)59 60#define APPLE_RTKIT_SYSLOG_TYPE GENMASK_ULL(59, 52)61 62#define APPLE_RTKIT_SYSLOG_LOG 563 64#define APPLE_RTKIT_SYSLOG_INIT 865#define APPLE_RTKIT_SYSLOG_N_ENTRIES GENMASK_ULL(7, 0)66#define APPLE_RTKIT_SYSLOG_MSG_SIZE GENMASK_ULL(31, 24)67 68#define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56)69#define APPLE_RTKIT_OSLOG_INIT 170#define APPLE_RTKIT_OSLOG_ACK 371 72#define APPLE_RTKIT_MIN_SUPPORTED_VERSION 1173#define APPLE_RTKIT_MAX_SUPPORTED_VERSION 1274 75struct apple_rtkit_rx_work {76 struct apple_rtkit *rtk;77 u8 ep;78 u64 msg;79 struct work_struct work;80};81 82bool apple_rtkit_is_running(struct apple_rtkit *rtk)83{84 if (rtk->crashed)85 return false;86 if ((rtk->iop_power_state & 0xff) != APPLE_RTKIT_PWR_STATE_ON)87 return false;88 if ((rtk->ap_power_state & 0xff) != APPLE_RTKIT_PWR_STATE_ON)89 return false;90 return true;91}92EXPORT_SYMBOL_GPL(apple_rtkit_is_running);93 94bool apple_rtkit_is_crashed(struct apple_rtkit *rtk)95{96 return rtk->crashed;97}98EXPORT_SYMBOL_GPL(apple_rtkit_is_crashed);99 100static void apple_rtkit_management_send(struct apple_rtkit *rtk, u8 type,101 u64 msg)102{103 msg &= ~APPLE_RTKIT_MGMT_TYPE;104 msg |= FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, type);105 apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_MGMT, msg, NULL, false);106}107 108static void apple_rtkit_management_rx_hello(struct apple_rtkit *rtk, u64 msg)109{110 u64 reply;111 112 int min_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MINVER, msg);113 int max_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MAXVER, msg);114 int want_ver = min(APPLE_RTKIT_MAX_SUPPORTED_VERSION, max_ver);115 116 dev_dbg(rtk->dev, "RTKit: Min ver %d, max ver %d\n", min_ver, max_ver);117 118 if (min_ver > APPLE_RTKIT_MAX_SUPPORTED_VERSION) {119 dev_err(rtk->dev, "RTKit: Firmware min version %d is too new\n",120 min_ver);121 goto abort_boot;122 }123 124 if (max_ver < APPLE_RTKIT_MIN_SUPPORTED_VERSION) {125 dev_err(rtk->dev, "RTKit: Firmware max version %d is too old\n",126 max_ver);127 goto abort_boot;128 }129 130 dev_info(rtk->dev, "RTKit: Initializing (protocol version %d)\n",131 want_ver);132 rtk->version = want_ver;133 134 reply = FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MINVER, want_ver);135 reply |= FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MAXVER, want_ver);136 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_HELLO_REPLY, reply);137 138 return;139 140abort_boot:141 rtk->boot_result = -EINVAL;142 complete_all(&rtk->epmap_completion);143}144 145static void apple_rtkit_management_rx_epmap(struct apple_rtkit *rtk, u64 msg)146{147 int i, ep;148 u64 reply;149 unsigned long bitmap = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BITMAP, msg);150 u32 base = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BASE, msg);151 152 dev_dbg(rtk->dev,153 "RTKit: received endpoint bitmap 0x%lx with base 0x%x\n",154 bitmap, base);155 156 for_each_set_bit(i, &bitmap, 32) {157 ep = 32 * base + i;158 dev_dbg(rtk->dev, "RTKit: Discovered endpoint 0x%02x\n", ep);159 set_bit(ep, rtk->endpoints);160 }161 162 reply = FIELD_PREP(APPLE_RTKIT_MGMT_EPMAP_BASE, base);163 if (msg & APPLE_RTKIT_MGMT_EPMAP_LAST)164 reply |= APPLE_RTKIT_MGMT_EPMAP_LAST;165 else166 reply |= APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE;167 168 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_EPMAP_REPLY, reply);169 170 if (!(msg & APPLE_RTKIT_MGMT_EPMAP_LAST))171 return;172 173 for_each_set_bit(ep, rtk->endpoints, APPLE_RTKIT_APP_ENDPOINT_START) {174 switch (ep) {175 /* the management endpoint is started by default */176 case APPLE_RTKIT_EP_MGMT:177 break;178 179 /* without starting these RTKit refuses to boot */180 case APPLE_RTKIT_EP_SYSLOG:181 case APPLE_RTKIT_EP_CRASHLOG:182 case APPLE_RTKIT_EP_DEBUG:183 case APPLE_RTKIT_EP_IOREPORT:184 case APPLE_RTKIT_EP_OSLOG:185 dev_dbg(rtk->dev,186 "RTKit: Starting system endpoint 0x%02x\n", ep);187 apple_rtkit_start_ep(rtk, ep);188 break;189 190 default:191 dev_warn(rtk->dev,192 "RTKit: Unknown system endpoint: 0x%02x\n",193 ep);194 }195 }196 197 rtk->boot_result = 0;198 complete_all(&rtk->epmap_completion);199}200 201static void apple_rtkit_management_rx_iop_pwr_ack(struct apple_rtkit *rtk,202 u64 msg)203{204 unsigned int new_state = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg);205 206 dev_dbg(rtk->dev, "RTKit: IOP power state transition: 0x%x -> 0x%x\n",207 rtk->iop_power_state, new_state);208 rtk->iop_power_state = new_state;209 210 complete_all(&rtk->iop_pwr_ack_completion);211}212 213static void apple_rtkit_management_rx_ap_pwr_ack(struct apple_rtkit *rtk,214 u64 msg)215{216 unsigned int new_state = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg);217 218 dev_dbg(rtk->dev, "RTKit: AP power state transition: 0x%x -> 0x%x\n",219 rtk->ap_power_state, new_state);220 rtk->ap_power_state = new_state;221 222 complete_all(&rtk->ap_pwr_ack_completion);223}224 225static void apple_rtkit_management_rx(struct apple_rtkit *rtk, u64 msg)226{227 u8 type = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg);228 229 switch (type) {230 case APPLE_RTKIT_MGMT_HELLO:231 apple_rtkit_management_rx_hello(rtk, msg);232 break;233 case APPLE_RTKIT_MGMT_EPMAP:234 apple_rtkit_management_rx_epmap(rtk, msg);235 break;236 case APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK:237 apple_rtkit_management_rx_iop_pwr_ack(rtk, msg);238 break;239 case APPLE_RTKIT_MGMT_SET_AP_PWR_STATE_ACK:240 apple_rtkit_management_rx_ap_pwr_ack(rtk, msg);241 break;242 default:243 dev_warn(244 rtk->dev,245 "RTKit: unknown management message: 0x%llx (type: 0x%02x)\n",246 msg, type);247 }248}249 250static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk,251 struct apple_rtkit_shmem *buffer,252 u8 ep, u64 msg)253{254 size_t n_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg);255 u64 reply;256 int err;257 258 buffer->buffer = NULL;259 buffer->iomem = NULL;260 buffer->is_mapped = false;261 buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg);262 buffer->size = n_4kpages << 12;263 264 dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n",265 buffer->size, &buffer->iova);266 267 if (buffer->iova &&268 (!rtk->ops->shmem_setup || !rtk->ops->shmem_destroy)) {269 err = -EINVAL;270 goto error;271 }272 273 if (rtk->ops->shmem_setup) {274 err = rtk->ops->shmem_setup(rtk->cookie, buffer);275 if (err)276 goto error;277 } else {278 buffer->buffer = dma_alloc_coherent(rtk->dev, buffer->size,279 &buffer->iova, GFP_KERNEL);280 if (!buffer->buffer) {281 err = -ENOMEM;282 goto error;283 }284 }285 286 if (!buffer->is_mapped) {287 reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE,288 APPLE_RTKIT_BUFFER_REQUEST);289 reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, n_4kpages);290 reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA,291 buffer->iova);292 apple_rtkit_send_message(rtk, ep, reply, NULL, false);293 }294 295 return 0;296 297error:298 buffer->buffer = NULL;299 buffer->iomem = NULL;300 buffer->iova = 0;301 buffer->size = 0;302 buffer->is_mapped = false;303 return err;304}305 306static void apple_rtkit_free_buffer(struct apple_rtkit *rtk,307 struct apple_rtkit_shmem *bfr)308{309 if (bfr->size == 0)310 return;311 312 if (rtk->ops->shmem_destroy)313 rtk->ops->shmem_destroy(rtk->cookie, bfr);314 else if (bfr->buffer)315 dma_free_coherent(rtk->dev, bfr->size, bfr->buffer, bfr->iova);316 317 bfr->buffer = NULL;318 bfr->iomem = NULL;319 bfr->iova = 0;320 bfr->size = 0;321 bfr->is_mapped = false;322}323 324static void apple_rtkit_memcpy(struct apple_rtkit *rtk, void *dst,325 struct apple_rtkit_shmem *bfr, size_t offset,326 size_t len)327{328 if (bfr->iomem)329 memcpy_fromio(dst, bfr->iomem + offset, len);330 else331 memcpy(dst, bfr->buffer + offset, len);332}333 334static void apple_rtkit_crashlog_rx(struct apple_rtkit *rtk, u64 msg)335{336 u8 type = FIELD_GET(APPLE_RTKIT_SYSLOG_TYPE, msg);337 u8 *bfr;338 339 if (type != APPLE_RTKIT_CRASHLOG_CRASH) {340 dev_warn(rtk->dev, "RTKit: Unknown crashlog message: %llx\n",341 msg);342 return;343 }344 345 if (!rtk->crashlog_buffer.size) {346 apple_rtkit_common_rx_get_buffer(rtk, &rtk->crashlog_buffer,347 APPLE_RTKIT_EP_CRASHLOG, msg);348 return;349 }350 351 dev_err(rtk->dev, "RTKit: co-processor has crashed\n");352 353 /*354 * create a shadow copy here to make sure the co-processor isn't able355 * to change the log while we're dumping it. this also ensures356 * the buffer is in normal memory and not iomem for e.g. the SMC357 */358 bfr = kzalloc(rtk->crashlog_buffer.size, GFP_KERNEL);359 if (bfr) {360 apple_rtkit_memcpy(rtk, bfr, &rtk->crashlog_buffer, 0,361 rtk->crashlog_buffer.size);362 apple_rtkit_crashlog_dump(rtk, bfr, rtk->crashlog_buffer.size);363 kfree(bfr);364 } else {365 dev_err(rtk->dev,366 "RTKit: Couldn't allocate crashlog shadow buffer\n");367 }368 369 rtk->crashed = true;370 if (rtk->ops->crashed)371 rtk->ops->crashed(rtk->cookie);372}373 374static void apple_rtkit_ioreport_rx(struct apple_rtkit *rtk, u64 msg)375{376 u8 type = FIELD_GET(APPLE_RTKIT_SYSLOG_TYPE, msg);377 378 switch (type) {379 case APPLE_RTKIT_BUFFER_REQUEST:380 apple_rtkit_common_rx_get_buffer(rtk, &rtk->ioreport_buffer,381 APPLE_RTKIT_EP_IOREPORT, msg);382 break;383 /* unknown, must be ACKed or the co-processor will hang */384 case 0x8:385 case 0xc:386 apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_IOREPORT, msg,387 NULL, false);388 break;389 default:390 dev_warn(rtk->dev, "RTKit: Unknown ioreport message: %llx\n",391 msg);392 }393}394 395static void apple_rtkit_syslog_rx_init(struct apple_rtkit *rtk, u64 msg)396{397 rtk->syslog_n_entries = FIELD_GET(APPLE_RTKIT_SYSLOG_N_ENTRIES, msg);398 rtk->syslog_msg_size = FIELD_GET(APPLE_RTKIT_SYSLOG_MSG_SIZE, msg);399 400 rtk->syslog_msg_buffer = kzalloc(rtk->syslog_msg_size, GFP_KERNEL);401 402 dev_dbg(rtk->dev,403 "RTKit: syslog initialized: entries: %zd, msg_size: %zd\n",404 rtk->syslog_n_entries, rtk->syslog_msg_size);405}406 407static bool should_crop_syslog_char(char c)408{409 return c == '\n' || c == '\r' || c == ' ' || c == '\0';410}411 412static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)413{414 u8 idx = msg & 0xff;415 char log_context[24];416 size_t entry_size = 0x20 + rtk->syslog_msg_size;417 int msglen;418 419 if (!rtk->syslog_msg_buffer) {420 dev_warn(421 rtk->dev,422 "RTKit: received syslog message but no syslog_msg_buffer\n");423 goto done;424 }425 if (!rtk->syslog_buffer.size) {426 dev_warn(427 rtk->dev,428 "RTKit: received syslog message but syslog_buffer.size is zero\n");429 goto done;430 }431 if (!rtk->syslog_buffer.buffer && !rtk->syslog_buffer.iomem) {432 dev_warn(433 rtk->dev,434 "RTKit: received syslog message but no syslog_buffer.buffer or syslog_buffer.iomem\n");435 goto done;436 }437 if (idx > rtk->syslog_n_entries) {438 dev_warn(rtk->dev, "RTKit: syslog index %d out of range\n",439 idx);440 goto done;441 }442 443 apple_rtkit_memcpy(rtk, log_context, &rtk->syslog_buffer,444 idx * entry_size + 8, sizeof(log_context));445 apple_rtkit_memcpy(rtk, rtk->syslog_msg_buffer, &rtk->syslog_buffer,446 idx * entry_size + 8 + sizeof(log_context),447 rtk->syslog_msg_size);448 449 log_context[sizeof(log_context) - 1] = 0;450 451 msglen = rtk->syslog_msg_size - 1;452 while (msglen > 0 &&453 should_crop_syslog_char(rtk->syslog_msg_buffer[msglen - 1]))454 msglen--;455 456 rtk->syslog_msg_buffer[msglen] = 0;457 dev_info(rtk->dev, "RTKit: syslog message: %s: %s\n", log_context,458 rtk->syslog_msg_buffer);459 460done:461 apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_SYSLOG, msg, NULL, false);462}463 464static void apple_rtkit_syslog_rx(struct apple_rtkit *rtk, u64 msg)465{466 u8 type = FIELD_GET(APPLE_RTKIT_SYSLOG_TYPE, msg);467 468 switch (type) {469 case APPLE_RTKIT_BUFFER_REQUEST:470 apple_rtkit_common_rx_get_buffer(rtk, &rtk->syslog_buffer,471 APPLE_RTKIT_EP_SYSLOG, msg);472 break;473 case APPLE_RTKIT_SYSLOG_INIT:474 apple_rtkit_syslog_rx_init(rtk, msg);475 break;476 case APPLE_RTKIT_SYSLOG_LOG:477 apple_rtkit_syslog_rx_log(rtk, msg);478 break;479 default:480 dev_warn(rtk->dev, "RTKit: Unknown syslog message: %llx\n",481 msg);482 }483}484 485static void apple_rtkit_oslog_rx_init(struct apple_rtkit *rtk, u64 msg)486{487 u64 ack;488 489 dev_dbg(rtk->dev, "RTKit: oslog init: msg: 0x%llx\n", msg);490 ack = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, APPLE_RTKIT_OSLOG_ACK);491 apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_OSLOG, ack, NULL, false);492}493 494static void apple_rtkit_oslog_rx(struct apple_rtkit *rtk, u64 msg)495{496 u8 type = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg);497 498 switch (type) {499 case APPLE_RTKIT_OSLOG_INIT:500 apple_rtkit_oslog_rx_init(rtk, msg);501 break;502 default:503 dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", msg);504 }505}506 507static void apple_rtkit_rx_work(struct work_struct *work)508{509 struct apple_rtkit_rx_work *rtk_work =510 container_of(work, struct apple_rtkit_rx_work, work);511 struct apple_rtkit *rtk = rtk_work->rtk;512 513 switch (rtk_work->ep) {514 case APPLE_RTKIT_EP_MGMT:515 apple_rtkit_management_rx(rtk, rtk_work->msg);516 break;517 case APPLE_RTKIT_EP_CRASHLOG:518 apple_rtkit_crashlog_rx(rtk, rtk_work->msg);519 break;520 case APPLE_RTKIT_EP_SYSLOG:521 apple_rtkit_syslog_rx(rtk, rtk_work->msg);522 break;523 case APPLE_RTKIT_EP_IOREPORT:524 apple_rtkit_ioreport_rx(rtk, rtk_work->msg);525 break;526 case APPLE_RTKIT_EP_OSLOG:527 apple_rtkit_oslog_rx(rtk, rtk_work->msg);528 break;529 case APPLE_RTKIT_APP_ENDPOINT_START ... 0xff:530 if (rtk->ops->recv_message)531 rtk->ops->recv_message(rtk->cookie, rtk_work->ep,532 rtk_work->msg);533 else534 dev_warn(535 rtk->dev,536 "Received unexpected message to EP%02d: %llx\n",537 rtk_work->ep, rtk_work->msg);538 break;539 default:540 dev_warn(rtk->dev,541 "RTKit: message to unknown endpoint %02x: %llx\n",542 rtk_work->ep, rtk_work->msg);543 }544 545 kfree(rtk_work);546}547 548static void apple_rtkit_rx(struct apple_mbox *mbox, struct apple_mbox_msg msg,549 void *cookie)550{551 struct apple_rtkit *rtk = cookie;552 struct apple_rtkit_rx_work *work;553 u8 ep = msg.msg1;554 555 /*556 * The message was read from a MMIO FIFO and we have to make557 * sure all reads from buffers sent with that message happen558 * afterwards.559 */560 dma_rmb();561 562 if (!test_bit(ep, rtk->endpoints))563 dev_warn(rtk->dev,564 "RTKit: Message to undiscovered endpoint 0x%02x\n",565 ep);566 567 if (ep >= APPLE_RTKIT_APP_ENDPOINT_START &&568 rtk->ops->recv_message_early &&569 rtk->ops->recv_message_early(rtk->cookie, ep, msg.msg0))570 return;571 572 work = kzalloc(sizeof(*work), GFP_ATOMIC);573 if (!work)574 return;575 576 work->rtk = rtk;577 work->ep = ep;578 work->msg = msg.msg0;579 INIT_WORK(&work->work, apple_rtkit_rx_work);580 queue_work(rtk->wq, &work->work);581}582 583int apple_rtkit_send_message(struct apple_rtkit *rtk, u8 ep, u64 message,584 struct completion *completion, bool atomic)585{586 struct apple_mbox_msg msg = {587 .msg0 = message,588 .msg1 = ep,589 };590 591 if (rtk->crashed)592 return -EINVAL;593 if (ep >= APPLE_RTKIT_APP_ENDPOINT_START &&594 !apple_rtkit_is_running(rtk))595 return -EINVAL;596 597 /*598 * The message will be sent with a MMIO write. We need the barrier599 * here to ensure any previous writes to buffers are visible to the600 * device before that MMIO write happens.601 */602 dma_wmb();603 604 return apple_mbox_send(rtk->mbox, msg, atomic);605}606EXPORT_SYMBOL_GPL(apple_rtkit_send_message);607 608int apple_rtkit_poll(struct apple_rtkit *rtk)609{610 return apple_mbox_poll(rtk->mbox);611}612EXPORT_SYMBOL_GPL(apple_rtkit_poll);613 614int apple_rtkit_start_ep(struct apple_rtkit *rtk, u8 endpoint)615{616 u64 msg;617 618 if (!test_bit(endpoint, rtk->endpoints))619 return -EINVAL;620 if (endpoint >= APPLE_RTKIT_APP_ENDPOINT_START &&621 !apple_rtkit_is_running(rtk))622 return -EINVAL;623 624 msg = FIELD_PREP(APPLE_RTKIT_MGMT_STARTEP_EP, endpoint);625 msg |= APPLE_RTKIT_MGMT_STARTEP_FLAG;626 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_STARTEP, msg);627 628 return 0;629}630EXPORT_SYMBOL_GPL(apple_rtkit_start_ep);631 632struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,633 const char *mbox_name, int mbox_idx,634 const struct apple_rtkit_ops *ops)635{636 struct apple_rtkit *rtk;637 int ret;638 639 if (!ops)640 return ERR_PTR(-EINVAL);641 642 rtk = kzalloc(sizeof(*rtk), GFP_KERNEL);643 if (!rtk)644 return ERR_PTR(-ENOMEM);645 646 rtk->dev = dev;647 rtk->cookie = cookie;648 rtk->ops = ops;649 650 init_completion(&rtk->epmap_completion);651 init_completion(&rtk->iop_pwr_ack_completion);652 init_completion(&rtk->ap_pwr_ack_completion);653 654 bitmap_zero(rtk->endpoints, APPLE_RTKIT_MAX_ENDPOINTS);655 set_bit(APPLE_RTKIT_EP_MGMT, rtk->endpoints);656 657 if (mbox_name)658 rtk->mbox = apple_mbox_get_byname(dev, mbox_name);659 else660 rtk->mbox = apple_mbox_get(dev, mbox_idx);661 662 if (IS_ERR(rtk->mbox)) {663 ret = PTR_ERR(rtk->mbox);664 goto free_rtk;665 }666 667 rtk->mbox->rx = apple_rtkit_rx;668 rtk->mbox->cookie = rtk;669 670 rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_MEM_RECLAIM,671 dev_name(rtk->dev));672 if (!rtk->wq) {673 ret = -ENOMEM;674 goto free_rtk;675 }676 677 ret = apple_mbox_start(rtk->mbox);678 if (ret)679 goto destroy_wq;680 681 return rtk;682 683destroy_wq:684 destroy_workqueue(rtk->wq);685free_rtk:686 kfree(rtk);687 return ERR_PTR(ret);688}689EXPORT_SYMBOL_GPL(apple_rtkit_init);690 691static int apple_rtkit_wait_for_completion(struct completion *c)692{693 long t;694 695 t = wait_for_completion_interruptible_timeout(c,696 msecs_to_jiffies(1000));697 if (t < 0)698 return t;699 else if (t == 0)700 return -ETIME;701 else702 return 0;703}704 705int apple_rtkit_reinit(struct apple_rtkit *rtk)706{707 /* make sure we don't handle any messages while reinitializing */708 apple_mbox_stop(rtk->mbox);709 flush_workqueue(rtk->wq);710 711 apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);712 apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);713 apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);714 715 kfree(rtk->syslog_msg_buffer);716 717 rtk->syslog_msg_buffer = NULL;718 rtk->syslog_n_entries = 0;719 rtk->syslog_msg_size = 0;720 721 bitmap_zero(rtk->endpoints, APPLE_RTKIT_MAX_ENDPOINTS);722 set_bit(APPLE_RTKIT_EP_MGMT, rtk->endpoints);723 724 reinit_completion(&rtk->epmap_completion);725 reinit_completion(&rtk->iop_pwr_ack_completion);726 reinit_completion(&rtk->ap_pwr_ack_completion);727 728 rtk->crashed = false;729 rtk->iop_power_state = APPLE_RTKIT_PWR_STATE_OFF;730 rtk->ap_power_state = APPLE_RTKIT_PWR_STATE_OFF;731 732 return apple_mbox_start(rtk->mbox);733}734EXPORT_SYMBOL_GPL(apple_rtkit_reinit);735 736static int apple_rtkit_set_ap_power_state(struct apple_rtkit *rtk,737 unsigned int state)738{739 u64 msg;740 int ret;741 742 reinit_completion(&rtk->ap_pwr_ack_completion);743 744 msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, state);745 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_AP_PWR_STATE,746 msg);747 748 ret = apple_rtkit_wait_for_completion(&rtk->ap_pwr_ack_completion);749 if (ret)750 return ret;751 752 if (rtk->ap_power_state != state)753 return -EINVAL;754 return 0;755}756 757static int apple_rtkit_set_iop_power_state(struct apple_rtkit *rtk,758 unsigned int state)759{760 u64 msg;761 int ret;762 763 reinit_completion(&rtk->iop_pwr_ack_completion);764 765 msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, state);766 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,767 msg);768 769 ret = apple_rtkit_wait_for_completion(&rtk->iop_pwr_ack_completion);770 if (ret)771 return ret;772 773 if (rtk->iop_power_state != state)774 return -EINVAL;775 return 0;776}777 778int apple_rtkit_boot(struct apple_rtkit *rtk)779{780 int ret;781 782 if (apple_rtkit_is_running(rtk))783 return 0;784 if (rtk->crashed)785 return -EINVAL;786 787 dev_dbg(rtk->dev, "RTKit: waiting for boot to finish\n");788 ret = apple_rtkit_wait_for_completion(&rtk->epmap_completion);789 if (ret)790 return ret;791 if (rtk->boot_result)792 return rtk->boot_result;793 794 dev_dbg(rtk->dev, "RTKit: waiting for IOP power state ACK\n");795 ret = apple_rtkit_wait_for_completion(&rtk->iop_pwr_ack_completion);796 if (ret)797 return ret;798 799 return apple_rtkit_set_ap_power_state(rtk, APPLE_RTKIT_PWR_STATE_ON);800}801EXPORT_SYMBOL_GPL(apple_rtkit_boot);802 803int apple_rtkit_shutdown(struct apple_rtkit *rtk)804{805 int ret;806 807 /* if OFF is used here the co-processor will not wake up again */808 ret = apple_rtkit_set_ap_power_state(rtk,809 APPLE_RTKIT_PWR_STATE_QUIESCED);810 if (ret)811 return ret;812 813 ret = apple_rtkit_set_iop_power_state(rtk, APPLE_RTKIT_PWR_STATE_SLEEP);814 if (ret)815 return ret;816 817 return apple_rtkit_reinit(rtk);818}819EXPORT_SYMBOL_GPL(apple_rtkit_shutdown);820 821int apple_rtkit_idle(struct apple_rtkit *rtk)822{823 int ret;824 825 /* if OFF is used here the co-processor will not wake up again */826 ret = apple_rtkit_set_ap_power_state(rtk,827 APPLE_RTKIT_PWR_STATE_IDLE);828 if (ret)829 return ret;830 831 ret = apple_rtkit_set_iop_power_state(rtk, APPLE_RTKIT_PWR_STATE_IDLE);832 if (ret)833 return ret;834 835 rtk->iop_power_state = APPLE_RTKIT_PWR_STATE_IDLE;836 rtk->ap_power_state = APPLE_RTKIT_PWR_STATE_IDLE;837 return 0;838}839EXPORT_SYMBOL_GPL(apple_rtkit_idle);840 841int apple_rtkit_quiesce(struct apple_rtkit *rtk)842{843 int ret;844 845 ret = apple_rtkit_set_ap_power_state(rtk,846 APPLE_RTKIT_PWR_STATE_QUIESCED);847 if (ret)848 return ret;849 850 ret = apple_rtkit_set_iop_power_state(rtk,851 APPLE_RTKIT_PWR_STATE_QUIESCED);852 if (ret)853 return ret;854 855 ret = apple_rtkit_reinit(rtk);856 if (ret)857 return ret;858 859 rtk->iop_power_state = APPLE_RTKIT_PWR_STATE_QUIESCED;860 rtk->ap_power_state = APPLE_RTKIT_PWR_STATE_QUIESCED;861 return 0;862}863EXPORT_SYMBOL_GPL(apple_rtkit_quiesce);864 865int apple_rtkit_wake(struct apple_rtkit *rtk)866{867 u64 msg;868 869 if (apple_rtkit_is_running(rtk))870 return -EINVAL;871 872 reinit_completion(&rtk->iop_pwr_ack_completion);873 874 /*875 * Use open-coded apple_rtkit_set_iop_power_state since apple_rtkit_boot876 * will wait for the completion anyway.877 */878 msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_ON);879 apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,880 msg);881 882 return apple_rtkit_boot(rtk);883}884EXPORT_SYMBOL_GPL(apple_rtkit_wake);885 886void apple_rtkit_free(struct apple_rtkit *rtk)887{888 apple_mbox_stop(rtk->mbox);889 destroy_workqueue(rtk->wq);890 891 apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);892 apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);893 apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);894 895 kfree(rtk->syslog_msg_buffer);896 kfree(rtk);897}898EXPORT_SYMBOL_GPL(apple_rtkit_free);899 900static void apple_rtkit_free_wrapper(void *data)901{902 apple_rtkit_free(data);903}904 905struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,906 const char *mbox_name, int mbox_idx,907 const struct apple_rtkit_ops *ops)908{909 struct apple_rtkit *rtk;910 int ret;911 912 rtk = apple_rtkit_init(dev, cookie, mbox_name, mbox_idx, ops);913 if (IS_ERR(rtk))914 return rtk;915 916 ret = devm_add_action_or_reset(dev, apple_rtkit_free_wrapper, rtk);917 if (ret)918 return ERR_PTR(ret);919 920 return rtk;921}922EXPORT_SYMBOL_GPL(devm_apple_rtkit_init);923 924MODULE_LICENSE("Dual MIT/GPL");925MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");926MODULE_DESCRIPTION("Apple RTKit driver");927