platform-drivers-x86 for v5.12-1
- Microsoft Surface devices System Aggregator Module support
- SW_TABLET_MODE reporting improvements
- thinkpad_acpi keyboard language setting support
- platform / DPTF profile settings support
- Base / userspace API parts merged from Rafael's acpi-platform branch
- thinkpad_acpi and ideapad-laptop support through pdx86
- Remove support for some obsolete Intel MID platforms through merging
of the shared intel-mid-removal branch
- Big cleanup of the ideapad-laptop driver
- Misc. other fixes / new hw support / quirks
The following is an automated git shortlog grouped by driver:
ACPI:
- platform-profile: Fix possible deadlock in platform_profile_remove()
- platform-profile: Introduce object pointers to callbacks
- platform-profile: Drop const qualifier for cur_profile
- platform: Add platform profile support
Documentation:
- Add documentation for new platform_profile sysfs attribute
Documentation/ABI:
- sysfs-platform-ideapad-laptop: conservation_mode attribute
- sysfs-platform-ideapad-laptop: update device attribute paths
Kconfig:
- add missing selects for ideapad-laptop
MAINTAINERS:
- update email address for Henrique de Moraes Holschuh
Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-hans:
- Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-hans
Merge remote-tracking branch 'linux-pm/acpi-platform' into review-hans:
- Merge remote-tracking branch 'linux-pm/acpi-platform' into review-hans
Merge tag 'ib-drm-gpio-pdx86-rtc-wdt-v5.12-1' into for-next:
- Merge tag 'ib-drm-gpio-pdx86-rtc-wdt-v5.12-1' into for-next
Move all dell drivers to their own subdirectory:
- Move all dell drivers to their own subdirectory
Platform:
- OLPC: Constify static struct regulator_ops
- OLPC: Specify the enable time
- OLPC: Remove dcon_rdev from olpc_ec_priv
- OLPC: Fix probe error handling
Revert "platform/x86:
- ideapad-laptop: Switch touchpad attribute to be RO"
acer-wmi:
- Don't use ACPI_EXCEPTION()
amd-pmc:
- put device on error paths
- Fix CONFIG_DEBUG_FS check
dell-wmi-sysman:
- fix a NULL pointer dereference
docs:
- driver-api: Add Surface Aggregator subsystem documentation
drm/gma500:
- Get rid of duplicate NULL checks
- Convert to use new SCU IPC API
gpio:
- msic: Remove driver for deprecated platform
- intel-mid: Remove driver for deprecated platform
hp-wmi:
- Disable tablet-mode reporting by default
- Don't log a warning on HPWMI_RET_UNKNOWN_COMMAND errors
i2c-multi-instantiate:
- Don't create platform device for INT3515 ACPI nodes
ideapad-laptop:
- add "always on USB charging" control support
- add keyboard backlight control support
- send notification about touchpad state change to sysfs
- fix checkpatch warnings, more consistent style
- change 'cfg' debugfs file format
- change 'status' debugfs file format
- check for touchpad support in _CFG
- check for Fn-lock support in HALS
- rework is_visible() logic
- rework and create new ACPI helpers
- group and separate (un)related constants into enums
- misc. device attribute changes
- always propagate error codes from device attributes' show() callback
- convert ACPI helpers to return -EIO in case of failure
- use dev_{err,warn} or appropriate variant to display log messages
- use msecs_to_jiffies() helper instead of hand-crafted formula
- use for_each_set_bit() helper to simplify event processing
- use kobj_to_dev()
- use device_{add,remove}_group
- use sysfs_emit()
- add missing call to submodule destructor
- sort includes lexicographically
- use appropriately typed variable to store the return value of ACPI methods
- remove unnecessary NULL checks
- remove unnecessary dev_set_drvdata() call
- DYTC Platform profile support
- Disable touchpad_switch for ELAN0634
intel-vbtn:
- Eval VBDL after registering our notifier
- Add alternative method to enable switches
- Create 2 separate input-devs for buttons and switches
- Rework wakeup handling in notify_handler()
- Drop HP Stream x360 Convertible PC 11 from allow-list
- Support for tablet mode on Dell Inspiron 7352
intel_mid_powerbtn:
- Remove driver for deprecated platform
- Remove driver for deprecated platform
intel_mid_thermal:
- Remove driver for deprecated platform
- Remove driver for deprecated platform
intel_pmt:
- Make INTEL_PMT_CLASS non-user-selectable
intel_pmt_crashlog:
- Add dependency on MFD_INTEL_PMT
intel_pmt_telemetry:
- Add dependency on MFD_INTEL_PMT
intel_scu_ipc:
- Increase virtual timeout from 3 to 5 seconds
intel_scu_wdt:
- Drop mistakenly added const
- Get rid of custom x86 model comparison
- Drop SCU notification
- Move driver from arch/x86
msi-wmi:
- Fix variable 'status' set but not used compiler warning
platform/surface:
- aggregator: Fix access of unaligned value
- Add Surface Hot-Plug driver
- surface3-wmi: Fix variable 'status' set but not used compiler warning
- aggregator: Fix braces in if condition with unlikely() macro
- aggregator: Fix kernel-doc references
- aggregator: fix a kernel-doc markup
- aggregator_cdev: Add comments regarding unchecked allocation size
- aggregator_cdev: Fix access of uninitialized variables
- fix potential integer overflow on shift of a int
- Add Surface ACPI Notify driver
- Add Surface Aggregator user-space interface
- aggregator: Add dedicated bus and device type
- aggregator: Add error injection capabilities
- aggregator: Add trace points
- aggregator: Add event item allocation caching
- aggregator: Add control packet allocation caching
- Add Surface Aggregator subsystem
- SURFACE_PLATFORMS should depend on ACPI
- surface_gpe: Fix non-PM_SLEEP build warnings
platform/x86/intel-uncore-freq:
- Add Sapphire Rapids server support
rtc:
- mrst: Remove driver for deprecated platform
sony-laptop:
- Remove unneeded semicolon
thinkpad_acpi:
- Replace ifdef CONFIG_ACPI_PLATFORM_PROFILE with depends on
- Fix 'warning: no previous prototype for' warnings
- Add platform profile support
- fixed warning and incorporated review comments
- rectify length of title underline
- Don't register keyboard_lang unnecessarily
- set keyboard language
- Add P53/73 firmware to fan_quirk_table for dual fan control
- correct palmsensor error checking
tools/power/x86/intel-speed-select:
- Update version to 1.8
- Add new command to get/set TRL
- Add new command turbo-mode
- Set higher of cpuinfo_max_freq or base_frequency
- Set scaling_max_freq to base_frequency
touchscreen_dmi:
- Add info for the Jumper EZpad 7 tablet
- Add swap-x-y quirk for Goodix touchscreen on Estar Beauty HD tablet
watchdog:
- intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
- intel_scu_watchdog: Remove driver for deprecated platform
-----BEGIN PGP SIGNATURE-----
iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmAqZ5cUHGhkZWdvZWRl
QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9zmuwf/XLoZzs6oW7Ps9DhkyU5lk7D79rti
DY4AabVnWZhJ+Yl5+qMCTjC0R0nJYoq9PCDU5q20HHSFq7PXV0fPEVo7ZOp8tPng
wdzb2glbtGjSWksjj3c8eB/jjPP0tpsWptH+9jlTv9yXwQNVh/rPVltmD+z8y69U
qNzySltQMtoKmQKNbktUeHA12jBldnH+QlkL8KUp5ZEVDd7gukkmAovpzEcnwk5U
lrza7I52c9Ggu1pD2OCX7an9tk6N7mQ6Rk2/c6GzRsOYa6SC5Aj7fi2bs0LRdGGx
Kz/gtKS3dRIreEs4LGmL8byVi7a/YvCQoTfO+MxKq/btedBwxO2edDDsRg==
=B+Fz
-----END PGP SIGNATURE-----
Merge tag 'platform-drivers-x86-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Hans de Goede:
"Highlights:
- Microsoft Surface devices System Aggregator Module support
- SW_TABLET_MODE reporting improvements
- thinkpad_acpi keyboard language setting support
- platform / DPTF profile settings support:
- Base / userspace API parts merged from Rafael's acpi-platform
branch
- thinkpad_acpi and ideapad-laptop support through pdx86
- Remove support for some obsolete Intel MID platforms through
merging of the shared intel-mid-removal branch
- Big cleanup of the ideapad-laptop driver
- Misc other fixes / new hw support / quirks"
* tag 'platform-drivers-x86-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (99 commits)
platform/x86: intel_scu_ipc: Increase virtual timeout from 3 to 5 seconds
platform/surface: aggregator: Fix access of unaligned value
tools/power/x86/intel-speed-select: Update version to 1.8
tools/power/x86/intel-speed-select: Add new command to get/set TRL
tools/power/x86/intel-speed-select: Add new command turbo-mode
Platform: OLPC: Constify static struct regulator_ops
platform/surface: Add Surface Hot-Plug driver
platform/x86: intel_scu_wdt: Drop mistakenly added const
platform/x86: Kconfig: add missing selects for ideapad-laptop
platform/x86: acer-wmi: Don't use ACPI_EXCEPTION()
platform/x86: thinkpad_acpi: Replace ifdef CONFIG_ACPI_PLATFORM_PROFILE with depends on
platform/x86: thinkpad_acpi: Fix 'warning: no previous prototype for' warnings
platform/x86: msi-wmi: Fix variable 'status' set but not used compiler warning
platform/surface: surface3-wmi: Fix variable 'status' set but not used compiler warning
platform/x86: Move all dell drivers to their own subdirectory
Documentation/ABI: sysfs-platform-ideapad-laptop: conservation_mode attribute
Documentation/ABI: sysfs-platform-ideapad-laptop: update device attribute paths
platform/x86: ideapad-laptop: add "always on USB charging" control support
platform/x86: ideapad-laptop: add keyboard backlight control support
platform/x86: ideapad-laptop: send notification about touchpad state change to sysfs
...
This commit is contained in:
commit
983e4adae0
108 changed files with 16567 additions and 3474 deletions
|
|
@ -846,4 +846,22 @@ struct auxiliary_device_id {
|
|||
kernel_ulong_t driver_data;
|
||||
};
|
||||
|
||||
/* Surface System Aggregator Module */
|
||||
|
||||
#define SSAM_MATCH_TARGET 0x1
|
||||
#define SSAM_MATCH_INSTANCE 0x2
|
||||
#define SSAM_MATCH_FUNCTION 0x4
|
||||
|
||||
struct ssam_device_id {
|
||||
__u8 match_flags;
|
||||
|
||||
__u8 domain;
|
||||
__u8 category;
|
||||
__u8 target;
|
||||
__u8 instance;
|
||||
__u8 function;
|
||||
|
||||
kernel_ulong_t driver_data;
|
||||
};
|
||||
|
||||
#endif /* LINUX_MOD_DEVICETABLE_H */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#if IS_ENABLED(CONFIG_SONY_LAPTOP)
|
||||
int sony_pic_camera_command(int command, u8 value);
|
||||
#else
|
||||
static inline int sony_pic_camera_command(int command, u8 value) { return 0; };
|
||||
static inline int sony_pic_camera_command(int command, u8 value) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
|||
39
include/linux/surface_acpi_notify.h
Normal file
39
include/linux/surface_acpi_notify.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Interface for Surface ACPI Notify (SAN) driver.
|
||||
*
|
||||
* Provides access to discrete GPU notifications sent from ACPI via the SAN
|
||||
* driver, which are not handled by this driver directly.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SURFACE_ACPI_NOTIFY_H
|
||||
#define _LINUX_SURFACE_ACPI_NOTIFY_H
|
||||
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* struct san_dgpu_event - Discrete GPU ACPI event.
|
||||
* @category: Category of the event.
|
||||
* @target: Target ID of the event source.
|
||||
* @command: Command ID of the event.
|
||||
* @instance: Instance ID of the event source.
|
||||
* @length: Length of the event's payload data (in bytes).
|
||||
* @payload: Pointer to the event's payload data.
|
||||
*/
|
||||
struct san_dgpu_event {
|
||||
u8 category;
|
||||
u8 target;
|
||||
u8 command;
|
||||
u8 instance;
|
||||
u16 length;
|
||||
u8 *payload;
|
||||
};
|
||||
|
||||
int san_client_link(struct device *client);
|
||||
int san_dgpu_notifier_register(struct notifier_block *nb);
|
||||
int san_dgpu_notifier_unregister(struct notifier_block *nb);
|
||||
|
||||
#endif /* _LINUX_SURFACE_ACPI_NOTIFY_H */
|
||||
824
include/linux/surface_aggregator/controller.h
Normal file
824
include/linux/surface_aggregator/controller.h
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Surface System Aggregator Module (SSAM) controller interface.
|
||||
*
|
||||
* Main communication interface for the SSAM EC. Provides a controller
|
||||
* managing access and communication to and from the SSAM EC, as well as main
|
||||
* communication structures and definitions.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
|
||||
#define _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/surface_aggregator/serial_hub.h>
|
||||
|
||||
|
||||
/* -- Main data types and definitions --------------------------------------- */
|
||||
|
||||
/**
|
||||
* enum ssam_event_flags - Flags for enabling/disabling SAM events
|
||||
* @SSAM_EVENT_SEQUENCED: The event will be sent via a sequenced data frame.
|
||||
*/
|
||||
enum ssam_event_flags {
|
||||
SSAM_EVENT_SEQUENCED = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssam_event - SAM event sent from the EC to the host.
|
||||
* @target_category: Target category of the event source. See &enum ssam_ssh_tc.
|
||||
* @target_id: Target ID of the event source.
|
||||
* @command_id: Command ID of the event.
|
||||
* @instance_id: Instance ID of the event source.
|
||||
* @length: Length of the event payload in bytes.
|
||||
* @data: Event payload data.
|
||||
*/
|
||||
struct ssam_event {
|
||||
u8 target_category;
|
||||
u8 target_id;
|
||||
u8 command_id;
|
||||
u8 instance_id;
|
||||
u16 length;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ssam_request_flags - Flags for SAM requests.
|
||||
*
|
||||
* @SSAM_REQUEST_HAS_RESPONSE:
|
||||
* Specifies that the request expects a response. If not set, the request
|
||||
* will be directly completed after its underlying packet has been
|
||||
* transmitted. If set, the request transport system waits for a response
|
||||
* of the request.
|
||||
*
|
||||
* @SSAM_REQUEST_UNSEQUENCED:
|
||||
* Specifies that the request should be transmitted via an unsequenced
|
||||
* packet. If set, the request must not have a response, meaning that this
|
||||
* flag and the %SSAM_REQUEST_HAS_RESPONSE flag are mutually exclusive.
|
||||
*/
|
||||
enum ssam_request_flags {
|
||||
SSAM_REQUEST_HAS_RESPONSE = BIT(0),
|
||||
SSAM_REQUEST_UNSEQUENCED = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssam_request - SAM request description.
|
||||
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
||||
* @target_id: ID of the request's target.
|
||||
* @command_id: Command ID of the request.
|
||||
* @instance_id: Instance ID of the request's target.
|
||||
* @flags: Flags for the request. See &enum ssam_request_flags.
|
||||
* @length: Length of the request payload in bytes.
|
||||
* @payload: Request payload data.
|
||||
*
|
||||
* This struct fully describes a SAM request with payload. It is intended to
|
||||
* help set up the actual transport struct, e.g. &struct ssam_request_sync,
|
||||
* and specifically its raw message data via ssam_request_write_data().
|
||||
*/
|
||||
struct ssam_request {
|
||||
u8 target_category;
|
||||
u8 target_id;
|
||||
u8 command_id;
|
||||
u8 instance_id;
|
||||
u16 flags;
|
||||
u16 length;
|
||||
const u8 *payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssam_response - Response buffer for SAM request.
|
||||
* @capacity: Capacity of the buffer, in bytes.
|
||||
* @length: Length of the actual data stored in the memory pointed to by
|
||||
* @pointer, in bytes. Set by the transport system.
|
||||
* @pointer: Pointer to the buffer's memory, storing the response payload data.
|
||||
*/
|
||||
struct ssam_response {
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
u8 *pointer;
|
||||
};
|
||||
|
||||
struct ssam_controller;
|
||||
|
||||
struct ssam_controller *ssam_get_controller(void);
|
||||
struct ssam_controller *ssam_client_bind(struct device *client);
|
||||
int ssam_client_link(struct ssam_controller *ctrl, struct device *client);
|
||||
|
||||
struct device *ssam_controller_device(struct ssam_controller *c);
|
||||
|
||||
struct ssam_controller *ssam_controller_get(struct ssam_controller *c);
|
||||
void ssam_controller_put(struct ssam_controller *c);
|
||||
|
||||
void ssam_controller_statelock(struct ssam_controller *c);
|
||||
void ssam_controller_stateunlock(struct ssam_controller *c);
|
||||
|
||||
ssize_t ssam_request_write_data(struct ssam_span *buf,
|
||||
struct ssam_controller *ctrl,
|
||||
const struct ssam_request *spec);
|
||||
|
||||
|
||||
/* -- Synchronous request interface. ---------------------------------------- */
|
||||
|
||||
/**
|
||||
* struct ssam_request_sync - Synchronous SAM request struct.
|
||||
* @base: Underlying SSH request.
|
||||
* @comp: Completion used to signal full completion of the request. After the
|
||||
* request has been submitted, this struct may only be modified or
|
||||
* deallocated after the completion has been signaled.
|
||||
* request has been submitted,
|
||||
* @resp: Buffer to store the response.
|
||||
* @status: Status of the request, set after the base request has been
|
||||
* completed or has failed.
|
||||
*/
|
||||
struct ssam_request_sync {
|
||||
struct ssh_request base;
|
||||
struct completion comp;
|
||||
struct ssam_response *resp;
|
||||
int status;
|
||||
};
|
||||
|
||||
int ssam_request_sync_alloc(size_t payload_len, gfp_t flags,
|
||||
struct ssam_request_sync **rqst,
|
||||
struct ssam_span *buffer);
|
||||
|
||||
void ssam_request_sync_free(struct ssam_request_sync *rqst);
|
||||
|
||||
int ssam_request_sync_init(struct ssam_request_sync *rqst,
|
||||
enum ssam_request_flags flags);
|
||||
|
||||
/**
|
||||
* ssam_request_sync_set_data - Set message data of a synchronous request.
|
||||
* @rqst: The request.
|
||||
* @ptr: Pointer to the request message data.
|
||||
* @len: Length of the request message data.
|
||||
*
|
||||
* Set the request message data of a synchronous request. The provided buffer
|
||||
* needs to live until the request has been completed.
|
||||
*/
|
||||
static inline void ssam_request_sync_set_data(struct ssam_request_sync *rqst,
|
||||
u8 *ptr, size_t len)
|
||||
{
|
||||
ssh_request_set_data(&rqst->base, ptr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* ssam_request_sync_set_resp - Set response buffer of a synchronous request.
|
||||
* @rqst: The request.
|
||||
* @resp: The response buffer.
|
||||
*
|
||||
* Sets the response buffer of a synchronous request. This buffer will store
|
||||
* the response of the request after it has been completed. May be %NULL if no
|
||||
* response is expected.
|
||||
*/
|
||||
static inline void ssam_request_sync_set_resp(struct ssam_request_sync *rqst,
|
||||
struct ssam_response *resp)
|
||||
{
|
||||
rqst->resp = resp;
|
||||
}
|
||||
|
||||
int ssam_request_sync_submit(struct ssam_controller *ctrl,
|
||||
struct ssam_request_sync *rqst);
|
||||
|
||||
/**
|
||||
* ssam_request_sync_wait - Wait for completion of a synchronous request.
|
||||
* @rqst: The request to wait for.
|
||||
*
|
||||
* Wait for completion and release of a synchronous request. After this
|
||||
* function terminates, the request is guaranteed to have left the transport
|
||||
* system. After successful submission of a request, this function must be
|
||||
* called before accessing the response of the request, freeing the request,
|
||||
* or freeing any of the buffers associated with the request.
|
||||
*
|
||||
* This function must not be called if the request has not been submitted yet
|
||||
* and may lead to a deadlock/infinite wait if a subsequent request submission
|
||||
* fails in that case, due to the completion never triggering.
|
||||
*
|
||||
* Return: Returns the status of the given request, which is set on completion
|
||||
* of the packet. This value is zero on success and negative on failure.
|
||||
*/
|
||||
static inline int ssam_request_sync_wait(struct ssam_request_sync *rqst)
|
||||
{
|
||||
wait_for_completion(&rqst->comp);
|
||||
return rqst->status;
|
||||
}
|
||||
|
||||
int ssam_request_sync(struct ssam_controller *ctrl,
|
||||
const struct ssam_request *spec,
|
||||
struct ssam_response *rsp);
|
||||
|
||||
int ssam_request_sync_with_buffer(struct ssam_controller *ctrl,
|
||||
const struct ssam_request *spec,
|
||||
struct ssam_response *rsp,
|
||||
struct ssam_span *buf);
|
||||
|
||||
/**
|
||||
* ssam_request_sync_onstack - Execute a synchronous request on the stack.
|
||||
* @ctrl: The controller via which the request is submitted.
|
||||
* @rqst: The request specification.
|
||||
* @rsp: The response buffer.
|
||||
* @payload_len: The (maximum) request payload length.
|
||||
*
|
||||
* Allocates a synchronous request with specified payload length on the stack,
|
||||
* fully initializes it via the provided request specification, submits it,
|
||||
* and finally waits for its completion before returning its status. This
|
||||
* helper macro essentially allocates the request message buffer on the stack
|
||||
* and then calls ssam_request_sync_with_buffer().
|
||||
*
|
||||
* Note: The @payload_len parameter specifies the maximum payload length, used
|
||||
* for buffer allocation. The actual payload length may be smaller.
|
||||
*
|
||||
* Return: Returns the status of the request or any failure during setup, i.e.
|
||||
* zero on success and a negative value on failure.
|
||||
*/
|
||||
#define ssam_request_sync_onstack(ctrl, rqst, rsp, payload_len) \
|
||||
({ \
|
||||
u8 __data[SSH_COMMAND_MESSAGE_LENGTH(payload_len)]; \
|
||||
struct ssam_span __buf = { &__data[0], ARRAY_SIZE(__data) }; \
|
||||
\
|
||||
ssam_request_sync_with_buffer(ctrl, rqst, rsp, &__buf); \
|
||||
})
|
||||
|
||||
/**
|
||||
* __ssam_retry - Retry request in case of I/O errors or timeouts.
|
||||
* @request: The request function to execute. Must return an integer.
|
||||
* @n: Number of tries.
|
||||
* @args: Arguments for the request function.
|
||||
*
|
||||
* Executes the given request function, i.e. calls @request. In case the
|
||||
* request returns %-EREMOTEIO (indicates I/O error) or %-ETIMEDOUT (request
|
||||
* or underlying packet timed out), @request will be re-executed again, up to
|
||||
* @n times in total.
|
||||
*
|
||||
* Return: Returns the return value of the last execution of @request.
|
||||
*/
|
||||
#define __ssam_retry(request, n, args...) \
|
||||
({ \
|
||||
int __i, __s = 0; \
|
||||
\
|
||||
for (__i = (n); __i > 0; __i--) { \
|
||||
__s = request(args); \
|
||||
if (__s != -ETIMEDOUT && __s != -EREMOTEIO) \
|
||||
break; \
|
||||
} \
|
||||
__s; \
|
||||
})
|
||||
|
||||
/**
|
||||
* ssam_retry - Retry request in case of I/O errors or timeouts up to three
|
||||
* times in total.
|
||||
* @request: The request function to execute. Must return an integer.
|
||||
* @args: Arguments for the request function.
|
||||
*
|
||||
* Executes the given request function, i.e. calls @request. In case the
|
||||
* request returns %-EREMOTEIO (indicates I/O error) or -%ETIMEDOUT (request
|
||||
* or underlying packet timed out), @request will be re-executed again, up to
|
||||
* three times in total.
|
||||
*
|
||||
* See __ssam_retry() for a more generic macro for this purpose.
|
||||
*
|
||||
* Return: Returns the return value of the last execution of @request.
|
||||
*/
|
||||
#define ssam_retry(request, args...) \
|
||||
__ssam_retry(request, 3, args)
|
||||
|
||||
/**
|
||||
* struct ssam_request_spec - Blue-print specification of SAM request.
|
||||
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
||||
* @target_id: ID of the request's target.
|
||||
* @command_id: Command ID of the request.
|
||||
* @instance_id: Instance ID of the request's target.
|
||||
* @flags: Flags for the request. See &enum ssam_request_flags.
|
||||
*
|
||||
* Blue-print specification for a SAM request. This struct describes the
|
||||
* unique static parameters of a request (i.e. type) without specifying any of
|
||||
* its instance-specific data (e.g. payload). It is intended to be used as base
|
||||
* for defining simple request functions via the
|
||||
* ``SSAM_DEFINE_SYNC_REQUEST_x()`` family of macros.
|
||||
*/
|
||||
struct ssam_request_spec {
|
||||
u8 target_category;
|
||||
u8 target_id;
|
||||
u8 command_id;
|
||||
u8 instance_id;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssam_request_spec_md - Blue-print specification for multi-device SAM
|
||||
* request.
|
||||
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
||||
* @command_id: Command ID of the request.
|
||||
* @flags: Flags for the request. See &enum ssam_request_flags.
|
||||
*
|
||||
* Blue-print specification for a multi-device SAM request, i.e. a request
|
||||
* that is applicable to multiple device instances, described by their
|
||||
* individual target and instance IDs. This struct describes the unique static
|
||||
* parameters of a request (i.e. type) without specifying any of its
|
||||
* instance-specific data (e.g. payload) and without specifying any of its
|
||||
* device specific IDs (i.e. target and instance ID). It is intended to be
|
||||
* used as base for defining simple multi-device request functions via the
|
||||
* ``SSAM_DEFINE_SYNC_REQUEST_MD_x()`` and ``SSAM_DEFINE_SYNC_REQUEST_CL_x()``
|
||||
* families of macros.
|
||||
*/
|
||||
struct ssam_request_spec_md {
|
||||
u8 target_category;
|
||||
u8 command_id;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_N() - Define synchronous SAM request function
|
||||
* with neither argument nor return value.
|
||||
* @name: Name of the generated function.
|
||||
* @spec: Specification (&struct ssam_request_spec) defining the request.
|
||||
*
|
||||
* Defines a function executing the synchronous SAM request specified by
|
||||
* @spec, with the request having neither argument nor return value. The
|
||||
* generated function takes care of setting up the request struct and 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 ``int name(struct ssam_controller
|
||||
* *ctrl)``, returning the status of the request, which is zero on success and
|
||||
* negative on failure. The ``ctrl`` parameter is the controller via which the
|
||||
* request is being sent.
|
||||
*
|
||||
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_N(name, spec...) \
|
||||
int name(struct ssam_controller *ctrl) \
|
||||
{ \
|
||||
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
||||
struct ssam_request rqst; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = s.target_id; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = s.instance_id; \
|
||||
rqst.flags = s.flags; \
|
||||
rqst.length = 0; \
|
||||
rqst.payload = NULL; \
|
||||
\
|
||||
return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
|
||||
}
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_W() - Define synchronous SAM request function with
|
||||
* argument.
|
||||
* @name: Name of the generated function.
|
||||
* @atype: Type of the request's argument.
|
||||
* @spec: Specification (&struct ssam_request_spec) 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. 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 ``int name(struct ssam_controller
|
||||
* *ctrl, const atype *arg)``, returning the status of the request, which is
|
||||
* zero on success and negative on failure. The ``ctrl`` parameter is the
|
||||
* controller via which the request is sent. The request argument is specified
|
||||
* via the ``arg`` pointer.
|
||||
*
|
||||
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_W(name, atype, spec...) \
|
||||
int name(struct ssam_controller *ctrl, const atype *arg) \
|
||||
{ \
|
||||
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
||||
struct ssam_request rqst; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = s.target_id; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = s.instance_id; \
|
||||
rqst.flags = s.flags; \
|
||||
rqst.length = sizeof(atype); \
|
||||
rqst.payload = (u8 *)arg; \
|
||||
\
|
||||
return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
|
||||
sizeof(atype)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_R() - Define synchronous 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) 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. The generated function takes care of setting up the request
|
||||
* and response structs, 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 ``int name(struct ssam_controller
|
||||
* *ctrl, rtype *ret)``, returning the status of the request, which is zero on
|
||||
* success and negative on failure. The ``ctrl`` parameter is 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_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_R(name, rtype, spec...) \
|
||||
int name(struct ssam_controller *ctrl, rtype *ret) \
|
||||
{ \
|
||||
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
||||
struct ssam_request rqst; \
|
||||
struct ssam_response rsp; \
|
||||
int status; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = s.target_id; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = s.instance_id; \
|
||||
rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
|
||||
rqst.length = 0; \
|
||||
rqst.payload = NULL; \
|
||||
\
|
||||
rsp.capacity = sizeof(rtype); \
|
||||
rsp.length = 0; \
|
||||
rsp.pointer = (u8 *)ret; \
|
||||
\
|
||||
status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
|
||||
if (status) \
|
||||
return status; \
|
||||
\
|
||||
if (rsp.length != sizeof(rtype)) { \
|
||||
struct device *dev = ssam_controller_device(ctrl); \
|
||||
dev_err(dev, \
|
||||
"rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
|
||||
sizeof(rtype), rsp.length, rqst.target_category,\
|
||||
rqst.command_id); \
|
||||
return -EIO; \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-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 must be provided to
|
||||
* the 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 ``int name(struct ssam_controller
|
||||
* *ctrl, u8 tid, u8 iid)``, returning the status of the request, which is
|
||||
* zero on success and negative on failure. The ``ctrl`` parameter is the
|
||||
* controller via which the request is sent, ``tid`` the target ID for the
|
||||
* request, and ``iid`` the instance ID.
|
||||
*
|
||||
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_MD_N(name, spec...) \
|
||||
int name(struct ssam_controller *ctrl, u8 tid, u8 iid) \
|
||||
{ \
|
||||
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
||||
struct ssam_request rqst; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = tid; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = iid; \
|
||||
rqst.flags = s.flags; \
|
||||
rqst.length = 0; \
|
||||
rqst.payload = NULL; \
|
||||
\
|
||||
return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
|
||||
}
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_MD_W() - Define synchronous multi-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
|
||||
* must be provided to the 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 ``int name(struct ssam_controller
|
||||
* *ctrl, u8 tid, u8 iid, const atype *arg)``, returning the status of the
|
||||
* request, which is zero on success and negative on failure. The ``ctrl``
|
||||
* parameter is the controller via which the request is sent, ``tid`` the
|
||||
* target ID for the request, and ``iid`` the instance ID. The request argument
|
||||
* is specified via the ``arg`` pointer.
|
||||
*
|
||||
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_MD_W(name, atype, spec...) \
|
||||
int name(struct ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg)\
|
||||
{ \
|
||||
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
||||
struct ssam_request rqst; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = tid; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = iid; \
|
||||
rqst.flags = s.flags; \
|
||||
rqst.length = sizeof(atype); \
|
||||
rqst.payload = (u8 *)arg; \
|
||||
\
|
||||
return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
|
||||
sizeof(atype)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* SSAM_DEFINE_SYNC_REQUEST_MD_R() - Define synchronous multi-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
|
||||
* must be provided to the function. The generated function takes care of
|
||||
* setting up the request and response structs, 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 ``int name(struct ssam_controller
|
||||
* *ctrl, u8 tid, u8 iid, rtype *ret)``, returning the status of the request,
|
||||
* which is zero on success and negative on failure. The ``ctrl`` parameter is
|
||||
* the controller via which the request is sent, ``tid`` the target ID for the
|
||||
* request, and ``iid`` the instance ID. The request's return value is written
|
||||
* to the memory pointed to by the ``ret`` parameter.
|
||||
*
|
||||
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
||||
* the generated function.
|
||||
*/
|
||||
#define SSAM_DEFINE_SYNC_REQUEST_MD_R(name, rtype, spec...) \
|
||||
int name(struct ssam_controller *ctrl, u8 tid, u8 iid, rtype *ret) \
|
||||
{ \
|
||||
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
||||
struct ssam_request rqst; \
|
||||
struct ssam_response rsp; \
|
||||
int status; \
|
||||
\
|
||||
rqst.target_category = s.target_category; \
|
||||
rqst.target_id = tid; \
|
||||
rqst.command_id = s.command_id; \
|
||||
rqst.instance_id = iid; \
|
||||
rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
|
||||
rqst.length = 0; \
|
||||
rqst.payload = NULL; \
|
||||
\
|
||||
rsp.capacity = sizeof(rtype); \
|
||||
rsp.length = 0; \
|
||||
rsp.pointer = (u8 *)ret; \
|
||||
\
|
||||
status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
|
||||
if (status) \
|
||||
return status; \
|
||||
\
|
||||
if (rsp.length != sizeof(rtype)) { \
|
||||
struct device *dev = ssam_controller_device(ctrl); \
|
||||
dev_err(dev, \
|
||||
"rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
|
||||
sizeof(rtype), rsp.length, rqst.target_category,\
|
||||
rqst.command_id); \
|
||||
return -EIO; \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
/* -- Event notifier/callbacks. --------------------------------------------- */
|
||||
|
||||
#define SSAM_NOTIF_STATE_SHIFT 2
|
||||
#define SSAM_NOTIF_STATE_MASK ((1 << SSAM_NOTIF_STATE_SHIFT) - 1)
|
||||
|
||||
/**
|
||||
* enum ssam_notif_flags - Flags used in return values from SSAM notifier
|
||||
* callback functions.
|
||||
*
|
||||
* @SSAM_NOTIF_HANDLED:
|
||||
* Indicates that the notification has been handled. This flag should be
|
||||
* set by the handler if the handler can act/has acted upon the event
|
||||
* provided to it. This flag should not be set if the handler is not a
|
||||
* primary handler intended for the provided event.
|
||||
*
|
||||
* If this flag has not been set by any handler after the notifier chain
|
||||
* has been traversed, a warning will be emitted, stating that the event
|
||||
* has not been handled.
|
||||
*
|
||||
* @SSAM_NOTIF_STOP:
|
||||
* Indicates that the notifier traversal should stop. If this flag is
|
||||
* returned from a notifier callback, notifier chain traversal will
|
||||
* immediately stop and any remaining notifiers will not be called. This
|
||||
* flag is automatically set when ssam_notifier_from_errno() is called
|
||||
* with a negative error value.
|
||||
*/
|
||||
enum ssam_notif_flags {
|
||||
SSAM_NOTIF_HANDLED = BIT(0),
|
||||
SSAM_NOTIF_STOP = BIT(1),
|
||||
};
|
||||
|
||||
struct ssam_event_notifier;
|
||||
|
||||
typedef u32 (*ssam_notifier_fn_t)(struct ssam_event_notifier *nf,
|
||||
const struct ssam_event *event);
|
||||
|
||||
/**
|
||||
* struct ssam_notifier_block - Base notifier block for SSAM event
|
||||
* notifications.
|
||||
* @node: The node for the list of notifiers.
|
||||
* @fn: The callback function of this notifier. This function takes the
|
||||
* respective notifier block and event as input and should return
|
||||
* a notifier value, which can either be obtained from the flags
|
||||
* provided in &enum ssam_notif_flags, converted from a standard
|
||||
* error value via ssam_notifier_from_errno(), or a combination of
|
||||
* both (e.g. ``ssam_notifier_from_errno(e) | SSAM_NOTIF_HANDLED``).
|
||||
* @priority: Priority value determining the order in which notifier callbacks
|
||||
* will be called. A higher value means higher priority, i.e. the
|
||||
* associated callback will be executed earlier than other (lower
|
||||
* priority) callbacks.
|
||||
*/
|
||||
struct ssam_notifier_block {
|
||||
struct list_head node;
|
||||
ssam_notifier_fn_t fn;
|
||||
int priority;
|
||||
};
|
||||
|
||||
/**
|
||||
* ssam_notifier_from_errno() - Convert standard error value to notifier
|
||||
* return code.
|
||||
* @err: The error code to convert, must be negative (in case of failure) or
|
||||
* zero (in case of success).
|
||||
*
|
||||
* Return: Returns the notifier return value obtained by converting the
|
||||
* specified @err value. In case @err is negative, the %SSAM_NOTIF_STOP flag
|
||||
* will be set, causing notifier call chain traversal to abort.
|
||||
*/
|
||||
static inline u32 ssam_notifier_from_errno(int err)
|
||||
{
|
||||
if (WARN_ON(err > 0) || err == 0)
|
||||
return 0;
|
||||
else
|
||||
return ((-err) << SSAM_NOTIF_STATE_SHIFT) | SSAM_NOTIF_STOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssam_notifier_to_errno() - Convert notifier return code to standard error
|
||||
* value.
|
||||
* @ret: The notifier return value to convert.
|
||||
*
|
||||
* Return: Returns the negative error value encoded in @ret or zero if @ret
|
||||
* indicates success.
|
||||
*/
|
||||
static inline int ssam_notifier_to_errno(u32 ret)
|
||||
{
|
||||
return -(ret >> SSAM_NOTIF_STATE_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
/* -- Event/notification registry. ------------------------------------------ */
|
||||
|
||||
/**
|
||||
* struct ssam_event_registry - Registry specification used for enabling events.
|
||||
* @target_category: Target category for the event registry requests.
|
||||
* @target_id: Target ID for the event registry requests.
|
||||
* @cid_enable: Command ID for the event-enable request.
|
||||
* @cid_disable: Command ID for the event-disable request.
|
||||
*
|
||||
* This struct describes a SAM event registry via the minimal collection of
|
||||
* SAM IDs specifying the requests to use for enabling and disabling an event.
|
||||
* The individual event to be enabled/disabled itself is specified via &struct
|
||||
* ssam_event_id.
|
||||
*/
|
||||
struct ssam_event_registry {
|
||||
u8 target_category;
|
||||
u8 target_id;
|
||||
u8 cid_enable;
|
||||
u8 cid_disable;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssam_event_id - Unique event ID used for enabling events.
|
||||
* @target_category: Target category of the event source.
|
||||
* @instance: Instance ID of the event source.
|
||||
*
|
||||
* This struct specifies the event to be enabled/disabled via an externally
|
||||
* provided registry. It does not specify the registry to be used itself, this
|
||||
* is done via &struct ssam_event_registry.
|
||||
*/
|
||||
struct ssam_event_id {
|
||||
u8 target_category;
|
||||
u8 instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ssam_event_mask - Flags specifying how events are matched to notifiers.
|
||||
*
|
||||
* @SSAM_EVENT_MASK_NONE:
|
||||
* Run the callback for any event with matching target category. Do not
|
||||
* do any additional filtering.
|
||||
*
|
||||
* @SSAM_EVENT_MASK_TARGET:
|
||||
* In addition to filtering by target category, only execute the notifier
|
||||
* callback for events with a target ID matching to the one of the
|
||||
* registry used for enabling/disabling the event.
|
||||
*
|
||||
* @SSAM_EVENT_MASK_INSTANCE:
|
||||
* In addition to filtering by target category, only execute the notifier
|
||||
* callback for events with an instance ID matching to the instance ID
|
||||
* used when enabling the event.
|
||||
*
|
||||
* @SSAM_EVENT_MASK_STRICT:
|
||||
* Do all the filtering above.
|
||||
*/
|
||||
enum ssam_event_mask {
|
||||
SSAM_EVENT_MASK_TARGET = BIT(0),
|
||||
SSAM_EVENT_MASK_INSTANCE = BIT(1),
|
||||
|
||||
SSAM_EVENT_MASK_NONE = 0,
|
||||
SSAM_EVENT_MASK_STRICT =
|
||||
SSAM_EVENT_MASK_TARGET
|
||||
| SSAM_EVENT_MASK_INSTANCE,
|
||||
};
|
||||
|
||||
/**
|
||||
* SSAM_EVENT_REGISTRY() - Define a new event registry.
|
||||
* @tc: Target category for the event registry requests.
|
||||
* @tid: Target ID for the event registry requests.
|
||||
* @cid_en: Command ID for the event-enable request.
|
||||
* @cid_dis: Command ID for the event-disable request.
|
||||
*
|
||||
* Return: Returns the &struct ssam_event_registry specified by the given
|
||||
* parameters.
|
||||
*/
|
||||
#define SSAM_EVENT_REGISTRY(tc, tid, cid_en, cid_dis) \
|
||||
((struct ssam_event_registry) { \
|
||||
.target_category = (tc), \
|
||||
.target_id = (tid), \
|
||||
.cid_enable = (cid_en), \
|
||||
.cid_disable = (cid_dis), \
|
||||
})
|
||||
|
||||
#define SSAM_EVENT_REGISTRY_SAM \
|
||||
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_SAM, 0x01, 0x0b, 0x0c)
|
||||
|
||||
#define SSAM_EVENT_REGISTRY_KIP \
|
||||
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_KIP, 0x02, 0x27, 0x28)
|
||||
|
||||
#define SSAM_EVENT_REGISTRY_REG \
|
||||
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02)
|
||||
|
||||
/**
|
||||
* struct ssam_event_notifier - Notifier block for SSAM events.
|
||||
* @base: The base notifier block with callback function and priority.
|
||||
* @event: The event for which this block will receive notifications.
|
||||
* @event.reg: Registry via which the event will be enabled/disabled.
|
||||
* @event.id: ID specifying the event.
|
||||
* @event.mask: Flags determining how events are matched to the notifier.
|
||||
* @event.flags: Flags used for enabling the event.
|
||||
*/
|
||||
struct ssam_event_notifier {
|
||||
struct ssam_notifier_block base;
|
||||
|
||||
struct {
|
||||
struct ssam_event_registry reg;
|
||||
struct ssam_event_id id;
|
||||
enum ssam_event_mask mask;
|
||||
u8 flags;
|
||||
} event;
|
||||
};
|
||||
|
||||
int ssam_notifier_register(struct ssam_controller *ctrl,
|
||||
struct ssam_event_notifier *n);
|
||||
|
||||
int ssam_notifier_unregister(struct ssam_controller *ctrl,
|
||||
struct ssam_event_notifier *n);
|
||||
|
||||
#endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */
|
||||
423
include/linux/surface_aggregator/device.h
Normal file
423
include/linux/surface_aggregator/device.h
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
/* 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-2020 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/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_ANY_TID 0xffff
|
||||
#define SSAM_ANY_IID 0xffff
|
||||
#define SSAM_ANY_FUN 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_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN 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_ANY_TID,
|
||||
* %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
|
||||
* allowed.
|
||||
*/
|
||||
#define SSAM_DEVICE(d, cat, tid, iid, fun) \
|
||||
.match_flags = (((tid) != SSAM_ANY_TID) ? SSAM_MATCH_TARGET : 0) \
|
||||
| (((iid) != SSAM_ANY_IID) ? SSAM_MATCH_INSTANCE : 0) \
|
||||
| (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0), \
|
||||
.domain = d, \
|
||||
.category = cat, \
|
||||
.target = ((tid) != SSAM_ANY_TID) ? (tid) : 0, \
|
||||
.instance = ((iid) != SSAM_ANY_IID) ? (iid) : 0, \
|
||||
.function = ((fun) != SSAM_ANY_FUN) ? (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_ANY_TID, %SSAM_ANY_IID, and
|
||||
* %SSAM_ANY_FUN 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_ANY_TID,
|
||||
* %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
|
||||
* allowed.
|
||||
*/
|
||||
#define SSAM_VDEV(cat, tid, iid, fun) \
|
||||
SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, 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_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN 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_ANY_TID,
|
||||
* %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
|
||||
* allowed.
|
||||
*/
|
||||
#define SSAM_SDEV(cat, tid, iid, fun) \
|
||||
SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
|
||||
|
||||
/**
|
||||
* struct ssam_device - SSAM client device.
|
||||
* @dev: Driver model representation of the device.
|
||||
* @ctrl: SSAM controller managing this device.
|
||||
* @uid: UID identifying the device.
|
||||
*/
|
||||
struct ssam_device {
|
||||
struct device dev;
|
||||
struct ssam_controller *ctrl;
|
||||
|
||||
struct ssam_device_uid uid;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static inline struct ssam_device *to_ssam_device(struct device *d)
|
||||
{
|
||||
return container_of(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_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 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 ``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_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) \
|
||||
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 ``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_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) \
|
||||
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 ``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_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) \
|
||||
int name(struct ssam_device *sdev, rtype *ret) \
|
||||
{ \
|
||||
return __raw_##name(sdev->ctrl, sdev->uid.target, \
|
||||
sdev->uid.instance, ret); \
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
|
||||
672
include/linux/surface_aggregator/serial_hub.h
Normal file
672
include/linux/surface_aggregator/serial_hub.h
Normal file
|
|
@ -0,0 +1,672 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Surface Serial Hub (SSH) protocol and communication interface.
|
||||
*
|
||||
* Lower-level communication layers and SSH protocol definitions for the
|
||||
* Surface System Aggregator Module (SSAM). Provides the interface for basic
|
||||
* packet- and request-based communication with the SSAM EC via SSH.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SURFACE_AGGREGATOR_SERIAL_HUB_H
|
||||
#define _LINUX_SURFACE_AGGREGATOR_SERIAL_HUB_H
|
||||
|
||||
#include <linux/crc-ccitt.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/* -- Data structures for SAM-over-SSH communication. ----------------------- */
|
||||
|
||||
/**
|
||||
* enum ssh_frame_type - Frame types for SSH frames.
|
||||
*
|
||||
* @SSH_FRAME_TYPE_DATA_SEQ:
|
||||
* Indicates a data frame, followed by a payload with the length specified
|
||||
* in the ``struct ssh_frame.len`` field. This frame is sequenced, meaning
|
||||
* that an ACK is required.
|
||||
*
|
||||
* @SSH_FRAME_TYPE_DATA_NSQ:
|
||||
* Same as %SSH_FRAME_TYPE_DATA_SEQ, but unsequenced, meaning that the
|
||||
* message does not have to be ACKed.
|
||||
*
|
||||
* @SSH_FRAME_TYPE_ACK:
|
||||
* Indicates an ACK message.
|
||||
*
|
||||
* @SSH_FRAME_TYPE_NAK:
|
||||
* Indicates an error response for previously sent frame. In general, this
|
||||
* means that the frame and/or payload is malformed, e.g. a CRC is wrong.
|
||||
* For command-type payloads, this can also mean that the command is
|
||||
* invalid.
|
||||
*/
|
||||
enum ssh_frame_type {
|
||||
SSH_FRAME_TYPE_DATA_SEQ = 0x80,
|
||||
SSH_FRAME_TYPE_DATA_NSQ = 0x00,
|
||||
SSH_FRAME_TYPE_ACK = 0x40,
|
||||
SSH_FRAME_TYPE_NAK = 0x04,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssh_frame - SSH communication frame.
|
||||
* @type: The type of the frame. See &enum ssh_frame_type.
|
||||
* @len: The length of the frame payload directly following the CRC for this
|
||||
* frame. Does not include the final CRC for that payload.
|
||||
* @seq: The sequence number for this message/exchange.
|
||||
*/
|
||||
struct ssh_frame {
|
||||
u8 type;
|
||||
__le16 len;
|
||||
u8 seq;
|
||||
} __packed;
|
||||
|
||||
static_assert(sizeof(struct ssh_frame) == 4);
|
||||
|
||||
/*
|
||||
* SSH_FRAME_MAX_PAYLOAD_SIZE - Maximum SSH frame payload length in bytes.
|
||||
*
|
||||
* This is the physical maximum length of the protocol. Implementations may
|
||||
* set a more constrained limit.
|
||||
*/
|
||||
#define SSH_FRAME_MAX_PAYLOAD_SIZE U16_MAX
|
||||
|
||||
/**
|
||||
* enum ssh_payload_type - Type indicator for the SSH payload.
|
||||
* @SSH_PLD_TYPE_CMD: The payload is a command structure with optional command
|
||||
* payload.
|
||||
*/
|
||||
enum ssh_payload_type {
|
||||
SSH_PLD_TYPE_CMD = 0x80,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssh_command - Payload of a command-type frame.
|
||||
* @type: The type of the payload. See &enum ssh_payload_type. Should be
|
||||
* SSH_PLD_TYPE_CMD for this struct.
|
||||
* @tc: Command target category.
|
||||
* @tid_out: Output target ID. Should be zero if this an incoming (EC to host)
|
||||
* message.
|
||||
* @tid_in: Input target ID. Should be zero if this is an outgoing (host to
|
||||
* EC) message.
|
||||
* @iid: Instance ID.
|
||||
* @rqid: Request ID. Used to match requests with responses and differentiate
|
||||
* between responses and events.
|
||||
* @cid: Command ID.
|
||||
*/
|
||||
struct ssh_command {
|
||||
u8 type;
|
||||
u8 tc;
|
||||
u8 tid_out;
|
||||
u8 tid_in;
|
||||
u8 iid;
|
||||
__le16 rqid;
|
||||
u8 cid;
|
||||
} __packed;
|
||||
|
||||
static_assert(sizeof(struct ssh_command) == 8);
|
||||
|
||||
/*
|
||||
* SSH_COMMAND_MAX_PAYLOAD_SIZE - Maximum SSH command payload length in bytes.
|
||||
*
|
||||
* This is the physical maximum length of the protocol. Implementations may
|
||||
* set a more constrained limit.
|
||||
*/
|
||||
#define SSH_COMMAND_MAX_PAYLOAD_SIZE \
|
||||
(SSH_FRAME_MAX_PAYLOAD_SIZE - sizeof(struct ssh_command))
|
||||
|
||||
/*
|
||||
* SSH_MSG_LEN_BASE - Base-length of a SSH message.
|
||||
*
|
||||
* This is the minimum number of bytes required to form a message. The actual
|
||||
* message length is SSH_MSG_LEN_BASE plus the length of the frame payload.
|
||||
*/
|
||||
#define SSH_MSG_LEN_BASE (sizeof(struct ssh_frame) + 3ull * sizeof(u16))
|
||||
|
||||
/*
|
||||
* SSH_MSG_LEN_CTRL - Length of a SSH control message.
|
||||
*
|
||||
* This is the length of a SSH control message, which is equal to a SSH
|
||||
* message without any payload.
|
||||
*/
|
||||
#define SSH_MSG_LEN_CTRL SSH_MSG_LEN_BASE
|
||||
|
||||
/**
|
||||
* SSH_MESSAGE_LENGTH() - Compute length of SSH message.
|
||||
* @payload_size: Length of the payload inside the SSH frame.
|
||||
*
|
||||
* Return: Returns the length of a SSH message with payload of specified size.
|
||||
*/
|
||||
#define SSH_MESSAGE_LENGTH(payload_size) (SSH_MSG_LEN_BASE + (payload_size))
|
||||
|
||||
/**
|
||||
* SSH_COMMAND_MESSAGE_LENGTH() - Compute length of SSH command message.
|
||||
* @payload_size: Length of the command payload.
|
||||
*
|
||||
* Return: Returns the length of a SSH command message with command payload of
|
||||
* specified size.
|
||||
*/
|
||||
#define SSH_COMMAND_MESSAGE_LENGTH(payload_size) \
|
||||
SSH_MESSAGE_LENGTH(sizeof(struct ssh_command) + (payload_size))
|
||||
|
||||
/**
|
||||
* SSH_MSGOFFSET_FRAME() - Compute offset in SSH message to specified field in
|
||||
* frame.
|
||||
* @field: The field for which the offset should be computed.
|
||||
*
|
||||
* Return: Returns the offset of the specified &struct ssh_frame field in the
|
||||
* raw SSH message data as. Takes SYN bytes (u16) preceding the frame into
|
||||
* account.
|
||||
*/
|
||||
#define SSH_MSGOFFSET_FRAME(field) \
|
||||
(sizeof(u16) + offsetof(struct ssh_frame, field))
|
||||
|
||||
/**
|
||||
* SSH_MSGOFFSET_COMMAND() - Compute offset in SSH message to specified field
|
||||
* in command.
|
||||
* @field: The field for which the offset should be computed.
|
||||
*
|
||||
* Return: Returns the offset of the specified &struct ssh_command field in
|
||||
* the raw SSH message data. Takes SYN bytes (u16) preceding the frame and the
|
||||
* frame CRC (u16) between frame and command into account.
|
||||
*/
|
||||
#define SSH_MSGOFFSET_COMMAND(field) \
|
||||
(2ull * sizeof(u16) + sizeof(struct ssh_frame) \
|
||||
+ offsetof(struct ssh_command, field))
|
||||
|
||||
/*
|
||||
* SSH_MSG_SYN - SSH message synchronization (SYN) bytes as u16.
|
||||
*/
|
||||
#define SSH_MSG_SYN ((u16)0x55aa)
|
||||
|
||||
/**
|
||||
* ssh_crc() - Compute CRC for SSH messages.
|
||||
* @buf: The pointer pointing to the data for which the CRC should be computed.
|
||||
* @len: The length of the data for which the CRC should be computed.
|
||||
*
|
||||
* Return: Returns the CRC computed on the provided data, as used for SSH
|
||||
* messages.
|
||||
*/
|
||||
static inline u16 ssh_crc(const u8 *buf, size_t len)
|
||||
{
|
||||
return crc_ccitt_false(0xffff, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH_NUM_EVENTS - The number of reserved event IDs.
|
||||
*
|
||||
* The number of reserved event IDs, used for registering an SSH event
|
||||
* handler. Valid event IDs are numbers below or equal to this value, with
|
||||
* exception of zero, which is not an event ID. Thus, this is also the
|
||||
* absolute maximum number of event handlers that can be registered.
|
||||
*/
|
||||
#define SSH_NUM_EVENTS 34
|
||||
|
||||
/*
|
||||
* SSH_NUM_TARGETS - The number of communication targets used in the protocol.
|
||||
*/
|
||||
#define SSH_NUM_TARGETS 2
|
||||
|
||||
/**
|
||||
* ssh_rqid_next_valid() - Return the next valid request ID.
|
||||
* @rqid: The current request ID.
|
||||
*
|
||||
* Return: Returns the next valid request ID, following the current request ID
|
||||
* provided to this function. This function skips any request IDs reserved for
|
||||
* events.
|
||||
*/
|
||||
static inline u16 ssh_rqid_next_valid(u16 rqid)
|
||||
{
|
||||
return rqid > 0 ? rqid + 1u : rqid + SSH_NUM_EVENTS + 1u;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_rqid_to_event() - Convert request ID to its corresponding event ID.
|
||||
* @rqid: The request ID to convert.
|
||||
*/
|
||||
static inline u16 ssh_rqid_to_event(u16 rqid)
|
||||
{
|
||||
return rqid - 1u;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_rqid_is_event() - Check if given request ID is a valid event ID.
|
||||
* @rqid: The request ID to check.
|
||||
*/
|
||||
static inline bool ssh_rqid_is_event(u16 rqid)
|
||||
{
|
||||
return ssh_rqid_to_event(rqid) < SSH_NUM_EVENTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_tc_to_rqid() - Convert target category to its corresponding request ID.
|
||||
* @tc: The target category to convert.
|
||||
*/
|
||||
static inline u16 ssh_tc_to_rqid(u8 tc)
|
||||
{
|
||||
return tc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_tid_to_index() - Convert target ID to its corresponding target index.
|
||||
* @tid: The target ID to convert.
|
||||
*/
|
||||
static inline u8 ssh_tid_to_index(u8 tid)
|
||||
{
|
||||
return tid - 1u;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_tid_is_valid() - Check if target ID is valid/supported.
|
||||
* @tid: The target ID to check.
|
||||
*/
|
||||
static inline bool ssh_tid_is_valid(u8 tid)
|
||||
{
|
||||
return ssh_tid_to_index(tid) < SSH_NUM_TARGETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ssam_span - Reference to a buffer region.
|
||||
* @ptr: Pointer to the buffer region.
|
||||
* @len: Length of the buffer region.
|
||||
*
|
||||
* A reference to a (non-owned) buffer segment, consisting of pointer and
|
||||
* length. Use of this struct indicates non-owned data, i.e. data of which the
|
||||
* life-time is managed (i.e. it is allocated/freed) via another pointer.
|
||||
*/
|
||||
struct ssam_span {
|
||||
u8 *ptr;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/*
|
||||
* Known SSH/EC target categories.
|
||||
*
|
||||
* List of currently known target category values; "Known" as in we know they
|
||||
* exist and are valid on at least some device/model. Detailed functionality
|
||||
* or the full category name is only known for some of these categories and
|
||||
* is detailed in the respective comment below.
|
||||
*
|
||||
* These values and abbreviations have been extracted from strings inside the
|
||||
* Windows driver.
|
||||
*/
|
||||
enum ssam_ssh_tc {
|
||||
/* Category 0x00 is invalid for EC use. */
|
||||
SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
|
||||
SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
|
||||
SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
|
||||
SSAM_SSH_TC_PMC = 0x04,
|
||||
SSAM_SSH_TC_FAN = 0x05,
|
||||
SSAM_SSH_TC_PoM = 0x06,
|
||||
SSAM_SSH_TC_DBG = 0x07,
|
||||
SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
|
||||
SSAM_SSH_TC_FWU = 0x09,
|
||||
SSAM_SSH_TC_UNI = 0x0a,
|
||||
SSAM_SSH_TC_LPC = 0x0b,
|
||||
SSAM_SSH_TC_TCL = 0x0c,
|
||||
SSAM_SSH_TC_SFL = 0x0d,
|
||||
SSAM_SSH_TC_KIP = 0x0e,
|
||||
SSAM_SSH_TC_EXT = 0x0f,
|
||||
SSAM_SSH_TC_BLD = 0x10,
|
||||
SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
|
||||
SSAM_SSH_TC_SEN = 0x12,
|
||||
SSAM_SSH_TC_SRQ = 0x13,
|
||||
SSAM_SSH_TC_MCU = 0x14,
|
||||
SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
|
||||
SSAM_SSH_TC_TCH = 0x16,
|
||||
SSAM_SSH_TC_BKL = 0x17,
|
||||
SSAM_SSH_TC_TAM = 0x18,
|
||||
SSAM_SSH_TC_ACC = 0x19,
|
||||
SSAM_SSH_TC_UFI = 0x1a,
|
||||
SSAM_SSH_TC_USC = 0x1b,
|
||||
SSAM_SSH_TC_PEN = 0x1c,
|
||||
SSAM_SSH_TC_VID = 0x1d,
|
||||
SSAM_SSH_TC_AUD = 0x1e,
|
||||
SSAM_SSH_TC_SMC = 0x1f,
|
||||
SSAM_SSH_TC_KPD = 0x20,
|
||||
SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
|
||||
};
|
||||
|
||||
|
||||
/* -- Packet transport layer (ptl). ----------------------------------------- */
|
||||
|
||||
/**
|
||||
* enum ssh_packet_base_priority - Base priorities for &struct ssh_packet.
|
||||
* @SSH_PACKET_PRIORITY_FLUSH: Base priority for flush packets.
|
||||
* @SSH_PACKET_PRIORITY_DATA: Base priority for normal data packets.
|
||||
* @SSH_PACKET_PRIORITY_NAK: Base priority for NAK packets.
|
||||
* @SSH_PACKET_PRIORITY_ACK: Base priority for ACK packets.
|
||||
*/
|
||||
enum ssh_packet_base_priority {
|
||||
SSH_PACKET_PRIORITY_FLUSH = 0, /* same as DATA to sequence flush */
|
||||
SSH_PACKET_PRIORITY_DATA = 0,
|
||||
SSH_PACKET_PRIORITY_NAK = 1,
|
||||
SSH_PACKET_PRIORITY_ACK = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* Same as SSH_PACKET_PRIORITY() below, only with actual values.
|
||||
*/
|
||||
#define __SSH_PACKET_PRIORITY(base, try) \
|
||||
(((base) << 4) | ((try) & 0x0f))
|
||||
|
||||
/**
|
||||
* SSH_PACKET_PRIORITY() - Compute packet priority from base priority and
|
||||
* number of tries.
|
||||
* @base: The base priority as suffix of &enum ssh_packet_base_priority, e.g.
|
||||
* ``FLUSH``, ``DATA``, ``ACK``, or ``NAK``.
|
||||
* @try: The number of tries (must be less than 16).
|
||||
*
|
||||
* Compute the combined packet priority. The combined priority is dominated by
|
||||
* the base priority, whereas the number of (re-)tries decides the precedence
|
||||
* of packets with the same base priority, giving higher priority to packets
|
||||
* that already have more tries.
|
||||
*
|
||||
* Return: Returns the computed priority as value fitting inside a &u8. A
|
||||
* higher number means a higher priority.
|
||||
*/
|
||||
#define SSH_PACKET_PRIORITY(base, try) \
|
||||
__SSH_PACKET_PRIORITY(SSH_PACKET_PRIORITY_##base, (try))
|
||||
|
||||
/**
|
||||
* ssh_packet_priority_get_try() - Get number of tries from packet priority.
|
||||
* @priority: The packet priority.
|
||||
*
|
||||
* Return: Returns the number of tries encoded in the specified packet
|
||||
* priority.
|
||||
*/
|
||||
static inline u8 ssh_packet_priority_get_try(u8 priority)
|
||||
{
|
||||
return priority & 0x0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_packet_priority_get_base - Get base priority from packet priority.
|
||||
* @priority: The packet priority.
|
||||
*
|
||||
* Return: Returns the base priority encoded in the given packet priority.
|
||||
*/
|
||||
static inline u8 ssh_packet_priority_get_base(u8 priority)
|
||||
{
|
||||
return (priority & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
enum ssh_packet_flags {
|
||||
/* state flags */
|
||||
SSH_PACKET_SF_LOCKED_BIT,
|
||||
SSH_PACKET_SF_QUEUED_BIT,
|
||||
SSH_PACKET_SF_PENDING_BIT,
|
||||
SSH_PACKET_SF_TRANSMITTING_BIT,
|
||||
SSH_PACKET_SF_TRANSMITTED_BIT,
|
||||
SSH_PACKET_SF_ACKED_BIT,
|
||||
SSH_PACKET_SF_CANCELED_BIT,
|
||||
SSH_PACKET_SF_COMPLETED_BIT,
|
||||
|
||||
/* type flags */
|
||||
SSH_PACKET_TY_FLUSH_BIT,
|
||||
SSH_PACKET_TY_SEQUENCED_BIT,
|
||||
SSH_PACKET_TY_BLOCKING_BIT,
|
||||
|
||||
/* mask for state flags */
|
||||
SSH_PACKET_FLAGS_SF_MASK =
|
||||
BIT(SSH_PACKET_SF_LOCKED_BIT)
|
||||
| BIT(SSH_PACKET_SF_QUEUED_BIT)
|
||||
| BIT(SSH_PACKET_SF_PENDING_BIT)
|
||||
| BIT(SSH_PACKET_SF_TRANSMITTING_BIT)
|
||||
| BIT(SSH_PACKET_SF_TRANSMITTED_BIT)
|
||||
| BIT(SSH_PACKET_SF_ACKED_BIT)
|
||||
| BIT(SSH_PACKET_SF_CANCELED_BIT)
|
||||
| BIT(SSH_PACKET_SF_COMPLETED_BIT),
|
||||
|
||||
/* mask for type flags */
|
||||
SSH_PACKET_FLAGS_TY_MASK =
|
||||
BIT(SSH_PACKET_TY_FLUSH_BIT)
|
||||
| BIT(SSH_PACKET_TY_SEQUENCED_BIT)
|
||||
| BIT(SSH_PACKET_TY_BLOCKING_BIT),
|
||||
};
|
||||
|
||||
struct ssh_ptl;
|
||||
struct ssh_packet;
|
||||
|
||||
/**
|
||||
* struct ssh_packet_ops - Callback operations for a SSH packet.
|
||||
* @release: Function called when the packet reference count reaches zero.
|
||||
* This callback must be relied upon to ensure that the packet has
|
||||
* left the transport system(s).
|
||||
* @complete: Function called when the packet is completed, either with
|
||||
* success or failure. In case of failure, the reason for the
|
||||
* failure is indicated by the value of the provided status code
|
||||
* argument. This value will be zero in case of success. Note that
|
||||
* a call to this callback does not guarantee that the packet is
|
||||
* not in use by the transport system any more.
|
||||
*/
|
||||
struct ssh_packet_ops {
|
||||
void (*release)(struct ssh_packet *p);
|
||||
void (*complete)(struct ssh_packet *p, int status);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssh_packet - SSH transport packet.
|
||||
* @ptl: Pointer to the packet transport layer. May be %NULL if the packet
|
||||
* (or enclosing request) has not been submitted yet.
|
||||
* @refcnt: Reference count of the packet.
|
||||
* @priority: Priority of the packet. Must be computed via
|
||||
* SSH_PACKET_PRIORITY(). Must only be accessed while holding the
|
||||
* queue lock after first submission.
|
||||
* @data: Raw message data.
|
||||
* @data.len: Length of the raw message data.
|
||||
* @data.ptr: Pointer to the raw message data buffer.
|
||||
* @state: State and type flags describing current packet state (dynamic)
|
||||
* and type (static). See &enum ssh_packet_flags for possible
|
||||
* options.
|
||||
* @timestamp: Timestamp specifying when the latest transmission of a
|
||||
* currently pending packet has been started. May be %KTIME_MAX
|
||||
* before or in-between transmission attempts. Used for the packet
|
||||
* timeout implementation. Must only be accessed while holding the
|
||||
* pending lock after first submission.
|
||||
* @queue_node: The list node for the packet queue.
|
||||
* @pending_node: The list node for the set of pending packets.
|
||||
* @ops: Packet operations.
|
||||
*/
|
||||
struct ssh_packet {
|
||||
struct ssh_ptl *ptl;
|
||||
struct kref refcnt;
|
||||
|
||||
u8 priority;
|
||||
|
||||
struct {
|
||||
size_t len;
|
||||
u8 *ptr;
|
||||
} data;
|
||||
|
||||
unsigned long state;
|
||||
ktime_t timestamp;
|
||||
|
||||
struct list_head queue_node;
|
||||
struct list_head pending_node;
|
||||
|
||||
const struct ssh_packet_ops *ops;
|
||||
};
|
||||
|
||||
struct ssh_packet *ssh_packet_get(struct ssh_packet *p);
|
||||
void ssh_packet_put(struct ssh_packet *p);
|
||||
|
||||
/**
|
||||
* ssh_packet_set_data() - Set raw message data of packet.
|
||||
* @p: The packet for which the message data should be set.
|
||||
* @ptr: Pointer to the memory holding the message data.
|
||||
* @len: Length of the message data.
|
||||
*
|
||||
* Sets the raw message data buffer of the packet to the provided memory. The
|
||||
* memory is not copied. Instead, the caller is responsible for management
|
||||
* (i.e. allocation and deallocation) of the memory. The caller must ensure
|
||||
* that the provided memory is valid and contains a valid SSH message,
|
||||
* starting from the time of submission of the packet until the ``release``
|
||||
* callback has been called. During this time, the memory may not be altered
|
||||
* in any way.
|
||||
*/
|
||||
static inline void ssh_packet_set_data(struct ssh_packet *p, u8 *ptr, size_t len)
|
||||
{
|
||||
p->data.ptr = ptr;
|
||||
p->data.len = len;
|
||||
}
|
||||
|
||||
|
||||
/* -- Request transport layer (rtl). ---------------------------------------- */
|
||||
|
||||
enum ssh_request_flags {
|
||||
/* state flags */
|
||||
SSH_REQUEST_SF_LOCKED_BIT,
|
||||
SSH_REQUEST_SF_QUEUED_BIT,
|
||||
SSH_REQUEST_SF_PENDING_BIT,
|
||||
SSH_REQUEST_SF_TRANSMITTING_BIT,
|
||||
SSH_REQUEST_SF_TRANSMITTED_BIT,
|
||||
SSH_REQUEST_SF_RSPRCVD_BIT,
|
||||
SSH_REQUEST_SF_CANCELED_BIT,
|
||||
SSH_REQUEST_SF_COMPLETED_BIT,
|
||||
|
||||
/* type flags */
|
||||
SSH_REQUEST_TY_FLUSH_BIT,
|
||||
SSH_REQUEST_TY_HAS_RESPONSE_BIT,
|
||||
|
||||
/* mask for state flags */
|
||||
SSH_REQUEST_FLAGS_SF_MASK =
|
||||
BIT(SSH_REQUEST_SF_LOCKED_BIT)
|
||||
| BIT(SSH_REQUEST_SF_QUEUED_BIT)
|
||||
| BIT(SSH_REQUEST_SF_PENDING_BIT)
|
||||
| BIT(SSH_REQUEST_SF_TRANSMITTING_BIT)
|
||||
| BIT(SSH_REQUEST_SF_TRANSMITTED_BIT)
|
||||
| BIT(SSH_REQUEST_SF_RSPRCVD_BIT)
|
||||
| BIT(SSH_REQUEST_SF_CANCELED_BIT)
|
||||
| BIT(SSH_REQUEST_SF_COMPLETED_BIT),
|
||||
|
||||
/* mask for type flags */
|
||||
SSH_REQUEST_FLAGS_TY_MASK =
|
||||
BIT(SSH_REQUEST_TY_FLUSH_BIT)
|
||||
| BIT(SSH_REQUEST_TY_HAS_RESPONSE_BIT),
|
||||
};
|
||||
|
||||
struct ssh_rtl;
|
||||
struct ssh_request;
|
||||
|
||||
/**
|
||||
* struct ssh_request_ops - Callback operations for a SSH request.
|
||||
* @release: Function called when the request's reference count reaches zero.
|
||||
* This callback must be relied upon to ensure that the request has
|
||||
* left the transport systems (both, packet an request systems).
|
||||
* @complete: Function called when the request is completed, either with
|
||||
* success or failure. The command data for the request response
|
||||
* is provided via the &struct ssh_command parameter (``cmd``),
|
||||
* the command payload of the request response via the &struct
|
||||
* ssh_span parameter (``data``).
|
||||
*
|
||||
* If the request does not have any response or has not been
|
||||
* completed with success, both ``cmd`` and ``data`` parameters will
|
||||
* be NULL. If the request response does not have any command
|
||||
* payload, the ``data`` span will be an empty (zero-length) span.
|
||||
*
|
||||
* In case of failure, the reason for the failure is indicated by
|
||||
* the value of the provided status code argument (``status``). This
|
||||
* value will be zero in case of success and a regular errno
|
||||
* otherwise.
|
||||
*
|
||||
* Note that a call to this callback does not guarantee that the
|
||||
* request is not in use by the transport systems any more.
|
||||
*/
|
||||
struct ssh_request_ops {
|
||||
void (*release)(struct ssh_request *rqst);
|
||||
void (*complete)(struct ssh_request *rqst,
|
||||
const struct ssh_command *cmd,
|
||||
const struct ssam_span *data, int status);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ssh_request - SSH transport request.
|
||||
* @packet: The underlying SSH transport packet.
|
||||
* @node: List node for the request queue and pending set.
|
||||
* @state: State and type flags describing current request state (dynamic)
|
||||
* and type (static). See &enum ssh_request_flags for possible
|
||||
* options.
|
||||
* @timestamp: Timestamp specifying when we start waiting on the response of
|
||||
* the request. This is set once the underlying packet has been
|
||||
* completed and may be %KTIME_MAX before that, or when the request
|
||||
* does not expect a response. Used for the request timeout
|
||||
* implementation.
|
||||
* @ops: Request Operations.
|
||||
*/
|
||||
struct ssh_request {
|
||||
struct ssh_packet packet;
|
||||
struct list_head node;
|
||||
|
||||
unsigned long state;
|
||||
ktime_t timestamp;
|
||||
|
||||
const struct ssh_request_ops *ops;
|
||||
};
|
||||
|
||||
/**
|
||||
* to_ssh_request() - Cast a SSH packet to its enclosing SSH request.
|
||||
* @p: The packet to cast.
|
||||
*
|
||||
* Casts the given &struct ssh_packet to its enclosing &struct ssh_request.
|
||||
* The caller is responsible for making sure that the packet is actually
|
||||
* wrapped in a &struct ssh_request.
|
||||
*
|
||||
* Return: Returns the &struct ssh_request wrapping the provided packet.
|
||||
*/
|
||||
static inline struct ssh_request *to_ssh_request(struct ssh_packet *p)
|
||||
{
|
||||
return container_of(p, struct ssh_request, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_request_get() - Increment reference count of request.
|
||||
* @r: The request to increment the reference count of.
|
||||
*
|
||||
* Increments the reference count of the given request by incrementing the
|
||||
* reference count of the underlying &struct ssh_packet, enclosed in it.
|
||||
*
|
||||
* See also ssh_request_put(), ssh_packet_get().
|
||||
*
|
||||
* Return: Returns the request provided as input.
|
||||
*/
|
||||
static inline struct ssh_request *ssh_request_get(struct ssh_request *r)
|
||||
{
|
||||
return r ? to_ssh_request(ssh_packet_get(&r->packet)) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_request_put() - Decrement reference count of request.
|
||||
* @r: The request to decrement the reference count of.
|
||||
*
|
||||
* Decrements the reference count of the given request by decrementing the
|
||||
* reference count of the underlying &struct ssh_packet, enclosed in it. If
|
||||
* the reference count reaches zero, the ``release`` callback specified in the
|
||||
* request's &struct ssh_request_ops, i.e. ``r->ops->release``, will be
|
||||
* called.
|
||||
*
|
||||
* See also ssh_request_get(), ssh_packet_put().
|
||||
*/
|
||||
static inline void ssh_request_put(struct ssh_request *r)
|
||||
{
|
||||
if (r)
|
||||
ssh_packet_put(&r->packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh_request_set_data() - Set raw message data of request.
|
||||
* @r: The request for which the message data should be set.
|
||||
* @ptr: Pointer to the memory holding the message data.
|
||||
* @len: Length of the message data.
|
||||
*
|
||||
* Sets the raw message data buffer of the underlying packet to the specified
|
||||
* buffer. Does not copy the actual message data, just sets the buffer pointer
|
||||
* and length. Refer to ssh_packet_set_data() for more details.
|
||||
*/
|
||||
static inline void ssh_request_set_data(struct ssh_request *r, u8 *ptr, size_t len)
|
||||
{
|
||||
ssh_packet_set_data(&r->packet, ptr, len);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SURFACE_AGGREGATOR_SERIAL_HUB_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue