Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0+ */
0002 /*
0003  * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
0004  *
0005  * Main interface for the surface-aggregator bus, surface-aggregator client
0006  * devices, and respective drivers building on top of the SSAM controller.
0007  * Provides support for non-platform/non-ACPI SSAM clients via dedicated
0008  * subsystem.
0009  *
0010  * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
0011  */
0012 
0013 #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
0014 #define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
0015 
0016 #include <linux/device.h>
0017 #include <linux/mod_devicetable.h>
0018 #include <linux/property.h>
0019 #include <linux/types.h>
0020 
0021 #include <linux/surface_aggregator/controller.h>
0022 
0023 
0024 /* -- Surface System Aggregator Module bus. --------------------------------- */
0025 
0026 /**
0027  * enum ssam_device_domain - SAM device domain.
0028  * @SSAM_DOMAIN_VIRTUAL:   Virtual device.
0029  * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
0030  */
0031 enum ssam_device_domain {
0032     SSAM_DOMAIN_VIRTUAL   = 0x00,
0033     SSAM_DOMAIN_SERIALHUB = 0x01,
0034 };
0035 
0036 /**
0037  * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
0038  * @SSAM_VIRTUAL_TC_HUB: Device hub category.
0039  */
0040 enum ssam_virtual_tc {
0041     SSAM_VIRTUAL_TC_HUB = 0x00,
0042 };
0043 
0044 /**
0045  * struct ssam_device_uid - Unique identifier for SSAM device.
0046  * @domain:   Domain of the device.
0047  * @category: Target category of the device.
0048  * @target:   Target ID of the device.
0049  * @instance: Instance ID of the device.
0050  * @function: Sub-function of the device. This field can be used to split a
0051  *            single SAM device into multiple virtual subdevices to separate
0052  *            different functionality of that device and allow one driver per
0053  *            such functionality.
0054  */
0055 struct ssam_device_uid {
0056     u8 domain;
0057     u8 category;
0058     u8 target;
0059     u8 instance;
0060     u8 function;
0061 };
0062 
0063 /*
0064  * Special values for device matching.
0065  *
0066  * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
0067  * SSAM_SDEV() exclusively. Specifically, they are used to initialize the
0068  * match_flags member of the device ID structure. Do not use them directly
0069  * with struct ssam_device_id or struct ssam_device_uid.
0070  */
0071 #define SSAM_ANY_TID        0xffff
0072 #define SSAM_ANY_IID        0xffff
0073 #define SSAM_ANY_FUN        0xffff
0074 
0075 /**
0076  * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
0077  * parameters.
0078  * @d:   Domain of the device.
0079  * @cat: Target category of the device.
0080  * @tid: Target ID of the device.
0081  * @iid: Instance ID of the device.
0082  * @fun: Sub-function of the device.
0083  *
0084  * Initializes a &struct ssam_device_id with the given parameters. See &struct
0085  * ssam_device_uid for details regarding the parameters. The special values
0086  * %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be used to specify that
0087  * matching should ignore target ID, instance ID, and/or sub-function,
0088  * respectively. This macro initializes the ``match_flags`` field based on the
0089  * given parameters.
0090  *
0091  * Note: The parameters @d and @cat must be valid &u8 values, the parameters
0092  * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
0093  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
0094  * allowed.
0095  */
0096 #define SSAM_DEVICE(d, cat, tid, iid, fun)                  \
0097     .match_flags = (((tid) != SSAM_ANY_TID) ? SSAM_MATCH_TARGET : 0)    \
0098              | (((iid) != SSAM_ANY_IID) ? SSAM_MATCH_INSTANCE : 0)  \
0099              | (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0), \
0100     .domain   = d,                              \
0101     .category = cat,                            \
0102     .target   = __builtin_choose_expr((tid) != SSAM_ANY_TID, (tid), 0), \
0103     .instance = __builtin_choose_expr((iid) != SSAM_ANY_IID, (iid), 0), \
0104     .function = __builtin_choose_expr((fun) != SSAM_ANY_FUN, (fun), 0)
0105 
0106 /**
0107  * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
0108  * the given parameters.
0109  * @cat: Target category of the device.
0110  * @tid: Target ID of the device.
0111  * @iid: Instance ID of the device.
0112  * @fun: Sub-function of the device.
0113  *
0114  * Initializes a &struct ssam_device_id with the given parameters in the
0115  * virtual domain. See &struct ssam_device_uid for details regarding the
0116  * parameters. The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and
0117  * %SSAM_ANY_FUN can be used to specify that matching should ignore target ID,
0118  * instance ID, and/or sub-function, respectively. This macro initializes the
0119  * ``match_flags`` field based on the given parameters.
0120  *
0121  * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
0122  * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
0123  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
0124  * allowed.
0125  */
0126 #define SSAM_VDEV(cat, tid, iid, fun) \
0127     SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, tid, iid, fun)
0128 
0129 /**
0130  * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
0131  * with the given parameters.
0132  * @cat: Target category of the device.
0133  * @tid: Target ID of the device.
0134  * @iid: Instance ID of the device.
0135  * @fun: Sub-function of the device.
0136  *
0137  * Initializes a &struct ssam_device_id with the given parameters in the SSH
0138  * domain. See &struct ssam_device_uid for details regarding the parameters.
0139  * The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be
0140  * used to specify that matching should ignore target ID, instance ID, and/or
0141  * sub-function, respectively. This macro initializes the ``match_flags``
0142  * field based on the given parameters.
0143  *
0144  * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
0145  * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
0146  * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
0147  * allowed.
0148  */
0149 #define SSAM_SDEV(cat, tid, iid, fun) \
0150     SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
0151 
0152 /*
0153  * enum ssam_device_flags - Flags for SSAM client devices.
0154  * @SSAM_DEVICE_HOT_REMOVED_BIT:
0155  *  The device has been hot-removed. Further communication with it may time
0156  *  out and should be avoided.
0157  */
0158 enum ssam_device_flags {
0159     SSAM_DEVICE_HOT_REMOVED_BIT = 0,
0160 };
0161 
0162 /**
0163  * struct ssam_device - SSAM client device.
0164  * @dev:   Driver model representation of the device.
0165  * @ctrl:  SSAM controller managing this device.
0166  * @uid:   UID identifying the device.
0167  * @flags: Device state flags, see &enum ssam_device_flags.
0168  */
0169 struct ssam_device {
0170     struct device dev;
0171     struct ssam_controller *ctrl;
0172 
0173     struct ssam_device_uid uid;
0174 
0175     unsigned long flags;
0176 };
0177 
0178 /**
0179  * struct ssam_device_driver - SSAM client device driver.
0180  * @driver:      Base driver model structure.
0181  * @match_table: Match table specifying which devices the driver should bind to.
0182  * @probe:       Called when the driver is being bound to a device.
0183  * @remove:      Called when the driver is being unbound from the device.
0184  */
0185 struct ssam_device_driver {
0186     struct device_driver driver;
0187 
0188     const struct ssam_device_id *match_table;
0189 
0190     int  (*probe)(struct ssam_device *sdev);
0191     void (*remove)(struct ssam_device *sdev);
0192 };
0193 
0194 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
0195 
0196 extern struct bus_type ssam_bus_type;
0197 extern const struct device_type ssam_device_type;
0198 
0199 /**
0200  * is_ssam_device() - Check if the given device is a SSAM client device.
0201  * @d: The device to test the type of.
0202  *
0203  * Return: Returns %true if the specified device is of type &struct
0204  * ssam_device, i.e. the device type points to %ssam_device_type, and %false
0205  * otherwise.
0206  */
0207 static inline bool is_ssam_device(struct device *d)
0208 {
0209     return d->type == &ssam_device_type;
0210 }
0211 
0212 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
0213 
0214 static inline bool is_ssam_device(struct device *d)
0215 {
0216     return false;
0217 }
0218 
0219 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
0220 
0221 /**
0222  * to_ssam_device() - Casts the given device to a SSAM client device.
0223  * @d: The device to cast.
0224  *
0225  * Casts the given &struct device to a &struct ssam_device. The caller has to
0226  * ensure that the given device is actually enclosed in a &struct ssam_device,
0227  * e.g. by calling is_ssam_device().
0228  *
0229  * Return: Returns a pointer to the &struct ssam_device wrapping the given
0230  * device @d.
0231  */
0232 static inline struct ssam_device *to_ssam_device(struct device *d)
0233 {
0234     return container_of(d, struct ssam_device, dev);
0235 }
0236 
0237 /**
0238  * to_ssam_device_driver() - Casts the given device driver to a SSAM client
0239  * device driver.
0240  * @d: The driver to cast.
0241  *
0242  * Casts the given &struct device_driver to a &struct ssam_device_driver. The
0243  * caller has to ensure that the given driver is actually enclosed in a
0244  * &struct ssam_device_driver.
0245  *
0246  * Return: Returns the pointer to the &struct ssam_device_driver wrapping the
0247  * given device driver @d.
0248  */
0249 static inline
0250 struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d)
0251 {
0252     return container_of(d, struct ssam_device_driver, driver);
0253 }
0254 
0255 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
0256                           const struct ssam_device_uid uid);
0257 
0258 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);
0259 
0260 const void *ssam_device_get_match_data(const struct ssam_device *dev);
0261 
0262 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
0263                       struct ssam_device_uid uid);
0264 
0265 int ssam_device_add(struct ssam_device *sdev);
0266 void ssam_device_remove(struct ssam_device *sdev);
0267 
0268 /**
0269  * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
0270  * @sdev: The device to mark as hot-removed.
0271  *
0272  * Mark the device as having been hot-removed. This signals drivers using the
0273  * device that communication with the device should be avoided and may lead to
0274  * timeouts.
0275  */
0276 static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
0277 {
0278     dev_dbg(&sdev->dev, "marking device as hot-removed\n");
0279     set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
0280 }
0281 
0282 /**
0283  * ssam_device_is_hot_removed() - Check if the given device has been
0284  * hot-removed.
0285  * @sdev: The device to check.
0286  *
0287  * Checks if the given device has been marked as hot-removed. See
0288  * ssam_device_mark_hot_removed() for more details.
0289  *
0290  * Return: Returns ``true`` if the device has been marked as hot-removed.
0291  */
0292 static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
0293 {
0294     return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
0295 }
0296 
0297 /**
0298  * ssam_device_get() - Increment reference count of SSAM client device.
0299  * @sdev: The device to increment the reference count of.
0300  *
0301  * Increments the reference count of the given SSAM client device by
0302  * incrementing the reference count of the enclosed &struct device via
0303  * get_device().
0304  *
0305  * See ssam_device_put() for the counter-part of this function.
0306  *
0307  * Return: Returns the device provided as input.
0308  */
0309 static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
0310 {
0311     return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
0312 }
0313 
0314 /**
0315  * ssam_device_put() - Decrement reference count of SSAM client device.
0316  * @sdev: The device to decrement the reference count of.
0317  *
0318  * Decrements the reference count of the given SSAM client device by
0319  * decrementing the reference count of the enclosed &struct device via
0320  * put_device().
0321  *
0322  * See ssam_device_get() for the counter-part of this function.
0323  */
0324 static inline void ssam_device_put(struct ssam_device *sdev)
0325 {
0326     if (sdev)
0327         put_device(&sdev->dev);
0328 }
0329 
0330 /**
0331  * ssam_device_get_drvdata() - Get driver-data of SSAM client device.
0332  * @sdev: The device to get the driver-data from.
0333  *
0334  * Return: Returns the driver-data of the given device, previously set via
0335  * ssam_device_set_drvdata().
0336  */
0337 static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
0338 {
0339     return dev_get_drvdata(&sdev->dev);
0340 }
0341 
0342 /**
0343  * ssam_device_set_drvdata() - Set driver-data of SSAM client device.
0344  * @sdev: The device to set the driver-data of.
0345  * @data: The data to set the device's driver-data pointer to.
0346  */
0347 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
0348 {
0349     dev_set_drvdata(&sdev->dev, data);
0350 }
0351 
0352 int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
0353 void ssam_device_driver_unregister(struct ssam_device_driver *d);
0354 
0355 /**
0356  * ssam_device_driver_register() - Register a SSAM client device driver.
0357  * @drv: The driver to register.
0358  */
0359 #define ssam_device_driver_register(drv) \
0360     __ssam_device_driver_register(drv, THIS_MODULE)
0361 
0362 /**
0363  * module_ssam_device_driver() - Helper macro for SSAM device driver
0364  * registration.
0365  * @drv: The driver managed by this module.
0366  *
0367  * Helper macro to register a SSAM device driver via module_init() and
0368  * module_exit(). This macro may only be used once per module and replaces the
0369  * aforementioned definitions.
0370  */
0371 #define module_ssam_device_driver(drv)          \
0372     module_driver(drv, ssam_device_driver_register, \
0373               ssam_device_driver_unregister)
0374 
0375 
0376 /* -- Helpers for controller and hub devices. ------------------------------- */
0377 
0378 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
0379 
0380 int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
0381                 struct fwnode_handle *node);
0382 void ssam_remove_clients(struct device *dev);
0383 
0384 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
0385 
0386 static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
0387                       struct fwnode_handle *node)
0388 {
0389     return 0;
0390 }
0391 
0392 static inline void ssam_remove_clients(struct device *dev) {}
0393 
0394 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
0395 
0396 /**
0397  * ssam_register_clients() - Register all client devices defined under the
0398  * given parent device.
0399  * @dev: The parent device under which clients should be registered.
0400  * @ctrl: The controller with which client should be registered.
0401  *
0402  * Register all clients that have via firmware nodes been defined as children
0403  * of the given (parent) device. The respective child firmware nodes will be
0404  * associated with the correspondingly created child devices.
0405  *
0406  * The given controller will be used to instantiate the new devices. See
0407  * ssam_device_add() for details.
0408  *
0409  * Return: Returns zero on success, nonzero on failure.
0410  */
0411 static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
0412 {
0413     return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
0414 }
0415 
0416 /**
0417  * ssam_device_register_clients() - Register all client devices defined under
0418  * the given SSAM parent device.
0419  * @sdev: The parent device under which clients should be registered.
0420  *
0421  * Register all clients that have via firmware nodes been defined as children
0422  * of the given (parent) device. The respective child firmware nodes will be
0423  * associated with the correspondingly created child devices.
0424  *
0425  * The controller used by the parent device will be used to instantiate the new
0426  * devices. See ssam_device_add() for details.
0427  *
0428  * Return: Returns zero on success, nonzero on failure.
0429  */
0430 static inline int ssam_device_register_clients(struct ssam_device *sdev)
0431 {
0432     return ssam_register_clients(&sdev->dev, sdev->ctrl);
0433 }
0434 
0435 
0436 /* -- Helpers for client-device requests. ----------------------------------- */
0437 
0438 /**
0439  * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM
0440  * request function with neither argument nor return value.
0441  * @name: Name of the generated function.
0442  * @spec: Specification (&struct ssam_request_spec_md) defining the request.
0443  *
0444  * Defines a function executing the synchronous SAM request specified by
0445  * @spec, with the request having neither argument nor return value. Device
0446  * specifying parameters are not hard-coded, but instead are provided via the
0447  * client device, specifically its UID, supplied when calling this function.
0448  * The generated function takes care of setting up the request struct, buffer
0449  * allocation, as well as execution of the request itself, returning once the
0450  * request has been fully completed. The required transport buffer will be
0451  * allocated on the stack.
0452  *
0453  * The generated function is defined as ``static int name(struct ssam_device
0454  * *sdev)``, returning the status of the request, which is zero on success and
0455  * negative on failure. The ``sdev`` parameter specifies both the target
0456  * device of the request and by association the controller via which the
0457  * request is sent.
0458  *
0459  * Refer to ssam_request_sync_onstack() for more details on the behavior of
0460  * the generated function.
0461  */
0462 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...)            \
0463     SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec)       \
0464     static int name(struct ssam_device *sdev)           \
0465     {                               \
0466         return __raw_##name(sdev->ctrl, sdev->uid.target,   \
0467                     sdev->uid.instance);        \
0468     }
0469 
0470 /**
0471  * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
0472  * request function with argument.
0473  * @name:  Name of the generated function.
0474  * @atype: Type of the request's argument.
0475  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
0476  *
0477  * Defines a function executing the synchronous SAM request specified by
0478  * @spec, with the request taking an argument of type @atype and having no
0479  * return value. Device specifying parameters are not hard-coded, but instead
0480  * are provided via the client device, specifically its UID, supplied when
0481  * calling this function. The generated function takes care of setting up the
0482  * request struct, buffer allocation, as well as execution of the request
0483  * itself, returning once the request has been fully completed. The required
0484  * transport buffer will be allocated on the stack.
0485  *
0486  * The generated function is defined as ``static int name(struct ssam_device
0487  * *sdev, const atype *arg)``, returning the status of the request, which is
0488  * zero on success and negative on failure. The ``sdev`` parameter specifies
0489  * both the target device of the request and by association the controller via
0490  * which the request is sent. The request's argument is specified via the
0491  * ``arg`` pointer.
0492  *
0493  * Refer to ssam_request_sync_onstack() for more details on the behavior of
0494  * the generated function.
0495  */
0496 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...)     \
0497     SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec)    \
0498     static int name(struct ssam_device *sdev, const atype *arg) \
0499     {                               \
0500         return __raw_##name(sdev->ctrl, sdev->uid.target,   \
0501                     sdev->uid.instance, arg);       \
0502     }
0503 
0504 /**
0505  * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
0506  * request function with return value.
0507  * @name:  Name of the generated function.
0508  * @rtype: Type of the request's return value.
0509  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
0510  *
0511  * Defines a function executing the synchronous SAM request specified by
0512  * @spec, with the request taking no argument but having a return value of
0513  * type @rtype. Device specifying parameters are not hard-coded, but instead
0514  * are provided via the client device, specifically its UID, supplied when
0515  * calling this function. The generated function takes care of setting up the
0516  * request struct, buffer allocation, as well as execution of the request
0517  * itself, returning once the request has been fully completed. The required
0518  * transport buffer will be allocated on the stack.
0519  *
0520  * The generated function is defined as ``static int name(struct ssam_device
0521  * *sdev, rtype *ret)``, returning the status of the request, which is zero on
0522  * success and negative on failure. The ``sdev`` parameter specifies both the
0523  * target device of the request and by association the controller via which
0524  * the request is sent. The request's return value is written to the memory
0525  * pointed to by the ``ret`` parameter.
0526  *
0527  * Refer to ssam_request_sync_onstack() for more details on the behavior of
0528  * the generated function.
0529  */
0530 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...)     \
0531     SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec)    \
0532     static int name(struct ssam_device *sdev, rtype *ret)       \
0533     {                               \
0534         return __raw_##name(sdev->ctrl, sdev->uid.target,   \
0535                     sdev->uid.instance, ret);       \
0536     }
0537 
0538 /**
0539  * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
0540  * request function with argument and return value.
0541  * @name:  Name of the generated function.
0542  * @atype: Type of the request's argument.
0543  * @rtype: Type of the request's return value.
0544  * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
0545  *
0546  * Defines a function executing the synchronous SAM request specified by @spec,
0547  * with the request taking an argument of type @atype and having a return value
0548  * of type @rtype. Device specifying parameters are not hard-coded, but instead
0549  * are provided via the client device, specifically its UID, supplied when
0550  * calling this function. The generated function takes care of setting up the
0551  * request struct, buffer allocation, as well as execution of the request
0552  * itself, returning once the request has been fully completed. The required
0553  * transport buffer will be allocated on the stack.
0554  *
0555  * The generated function is defined as ``static int name(struct ssam_device
0556  * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
0557  * which is zero on success and negative on failure. The ``sdev`` parameter
0558  * specifies both the target device of the request and by association the
0559  * controller via which the request is sent. The request's argument is
0560  * specified via the ``arg`` pointer. The request's return value is written to
0561  * the memory pointed to by the ``ret`` parameter.
0562  *
0563  * Refer to ssam_request_sync_onstack() for more details on the behavior of
0564  * the generated function.
0565  */
0566 #define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...)     \
0567     SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec)    \
0568     static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \
0569     {                                   \
0570         return __raw_##name(sdev->ctrl, sdev->uid.target,       \
0571                     sdev->uid.instance, arg, ret);      \
0572     }
0573 
0574 
0575 /* -- Helpers for client-device notifiers. ---------------------------------- */
0576 
0577 /**
0578  * ssam_device_notifier_register() - Register an event notifier for the
0579  * specified client device.
0580  * @sdev: The device the notifier should be registered on.
0581  * @n:    The event notifier to register.
0582  *
0583  * Register an event notifier. Increment the usage counter of the associated
0584  * SAM event if the notifier is not marked as an observer. If the event is not
0585  * marked as an observer and is currently not enabled, it will be enabled
0586  * during this call. If the notifier is marked as an observer, no attempt will
0587  * be made at enabling any event and no reference count will be modified.
0588  *
0589  * Notifiers marked as observers do not need to be associated with one specific
0590  * event, i.e. as long as no event matching is performed, only the event target
0591  * category needs to be set.
0592  *
0593  * Return: Returns zero on success, %-ENOSPC if there have already been
0594  * %INT_MAX notifiers for the event ID/type associated with the notifier block
0595  * registered, %-ENOMEM if the corresponding event entry could not be
0596  * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
0597  * first time that a notifier block is registered for the specific associated
0598  * event, returns the status of the event-enable EC-command.
0599  */
0600 static inline int ssam_device_notifier_register(struct ssam_device *sdev,
0601                         struct ssam_event_notifier *n)
0602 {
0603     /*
0604      * Note that this check does not provide any guarantees whatsoever as
0605      * hot-removal could happen at any point and we can't protect against
0606      * it. Nevertheless, if we can detect hot-removal, bail early to avoid
0607      * communication timeouts.
0608      */
0609     if (ssam_device_is_hot_removed(sdev))
0610         return -ENODEV;
0611 
0612     return ssam_notifier_register(sdev->ctrl, n);
0613 }
0614 
0615 /**
0616  * ssam_device_notifier_unregister() - Unregister an event notifier for the
0617  * specified client device.
0618  * @sdev: The device the notifier has been registered on.
0619  * @n:    The event notifier to unregister.
0620  *
0621  * Unregister an event notifier. Decrement the usage counter of the associated
0622  * SAM event if the notifier is not marked as an observer. If the usage counter
0623  * reaches zero, the event will be disabled.
0624  *
0625  * In case the device has been marked as hot-removed, the event will not be
0626  * disabled on the EC, as in those cases any attempt at doing so may time out.
0627  *
0628  * Return: Returns zero on success, %-ENOENT if the given notifier block has
0629  * not been registered on the controller. If the given notifier block was the
0630  * last one associated with its specific event, returns the status of the
0631  * event-disable EC-command.
0632  */
0633 static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
0634                           struct ssam_event_notifier *n)
0635 {
0636     return __ssam_notifier_unregister(sdev->ctrl, n,
0637                       !ssam_device_is_hot_removed(sdev));
0638 }
0639 
0640 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */