linux-stable/include/linux/surface_aggregator/device.h
Linus Torvalds a93e884edf Driver core changes for 6.3-rc1
Here is the large set of driver core changes for 6.3-rc1.
 
 There's a lot of changes this development cycle, most of the work falls
 into two different categories:
   - fw_devlink fixes and updates.  This has gone through numerous review
     cycles and lots of review and testing by lots of different devices.
     Hopefully all should be good now, and Saravana will be keeping a
     watch for any potential regression on odd embedded systems.
   - driver core changes to work to make struct bus_type able to be moved
     into read-only memory (i.e. const)  The recent work with Rust has
     pointed out a number of areas in the driver core where we are
     passing around and working with structures that really do not have
     to be dynamic at all, and they should be able to be read-only making
     things safer overall.  This is the contuation of that work (started
     last release with kobject changes) in moving struct bus_type to be
     constant.  We didn't quite make it for this release, but the
     remaining patches will be finished up for the release after this
     one, but the groundwork has been laid for this effort.
 
 Other than that we have in here:
   - debugfs memory leak fixes in some subsystems
   - error path cleanups and fixes for some never-able-to-be-hit
     codepaths.
   - cacheinfo rework and fixes
   - Other tiny fixes, full details are in the shortlog
 
 All of these have been in linux-next for a while with no reported
 problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCY/ipdg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ynL3gCgwzbcWu0So3piZyLiJKxsVo9C2EsAn3sZ9gN6
 6oeFOjD3JDju3cQsfGgd
 =Su6W
 -----END PGP SIGNATURE-----

Merge tag 'driver-core-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is the large set of driver core changes for 6.3-rc1.

  There's a lot of changes this development cycle, most of the work
  falls into two different categories:

   - fw_devlink fixes and updates. This has gone through numerous review
     cycles and lots of review and testing by lots of different devices.
     Hopefully all should be good now, and Saravana will be keeping a
     watch for any potential regression on odd embedded systems.

   - driver core changes to work to make struct bus_type able to be
     moved into read-only memory (i.e. const) The recent work with Rust
     has pointed out a number of areas in the driver core where we are
     passing around and working with structures that really do not have
     to be dynamic at all, and they should be able to be read-only
     making things safer overall. This is the contuation of that work
     (started last release with kobject changes) in moving struct
     bus_type to be constant. We didn't quite make it for this release,
     but the remaining patches will be finished up for the release after
     this one, but the groundwork has been laid for this effort.

  Other than that we have in here:

   - debugfs memory leak fixes in some subsystems

   - error path cleanups and fixes for some never-able-to-be-hit
     codepaths.

   - cacheinfo rework and fixes

   - Other tiny fixes, full details are in the shortlog

  All of these have been in linux-next for a while with no reported
  problems"

[ Geert Uytterhoeven points out that that last sentence isn't true, and
  that there's a pending report that has a fix that is queued up - Linus ]

* tag 'driver-core-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (124 commits)
  debugfs: drop inline constant formatting for ERR_PTR(-ERROR)
  OPP: fix error checking in opp_migrate_dentry()
  debugfs: update comment of debugfs_rename()
  i3c: fix device.h kernel-doc warnings
  dma-mapping: no need to pass a bus_type into get_arch_dma_ops()
  driver core: class: move EXPORT_SYMBOL_GPL() lines to the correct place
  Revert "driver core: add error handling for devtmpfs_create_node()"
  Revert "devtmpfs: add debug info to handle()"
  Revert "devtmpfs: remove return value of devtmpfs_delete_node()"
  driver core: cpu: don't hand-override the uevent bus_type callback.
  devtmpfs: remove return value of devtmpfs_delete_node()
  devtmpfs: add debug info to handle()
  driver core: add error handling for devtmpfs_create_node()
  driver core: bus: update my copyright notice
  driver core: bus: add bus_get_dev_root() function
  driver core: bus: constify bus_unregister()
  driver core: bus: constify some internal functions
  driver core: bus: constify bus_get_kset()
  driver core: bus: constify bus_register/unregister_notifier()
  driver core: remove private pointer from struct bus_type
  ...
2023-02-24 12:58:55 -08:00

637 lines
24 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Surface System Aggregator Module (SSAM) bus and client-device subsystem.
*
* Main interface for the surface-aggregator bus, surface-aggregator client
* devices, and respective drivers building on top of the SSAM controller.
* Provides support for non-platform/non-ACPI SSAM clients via dedicated
* subsystem.
*
* Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
*/
#ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
#define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/types.h>
#include <linux/surface_aggregator/controller.h>
/* -- Surface System Aggregator Module bus. --------------------------------- */
/**
* enum ssam_device_domain - SAM device domain.
* @SSAM_DOMAIN_VIRTUAL: Virtual device.
* @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
*/
enum ssam_device_domain {
SSAM_DOMAIN_VIRTUAL = 0x00,
SSAM_DOMAIN_SERIALHUB = 0x01,
};
/**
* enum ssam_virtual_tc - Target categories for the virtual SAM domain.
* @SSAM_VIRTUAL_TC_HUB: Device hub category.
*/
enum ssam_virtual_tc {
SSAM_VIRTUAL_TC_HUB = 0x00,
};
/**
* struct ssam_device_uid - Unique identifier for SSAM device.
* @domain: Domain of the device.
* @category: Target category of the device.
* @target: Target ID of the device.
* @instance: Instance ID of the device.
* @function: Sub-function of the device. This field can be used to split a
* single SAM device into multiple virtual subdevices to separate
* different functionality of that device and allow one driver per
* such functionality.
*/
struct ssam_device_uid {
u8 domain;
u8 category;
u8 target;
u8 instance;
u8 function;
};
/*
* Special values for device matching.
*
* These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
* SSAM_SDEV() exclusively. Specifically, they are used to initialize the
* match_flags member of the device ID structure. Do not use them directly
* with struct ssam_device_id or struct ssam_device_uid.
*/
#define SSAM_SSH_TID_ANY 0xffff
#define SSAM_SSH_IID_ANY 0xffff
#define SSAM_SSH_FUN_ANY 0xffff
/**
* SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
* parameters.
* @d: Domain of the device.
* @cat: Target category of the device.
* @tid: Target ID of the device.
* @iid: Instance ID of the device.
* @fun: Sub-function of the device.
*
* Initializes a &struct ssam_device_id with the given parameters. See &struct
* ssam_device_uid for details regarding the parameters. The special values
* %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and %SSAM_SSH_FUN_ANY can be used to specify that
* matching should ignore target ID, instance ID, and/or sub-function,
* respectively. This macro initializes the ``match_flags`` field based on the
* given parameters.
*
* Note: The parameters @d and @cat must be valid &u8 values, the parameters
* @tid, @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
* %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not
* allowed.
*/
#define SSAM_DEVICE(d, cat, tid, iid, fun) \
.match_flags = (((tid) != SSAM_SSH_TID_ANY) ? SSAM_MATCH_TARGET : 0) \
| (((iid) != SSAM_SSH_IID_ANY) ? SSAM_MATCH_INSTANCE : 0) \
| (((fun) != SSAM_SSH_FUN_ANY) ? SSAM_MATCH_FUNCTION : 0), \
.domain = d, \
.category = cat, \
.target = __builtin_choose_expr((tid) != SSAM_SSH_TID_ANY, (tid), 0), \
.instance = __builtin_choose_expr((iid) != SSAM_SSH_IID_ANY, (iid), 0), \
.function = __builtin_choose_expr((fun) != SSAM_SSH_FUN_ANY, (fun), 0)
/**
* SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
* the given parameters.
* @cat: Target category of the device.
* @tid: Target ID of the device.
* @iid: Instance ID of the device.
* @fun: Sub-function of the device.
*
* Initializes a &struct ssam_device_id with the given parameters in the
* virtual domain. See &struct ssam_device_uid for details regarding the
* parameters. The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and
* %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target ID,
* instance ID, and/or sub-function, respectively. This macro initializes the
* ``match_flags`` field based on the given parameters.
*
* Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
* @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
* %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not
* allowed.
*/
#define SSAM_VDEV(cat, tid, iid, fun) \
SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, SSAM_SSH_TID_##tid, iid, fun)
/**
* SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
* with the given parameters.
* @cat: Target category of the device.
* @tid: Target ID of the device.
* @iid: Instance ID of the device.
* @fun: Sub-function of the device.
*
* Initializes a &struct ssam_device_id with the given parameters in the SSH
* domain. See &struct ssam_device_uid for details regarding the parameters.
* The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and
* %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target
* ID, instance ID, and/or sub-function, respectively. This macro initializes
* the ``match_flags`` field based on the given parameters.
*
* Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
* @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY,
* %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values
* are not allowed.
*/
#define SSAM_SDEV(cat, tid, iid, fun) \
SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, SSAM_SSH_TID_##tid, iid, fun)
/*
* enum ssam_device_flags - Flags for SSAM client devices.
* @SSAM_DEVICE_HOT_REMOVED_BIT:
* The device has been hot-removed. Further communication with it may time
* out and should be avoided.
*/
enum ssam_device_flags {
SSAM_DEVICE_HOT_REMOVED_BIT = 0,
};
/**
* struct ssam_device - SSAM client device.
* @dev: Driver model representation of the device.
* @ctrl: SSAM controller managing this device.
* @uid: UID identifying the device.
* @flags: Device state flags, see &enum ssam_device_flags.
*/
struct ssam_device {
struct device dev;
struct ssam_controller *ctrl;
struct ssam_device_uid uid;
unsigned long flags;
};
/**
* struct ssam_device_driver - SSAM client device driver.
* @driver: Base driver model structure.
* @match_table: Match table specifying which devices the driver should bind to.
* @probe: Called when the driver is being bound to a device.
* @remove: Called when the driver is being unbound from the device.
*/
struct ssam_device_driver {
struct device_driver driver;
const struct ssam_device_id *match_table;
int (*probe)(struct ssam_device *sdev);
void (*remove)(struct ssam_device *sdev);
};
#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
extern struct bus_type ssam_bus_type;
extern const struct device_type ssam_device_type;
/**
* is_ssam_device() - Check if the given device is a SSAM client device.
* @d: The device to test the type of.
*
* Return: Returns %true if the specified device is of type &struct
* ssam_device, i.e. the device type points to %ssam_device_type, and %false
* otherwise.
*/
static inline bool is_ssam_device(struct device *d)
{
return d->type == &ssam_device_type;
}
#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
static inline bool is_ssam_device(struct device *d)
{
return false;
}
#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
/**
* to_ssam_device() - Casts the given device to a SSAM client device.
* @d: The device to cast.
*
* Casts the given &struct device to a &struct ssam_device. The caller has to
* ensure that the given device is actually enclosed in a &struct ssam_device,
* e.g. by calling is_ssam_device().
*
* Return: Returns a pointer to the &struct ssam_device wrapping the given
* device @d.
*/
#define to_ssam_device(d) container_of_const(d, struct ssam_device, dev)
/**
* to_ssam_device_driver() - Casts the given device driver to a SSAM client
* device driver.
* @d: The driver to cast.
*
* Casts the given &struct device_driver to a &struct ssam_device_driver. The
* caller has to ensure that the given driver is actually enclosed in a
* &struct ssam_device_driver.
*
* Return: Returns the pointer to the &struct ssam_device_driver wrapping the
* given device driver @d.
*/
static inline
struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d)
{
return container_of(d, struct ssam_device_driver, driver);
}
const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
const struct ssam_device_uid uid);
const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);
const void *ssam_device_get_match_data(const struct ssam_device *dev);
struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
struct ssam_device_uid uid);
int ssam_device_add(struct ssam_device *sdev);
void ssam_device_remove(struct ssam_device *sdev);
/**
* ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
* @sdev: The device to mark as hot-removed.
*
* Mark the device as having been hot-removed. This signals drivers using the
* device that communication with the device should be avoided and may lead to
* timeouts.
*/
static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
{
dev_dbg(&sdev->dev, "marking device as hot-removed\n");
set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
}
/**
* ssam_device_is_hot_removed() - Check if the given device has been
* hot-removed.
* @sdev: The device to check.
*
* Checks if the given device has been marked as hot-removed. See
* ssam_device_mark_hot_removed() for more details.
*
* Return: Returns ``true`` if the device has been marked as hot-removed.
*/
static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
{
return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
}
/**
* ssam_device_get() - Increment reference count of SSAM client device.
* @sdev: The device to increment the reference count of.
*
* Increments the reference count of the given SSAM client device by
* incrementing the reference count of the enclosed &struct device via
* get_device().
*
* See ssam_device_put() for the counter-part of this function.
*
* Return: Returns the device provided as input.
*/
static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
{
return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
}
/**
* ssam_device_put() - Decrement reference count of SSAM client device.
* @sdev: The device to decrement the reference count of.
*
* Decrements the reference count of the given SSAM client device by
* decrementing the reference count of the enclosed &struct device via
* put_device().
*
* See ssam_device_get() for the counter-part of this function.
*/
static inline void ssam_device_put(struct ssam_device *sdev)
{
if (sdev)
put_device(&sdev->dev);
}
/**
* ssam_device_get_drvdata() - Get driver-data of SSAM client device.
* @sdev: The device to get the driver-data from.
*
* Return: Returns the driver-data of the given device, previously set via
* ssam_device_set_drvdata().
*/
static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
{
return dev_get_drvdata(&sdev->dev);
}
/**
* ssam_device_set_drvdata() - Set driver-data of SSAM client device.
* @sdev: The device to set the driver-data of.
* @data: The data to set the device's driver-data pointer to.
*/
static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
{
dev_set_drvdata(&sdev->dev, data);
}
int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
void ssam_device_driver_unregister(struct ssam_device_driver *d);
/**
* ssam_device_driver_register() - Register a SSAM client device driver.
* @drv: The driver to register.
*/
#define ssam_device_driver_register(drv) \
__ssam_device_driver_register(drv, THIS_MODULE)
/**
* module_ssam_device_driver() - Helper macro for SSAM device driver
* registration.
* @drv: The driver managed by this module.
*
* Helper macro to register a SSAM device driver via module_init() and
* module_exit(). This macro may only be used once per module and replaces the
* aforementioned definitions.
*/
#define module_ssam_device_driver(drv) \
module_driver(drv, ssam_device_driver_register, \
ssam_device_driver_unregister)
/* -- Helpers for controller and hub devices. ------------------------------- */
#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
struct fwnode_handle *node);
void ssam_remove_clients(struct device *dev);
#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
struct fwnode_handle *node)
{
return 0;
}
static inline void ssam_remove_clients(struct device *dev) {}
#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
/**
* ssam_register_clients() - Register all client devices defined under the
* given parent device.
* @dev: The parent device under which clients should be registered.
* @ctrl: The controller with which client should be registered.
*
* Register all clients that have via firmware nodes been defined as children
* of the given (parent) device. The respective child firmware nodes will be
* associated with the correspondingly created child devices.
*
* The given controller will be used to instantiate the new devices. See
* ssam_device_add() for details.
*
* Return: Returns zero on success, nonzero on failure.
*/
static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
{
return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
}
/**
* ssam_device_register_clients() - Register all client devices defined under
* the given SSAM parent device.
* @sdev: The parent device under which clients should be registered.
*
* Register all clients that have via firmware nodes been defined as children
* of the given (parent) device. The respective child firmware nodes will be
* associated with the correspondingly created child devices.
*
* The controller used by the parent device will be used to instantiate the new
* devices. See ssam_device_add() for details.
*
* Return: Returns zero on success, nonzero on failure.
*/
static inline int ssam_device_register_clients(struct ssam_device *sdev)
{
return ssam_register_clients(&sdev->dev, sdev->ctrl);
}
/* -- Helpers for client-device requests. ----------------------------------- */
/**
* SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM
* request function with neither argument nor return value.
* @name: Name of the generated function.
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
*
* Defines a function executing the synchronous SAM request specified by
* @spec, with the request having neither argument nor return value. Device
* specifying parameters are not hard-coded, but instead are provided via the
* client device, specifically its UID, supplied when calling this function.
* The generated function takes care of setting up the request struct, buffer
* allocation, as well as execution of the request itself, returning once the
* request has been fully completed. The required transport buffer will be
* allocated on the stack.
*
* The generated function is defined as ``static int name(struct ssam_device
* *sdev)``, returning the status of the request, which is zero on success and
* negative on failure. The ``sdev`` parameter specifies both the target
* device of the request and by association the controller via which the
* request is sent.
*
* Refer to ssam_request_do_sync_onstack() for more details on the behavior of
* the generated function.
*/
#define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \
static int name(struct ssam_device *sdev) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance); \
}
/**
* SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
* request function with argument.
* @name: Name of the generated function.
* @atype: Type of the request's argument.
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
*
* Defines a function executing the synchronous SAM request specified by
* @spec, with the request taking an argument of type @atype and having no
* return value. Device specifying parameters are not hard-coded, but instead
* are provided via the client device, specifically its UID, supplied when
* calling this function. The generated function takes care of setting up the
* request struct, buffer allocation, as well as execution of the request
* itself, returning once the request has been fully completed. The required
* transport buffer will be allocated on the stack.
*
* The generated function is defined as ``static int name(struct ssam_device
* *sdev, const atype *arg)``, returning the status of the request, which is
* zero on success and negative on failure. The ``sdev`` parameter specifies
* both the target device of the request and by association the controller via
* which the request is sent. The request's argument is specified via the
* ``arg`` pointer.
*
* Refer to ssam_request_do_sync_onstack() for more details on the behavior of
* the generated function.
*/
#define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \
static int name(struct ssam_device *sdev, const atype *arg) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, arg); \
}
/**
* SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
* request function with return value.
* @name: Name of the generated function.
* @rtype: Type of the request's return value.
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
*
* Defines a function executing the synchronous SAM request specified by
* @spec, with the request taking no argument but having a return value of
* type @rtype. Device specifying parameters are not hard-coded, but instead
* are provided via the client device, specifically its UID, supplied when
* calling this function. The generated function takes care of setting up the
* request struct, buffer allocation, as well as execution of the request
* itself, returning once the request has been fully completed. The required
* transport buffer will be allocated on the stack.
*
* The generated function is defined as ``static int name(struct ssam_device
* *sdev, rtype *ret)``, returning the status of the request, which is zero on
* success and negative on failure. The ``sdev`` parameter specifies both the
* target device of the request and by association the controller via which
* the request is sent. The request's return value is written to the memory
* pointed to by the ``ret`` parameter.
*
* Refer to ssam_request_do_sync_onstack() for more details on the behavior of
* the generated function.
*/
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
static int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
/**
* SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
* request function with argument and return value.
* @name: Name of the generated function.
* @atype: Type of the request's argument.
* @rtype: Type of the request's return value.
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
*
* Defines a function executing the synchronous SAM request specified by @spec,
* with the request taking an argument of type @atype and having a return value
* of type @rtype. Device specifying parameters are not hard-coded, but instead
* are provided via the client device, specifically its UID, supplied when
* calling this function. The generated function takes care of setting up the
* request struct, buffer allocation, as well as execution of the request
* itself, returning once the request has been fully completed. The required
* transport buffer will be allocated on the stack.
*
* The generated function is defined as ``static int name(struct ssam_device
* *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
* which is zero on success and negative on failure. The ``sdev`` parameter
* specifies both the target device of the request and by association the
* controller via which the request is sent. The request's argument is
* specified via the ``arg`` pointer. The request's return value is written to
* the memory pointed to by the ``ret`` parameter.
*
* Refer to ssam_request_do_sync_onstack() for more details on the behavior of
* the generated function.
*/
#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \
static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, arg, ret); \
}
/* -- Helpers for client-device notifiers. ---------------------------------- */
/**
* ssam_device_notifier_register() - Register an event notifier for the
* specified client device.
* @sdev: The device the notifier should be registered on.
* @n: The event notifier to register.
*
* Register an event notifier. Increment the usage counter of the associated
* SAM event if the notifier is not marked as an observer. If the event is not
* marked as an observer and is currently not enabled, it will be enabled
* during this call. If the notifier is marked as an observer, no attempt will
* be made at enabling any event and no reference count will be modified.
*
* Notifiers marked as observers do not need to be associated with one specific
* event, i.e. as long as no event matching is performed, only the event target
* category needs to be set.
*
* Return: Returns zero on success, %-ENOSPC if there have already been
* %INT_MAX notifiers for the event ID/type associated with the notifier block
* registered, %-ENOMEM if the corresponding event entry could not be
* allocated, %-ENODEV if the device is marked as hot-removed. If this is the
* first time that a notifier block is registered for the specific associated
* event, returns the status of the event-enable EC-command.
*/
static inline int ssam_device_notifier_register(struct ssam_device *sdev,
struct ssam_event_notifier *n)
{
/*
* Note that this check does not provide any guarantees whatsoever as
* hot-removal could happen at any point and we can't protect against
* it. Nevertheless, if we can detect hot-removal, bail early to avoid
* communication timeouts.
*/
if (ssam_device_is_hot_removed(sdev))
return -ENODEV;
return ssam_notifier_register(sdev->ctrl, n);
}
/**
* ssam_device_notifier_unregister() - Unregister an event notifier for the
* specified client device.
* @sdev: The device the notifier has been registered on.
* @n: The event notifier to unregister.
*
* Unregister an event notifier. Decrement the usage counter of the associated
* SAM event if the notifier is not marked as an observer. If the usage counter
* reaches zero, the event will be disabled.
*
* In case the device has been marked as hot-removed, the event will not be
* disabled on the EC, as in those cases any attempt at doing so may time out.
*
* Return: Returns zero on success, %-ENOENT if the given notifier block has
* not been registered on the controller. If the given notifier block was the
* last one associated with its specific event, returns the status of the
* event-disable EC-command.
*/
static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
struct ssam_event_notifier *n)
{
return __ssam_notifier_unregister(sdev->ctrl, n,
!ssam_device_is_hot_removed(sdev));
}
#endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */