Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Driver for the Surface ACPI Notify (SAN) interface/shim.
  4 *
  5 * Translates communication from ACPI to Surface System Aggregator Module
  6 * (SSAM/SAM) requests and back, specifically SAM-over-SSH. Translates SSAM
  7 * events back to ACPI notifications. Allows handling of discrete GPU
  8 * notifications sent from ACPI via the SAN interface by providing them to any
  9 * registered external driver.
 10 *
 11 * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
 12 */
 13
 14#include <asm/unaligned.h>
 15#include <linux/acpi.h>
 16#include <linux/delay.h>
 17#include <linux/jiffies.h>
 18#include <linux/kernel.h>
 19#include <linux/module.h>
 20#include <linux/notifier.h>
 21#include <linux/platform_device.h>
 22#include <linux/rwsem.h>
 23
 24#include <linux/surface_aggregator/controller.h>
 25#include <linux/surface_acpi_notify.h>
 26
 27struct san_data {
 28	struct device *dev;
 29	struct ssam_controller *ctrl;
 30
 31	struct acpi_connection_info info;
 32
 33	struct ssam_event_notifier nf_bat;
 34	struct ssam_event_notifier nf_tmp;
 35};
 36
 37#define to_san_data(ptr, member) \
 38	container_of(ptr, struct san_data, member)
 39
 40static struct workqueue_struct *san_wq;
 41
 42/* -- dGPU notifier interface. ---------------------------------------------- */
 43
 44struct san_rqsg_if {
 45	struct rw_semaphore lock;
 46	struct device *dev;
 47	struct blocking_notifier_head nh;
 48};
 49
 50static struct san_rqsg_if san_rqsg_if = {
 51	.lock = __RWSEM_INITIALIZER(san_rqsg_if.lock),
 52	.dev = NULL,
 53	.nh = BLOCKING_NOTIFIER_INIT(san_rqsg_if.nh),
 54};
 55
 56static int san_set_rqsg_interface_device(struct device *dev)
 57{
 58	int status = 0;
 59
 60	down_write(&san_rqsg_if.lock);
 61	if (!san_rqsg_if.dev && dev)
 62		san_rqsg_if.dev = dev;
 63	else
 64		status = -EBUSY;
 65	up_write(&san_rqsg_if.lock);
 66
 67	return status;
 68}
 69
 70/**
 71 * san_client_link() - Link client as consumer to SAN device.
 72 * @client: The client to link.
 73 *
 74 * Sets up a device link between the provided client device as consumer and
 75 * the SAN device as provider. This function can be used to ensure that the
 76 * SAN interface has been set up and will be set up for as long as the driver
 77 * of the client device is bound. This guarantees that, during that time, all
 78 * dGPU events will be received by any registered notifier.
 79 *
 80 * The link will be automatically removed once the client device's driver is
 81 * unbound.
 82 *
 83 * Return: Returns zero on success, %-ENXIO if the SAN interface has not been
 84 * set up yet, and %-ENOMEM if device link creation failed.
 85 */
 86int san_client_link(struct device *client)
 87{
 88	const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;
 89	struct device_link *link;
 90
 91	down_read(&san_rqsg_if.lock);
 92
 93	if (!san_rqsg_if.dev) {
 94		up_read(&san_rqsg_if.lock);
 95		return -ENXIO;
 96	}
 97
 98	link = device_link_add(client, san_rqsg_if.dev, flags);
 99	if (!link) {
100		up_read(&san_rqsg_if.lock);
101		return -ENOMEM;
102	}
103
104	if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) {
105		up_read(&san_rqsg_if.lock);
106		return -ENXIO;
107	}
108
109	up_read(&san_rqsg_if.lock);
110	return 0;
111}
112EXPORT_SYMBOL_GPL(san_client_link);
113
114/**
115 * san_dgpu_notifier_register() - Register a SAN dGPU notifier.
116 * @nb: The notifier-block to register.
117 *
118 * Registers a SAN dGPU notifier, receiving any new SAN dGPU events sent from
119 * ACPI. The registered notifier will be called with &struct san_dgpu_event
120 * as notifier data and the command ID of that event as notifier action.
121 */
122int san_dgpu_notifier_register(struct notifier_block *nb)
123{
124	return blocking_notifier_chain_register(&san_rqsg_if.nh, nb);
125}
126EXPORT_SYMBOL_GPL(san_dgpu_notifier_register);
127
128/**
129 * san_dgpu_notifier_unregister() - Unregister a SAN dGPU notifier.
130 * @nb: The notifier-block to unregister.
131 */
132int san_dgpu_notifier_unregister(struct notifier_block *nb)
133{
134	return blocking_notifier_chain_unregister(&san_rqsg_if.nh, nb);
135}
136EXPORT_SYMBOL_GPL(san_dgpu_notifier_unregister);
137
138static int san_dgpu_notifier_call(struct san_dgpu_event *evt)
139{
140	int ret;
141
142	ret = blocking_notifier_call_chain(&san_rqsg_if.nh, evt->command, evt);
143	return notifier_to_errno(ret);
144}
145
146
147/* -- ACPI _DSM event relay. ------------------------------------------------ */
148
149#define SAN_DSM_REVISION	0
150
151/* 93b666c5-70c6-469f-a215-3d487c91ab3c */
152static const guid_t SAN_DSM_UUID =
153	GUID_INIT(0x93b666c5, 0x70c6, 0x469f, 0xa2, 0x15, 0x3d,
154		  0x48, 0x7c, 0x91, 0xab, 0x3c);
155
156enum san_dsm_event_fn {
157	SAN_DSM_EVENT_FN_BAT1_STAT = 0x03,
158	SAN_DSM_EVENT_FN_BAT1_INFO = 0x04,
159	SAN_DSM_EVENT_FN_ADP1_STAT = 0x05,
160	SAN_DSM_EVENT_FN_ADP1_INFO = 0x06,
161	SAN_DSM_EVENT_FN_BAT2_STAT = 0x07,
162	SAN_DSM_EVENT_FN_BAT2_INFO = 0x08,
163	SAN_DSM_EVENT_FN_THERMAL   = 0x09,
164	SAN_DSM_EVENT_FN_DPTF      = 0x0a,
165};
166
167enum sam_event_cid_bat {
168	SAM_EVENT_CID_BAT_BIX  = 0x15,
169	SAM_EVENT_CID_BAT_BST  = 0x16,
170	SAM_EVENT_CID_BAT_ADP  = 0x17,
171	SAM_EVENT_CID_BAT_PROT = 0x18,
172	SAM_EVENT_CID_BAT_DPTF = 0x4f,
173};
174
175enum sam_event_cid_tmp {
176	SAM_EVENT_CID_TMP_TRIP = 0x0b,
177};
178
179struct san_event_work {
180	struct delayed_work work;
181	struct device *dev;
182	struct ssam_event event;	/* must be last */
183};
184
185static int san_acpi_notify_event(struct device *dev, u64 func,
186				 union acpi_object *param)
187{
188	acpi_handle san = ACPI_HANDLE(dev);
189	union acpi_object *obj;
190	int status = 0;
191
192	if (!acpi_check_dsm(san, &SAN_DSM_UUID, SAN_DSM_REVISION, BIT_ULL(func)))
193		return 0;
194
195	dev_dbg(dev, "notify event %#04llx\n", func);
196
197	obj = acpi_evaluate_dsm_typed(san, &SAN_DSM_UUID, SAN_DSM_REVISION,
198				      func, param, ACPI_TYPE_BUFFER);
199	if (!obj)
200		return -EFAULT;
201
202	if (obj->buffer.length != 1 || obj->buffer.pointer[0] != 0) {
203		dev_err(dev, "got unexpected result from _DSM\n");
204		status = -EPROTO;
205	}
206
207	ACPI_FREE(obj);
208	return status;
209}
210
211static int san_evt_bat_adp(struct device *dev, const struct ssam_event *event)
212{
213	int status;
214
215	status = san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_ADP1_STAT, NULL);
216	if (status)
217		return status;
218
219	/*
220	 * Ensure that the battery states get updated correctly. When the
221	 * battery is fully charged and an adapter is plugged in, it sometimes
222	 * is not updated correctly, instead showing it as charging.
223	 * Explicitly trigger battery updates to fix this.
224	 */
225
226	status = san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_BAT1_STAT, NULL);
227	if (status)
228		return status;
229
230	return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_BAT2_STAT, NULL);
231}
232
233static int san_evt_bat_bix(struct device *dev, const struct ssam_event *event)
234{
235	enum san_dsm_event_fn fn;
236
237	if (event->instance_id == 0x02)
238		fn = SAN_DSM_EVENT_FN_BAT2_INFO;
239	else
240		fn = SAN_DSM_EVENT_FN_BAT1_INFO;
241
242	return san_acpi_notify_event(dev, fn, NULL);
243}
244
245static int san_evt_bat_bst(struct device *dev, const struct ssam_event *event)
246{
247	enum san_dsm_event_fn fn;
248
249	if (event->instance_id == 0x02)
250		fn = SAN_DSM_EVENT_FN_BAT2_STAT;
251	else
252		fn = SAN_DSM_EVENT_FN_BAT1_STAT;
253
254	return san_acpi_notify_event(dev, fn, NULL);
255}
256
257static int san_evt_bat_dptf(struct device *dev, const struct ssam_event *event)
258{
259	union acpi_object payload;
260
261	/*
262	 * The Surface ACPI expects a buffer and not a package. It specifically
263	 * checks for ObjectType (Arg3) == 0x03. This will cause a warning in
264	 * acpica/nsarguments.c, but that warning can be safely ignored.
265	 */
266	payload.type = ACPI_TYPE_BUFFER;
267	payload.buffer.length = event->length;
268	payload.buffer.pointer = (u8 *)&event->data[0];
269
270	return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_DPTF, &payload);
271}
272
273static unsigned long san_evt_bat_delay(u8 cid)
274{
275	switch (cid) {
276	case SAM_EVENT_CID_BAT_ADP:
277		/*
278		 * Wait for battery state to update before signaling adapter
279		 * change.
280		 */
281		return msecs_to_jiffies(5000);
282
283	case SAM_EVENT_CID_BAT_BST:
284		/* Ensure we do not miss anything important due to caching. */
285		return msecs_to_jiffies(2000);
286
287	default:
288		return 0;
289	}
290}
291
292static bool san_evt_bat(const struct ssam_event *event, struct device *dev)
293{
294	int status;
295
296	switch (event->command_id) {
297	case SAM_EVENT_CID_BAT_BIX:
298		status = san_evt_bat_bix(dev, event);
299		break;
300
301	case SAM_EVENT_CID_BAT_BST:
302		status = san_evt_bat_bst(dev, event);
303		break;
304
305	case SAM_EVENT_CID_BAT_ADP:
306		status = san_evt_bat_adp(dev, event);
307		break;
308
309	case SAM_EVENT_CID_BAT_PROT:
310		/*
311		 * TODO: Implement support for battery protection status change
312		 *       event.
313		 */
314		return true;
315
316	case SAM_EVENT_CID_BAT_DPTF:
317		status = san_evt_bat_dptf(dev, event);
318		break;
319
320	default:
321		return false;
322	}
323
324	if (status) {
325		dev_err(dev, "error handling power event (cid = %#04x)\n",
326			event->command_id);
327	}
328
329	return true;
330}
331
332static void san_evt_bat_workfn(struct work_struct *work)
333{
334	struct san_event_work *ev;
335
336	ev = container_of(work, struct san_event_work, work.work);
337	san_evt_bat(&ev->event, ev->dev);
338	kfree(ev);
339}
340
341static u32 san_evt_bat_nf(struct ssam_event_notifier *nf,
342			  const struct ssam_event *event)
343{
344	struct san_data *d = to_san_data(nf, nf_bat);
345	struct san_event_work *work;
346	unsigned long delay = san_evt_bat_delay(event->command_id);
347
348	if (delay == 0)
349		return san_evt_bat(event, d->dev) ? SSAM_NOTIF_HANDLED : 0;
350
351	work = kzalloc(sizeof(*work) + event->length, GFP_KERNEL);
352	if (!work)
353		return ssam_notifier_from_errno(-ENOMEM);
354
355	INIT_DELAYED_WORK(&work->work, san_evt_bat_workfn);
356	work->dev = d->dev;
357
358	work->event = *event;
359	memcpy(work->event.data, event->data, event->length);
360
361	queue_delayed_work(san_wq, &work->work, delay);
362	return SSAM_NOTIF_HANDLED;
363}
364
365static int san_evt_tmp_trip(struct device *dev, const struct ssam_event *event)
366{
367	union acpi_object param;
368
369	/*
370	 * The Surface ACPI expects an integer and not a package. This will
371	 * cause a warning in acpica/nsarguments.c, but that warning can be
372	 * safely ignored.
373	 */
374	param.type = ACPI_TYPE_INTEGER;
375	param.integer.value = event->instance_id;
376
377	return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_THERMAL, &param);
378}
379
380static bool san_evt_tmp(const struct ssam_event *event, struct device *dev)
381{
382	int status;
383
384	switch (event->command_id) {
385	case SAM_EVENT_CID_TMP_TRIP:
386		status = san_evt_tmp_trip(dev, event);
387		break;
388
389	default:
390		return false;
391	}
392
393	if (status) {
394		dev_err(dev, "error handling thermal event (cid = %#04x)\n",
395			event->command_id);
396	}
397
398	return true;
399}
400
401static u32 san_evt_tmp_nf(struct ssam_event_notifier *nf,
402			  const struct ssam_event *event)
403{
404	struct san_data *d = to_san_data(nf, nf_tmp);
405
406	return san_evt_tmp(event, d->dev) ? SSAM_NOTIF_HANDLED : 0;
407}
408
409
410/* -- ACPI GSB OperationRegion handler -------------------------------------- */
411
412struct gsb_data_in {
413	u8 cv;
414} __packed;
415
416struct gsb_data_rqsx {
417	u8 cv;				/* Command value (san_gsb_request_cv). */
418	u8 tc;				/* Target category. */
419	u8 tid;				/* Target ID. */
420	u8 iid;				/* Instance ID. */
421	u8 snc;				/* Expect-response-flag. */
422	u8 cid;				/* Command ID. */
423	u16 cdl;			/* Payload length. */
424	u8 pld[];			/* Payload. */
425} __packed;
426
427struct gsb_data_etwl {
428	u8 cv;				/* Command value (should be 0x02). */
429	u8 etw3;			/* Unknown. */
430	u8 etw4;			/* Unknown. */
431	u8 msg[];			/* Error message (ASCIIZ). */
432} __packed;
433
434struct gsb_data_out {
435	u8 status;			/* _SSH communication status. */
436	u8 len;				/* _SSH payload length. */
437	u8 pld[];			/* _SSH payload. */
438} __packed;
439
440union gsb_buffer_data {
441	struct gsb_data_in   in;	/* Common input. */
442	struct gsb_data_rqsx rqsx;	/* RQSX input. */
443	struct gsb_data_etwl etwl;	/* ETWL input. */
444	struct gsb_data_out  out;	/* Output. */
445};
446
447struct gsb_buffer {
448	u8 status;			/* GSB AttribRawProcess status. */
449	u8 len;				/* GSB AttribRawProcess length. */
450	union gsb_buffer_data data;
451} __packed;
452
453#define SAN_GSB_MAX_RQSX_PAYLOAD  (U8_MAX - 2 - sizeof(struct gsb_data_rqsx))
454#define SAN_GSB_MAX_RESPONSE	  (U8_MAX - 2 - sizeof(struct gsb_data_out))
455
456#define SAN_GSB_COMMAND		0
457
458enum san_gsb_request_cv {
459	SAN_GSB_REQUEST_CV_RQST = 0x01,
460	SAN_GSB_REQUEST_CV_ETWL = 0x02,
461	SAN_GSB_REQUEST_CV_RQSG = 0x03,
462};
463
464#define SAN_REQUEST_NUM_TRIES	5
465
466static acpi_status san_etwl(struct san_data *d, struct gsb_buffer *b)
467{
468	struct gsb_data_etwl *etwl = &b->data.etwl;
469
470	if (b->len < sizeof(struct gsb_data_etwl)) {
471		dev_err(d->dev, "invalid ETWL package (len = %d)\n", b->len);
472		return AE_OK;
473	}
474
475	dev_err(d->dev, "ETWL(%#04x, %#04x): %.*s\n", etwl->etw3, etwl->etw4,
476		(unsigned int)(b->len - sizeof(struct gsb_data_etwl)),
477		(char *)etwl->msg);
478
479	/* Indicate success. */
480	b->status = 0x00;
481	b->len = 0x00;
482
483	return AE_OK;
484}
485
486static
487struct gsb_data_rqsx *san_validate_rqsx(struct device *dev, const char *type,
488					struct gsb_buffer *b)
489{
490	struct gsb_data_rqsx *rqsx = &b->data.rqsx;
491
492	if (b->len < sizeof(struct gsb_data_rqsx)) {
493		dev_err(dev, "invalid %s package (len = %d)\n", type, b->len);
494		return NULL;
495	}
496
497	if (get_unaligned(&rqsx->cdl) != b->len - sizeof(struct gsb_data_rqsx)) {
498		dev_err(dev, "bogus %s package (len = %d, cdl = %d)\n",
499			type, b->len, get_unaligned(&rqsx->cdl));
500		return NULL;
501	}
502
503	if (get_unaligned(&rqsx->cdl) > SAN_GSB_MAX_RQSX_PAYLOAD) {
504		dev_err(dev, "payload for %s package too large (cdl = %d)\n",
505			type, get_unaligned(&rqsx->cdl));
506		return NULL;
507	}
508
509	return rqsx;
510}
511
512static void gsb_rqsx_response_error(struct gsb_buffer *gsb, int status)
513{
514	gsb->status = 0x00;
515	gsb->len = 0x02;
516	gsb->data.out.status = (u8)(-status);
517	gsb->data.out.len = 0x00;
518}
519
520static void gsb_rqsx_response_success(struct gsb_buffer *gsb, u8 *ptr, size_t len)
521{
522	gsb->status = 0x00;
523	gsb->len = len + 2;
524	gsb->data.out.status = 0x00;
525	gsb->data.out.len = len;
526
527	if (len)
528		memcpy(&gsb->data.out.pld[0], ptr, len);
529}
530
531static acpi_status san_rqst_fixup_suspended(struct san_data *d,
532					    struct ssam_request *rqst,
533					    struct gsb_buffer *gsb)
534{
535	if (rqst->target_category == SSAM_SSH_TC_BAS && rqst->command_id == 0x0D) {
536		u8 base_state = 1;
537
538		/* Base state quirk:
539		 * The base state may be queried from ACPI when the EC is still
540		 * suspended. In this case it will return '-EPERM'. This query
541		 * will only be triggered from the ACPI lid GPE interrupt, thus
542		 * we are either in laptop or studio mode (base status 0x01 or
543		 * 0x02). Furthermore, we will only get here if the device (and
544		 * EC) have been suspended.
545		 *
546		 * We now assume that the device is in laptop mode (0x01). This
547		 * has the drawback that it will wake the device when unfolding
548		 * it in studio mode, but it also allows us to avoid actively
549		 * waiting for the EC to wake up, which may incur a notable
550		 * delay.
551		 */
552
553		dev_dbg(d->dev, "rqst: fixup: base-state quirk\n");
554
555		gsb_rqsx_response_success(gsb, &base_state, sizeof(base_state));
556		return AE_OK;
557	}
558
559	gsb_rqsx_response_error(gsb, -ENXIO);
560	return AE_OK;
561}
562
563static acpi_status san_rqst(struct san_data *d, struct gsb_buffer *buffer)
564{
565	u8 rspbuf[SAN_GSB_MAX_RESPONSE];
566	struct gsb_data_rqsx *gsb_rqst;
567	struct ssam_request rqst;
568	struct ssam_response rsp;
569	int status = 0;
570
571	gsb_rqst = san_validate_rqsx(d->dev, "RQST", buffer);
572	if (!gsb_rqst)
573		return AE_OK;
574
575	rqst.target_category = gsb_rqst->tc;
576	rqst.target_id = gsb_rqst->tid;
577	rqst.command_id = gsb_rqst->cid;
578	rqst.instance_id = gsb_rqst->iid;
579	rqst.flags = gsb_rqst->snc ? SSAM_REQUEST_HAS_RESPONSE : 0;
580	rqst.length = get_unaligned(&gsb_rqst->cdl);
581	rqst.payload = &gsb_rqst->pld[0];
582
583	rsp.capacity = ARRAY_SIZE(rspbuf);
584	rsp.length = 0;
585	rsp.pointer = &rspbuf[0];
586
587	/* Handle suspended device. */
588	if (d->dev->power.is_suspended) {
589		dev_warn(d->dev, "rqst: device is suspended, not executing\n");
590		return san_rqst_fixup_suspended(d, &rqst, buffer);
591	}
592
593	status = __ssam_retry(ssam_request_do_sync_onstack, SAN_REQUEST_NUM_TRIES,
594			      d->ctrl, &rqst, &rsp, SAN_GSB_MAX_RQSX_PAYLOAD);
595
596	if (!status) {
597		gsb_rqsx_response_success(buffer, rsp.pointer, rsp.length);
598	} else {
599		dev_err(d->dev, "rqst: failed with error %d\n", status);
600		gsb_rqsx_response_error(buffer, status);
601	}
602
603	return AE_OK;
604}
605
606static acpi_status san_rqsg(struct san_data *d, struct gsb_buffer *buffer)
607{
608	struct gsb_data_rqsx *gsb_rqsg;
609	struct san_dgpu_event evt;
610	int status;
611
612	gsb_rqsg = san_validate_rqsx(d->dev, "RQSG", buffer);
613	if (!gsb_rqsg)
614		return AE_OK;
615
616	evt.category = gsb_rqsg->tc;
617	evt.target = gsb_rqsg->tid;
618	evt.command = gsb_rqsg->cid;
619	evt.instance = gsb_rqsg->iid;
620	evt.length = get_unaligned(&gsb_rqsg->cdl);
621	evt.payload = &gsb_rqsg->pld[0];
622
623	status = san_dgpu_notifier_call(&evt);
624	if (!status) {
625		gsb_rqsx_response_success(buffer, NULL, 0);
626	} else {
627		dev_err(d->dev, "rqsg: failed with error %d\n", status);
628		gsb_rqsx_response_error(buffer, status);
629	}
630
631	return AE_OK;
632}
633
634static acpi_status san_opreg_handler(u32 function, acpi_physical_address command,
635				     u32 bits, u64 *value64, void *opreg_context,
636				     void *region_context)
637{
638	struct san_data *d = to_san_data(opreg_context, info);
639	struct gsb_buffer *buffer = (struct gsb_buffer *)value64;
640	int accessor_type = (function & 0xFFFF0000) >> 16;
641
642	if (command != SAN_GSB_COMMAND) {
643		dev_warn(d->dev, "unsupported command: %#04llx\n", command);
644		return AE_OK;
645	}
646
647	if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
648		dev_err(d->dev, "invalid access type: %#04x\n", accessor_type);
649		return AE_OK;
650	}
651
652	/* Buffer must have at least contain the command-value. */
653	if (buffer->len == 0) {
654		dev_err(d->dev, "request-package too small\n");
655		return AE_OK;
656	}
657
658	switch (buffer->data.in.cv) {
659	case SAN_GSB_REQUEST_CV_RQST:
660		return san_rqst(d, buffer);
661
662	case SAN_GSB_REQUEST_CV_ETWL:
663		return san_etwl(d, buffer);
664
665	case SAN_GSB_REQUEST_CV_RQSG:
666		return san_rqsg(d, buffer);
667
668	default:
669		dev_warn(d->dev, "unsupported SAN0 request (cv: %#04x)\n",
670			 buffer->data.in.cv);
671		return AE_OK;
672	}
673}
674
675
676/* -- Driver setup. --------------------------------------------------------- */
677
678static int san_events_register(struct platform_device *pdev)
679{
680	struct san_data *d = platform_get_drvdata(pdev);
681	int status;
682
683	d->nf_bat.base.priority = 1;
684	d->nf_bat.base.fn = san_evt_bat_nf;
685	d->nf_bat.event.reg = SSAM_EVENT_REGISTRY_SAM;
686	d->nf_bat.event.id.target_category = SSAM_SSH_TC_BAT;
687	d->nf_bat.event.id.instance = 0;
688	d->nf_bat.event.mask = SSAM_EVENT_MASK_TARGET;
689	d->nf_bat.event.flags = SSAM_EVENT_SEQUENCED;
690
691	d->nf_tmp.base.priority = 1;
692	d->nf_tmp.base.fn = san_evt_tmp_nf;
693	d->nf_tmp.event.reg = SSAM_EVENT_REGISTRY_SAM;
694	d->nf_tmp.event.id.target_category = SSAM_SSH_TC_TMP;
695	d->nf_tmp.event.id.instance = 0;
696	d->nf_tmp.event.mask = SSAM_EVENT_MASK_TARGET;
697	d->nf_tmp.event.flags = SSAM_EVENT_SEQUENCED;
698
699	status = ssam_notifier_register(d->ctrl, &d->nf_bat);
700	if (status)
701		return status;
702
703	status = ssam_notifier_register(d->ctrl, &d->nf_tmp);
704	if (status)
705		ssam_notifier_unregister(d->ctrl, &d->nf_bat);
706
707	return status;
708}
709
710static void san_events_unregister(struct platform_device *pdev)
711{
712	struct san_data *d = platform_get_drvdata(pdev);
713
714	ssam_notifier_unregister(d->ctrl, &d->nf_bat);
715	ssam_notifier_unregister(d->ctrl, &d->nf_tmp);
716}
717
718#define san_consumer_printk(level, dev, handle, fmt, ...)			\
719do {										\
720	char *path = "<error getting consumer path>";				\
721	struct acpi_buffer buffer = {						\
722		.length = ACPI_ALLOCATE_BUFFER,					\
723		.pointer = NULL,						\
724	};									\
725										\
726	if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))	\
727		path = buffer.pointer;						\
728										\
729	dev_##level(dev, "[%s]: " fmt, path, ##__VA_ARGS__);			\
730	kfree(buffer.pointer);							\
731} while (0)
732
733#define san_consumer_dbg(dev, handle, fmt, ...) \
734	san_consumer_printk(dbg, dev, handle, fmt, ##__VA_ARGS__)
735
736#define san_consumer_warn(dev, handle, fmt, ...) \
737	san_consumer_printk(warn, dev, handle, fmt, ##__VA_ARGS__)
738
739static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl,
740				      void *context, void **rv)
741{
742	const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER;
743	struct platform_device *pdev = context;
744	struct acpi_device *adev;
745	struct device_link *link;
746
747	if (!acpi_device_dep(handle, ACPI_HANDLE(&pdev->dev)))
748		return AE_OK;
749
750	/* Ignore ACPI devices that are not present. */
751	adev = acpi_fetch_acpi_dev(handle);
752	if (!adev)
753		return AE_OK;
754
755	san_consumer_dbg(&pdev->dev, handle, "creating device link\n");
756
757	/* Try to set up device links, ignore but log errors. */
758	link = device_link_add(&adev->dev, &pdev->dev, flags);
759	if (!link) {
760		san_consumer_warn(&pdev->dev, handle, "failed to create device link\n");
761		return AE_OK;
762	}
763
764	return AE_OK;
765}
766
767static int san_consumer_links_setup(struct platform_device *pdev)
768{
769	acpi_status status;
770
771	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
772				     ACPI_UINT32_MAX, san_consumer_setup, NULL,
773				     pdev, NULL);
774
775	return status ? -EFAULT : 0;
776}
777
778static int san_probe(struct platform_device *pdev)
779{
780	struct acpi_device *san = ACPI_COMPANION(&pdev->dev);
781	struct ssam_controller *ctrl;
782	struct san_data *data;
783	acpi_status astatus;
784	int status;
785
786	ctrl = ssam_client_bind(&pdev->dev);
787	if (IS_ERR(ctrl))
788		return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl);
789
790	status = san_consumer_links_setup(pdev);
791	if (status)
792		return status;
793
794	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
795	if (!data)
796		return -ENOMEM;
797
798	data->dev = &pdev->dev;
799	data->ctrl = ctrl;
800
801	platform_set_drvdata(pdev, data);
802
803	astatus = acpi_install_address_space_handler(san->handle,
804						     ACPI_ADR_SPACE_GSBUS,
805						     &san_opreg_handler, NULL,
806						     &data->info);
807	if (ACPI_FAILURE(astatus))
808		return -ENXIO;
809
810	status = san_events_register(pdev);
811	if (status)
812		goto err_enable_events;
813
814	status = san_set_rqsg_interface_device(&pdev->dev);
815	if (status)
816		goto err_install_dev;
817
818	acpi_dev_clear_dependencies(san);
819	return 0;
820
821err_install_dev:
822	san_events_unregister(pdev);
823err_enable_events:
824	acpi_remove_address_space_handler(san, ACPI_ADR_SPACE_GSBUS,
825					  &san_opreg_handler);
826	return status;
827}
828
829static void san_remove(struct platform_device *pdev)
830{
831	acpi_handle san = ACPI_HANDLE(&pdev->dev);
832
833	san_set_rqsg_interface_device(NULL);
834	acpi_remove_address_space_handler(san, ACPI_ADR_SPACE_GSBUS,
835					  &san_opreg_handler);
836	san_events_unregister(pdev);
837
838	/*
839	 * We have unregistered our event sources. Now we need to ensure that
840	 * all delayed works they may have spawned are run to completion.
841	 */
842	flush_workqueue(san_wq);
843}
844
845static const struct acpi_device_id san_match[] = {
846	{ "MSHW0091" },
847	{ },
848};
849MODULE_DEVICE_TABLE(acpi, san_match);
850
851static struct platform_driver surface_acpi_notify = {
852	.probe = san_probe,
853	.remove_new = san_remove,
854	.driver = {
855		.name = "surface_acpi_notify",
856		.acpi_match_table = san_match,
857		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
858	},
859};
860
861static int __init san_init(void)
862{
863	int ret;
864
865	san_wq = alloc_workqueue("san_wq", 0, 0);
866	if (!san_wq)
867		return -ENOMEM;
868	ret = platform_driver_register(&surface_acpi_notify);
869	if (ret)
870		destroy_workqueue(san_wq);
871	return ret;
872}
873module_init(san_init);
874
875static void __exit san_exit(void)
876{
877	platform_driver_unregister(&surface_acpi_notify);
878	destroy_workqueue(san_wq);
879}
880module_exit(san_exit);
881
882MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
883MODULE_DESCRIPTION("Surface ACPI Notify driver for Surface System Aggregator Module");
884MODULE_LICENSE("GPL");