brintos

brintos / linux-shallow public Read only

0
0
Text · 23.1 KiB · e6d9402 Raw
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