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 */
is_ssam_device(struct device * d)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
is_ssam_device(struct device * d)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 */
to_ssam_device(struct device * d)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
to_ssam_device_driver(struct device_driver * d)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 */
ssam_device_mark_hot_removed(struct ssam_device * sdev)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 */
ssam_device_is_hot_removed(struct ssam_device * sdev)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 */
ssam_device_get(struct ssam_device * sdev)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 */
ssam_device_put(struct ssam_device * sdev)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 */
ssam_device_get_drvdata(struct ssam_device * sdev)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 */
ssam_device_set_drvdata(struct ssam_device * sdev,void * data)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
__ssam_register_clients(struct device * parent,struct ssam_controller * ctrl,struct fwnode_handle * node)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
ssam_remove_clients(struct device * dev)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 */
ssam_register_clients(struct device * dev,struct ssam_controller * ctrl)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 */
ssam_device_register_clients(struct ssam_device * sdev)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 */
ssam_device_notifier_register(struct ssam_device * sdev,struct ssam_event_notifier * n)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 */
ssam_device_notifier_unregister(struct ssam_device * sdev,struct ssam_event_notifier * n)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