device.h 24 KB

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