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