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_SSH_TID_ANY 0xffff |
72 | #define SSAM_SSH_IID_ANY 0xffff |
73 | #define SSAM_SSH_FUN_ANY 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_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and %SSAM_SSH_FUN_ANY 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_SSH_TID_ANY, |
93 | * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not |
94 | * allowed. |
95 | */ |
96 | #define SSAM_DEVICE(d, cat, tid, iid, fun) \ |
97 | .match_flags = (((tid) != SSAM_SSH_TID_ANY) ? SSAM_MATCH_TARGET : 0) \ |
98 | | (((iid) != SSAM_SSH_IID_ANY) ? SSAM_MATCH_INSTANCE : 0) \ |
99 | | (((fun) != SSAM_SSH_FUN_ANY) ? SSAM_MATCH_FUNCTION : 0), \ |
100 | .domain = d, \ |
101 | .category = cat, \ |
102 | .target = __builtin_choose_expr((tid) != SSAM_SSH_TID_ANY, (tid), 0), \ |
103 | .instance = __builtin_choose_expr((iid) != SSAM_SSH_IID_ANY, (iid), 0), \ |
104 | .function = __builtin_choose_expr((fun) != SSAM_SSH_FUN_ANY, (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_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and |
117 | * %SSAM_SSH_FUN_ANY 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_SSH_TID_ANY, |
123 | * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, 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, SSAM_SSH_TID_##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_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and |
140 | * %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target |
141 | * ID, instance ID, and/or sub-function, respectively. This macro initializes |
142 | * the ``match_flags`` 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_SSH_TID_ANY, |
146 | * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values |
147 | * are not allowed. |
148 | */ |
149 | #define SSAM_SDEV(cat, tid, iid, fun) \ |
150 | SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, SSAM_SSH_TID_##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 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 | #define to_ssam_device(d) container_of_const(d, struct ssam_device, dev) |
232 | |
233 | /** |
234 | * to_ssam_device_driver() - Casts the given device driver to a SSAM client |
235 | * device driver. |
236 | * @d: The driver to cast. |
237 | * |
238 | * Casts the given &struct device_driver to a &struct ssam_device_driver. The |
239 | * caller has to ensure that the given driver is actually enclosed in a |
240 | * &struct ssam_device_driver. |
241 | * |
242 | * Return: Returns the pointer to the &struct ssam_device_driver wrapping the |
243 | * given device driver @d. |
244 | */ |
245 | #define to_ssam_device_driver(d) container_of_const(d, struct ssam_device_driver, driver) |
246 | |
247 | const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table, |
248 | const struct ssam_device_uid uid); |
249 | |
250 | const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev); |
251 | |
252 | const void *ssam_device_get_match_data(const struct ssam_device *dev); |
253 | |
254 | struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl, |
255 | struct ssam_device_uid uid); |
256 | |
257 | int ssam_device_add(struct ssam_device *sdev); |
258 | void ssam_device_remove(struct ssam_device *sdev); |
259 | |
260 | /** |
261 | * ssam_device_mark_hot_removed() - Mark the given device as hot-removed. |
262 | * @sdev: The device to mark as hot-removed. |
263 | * |
264 | * Mark the device as having been hot-removed. This signals drivers using the |
265 | * device that communication with the device should be avoided and may lead to |
266 | * timeouts. |
267 | */ |
268 | static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev) |
269 | { |
270 | dev_dbg(&sdev->dev, "marking device as hot-removed\n" ); |
271 | set_bit(nr: SSAM_DEVICE_HOT_REMOVED_BIT, addr: &sdev->flags); |
272 | } |
273 | |
274 | /** |
275 | * ssam_device_is_hot_removed() - Check if the given device has been |
276 | * hot-removed. |
277 | * @sdev: The device to check. |
278 | * |
279 | * Checks if the given device has been marked as hot-removed. See |
280 | * ssam_device_mark_hot_removed() for more details. |
281 | * |
282 | * Return: Returns ``true`` if the device has been marked as hot-removed. |
283 | */ |
284 | static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev) |
285 | { |
286 | return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags); |
287 | } |
288 | |
289 | /** |
290 | * ssam_device_get() - Increment reference count of SSAM client device. |
291 | * @sdev: The device to increment the reference count of. |
292 | * |
293 | * Increments the reference count of the given SSAM client device by |
294 | * incrementing the reference count of the enclosed &struct device via |
295 | * get_device(). |
296 | * |
297 | * See ssam_device_put() for the counter-part of this function. |
298 | * |
299 | * Return: Returns the device provided as input. |
300 | */ |
301 | static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev) |
302 | { |
303 | return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL; |
304 | } |
305 | |
306 | /** |
307 | * ssam_device_put() - Decrement reference count of SSAM client device. |
308 | * @sdev: The device to decrement the reference count of. |
309 | * |
310 | * Decrements the reference count of the given SSAM client device by |
311 | * decrementing the reference count of the enclosed &struct device via |
312 | * put_device(). |
313 | * |
314 | * See ssam_device_get() for the counter-part of this function. |
315 | */ |
316 | static inline void ssam_device_put(struct ssam_device *sdev) |
317 | { |
318 | if (sdev) |
319 | put_device(dev: &sdev->dev); |
320 | } |
321 | |
322 | /** |
323 | * ssam_device_get_drvdata() - Get driver-data of SSAM client device. |
324 | * @sdev: The device to get the driver-data from. |
325 | * |
326 | * Return: Returns the driver-data of the given device, previously set via |
327 | * ssam_device_set_drvdata(). |
328 | */ |
329 | static inline void *ssam_device_get_drvdata(struct ssam_device *sdev) |
330 | { |
331 | return dev_get_drvdata(dev: &sdev->dev); |
332 | } |
333 | |
334 | /** |
335 | * ssam_device_set_drvdata() - Set driver-data of SSAM client device. |
336 | * @sdev: The device to set the driver-data of. |
337 | * @data: The data to set the device's driver-data pointer to. |
338 | */ |
339 | static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data) |
340 | { |
341 | dev_set_drvdata(dev: &sdev->dev, data); |
342 | } |
343 | |
344 | int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o); |
345 | void ssam_device_driver_unregister(struct ssam_device_driver *d); |
346 | |
347 | /** |
348 | * ssam_device_driver_register() - Register a SSAM client device driver. |
349 | * @drv: The driver to register. |
350 | */ |
351 | #define ssam_device_driver_register(drv) \ |
352 | __ssam_device_driver_register(drv, THIS_MODULE) |
353 | |
354 | /** |
355 | * module_ssam_device_driver() - Helper macro for SSAM device driver |
356 | * registration. |
357 | * @drv: The driver managed by this module. |
358 | * |
359 | * Helper macro to register a SSAM device driver via module_init() and |
360 | * module_exit(). This macro may only be used once per module and replaces the |
361 | * aforementioned definitions. |
362 | */ |
363 | #define module_ssam_device_driver(drv) \ |
364 | module_driver(drv, ssam_device_driver_register, \ |
365 | ssam_device_driver_unregister) |
366 | |
367 | |
368 | /* -- Helpers for controller and hub devices. ------------------------------- */ |
369 | |
370 | #ifdef CONFIG_SURFACE_AGGREGATOR_BUS |
371 | |
372 | int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, |
373 | struct fwnode_handle *node); |
374 | void ssam_remove_clients(struct device *dev); |
375 | |
376 | #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ |
377 | |
378 | static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, |
379 | struct fwnode_handle *node) |
380 | { |
381 | return 0; |
382 | } |
383 | |
384 | static inline void ssam_remove_clients(struct device *dev) {} |
385 | |
386 | #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ |
387 | |
388 | /** |
389 | * ssam_register_clients() - Register all client devices defined under the |
390 | * given parent device. |
391 | * @dev: The parent device under which clients should be registered. |
392 | * @ctrl: The controller with which client should be registered. |
393 | * |
394 | * Register all clients that have via firmware nodes been defined as children |
395 | * of the given (parent) device. The respective child firmware nodes will be |
396 | * associated with the correspondingly created child devices. |
397 | * |
398 | * The given controller will be used to instantiate the new devices. See |
399 | * ssam_device_add() for details. |
400 | * |
401 | * Return: Returns zero on success, nonzero on failure. |
402 | */ |
403 | static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl) |
404 | { |
405 | return __ssam_register_clients(parent: dev, ctrl, dev_fwnode(dev)); |
406 | } |
407 | |
408 | /** |
409 | * ssam_device_register_clients() - Register all client devices defined under |
410 | * the given SSAM parent device. |
411 | * @sdev: The parent device under which clients should be registered. |
412 | * |
413 | * Register all clients that have via firmware nodes been defined as children |
414 | * of the given (parent) device. The respective child firmware nodes will be |
415 | * associated with the correspondingly created child devices. |
416 | * |
417 | * The controller used by the parent device will be used to instantiate the new |
418 | * devices. See ssam_device_add() for details. |
419 | * |
420 | * Return: Returns zero on success, nonzero on failure. |
421 | */ |
422 | static inline int ssam_device_register_clients(struct ssam_device *sdev) |
423 | { |
424 | return ssam_register_clients(dev: &sdev->dev, ctrl: sdev->ctrl); |
425 | } |
426 | |
427 | |
428 | /* -- Helpers for client-device requests. ----------------------------------- */ |
429 | |
430 | /** |
431 | * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM |
432 | * request function with neither argument nor return value. |
433 | * @name: Name of the generated function. |
434 | * @spec: Specification (&struct ssam_request_spec_md) defining the request. |
435 | * |
436 | * Defines a function executing the synchronous SAM request specified by |
437 | * @spec, with the request having neither argument nor return value. Device |
438 | * specifying parameters are not hard-coded, but instead are provided via the |
439 | * client device, specifically its UID, supplied when calling this function. |
440 | * The generated function takes care of setting up the request struct, buffer |
441 | * allocation, as well as execution of the request itself, returning once the |
442 | * request has been fully completed. The required transport buffer will be |
443 | * allocated on the stack. |
444 | * |
445 | * The generated function is defined as ``static int name(struct ssam_device |
446 | * *sdev)``, returning the status of the request, which is zero on success and |
447 | * negative on failure. The ``sdev`` parameter specifies both the target |
448 | * device of the request and by association the controller via which the |
449 | * request is sent. |
450 | * |
451 | * Refer to ssam_request_do_sync_onstack() for more details on the behavior of |
452 | * the generated function. |
453 | */ |
454 | #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \ |
455 | SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \ |
456 | static int name(struct ssam_device *sdev) \ |
457 | { \ |
458 | return __raw_##name(sdev->ctrl, sdev->uid.target, \ |
459 | sdev->uid.instance); \ |
460 | } |
461 | |
462 | /** |
463 | * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM |
464 | * request function with argument. |
465 | * @name: Name of the generated function. |
466 | * @atype: Type of the request's argument. |
467 | * @spec: Specification (&struct ssam_request_spec_md) defining the request. |
468 | * |
469 | * Defines a function executing the synchronous SAM request specified by |
470 | * @spec, with the request taking an argument of type @atype and having no |
471 | * return value. Device specifying parameters are not hard-coded, but instead |
472 | * are provided via the client device, specifically its UID, supplied when |
473 | * calling this function. The generated function takes care of setting up the |
474 | * request struct, buffer allocation, as well as execution of the request |
475 | * itself, returning once the request has been fully completed. The required |
476 | * transport buffer will be allocated on the stack. |
477 | * |
478 | * The generated function is defined as ``static int name(struct ssam_device |
479 | * *sdev, const atype *arg)``, returning the status of the request, which is |
480 | * zero on success and negative on failure. The ``sdev`` parameter specifies |
481 | * both the target device of the request and by association the controller via |
482 | * which the request is sent. The request's argument is specified via the |
483 | * ``arg`` pointer. |
484 | * |
485 | * Refer to ssam_request_do_sync_onstack() for more details on the behavior of |
486 | * the generated function. |
487 | */ |
488 | #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \ |
489 | SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \ |
490 | static int name(struct ssam_device *sdev, const atype *arg) \ |
491 | { \ |
492 | return __raw_##name(sdev->ctrl, sdev->uid.target, \ |
493 | sdev->uid.instance, arg); \ |
494 | } |
495 | |
496 | /** |
497 | * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM |
498 | * request function with return value. |
499 | * @name: Name of the generated function. |
500 | * @rtype: Type of the request's return value. |
501 | * @spec: Specification (&struct ssam_request_spec_md) defining the request. |
502 | * |
503 | * Defines a function executing the synchronous SAM request specified by |
504 | * @spec, with the request taking no argument but having a return value of |
505 | * type @rtype. Device specifying parameters are not hard-coded, but instead |
506 | * are provided via the client device, specifically its UID, supplied when |
507 | * calling this function. The generated function takes care of setting up the |
508 | * request struct, buffer allocation, as well as execution of the request |
509 | * itself, returning once the request has been fully completed. The required |
510 | * transport buffer will be allocated on the stack. |
511 | * |
512 | * The generated function is defined as ``static int name(struct ssam_device |
513 | * *sdev, rtype *ret)``, returning the status of the request, which is zero on |
514 | * success and negative on failure. The ``sdev`` parameter specifies both the |
515 | * target device of the request and by association the controller via which |
516 | * the request is sent. The request's return value is written to the memory |
517 | * pointed to by the ``ret`` parameter. |
518 | * |
519 | * Refer to ssam_request_do_sync_onstack() for more details on the behavior of |
520 | * the generated function. |
521 | */ |
522 | #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \ |
523 | SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \ |
524 | static int name(struct ssam_device *sdev, rtype *ret) \ |
525 | { \ |
526 | return __raw_##name(sdev->ctrl, sdev->uid.target, \ |
527 | sdev->uid.instance, ret); \ |
528 | } |
529 | |
530 | /** |
531 | * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM |
532 | * request function with argument and return value. |
533 | * @name: Name of the generated function. |
534 | * @atype: Type of the request's argument. |
535 | * @rtype: Type of the request's return value. |
536 | * @spec: Specification (&struct ssam_request_spec_md) defining the request. |
537 | * |
538 | * Defines a function executing the synchronous SAM request specified by @spec, |
539 | * with the request taking an argument of type @atype and having a return value |
540 | * of type @rtype. Device specifying parameters are not hard-coded, but instead |
541 | * are provided via the client device, specifically its UID, supplied when |
542 | * calling this function. The generated function takes care of setting up the |
543 | * request struct, buffer allocation, as well as execution of the request |
544 | * itself, returning once the request has been fully completed. The required |
545 | * transport buffer will be allocated on the stack. |
546 | * |
547 | * The generated function is defined as ``static int name(struct ssam_device |
548 | * *sdev, const atype *arg, rtype *ret)``, returning the status of the request, |
549 | * which is zero on success and negative on failure. The ``sdev`` parameter |
550 | * specifies both the target device of the request and by association the |
551 | * controller via which the request is sent. The request's argument is |
552 | * specified via the ``arg`` pointer. The request's return value is written to |
553 | * the memory pointed to by the ``ret`` parameter. |
554 | * |
555 | * Refer to ssam_request_do_sync_onstack() for more details on the behavior of |
556 | * the generated function. |
557 | */ |
558 | #define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \ |
559 | SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \ |
560 | static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \ |
561 | { \ |
562 | return __raw_##name(sdev->ctrl, sdev->uid.target, \ |
563 | sdev->uid.instance, arg, ret); \ |
564 | } |
565 | |
566 | |
567 | /* -- Helpers for client-device notifiers. ---------------------------------- */ |
568 | |
569 | /** |
570 | * ssam_device_notifier_register() - Register an event notifier for the |
571 | * specified client device. |
572 | * @sdev: The device the notifier should be registered on. |
573 | * @n: The event notifier to register. |
574 | * |
575 | * Register an event notifier. Increment the usage counter of the associated |
576 | * SAM event if the notifier is not marked as an observer. If the event is not |
577 | * marked as an observer and is currently not enabled, it will be enabled |
578 | * during this call. If the notifier is marked as an observer, no attempt will |
579 | * be made at enabling any event and no reference count will be modified. |
580 | * |
581 | * Notifiers marked as observers do not need to be associated with one specific |
582 | * event, i.e. as long as no event matching is performed, only the event target |
583 | * category needs to be set. |
584 | * |
585 | * Return: Returns zero on success, %-ENOSPC if there have already been |
586 | * %INT_MAX notifiers for the event ID/type associated with the notifier block |
587 | * registered, %-ENOMEM if the corresponding event entry could not be |
588 | * allocated, %-ENODEV if the device is marked as hot-removed. If this is the |
589 | * first time that a notifier block is registered for the specific associated |
590 | * event, returns the status of the event-enable EC-command. |
591 | */ |
592 | static inline int ssam_device_notifier_register(struct ssam_device *sdev, |
593 | struct ssam_event_notifier *n) |
594 | { |
595 | /* |
596 | * Note that this check does not provide any guarantees whatsoever as |
597 | * hot-removal could happen at any point and we can't protect against |
598 | * it. Nevertheless, if we can detect hot-removal, bail early to avoid |
599 | * communication timeouts. |
600 | */ |
601 | if (ssam_device_is_hot_removed(sdev)) |
602 | return -ENODEV; |
603 | |
604 | return ssam_notifier_register(ctrl: sdev->ctrl, n); |
605 | } |
606 | |
607 | /** |
608 | * ssam_device_notifier_unregister() - Unregister an event notifier for the |
609 | * specified client device. |
610 | * @sdev: The device the notifier has been registered on. |
611 | * @n: The event notifier to unregister. |
612 | * |
613 | * Unregister an event notifier. Decrement the usage counter of the associated |
614 | * SAM event if the notifier is not marked as an observer. If the usage counter |
615 | * reaches zero, the event will be disabled. |
616 | * |
617 | * In case the device has been marked as hot-removed, the event will not be |
618 | * disabled on the EC, as in those cases any attempt at doing so may time out. |
619 | * |
620 | * Return: Returns zero on success, %-ENOENT if the given notifier block has |
621 | * not been registered on the controller. If the given notifier block was the |
622 | * last one associated with its specific event, returns the status of the |
623 | * event-disable EC-command. |
624 | */ |
625 | static inline int ssam_device_notifier_unregister(struct ssam_device *sdev, |
626 | struct ssam_event_notifier *n) |
627 | { |
628 | return __ssam_notifier_unregister(ctrl: sdev->ctrl, n, |
629 | disable: !ssam_device_is_hot_removed(sdev)); |
630 | } |
631 | |
632 | #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */ |
633 | |