1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
4  *
5  * Main interface for the surface-aggregator bus, surface-aggregator client
6  * devices, and respective drivers building on top of the SSAM controller.
7  * Provides support for non-platform/non-ACPI SSAM clients via dedicated
8  * subsystem.
9  *
10  * Copyright (C) 2019-2021 Maximilian Luz <[email protected]>
11  */
12 
13 #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
14 #define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
15 
16 #include <linux/device.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/types.h>
19 
20 #include <linux/surface_aggregator/controller.h>
21 
22 
23 /* -- Surface System Aggregator Module bus. --------------------------------- */
24 
25 /**
26  * enum ssam_device_domain - SAM device domain.
27  * @SSAM_DOMAIN_VIRTUAL:   Virtual device.
28  * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
29  */
30 enum ssam_device_domain {
31 	SSAM_DOMAIN_VIRTUAL   = 0x00,
32 	SSAM_DOMAIN_SERIALHUB = 0x01,
33 };
34 
35 /**
36  * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
37  * @SSAM_VIRTUAL_TC_HUB: Device hub category.
38  */
39 enum ssam_virtual_tc {
40 	SSAM_VIRTUAL_TC_HUB = 0x00,
41 };
42 
43 /**
44  * struct ssam_device_uid - Unique identifier for SSAM device.
45  * @domain:   Domain of the device.
46  * @category: Target category of the device.
47  * @target:   Target ID of the device.
48  * @instance: Instance ID of the device.
49  * @function: Sub-function of the device. This field can be used to split a
50  *            single SAM device into multiple virtual subdevices to separate
51  *            different functionality of that device and allow one driver per
52  *            such functionality.
53  */
54 struct ssam_device_uid {
55 	u8 domain;
56 	u8 category;
57 	u8 target;
58 	u8 instance;
59 	u8 function;
60 };
61 
62 /*
63  * Special values for device matching.
64  *
65  * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
66  * SSAM_SDEV() exclusively. Specifically, they are used to initialize the
67  * match_flags member of the device ID structure. Do not use them directly
68  * with struct ssam_device_id or struct ssam_device_uid.
69  */
70 #define SSAM_ANY_TID		0xffff
71 #define SSAM_ANY_IID		0xffff
72 #define SSAM_ANY_FUN		0xffff
73 
74 /**
75  * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
76  * parameters.
77  * @d:   Domain of the device.
78  * @cat: Target category of the device.
79  * @tid: Target ID of the device.
80  * @iid: Instance ID of the device.
81  * @fun: Sub-function of the device.
82  *
83  * Initializes a &struct ssam_device_id with the given parameters. See &struct
84  * ssam_device_uid for details regarding the parameters. The special values
85  * %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be used to specify that
86  * matching should ignore target ID, instance ID, and/or sub-function,
87  * respectively. This macro initializes the ``match_flags`` field based on the
88  * given parameters.
89  *
90  * Note: The parameters @d and @cat must be valid &u8 values, the parameters
91  * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
92  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
93  * allowed.
94  */
95 #define SSAM_DEVICE(d, cat, tid, iid, fun)					\
96 	.match_flags = (((tid) != SSAM_ANY_TID) ? SSAM_MATCH_TARGET : 0)	\
97 		     | (((iid) != SSAM_ANY_IID) ? SSAM_MATCH_INSTANCE : 0)	\
98 		     | (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0),	\
99 	.domain   = d,								\
100 	.category = cat,							\
101 	.target   = __builtin_choose_expr((tid) != SSAM_ANY_TID, (tid), 0),	\
102 	.instance = __builtin_choose_expr((iid) != SSAM_ANY_IID, (iid), 0),	\
103 	.function = __builtin_choose_expr((fun) != SSAM_ANY_FUN, (fun), 0)
104 
105 /**
106  * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
107  * the given parameters.
108  * @cat: Target category of the device.
109  * @tid: Target ID of the device.
110  * @iid: Instance ID of the device.
111  * @fun: Sub-function of the device.
112  *
113  * Initializes a &struct ssam_device_id with the given parameters in the
114  * virtual domain. See &struct ssam_device_uid for details regarding the
115  * parameters. The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and
116  * %SSAM_ANY_FUN can be used to specify that matching should ignore target ID,
117  * instance ID, and/or sub-function, respectively. This macro initializes the
118  * ``match_flags`` field based on the given parameters.
119  *
120  * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
121  * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
122  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
123  * allowed.
124  */
125 #define SSAM_VDEV(cat, tid, iid, fun) \
126 	SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, tid, iid, fun)
127 
128 /**
129  * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
130  * with the given parameters.
131  * @cat: Target category of the device.
132  * @tid: Target ID of the device.
133  * @iid: Instance ID of the device.
134  * @fun: Sub-function of the device.
135  *
136  * Initializes a &struct ssam_device_id with the given parameters in the SSH
137  * domain. See &struct ssam_device_uid for details regarding the parameters.
138  * The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be
139  * used to specify that matching should ignore target ID, instance ID, and/or
140  * sub-function, respectively. This macro initializes the ``match_flags``
141  * field based on the given parameters.
142  *
143  * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
144  * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
145  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
146  * allowed.
147  */
148 #define SSAM_SDEV(cat, tid, iid, fun) \
149 	SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
150 
151 /*
152  * enum ssam_device_flags - Flags for SSAM client devices.
153  * @SSAM_DEVICE_HOT_REMOVED_BIT:
154  *	The device has been hot-removed. Further communication with it may time
155  *	out and should be avoided.
156  */
157 enum ssam_device_flags {
158 	SSAM_DEVICE_HOT_REMOVED_BIT = 0,
159 };
160 
161 /**
162  * struct ssam_device - SSAM client device.
163  * @dev:   Driver model representation of the device.
164  * @ctrl:  SSAM controller managing this device.
165  * @uid:   UID identifying the device.
166  * @flags: Device state flags, see &enum ssam_device_flags.
167  */
168 struct ssam_device {
169 	struct device dev;
170 	struct ssam_controller *ctrl;
171 
172 	struct ssam_device_uid uid;
173 
174 	unsigned long flags;
175 };
176 
177 /**
178  * struct ssam_device_driver - SSAM client device driver.
179  * @driver:      Base driver model structure.
180  * @match_table: Match table specifying which devices the driver should bind to.
181  * @probe:       Called when the driver is being bound to a device.
182  * @remove:      Called when the driver is being unbound from the device.
183  */
184 struct ssam_device_driver {
185 	struct device_driver driver;
186 
187 	const struct ssam_device_id *match_table;
188 
189 	int  (*probe)(struct ssam_device *sdev);
190 	void (*remove)(struct ssam_device *sdev);
191 };
192 
193 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
194 
195 extern struct bus_type ssam_bus_type;
196 extern const struct device_type ssam_device_type;
197 
198 /**
199  * is_ssam_device() - Check if the given device is a SSAM client device.
200  * @d: The device to test the type of.
201  *
202  * Return: Returns %true if the specified device is of type &struct
203  * ssam_device, i.e. the device type points to %ssam_device_type, and %false
204  * otherwise.
205  */
206 static inline bool is_ssam_device(struct device *d)
207 {
208 	return d->type == &ssam_device_type;
209 }
210 
211 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
212 
213 static inline bool is_ssam_device(struct device *d)
214 {
215 	return false;
216 }
217 
218 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
219 
220 /**
221  * to_ssam_device() - Casts the given device to a SSAM client device.
222  * @d: The device to cast.
223  *
224  * Casts the given &struct device to a &struct ssam_device. The caller has to
225  * ensure that the given device is actually enclosed in a &struct ssam_device,
226  * e.g. by calling is_ssam_device().
227  *
228  * Return: Returns a pointer to the &struct ssam_device wrapping the given
229  * device @d.
230  */
231 static inline struct ssam_device *to_ssam_device(struct device *d)
232 {
233 	return container_of(d, struct ssam_device, dev);
234 }
235 
236 /**
237  * to_ssam_device_driver() - Casts the given device driver to a SSAM client
238  * device driver.
239  * @d: The driver to cast.
240  *
241  * Casts the given &struct device_driver to a &struct ssam_device_driver. The
242  * caller has to ensure that the given driver is actually enclosed in a
243  * &struct ssam_device_driver.
244  *
245  * Return: Returns the pointer to the &struct ssam_device_driver wrapping the
246  * given device driver @d.
247  */
248 static inline
249 struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d)
250 {
251 	return container_of(d, struct ssam_device_driver, driver);
252 }
253 
254 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
255 						  const struct ssam_device_uid uid);
256 
257 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);
258 
259 const void *ssam_device_get_match_data(const struct ssam_device *dev);
260 
261 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
262 				      struct ssam_device_uid uid);
263 
264 int ssam_device_add(struct ssam_device *sdev);
265 void ssam_device_remove(struct ssam_device *sdev);
266 
267 /**
268  * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
269  * @sdev: The device to mark as hot-removed.
270  *
271  * Mark the device as having been hot-removed. This signals drivers using the
272  * device that communication with the device should be avoided and may lead to
273  * timeouts.
274  */
275 static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
276 {
277 	dev_dbg(&sdev->dev, "marking device as hot-removed\n");
278 	set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
279 }
280 
281 /**
282  * ssam_device_is_hot_removed() - Check if the given device has been
283  * hot-removed.
284  * @sdev: The device to check.
285  *
286  * Checks if the given device has been marked as hot-removed. See
287  * ssam_device_mark_hot_removed() for more details.
288  *
289  * Return: Returns ``true`` if the device has been marked as hot-removed.
290  */
291 static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
292 {
293 	return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
294 }
295 
296 /**
297  * ssam_device_get() - Increment reference count of SSAM client device.
298  * @sdev: The device to increment the reference count of.
299  *
300  * Increments the reference count of the given SSAM client device by
301  * incrementing the reference count of the enclosed &struct device via
302  * get_device().
303  *
304  * See ssam_device_put() for the counter-part of this function.
305  *
306  * Return: Returns the device provided as input.
307  */
308 static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
309 {
310 	return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
311 }
312 
313 /**
314  * ssam_device_put() - Decrement reference count of SSAM client device.
315  * @sdev: The device to decrement the reference count of.
316  *
317  * Decrements the reference count of the given SSAM client device by
318  * decrementing the reference count of the enclosed &struct device via
319  * put_device().
320  *
321  * See ssam_device_get() for the counter-part of this function.
322  */
323 static inline void ssam_device_put(struct ssam_device *sdev)
324 {
325 	if (sdev)
326 		put_device(&sdev->dev);
327 }
328 
329 /**
330  * ssam_device_get_drvdata() - Get driver-data of SSAM client device.
331  * @sdev: The device to get the driver-data from.
332  *
333  * Return: Returns the driver-data of the given device, previously set via
334  * ssam_device_set_drvdata().
335  */
336 static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
337 {
338 	return dev_get_drvdata(&sdev->dev);
339 }
340 
341 /**
342  * ssam_device_set_drvdata() - Set driver-data of SSAM client device.
343  * @sdev: The device to set the driver-data of.
344  * @data: The data to set the device's driver-data pointer to.
345  */
346 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
347 {
348 	dev_set_drvdata(&sdev->dev, data);
349 }
350 
351 int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
352 void ssam_device_driver_unregister(struct ssam_device_driver *d);
353 
354 /**
355  * ssam_device_driver_register() - Register a SSAM client device driver.
356  * @drv: The driver to register.
357  */
358 #define ssam_device_driver_register(drv) \
359 	__ssam_device_driver_register(drv, THIS_MODULE)
360 
361 /**
362  * module_ssam_device_driver() - Helper macro for SSAM device driver
363  * registration.
364  * @drv: The driver managed by this module.
365  *
366  * Helper macro to register a SSAM device driver via module_init() and
367  * module_exit(). This macro may only be used once per module and replaces the
368  * aforementioned definitions.
369  */
370 #define module_ssam_device_driver(drv)			\
371 	module_driver(drv, ssam_device_driver_register,	\
372 		      ssam_device_driver_unregister)
373 
374 
375 /* -- Helpers for controller and hub devices. ------------------------------- */
376 
377 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
378 void ssam_remove_clients(struct device *dev);
379 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
380 static inline void ssam_remove_clients(struct device *dev) {}
381 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
382 
383 
384 /* -- Helpers for client-device requests. ----------------------------------- */
385 
386 /**
387  * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM
388  * request function with neither argument nor return value.
389  * @name: Name of the generated function.
390  * @spec: Specification (&struct ssam_request_spec_md) defining the request.
391  *
392  * Defines a function executing the synchronous SAM request specified by
393  * @spec, with the request having neither argument nor return value. Device
394  * specifying parameters are not hard-coded, but instead are provided via the
395  * client device, specifically its UID, supplied when calling this function.
396  * The generated function takes care of setting up the request struct, buffer
397  * allocation, as well as execution of the request itself, returning once the
398  * request has been fully completed. The required transport buffer will be
399  * allocated on the stack.
400  *
401  * The generated function is defined as ``static int name(struct ssam_device
402  * *sdev)``, returning the status of the request, which is zero on success and
403  * negative on failure. The ``sdev`` parameter specifies both the target
404  * device of the request and by association the controller via which the
405  * request is sent.
406  *
407  * Refer to ssam_request_sync_onstack() for more details on the behavior of
408  * the generated function.
409  */
410 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...)			\
411 	SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec)		\
412 	static int name(struct ssam_device *sdev)			\
413 	{								\
414 		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
415 				    sdev->uid.instance);		\
416 	}
417 
418 /**
419  * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
420  * request function with argument.
421  * @name:  Name of the generated function.
422  * @atype: Type of the request's argument.
423  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
424  *
425  * Defines a function executing the synchronous SAM request specified by
426  * @spec, with the request taking an argument of type @atype and having no
427  * return value. Device specifying parameters are not hard-coded, but instead
428  * are provided via the client device, specifically its UID, supplied when
429  * calling this function. The generated function takes care of setting up the
430  * request struct, buffer allocation, as well as execution of the request
431  * itself, returning once the request has been fully completed. The required
432  * transport buffer will be allocated on the stack.
433  *
434  * The generated function is defined as ``static int name(struct ssam_device
435  * *sdev, const atype *arg)``, returning the status of the request, which is
436  * zero on success and negative on failure. The ``sdev`` parameter specifies
437  * both the target device of the request and by association the controller via
438  * which the request is sent. The request's argument is specified via the
439  * ``arg`` pointer.
440  *
441  * Refer to ssam_request_sync_onstack() for more details on the behavior of
442  * the generated function.
443  */
444 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...)		\
445 	SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec)	\
446 	static int name(struct ssam_device *sdev, const atype *arg)	\
447 	{								\
448 		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
449 				    sdev->uid.instance, arg);		\
450 	}
451 
452 /**
453  * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
454  * request function with return value.
455  * @name:  Name of the generated function.
456  * @rtype: Type of the request's return value.
457  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
458  *
459  * Defines a function executing the synchronous SAM request specified by
460  * @spec, with the request taking no argument but having a return value of
461  * type @rtype. Device specifying parameters are not hard-coded, but instead
462  * are provided via the client device, specifically its UID, supplied when
463  * calling this function. The generated function takes care of setting up the
464  * request struct, buffer allocation, as well as execution of the request
465  * itself, returning once the request has been fully completed. The required
466  * transport buffer will be allocated on the stack.
467  *
468  * The generated function is defined as ``static int name(struct ssam_device
469  * *sdev, rtype *ret)``, returning the status of the request, which is zero on
470  * success and negative on failure. The ``sdev`` parameter specifies both the
471  * target device of the request and by association the controller via which
472  * the request is sent. The request's return value is written to the memory
473  * pointed to by the ``ret`` parameter.
474  *
475  * Refer to ssam_request_sync_onstack() for more details on the behavior of
476  * the generated function.
477  */
478 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...)		\
479 	SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec)	\
480 	static int name(struct ssam_device *sdev, rtype *ret)		\
481 	{								\
482 		return __raw_##name(sdev->ctrl, sdev->uid.target,	\
483 				    sdev->uid.instance, ret);		\
484 	}
485 
486 /**
487  * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
488  * request function with argument and return value.
489  * @name:  Name of the generated function.
490  * @atype: Type of the request's argument.
491  * @rtype: Type of the request's return value.
492  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
493  *
494  * Defines a function executing the synchronous SAM request specified by @spec,
495  * with the request taking an argument of type @atype and having a return value
496  * of type @rtype. Device specifying parameters are not hard-coded, but instead
497  * are provided via the client device, specifically its UID, supplied when
498  * calling this function. The generated function takes care of setting up the
499  * request struct, buffer allocation, as well as execution of the request
500  * itself, returning once the request has been fully completed. The required
501  * transport buffer will be allocated on the stack.
502  *
503  * The generated function is defined as ``static int name(struct ssam_device
504  * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
505  * which is zero on success and negative on failure. The ``sdev`` parameter
506  * specifies both the target device of the request and by association the
507  * controller via which the request is sent. The request's argument is
508  * specified via the ``arg`` pointer. The request's return value is written to
509  * the memory pointed to by the ``ret`` parameter.
510  *
511  * Refer to ssam_request_sync_onstack() for more details on the behavior of
512  * the generated function.
513  */
514 #define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...)		\
515 	SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec)	\
516 	static int name(struct ssam_device *sdev, const atype *arg, rtype *ret)	\
517 	{									\
518 		return __raw_##name(sdev->ctrl, sdev->uid.target,		\
519 				    sdev->uid.instance, arg, ret);		\
520 	}
521 
522 
523 /* -- Helpers for client-device notifiers. ---------------------------------- */
524 
525 /**
526  * ssam_device_notifier_register() - Register an event notifier for the
527  * specified client device.
528  * @sdev: The device the notifier should be registered on.
529  * @n:    The event notifier to register.
530  *
531  * Register an event notifier. Increment the usage counter of the associated
532  * SAM event if the notifier is not marked as an observer. If the event is not
533  * marked as an observer and is currently not enabled, it will be enabled
534  * during this call. If the notifier is marked as an observer, no attempt will
535  * be made at enabling any event and no reference count will be modified.
536  *
537  * Notifiers marked as observers do not need to be associated with one specific
538  * event, i.e. as long as no event matching is performed, only the event target
539  * category needs to be set.
540  *
541  * Return: Returns zero on success, %-ENOSPC if there have already been
542  * %INT_MAX notifiers for the event ID/type associated with the notifier block
543  * registered, %-ENOMEM if the corresponding event entry could not be
544  * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
545  * first time that a notifier block is registered for the specific associated
546  * event, returns the status of the event-enable EC-command.
547  */
548 static inline int ssam_device_notifier_register(struct ssam_device *sdev,
549 						struct ssam_event_notifier *n)
550 {
551 	/*
552 	 * Note that this check does not provide any guarantees whatsoever as
553 	 * hot-removal could happen at any point and we can't protect against
554 	 * it. Nevertheless, if we can detect hot-removal, bail early to avoid
555 	 * communication timeouts.
556 	 */
557 	if (ssam_device_is_hot_removed(sdev))
558 		return -ENODEV;
559 
560 	return ssam_notifier_register(sdev->ctrl, n);
561 }
562 
563 /**
564  * ssam_device_notifier_unregister() - Unregister an event notifier for the
565  * specified client device.
566  * @sdev: The device the notifier has been registered on.
567  * @n:    The event notifier to unregister.
568  *
569  * Unregister an event notifier. Decrement the usage counter of the associated
570  * SAM event if the notifier is not marked as an observer. If the usage counter
571  * reaches zero, the event will be disabled.
572  *
573  * In case the device has been marked as hot-removed, the event will not be
574  * disabled on the EC, as in those cases any attempt at doing so may time out.
575  *
576  * Return: Returns zero on success, %-ENOENT if the given notifier block has
577  * not been registered on the controller. If the given notifier block was the
578  * last one associated with its specific event, returns the status of the
579  * event-disable EC-command.
580  */
581 static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
582 						  struct ssam_event_notifier *n)
583 {
584 	return __ssam_notifier_unregister(sdev->ctrl, n,
585 					  !ssam_device_is_hot_removed(sdev));
586 }
587 
588 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
589