History

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 ...

Linus Torvalds committed 5 years ago

Commit 983e4ad2 parents 31caf8b a7d53db108 files · +16545 −3452Browse files

Unified · Split

108 files
  1. Documentation/ABI/testing/sysfs-platform-ideapad-laptop +22 −4
  2. Documentation/admin-guide/laptops/thinkpad-acpi.rst +25 −0
  3. Documentation/driver-api/index.rst +1 −0
  4. Documentation/driver-api/surface_aggregator/client-api.rst +38 −0
  5. Documentation/driver-api/surface_aggregator/client.rst +393 −0
  6. Documentation/driver-api/surface_aggregator/clients/cdev.rst +87 −0
  7. Documentation/driver-api/surface_aggregator/clients/index.rst +21 −0
  8. Documentation/driver-api/surface_aggregator/clients/san.rst +44 −0
  9. Documentation/driver-api/surface_aggregator/index.rst +21 −0
  10. Documentation/driver-api/surface_aggregator/internal-api.rst +67 −0
  11. Documentation/driver-api/surface_aggregator/internal.rst +577 −0
  12. Documentation/driver-api/surface_aggregator/overview.rst +77 −0
  13. Documentation/driver-api/surface_aggregator/ssh.rst +344 −0
  14. Documentation/userspace-api/ioctl/ioctl-number.rst +2 −0
  15. MAINTAINERS +31 −14
  16. arch/x86/platform/intel-mid/device_libs/Makefile +0 −1
  17. drivers/gpio/Kconfig +0 −14
  18. drivers/gpio/Makefile +0 −1
  19. drivers/gpio/TODO +1 −1
  20. drivers/gpio/gpio-intel-mid.c +0 −414
  21. drivers/gpio/gpio-msic.c +0 −314
  22. drivers/gpu/drm/gma500/oaktrail_device.c +0 −3
  23. drivers/gpu/drm/gma500/psb_drv.h +3 −0
  24. drivers/platform/olpc/olpc-ec.c +19 −18
  25. drivers/platform/surface/Kconfig +57 −0
  26. drivers/platform/surface/Makefile +4 −0
  27. drivers/platform/surface/aggregator/Kconfig +68 −0
  28. drivers/platform/surface/aggregator/Makefile +17 −0
  29. drivers/platform/surface/aggregator/bus.c +415 −0
  30. drivers/platform/surface/aggregator/bus.h +27 −0
  31. drivers/platform/surface/aggregator/controller.c +2579 −0
  32. drivers/platform/surface/aggregator/controller.h +285 −0
  33. drivers/platform/surface/aggregator/core.c +839 −0
  34. drivers/platform/surface/aggregator/ssh_msgb.h +205 −0
  35. drivers/platform/surface/aggregator/ssh_packet_layer.c +2074 −0
  36. drivers/platform/surface/aggregator/ssh_packet_layer.h +190 −0
  37. drivers/platform/surface/aggregator/ssh_parser.c +228 −0
  38. drivers/platform/surface/aggregator/ssh_parser.h +154 −0
  39. drivers/platform/surface/aggregator/ssh_request_layer.c +1263 −0
  40. drivers/platform/surface/aggregator/ssh_request_layer.h +143 −0
  41. drivers/platform/surface/aggregator/trace.h +632 −0
  42. drivers/platform/surface/surface3-wmi.c +5 −1
  43. drivers/platform/surface/surface_acpi_notify.c +886 −0
  44. drivers/platform/surface/surface_aggregator_cdev.c +322 −0
  45. drivers/platform/surface/surface_hotplug.c +282 −0
  46. drivers/platform/x86/Kconfig +16 −191
  47. drivers/platform/x86/Makefile +2 −17
  48. drivers/platform/x86/acer-wmi.c +2 −2
  49. drivers/platform/x86/amd-pmc.c +11 −3
  50. drivers/platform/x86/dell/Kconfig +207 −0
  51. drivers/platform/x86/dell/Makefile +21 −0
  52. drivers/platform/x86/dell/alienware-wmi.c +0 −0
  53. drivers/platform/x86/dell/dcdbas.c +0 −0
  54. drivers/platform/x86/dell/dcdbas.h +0 −0
  55. drivers/platform/x86/dell/dell-laptop.c +0 −0
  56. drivers/platform/x86/dell/dell-rbtn.c +0 −0
  57. drivers/platform/x86/dell/dell-rbtn.h +0 −0
  58. drivers/platform/x86/dell/dell-smbios-base.c +0 −0
  59. drivers/platform/x86/dell/dell-smbios-smm.c +0 −0
  60. drivers/platform/x86/dell/dell-smbios-wmi.c +0 −0
  61. drivers/platform/x86/dell/dell-smbios.h +0 −0
  62. drivers/platform/x86/dell/dell-smo8800.c +0 −0
  63. drivers/platform/x86/dell/dell-wmi-aio.c +0 −0
  64. drivers/platform/x86/dell/dell-wmi-descriptor.c +0 −0
  65. drivers/platform/x86/dell/dell-wmi-descriptor.h +0 −0
  66. drivers/platform/x86/dell/dell-wmi-led.c +0 −0
  67. drivers/platform/x86/dell/dell-wmi-sysman/Makefile +0 −0
  68. drivers/platform/x86/dell/dell-wmi-sysman/biosattr-interface.c +0 −0
  69. drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h +0 −0
  70. drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c +0 −0
  71. drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.c +0 −0
  72. drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.c +0 −0
  73. drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c +0 −0
  74. drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.c +0 −0
  75. drivers/platform/x86/dell/dell-wmi-sysman/sysman.c +0 −0
  76. drivers/platform/x86/dell/dell-wmi.c +0 −0
  77. drivers/platform/x86/dell/dell_rbu.c +0 −0
  78. drivers/platform/x86/ideapad-laptop.c +1017 −439
  79. drivers/platform/x86/intel-uncore-frequency.c +1 −0
  80. drivers/platform/x86/intel-vbtn.c +81 −57
  81. drivers/platform/x86/intel_mid_powerbtn.c +0 −233
  82. drivers/platform/x86/intel_mid_thermal.c +0 −560
  83. drivers/platform/x86/intel_scu_ipc.c +1 −1
  84. drivers/platform/x86/intel_scu_wdt.c +17 −24
  85. drivers/platform/x86/msi-wmi.c +2 −0
  86. drivers/platform/x86/thinkpad_acpi.c +458 −6
  87. drivers/platform/x86/touchscreen_dmi.c +27 −0
  88. drivers/rtc/Kconfig +0 −12
  89. drivers/rtc/Makefile +0 −1
  90. drivers/rtc/rtc-mrst.c +0 −521
  91. drivers/watchdog/Kconfig +0 −9
  92. drivers/watchdog/Makefile +0 −1
  93. drivers/watchdog/intel-mid_wdt.c +4 −4
  94. drivers/watchdog/intel_scu_watchdog.c +0 −533
  95. drivers/watchdog/intel_scu_watchdog.h +0 −50
  96. include/linux/mod_devicetable.h +18 −0
  97. include/linux/sony-laptop.h +1 −1
  98. include/linux/surface_acpi_notify.h +39 −0
  99. include/linux/surface_aggregator/controller.h +824 −0
  100. include/linux/surface_aggregator/device.h +423 −0
  101. include/linux/surface_aggregator/serial_hub.h +672 −0
  102. include/uapi/linux/surface_aggregator/cdev.h +78 −0
  103. scripts/mod/devicetable-offsets.c +8 −0
  104. scripts/mod/file2alias.c +23 −0
  105. tools/power/x86/intel-speed-select/isst-config.c +113 −2
  106. tools/power/x86/intel-speed-select/isst-core.c +11 −0
  107. tools/power/x86/intel-speed-select/isst-display.c +18 −0
  108. tools/power/x86/intel-speed-select/isst.h +2 −0
Documentation/ABI/testing/sysfs-platform-ideapad-laptop+22−4
@@ -1,11 +1,11 @@
1What: /sys/devices/platform/ideapad/camera_power1What: /sys/bus/platform/devices/VPC2004:*/camera_power
2Date: Dec 20102Date: Dec 2010
3KernelVersion: 2.6.373KernelVersion: 2.6.37
4Contact: "Ike Panhc <ike.pan@canonical.com>"4Contact: "Ike Panhc <ike.pan@canonical.com>"
5Description:5Description:
6 Control the power of camera module. 1 means on, 0 means off.6 Control the power of camera module. 1 means on, 0 means off.
7 7
8What: /sys/devices/platform/ideapad/fan_mode8What: /sys/bus/platform/devices/VPC2004:*/fan_mode
9Date: June 20129Date: June 2012
10KernelVersion: 3.610KernelVersion: 3.6
11Contact: "Maxim Mikityanskiy <maxtram95@gmail.com>"11Contact: "Maxim Mikityanskiy <maxtram95@gmail.com>"
@@ -18,7 +18,7 @@ Description: · 6 unmodified lines
18 * 2 -> Dust Cleaning18 * 2 -> Dust Cleaning
19 * 4 -> Efficient Thermal Dissipation Mode19 * 4 -> Efficient Thermal Dissipation Mode
20 20
21What: /sys/devices/platform/ideapad/touchpad21What: /sys/bus/platform/devices/VPC2004:*/touchpad
22Date: May 201722Date: May 2017
23KernelVersion: 4.1323KernelVersion: 4.13
24Contact: "Ritesh Raj Sarraf <rrs@debian.org>"24Contact: "Ritesh Raj Sarraf <rrs@debian.org>"
@@ -27,7 +27,16 @@ Description: · 2 unmodified lines
27 * 1 -> Switched On27 * 1 -> Switched On
28 * 0 -> Switched Off28 * 0 -> Switched Off
29 29
30What: /sys/bus/pci/devices/<bdf>/<device>/VPC2004:00/fn_lock30What: /sys/bus/platform/devices/VPC2004:*/conservation_mode
31Date: Aug 2017
32KernelVersion: 4.14
33Contact: platform-driver-x86@vger.kernel.org
34Description:
35 Controls whether the conservation mode is enabled or not.
36 This feature limits the maximum battery charge percentage to
37 around 50-60% in order to prolong the lifetime of the battery.
38
39What: /sys/bus/platform/devices/VPC2004:*/fn_lock
31Date: May 201840Date: May 2018
32KernelVersion: 4.1841KernelVersion: 4.18
33Contact: "Oleg Keri <ezhi99@gmail.com>"42Contact: "Oleg Keri <ezhi99@gmail.com>"
@@ -41,3 +50,12 @@ Description: · 7 unmodified lines
41 50
42 # echo "0" > \51 # echo "0" > \
43 /sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock52 /sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock
53
54What: /sys/bus/platform/devices/VPC2004:*/usb_charging
55Date: Feb 2021
56KernelVersion: 5.12
57Contact: platform-driver-x86@vger.kernel.org
58Description:
59 Controls whether the "always on USB charging" feature is
60 enabled or not. This feature enables charging USB devices
61 even if the computer is not turned on.
Documentation/admin-guide/laptops/thinkpad-acpi.rst+25−0
@@ -51,6 +51,7 @@ detailed description): · 50 unmodified lines
51 - UWB enable and disable51 - UWB enable and disable
52 - LCD Shadow (PrivacyGuard) enable and disable52 - LCD Shadow (PrivacyGuard) enable and disable
53 - Lap mode sensor53 - Lap mode sensor
54 - Setting keyboard language
54 55
55A compatibility table by model and feature is maintained on the web56A compatibility table by model and feature is maintained on the web
56site, http://ibm-acpi.sf.net/. I appreciate any success or failure57site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -1466,6 +1467,30 @@ Sysfs notes · 1409 unmodified lines
1466 rfkill controller switch "tpacpi_uwb_sw": refer to1467 rfkill controller switch "tpacpi_uwb_sw": refer to
1467 Documentation/driver-api/rfkill.rst for details.1468 Documentation/driver-api/rfkill.rst for details.
1468 1469
1470
1471Setting keyboard language
1472-------------------------
1473
1474sysfs: keyboard_lang
1475
1476This feature is used to set keyboard language to ECFW using ASL interface.
1477Fewer thinkpads models like T580 , T590 , T15 Gen 1 etc.. has "=", "(',
1478")" numeric keys, which are not displaying correctly, when keyboard language
1479is other than "english". This is because the default keyboard language in ECFW
1480is set as "english". Hence using this sysfs, user can set the correct keyboard
1481language to ECFW and then these key's will work correctly.
1482
1483Example of command to set keyboard language is mentioned below::
1484
1485 echo jp > /sys/devices/platform/thinkpad_acpi/keyboard_lang
1486
1487Text corresponding to keyboard layout to be set in sysfs are: be(Belgian),
1488cz(Czech), da(Danish), de(German), en(English), es(Spain), et(Estonian),
1489fr(French), fr-ch(French(Switzerland)), hu(Hungarian), it(Italy), jp (Japan),
1490nl(Dutch), nn(Norway), pl(Polish), pt(portugese), sl(Slovenian), sv(Sweden),
1491tr(Turkey)
1492
1493
1469Adaptive keyboard1494Adaptive keyboard
1470-----------------1495-----------------
1471 1496
Documentation/driver-api/index.rst+1−0
@@ -99,6 +99,7 @@ available subsections can be seen below. · 98 unmodified lines
99 rfkill99 rfkill
100 serial/index100 serial/index
101 sm501101 sm501
102 surface_aggregator/index
102 switchtec103 switchtec
103 sync_file104 sync_file
104 vfio-mediated-device105 vfio-mediated-device
Documentation/driver-api/surface_aggregator/client-api.rst+38−0
@@ -0,0 +1,38 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3===============================
4Client Driver API Documentation
5===============================
6
7.. contents::
8 :depth: 2
9
10
11Serial Hub Communication
12========================
13
14.. kernel-doc:: include/linux/surface_aggregator/serial_hub.h
15
16.. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.c
17 :export:
18
19
20Controller and Core Interface
21=============================
22
23.. kernel-doc:: include/linux/surface_aggregator/controller.h
24
25.. kernel-doc:: drivers/platform/surface/aggregator/controller.c
26 :export:
27
28.. kernel-doc:: drivers/platform/surface/aggregator/core.c
29 :export:
30
31
32Client Bus and Client Device API
33================================
34
35.. kernel-doc:: include/linux/surface_aggregator/device.h
36
37.. kernel-doc:: drivers/platform/surface/aggregator/bus.c
38 :export:
Documentation/driver-api/surface_aggregator/client.rst+393−0
@@ -0,0 +1,393 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3.. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>`
4.. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>`
5.. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>`
6.. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`
7.. |ssam_client_link| replace:: :c:func:`ssam_client_link`
8.. |ssam_get_controller| replace:: :c:func:`ssam_get_controller`
9.. |ssam_controller_get| replace:: :c:func:`ssam_controller_get`
10.. |ssam_controller_put| replace:: :c:func:`ssam_controller_put`
11.. |ssam_device_alloc| replace:: :c:func:`ssam_device_alloc`
12.. |ssam_device_add| replace:: :c:func:`ssam_device_add`
13.. |ssam_device_remove| replace:: :c:func:`ssam_device_remove`
14.. |ssam_device_driver_register| replace:: :c:func:`ssam_device_driver_register`
15.. |ssam_device_driver_unregister| replace:: :c:func:`ssam_device_driver_unregister`
16.. |module_ssam_device_driver| replace:: :c:func:`module_ssam_device_driver`
17.. |SSAM_DEVICE| replace:: :c:func:`SSAM_DEVICE`
18.. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
19.. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
20.. |ssam_request_sync| replace:: :c:func:`ssam_request_sync`
21.. |ssam_event_mask| replace:: :c:type:`enum ssam_event_mask <ssam_event_mask>`
22
23
24======================
25Writing Client Drivers
26======================
27
28For the API documentation, refer to:
29
30.. toctree::
31 :maxdepth: 2
32
33 client-api
34
35
36Overview
37========
38
39Client drivers can be set up in two main ways, depending on how the
40corresponding device is made available to the system. We specifically
41differentiate between devices that are presented to the system via one of
42the conventional ways, e.g. as platform devices via ACPI, and devices that
43are non-discoverable and instead need to be explicitly provided by some
44other mechanism, as discussed further below.
45
46
47Non-SSAM Client Drivers
48=======================
49
50All communication with the SAM EC is handled via the |ssam_controller|
51representing that EC to the kernel. Drivers targeting a non-SSAM device (and
52thus not being a |ssam_device_driver|) need to explicitly establish a
53connection/relation to that controller. This can be done via the
54|ssam_client_bind| function. Said function returns a reference to the SSAM
55controller, but, more importantly, also establishes a device link between
56client device and controller (this can also be done separate via
57|ssam_client_link|). It is important to do this, as it, first, guarantees
58that the returned controller is valid for use in the client driver for as
59long as this driver is bound to its device, i.e. that the driver gets
60unbound before the controller ever becomes invalid, and, second, as it
61ensures correct suspend/resume ordering. This setup should be done in the
62driver's probe function, and may be used to defer probing in case the SSAM
63subsystem is not ready yet, for example:
64
65.. code-block:: c
66
67 static int client_driver_probe(struct platform_device *pdev)
68 {
69 struct ssam_controller *ctrl;
70
71 ctrl = ssam_client_bind(&pdev->dev);
72 if (IS_ERR(ctrl))
73 return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl);
74
75 // ...
76
77 return 0;
78 }
79
80The controller may be separately obtained via |ssam_get_controller| and its
81lifetime be guaranteed via |ssam_controller_get| and |ssam_controller_put|.
82Note that none of these functions, however, guarantee that the controller
83will not be shut down or suspended. These functions essentially only operate
84on the reference, i.e. only guarantee a bare minimum of accessibility
85without any guarantees at all on practical operability.
86
87
88Adding SSAM Devices
89===================
90
91If a device does not already exist/is not already provided via conventional
92means, it should be provided as |ssam_device| via the SSAM client device
93hub. New devices can be added to this hub by entering their UID into the
94corresponding registry. SSAM devices can also be manually allocated via
95|ssam_device_alloc|, subsequently to which they have to be added via
96|ssam_device_add| and eventually removed via |ssam_device_remove|. By
97default, the parent of the device is set to the controller device provided
98for allocation, however this may be changed before the device is added. Note
99that, when changing the parent device, care must be taken to ensure that the
100controller lifetime and suspend/resume ordering guarantees, in the default
101setup provided through the parent-child relation, are preserved. If
102necessary, by use of |ssam_client_link| as is done for non-SSAM client
103drivers and described in more detail above.
104
105A client device must always be removed by the party which added the
106respective device before the controller shuts down. Such removal can be
107guaranteed by linking the driver providing the SSAM device to the controller
108via |ssam_client_link|, causing it to unbind before the controller driver
109unbinds. Client devices registered with the controller as parent are
110automatically removed when the controller shuts down, but this should not be
111relied upon, especially as this does not extend to client devices with a
112different parent.
113
114
115SSAM Client Drivers
116===================
117
118SSAM client device drivers are, in essence, no different than other device
119driver types. They are represented via |ssam_device_driver| and bind to a
120|ssam_device| via its UID (:c:type:`struct ssam_device.uid <ssam_device>`)
121member and the match table
122(:c:type:`struct ssam_device_driver.match_table <ssam_device_driver>`),
123which should be set when declaring the driver struct instance. Refer to the
124|SSAM_DEVICE| macro documentation for more details on how to define members
125of the driver's match table.
126
127The UID for SSAM client devices consists of a ``domain``, a ``category``,
128a ``target``, an ``instance``, and a ``function``. The ``domain`` is used
129differentiate between physical SAM devices
130(:c:type:`SSAM_DOMAIN_SERIALHUB <ssam_device_domain>`), i.e. devices that can
131be accessed via the Surface Serial Hub, and virtual ones
132(:c:type:`SSAM_DOMAIN_VIRTUAL <ssam_device_domain>`), such as client-device
133hubs, that have no real representation on the SAM EC and are solely used on
134the kernel/driver-side. For physical devices, ``category`` represents the
135target category, ``target`` the target ID, and ``instance`` the instance ID
136used to access the physical SAM device. In addition, ``function`` references
137a specific device functionality, but has no meaning to the SAM EC. The
138(default) name of a client device is generated based on its UID.
139
140A driver instance can be registered via |ssam_device_driver_register| and
141unregistered via |ssam_device_driver_unregister|. For convenience, the
142|module_ssam_device_driver| macro may be used to define module init- and
143exit-functions registering the driver.
144
145The controller associated with a SSAM client device can be found in its
146:c:type:`struct ssam_device.ctrl <ssam_device>` member. This reference is
147guaranteed to be valid for at least as long as the client driver is bound,
148but should also be valid for as long as the client device exists. Note,
149however, that access outside of the bound client driver must ensure that the
150controller device is not suspended while making any requests or
151(un-)registering event notifiers (and thus should generally be avoided). This
152is guaranteed when the controller is accessed from inside the bound client
153driver.
154
155
156Making Synchronous Requests
157===========================
158
159Synchronous requests are (currently) the main form of host-initiated
160communication with the EC. There are a couple of ways to define and execute
161such requests, however, most of them boil down to something similar as shown
162in the example below. This example defines a write-read request, meaning
163that the caller provides an argument to the SAM EC and receives a response.
164The caller needs to know the (maximum) length of the response payload and
165provide a buffer for it.
166
167Care must be taken to ensure that any command payload data passed to the SAM
168EC is provided in little-endian format and, similarly, any response payload
169data received from it is converted from little-endian to host endianness.
170
171.. code-block:: c
172
173 int perform_request(struct ssam_controller *ctrl, u32 arg, u32 *ret)
174 {
175 struct ssam_request rqst;
176 struct ssam_response resp;
177 int status;
178
179 /* Convert request argument to little-endian. */
180 __le32 arg_le = cpu_to_le32(arg);
181 __le32 ret_le = cpu_to_le32(0);
182
183 /*
184 * Initialize request specification. Replace this with your values.
185 * The rqst.payload field may be NULL if rqst.length is zero,
186 * indicating that the request does not have any argument.
187 *
188 * Note: The request parameters used here are not valid, i.e.
189 * they do not correspond to an actual SAM/EC request.
190 */
191 rqst.target_category = SSAM_SSH_TC_SAM;
192 rqst.target_id = 0x01;
193 rqst.command_id = 0x02;
194 rqst.instance_id = 0x03;
195 rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
196 rqst.length = sizeof(arg_le);
197 rqst.payload = (u8 *)&arg_le;
198
199 /* Initialize request response. */
200 resp.capacity = sizeof(ret_le);
201 resp.length = 0;
202 resp.pointer = (u8 *)&ret_le;
203
204 /*
205 * Perform actual request. The response pointer may be null in case
206 * the request does not have any response. This must be consistent
207 * with the SSAM_REQUEST_HAS_RESPONSE flag set in the specification
208 * above.
209 */
210 status = ssam_request_sync(ctrl, &rqst, &resp);
211
212 /*
213 * Alternatively use
214 *
215 * ssam_request_sync_onstack(ctrl, &rqst, &resp, sizeof(arg_le));
216 *
217 * to perform the request, allocating the message buffer directly
218 * on the stack as opposed to allocation via kzalloc().
219 */
220
221 /*
222 * Convert request response back to native format. Note that in the
223 * error case, this value is not touched by the SSAM core, i.e.
224 * 'ret_le' will be zero as specified in its initialization.
225 */
226 *ret = le32_to_cpu(ret_le);
227
228 return status;
229 }
230
231Note that |ssam_request_sync| in its essence is a wrapper over lower-level
232request primitives, which may also be used to perform requests. Refer to its
233implementation and documentation for more details.
234
235An arguably more user-friendly way of defining such functions is by using
236one of the generator macros, for example via:
237
238.. code-block:: c
239
240 SSAM_DEFINE_SYNC_REQUEST_W(__ssam_tmp_perf_mode_set, __le32, {
241 .target_category = SSAM_SSH_TC_TMP,
242 .target_id = 0x01,
243 .command_id = 0x03,
244 .instance_id = 0x00,
245 });
246
247This example defines a function
248
249.. code-block:: c
250
251 int __ssam_tmp_perf_mode_set(struct ssam_controller *ctrl, const __le32 *arg);
252
253executing the specified request, with the controller passed in when calling
254said function. In this example, the argument is provided via the ``arg``
255pointer. Note that the generated function allocates the message buffer on
256the stack. Thus, if the argument provided via the request is large, these
257kinds of macros should be avoided. Also note that, in contrast to the
258previous non-macro example, this function does not do any endianness
259conversion, which has to be handled by the caller. Apart from those
260differences the function generated by the macro is similar to the one
261provided in the non-macro example above.
262
263The full list of such function-generating macros is
264
265- :c:func:`SSAM_DEFINE_SYNC_REQUEST_N` for requests without return value and
266 without argument.
267- :c:func:`SSAM_DEFINE_SYNC_REQUEST_R` for requests with return value but no
268 argument.
269- :c:func:`SSAM_DEFINE_SYNC_REQUEST_W` for requests without return value but
270 with argument.
271
272Refer to their respective documentation for more details. For each one of
273these macros, a special variant is provided, which targets request types
274applicable to multiple instances of the same device type:
275
276- :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_N`
277- :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_R`
278- :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_W`
279
280The difference of those macros to the previously mentioned versions is, that
281the device target and instance IDs are not fixed for the generated function,
282but instead have to be provided by the caller of said function.
283
284Additionally, variants for direct use with client devices, i.e.
285|ssam_device|, are also provided. These can, for example, be used as
286follows:
287
288.. code-block:: c
289
290 SSAM_DEFINE_SYNC_REQUEST_CL_R(ssam_bat_get_sta, __le32, {
291 .target_category = SSAM_SSH_TC_BAT,
292 .command_id = 0x01,
293 });
294
295This invocation of the macro defines a function
296
297.. code-block:: c
298
299 int ssam_bat_get_sta(struct ssam_device *sdev, __le32 *ret);
300
301executing the specified request, using the device IDs and controller given
302in the client device. The full list of such macros for client devices is:
303
304- :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_N`
305- :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_R`
306- :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_W`
307
308
309Handling Events
310===============
311
312To receive events from the SAM EC, an event notifier must be registered for
313the desired event via |ssam_notifier_register|. The notifier must be
314unregistered via |ssam_notifier_unregister| once it is not required any
315more.
316
317Event notifiers are registered by providing (at minimum) a callback to call
318in case an event has been received, the registry specifying how the event
319should be enabled, an event ID specifying for which target category and,
320optionally and depending on the registry used, for which instance ID events
321should be enabled, and finally, flags describing how the EC will send these
322events. If the specific registry does not enable events by instance ID, the
323instance ID must be set to zero. Additionally, a priority for the respective
324notifier may be specified, which determines its order in relation to any
325other notifier registered for the same target category.
326
327By default, event notifiers will receive all events for the specific target
328category, regardless of the instance ID specified when registering the
329notifier. The core may be instructed to only call a notifier if the target
330ID or instance ID (or both) of the event match the ones implied by the
331notifier IDs (in case of target ID, the target ID of the registry), by
332providing an event mask (see |ssam_event_mask|).
333
334In general, the target ID of the registry is also the target ID of the
335enabled event (with the notable exception being keyboard input events on the
336Surface Laptop 1 and 2, which are enabled via a registry with target ID 1,
337but provide events with target ID 2).
338
339A full example for registering an event notifier and handling received
340events is provided below:
341
342.. code-block:: c
343
344 u32 notifier_callback(struct ssam_event_notifier *nf,
345 const struct ssam_event *event)
346 {
347 int status = ...
348
349 /* Handle the event here ... */
350
351 /* Convert return value and indicate that we handled the event. */
352 return ssam_notifier_from_errno(status) | SSAM_NOTIF_HANDLED;
353 }
354
355 int setup_notifier(struct ssam_device *sdev,
356 struct ssam_event_notifier *nf)
357 {
358 /* Set priority wrt. other handlers of same target category. */
359 nf->base.priority = 1;
360
361 /* Set event/notifier callback. */
362 nf->base.fn = notifier_callback;
363
364 /* Specify event registry, i.e. how events get enabled/disabled. */
365 nf->event.reg = SSAM_EVENT_REGISTRY_KIP;
366
367 /* Specify which event to enable/disable */
368 nf->event.id.target_category = sdev->uid.category;
369 nf->event.id.instance = sdev->uid.instance;
370
371 /*
372 * Specify for which events the notifier callback gets executed.
373 * This essentially tells the core if it can skip notifiers that
374 * don't have target or instance IDs matching those of the event.
375 */
376 nf->event.mask = SSAM_EVENT_MASK_STRICT;
377
378 /* Specify event flags. */
379 nf->event.flags = SSAM_EVENT_SEQUENCED;
380
381 return ssam_notifier_register(sdev->ctrl, nf);
382 }
383
384Multiple event notifiers can be registered for the same event. The event
385handler core takes care of enabling and disabling events when notifiers are
386registered and unregistered, by keeping track of how many notifiers for a
387specific event (combination of registry, event target category, and event
388instance ID) are currently registered. This means that a specific event will
389be enabled when the first notifier for it is being registered and disabled
390when the last notifier for it is being unregistered. Note that the event
391flags are therefore only used on the first registered notifier, however, one
392should take care that notifiers for a specific event are always registered
393with the same flag and it is considered a bug to do otherwise.
Documentation/driver-api/surface_aggregator/clients/cdev.rst+87−0
@@ -0,0 +1,87 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3.. |u8| replace:: :c:type:`u8 <u8>`
4.. |u16| replace:: :c:type:`u16 <u16>`
5.. |ssam_cdev_request| replace:: :c:type:`struct ssam_cdev_request <ssam_cdev_request>`
6.. |ssam_cdev_request_flags| replace:: :c:type:`enum ssam_cdev_request_flags <ssam_cdev_request_flags>`
7
8==============================
9User-Space EC Interface (cdev)
10==============================
11
12The ``surface_aggregator_cdev`` module provides a misc-device for the SSAM
13controller to allow for a (more or less) direct connection from user-space to
14the SAM EC. It is intended to be used for development and debugging, and
15therefore should not be used or relied upon in any other way. Note that this
16module is not loaded automatically, but instead must be loaded manually.
17
18The provided interface is accessible through the ``/dev/surface/aggregator``
19device-file. All functionality of this interface is provided via IOCTLs.
20These IOCTLs and their respective input/output parameter structs are defined in
21``include/uapi/linux/surface_aggregator/cdev.h``.
22
23A small python library and scripts for accessing this interface can be found
24at https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam.
25
26
27Controller IOCTLs
28=================
29
30The following IOCTLs are provided:
31
32.. flat-table:: Controller IOCTLs
33 :widths: 1 1 1 1 4
34 :header-rows: 1
35
36 * - Type
37 - Number
38 - Direction
39 - Name
40 - Description
41
42 * - ``0xA5``
43 - ``1``
44 - ``WR``
45 - ``REQUEST``
46 - Perform synchronous SAM request.
47
48
49``REQUEST``
50-----------
51
52Defined as ``_IOWR(0xA5, 1, struct ssam_cdev_request)``.
53
54Executes a synchronous SAM request. The request specification is passed in
55as argument of type |ssam_cdev_request|, which is then written to/modified
56by the IOCTL to return status and result of the request.
57
58Request payload data must be allocated separately and is passed in via the
59``payload.data`` and ``payload.length`` members. If a response is required,
60the response buffer must be allocated by the caller and passed in via the
61``response.data`` member. The ``response.length`` member must be set to the
62capacity of this buffer, or if no response is required, zero. Upon
63completion of the request, the call will write the response to the response
64buffer (if its capacity allows it) and overwrite the length field with the
65actual size of the response, in bytes.
66
67Additionally, if the request has a response, this must be indicated via the
68request flags, as is done with in-kernel requests. Request flags can be set
69via the ``flags`` member and the values correspond to the values found in
70|ssam_cdev_request_flags|.
71
72Finally, the status of the request itself is returned in the ``status``
73member (a negative errno value indicating failure). Note that failure
74indication of the IOCTL is separated from failure indication of the request:
75The IOCTL returns a negative status code if anything failed during setup of
76the request (``-EFAULT``) or if the provided argument or any of its fields
77are invalid (``-EINVAL``). In this case, the status value of the request
78argument may be set, providing more detail on what went wrong (e.g.
79``-ENOMEM`` for out-of-memory), but this value may also be zero. The IOCTL
80will return with a zero status code in case the request has been set up,
81submitted, and completed (i.e. handed back to user-space) successfully from
82inside the IOCTL, but the request ``status`` member may still be negative in
83case the actual execution of the request failed after it has been submitted.
84
85A full definition of the argument struct is provided below:
86
87.. kernel-doc:: include/uapi/linux/surface_aggregator/cdev.h
Documentation/driver-api/surface_aggregator/clients/index.rst+21−0
@@ -0,0 +1,21 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3===========================
4Client Driver Documentation
5===========================
6
7This is the documentation for client drivers themselves. Refer to
8:doc:`../client` for documentation on how to write client drivers.
9
10.. toctree::
11 :maxdepth: 1
12
13 cdev
14 san
15
16.. only:: subproject and html
17
18 Indices
19 =======
20
21 * :ref:`genindex`
Documentation/driver-api/surface_aggregator/clients/san.rst+44−0
@@ -0,0 +1,44 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3.. |san_client_link| replace:: :c:func:`san_client_link`
4.. |san_dgpu_notifier_register| replace:: :c:func:`san_dgpu_notifier_register`
5.. |san_dgpu_notifier_unregister| replace:: :c:func:`san_dgpu_notifier_unregister`
6
7===================
8Surface ACPI Notify
9===================
10
11The Surface ACPI Notify (SAN) device provides the bridge between ACPI and
12SAM controller. Specifically, ACPI code can execute requests and handle
13battery and thermal events via this interface. In addition to this, events
14relating to the discrete GPU (dGPU) of the Surface Book 2 can be sent from
15ACPI code (note: the Surface Book 3 uses a different method for this). The
16only currently known event sent via this interface is a dGPU power-on
17notification. While this driver handles the former part internally, it only
18relays the dGPU events to any other driver interested via its public API and
19does not handle them.
20
21The public interface of this driver is split into two parts: Client
22registration and notifier-block registration.
23
24A client to the SAN interface can be linked as consumer to the SAN device
25via |san_client_link|. This can be used to ensure that the a client
26receiving dGPU events does not miss any events due to the SAN interface not
27being set up as this forces the client driver to unbind once the SAN driver
28is unbound.
29
30Notifier-blocks can be registered by any device for as long as the module is
31loaded, regardless of being linked as client or not. Registration is done
32with |san_dgpu_notifier_register|. If the notifier is not needed any more, it
33should be unregistered via |san_dgpu_notifier_unregister|.
34
35Consult the API documentation below for more details.
36
37
38API Documentation
39=================
40
41.. kernel-doc:: include/linux/surface_acpi_notify.h
42
43.. kernel-doc:: drivers/platform/surface/surface_acpi_notify.c
44 :export:
Documentation/driver-api/surface_aggregator/index.rst+21−0
@@ -0,0 +1,21 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3=======================================
4Surface System Aggregator Module (SSAM)
5=======================================
6
7.. toctree::
8 :maxdepth: 2
9
10 overview
11 client
12 clients/index
13 ssh
14 internal
15
16.. only:: subproject and html
17
18 Indices
19 =======
20
21 * :ref:`genindex`
Documentation/driver-api/surface_aggregator/internal-api.rst+67−0
@@ -0,0 +1,67 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3==========================
4Internal API Documentation
5==========================
6
7.. contents::
8 :depth: 2
9
10
11Packet Transport Layer
12======================
13
14.. kernel-doc:: drivers/platform/surface/aggregator/ssh_parser.h
15 :internal:
16
17.. kernel-doc:: drivers/platform/surface/aggregator/ssh_parser.c
18 :internal:
19
20.. kernel-doc:: drivers/platform/surface/aggregator/ssh_msgb.h
21 :internal:
22
23.. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.h
24 :internal:
25
26.. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.c
27 :internal:
28
29
30Request Transport Layer
31=======================
32
33.. kernel-doc:: drivers/platform/surface/aggregator/ssh_request_layer.h
34 :internal:
35
36.. kernel-doc:: drivers/platform/surface/aggregator/ssh_request_layer.c
37 :internal:
38
39
40Controller
41==========
42
43.. kernel-doc:: drivers/platform/surface/aggregator/controller.h
44 :internal:
45
46.. kernel-doc:: drivers/platform/surface/aggregator/controller.c
47 :internal:
48
49
50Client Device Bus
51=================
52
53.. kernel-doc:: drivers/platform/surface/aggregator/bus.c
54 :internal:
55
56
57Core
58====
59
60.. kernel-doc:: drivers/platform/surface/aggregator/core.c
61 :internal:
62
63
64Trace Helpers
65=============
66
67.. kernel-doc:: drivers/platform/surface/aggregator/trace.h
Documentation/driver-api/surface_aggregator/internal.rst+577−0
@@ -0,0 +1,577 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3.. |ssh_ptl| replace:: :c:type:`struct ssh_ptl <ssh_ptl>`
4.. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit`
5.. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel`
6.. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown`
7.. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf`
8.. |ssh_rtl| replace:: :c:type:`struct ssh_rtl <ssh_rtl>`
9.. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit`
10.. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel`
11.. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown`
12.. |ssh_packet| replace:: :c:type:`struct ssh_packet <ssh_packet>`
13.. |ssh_packet_get| replace:: :c:func:`ssh_packet_get`
14.. |ssh_packet_put| replace:: :c:func:`ssh_packet_put`
15.. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops <ssh_packet_ops>`
16.. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority <ssh_packet_base_priority>`
17.. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags <ssh_packet_flags>`
18.. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY`
19.. |ssh_frame| replace:: :c:type:`struct ssh_frame <ssh_frame>`
20.. |ssh_command| replace:: :c:type:`struct ssh_command <ssh_command>`
21.. |ssh_request| replace:: :c:type:`struct ssh_request <ssh_request>`
22.. |ssh_request_get| replace:: :c:func:`ssh_request_get`
23.. |ssh_request_put| replace:: :c:func:`ssh_request_put`
24.. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops <ssh_request_ops>`
25.. |ssh_request_init| replace:: :c:func:`ssh_request_init`
26.. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags <ssh_request_flags>`
27.. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>`
28.. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>`
29.. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>`
30.. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`
31.. |ssam_client_link| replace:: :c:func:`ssam_client_link`
32.. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync <ssam_request_sync>`
33.. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry <ssam_event_registry>`
34.. |ssam_event_id| replace:: :c:type:`struct ssam_event_id <ssam_event_id>`
35.. |ssam_nf| replace:: :c:type:`struct ssam_nf <ssam_nf>`
36.. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc`
37.. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec`
38.. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
39.. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
40.. |ssam_cplt| replace:: :c:type:`struct ssam_cplt <ssam_cplt>`
41.. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue <ssam_event_queue>`
42.. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit`
43
44=====================
45Core Driver Internals
46=====================
47
48Architectural overview of the Surface System Aggregator Module (SSAM) core
49and Surface Serial Hub (SSH) driver. For the API documentation, refer to:
50
51.. toctree::
52 :maxdepth: 2
53
54 internal-api
55
56
57Overview
58========
59
60The SSAM core implementation is structured in layers, somewhat following the
61SSH protocol structure:
62
63Lower-level packet transport is implemented in the *packet transport layer
64(PTL)*, directly building on top of the serial device (serdev)
65infrastructure of the kernel. As the name indicates, this layer deals with
66the packet transport logic and handles things like packet validation, packet
67acknowledgment (ACKing), packet (retransmission) timeouts, and relaying
68packet payloads to higher-level layers.
69
70Above this sits the *request transport layer (RTL)*. This layer is centered
71around command-type packet payloads, i.e. requests (sent from host to EC),
72responses of the EC to those requests, and events (sent from EC to host).
73It, specifically, distinguishes events from request responses, matches
74responses to their corresponding requests, and implements request timeouts.
75
76The *controller* layer is building on top of this and essentially decides
77how request responses and, especially, events are dealt with. It provides an
78event notifier system, handles event activation/deactivation, provides a
79workqueue for event and asynchronous request completion, and also manages
80the message counters required for building command messages (``SEQ``,
81``RQID``). This layer basically provides a fundamental interface to the SAM
82EC for use in other kernel drivers.
83
84While the controller layer already provides an interface for other kernel
85drivers, the client *bus* extends this interface to provide support for
86native SSAM devices, i.e. devices that are not defined in ACPI and not
87implemented as platform devices, via |ssam_device| and |ssam_device_driver|
88simplify management of client devices and client drivers.
89
90Refer to :doc:`client` for documentation regarding the client device/driver
91API and interface options for other kernel drivers. It is recommended to
92familiarize oneself with that chapter and the :doc:`ssh` before continuing
93with the architectural overview below.
94
95
96Packet Transport Layer
97======================
98
99The packet transport layer is represented via |ssh_ptl| and is structured
100around the following key concepts:
101
102Packets
103-------
104
105Packets are the fundamental transmission unit of the SSH protocol. They are
106managed by the packet transport layer, which is essentially the lowest layer
107of the driver and is built upon by other components of the SSAM core.
108Packets to be transmitted by the SSAM core are represented via |ssh_packet|
109(in contrast, packets received by the core do not have any specific
110structure and are managed entirely via the raw |ssh_frame|).
111
112This structure contains the required fields to manage the packet inside the
113transport layer, as well as a reference to the buffer containing the data to
114be transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it
115contains an internal reference count, which is used for managing its
116lifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this
117counter reaches zero, the ``release()`` callback provided to the packet via
118its |ssh_packet_ops| reference is executed, which may then deallocate the
119packet or its enclosing structure (e.g. |ssh_request|).
120
121In addition to the ``release`` callback, the |ssh_packet_ops| reference also
122provides a ``complete()`` callback, which is run once the packet has been
123completed and provides the status of this completion, i.e. zero on success
124or a negative errno value in case of an error. Once the packet has been
125submitted to the packet transport layer, the ``complete()`` callback is
126always guaranteed to be executed before the ``release()`` callback, i.e. the
127packet will always be completed, either successfully, with an error, or due
128to cancellation, before it will be released.
129
130The state of a packet is managed via its ``state`` flags
131(|ssh_packet_flags|), which also contains the packet type. In particular,
132the following bits are noteworthy:
133
134* ``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either
135 through error or success, is imminent. It indicates that no further
136 references of the packet should be taken and any existing references
137 should be dropped as soon as possible. The process setting this bit is
138 responsible for removing any references to this packet from the packet
139 queue and pending set.
140
141* ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the
142 ``complete()`` callback and is used to ensure that this callback only runs
143 once.
144
145* ``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on
146 the packet queue and cleared when it is dequeued.
147
148* ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to
149 the pending set and cleared when it is removed from it.
150
151Packet Queue
152------------
153
154The packet queue is the first of the two fundamental collections in the
155packet transport layer. It is a priority queue, with priority of the
156respective packets based on the packet type (major) and number of tries
157(minor). See |SSH_PACKET_PRIORITY| for more details on the priority value.
158
159All packets to be transmitted by the transport layer must be submitted to
160this queue via |ssh_ptl_submit|. Note that this includes control packets
161sent by the transport layer itself. Internally, data packets can be
162re-submitted to this queue due to timeouts or NAK packets sent by the EC.
163
164Pending Set
165-----------
166
167The pending set is the second of the two fundamental collections in the
168packet transport layer. It stores references to packets that have already
169been transmitted, but wait for acknowledgment (e.g. the corresponding ACK
170packet) by the EC.
171
172Note that a packet may both be pending and queued if it has been
173re-submitted due to a packet acknowledgment timeout or NAK. On such a
174re-submission, packets are not removed from the pending set.
175
176Transmitter Thread
177------------------
178
179The transmitter thread is responsible for most of the actual work regarding
180packet transmission. In each iteration, it (waits for and) checks if the
181next packet on the queue (if any) can be transmitted and, if so, removes it
182from the queue and increments its counter for the number of transmission
183attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by
184the EC, the packet is added to the pending set. Next, the packet's data is
185submitted to the serdev subsystem. In case of an error or timeout during
186this submission, the packet is completed by the transmitter thread with the
187status value of the callback set accordingly. In case the packet is
188unsequenced, i.e. does not require an ACK by the EC, the packet is completed
189with success on the transmitter thread.
190
191Transmission of sequenced packets is limited by the number of concurrently
192pending packets, i.e. a limit on how many packets may be waiting for an ACK
193from the EC in parallel. This limit is currently set to one (see :doc:`ssh`
194for the reasoning behind this). Control packets (i.e. ACK and NAK) can
195always be transmitted.
196
197Receiver Thread
198---------------
199
200Any data received from the EC is put into a FIFO buffer for further
201processing. This processing happens on the receiver thread. The receiver
202thread parses and validates the received message into its |ssh_frame| and
203corresponding payload. It prepares and submits the necessary ACK (and on
204validation error or invalid data NAK) packets for the received messages.
205
206This thread also handles further processing, such as matching ACK messages
207to the corresponding pending packet (via sequence ID) and completing it, as
208well as initiating re-submission of all currently pending packets on
209receival of a NAK message (re-submission in case of a NAK is similar to
210re-submission due to timeout, see below for more details on that). Note that
211the successful completion of a sequenced packet will always run on the
212receiver thread (whereas any failure-indicating completion will run on the
213process where the failure occurred).
214
215Any payload data is forwarded via a callback to the next upper layer, i.e.
216the request transport layer.
217
218Timeout Reaper
219--------------
220
221The packet acknowledgment timeout is a per-packet timeout for sequenced
222packets, started when the respective packet begins (re-)transmission (i.e.
223this timeout is armed once per transmission attempt on the transmitter
224thread). It is used to trigger re-submission or, when the number of tries
225has been exceeded, cancellation of the packet in question.
226
227This timeout is handled via a dedicated reaper task, which is essentially a
228work item (re-)scheduled to run when the next packet is set to time out. The
229work item then checks the set of pending packets for any packets that have
230exceeded the timeout and, if there are any remaining packets, re-schedules
231itself to the next appropriate point in time.
232
233If a timeout has been detected by the reaper, the packet will either be
234re-submitted if it still has some remaining tries left, or completed with
235``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and
236triggered by receival of a NAK, means that the packet is added to the queue
237with a now incremented number of tries, yielding a higher priority. The
238timeout for the packet will be disabled until the next transmission attempt
239and the packet remains on the pending set.
240
241Note that due to transmission and packet acknowledgment timeouts, the packet
242transport layer is always guaranteed to make progress, if only through
243timing out packets, and will never fully block.
244
245Concurrency and Locking
246-----------------------
247
248There are two main locks in the packet transport layer: One guarding access
249to the packet queue and one guarding access to the pending set. These
250collections may only be accessed and modified under the respective lock. If
251access to both collections is needed, the pending lock must be acquired
252before the queue lock to avoid deadlocks.
253
254In addition to guarding the collections, after initial packet submission
255certain packet fields may only be accessed under one of the locks.
256Specifically, the packet priority must only be accessed while holding the
257queue lock and the packet timestamp must only be accessed while holding the
258pending lock.
259
260Other parts of the packet transport layer are guarded independently. State
261flags are managed by atomic bit operations and, if necessary, memory
262barriers. Modifications to the timeout reaper work item and expiration date
263are guarded by their own lock.
264
265The reference of the packet to the packet transport layer (``ptl``) is
266somewhat special. It is either set when the upper layer request is submitted
267or, if there is none, when the packet is first submitted. After it is set,
268it will not change its value. Functions that may run concurrently with
269submission, i.e. cancellation, can not rely on the ``ptl`` reference to be
270set. Access to it in these functions is guarded by ``READ_ONCE()``, whereas
271setting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry.
272
273Some packet fields may be read outside of the respective locks guarding
274them, specifically priority and state for tracing. In those cases, proper
275access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such
276read-only access is only allowed when stale values are not critical.
277
278With respect to the interface for higher layers, packet submission
279(|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival
280(|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be
281executed concurrently with respect to each other. Note that packet
282submission may not run concurrently with itself for the same packet.
283Equally, shutdown and data receival may also not run concurrently with
284themselves (but may run concurrently with each other).
285
286
287Request Transport Layer
288=======================
289
290The request transport layer is represented via |ssh_rtl| and builds on top
291of the packet transport layer. It deals with requests, i.e. SSH packets sent
292by the host containing a |ssh_command| as frame payload. This layer
293separates responses to requests from events, which are also sent by the EC
294via a |ssh_command| payload. While responses are handled in this layer,
295events are relayed to the next upper layer, i.e. the controller layer, via
296the corresponding callback. The request transport layer is structured around
297the following key concepts:
298
299Request
300-------
301
302Requests are packets with a command-type payload, sent from host to EC to
303query data from or trigger an action on it (or both simultaneously). They
304are represented by |ssh_request|, wrapping the underlying |ssh_packet|
305storing its message data (i.e. SSH frame with command payload). Note that
306all top-level representations, e.g. |ssam_request_sync| are built upon this
307struct.
308
309As |ssh_request| extends |ssh_packet|, its lifetime is also managed by the
310reference counter inside the packet struct (which can be accessed via
311|ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the
312``release()`` callback of the |ssh_request_ops| reference of the request is
313called.
314
315Requests can have an optional response that is equally sent via a SSH
316message with command-type payload (from EC to host). The party constructing
317the request must know if a response is expected and mark this in the request
318flags provided to |ssh_request_init|, so that the request transport layer
319can wait for this response.
320
321Similar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback
322provided via its request ops reference and is guaranteed to be completed
323before it is released once it has been submitted to the request transport
324layer via |ssh_rtl_submit|. For a request without a response, successful
325completion will occur once the underlying packet has been successfully
326transmitted by the packet transport layer (i.e. from within the packet
327completion callback). For a request with response, successful completion
328will occur once the response has been received and matched to the request
329via its request ID (which happens on the packet layer's data-received
330callback running on the receiver thread). If the request is completed with
331an error, the status value will be set to the corresponding (negative) errno
332value.
333
334The state of a request is again managed via its ``state`` flags
335(|ssh_request_flags|), which also encode the request type. In particular,
336the following bits are noteworthy:
337
338* ``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either
339 through error or success, is imminent. It indicates that no further
340 references of the request should be taken and any existing references
341 should be dropped as soon as possible. The process setting this bit is
342 responsible for removing any references to this request from the request
343 queue and pending set.
344
345* ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the
346 ``complete()`` callback and is used to ensure that this callback only runs
347 once.
348
349* ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on
350 the request queue and cleared when it is dequeued.
351
352* ``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to
353 the pending set and cleared when it is removed from it.
354
355Request Queue
356-------------
357
358The request queue is the first of the two fundamental collections in the
359request transport layer. In contrast to the packet queue of the packet
360transport layer, it is not a priority queue and the simple first come first
361serve principle applies.
362
363All requests to be transmitted by the request transport layer must be
364submitted to this queue via |ssh_rtl_submit|. Once submitted, requests may
365not be re-submitted, and will not be re-submitted automatically on timeout.
366Instead, the request is completed with a timeout error. If desired, the
367caller can create and submit a new request for another try, but it must not
368submit the same request again.
369
370Pending Set
371-----------
372
373The pending set is the second of the two fundamental collections in the
374request transport layer. This collection stores references to all pending
375requests, i.e. requests awaiting a response from the EC (similar to what the
376pending set of the packet transport layer does for packets).
377
378Transmitter Task
379----------------
380
381The transmitter task is scheduled when a new request is available for
382transmission. It checks if the next request on the request queue can be
383transmitted and, if so, submits its underlying packet to the packet
384transport layer. This check ensures that only a limited number of
385requests can be pending, i.e. waiting for a response, at the same time. If
386the request requires a response, the request is added to the pending set
387before its packet is submitted.
388
389Packet Completion Callback
390--------------------------
391
392The packet completion callback is executed once the underlying packet of a
393request has been completed. In case of an error completion, the
394corresponding request is completed with the error value provided in this
395callback.
396
397On successful packet completion, further processing depends on the request.
398If the request expects a response, it is marked as transmitted and the
399request timeout is started. If the request does not expect a response, it is
400completed with success.
401
402Data-Received Callback
403----------------------
404
405The data received callback notifies the request transport layer of data
406being received by the underlying packet transport layer via a data-type
407frame. In general, this is expected to be a command-type payload.
408
409If the request ID of the command is one of the request IDs reserved for
410events (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the
411event callback registered in the request transport layer. If the request ID
412indicates a response to a request, the respective request is looked up in
413the pending set and, if found and marked as transmitted, completed with
414success.
415
416Timeout Reaper
417--------------
418
419The request-response-timeout is a per-request timeout for requests expecting
420a response. It is used to ensure that a request does not wait indefinitely
421on a response from the EC and is started after the underlying packet has
422been successfully completed.
423
424This timeout is, similar to the packet acknowledgment timeout on the packet
425transport layer, handled via a dedicated reaper task. This task is
426essentially a work-item (re-)scheduled to run when the next request is set
427to time out. The work item then scans the set of pending requests for any
428requests that have timed out and completes them with ``-ETIMEDOUT`` as
429status. Requests will not be re-submitted automatically. Instead, the issuer
430of the request must construct and submit a new request, if so desired.
431
432Note that this timeout, in combination with packet transmission and
433acknowledgment timeouts, guarantees that the request layer will always make
434progress, even if only through timing out packets, and never fully block.
435
436Concurrency and Locking
437-----------------------
438
439Similar to the packet transport layer, there are two main locks in the
440request transport layer: One guarding access to the request queue and one
441guarding access to the pending set. These collections may only be accessed
442and modified under the respective lock.
443
444Other parts of the request transport layer are guarded independently. State
445flags are (again) managed by atomic bit operations and, if necessary, memory
446barriers. Modifications to the timeout reaper work item and expiration date
447are guarded by their own lock.
448
449Some request fields may be read outside of the respective locks guarding
450them, specifically the state for tracing. In those cases, proper access is
451ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only
452access is only allowed when stale values are not critical.
453
454With respect to the interface for higher layers, request submission
455(|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer
456shutdown (|ssh_rtl_shutdown|) may always be executed concurrently with
457respect to each other. Note that request submission may not run concurrently
458with itself for the same request (and also may only be called once per
459request). Equally, shutdown may also not run concurrently with itself.
460
461
462Controller Layer
463================
464
465The controller layer extends on the request transport layer to provide an
466easy-to-use interface for client drivers. It is represented by
467|ssam_controller| and the SSH driver. While the lower level transport layers
468take care of transmitting and handling packets and requests, the controller
469layer takes on more of a management role. Specifically, it handles device
470initialization, power management, and event handling, including event
471delivery and registration via the (event) completion system (|ssam_cplt|).
472
473Event Registration
474------------------
475
476In general, an event (or rather a class of events) has to be explicitly
477requested by the host before the EC will send it (HID input events seem to
478be the exception). This is done via an event-enable request (similarly,
479events should be disabled via an event-disable request once no longer
480desired).
481
482The specific request used to enable (or disable) an event is given via an
483event registry, i.e. the governing authority of this event (so to speak),
484represented by |ssam_event_registry|. As parameters to this request, the
485target category and, depending on the event registry, instance ID of the
486event to be enabled must be provided. This (optional) instance ID must be
487zero if the registry does not use it. Together, target category and instance
488ID form the event ID, represented by |ssam_event_id|. In short, both, event
489registry and event ID, are required to uniquely identify a respective class
490of events.
491
492Note that a further *request ID* parameter must be provided for the
493enable-event request. This parameter does not influence the class of events
494being enabled, but instead is set as the request ID (RQID) on each event of
495this class sent by the EC. It is used to identify events (as a limited
496number of request IDs is reserved for use in events only, specifically one
497to ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific
498class. Currently, the controller always sets this parameter to the target
499category specified in |ssam_event_id|.
500
501As multiple client drivers may rely on the same (or overlapping) classes of
502events and enable/disable calls are strictly binary (i.e. on/off), the
503controller has to manage access to these events. It does so via reference
504counting, storing the counter inside an RB-tree based mapping with event
505registry and ID as key (there is no known list of valid event registry and
506event ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and
507|ssam_nf_refcount_dec| for details.
508
509This management is done together with notifier registration (described in
510the next section) via the top-level |ssam_notifier_register| and
511|ssam_notifier_unregister| functions.
512
513Event Delivery
514--------------
515
516To receive events, a client driver has to register an event notifier via
517|ssam_notifier_register|. This increments the reference counter for that
518specific class of events (as detailed in the previous section), enables the
519class on the EC (if it has not been enabled already), and installs the
520provided notifier callback.
521
522Notifier callbacks are stored in lists, with one (RCU) list per target
523category (provided via the event ID; NB: there is a fixed known number of
524target categories). There is no known association from the combination of
525event registry and event ID to the command data (target ID, target category,
526command ID, and instance ID) that can be provided by an event class, apart
527from target category and instance ID given via the event ID.
528
529Note that due to the way notifiers are (or rather have to be) stored, client
530drivers may receive events that they have not requested and need to account
531for them. Specifically, they will, by default, receive all events from the
532same target category. To simplify dealing with this, filtering of events by
533target ID (provided via the event registry) and instance ID (provided via
534the event ID) can be requested when registering a notifier. This filtering
535is applied when iterating over the notifiers at the time they are executed.
536
537All notifier callbacks are executed on a dedicated workqueue, the so-called
538completion workqueue. After an event has been received via the callback
539installed in the request layer (running on the receiver thread of the packet
540transport layer), it will be put on its respective event queue
541(|ssam_event_queue|). From this event queue the completion work item of that
542queue (running on the completion workqueue) will pick up the event and
543execute the notifier callback. This is done to avoid blocking on the
544receiver thread.
545
546There is one event queue per combination of target ID and target category.
547This is done to ensure that notifier callbacks are executed in sequence for
548events of the same target ID and target category. Callbacks can be executed
549in parallel for events with a different combination of target ID and target
550category.
551
552Concurrency and Locking
553-----------------------
554
555Most of the concurrency related safety guarantees of the controller are
556provided by the lower-level request transport layer. In addition to this,
557event (un-)registration is guarded by its own lock.
558
559Access to the controller state is guarded by the state lock. This lock is a
560read/write semaphore. The reader part can be used to ensure that the state
561does not change while functions depending on the state to stay the same
562(e.g. |ssam_notifier_register|, |ssam_notifier_unregister|,
563|ssam_request_sync_submit|, and derivatives) are executed and this guarantee
564is not already provided otherwise (e.g. through |ssam_client_bind| or
565|ssam_client_link|). The writer part guards any transitions that will change
566the state, i.e. initialization, destruction, suspension, and resumption.
567
568The controller state may be accessed (read-only) outside the state lock for
569smoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|).
570Note that such checks are not supposed to (and will not) protect against all
571invalid usages, but rather aim to help catch them. In those cases, proper
572variable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``.
573
574Assuming any preconditions on the state not changing have been satisfied,
575all non-initialization and non-shutdown functions may run concurrently with
576each other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|,
577|ssam_request_sync_submit|, as well as all functions building on top of those.
Documentation/driver-api/surface_aggregator/overview.rst+77−0
@@ -0,0 +1,77 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3========
4Overview
5========
6
7The Surface/System Aggregator Module (SAM, SSAM) is an (arguably *the*)
8embedded controller (EC) on Microsoft Surface devices. It has been originally
9introduced on 4th generation devices (Surface Pro 4, Surface Book 1), but
10its responsibilities and feature-set have since been expanded significantly
11with the following generations.
12
13
14Features and Integration
15========================
16
17Not much is currently known about SAM on 4th generation devices (Surface Pro
184, Surface Book 1), due to the use of a different communication interface
19between host and EC (as detailed below). On 5th (Surface Pro 2017, Surface
20Book 2, Surface Laptop 1) and later generation devices, SAM is responsible
21for providing battery information (both current status and static values,
22such as maximum capacity etc.), as well as an assortment of temperature
23sensors (e.g. skin temperature) and cooling/performance-mode setting to the
24host. On the Surface Book 2, specifically, it additionally provides an
25interface for properly handling clipboard detachment (i.e. separating the
26display part from the keyboard part of the device), on the Surface Laptop 1
27and 2 it is required for keyboard HID input. This HID subsystem has been
28restructured for 7th generation devices and on those, specifically Surface
29Laptop 3 and Surface Book 3, is responsible for all major HID input (i.e.
30keyboard and touchpad).
31
32While features have not changed much on a coarse level since the 5th
33generation, internal interfaces have undergone some rather large changes. On
345th and 6th generation devices, both battery and temperature information is
35exposed to ACPI via a shim driver (referred to as Surface ACPI Notify, or
36SAN), translating ACPI generic serial bus write-/read-accesses to SAM
37requests. On 7th generation devices, this additional layer is gone and these
38devices require a driver hooking directly into the SAM interface. Equally,
39on newer generations, less devices are declared in ACPI, making them a bit
40harder to discover and requiring us to hard-code a sort of device registry.
41Due to this, a SSAM bus and subsystem with client devices
42(:c:type:`struct ssam_device <ssam_device>`) has been implemented.
43
44
45Communication
46=============
47
48The type of communication interface between host and EC depends on the
49generation of the Surface device. On 4th generation devices, host and EC
50communicate via HID, specifically using a HID-over-I2C device, whereas on
515th and later generations, communication takes place via a USART serial
52device. In accordance to the drivers found on other operating systems, we
53refer to the serial device and its driver as Surface Serial Hub (SSH). When
54needed, we differentiate between both types of SAM by referring to them as
55SAM-over-SSH and SAM-over-HID.
56
57Currently, this subsystem only supports SAM-over-SSH. The SSH communication
58interface is described in more detail below. The HID interface has not been
59reverse engineered yet and it is, at the moment, unclear how many (and
60which) concepts of the SSH interface detailed below can be transferred to
61it.
62
63Surface Serial Hub
64------------------
65
66As already elaborated above, the Surface Serial Hub (SSH) is the
67communication interface for SAM on 5th- and all later-generation Surface
68devices. On the highest level, communication can be separated into two main
69types: Requests, messages sent from host to EC that may trigger a direct
70response from the EC (explicitly associated with the request), and events
71(sometimes also referred to as notifications), sent from EC to host without
72being a direct response to a previous request. We may also refer to requests
73without response as commands. In general, events need to be enabled via one
74of multiple dedicated requests before they are sent by the EC.
75
76See :doc:`ssh` for a more technical protocol documentation and
77:doc:`internal` for an overview of the internal driver architecture.
Documentation/driver-api/surface_aggregator/ssh.rst+344−0
@@ -0,0 +1,344 @@
1.. SPDX-License-Identifier: GPL-2.0+
2
3.. |u8| replace:: :c:type:`u8 <u8>`
4.. |u16| replace:: :c:type:`u16 <u16>`
5.. |TYPE| replace:: ``TYPE``
6.. |LEN| replace:: ``LEN``
7.. |SEQ| replace:: ``SEQ``
8.. |SYN| replace:: ``SYN``
9.. |NAK| replace:: ``NAK``
10.. |ACK| replace:: ``ACK``
11.. |DATA| replace:: ``DATA``
12.. |DATA_SEQ| replace:: ``DATA_SEQ``
13.. |DATA_NSQ| replace:: ``DATA_NSQ``
14.. |TC| replace:: ``TC``
15.. |TID| replace:: ``TID``
16.. |IID| replace:: ``IID``
17.. |RQID| replace:: ``RQID``
18.. |CID| replace:: ``CID``
19
20===========================
21Surface Serial Hub Protocol
22===========================
23
24The Surface Serial Hub (SSH) is the central communication interface for the
25embedded Surface Aggregator Module controller (SAM or EC), found on newer
26Surface generations. We will refer to this protocol and interface as
27SAM-over-SSH, as opposed to SAM-over-HID for the older generations.
28
29On Surface devices with SAM-over-SSH, SAM is connected to the host via UART
30and defined in ACPI as device with ID ``MSHW0084``. On these devices,
31significant functionality is provided via SAM, including access to battery
32and power information and events, thermal read-outs and events, and many
33more. For Surface Laptops, keyboard input is handled via HID directed
34through SAM, on the Surface Laptop 3 and Surface Book 3 this also includes
35touchpad input.
36
37Note that the standard disclaimer for this subsystem also applies to this
38document: All of this has been reverse-engineered and may thus be erroneous
39and/or incomplete.
40
41All CRCs used in the following are two-byte ``crc_ccitt_false(0xffff, ...)``.
42All multi-byte values are little-endian, there is no implicit padding between
43values.
44
45
46SSH Packet Protocol: Definitions
47================================
48
49The fundamental communication unit of the SSH protocol is a frame
50(:c:type:`struct ssh_frame <ssh_frame>`). A frame consists of the following
51fields, packed together and in order:
52
53.. flat-table:: SSH Frame
54 :widths: 1 1 4
55 :header-rows: 1
56
57 * - Field
58 - Type
59 - Description
60
61 * - |TYPE|
62 - |u8|
63 - Type identifier of the frame.
64
65 * - |LEN|
66 - |u16|
67 - Length of the payload associated with the frame.
68
69 * - |SEQ|
70 - |u8|
71 - Sequence ID (see explanation below).
72
73Each frame structure is followed by a CRC over this structure. The CRC over
74the frame structure (|TYPE|, |LEN|, and |SEQ| fields) is placed directly
75after the frame structure and before the payload. The payload is followed by
76its own CRC (over all payload bytes). If the payload is not present (i.e.
77the frame has ``LEN=0``), the CRC of the payload is still present and will
78evaluate to ``0xffff``. The |LEN| field does not include any of the CRCs, it
79equals the number of bytes inbetween the CRC of the frame and the CRC of the
80payload.
81
82Additionally, the following fixed two-byte sequences are used:
83
84.. flat-table:: SSH Byte Sequences
85 :widths: 1 1 4
86 :header-rows: 1
87
88 * - Name
89 - Value
90 - Description
91
92 * - |SYN|
93 - ``[0xAA, 0x55]``
94 - Synchronization bytes.
95
96A message consists of |SYN|, followed by the frame (|TYPE|, |LEN|, |SEQ| and
97CRC) and, if specified in the frame (i.e. ``LEN > 0``), payload bytes,
98followed finally, regardless if the payload is present, the payload CRC. The
99messages corresponding to an exchange are, in part, identified by having the
100same sequence ID (|SEQ|), stored inside the frame (more on this in the next
101section). The sequence ID is a wrapping counter.
102
103A frame can have the following types
104(:c:type:`enum ssh_frame_type <ssh_frame_type>`):
105
106.. flat-table:: SSH Frame Types
107 :widths: 1 1 4
108 :header-rows: 1
109
110 * - Name
111 - Value
112 - Short Description
113
114 * - |NAK|
115 - ``0x04``
116 - Sent on error in previously received message.
117
118 * - |ACK|
119 - ``0x40``
120 - Sent to acknowledge receival of |DATA| frame.
121
122 * - |DATA_SEQ|
123 - ``0x80``
124 - Sent to transfer data. Sequenced.
125
126 * - |DATA_NSQ|
127 - ``0x00``
128 - Same as |DATA_SEQ|, but does not need to be ACKed.
129
130Both |NAK|- and |ACK|-type frames are used to control flow of messages and
131thus do not carry a payload. |DATA_SEQ|- and |DATA_NSQ|-type frames on the
132other hand must carry a payload. The flow sequence and interaction of
133different frame types will be described in more depth in the next section.
134
135
136SSH Packet Protocol: Flow Sequence
137==================================
138
139Each exchange begins with |SYN|, followed by a |DATA_SEQ|- or
140|DATA_NSQ|-type frame, followed by its CRC, payload, and payload CRC. In
141case of a |DATA_NSQ|-type frame, the exchange is then finished. In case of a
142|DATA_SEQ|-type frame, the receiving party has to acknowledge receival of
143the frame by responding with a message containing an |ACK|-type frame with
144the same sequence ID of the |DATA| frame. In other words, the sequence ID of
145the |ACK| frame specifies the |DATA| frame to be acknowledged. In case of an
146error, e.g. an invalid CRC, the receiving party responds with a message
147containing an |NAK|-type frame. As the sequence ID of the previous data
148frame, for which an error is indicated via the |NAK| frame, cannot be relied
149upon, the sequence ID of the |NAK| frame should not be used and is set to
150zero. After receival of an |NAK| frame, the sending party should re-send all
151outstanding (non-ACKed) messages.
152
153Sequence IDs are not synchronized between the two parties, meaning that they
154are managed independently for each party. Identifying the messages
155corresponding to a single exchange thus relies on the sequence ID as well as
156the type of the message, and the context. Specifically, the sequence ID is
157used to associate an ``ACK`` with its ``DATA_SEQ``-type frame, but not
158``DATA_SEQ``- or ``DATA_NSQ``-type frames with other ``DATA``- type frames.
159
160An example exchange might look like this:
161
162::
163
164 tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) -----------------------------
165 rx: ------------------------------------- SYN FRAME(A) CRC(F) CRC(P) --
166
167where both frames have the same sequence ID (``SEQ``). Here, ``FRAME(D)``
168indicates a |DATA_SEQ|-type frame, ``FRAME(A)`` an ``ACK``-type frame,
169``CRC(F)`` the CRC over the previous frame, ``CRC(P)`` the CRC over the
170previous payload. In case of an error, the exchange would look like this:
171
172::
173
174 tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) -----------------------------
175 rx: ------------------------------------- SYN FRAME(N) CRC(F) CRC(P) --
176
177upon which the sender should re-send the message. ``FRAME(N)`` indicates an
178|NAK|-type frame. Note that the sequence ID of the |NAK|-type frame is fixed
179to zero. For |DATA_NSQ|-type frames, both exchanges are the same:
180
181::
182
183 tx: -- SYN FRAME(DATA_NSQ) CRC(F) PAYLOAD CRC(P) ----------------------
184 rx: -------------------------------------------------------------------
185
186Here, an error can be detected, but not corrected or indicated to the
187sending party. These exchanges are symmetric, i.e. switching ``rx`` and
188``tx`` results again in a valid exchange. Currently, no longer exchanges are
189known.
190
191
192Commands: Requests, Responses, and Events
193=========================================
194
195Commands are sent as payload inside a data frame. Currently, this is the
196only known payload type of |DATA| frames, with a payload-type value of
197``0x80`` (:c:type:`SSH_PLD_TYPE_CMD <ssh_payload_type>`).
198
199The command-type payload (:c:type:`struct ssh_command <ssh_command>`)
200consists of an eight-byte command structure, followed by optional and
201variable length command data. The length of this optional data is derived
202from the frame payload length given in the corresponding frame, i.e. it is
203``frame.len - sizeof(struct ssh_command)``. The command struct contains the
204following fields, packed together and in order:
205
206.. flat-table:: SSH Command
207 :widths: 1 1 4
208 :header-rows: 1
209
210 * - Field
211 - Type
212 - Description
213
214 * - |TYPE|
215 - |u8|
216 - Type of the payload. For commands always ``0x80``.
217
218 * - |TC|
219 - |u8|
220 - Target category.
221
222 * - |TID| (out)
223 - |u8|
224 - Target ID for outgoing (host to EC) commands.
225
226 * - |TID| (in)
227 - |u8|
228 - Target ID for incoming (EC to host) commands.
229
230 * - |IID|
231 - |u8|
232 - Instance ID.
233
234 * - |RQID|
235 - |u16|
236 - Request ID.
237
238 * - |CID|
239 - |u8|
240 - Command ID.
241
242The command struct and data, in general, does not contain any failure
243detection mechanism (e.g. CRCs), this is solely done on the frame level.
244
245Command-type payloads are used by the host to send commands and requests to
246the EC as well as by the EC to send responses and events back to the host.
247We differentiate between requests (sent by the host), responses (sent by the
248EC in response to a request), and events (sent by the EC without a preceding
249request).
250
251Commands and events are uniquely identified by their target category
252(``TC``) and command ID (``CID``). The target category specifies a general
253category for the command (e.g. system in general, vs. battery and AC, vs.
254temperature, and so on), while the command ID specifies the command inside
255that category. Only the combination of |TC| + |CID| is unique. Additionally,
256commands have an instance ID (``IID``), which is used to differentiate
257between different sub-devices. For example ``TC=3`` ``CID=1`` is a
258request to get the temperature on a thermal sensor, where |IID| specifies
259the respective sensor. If the instance ID is not used, it should be set to
260zero. If instance IDs are used, they, in general, start with a value of one,
261whereas zero may be used for instance independent queries, if applicable. A
262response to a request should have the same target category, command ID, and
263instance ID as the corresponding request.
264
265Responses are matched to their corresponding request via the request ID
266(``RQID``) field. This is a 16 bit wrapping counter similar to the sequence
267ID on the frames. Note that the sequence ID of the frames for a
268request-response pair does not match. Only the request ID has to match.
269Frame-protocol wise these are two separate exchanges, and may even be
270separated, e.g. by an event being sent after the request but before the
271response. Not all commands produce a response, and this is not detectable by
272|TC| + |CID|. It is the responsibility of the issuing party to wait for a
273response (or signal this to the communication framework, as is done in
274SAN/ACPI via the ``SNC`` flag).
275
276Events are identified by unique and reserved request IDs. These IDs should
277not be used by the host when sending a new request. They are used on the
278host to, first, detect events and, second, match them with a registered
279event handler. Request IDs for events are chosen by the host and directed to
280the EC when setting up and enabling an event source (via the
281enable-event-source request). The EC then uses the specified request ID for
282events sent from the respective source. Note that an event should still be
283identified by its target category, command ID, and, if applicable, instance
284ID, as a single event source can send multiple different event types. In
285general, however, a single target category should map to a single reserved
286event request ID.
287
288Furthermore, requests, responses, and events have an associated target ID
289(``TID``). This target ID is split into output (host to EC) and input (EC to
290host) fields, with the respecting other field (e.g. output field on incoming
291messages) set to zero. Two ``TID`` values are known: Primary (``0x01``) and
292secondary (``0x02``). In general, the response to a request should have the
293same ``TID`` value, however, the field (output vs. input) should be used in
294accordance to the direction in which the response is sent (i.e. on the input
295field, as responses are generally sent from the EC to the host).
296
297Note that, even though requests and events should be uniquely identifiable
298by target category and command ID alone, the EC may require specific
299target ID and instance ID values to accept a command. A command that is
300accepted for ``TID=1``, for example, may not be accepted for ``TID=2``
301and vice versa.
302
303
304Limitations and Observations
305============================
306
307The protocol can, in theory, handle up to ``U8_MAX`` frames in parallel,
308with up to ``U16_MAX`` pending requests (neglecting request IDs reserved for
309events). In practice, however, this is more limited. From our testing
310(although via a python and thus a user-space program), it seems that the EC
311can handle up to four requests (mostly) reliably in parallel at a certain
312time. With five or more requests in parallel, consistent discarding of
313commands (ACKed frame but no command response) has been observed. For five
314simultaneous commands, this reproducibly resulted in one command being
315dropped and four commands being handled.
316
317However, it has also been noted that, even with three requests in parallel,
318occasional frame drops happen. Apart from this, with a limit of three
319pending requests, no dropped commands (i.e. command being dropped but frame
320carrying command being ACKed) have been observed. In any case, frames (and
321possibly also commands) should be re-sent by the host if a certain timeout
322is exceeded. This is done by the EC for frames with a timeout of one second,
323up to two re-tries (i.e. three transmissions in total). The limit of
324re-tries also applies to received NAKs, and, in a worst case scenario, can
325lead to entire messages being dropped.
326
327While this also seems to work fine for pending data frames as long as no
328transmission failures occur, implementation and handling of these seems to
329depend on the assumption that there is only one non-acknowledged data frame.
330In particular, the detection of repeated frames relies on the last sequence
331number. This means that, if a frame that has been successfully received by
332the EC is sent again, e.g. due to the host not receiving an |ACK|, the EC
333will only detect this if it has the sequence ID of the last frame received
334by the EC. As an example: Sending two frames with ``SEQ=0`` and ``SEQ=1``
335followed by a repetition of ``SEQ=0`` will not detect the second ``SEQ=0``
336frame as such, and thus execute the command in this frame each time it has
337been received, i.e. twice in this example. Sending ``SEQ=0``, ``SEQ=1`` and
338then repeating ``SEQ=1`` will detect the second ``SEQ=1`` as repetition of
339the first one and ignore it, thus executing the contained command only once.
340
341In conclusion, this suggests a limit of at most one pending un-ACKed frame
342(per party, effectively leading to synchronous communication regarding
343frames) and at most three pending commands. The limit to synchronous frame
344transfers seems to be consistent with behavior observed on Windows.
Documentation/userspace-api/ioctl/ioctl-number.rst+2−0
@@ -324,6 +324,8 @@ Code Seq# Include File Comments · 323 unmodified lines
3240xA3 90-9F linux/dtlk.h3240xA3 90-9F linux/dtlk.h
3250xA4 00-1F uapi/linux/tee.h Generic TEE subsystem3250xA4 00-1F uapi/linux/tee.h Generic TEE subsystem
3260xA4 00-1F uapi/asm/sgx.h <mailto:linux-sgx@vger.kernel.org>3260xA4 00-1F uapi/asm/sgx.h <mailto:linux-sgx@vger.kernel.org>
3270xA5 01 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator
328 <mailto:luzmaximilian@gmail.com>
3270xAA 00-3F linux/uapi/linux/userfaultfd.h3290xAA 00-3F linux/uapi/linux/userfaultfd.h
3280xAB 00-1F linux/nbd.h3300xAB 00-1F linux/nbd.h
3290xAC 00-1F linux/raw.h3310xAC 00-1F linux/raw.h
MAINTAINERS+31−14
@@ -4946,17 +4946,17 @@ M: Matthew Garrett <mjg59@srcf.ucam.org> · 4945 unmodified lines
4946M: Pali Rohár <pali@kernel.org>4946M: Pali Rohár <pali@kernel.org>
4947L: platform-driver-x86@vger.kernel.org4947L: platform-driver-x86@vger.kernel.org
4948S: Maintained4948S: Maintained
4949F: drivers/platform/x86/dell-laptop.c4949F: drivers/platform/x86/dell/dell-laptop.c
4950 4950
4951DELL LAPTOP FREEFALL DRIVER4951DELL LAPTOP FREEFALL DRIVER
4952M: Pali Rohár <pali@kernel.org>4952M: Pali Rohár <pali@kernel.org>
4953S: Maintained4953S: Maintained
4954F: drivers/platform/x86/dell-smo8800.c4954F: drivers/platform/x86/dell/dell-smo8800.c
4955 4955
4956DELL LAPTOP RBTN DRIVER4956DELL LAPTOP RBTN DRIVER
4957M: Pali Rohár <pali@kernel.org>4957M: Pali Rohár <pali@kernel.org>
4958S: Maintained4958S: Maintained
4959F: drivers/platform/x86/dell-rbtn.*4959F: drivers/platform/x86/dell/dell-rbtn.*
4960 4960
4961DELL LAPTOP SMM DRIVER4961DELL LAPTOP SMM DRIVER
4962M: Pali Rohár <pali@kernel.org>4962M: Pali Rohár <pali@kernel.org>
@@ -4968,26 +4968,26 @@ DELL REMOTE BIOS UPDATE DRIVER · 5 unmodified lines
4968M: Stuart Hayes <stuart.w.hayes@gmail.com>4968M: Stuart Hayes <stuart.w.hayes@gmail.com>
4969L: platform-driver-x86@vger.kernel.org4969L: platform-driver-x86@vger.kernel.org
4970S: Maintained4970S: Maintained
4971F: drivers/platform/x86/dell_rbu.c4971F: drivers/platform/x86/dell/dell_rbu.c
4972 4972
4973DELL SMBIOS DRIVER4973DELL SMBIOS DRIVER
4974M: Pali Rohár <pali@kernel.org>4974M: Pali Rohár <pali@kernel.org>
4975M: Mario Limonciello <mario.limonciello@dell.com>4975M: Mario Limonciello <mario.limonciello@dell.com>
4976L: platform-driver-x86@vger.kernel.org4976L: platform-driver-x86@vger.kernel.org
4977S: Maintained4977S: Maintained
4978F: drivers/platform/x86/dell-smbios.*4978F: drivers/platform/x86/dell/dell-smbios.*
4979 4979
4980DELL SMBIOS SMM DRIVER4980DELL SMBIOS SMM DRIVER
4981M: Mario Limonciello <mario.limonciello@dell.com>4981M: Mario Limonciello <mario.limonciello@dell.com>
4982L: platform-driver-x86@vger.kernel.org4982L: platform-driver-x86@vger.kernel.org
4983S: Maintained4983S: Maintained
4984F: drivers/platform/x86/dell-smbios-smm.c4984F: drivers/platform/x86/dell/dell-smbios-smm.c
4985 4985
4986DELL SMBIOS WMI DRIVER4986DELL SMBIOS WMI DRIVER
4987M: Mario Limonciello <mario.limonciello@dell.com>4987M: Mario Limonciello <mario.limonciello@dell.com>
4988L: platform-driver-x86@vger.kernel.org4988L: platform-driver-x86@vger.kernel.org
4989S: Maintained4989S: Maintained
4990F: drivers/platform/x86/dell-smbios-wmi.c4990F: drivers/platform/x86/dell/dell-smbios-wmi.c
4991F: tools/wmi/dell-smbios-example.c4991F: tools/wmi/dell-smbios-example.c
4992 4992
4993DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)4993DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
@@ -4995,12 +4995,12 @@ M: Stuart Hayes <stuart.w.hayes@gmail.com> · 1 unmodified line
4995L: platform-driver-x86@vger.kernel.org4995L: platform-driver-x86@vger.kernel.org
4996S: Maintained4996S: Maintained
4997F: Documentation/driver-api/dcdbas.rst4997F: Documentation/driver-api/dcdbas.rst
4998F: drivers/platform/x86/dcdbas.*4998F: drivers/platform/x86/dell/dcdbas.*
4999 4999
5000DELL WMI DESCRIPTOR DRIVER5000DELL WMI DESCRIPTOR DRIVER
5001M: Mario Limonciello <mario.limonciello@dell.com>5001M: Mario Limonciello <mario.limonciello@dell.com>
5002S: Maintained5002S: Maintained
5003F: drivers/platform/x86/dell-wmi-descriptor.c5003F: drivers/platform/x86/dell/dell-wmi-descriptor.c
5004 5004
5005DELL WMI SYSMAN DRIVER5005DELL WMI SYSMAN DRIVER
5006M: Divya Bharathi <divya.bharathi@dell.com>5006M: Divya Bharathi <divya.bharathi@dell.com>
@@ -5009,13 +5009,13 @@ M: Prasanth Ksr <prasanth.ksr@dell.com> · 2 unmodified lines
5009L: platform-driver-x86@vger.kernel.org5009L: platform-driver-x86@vger.kernel.org
5010S: Maintained5010S: Maintained
5011F: Documentation/ABI/testing/sysfs-class-firmware-attributes5011F: Documentation/ABI/testing/sysfs-class-firmware-attributes
5012F: drivers/platform/x86/dell-wmi-sysman/5012F: drivers/platform/x86/dell/dell-wmi-sysman/
5013 5013
5014DELL WMI NOTIFICATIONS DRIVER5014DELL WMI NOTIFICATIONS DRIVER
5015M: Matthew Garrett <mjg59@srcf.ucam.org>5015M: Matthew Garrett <mjg59@srcf.ucam.org>
5016M: Pali Rohár <pali@kernel.org>5016M: Pali Rohár <pali@kernel.org>
5017S: Maintained5017S: Maintained
5018F: drivers/platform/x86/dell-wmi.c5018F: drivers/platform/x86/dell/dell-wmi.c
5019 5019
5020DELTA ST MEDIA DRIVER5020DELTA ST MEDIA DRIVER
5021M: Hugues Fruchet <hugues.fruchet@st.com>5021M: Hugues Fruchet <hugues.fruchet@st.com>
@@ -8908,7 +8908,6 @@ L: linux-gpio@vger.kernel.org · 3886 unmodified lines
8908S: Maintained8908S: Maintained
8909T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git8909T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
8910F: drivers/gpio/gpio-ich.c8910F: drivers/gpio/gpio-ich.c
8911F: drivers/gpio/gpio-intel-mid.c
8912F: drivers/gpio/gpio-merrifield.c8911F: drivers/gpio/gpio-merrifield.c
8913F: drivers/gpio/gpio-ml-ioh.c8912F: drivers/gpio/gpio-ml-ioh.c
8914F: drivers/gpio/gpio-pch.c8913F: drivers/gpio/gpio-pch.c
@@ -9080,7 +9079,6 @@ M: Andy Shevchenko <andy@kernel.org> · 165 unmodified lines
9080S: Maintained9079S: Maintained
9081T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git9080T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
9082F: drivers/gpio/gpio-*cove.c9081F: drivers/gpio/gpio-*cove.c
9083F: drivers/gpio/gpio-msic.c
9084 9082
9085INTEL PMIC MULTIFUNCTION DEVICE DRIVERS9083INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
9086M: Andy Shevchenko <andy@kernel.org>9084M: Andy Shevchenko <andy@kernel.org>
@@ -11798,12 +11796,31 @@ S: Maintained · 2711 unmodified lines
11798T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git11796T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
11799F: drivers/platform/surface/11797F: drivers/platform/surface/
11800 11798
11799MICROSOFT SURFACE HOT-PLUG DRIVER
11800M: Maximilian Luz <luzmaximilian@gmail.com>
11801L: platform-driver-x86@vger.kernel.org
11802S: Maintained
11803F: drivers/platform/surface/surface_hotplug.c
11804
11801MICROSOFT SURFACE PRO 3 BUTTON DRIVER11805MICROSOFT SURFACE PRO 3 BUTTON DRIVER
11802M: Chen Yu <yu.c.chen@intel.com>11806M: Chen Yu <yu.c.chen@intel.com>
11803L: platform-driver-x86@vger.kernel.org11807L: platform-driver-x86@vger.kernel.org
11804S: Supported11808S: Supported
11805F: drivers/platform/surface/surfacepro3_button.c11809F: drivers/platform/surface/surfacepro3_button.c
11806 11810
11811MICROSOFT SURFACE SYSTEM AGGREGATOR SUBSYSTEM
11812M: Maximilian Luz <luzmaximilian@gmail.com>
11813S: Maintained
11814W: https://github.com/linux-surface/surface-aggregator-module
11815C: irc://chat.freenode.net/##linux-surface
11816F: Documentation/driver-api/surface_aggregator/
11817F: drivers/platform/surface/aggregator/
11818F: drivers/platform/surface/surface_acpi_notify.c
11819F: drivers/platform/surface/surface_aggregator_cdev.c
11820F: include/linux/surface_acpi_notify.h
11821F: include/linux/surface_aggregator/
11822F: include/uapi/linux/surface_aggregator/
11823
11807MICROTEK X6 SCANNER11824MICROTEK X6 SCANNER
11808M: Oliver Neukum <oliver@neukum.org>11825M: Oliver Neukum <oliver@neukum.org>
11809S: Maintained11826S: Maintained
@@ -17656,7 +17673,7 @@ F: drivers/thermal/gov_power_allocator.c · 5846 unmodified lines
17656F: include/trace/events/thermal_power_allocator.h17673F: include/trace/events/thermal_power_allocator.h
17657 17674
17658THINKPAD ACPI EXTRAS DRIVER17675THINKPAD ACPI EXTRAS DRIVER
17659M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>17676M: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
17660L: ibm-acpi-devel@lists.sourceforge.net17677L: ibm-acpi-devel@lists.sourceforge.net
17661L: platform-driver-x86@vger.kernel.org17678L: platform-driver-x86@vger.kernel.org
17662S: Maintained17679S: Maintained
arch/x86/platform/intel-mid/device_libs/Makefile+0−1
@@ -30,4 +30,3 @@ obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o · 29 unmodified lines
30obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o30obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o
31obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_mrfld_power_btn.o31obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_mrfld_power_btn.o
32obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o32obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o
33obj-$(subst m,y,$(CONFIG_INTEL_MID_WATCHDOG)) += platform_mrfld_wdt.o
drivers/gpio/Kconfig+0−14
@@ -1253,13 +1253,6 @@ config GPIO_MAX77650 · 1252 unmodified lines
1253 GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.1253 GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.
1254 These chips have a single pin that can be configured as GPIO.1254 These chips have a single pin that can be configured as GPIO.
1255 1255
1256config GPIO_MSIC
1257 bool "Intel MSIC mixed signal gpio support"
1258 depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
1259 help
1260 Enable support for GPIO on intel MSIC controllers found in
1261 intel MID devices
1262
1263config GPIO_PALMAS1256config GPIO_PALMAS
1264 bool "TI PALMAS series PMICs GPIO"1257 bool "TI PALMAS series PMICs GPIO"
1265 depends on MFD_PALMAS1258 depends on MFD_PALMAS
@@ -1455,13 +1448,6 @@ config GPIO_BT8XX · 189 unmodified lines
1455 1448
1456 If unsure, say N.1449 If unsure, say N.
1457 1450
1458config GPIO_INTEL_MID
1459 bool "Intel MID GPIO support"
1460 depends on X86_INTEL_MID
1461 select GPIOLIB_IRQCHIP
1462 help
1463 Say Y here to support Intel MID GPIO.
1464
1465config GPIO_MERRIFIELD1451config GPIO_MERRIFIELD
1466 tristate "Intel Merrifield GPIO support"1452 tristate "Intel Merrifield GPIO support"
1467 depends on X86_INTEL_MID1453 depends on X86_INTEL_MID
drivers/gpio/Makefile+0−1
@@ -67,7 +67,6 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o · 66 unmodified lines
67obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o67obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
68obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o68obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
69obj-$(CONFIG_GPIO_ICH) += gpio-ich.o69obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
70obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
71obj-$(CONFIG_GPIO_IOP) += gpio-iop.o70obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
72obj-$(CONFIG_GPIO_IT87) += gpio-it87.o71obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
73obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o72obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
drivers/gpio/TODO+1−1
@@ -101,7 +101,7 @@ for a few GPIOs. Those should stay where they are. · 100 unmodified lines
101 101
102At the same time it makes sense to get rid of code duplication in existing or102At the same time it makes sense to get rid of code duplication in existing or
103new coming drivers. For example, gpio-ml-ioh should be incorporated into103new coming drivers. For example, gpio-ml-ioh should be incorporated into
104gpio-pch. In similar way gpio-intel-mid into gpio-pxa.104gpio-pch.
105 105
106 106
107Generic MMIO GPIO107Generic MMIO GPIO
drivers/gpio/gpio-intel-mid.c+0−414
@@ -1,414 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel MID GPIO driver
4 *
5 * Copyright (c) 2008-2014,2016 Intel Corporation.
6 */
7
8/* Supports:
9 * Moorestown platform Langwell chip.
10 * Medfield platform Penwell chip.
11 * Clovertrail platform Cloverview chip.
12 */
13
14#include <linux/delay.h>
15#include <linux/gpio/driver.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/pci.h>
21#include <linux/platform_device.h>
22#include <linux/pm_runtime.h>
23#include <linux/slab.h>
24#include <linux/stddef.h>
25
26#define INTEL_MID_IRQ_TYPE_EDGE (1 << 0)
27#define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1)
28
29/*
30 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
31 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
32 * registers to control them, so we only define the order here instead of a
33 * structure, to get a bit offset for a pin (use GPDR as an example):
34 *
35 * nreg = ngpio / 32;
36 * reg = offset / 32;
37 * bit = offset % 32;
38 * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
39 *
40 * so the bit of reg_addr is to control pin offset's GPDR feature
41*/
42
43enum GPIO_REG {
44 GPLR = 0, /* pin level read-only */
45 GPDR, /* pin direction */
46 GPSR, /* pin set */
47 GPCR, /* pin clear */
48 GRER, /* rising edge detect */
49 GFER, /* falling edge detect */
50 GEDR, /* edge detect result */
51 GAFR, /* alt function */
52};
53
54/* intel_mid gpio driver data */
55struct intel_mid_gpio_ddata {
56 u16 ngpio; /* number of gpio pins */
57 u32 chip_irq_type; /* chip interrupt type */
58};
59
60struct intel_mid_gpio {
61 struct gpio_chip chip;
62 void __iomem *reg_base;
63 spinlock_t lock;
64 struct pci_dev *pdev;
65};
66
67static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
68 enum GPIO_REG reg_type)
69{
70 struct intel_mid_gpio *priv = gpiochip_get_data(chip);
71 unsigned nreg = chip->ngpio / 32;
72 u8 reg = offset / 32;
73
74 return priv->reg_base + reg_type * nreg * 4 + reg * 4;
75}
76
77static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
78 enum GPIO_REG reg_type)
79{
80 struct intel_mid_gpio *priv = gpiochip_get_data(chip);
81 unsigned nreg = chip->ngpio / 32;
82 u8 reg = offset / 16;
83
84 return priv->reg_base + reg_type * nreg * 4 + reg * 4;
85}
86
87static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
88{
89 void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
90 u32 value = readl(gafr);
91 int shift = (offset % 16) << 1, af = (value >> shift) & 3;
92
93 if (af) {
94 value &= ~(3 << shift);
95 writel(value, gafr);
96 }
97 return 0;
98}
99
100static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
101{
102 void __iomem *gplr = gpio_reg(chip, offset, GPLR);
103
104 return !!(readl(gplr) & BIT(offset % 32));
105}
106
107static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
108{
109 void __iomem *gpsr, *gpcr;
110
111 if (value) {
112 gpsr = gpio_reg(chip, offset, GPSR);
113 writel(BIT(offset % 32), gpsr);
114 } else {
115 gpcr = gpio_reg(chip, offset, GPCR);
116 writel(BIT(offset % 32), gpcr);
117 }
118}
119
120static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
121{
122 struct intel_mid_gpio *priv = gpiochip_get_data(chip);
123 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
124 u32 value;
125 unsigned long flags;
126
127 if (priv->pdev)
128 pm_runtime_get(&priv->pdev->dev);
129
130 spin_lock_irqsave(&priv->lock, flags);
131 value = readl(gpdr);
132 value &= ~BIT(offset % 32);
133 writel(value, gpdr);
134 spin_unlock_irqrestore(&priv->lock, flags);
135
136 if (priv->pdev)
137 pm_runtime_put(&priv->pdev->dev);
138
139 return 0;
140}
141
142static int intel_gpio_direction_output(struct gpio_chip *chip,
143 unsigned offset, int value)
144{
145 struct intel_mid_gpio *priv = gpiochip_get_data(chip);
146 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
147 unsigned long flags;
148
149 intel_gpio_set(chip, offset, value);
150
151 if (priv->pdev)
152 pm_runtime_get(&priv->pdev->dev);
153
154 spin_lock_irqsave(&priv->lock, flags);
155 value = readl(gpdr);
156 value |= BIT(offset % 32);
157 writel(value, gpdr);
158 spin_unlock_irqrestore(&priv->lock, flags);
159
160 if (priv->pdev)
161 pm_runtime_put(&priv->pdev->dev);
162
163 return 0;
164}
165
166static int intel_mid_irq_type(struct irq_data *d, unsigned type)
167{
168 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
169 struct intel_mid_gpio *priv = gpiochip_get_data(gc);
170 u32 gpio = irqd_to_hwirq(d);
171 unsigned long flags;
172 u32 value;
173 void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
174 void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
175
176 if (gpio >= priv->chip.ngpio)
177 return -EINVAL;
178
179 if (priv->pdev)
180 pm_runtime_get(&priv->pdev->dev);
181
182 spin_lock_irqsave(&priv->lock, flags);
183 if (type & IRQ_TYPE_EDGE_RISING)
184 value = readl(grer) | BIT(gpio % 32);
185 else
186 value = readl(grer) & (~BIT(gpio % 32));
187 writel(value, grer);
188
189 if (type & IRQ_TYPE_EDGE_FALLING)
190 value = readl(gfer) | BIT(gpio % 32);
191 else
192 value = readl(gfer) & (~BIT(gpio % 32));
193 writel(value, gfer);
194 spin_unlock_irqrestore(&priv->lock, flags);
195
196 if (priv->pdev)
197 pm_runtime_put(&priv->pdev->dev);
198
199 return 0;
200}
201
202static void intel_mid_irq_unmask(struct irq_data *d)
203{
204}
205
206static void intel_mid_irq_mask(struct irq_data *d)
207{
208}
209
210static struct irq_chip intel_mid_irqchip = {
211 .name = "INTEL_MID-GPIO",
212 .irq_mask = intel_mid_irq_mask,
213 .irq_unmask = intel_mid_irq_unmask,
214 .irq_set_type = intel_mid_irq_type,
215};
216
217static const struct intel_mid_gpio_ddata gpio_lincroft = {
218 .ngpio = 64,
219};
220
221static const struct intel_mid_gpio_ddata gpio_penwell_aon = {
222 .ngpio = 96,
223 .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
224};
225
226static const struct intel_mid_gpio_ddata gpio_penwell_core = {
227 .ngpio = 96,
228 .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
229};
230
231static const struct intel_mid_gpio_ddata gpio_cloverview_aon = {
232 .ngpio = 96,
233 .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL,
234};
235
236static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
237 .ngpio = 96,
238 .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
239};
240
241static const struct pci_device_id intel_gpio_ids[] = {
242 {
243 /* Lincroft */
244 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
245 .driver_data = (kernel_ulong_t)&gpio_lincroft,
246 },
247 {
248 /* Penwell AON */
249 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
250 .driver_data = (kernel_ulong_t)&gpio_penwell_aon,
251 },
252 {
253 /* Penwell Core */
254 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
255 .driver_data = (kernel_ulong_t)&gpio_penwell_core,
256 },
257 {
258 /* Cloverview Aon */
259 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
260 .driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
261 },
262 {
263 /* Cloverview Core */
264 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
265 .driver_data = (kernel_ulong_t)&gpio_cloverview_core,
266 },
267 { }
268};
269
270static void intel_mid_irq_handler(struct irq_desc *desc)
271{
272 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
273 struct intel_mid_gpio *priv = gpiochip_get_data(gc);
274 struct irq_data *data = irq_desc_get_irq_data(desc);
275 struct irq_chip *chip = irq_data_get_irq_chip(data);
276 u32 base, gpio, mask;
277 unsigned long pending;
278 void __iomem *gedr;
279
280 /* check GPIO controller to check which pin triggered the interrupt */
281 for (base = 0; base < priv->chip.ngpio; base += 32) {
282 gedr = gpio_reg(&priv->chip, base, GEDR);
283 while ((pending = readl(gedr))) {
284 gpio = __ffs(pending);
285 mask = BIT(gpio);
286 /* Clear before handling so we can't lose an edge */
287 writel(mask, gedr);
288 generic_handle_irq(irq_find_mapping(gc->irq.domain,
289 base + gpio));
290 }
291 }
292
293 chip->irq_eoi(data);
294}
295
296static int intel_mid_irq_init_hw(struct gpio_chip *chip)
297{
298 struct intel_mid_gpio *priv = gpiochip_get_data(chip);
299 void __iomem *reg;
300 unsigned base;
301
302 for (base = 0; base < priv->chip.ngpio; base += 32) {
303 /* Clear the rising-edge detect register */
304 reg = gpio_reg(&priv->chip, base, GRER);
305 writel(0, reg);
306 /* Clear the falling-edge detect register */
307 reg = gpio_reg(&priv->chip, base, GFER);
308 writel(0, reg);
309 /* Clear the edge detect status register */
310 reg = gpio_reg(&priv->chip, base, GEDR);
311 writel(~0, reg);
312 }
313
314 return 0;
315}
316
317static int __maybe_unused intel_gpio_runtime_idle(struct device *dev)
318{
319 int err = pm_schedule_suspend(dev, 500);
320 return err ?: -EBUSY;
321}
322
323static const struct dev_pm_ops intel_gpio_pm_ops = {
324 SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle)
325};
326
327static int intel_gpio_probe(struct pci_dev *pdev,
328 const struct pci_device_id *id)
329{
330 void __iomem *base;
331 struct intel_mid_gpio *priv;
332 u32 gpio_base;
333 u32 irq_base;
334 int retval;
335 struct gpio_irq_chip *girq;
336 struct intel_mid_gpio_ddata *ddata =
337 (struct intel_mid_gpio_ddata *)id->driver_data;
338
339 retval = pcim_enable_device(pdev);
340 if (retval)
341 return retval;
342
343 retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
344 if (retval) {
345 dev_err(&pdev->dev, "I/O memory mapping error\n");
346 return retval;
347 }
348
349 base = pcim_iomap_table(pdev)[1];
350
351 irq_base = readl(base);
352 gpio_base = readl(sizeof(u32) + base);
353
354 /* release the IO mapping, since we already get the info from bar1 */
355 pcim_iounmap_regions(pdev, 1 << 1);
356
357 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
358 if (!priv)
359 return -ENOMEM;
360
361 priv->reg_base = pcim_iomap_table(pdev)[0];
362 priv->chip.label = dev_name(&pdev->dev);
363 priv->chip.parent = &pdev->dev;
364 priv->chip.request = intel_gpio_request;
365 priv->chip.direction_input = intel_gpio_direction_input;
366 priv->chip.direction_output = intel_gpio_direction_output;
367 priv->chip.get = intel_gpio_get;
368 priv->chip.set = intel_gpio_set;
369 priv->chip.base = gpio_base;
370 priv->chip.ngpio = ddata->ngpio;
371 priv->chip.can_sleep = false;
372 priv->pdev = pdev;
373
374 spin_lock_init(&priv->lock);
375
376 girq = &priv->chip.irq;
377 girq->chip = &intel_mid_irqchip;
378 girq->init_hw = intel_mid_irq_init_hw;
379 girq->parent_handler = intel_mid_irq_handler;
380 girq->num_parents = 1;
381 girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
382 sizeof(*girq->parents),
383 GFP_KERNEL);
384 if (!girq->parents)
385 return -ENOMEM;
386 girq->parents[0] = pdev->irq;
387 girq->first = irq_base;
388 girq->default_type = IRQ_TYPE_NONE;
389 girq->handler = handle_simple_irq;
390
391 pci_set_drvdata(pdev, priv);
392
393 retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
394 if (retval) {
395 dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
396 return retval;
397 }
398
399 pm_runtime_put_noidle(&pdev->dev);
400 pm_runtime_allow(&pdev->dev);
401
402 return 0;
403}
404
405static struct pci_driver intel_gpio_driver = {
406 .name = "intel_mid_gpio",
407 .id_table = intel_gpio_ids,
408 .probe = intel_gpio_probe,
409 .driver = {
410 .pm = &intel_gpio_pm_ops,
411 },
412};
413
414builtin_pci_driver(intel_gpio_driver);
drivers/gpio/gpio-msic.c+0−314
@@ -1,314 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel Medfield MSIC GPIO driver>
4 * Copyright (c) 2011, Intel Corporation.
5 *
6 * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
7 * Based on intel_pmic_gpio.c
8 */
9
10#include <linux/gpio/driver.h>
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/kernel.h>
14#include <linux/mfd/intel_msic.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17
18/* the offset for the mapping of global gpio pin to irq */
19#define MSIC_GPIO_IRQ_OFFSET 0x100
20
21#define MSIC_GPIO_DIR_IN 0
22#define MSIC_GPIO_DIR_OUT BIT(5)
23#define MSIC_GPIO_TRIG_FALL BIT(1)
24#define MSIC_GPIO_TRIG_RISE BIT(2)
25
26/* masks for msic gpio output GPIOxxxxCTLO registers */
27#define MSIC_GPIO_DIR_MASK BIT(5)
28#define MSIC_GPIO_DRV_MASK BIT(4)
29#define MSIC_GPIO_REN_MASK BIT(3)
30#define MSIC_GPIO_RVAL_MASK (BIT(2) | BIT(1))
31#define MSIC_GPIO_DOUT_MASK BIT(0)
32
33/* masks for msic gpio input GPIOxxxxCTLI registers */
34#define MSIC_GPIO_GLBYP_MASK BIT(5)
35#define MSIC_GPIO_DBNC_MASK (BIT(4) | BIT(3))
36#define MSIC_GPIO_INTCNT_MASK (BIT(2) | BIT(1))
37#define MSIC_GPIO_DIN_MASK BIT(0)
38
39#define MSIC_NUM_GPIO 24
40
41struct msic_gpio {
42 struct platform_device *pdev;
43 struct mutex buslock;
44 struct gpio_chip chip;
45 int irq;
46 unsigned irq_base;
47 unsigned long trig_change_mask;
48 unsigned trig_type;
49};
50
51/*
52 * MSIC has 24 gpios, 16 low voltage (1.2-1.8v) and 8 high voltage (3v).
53 * Both the high and low voltage gpios are divided in two banks.
54 * GPIOs are numbered with GPIO0LV0 as gpio_base in the following order:
55 * GPIO0LV0..GPIO0LV7: low voltage, bank 0, gpio_base
56 * GPIO1LV0..GPIO1LV7: low voltage, bank 1, gpio_base + 8
57 * GPIO0HV0..GPIO0HV3: high voltage, bank 0, gpio_base + 16
58 * GPIO1HV0..GPIO1HV3: high voltage, bank 1, gpio_base + 20
59 */
60
61static int msic_gpio_to_ireg(unsigned offset)
62{
63 if (offset >= MSIC_NUM_GPIO)
64 return -EINVAL;
65
66 if (offset < 8)
67 return INTEL_MSIC_GPIO0LV0CTLI - offset;
68 if (offset < 16)
69 return INTEL_MSIC_GPIO1LV0CTLI - offset + 8;
70 if (offset < 20)
71 return INTEL_MSIC_GPIO0HV0CTLI - offset + 16;
72
73 return INTEL_MSIC_GPIO1HV0CTLI - offset + 20;
74}
75
76static int msic_gpio_to_oreg(unsigned offset)
77{
78 if (offset >= MSIC_NUM_GPIO)
79 return -EINVAL;
80
81 if (offset < 8)
82 return INTEL_MSIC_GPIO0LV0CTLO - offset;
83 if (offset < 16)
84 return INTEL_MSIC_GPIO1LV0CTLO - offset + 8;
85 if (offset < 20)
86 return INTEL_MSIC_GPIO0HV0CTLO - offset + 16;
87
88 return INTEL_MSIC_GPIO1HV0CTLO - offset + 20;
89}
90
91static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
92{
93 int reg;
94
95 reg = msic_gpio_to_oreg(offset);
96 if (reg < 0)
97 return reg;
98
99 return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK);
100}
101
102static int msic_gpio_direction_output(struct gpio_chip *chip,
103 unsigned offset, int value)
104{
105 int reg;
106 unsigned mask;
107
108 value = (!!value) | MSIC_GPIO_DIR_OUT;
109 mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK;
110
111 reg = msic_gpio_to_oreg(offset);
112 if (reg < 0)
113 return reg;
114
115 return intel_msic_reg_update(reg, value, mask);
116}
117
118static int msic_gpio_get(struct gpio_chip *chip, unsigned offset)
119{
120 u8 r;
121 int ret;
122 int reg;
123
124 reg = msic_gpio_to_ireg(offset);
125 if (reg < 0)
126 return reg;
127
128 ret = intel_msic_reg_read(reg, &r);
129 if (ret < 0)
130 return ret;
131
132 return !!(r & MSIC_GPIO_DIN_MASK);
133}
134
135static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
136{
137 int reg;
138
139 reg = msic_gpio_to_oreg(offset);
140 if (reg < 0)
141 return;
142
143 intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK);
144}
145
146/*
147 * This is called from genirq with mg->buslock locked and
148 * irq_desc->lock held. We can not access the scu bus here, so we
149 * store the change and update in the bus_sync_unlock() function below
150 */
151static int msic_irq_type(struct irq_data *data, unsigned type)
152{
153 struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
154 u32 gpio = data->irq - mg->irq_base;
155
156 if (gpio >= mg->chip.ngpio)
157 return -EINVAL;
158
159 /* mark for which gpio the trigger changed, protected by buslock */
160 mg->trig_change_mask |= (1 << gpio);
161 mg->trig_type = type;
162
163 return 0;
164}
165
166static int msic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
167{
168 struct msic_gpio *mg = gpiochip_get_data(chip);
169 return mg->irq_base + offset;
170}
171
172static void msic_bus_lock(struct irq_data *data)
173{
174 struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
175 mutex_lock(&mg->buslock);
176}
177
178static void msic_bus_sync_unlock(struct irq_data *data)
179{
180 struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
181 int offset;
182 int reg;
183 u8 trig = 0;
184
185 /* We can only get one change at a time as the buslock covers the
186 entire transaction. The irq_desc->lock is dropped before we are
187 called but that is fine */
188 if (mg->trig_change_mask) {
189 offset = __ffs(mg->trig_change_mask);
190
191 reg = msic_gpio_to_ireg(offset);
192 if (reg < 0)
193 goto out;
194
195 if (mg->trig_type & IRQ_TYPE_EDGE_RISING)
196 trig |= MSIC_GPIO_TRIG_RISE;
197 if (mg->trig_type & IRQ_TYPE_EDGE_FALLING)
198 trig |= MSIC_GPIO_TRIG_FALL;
199
200 intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK);
201 mg->trig_change_mask = 0;
202 }
203out:
204 mutex_unlock(&mg->buslock);
205}
206
207/* Firmware does all the masking and unmasking for us, no masking here. */
208static void msic_irq_unmask(struct irq_data *data) { }
209
210static void msic_irq_mask(struct irq_data *data) { }
211
212static struct irq_chip msic_irqchip = {
213 .name = "MSIC-GPIO",
214 .irq_mask = msic_irq_mask,
215 .irq_unmask = msic_irq_unmask,
216 .irq_set_type = msic_irq_type,
217 .irq_bus_lock = msic_bus_lock,
218 .irq_bus_sync_unlock = msic_bus_sync_unlock,
219};
220
221static void msic_gpio_irq_handler(struct irq_desc *desc)
222{
223 struct irq_data *data = irq_desc_get_irq_data(desc);
224 struct msic_gpio *mg = irq_data_get_irq_handler_data(data);
225 struct irq_chip *chip = irq_data_get_irq_chip(data);
226 struct intel_msic *msic = pdev_to_intel_msic(mg->pdev);
227 unsigned long pending;
228 int i;
229 int bitnr;
230 u8 pin;
231
232 for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) {
233 intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin);
234 pending = pin;
235
236 for_each_set_bit(bitnr, &pending, BITS_PER_BYTE)
237 generic_handle_irq(mg->irq_base + i * BITS_PER_BYTE + bitnr);
238 }
239 chip->irq_eoi(data);
240}
241
242static int platform_msic_gpio_probe(struct platform_device *pdev)
243{
244 struct device *dev = &pdev->dev;
245 struct intel_msic_gpio_pdata *pdata = dev_get_platdata(dev);
246 struct msic_gpio *mg;
247 int irq = platform_get_irq(pdev, 0);
248 int retval;
249 int i;
250
251 if (irq < 0) {
252 dev_err(dev, "no IRQ line: %d\n", irq);
253 return irq;
254 }
255
256 if (!pdata || !pdata->gpio_base) {
257 dev_err(dev, "incorrect or missing platform data\n");
258 return -EINVAL;
259 }
260
261 mg = kzalloc(sizeof(*mg), GFP_KERNEL);
262 if (!mg)
263 return -ENOMEM;
264
265 dev_set_drvdata(dev, mg);
266
267 mg->pdev = pdev;
268 mg->irq = irq;
269 mg->irq_base = pdata->gpio_base + MSIC_GPIO_IRQ_OFFSET;
270 mg->chip.label = "msic_gpio";
271 mg->chip.direction_input = msic_gpio_direction_input;
272 mg->chip.direction_output = msic_gpio_direction_output;
273 mg->chip.get = msic_gpio_get;
274 mg->chip.set = msic_gpio_set;
275 mg->chip.to_irq = msic_gpio_to_irq;
276 mg->chip.base = pdata->gpio_base;
277 mg->chip.ngpio = MSIC_NUM_GPIO;
278 mg->chip.can_sleep = true;
279 mg->chip.parent = dev;
280
281 mutex_init(&mg->buslock);
282
283 retval = gpiochip_add_data(&mg->chip, mg);
284 if (retval) {
285 dev_err(dev, "Adding MSIC gpio chip failed\n");
286 goto err;
287 }
288
289 for (i = 0; i < mg->chip.ngpio; i++) {
290 irq_set_chip_data(i + mg->irq_base, mg);
291 irq_set_chip_and_handler(i + mg->irq_base,
292 &msic_irqchip,
293 handle_simple_irq);
294 }
295 irq_set_chained_handler_and_data(mg->irq, msic_gpio_irq_handler, mg);
296
297 return 0;
298err:
299 kfree(mg);
300 return retval;
301}
302
303static struct platform_driver platform_msic_gpio_driver = {
304 .driver = {
305 .name = "msic_gpio",
306 },
307 .probe = platform_msic_gpio_probe,
308};
309
310static int __init platform_msic_gpio_init(void)
311{
312 return platform_driver_register(&platform_msic_gpio_driver);
313}
314subsys_initcall(platform_msic_gpio_init);
drivers/gpu/drm/gma500/oaktrail_device.c+0−3
@@ -10,9 +10,6 @@ · 9 unmodified lines
10#include <linux/dmi.h>10#include <linux/dmi.h>
11#include <linux/module.h>11#include <linux/module.h>
12 12
13#include <asm/intel-mid.h>
14#include <asm/intel_scu_ipc.h>
15
16#include <drm/drm.h>13#include <drm/drm.h>
17 14
18#include "intel_bios.h"15#include "intel_bios.h"
drivers/gpu/drm/gma500/psb_drv.h+3−0
@@ -386,6 +386,8 @@ struct psb_ops; · 385 unmodified lines
386 386
387#define PSB_NUM_PIPE 3387#define PSB_NUM_PIPE 3
388 388
389struct intel_scu_ipc_dev;
390
389struct drm_psb_private {391struct drm_psb_private {
390 struct drm_device *dev;392 struct drm_device *dev;
391 struct pci_dev *aux_pdev; /* Currently only used by mrst */393 struct pci_dev *aux_pdev; /* Currently only used by mrst */
@@ -525,6 +527,7 @@ struct drm_psb_private { · 133 unmodified lines
525 * Used for modifying backlight from527 * Used for modifying backlight from
526 * xrandr -- consider removing and using HAL instead528 * xrandr -- consider removing and using HAL instead
527 */529 */
530 struct intel_scu_ipc_dev *scu;
528 struct backlight_device *backlight_device;531 struct backlight_device *backlight_device;
529 struct drm_property *backlight_property;532 struct drm_property *backlight_property;
530 bool backlight_enabled;533 bool backlight_enabled;
drivers/platform/olpc/olpc-ec.c+19−18
@@ -37,7 +37,6 @@ struct olpc_ec_priv { · 36 unmodified lines
37 struct mutex cmd_lock;37 struct mutex cmd_lock;
38 38
39 /* DCON regulator */39 /* DCON regulator */
40 struct regulator_dev *dcon_rdev;
41 bool dcon_enabled;40 bool dcon_enabled;
42 41
43 /* Pending EC commands */42 /* Pending EC commands */
@@ -387,24 +386,26 @@ static int dcon_regulator_is_enabled(struct regulator_dev *rdev) · 343 unmodified lines
387 return ec->dcon_enabled ? 1 : 0;386 return ec->dcon_enabled ? 1 : 0;
388}387}
389 388
390static struct regulator_ops dcon_regulator_ops = {389static const struct regulator_ops dcon_regulator_ops = {
391 .enable = dcon_regulator_enable,390 .enable = dcon_regulator_enable,
392 .disable = dcon_regulator_disable,391 .disable = dcon_regulator_disable,
393 .is_enabled = dcon_regulator_is_enabled,392 .is_enabled = dcon_regulator_is_enabled,
394};393};
395 394
396static const struct regulator_desc dcon_desc = {395static const struct regulator_desc dcon_desc = {
397 .name = "dcon",396 .name = "dcon",
398 .id = 0,397 .id = 0,
399 .ops = &dcon_regulator_ops,398 .ops = &dcon_regulator_ops,
400 .type = REGULATOR_VOLTAGE,399 .type = REGULATOR_VOLTAGE,
401 .owner = THIS_MODULE,400 .owner = THIS_MODULE,
401 .enable_time = 25000,
402};402};
403 403
404static int olpc_ec_probe(struct platform_device *pdev)404static int olpc_ec_probe(struct platform_device *pdev)
405{405{
406 struct olpc_ec_priv *ec;406 struct olpc_ec_priv *ec;
407 struct regulator_config config = { };407 struct regulator_config config = { };
408 struct regulator_dev *regulator;
408 int err;409 int err;
409 410
410 if (!ec_driver)411 if (!ec_driver)
@@ -426,26 +427,26 @@ static int olpc_ec_probe(struct platform_device *pdev) · 15 unmodified lines
426 427
427 /* get the EC revision */428 /* get the EC revision */
428 err = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ec->version, 1);429 err = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ec->version, 1);
429 if (err) {430 if (err)
430 ec_priv = NULL;431 goto error;
431 kfree(ec);
432 return err;
433 }
434 432
435 config.dev = pdev->dev.parent;433 config.dev = pdev->dev.parent;
436 config.driver_data = ec;434 config.driver_data = ec;
437 ec->dcon_enabled = true;435 ec->dcon_enabled = true;
438 ec->dcon_rdev = devm_regulator_register(&pdev->dev, &dcon_desc,436 regulator = devm_regulator_register(&pdev->dev, &dcon_desc, &config);
439 &config);437 if (IS_ERR(regulator)) {
440 if (IS_ERR(ec->dcon_rdev)) {
441 dev_err(&pdev->dev, "failed to register DCON regulator\n");438 dev_err(&pdev->dev, "failed to register DCON regulator\n");
442 err = PTR_ERR(ec->dcon_rdev);439 err = PTR_ERR(regulator);
443 kfree(ec);440 goto error;
444 return err;
445 }441 }
446 442
447 ec->dbgfs_dir = olpc_ec_setup_debugfs();443 ec->dbgfs_dir = olpc_ec_setup_debugfs();
448 444
445 return 0;
446
447error:
448 ec_priv = NULL;
449 kfree(ec);
449 return err;450 return err;
450}451}
451 452
drivers/platform/surface/Kconfig+57−0
@@ -41,6 +41,42 @@ config SURFACE_3_POWER_OPREGION · 40 unmodified lines
41 This driver provides support for ACPI operation41 This driver provides support for ACPI operation
42 region of the Surface 3 battery platform driver.42 region of the Surface 3 battery platform driver.
43 43
44config SURFACE_ACPI_NOTIFY
45 tristate "Surface ACPI Notify Driver"
46 depends on SURFACE_AGGREGATOR
47 help
48 Surface ACPI Notify (SAN) driver for Microsoft Surface devices.
49
50 This driver provides support for the ACPI interface (called SAN) of
51 the Surface System Aggregator Module (SSAM) EC. This interface is used
52 on 5th- and 6th-generation Microsoft Surface devices (including
53 Surface Pro 5 and 6, Surface Book 2, Surface Laptops 1 and 2, and in
54 reduced functionality on the Surface Laptop 3) to execute SSAM
55 requests directly from ACPI code, as well as receive SSAM events and
56 turn them into ACPI notifications. It essentially acts as a
57 translation layer between the SSAM controller and ACPI.
58
59 Specifically, this driver may be needed for battery status reporting,
60 thermal sensor access, and real-time clock information, depending on
61 the Surface device in question.
62
63config SURFACE_AGGREGATOR_CDEV
64 tristate "Surface System Aggregator Module User-Space Interface"
65 depends on SURFACE_AGGREGATOR
66 help
67 Provides a misc-device interface to the Surface System Aggregator
68 Module (SSAM) controller.
69
70 This option provides a module (called surface_aggregator_cdev), that,
71 when loaded, will add a client device (and its respective driver) to
72 the SSAM controller. Said client device manages a misc-device
73 interface (/dev/surface/aggregator), which can be used by user-space
74 tools to directly communicate with the SSAM EC by sending requests and
75 receiving the corresponding responses.
76
77 The provided interface is intended for debugging and development only,
78 and should not be used otherwise.
79
44config SURFACE_GPE80config SURFACE_GPE
45 tristate "Surface GPE/Lid Support Driver"81 tristate "Surface GPE/Lid Support Driver"
46 depends on DMI82 depends on DMI
@@ -50,10 +86,31 @@ config SURFACE_GPE · 3 unmodified lines
50 accordingly. It is required on those devices to allow wake-ups from86 accordingly. It is required on those devices to allow wake-ups from
51 suspend by opening the lid.87 suspend by opening the lid.
52 88
89config SURFACE_HOTPLUG
90 tristate "Surface Hot-Plug Driver"
91 depends on GPIOLIB
92 help
93 Driver for out-of-band hot-plug event signaling on Microsoft Surface
94 devices with hot-pluggable PCIe cards.
95
96 This driver is used on Surface Book (2 and 3) devices with a
97 hot-pluggable discrete GPU (dGPU). When not in use, the dGPU on those
98 devices can enter D3cold, which prevents in-band (standard) PCIe
99 hot-plug signaling. Thus, without this driver, detaching the base
100 containing the dGPU will not correctly update the state of the
101 corresponding PCIe device if it is in D3cold. This driver adds support
102 for out-of-band hot-plug notifications, ensuring that the device state
103 is properly updated even when the device in question is in D3cold.
104
105 Select M or Y here, if you want to (fully) support hot-plugging of
106 dGPU devices on the Surface Book 2 and/or 3 during D3cold.
107
53config SURFACE_PRO3_BUTTON108config SURFACE_PRO3_BUTTON
54 tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet"109 tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet"
55 depends on INPUT110 depends on INPUT
56 help111 help
57 This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet.112 This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet.
58 113
114source "drivers/platform/surface/aggregator/Kconfig"
115
59endif # SURFACE_PLATFORMS116endif # SURFACE_PLATFORMS
drivers/platform/surface/Makefile+4−0
@@ -7,5 +7,9 @@ · 6 unmodified lines
7obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o7obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o
8obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o8obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
9obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o9obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
10obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
11obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
12obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
10obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o13obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
14obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o
11obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o15obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o
drivers/platform/surface/aggregator/Kconfig+68−0
@@ -0,0 +1,68 @@
1# SPDX-License-Identifier: GPL-2.0+
2# Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
3
4menuconfig SURFACE_AGGREGATOR
5 tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
6 depends on SERIAL_DEV_BUS
7 select CRC_CCITT
8 help
9 The Surface System Aggregator Module (Surface SAM or SSAM) is an
10 embedded controller (EC) found on 5th- and later-generation Microsoft
11 Surface devices (i.e. Surface Pro 5, Surface Book 2, Surface Laptop,
12 and newer, with exception of Surface Go series devices).
13
14 Depending on the device in question, this EC provides varying
15 functionality, including:
16 - EC access from ACPI via Surface ACPI Notify (5th- and 6th-generation)
17 - battery status information (all devices)
18 - thermal sensor access (all devices)
19 - performance mode / cooling mode control (all devices)
20 - clipboard detachment system control (Surface Book 2 and 3)
21 - HID / keyboard input (Surface Laptops, Surface Book 3)
22
23 This option controls whether the Surface SAM subsystem core will be
24 built. This includes a driver for the Surface Serial Hub (SSH), which
25 is the device responsible for the communication with the EC, and a
26 basic kernel interface exposing the EC functionality to other client
27 drivers, i.e. allowing them to make requests to the EC and receive
28 events from it. Selecting this option alone will not provide any
29 client drivers and therefore no functionality beyond the in-kernel
30 interface. Said functionality is the responsibility of the respective
31 client drivers.
32
33 Note: While 4th-generation Surface devices also make use of a SAM EC,
34 due to a difference in the communication interface of the controller,
35 only 5th and later generations are currently supported. Specifically,
36 devices using SAM-over-SSH are supported, whereas devices using
37 SAM-over-HID, which is used on the 4th generation, are currently not
38 supported.
39
40 Choose m if you want to build the SAM subsystem core and SSH driver as
41 module, y if you want to build it into the kernel and n if you don't
42 want it at all.
43
44config SURFACE_AGGREGATOR_BUS
45 bool "Surface System Aggregator Module Bus"
46 depends on SURFACE_AGGREGATOR
47 default y
48 help
49 Expands the Surface System Aggregator Module (SSAM) core driver by
50 providing a dedicated bus and client-device type.
51
52 This bus and device type are intended to provide and simplify support
53 for non-platform and non-ACPI SSAM devices, i.e. SSAM devices that are
54 not auto-detectable via the conventional means (e.g. ACPI).
55
56config SURFACE_AGGREGATOR_ERROR_INJECTION
57 bool "Surface System Aggregator Module Error Injection Capabilities"
58 depends on SURFACE_AGGREGATOR
59 depends on FUNCTION_ERROR_INJECTION
60 help
61 Provides error-injection capabilities for the Surface System
62 Aggregator Module subsystem and Surface Serial Hub driver.
63
64 Specifically, exports error injection hooks to be used with the
65 kernel's function error injection capabilities to simulate underlying
66 transport and communication problems, such as invalid data sent to or
67 received from the EC, dropped data, and communication timeouts.
68 Intended for development and debugging.
drivers/platform/surface/aggregator/Makefile+17−0
@@ -0,0 +1,17 @@
1# SPDX-License-Identifier: GPL-2.0+
2# Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
3
4# For include/trace/define_trace.h to include trace.h
5CFLAGS_core.o = -I$(src)
6
7obj-$(CONFIG_SURFACE_AGGREGATOR) += surface_aggregator.o
8
9surface_aggregator-objs := core.o
10surface_aggregator-objs += ssh_parser.o
11surface_aggregator-objs += ssh_packet_layer.o
12surface_aggregator-objs += ssh_request_layer.o
13surface_aggregator-objs += controller.o
14
15ifeq ($(CONFIG_SURFACE_AGGREGATOR_BUS),y)
16surface_aggregator-objs += bus.o
17endif
drivers/platform/surface/aggregator/bus.c+415−0
@@ -0,0 +1,415 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Surface System Aggregator Module bus and device integration.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#include <linux/device.h>
9#include <linux/slab.h>
10
11#include <linux/surface_aggregator/controller.h>
12#include <linux/surface_aggregator/device.h>
13
14#include "bus.h"
15#include "controller.h"
16
17static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
18 char *buf)
19{
20 struct ssam_device *sdev = to_ssam_device(dev);
21
22 return sysfs_emit(buf, "ssam:d%02Xc%02Xt%02Xi%02Xf%02X\n",
23 sdev->uid.domain, sdev->uid.category, sdev->uid.target,
24 sdev->uid.instance, sdev->uid.function);
25}
26static DEVICE_ATTR_RO(modalias);
27
28static struct attribute *ssam_device_attrs[] = {
29 &dev_attr_modalias.attr,
30 NULL,
31};
32ATTRIBUTE_GROUPS(ssam_device);
33
34static int ssam_device_uevent(struct device *dev, struct kobj_uevent_env *env)
35{
36 struct ssam_device *sdev = to_ssam_device(dev);
37
38 return add_uevent_var(env, "MODALIAS=ssam:d%02Xc%02Xt%02Xi%02Xf%02X",
39 sdev->uid.domain, sdev->uid.category,
40 sdev->uid.target, sdev->uid.instance,
41 sdev->uid.function);
42}
43
44static void ssam_device_release(struct device *dev)
45{
46 struct ssam_device *sdev = to_ssam_device(dev);
47
48 ssam_controller_put(sdev->ctrl);
49 kfree(sdev);
50}
51
52const struct device_type ssam_device_type = {
53 .name = "surface_aggregator_device",
54 .groups = ssam_device_groups,
55 .uevent = ssam_device_uevent,
56 .release = ssam_device_release,
57};
58EXPORT_SYMBOL_GPL(ssam_device_type);
59
60/**
61 * ssam_device_alloc() - Allocate and initialize a SSAM client device.
62 * @ctrl: The controller under which the device should be added.
63 * @uid: The UID of the device to be added.
64 *
65 * Allocates and initializes a new client device. The parent of the device
66 * will be set to the controller device and the name will be set based on the
67 * UID. Note that the device still has to be added via ssam_device_add().
68 * Refer to that function for more details.
69 *
70 * Return: Returns the newly allocated and initialized SSAM client device, or
71 * %NULL if it could not be allocated.
72 */
73struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
74 struct ssam_device_uid uid)
75{
76 struct ssam_device *sdev;
77
78 sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
79 if (!sdev)
80 return NULL;
81
82 device_initialize(&sdev->dev);
83 sdev->dev.bus = &ssam_bus_type;
84 sdev->dev.type = &ssam_device_type;
85 sdev->dev.parent = ssam_controller_device(ctrl);
86 sdev->ctrl = ssam_controller_get(ctrl);
87 sdev->uid = uid;
88
89 dev_set_name(&sdev->dev, "%02x:%02x:%02x:%02x:%02x",
90 sdev->uid.domain, sdev->uid.category, sdev->uid.target,
91 sdev->uid.instance, sdev->uid.function);
92
93 return sdev;
94}
95EXPORT_SYMBOL_GPL(ssam_device_alloc);
96
97/**
98 * ssam_device_add() - Add a SSAM client device.
99 * @sdev: The SSAM client device to be added.
100 *
101 * Added client devices must be guaranteed to always have a valid and active
102 * controller. Thus, this function will fail with %-ENODEV if the controller
103 * of the device has not been initialized yet, has been suspended, or has been
104 * shut down.
105 *
106 * The caller of this function should ensure that the corresponding call to
107 * ssam_device_remove() is issued before the controller is shut down. If the
108 * added device is a direct child of the controller device (default), it will
109 * be automatically removed when the controller is shut down.
110 *
111 * By default, the controller device will become the parent of the newly
112 * created client device. The parent may be changed before ssam_device_add is
113 * called, but care must be taken that a) the correct suspend/resume ordering
114 * is guaranteed and b) the client device does not outlive the controller,
115 * i.e. that the device is removed before the controller is being shut down.
116 * In case these guarantees have to be manually enforced, please refer to the
117 * ssam_client_link() and ssam_client_bind() functions, which are intended to
118 * set up device-links for this purpose.
119 *
120 * Return: Returns zero on success, a negative error code on failure.
121 */
122int ssam_device_add(struct ssam_device *sdev)
123{
124 int status;
125
126 /*
127 * Ensure that we can only add new devices to a controller if it has
128 * been started and is not going away soon. This works in combination
129 * with ssam_controller_remove_clients to ensure driver presence for the
130 * controller device, i.e. it ensures that the controller (sdev->ctrl)
131 * is always valid and can be used for requests as long as the client
132 * device we add here is registered as child under it. This essentially
133 * guarantees that the client driver can always expect the preconditions
134 * for functions like ssam_request_sync (controller has to be started
135 * and is not suspended) to hold and thus does not have to check for
136 * them.
137 *
138 * Note that for this to work, the controller has to be a parent device.
139 * If it is not a direct parent, care has to be taken that the device is
140 * removed via ssam_device_remove(), as device_unregister does not
141 * remove child devices recursively.
142 */
143 ssam_controller_statelock(sdev->ctrl);
144
145 if (sdev->ctrl->state != SSAM_CONTROLLER_STARTED) {
146 ssam_controller_stateunlock(sdev->ctrl);
147 return -ENODEV;
148 }
149
150 status = device_add(&sdev->dev);
151
152 ssam_controller_stateunlock(sdev->ctrl);
153 return status;
154}
155EXPORT_SYMBOL_GPL(ssam_device_add);
156
157/**
158 * ssam_device_remove() - Remove a SSAM client device.
159 * @sdev: The device to remove.
160 *
161 * Removes and unregisters the provided SSAM client device.
162 */
163void ssam_device_remove(struct ssam_device *sdev)
164{
165 device_unregister(&sdev->dev);
166}
167EXPORT_SYMBOL_GPL(ssam_device_remove);
168
169/**
170 * ssam_device_id_compatible() - Check if a device ID matches a UID.
171 * @id: The device ID as potential match.
172 * @uid: The device UID matching against.
173 *
174 * Check if the given ID is a match for the given UID, i.e. if a device with
175 * the provided UID is compatible to the given ID following the match rules
176 * described in its &ssam_device_id.match_flags member.
177 *
178 * Return: Returns %true if the given UID is compatible to the match rule
179 * described by the given ID, %false otherwise.
180 */
181static bool ssam_device_id_compatible(const struct ssam_device_id *id,
182 struct ssam_device_uid uid)
183{
184 if (id->domain != uid.domain || id->category != uid.category)
185 return false;
186
187 if ((id->match_flags & SSAM_MATCH_TARGET) && id->target != uid.target)
188 return false;
189
190 if ((id->match_flags & SSAM_MATCH_INSTANCE) && id->instance != uid.instance)
191 return false;
192
193 if ((id->match_flags & SSAM_MATCH_FUNCTION) && id->function != uid.function)
194 return false;
195
196 return true;
197}
198
199/**
200 * ssam_device_id_is_null() - Check if a device ID is null.
201 * @id: The device ID to check.
202 *
203 * Check if a given device ID is null, i.e. all zeros. Used to check for the
204 * end of ``MODULE_DEVICE_TABLE(ssam, ...)`` or similar lists.
205 *
206 * Return: Returns %true if the given ID represents a null ID, %false
207 * otherwise.
208 */
209static bool ssam_device_id_is_null(const struct ssam_device_id *id)
210{
211 return id->match_flags == 0 &&
212 id->domain == 0 &&
213 id->category == 0 &&
214 id->target == 0 &&
215 id->instance == 0 &&
216 id->function == 0 &&
217 id->driver_data == 0;
218}
219
220/**
221 * ssam_device_id_match() - Find the matching ID table entry for the given UID.
222 * @table: The table to search in.
223 * @uid: The UID to matched against the individual table entries.
224 *
225 * Find the first match for the provided device UID in the provided ID table
226 * and return it. Returns %NULL if no match could be found.
227 */
228const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
229 const struct ssam_device_uid uid)
230{
231 const struct ssam_device_id *id;
232
233 for (id = table; !ssam_device_id_is_null(id); ++id)
234 if (ssam_device_id_compatible(id, uid))
235 return id;
236
237 return NULL;
238}
239EXPORT_SYMBOL_GPL(ssam_device_id_match);
240
241/**
242 * ssam_device_get_match() - Find and return the ID matching the device in the
243 * ID table of the bound driver.
244 * @dev: The device for which to get the matching ID table entry.
245 *
246 * Find the fist match for the UID of the device in the ID table of the
247 * currently bound driver and return it. Returns %NULL if the device does not
248 * have a driver bound to it, the driver does not have match_table (i.e. it is
249 * %NULL), or there is no match in the driver's match_table.
250 *
251 * This function essentially calls ssam_device_id_match() with the ID table of
252 * the bound device driver and the UID of the device.
253 *
254 * Return: Returns the first match for the UID of the device in the device
255 * driver's match table, or %NULL if no such match could be found.
256 */
257const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev)
258{
259 const struct ssam_device_driver *sdrv;
260
261 sdrv = to_ssam_device_driver(dev->dev.driver);
262 if (!sdrv)
263 return NULL;
264
265 if (!sdrv->match_table)
266 return NULL;
267
268 return ssam_device_id_match(sdrv->match_table, dev->uid);
269}
270EXPORT_SYMBOL_GPL(ssam_device_get_match);
271
272/**
273 * ssam_device_get_match_data() - Find the ID matching the device in the
274 * ID table of the bound driver and return its ``driver_data`` member.
275 * @dev: The device for which to get the match data.
276 *
277 * Find the fist match for the UID of the device in the ID table of the
278 * corresponding driver and return its driver_data. Returns %NULL if the
279 * device does not have a driver bound to it, the driver does not have
280 * match_table (i.e. it is %NULL), there is no match in the driver's
281 * match_table, or the match does not have any driver_data.
282 *
283 * This function essentially calls ssam_device_get_match() and, if any match
284 * could be found, returns its ``struct ssam_device_id.driver_data`` member.
285 *
286 * Return: Returns the driver data associated with the first match for the UID
287 * of the device in the device driver's match table, or %NULL if no such match
288 * could be found.
289 */
290const void *ssam_device_get_match_data(const struct ssam_device *dev)
291{
292 const struct ssam_device_id *id;
293
294 id = ssam_device_get_match(dev);
295 if (!id)
296 return NULL;
297
298 return (const void *)id->driver_data;
299}
300EXPORT_SYMBOL_GPL(ssam_device_get_match_data);
301
302static int ssam_bus_match(struct device *dev, struct device_driver *drv)
303{
304 struct ssam_device_driver *sdrv = to_ssam_device_driver(drv);
305 struct ssam_device *sdev = to_ssam_device(dev);
306
307 if (!is_ssam_device(dev))
308 return 0;
309
310 return !!ssam_device_id_match(sdrv->match_table, sdev->uid);
311}
312
313static int ssam_bus_probe(struct device *dev)
314{
315 return to_ssam_device_driver(dev->driver)
316 ->probe(to_ssam_device(dev));
317}
318
319static int ssam_bus_remove(struct device *dev)
320{
321 struct ssam_device_driver *sdrv = to_ssam_device_driver(dev->driver);
322
323 if (sdrv->remove)
324 sdrv->remove(to_ssam_device(dev));
325
326 return 0;
327}
328
329struct bus_type ssam_bus_type = {
330 .name = "surface_aggregator",
331 .match = ssam_bus_match,
332 .probe = ssam_bus_probe,
333 .remove = ssam_bus_remove,
334};
335EXPORT_SYMBOL_GPL(ssam_bus_type);
336
337/**
338 * __ssam_device_driver_register() - Register a SSAM client device driver.
339 * @sdrv: The driver to register.
340 * @owner: The module owning the provided driver.
341 *
342 * Please refer to the ssam_device_driver_register() macro for the normal way
343 * to register a driver from inside its owning module.
344 */
345int __ssam_device_driver_register(struct ssam_device_driver *sdrv,
346 struct module *owner)
347{
348 sdrv->driver.owner = owner;
349 sdrv->driver.bus = &ssam_bus_type;
350
351 /* force drivers to async probe so I/O is possible in probe */
352 sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS;
353
354 return driver_register(&sdrv->driver);
355}
356EXPORT_SYMBOL_GPL(__ssam_device_driver_register);
357
358/**
359 * ssam_device_driver_unregister - Unregister a SSAM device driver.
360 * @sdrv: The driver to unregister.
361 */
362void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
363{
364 driver_unregister(&sdrv->driver);
365}
366EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
367
368static int ssam_remove_device(struct device *dev, void *_data)
369{
370 struct ssam_device *sdev = to_ssam_device(dev);
371
372 if (is_ssam_device(dev))
373 ssam_device_remove(sdev);
374
375 return 0;
376}
377
378/**
379 * ssam_controller_remove_clients() - Remove SSAM client devices registered as
380 * direct children under the given controller.
381 * @ctrl: The controller to remove all direct clients for.
382 *
383 * Remove all SSAM client devices registered as direct children under the
384 * given controller. Note that this only accounts for direct children of the
385 * controller device. This does not take care of any client devices where the
386 * parent device has been manually set before calling ssam_device_add. Refer
387 * to ssam_device_add()/ssam_device_remove() for more details on those cases.
388 *
389 * To avoid new devices being added in parallel to this call, the main
390 * controller lock (not statelock) must be held during this (and if
391 * necessary, any subsequent deinitialization) call.
392 */
393void ssam_controller_remove_clients(struct ssam_controller *ctrl)
394{
395 struct device *dev;
396
397 dev = ssam_controller_device(ctrl);
398 device_for_each_child_reverse(dev, NULL, ssam_remove_device);
399}
400
401/**
402 * ssam_bus_register() - Register and set-up the SSAM client device bus.
403 */
404int ssam_bus_register(void)
405{
406 return bus_register(&ssam_bus_type);
407}
408
409/**
410 * ssam_bus_unregister() - Unregister the SSAM client device bus.
411 */
412void ssam_bus_unregister(void)
413{
414 return bus_unregister(&ssam_bus_type);
415}
drivers/platform/surface/aggregator/bus.h+27−0
@@ -0,0 +1,27 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Surface System Aggregator Module bus and device integration.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_BUS_H
9#define _SURFACE_AGGREGATOR_BUS_H
10
11#include <linux/surface_aggregator/controller.h>
12
13#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
14
15void ssam_controller_remove_clients(struct ssam_controller *ctrl);
16
17int ssam_bus_register(void);
18void ssam_bus_unregister(void);
19
20#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
21
22static inline void ssam_controller_remove_clients(struct ssam_controller *ctrl) {}
23static inline int ssam_bus_register(void) { return 0; }
24static inline void ssam_bus_unregister(void) {}
25
26#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
27#endif /* _SURFACE_AGGREGATOR_BUS_H */
drivers/platform/surface/aggregator/controller.c+2579−0
@@ -0,0 +1,2579 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Main SSAM/SSH controller structure and functionality.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#include <linux/acpi.h>
9#include <linux/atomic.h>
10#include <linux/completion.h>
11#include <linux/gpio/consumer.h>
12#include <linux/interrupt.h>
13#include <linux/kref.h>
14#include <linux/limits.h>
15#include <linux/list.h>
16#include <linux/lockdep.h>
17#include <linux/mutex.h>
18#include <linux/rculist.h>
19#include <linux/rbtree.h>
20#include <linux/rwsem.h>
21#include <linux/serdev.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/srcu.h>
25#include <linux/types.h>
26#include <linux/workqueue.h>
27
28#include <linux/surface_aggregator/controller.h>
29#include <linux/surface_aggregator/serial_hub.h>
30
31#include "controller.h"
32#include "ssh_msgb.h"
33#include "ssh_request_layer.h"
34
35#include "trace.h"
36
37
38/* -- Safe counters. -------------------------------------------------------- */
39
40/**
41 * ssh_seq_reset() - Reset/initialize sequence ID counter.
42 * @c: The counter to reset.
43 */
44static void ssh_seq_reset(struct ssh_seq_counter *c)
45{
46 WRITE_ONCE(c->value, 0);
47}
48
49/**
50 * ssh_seq_next() - Get next sequence ID.
51 * @c: The counter providing the sequence IDs.
52 *
53 * Return: Returns the next sequence ID of the counter.
54 */
55static u8 ssh_seq_next(struct ssh_seq_counter *c)
56{
57 u8 old = READ_ONCE(c->value);
58 u8 new = old + 1;
59 u8 ret;
60
61 while (unlikely((ret = cmpxchg(&c->value, old, new)) != old)) {
62 old = ret;
63 new = old + 1;
64 }
65
66 return old;
67}
68
69/**
70 * ssh_rqid_reset() - Reset/initialize request ID counter.
71 * @c: The counter to reset.
72 */
73static void ssh_rqid_reset(struct ssh_rqid_counter *c)
74{
75 WRITE_ONCE(c->value, 0);
76}
77
78/**
79 * ssh_rqid_next() - Get next request ID.
80 * @c: The counter providing the request IDs.
81 *
82 * Return: Returns the next request ID of the counter, skipping any reserved
83 * request IDs.
84 */
85static u16 ssh_rqid_next(struct ssh_rqid_counter *c)
86{
87 u16 old = READ_ONCE(c->value);
88 u16 new = ssh_rqid_next_valid(old);
89 u16 ret;
90
91 while (unlikely((ret = cmpxchg(&c->value, old, new)) != old)) {
92 old = ret;
93 new = ssh_rqid_next_valid(old);
94 }
95
96 return old;
97}
98
99
100/* -- Event notifier/callbacks. --------------------------------------------- */
101/*
102 * The notifier system is based on linux/notifier.h, specifically the SRCU
103 * implementation. The difference to that is, that some bits of the notifier
104 * call return value can be tracked across multiple calls. This is done so
105 * that handling of events can be tracked and a warning can be issued in case
106 * an event goes unhandled. The idea of that warning is that it should help
107 * discover and identify new/currently unimplemented features.
108 */
109
110/**
111 * ssam_event_matches_notifier() - Test if an event matches a notifier.
112 * @n: The event notifier to test against.
113 * @event: The event to test.
114 *
115 * Return: Returns %true if the given event matches the given notifier
116 * according to the rules set in the notifier's event mask, %false otherwise.
117 */
118static bool ssam_event_matches_notifier(const struct ssam_event_notifier *n,
119 const struct ssam_event *event)
120{
121 bool match = n->event.id.target_category == event->target_category;
122
123 if (n->event.mask & SSAM_EVENT_MASK_TARGET)
124 match &= n->event.reg.target_id == event->target_id;
125
126 if (n->event.mask & SSAM_EVENT_MASK_INSTANCE)
127 match &= n->event.id.instance == event->instance_id;
128
129 return match;
130}
131
132/**
133 * ssam_nfblk_call_chain() - Call event notifier callbacks of the given chain.
134 * @nh: The notifier head for which the notifier callbacks should be called.
135 * @event: The event data provided to the callbacks.
136 *
137 * Call all registered notifier callbacks in order of their priority until
138 * either no notifier is left or a notifier returns a value with the
139 * %SSAM_NOTIF_STOP bit set. Note that this bit is automatically set via
140 * ssam_notifier_from_errno() on any non-zero error value.
141 *
142 * Return: Returns the notifier status value, which contains the notifier
143 * status bits (%SSAM_NOTIF_HANDLED and %SSAM_NOTIF_STOP) as well as a
144 * potential error value returned from the last executed notifier callback.
145 * Use ssam_notifier_to_errno() to convert this value to the original error
146 * value.
147 */
148static int ssam_nfblk_call_chain(struct ssam_nf_head *nh, struct ssam_event *event)
149{
150 struct ssam_event_notifier *nf;
151 int ret = 0, idx;
152
153 idx = srcu_read_lock(&nh->srcu);
154
155 list_for_each_entry_rcu(nf, &nh->head, base.node,
156 srcu_read_lock_held(&nh->srcu)) {
157 if (ssam_event_matches_notifier(nf, event)) {
158 ret = (ret & SSAM_NOTIF_STATE_MASK) | nf->base.fn(nf, event);
159 if (ret & SSAM_NOTIF_STOP)
160 break;
161 }
162 }
163
164 srcu_read_unlock(&nh->srcu, idx);
165 return ret;
166}
167
168/**
169 * ssam_nfblk_insert() - Insert a new notifier block into the given notifier
170 * list.
171 * @nh: The notifier head into which the block should be inserted.
172 * @nb: The notifier block to add.
173 *
174 * Note: This function must be synchronized by the caller with respect to other
175 * insert, find, and/or remove calls by holding ``struct ssam_nf.lock``.
176 *
177 * Return: Returns zero on success, %-EEXIST if the notifier block has already
178 * been registered.
179 */
180static int ssam_nfblk_insert(struct ssam_nf_head *nh, struct ssam_notifier_block *nb)
181{
182 struct ssam_notifier_block *p;
183 struct list_head *h;
184
185 /* Runs under lock, no need for RCU variant. */
186 list_for_each(h, &nh->head) {
187 p = list_entry(h, struct ssam_notifier_block, node);
188
189 if (unlikely(p == nb)) {
190 WARN(1, "double register detected");
191 return -EEXIST;
192 }
193
194 if (nb->priority > p->priority)
195 break;
196 }
197
198 list_add_tail_rcu(&nb->node, h);
199 return 0;
200}
201
202/**
203 * ssam_nfblk_find() - Check if a notifier block is registered on the given
204 * notifier head.
205 * list.
206 * @nh: The notifier head on which to search.
207 * @nb: The notifier block to search for.
208 *
209 * Note: This function must be synchronized by the caller with respect to other
210 * insert, find, and/or remove calls by holding ``struct ssam_nf.lock``.
211 *
212 * Return: Returns true if the given notifier block is registered on the given
213 * notifier head, false otherwise.
214 */
215static bool ssam_nfblk_find(struct ssam_nf_head *nh, struct ssam_notifier_block *nb)
216{
217 struct ssam_notifier_block *p;
218
219 /* Runs under lock, no need for RCU variant. */
220 list_for_each_entry(p, &nh->head, node) {
221 if (p == nb)
222 return true;
223 }
224
225 return false;
226}
227
228/**
229 * ssam_nfblk_remove() - Remove a notifier block from its notifier list.
230 * @nb: The notifier block to be removed.
231 *
232 * Note: This function must be synchronized by the caller with respect to
233 * other insert, find, and/or remove calls by holding ``struct ssam_nf.lock``.
234 * Furthermore, the caller _must_ ensure SRCU synchronization by calling
235 * synchronize_srcu() with ``nh->srcu`` after leaving the critical section, to
236 * ensure that the removed notifier block is not in use any more.
237 */
238static void ssam_nfblk_remove(struct ssam_notifier_block *nb)
239{
240 list_del_rcu(&nb->node);
241}
242
243/**
244 * ssam_nf_head_init() - Initialize the given notifier head.
245 * @nh: The notifier head to initialize.
246 */
247static int ssam_nf_head_init(struct ssam_nf_head *nh)
248{
249 int status;
250
251 status = init_srcu_struct(&nh->srcu);
252 if (status)
253 return status;
254
255 INIT_LIST_HEAD(&nh->head);
256 return 0;
257}
258
259/**
260 * ssam_nf_head_destroy() - Deinitialize the given notifier head.
261 * @nh: The notifier head to deinitialize.
262 */
263static void ssam_nf_head_destroy(struct ssam_nf_head *nh)
264{
265 cleanup_srcu_struct(&nh->srcu);
266}
267
268
269/* -- Event/notification registry. ------------------------------------------ */
270
271/**
272 * struct ssam_nf_refcount_key - Key used for event activation reference
273 * counting.
274 * @reg: The registry via which the event is enabled/disabled.
275 * @id: The ID uniquely describing the event.
276 */
277struct ssam_nf_refcount_key {
278 struct ssam_event_registry reg;
279 struct ssam_event_id id;
280};
281
282/**
283 * struct ssam_nf_refcount_entry - RB-tree entry for reference counting event
284 * activations.
285 * @node: The node of this entry in the rb-tree.
286 * @key: The key of the event.
287 * @refcount: The reference-count of the event.
288 * @flags: The flags used when enabling the event.
289 */
290struct ssam_nf_refcount_entry {
291 struct rb_node node;
292 struct ssam_nf_refcount_key key;
293 int refcount;
294 u8 flags;
295};
296
297/**
298 * ssam_nf_refcount_inc() - Increment reference-/activation-count of the given
299 * event.
300 * @nf: The notifier system reference.
301 * @reg: The registry used to enable/disable the event.
302 * @id: The event ID.
303 *
304 * Increments the reference-/activation-count associated with the specified
305 * event type/ID, allocating a new entry for this event ID if necessary. A
306 * newly allocated entry will have a refcount of one.
307 *
308 * Note: ``nf->lock`` must be held when calling this function.
309 *
310 * Return: Returns the refcount entry on success. Returns an error pointer
311 * with %-ENOSPC if there have already been %INT_MAX events of the specified
312 * ID and type registered, or %-ENOMEM if the entry could not be allocated.
313 */
314static struct ssam_nf_refcount_entry *
315ssam_nf_refcount_inc(struct ssam_nf *nf, struct ssam_event_registry reg,
316 struct ssam_event_id id)
317{
318 struct ssam_nf_refcount_entry *entry;
319 struct ssam_nf_refcount_key key;
320 struct rb_node **link = &nf->refcount.rb_node;
321 struct rb_node *parent = NULL;
322 int cmp;
323
324 lockdep_assert_held(&nf->lock);
325
326 key.reg = reg;
327 key.id = id;
328
329 while (*link) {
330 entry = rb_entry(*link, struct ssam_nf_refcount_entry, node);
331 parent = *link;
332
333 cmp = memcmp(&key, &entry->key, sizeof(key));
334 if (cmp < 0) {
335 link = &(*link)->rb_left;
336 } else if (cmp > 0) {
337 link = &(*link)->rb_right;
338 } else if (entry->refcount < INT_MAX) {
339 entry->refcount++;
340 return entry;
341 } else {
342 WARN_ON(1);
343 return ERR_PTR(-ENOSPC);
344 }
345 }
346
347 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
348 if (!entry)
349 return ERR_PTR(-ENOMEM);
350
351 entry->key = key;
352 entry->refcount = 1;
353
354 rb_link_node(&entry->node, parent, link);
355 rb_insert_color(&entry->node, &nf->refcount);
356
357 return entry;
358}
359
360/**
361 * ssam_nf_refcount_dec() - Decrement reference-/activation-count of the given
362 * event.
363 * @nf: The notifier system reference.
364 * @reg: The registry used to enable/disable the event.
365 * @id: The event ID.
366 *
367 * Decrements the reference-/activation-count of the specified event,
368 * returning its entry. If the returned entry has a refcount of zero, the
369 * caller is responsible for freeing it using kfree().
370 *
371 * Note: ``nf->lock`` must be held when calling this function.
372 *
373 * Return: Returns the refcount entry on success or %NULL if the entry has not
374 * been found.
375 */
376static struct ssam_nf_refcount_entry *
377ssam_nf_refcount_dec(struct ssam_nf *nf, struct ssam_event_registry reg,
378 struct ssam_event_id id)
379{
380 struct ssam_nf_refcount_entry *entry;
381 struct ssam_nf_refcount_key key;
382 struct rb_node *node = nf->refcount.rb_node;
383 int cmp;
384
385 lockdep_assert_held(&nf->lock);
386
387 key.reg = reg;
388 key.id = id;
389
390 while (node) {
391 entry = rb_entry(node, struct ssam_nf_refcount_entry, node);
392
393 cmp = memcmp(&key, &entry->key, sizeof(key));
394 if (cmp < 0) {
395 node = node->rb_left;
396 } else if (cmp > 0) {
397 node = node->rb_right;
398 } else {
399 entry->refcount--;
400 if (entry->refcount == 0)
401 rb_erase(&entry->node, &nf->refcount);
402
403 return entry;
404 }
405 }
406
407 return NULL;
408}
409
410/**
411 * ssam_nf_refcount_empty() - Test if the notification system has any
412 * enabled/active events.
413 * @nf: The notification system.
414 */
415static bool ssam_nf_refcount_empty(struct ssam_nf *nf)
416{
417 return RB_EMPTY_ROOT(&nf->refcount);
418}
419
420/**
421 * ssam_nf_call() - Call notification callbacks for the provided event.
422 * @nf: The notifier system
423 * @dev: The associated device, only used for logging.
424 * @rqid: The request ID of the event.
425 * @event: The event provided to the callbacks.
426 *
427 * Execute registered callbacks in order of their priority until either no
428 * callback is left or a callback returns a value with the %SSAM_NOTIF_STOP
429 * bit set. Note that this bit is set automatically when converting non-zero
430 * error values via ssam_notifier_from_errno() to notifier values.
431 *
432 * Also note that any callback that could handle an event should return a value
433 * with bit %SSAM_NOTIF_HANDLED set, indicating that the event does not go
434 * unhandled/ignored. In case no registered callback could handle an event,
435 * this function will emit a warning.
436 *
437 * In case a callback failed, this function will emit an error message.
438 */
439static void ssam_nf_call(struct ssam_nf *nf, struct device *dev, u16 rqid,
440 struct ssam_event *event)
441{
442 struct ssam_nf_head *nf_head;
443 int status, nf_ret;
444
445 if (!ssh_rqid_is_event(rqid)) {
446 dev_warn(dev, "event: unsupported rqid: %#06x\n", rqid);
447 return;
448 }
449
450 nf_head = &nf->head[ssh_rqid_to_event(rqid)];
451 nf_ret = ssam_nfblk_call_chain(nf_head, event);
452 status = ssam_notifier_to_errno(nf_ret);
453
454 if (status < 0) {
455 dev_err(dev,
456 "event: error handling event: %d (tc: %#04x, tid: %#04x, cid: %#04x, iid: %#04x)\n",
457 status, event->target_category, event->target_id,
458 event->command_id, event->instance_id);
459 } else if (!(nf_ret & SSAM_NOTIF_HANDLED)) {
460 dev_warn(dev,
461 "event: unhandled event (rqid: %#04x, tc: %#04x, tid: %#04x, cid: %#04x, iid: %#04x)\n",
462 rqid, event->target_category, event->target_id,
463 event->command_id, event->instance_id);
464 }
465}
466
467/**
468 * ssam_nf_init() - Initialize the notifier system.
469 * @nf: The notifier system to initialize.
470 */
471static int ssam_nf_init(struct ssam_nf *nf)
472{
473 int i, status;
474
475 for (i = 0; i < SSH_NUM_EVENTS; i++) {
476 status = ssam_nf_head_init(&nf->head[i]);
477 if (status)
478 break;
479 }
480
481 if (status) {
482 while (i--)
483 ssam_nf_head_destroy(&nf->head[i]);
484
485 return status;
486 }
487
488 mutex_init(&nf->lock);
489 return 0;
490}
491
492/**
493 * ssam_nf_destroy() - Deinitialize the notifier system.
494 * @nf: The notifier system to deinitialize.
495 */
496static void ssam_nf_destroy(struct ssam_nf *nf)
497{
498 int i;
499
500 for (i = 0; i < SSH_NUM_EVENTS; i++)
501 ssam_nf_head_destroy(&nf->head[i]);
502
503 mutex_destroy(&nf->lock);
504}
505
506
507/* -- Event/async request completion system. -------------------------------- */
508
509#define SSAM_CPLT_WQ_NAME "ssam_cpltq"
510
511/*
512 * SSAM_CPLT_WQ_BATCH - Maximum number of event item completions executed per
513 * work execution. Used to prevent livelocking of the workqueue. Value chosen
514 * via educated guess, may be adjusted.
515 */
516#define SSAM_CPLT_WQ_BATCH 10
517
518/*
519 * SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN - Maximum payload length for a cached
520 * &struct ssam_event_item.
521 *
522 * This length has been chosen to be accommodate standard touchpad and
523 * keyboard input events. Events with larger payloads will be allocated
524 * separately.
525 */
526#define SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN 32
527
528static struct kmem_cache *ssam_event_item_cache;
529
530/**
531 * ssam_event_item_cache_init() - Initialize the event item cache.
532 */
533int ssam_event_item_cache_init(void)
534{
535 const unsigned int size = sizeof(struct ssam_event_item)
536 + SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN;
537 const unsigned int align = __alignof__(struct ssam_event_item);
538 struct kmem_cache *cache;
539
540 cache = kmem_cache_create("ssam_event_item", size, align, 0, NULL);
541 if (!cache)
542 return -ENOMEM;
543
544 ssam_event_item_cache = cache;
545 return 0;
546}
547
548/**
549 * ssam_event_item_cache_destroy() - Deinitialize the event item cache.
550 */
551void ssam_event_item_cache_destroy(void)
552{
553 kmem_cache_destroy(ssam_event_item_cache);
554 ssam_event_item_cache = NULL;
555}
556
557static void __ssam_event_item_free_cached(struct ssam_event_item *item)
558{
559 kmem_cache_free(ssam_event_item_cache, item);
560}
561
562static void __ssam_event_item_free_generic(struct ssam_event_item *item)
563{
564 kfree(item);
565}
566
567/**
568 * ssam_event_item_free() - Free the provided event item.
569 * @item: The event item to free.
570 */
571static void ssam_event_item_free(struct ssam_event_item *item)
572{
573 trace_ssam_event_item_free(item);
574 item->ops.free(item);
575}
576
577/**
578 * ssam_event_item_alloc() - Allocate an event item with the given payload size.
579 * @len: The event payload length.
580 * @flags: The flags used for allocation.
581 *
582 * Allocate an event item with the given payload size, preferring allocation
583 * from the event item cache if the payload is small enough (i.e. smaller than
584 * %SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN). Sets the item operations and payload
585 * length values. The item free callback (``ops.free``) should not be
586 * overwritten after this call.
587 *
588 * Return: Returns the newly allocated event item.
589 */
590static struct ssam_event_item *ssam_event_item_alloc(size_t len, gfp_t flags)
591{
592 struct ssam_event_item *item;
593
594 if (len <= SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN) {
595 item = kmem_cache_alloc(ssam_event_item_cache, flags);
596 if (!item)
597 return NULL;
598
599 item->ops.free = __ssam_event_item_free_cached;
600 } else {
601 item = kzalloc(struct_size(item, event.data, len), flags);
602 if (!item)
603 return NULL;
604
605 item->ops.free = __ssam_event_item_free_generic;
606 }
607
608 item->event.length = len;
609
610 trace_ssam_event_item_alloc(item, len);
611 return item;
612}
613
614/**
615 * ssam_event_queue_push() - Push an event item to the event queue.
616 * @q: The event queue.
617 * @item: The item to add.
618 */
619static void ssam_event_queue_push(struct ssam_event_queue *q,
620 struct ssam_event_item *item)
621{
622 spin_lock(&q->lock);
623 list_add_tail(&item->node, &q->head);
624 spin_unlock(&q->lock);
625}
626
627/**
628 * ssam_event_queue_pop() - Pop the next event item from the event queue.
629 * @q: The event queue.
630 *
631 * Returns and removes the next event item from the queue. Returns %NULL If
632 * there is no event item left.
633 */
634static struct ssam_event_item *ssam_event_queue_pop(struct ssam_event_queue *q)
635{
636 struct ssam_event_item *item;
637
638 spin_lock(&q->lock);
639 item = list_first_entry_or_null(&q->head, struct ssam_event_item, node);
640 if (item)
641 list_del(&item->node);
642 spin_unlock(&q->lock);
643
644 return item;
645}
646
647/**
648 * ssam_event_queue_is_empty() - Check if the event queue is empty.
649 * @q: The event queue.
650 */
651static bool ssam_event_queue_is_empty(struct ssam_event_queue *q)
652{
653 bool empty;
654
655 spin_lock(&q->lock);
656 empty = list_empty(&q->head);
657 spin_unlock(&q->lock);
658
659 return empty;
660}
661
662/**
663 * ssam_cplt_get_event_queue() - Get the event queue for the given parameters.
664 * @cplt: The completion system on which to look for the queue.
665 * @tid: The target ID of the queue.
666 * @rqid: The request ID representing the event ID for which to get the queue.
667 *
668 * Return: Returns the event queue corresponding to the event type described
669 * by the given parameters. If the request ID does not represent an event,
670 * this function returns %NULL. If the target ID is not supported, this
671 * function will fall back to the default target ID (``tid = 1``).
672 */
673static
674struct ssam_event_queue *ssam_cplt_get_event_queue(struct ssam_cplt *cplt,
675 u8 tid, u16 rqid)
676{
677 u16 event = ssh_rqid_to_event(rqid);
678 u16 tidx = ssh_tid_to_index(tid);
679
680 if (!ssh_rqid_is_event(rqid)) {
681 dev_err(cplt->dev, "event: unsupported request ID: %#06x\n", rqid);
682 return NULL;
683 }
684
685 if (!ssh_tid_is_valid(tid)) {
686 dev_warn(cplt->dev, "event: unsupported target ID: %u\n", tid);
687 tidx = 0;
688 }
689
690 return &cplt->event.target[tidx].queue[event];
691}
692
693/**
694 * ssam_cplt_submit() - Submit a work item to the completion system workqueue.
695 * @cplt: The completion system.
696 * @work: The work item to submit.
697 */
698static bool ssam_cplt_submit(struct ssam_cplt *cplt, struct work_struct *work)
699{
700 return queue_work(cplt->wq, work);
701}
702
703/**
704 * ssam_cplt_submit_event() - Submit an event to the completion system.
705 * @cplt: The completion system.
706 * @item: The event item to submit.
707 *
708 * Submits the event to the completion system by queuing it on the event item
709 * queue and queuing the respective event queue work item on the completion
710 * workqueue, which will eventually complete the event.
711 *
712 * Return: Returns zero on success, %-EINVAL if there is no event queue that
713 * can handle the given event item.
714 */
715static int ssam_cplt_submit_event(struct ssam_cplt *cplt,
716 struct ssam_event_item *item)
717{
718 struct ssam_event_queue *evq;
719
720 evq = ssam_cplt_get_event_queue(cplt, item->event.target_id, item->rqid);
721 if (!evq)
722 return -EINVAL;
723
724 ssam_event_queue_push(evq, item);
725 ssam_cplt_submit(cplt, &evq->work);
726 return 0;
727}
728
729/**
730 * ssam_cplt_flush() - Flush the completion system.
731 * @cplt: The completion system.
732 *
733 * Flush the completion system by waiting until all currently submitted work
734 * items have been completed.
735 *
736 * Note: This function does not guarantee that all events will have been
737 * handled once this call terminates. In case of a larger number of
738 * to-be-completed events, the event queue work function may re-schedule its
739 * work item, which this flush operation will ignore.
740 *
741 * This operation is only intended to, during normal operation prior to
742 * shutdown, try to complete most events and requests to get them out of the
743 * system while the system is still fully operational. It does not aim to
744 * provide any guarantee that all of them have been handled.
745 */
746static void ssam_cplt_flush(struct ssam_cplt *cplt)
747{
748 flush_workqueue(cplt->wq);
749}
750
751static void ssam_event_queue_work_fn(struct work_struct *work)
752{
753 struct ssam_event_queue *queue;
754 struct ssam_event_item *item;
755 struct ssam_nf *nf;
756 struct device *dev;
757 unsigned int iterations = SSAM_CPLT_WQ_BATCH;
758
759 queue = container_of(work, struct ssam_event_queue, work);
760 nf = &queue->cplt->event.notif;
761 dev = queue->cplt->dev;
762
763 /* Limit number of processed events to avoid livelocking. */
764 do {
765 item = ssam_event_queue_pop(queue);
766 if (!item)
767 return;
768
769 ssam_nf_call(nf, dev, item->rqid, &item->event);
770 ssam_event_item_free(item);
771 } while (--iterations);
772
773 if (!ssam_event_queue_is_empty(queue))
774 ssam_cplt_submit(queue->cplt, &queue->work);
775}
776
777/**
778 * ssam_event_queue_init() - Initialize an event queue.
779 * @cplt: The completion system on which the queue resides.
780 * @evq: The event queue to initialize.
781 */
782static void ssam_event_queue_init(struct ssam_cplt *cplt,
783 struct ssam_event_queue *evq)
784{
785 evq->cplt = cplt;
786 spin_lock_init(&evq->lock);
787 INIT_LIST_HEAD(&evq->head);
788 INIT_WORK(&evq->work, ssam_event_queue_work_fn);
789}
790
791/**
792 * ssam_cplt_init() - Initialize completion system.
793 * @cplt: The completion system to initialize.
794 * @dev: The device used for logging.
795 */
796static int ssam_cplt_init(struct ssam_cplt *cplt, struct device *dev)
797{
798 struct ssam_event_target *target;
799 int status, c, i;
800
801 cplt->dev = dev;
802
803 cplt->wq = create_workqueue(SSAM_CPLT_WQ_NAME);
804 if (!cplt->wq)
805 return -ENOMEM;
806
807 for (c = 0; c < ARRAY_SIZE(cplt->event.target); c++) {
808 target = &cplt->event.target[c];
809
810 for (i = 0; i < ARRAY_SIZE(target->queue); i++)
811 ssam_event_queue_init(cplt, &target->queue[i]);
812 }
813
814 status = ssam_nf_init(&cplt->event.notif);
815 if (status)
816 destroy_workqueue(cplt->wq);
817
818 return status;
819}
820
821/**
822 * ssam_cplt_destroy() - Deinitialize the completion system.
823 * @cplt: The completion system to deinitialize.
824 *
825 * Deinitialize the given completion system and ensure that all pending, i.e.
826 * yet-to-be-completed, event items and requests have been handled.
827 */
828static void ssam_cplt_destroy(struct ssam_cplt *cplt)
829{
830 /*
831 * Note: destroy_workqueue ensures that all currently queued work will
832 * be fully completed and the workqueue drained. This means that this
833 * call will inherently also free any queued ssam_event_items, thus we
834 * don't have to take care of that here explicitly.
835 */
836 destroy_workqueue(cplt->wq);
837 ssam_nf_destroy(&cplt->event.notif);
838}
839
840
841/* -- Main SSAM device structures. ------------------------------------------ */
842
843/**
844 * ssam_controller_device() - Get the &struct device associated with this
845 * controller.
846 * @c: The controller for which to get the device.
847 *
848 * Return: Returns the &struct device associated with this controller,
849 * providing its lower-level transport.
850 */
851struct device *ssam_controller_device(struct ssam_controller *c)
852{
853 return ssh_rtl_get_device(&c->rtl);
854}
855EXPORT_SYMBOL_GPL(ssam_controller_device);
856
857static void __ssam_controller_release(struct kref *kref)
858{
859 struct ssam_controller *ctrl = to_ssam_controller(kref, kref);
860
861 /*
862 * The lock-call here is to satisfy lockdep. At this point we really
863 * expect this to be the last remaining reference to the controller.
864 * Anything else is a bug.
865 */
866 ssam_controller_lock(ctrl);
867 ssam_controller_destroy(ctrl);
868 ssam_controller_unlock(ctrl);
869
870 kfree(ctrl);
871}
872
873/**
874 * ssam_controller_get() - Increment reference count of controller.
875 * @c: The controller.
876 *
877 * Return: Returns the controller provided as input.
878 */
879struct ssam_controller *ssam_controller_get(struct ssam_controller *c)
880{
881 if (c)
882 kref_get(&c->kref);
883 return c;
884}
885EXPORT_SYMBOL_GPL(ssam_controller_get);
886
887/**
888 * ssam_controller_put() - Decrement reference count of controller.
889 * @c: The controller.
890 */
891void ssam_controller_put(struct ssam_controller *c)
892{
893 if (c)
894 kref_put(&c->kref, __ssam_controller_release);
895}
896EXPORT_SYMBOL_GPL(ssam_controller_put);
897
898/**
899 * ssam_controller_statelock() - Lock the controller against state transitions.
900 * @c: The controller to lock.
901 *
902 * Lock the controller against state transitions. Holding this lock guarantees
903 * that the controller will not transition between states, i.e. if the
904 * controller is in state "started", when this lock has been acquired, it will
905 * remain in this state at least until the lock has been released.
906 *
907 * Multiple clients may concurrently hold this lock. In other words: The
908 * ``statelock`` functions represent the read-lock part of a r/w-semaphore.
909 * Actions causing state transitions of the controller must be executed while
910 * holding the write-part of this r/w-semaphore (see ssam_controller_lock()
911 * and ssam_controller_unlock() for that).
912 *
913 * See ssam_controller_stateunlock() for the corresponding unlock function.
914 */
915void ssam_controller_statelock(struct ssam_controller *c)
916{
917 down_read(&c->lock);
918}
919EXPORT_SYMBOL_GPL(ssam_controller_statelock);
920
921/**
922 * ssam_controller_stateunlock() - Unlock controller state transitions.
923 * @c: The controller to unlock.
924 *
925 * See ssam_controller_statelock() for the corresponding lock function.
926 */
927void ssam_controller_stateunlock(struct ssam_controller *c)
928{
929 up_read(&c->lock);
930}
931EXPORT_SYMBOL_GPL(ssam_controller_stateunlock);
932
933/**
934 * ssam_controller_lock() - Acquire the main controller lock.
935 * @c: The controller to lock.
936 *
937 * This lock must be held for any state transitions, including transition to
938 * suspend/resumed states and during shutdown. See ssam_controller_statelock()
939 * for more details on controller locking.
940 *
941 * See ssam_controller_unlock() for the corresponding unlock function.
942 */
943void ssam_controller_lock(struct ssam_controller *c)
944{
945 down_write(&c->lock);
946}
947
948/*
949 * ssam_controller_unlock() - Release the main controller lock.
950 * @c: The controller to unlock.
951 *
952 * See ssam_controller_lock() for the corresponding lock function.
953 */
954void ssam_controller_unlock(struct ssam_controller *c)
955{
956 up_write(&c->lock);
957}
958
959static void ssam_handle_event(struct ssh_rtl *rtl,
960 const struct ssh_command *cmd,
961 const struct ssam_span *data)
962{
963 struct ssam_controller *ctrl = to_ssam_controller(rtl, rtl);
964 struct ssam_event_item *item;
965
966 item = ssam_event_item_alloc(data->len, GFP_KERNEL);
967 if (!item)
968 return;
969
970 item->rqid = get_unaligned_le16(&cmd->rqid);
971 item->event.target_category = cmd->tc;
972 item->event.target_id = cmd->tid_in;
973 item->event.command_id = cmd->cid;
974 item->event.instance_id = cmd->iid;
975 memcpy(&item->event.data[0], data->ptr, data->len);
976
977 if (WARN_ON(ssam_cplt_submit_event(&ctrl->cplt, item)))
978 ssam_event_item_free(item);
979}
980
981static const struct ssh_rtl_ops ssam_rtl_ops = {
982 .handle_event = ssam_handle_event,
983};
984
985static bool ssam_notifier_is_empty(struct ssam_controller *ctrl);
986static void ssam_notifier_unregister_all(struct ssam_controller *ctrl);
987
988#define SSAM_SSH_DSM_REVISION 0
989
990/* d5e383e1-d892-4a76-89fc-f6aaae7ed5b5 */
991static const guid_t SSAM_SSH_DSM_GUID =
992 GUID_INIT(0xd5e383e1, 0xd892, 0x4a76,
993 0x89, 0xfc, 0xf6, 0xaa, 0xae, 0x7e, 0xd5, 0xb5);
994
995enum ssh_dsm_fn {
996 SSH_DSM_FN_SSH_POWER_PROFILE = 0x05,
997 SSH_DSM_FN_SCREEN_ON_SLEEP_IDLE_TIMEOUT = 0x06,
998 SSH_DSM_FN_SCREEN_OFF_SLEEP_IDLE_TIMEOUT = 0x07,
999 SSH_DSM_FN_D3_CLOSES_HANDLE = 0x08,
1000 SSH_DSM_FN_SSH_BUFFER_SIZE = 0x09,
1001};
1002
1003static int ssam_dsm_get_functions(acpi_handle handle, u64 *funcs)
1004{
1005 union acpi_object *obj;
1006 u64 mask = 0;
1007 int i;
1008
1009 *funcs = 0;
1010
1011 /*
1012 * The _DSM function is only present on newer models. It is not
1013 * present on 5th and 6th generation devices (i.e. up to and including
1014 * Surface Pro 6, Surface Laptop 2, Surface Book 2).
1015 *
1016 * If the _DSM is not present, indicate that no function is supported.
1017 * This will result in default values being set.
1018 */
1019 if (!acpi_has_method(handle, "_DSM"))
1020 return 0;
1021
1022 obj = acpi_evaluate_dsm_typed(handle, &SSAM_SSH_DSM_GUID,
1023 SSAM_SSH_DSM_REVISION, 0, NULL,
1024 ACPI_TYPE_BUFFER);
1025 if (!obj)
1026 return -EIO;
1027
1028 for (i = 0; i < obj->buffer.length && i < 8; i++)
1029 mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
1030
1031 if (mask & BIT(0))
1032 *funcs = mask;
1033
1034 ACPI_FREE(obj);
1035 return 0;
1036}
1037
1038static int ssam_dsm_load_u32(acpi_handle handle, u64 funcs, u64 func, u32 *ret)
1039{
1040 union acpi_object *obj;
1041 u64 val;
1042
1043 if (!(funcs & BIT(func)))
1044 return 0; /* Not supported, leave *ret at its default value */
1045
1046 obj = acpi_evaluate_dsm_typed(handle, &SSAM_SSH_DSM_GUID,
1047 SSAM_SSH_DSM_REVISION, func, NULL,
1048 ACPI_TYPE_INTEGER);
1049 if (!obj)
1050 return -EIO;
1051
1052 val = obj->integer.value;
1053 ACPI_FREE(obj);
1054
1055 if (val > U32_MAX)
1056 return -ERANGE;
1057
1058 *ret = val;
1059 return 0;
1060}
1061
1062/**
1063 * ssam_controller_caps_load_from_acpi() - Load controller capabilities from
1064 * ACPI _DSM.
1065 * @handle: The handle of the ACPI controller/SSH device.
1066 * @caps: Where to store the capabilities in.
1067 *
1068 * Initializes the given controller capabilities with default values, then
1069 * checks and, if the respective _DSM functions are available, loads the
1070 * actual capabilities from the _DSM.
1071 *
1072 * Return: Returns zero on success, a negative error code on failure.
1073 */
1074static
1075int ssam_controller_caps_load_from_acpi(acpi_handle handle,
1076 struct ssam_controller_caps *caps)
1077{
1078 u32 d3_closes_handle = false;
1079 u64 funcs;
1080 int status;
1081
1082 /* Set defaults. */
1083 caps->ssh_power_profile = U32_MAX;
1084 caps->screen_on_sleep_idle_timeout = U32_MAX;
1085 caps->screen_off_sleep_idle_timeout = U32_MAX;
1086 caps->d3_closes_handle = false;
1087 caps->ssh_buffer_size = U32_MAX;
1088
1089 /* Pre-load supported DSM functions. */
1090 status = ssam_dsm_get_functions(handle, &funcs);
1091 if (status)
1092 return status;
1093
1094 /* Load actual values from ACPI, if present. */
1095 status = ssam_dsm_load_u32(handle, funcs, SSH_DSM_FN_SSH_POWER_PROFILE,
1096 &caps->ssh_power_profile);
1097 if (status)
1098 return status;
1099
1100 status = ssam_dsm_load_u32(handle, funcs,
1101 SSH_DSM_FN_SCREEN_ON_SLEEP_IDLE_TIMEOUT,
1102 &caps->screen_on_sleep_idle_timeout);
1103 if (status)
1104 return status;
1105
1106 status = ssam_dsm_load_u32(handle, funcs,
1107 SSH_DSM_FN_SCREEN_OFF_SLEEP_IDLE_TIMEOUT,
1108 &caps->screen_off_sleep_idle_timeout);
1109 if (status)
1110 return status;
1111
1112 status = ssam_dsm_load_u32(handle, funcs, SSH_DSM_FN_D3_CLOSES_HANDLE,
1113 &d3_closes_handle);
1114 if (status)
1115 return status;
1116
1117 caps->d3_closes_handle = !!d3_closes_handle;
1118
1119 status = ssam_dsm_load_u32(handle, funcs, SSH_DSM_FN_SSH_BUFFER_SIZE,
1120 &caps->ssh_buffer_size);
1121 if (status)
1122 return status;
1123
1124 return 0;
1125}
1126
1127/**
1128 * ssam_controller_init() - Initialize SSAM controller.
1129 * @ctrl: The controller to initialize.
1130 * @serdev: The serial device representing the underlying data transport.
1131 *
1132 * Initializes the given controller. Does neither start receiver nor
1133 * transmitter threads. After this call, the controller has to be hooked up to
1134 * the serdev core separately via &struct serdev_device_ops, relaying calls to
1135 * ssam_controller_receive_buf() and ssam_controller_write_wakeup(). Once the
1136 * controller has been hooked up, transmitter and receiver threads may be
1137 * started via ssam_controller_start(). These setup steps need to be completed
1138 * before controller can be used for requests.
1139 */
1140int ssam_controller_init(struct ssam_controller *ctrl,
1141 struct serdev_device *serdev)
1142{
1143 acpi_handle handle = ACPI_HANDLE(&serdev->dev);
1144 int status;
1145
1146 init_rwsem(&ctrl->lock);
1147 kref_init(&ctrl->kref);
1148
1149 status = ssam_controller_caps_load_from_acpi(handle, &ctrl->caps);
1150 if (status)
1151 return status;
1152
1153 dev_dbg(&serdev->dev,
1154 "device capabilities:\n"
1155 " ssh_power_profile: %u\n"
1156 " ssh_buffer_size: %u\n"
1157 " screen_on_sleep_idle_timeout: %u\n"
1158 " screen_off_sleep_idle_timeout: %u\n"
1159 " d3_closes_handle: %u\n",
1160 ctrl->caps.ssh_power_profile,
1161 ctrl->caps.ssh_buffer_size,
1162 ctrl->caps.screen_on_sleep_idle_timeout,
1163 ctrl->caps.screen_off_sleep_idle_timeout,
1164 ctrl->caps.d3_closes_handle);
1165
1166 ssh_seq_reset(&ctrl->counter.seq);
1167 ssh_rqid_reset(&ctrl->counter.rqid);
1168
1169 /* Initialize event/request completion system. */
1170 status = ssam_cplt_init(&ctrl->cplt, &serdev->dev);
1171 if (status)
1172 return status;
1173
1174 /* Initialize request and packet transport layers. */
1175 status = ssh_rtl_init(&ctrl->rtl, serdev, &ssam_rtl_ops);
1176 if (status) {
1177 ssam_cplt_destroy(&ctrl->cplt);
1178 return status;
1179 }
1180
1181 /*
1182 * Set state via write_once even though we expect to be in an
1183 * exclusive context, due to smoke-testing in
1184 * ssam_request_sync_submit().
1185 */
1186 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_INITIALIZED);
1187 return 0;
1188}
1189
1190/**
1191 * ssam_controller_start() - Start the receiver and transmitter threads of the
1192 * controller.
1193 * @ctrl: The controller.
1194 *
1195 * Note: When this function is called, the controller should be properly
1196 * hooked up to the serdev core via &struct serdev_device_ops. Please refer
1197 * to ssam_controller_init() for more details on controller initialization.
1198 *
1199 * This function must be called with the main controller lock held (i.e. by
1200 * calling ssam_controller_lock()).
1201 */
1202int ssam_controller_start(struct ssam_controller *ctrl)
1203{
1204 int status;
1205
1206 lockdep_assert_held_write(&ctrl->lock);
1207
1208 if (ctrl->state != SSAM_CONTROLLER_INITIALIZED)
1209 return -EINVAL;
1210
1211 status = ssh_rtl_start(&ctrl->rtl);
1212 if (status)
1213 return status;
1214
1215 /*
1216 * Set state via write_once even though we expect to be locked/in an
1217 * exclusive context, due to smoke-testing in
1218 * ssam_request_sync_submit().
1219 */
1220 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STARTED);
1221 return 0;
1222}
1223
1224/*
1225 * SSAM_CTRL_SHUTDOWN_FLUSH_TIMEOUT - Timeout for flushing requests during
1226 * shutdown.
1227 *
1228 * Chosen to be larger than one full request timeout, including packets timing
1229 * out. This value should give ample time to complete any outstanding requests
1230 * during normal operation and account for the odd package timeout.
1231 */
1232#define SSAM_CTRL_SHUTDOWN_FLUSH_TIMEOUT msecs_to_jiffies(5000)
1233
1234/**
1235 * ssam_controller_shutdown() - Shut down the controller.
1236 * @ctrl: The controller.
1237 *
1238 * Shuts down the controller by flushing all pending requests and stopping the
1239 * transmitter and receiver threads. All requests submitted after this call
1240 * will fail with %-ESHUTDOWN. While it is discouraged to do so, this function
1241 * is safe to use in parallel with ongoing request submission.
1242 *
1243 * In the course of this shutdown procedure, all currently registered
1244 * notifiers will be unregistered. It is, however, strongly recommended to not
1245 * rely on this behavior, and instead the party registering the notifier
1246 * should unregister it before the controller gets shut down, e.g. via the
1247 * SSAM bus which guarantees client devices to be removed before a shutdown.
1248 *
1249 * Note that events may still be pending after this call, but, due to the
1250 * notifiers being unregistered, these events will be dropped when the
1251 * controller is subsequently destroyed via ssam_controller_destroy().
1252 *
1253 * This function must be called with the main controller lock held (i.e. by
1254 * calling ssam_controller_lock()).
1255 */
1256void ssam_controller_shutdown(struct ssam_controller *ctrl)
1257{
1258 enum ssam_controller_state s = ctrl->state;
1259 int status;
1260
1261 lockdep_assert_held_write(&ctrl->lock);
1262
1263 if (s == SSAM_CONTROLLER_UNINITIALIZED || s == SSAM_CONTROLLER_STOPPED)
1264 return;
1265
1266 /*
1267 * Try to flush pending events and requests while everything still
1268 * works. Note: There may still be packets and/or requests in the
1269 * system after this call (e.g. via control packets submitted by the
1270 * packet transport layer or flush timeout / failure, ...). Those will
1271 * be handled with the ssh_rtl_shutdown() call below.
1272 */
1273 status = ssh_rtl_flush(&ctrl->rtl, SSAM_CTRL_SHUTDOWN_FLUSH_TIMEOUT);
1274 if (status) {
1275 ssam_err(ctrl, "failed to flush request transport layer: %d\n",
1276 status);
1277 }
1278
1279 /* Try to flush all currently completing requests and events. */
1280 ssam_cplt_flush(&ctrl->cplt);
1281
1282 /*
1283 * We expect all notifiers to have been removed by the respective client
1284 * driver that set them up at this point. If this warning occurs, some
1285 * client driver has not done that...
1286 */
1287 WARN_ON(!ssam_notifier_is_empty(ctrl));
1288
1289 /*
1290 * Nevertheless, we should still take care of drivers that don't behave
1291 * well. Thus disable all enabled events, unregister all notifiers.
1292 */
1293 ssam_notifier_unregister_all(ctrl);
1294
1295 /*
1296 * Cancel remaining requests. Ensure no new ones can be queued and stop
1297 * threads.
1298 */
1299 ssh_rtl_shutdown(&ctrl->rtl);
1300
1301 /*
1302 * Set state via write_once even though we expect to be locked/in an
1303 * exclusive context, due to smoke-testing in
1304 * ssam_request_sync_submit().
1305 */
1306 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STOPPED);
1307 ctrl->rtl.ptl.serdev = NULL;
1308}
1309
1310/**
1311 * ssam_controller_destroy() - Destroy the controller and free its resources.
1312 * @ctrl: The controller.
1313 *
1314 * Ensures that all resources associated with the controller get freed. This
1315 * function should only be called after the controller has been stopped via
1316 * ssam_controller_shutdown(). In general, this function should not be called
1317 * directly. The only valid place to call this function directly is during
1318 * initialization, before the controller has been fully initialized and passed
1319 * to other processes. This function is called automatically when the
1320 * reference count of the controller reaches zero.
1321 *
1322 * This function must be called with the main controller lock held (i.e. by
1323 * calling ssam_controller_lock()).
1324 */
1325void ssam_controller_destroy(struct ssam_controller *ctrl)
1326{
1327 lockdep_assert_held_write(&ctrl->lock);
1328
1329 if (ctrl->state == SSAM_CONTROLLER_UNINITIALIZED)
1330 return;
1331
1332 WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED);
1333
1334 /*
1335 * Note: New events could still have been received after the previous
1336 * flush in ssam_controller_shutdown, before the request transport layer
1337 * has been shut down. At this point, after the shutdown, we can be sure
1338 * that no new events will be queued. The call to ssam_cplt_destroy will
1339 * ensure that those remaining are being completed and freed.
1340 */
1341
1342 /* Actually free resources. */
1343 ssam_cplt_destroy(&ctrl->cplt);
1344 ssh_rtl_destroy(&ctrl->rtl);
1345
1346 /*
1347 * Set state via write_once even though we expect to be locked/in an
1348 * exclusive context, due to smoke-testing in
1349 * ssam_request_sync_submit().
1350 */
1351 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_UNINITIALIZED);
1352}
1353
1354/**
1355 * ssam_controller_suspend() - Suspend the controller.
1356 * @ctrl: The controller to suspend.
1357 *
1358 * Marks the controller as suspended. Note that display-off and D0-exit
1359 * notifications have to be sent manually before transitioning the controller
1360 * into the suspended state via this function.
1361 *
1362 * See ssam_controller_resume() for the corresponding resume function.
1363 *
1364 * Return: Returns %-EINVAL if the controller is currently not in the
1365 * "started" state.
1366 */
1367int ssam_controller_suspend(struct ssam_controller *ctrl)
1368{
1369 ssam_controller_lock(ctrl);
1370
1371 if (ctrl->state != SSAM_CONTROLLER_STARTED) {
1372 ssam_controller_unlock(ctrl);
1373 return -EINVAL;
1374 }
1375
1376 ssam_dbg(ctrl, "pm: suspending controller\n");
1377
1378 /*
1379 * Set state via write_once even though we're locked, due to
1380 * smoke-testing in ssam_request_sync_submit().
1381 */
1382 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_SUSPENDED);
1383
1384 ssam_controller_unlock(ctrl);
1385 return 0;
1386}
1387
1388/**
1389 * ssam_controller_resume() - Resume the controller from suspend.
1390 * @ctrl: The controller to resume.
1391 *
1392 * Resume the controller from the suspended state it was put into via
1393 * ssam_controller_suspend(). This function does not issue display-on and
1394 * D0-entry notifications. If required, those have to be sent manually after
1395 * this call.
1396 *
1397 * Return: Returns %-EINVAL if the controller is currently not suspended.
1398 */
1399int ssam_controller_resume(struct ssam_controller *ctrl)
1400{
1401 ssam_controller_lock(ctrl);
1402
1403 if (ctrl->state != SSAM_CONTROLLER_SUSPENDED) {
1404 ssam_controller_unlock(ctrl);
1405 return -EINVAL;
1406 }
1407
1408 ssam_dbg(ctrl, "pm: resuming controller\n");
1409
1410 /*
1411 * Set state via write_once even though we're locked, due to
1412 * smoke-testing in ssam_request_sync_submit().
1413 */
1414 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STARTED);
1415
1416 ssam_controller_unlock(ctrl);
1417 return 0;
1418}
1419
1420
1421/* -- Top-level request interface ------------------------------------------- */
1422
1423/**
1424 * ssam_request_write_data() - Construct and write SAM request message to
1425 * buffer.
1426 * @buf: The buffer to write the data to.
1427 * @ctrl: The controller via which the request will be sent.
1428 * @spec: The request data and specification.
1429 *
1430 * Constructs a SAM/SSH request message and writes it to the provided buffer.
1431 * The request and transport counters, specifically RQID and SEQ, will be set
1432 * in this call. These counters are obtained from the controller. It is thus
1433 * only valid to send the resulting message via the controller specified here.
1434 *
1435 * For calculation of the required buffer size, refer to the
1436 * SSH_COMMAND_MESSAGE_LENGTH() macro.
1437 *
1438 * Return: Returns the number of bytes used in the buffer on success. Returns
1439 * %-EINVAL if the payload length provided in the request specification is too
1440 * large (larger than %SSH_COMMAND_MAX_PAYLOAD_SIZE) or if the provided buffer
1441 * is too small.
1442 */
1443ssize_t ssam_request_write_data(struct ssam_span *buf,
1444 struct ssam_controller *ctrl,
1445 const struct ssam_request *spec)
1446{
1447 struct msgbuf msgb;
1448 u16 rqid;
1449 u8 seq;
1450
1451 if (spec->length > SSH_COMMAND_MAX_PAYLOAD_SIZE)
1452 return -EINVAL;
1453
1454 if (SSH_COMMAND_MESSAGE_LENGTH(spec->length) > buf->len)
1455 return -EINVAL;
1456
1457 msgb_init(&msgb, buf->ptr, buf->len);
1458 seq = ssh_seq_next(&ctrl->counter.seq);
1459 rqid = ssh_rqid_next(&ctrl->counter.rqid);
1460 msgb_push_cmd(&msgb, seq, rqid, spec);
1461
1462 return msgb_bytes_used(&msgb);
1463}
1464EXPORT_SYMBOL_GPL(ssam_request_write_data);
1465
1466static void ssam_request_sync_complete(struct ssh_request *rqst,
1467 const struct ssh_command *cmd,
1468 const struct ssam_span *data, int status)
1469{
1470 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
1471 struct ssam_request_sync *r;
1472
1473 r = container_of(rqst, struct ssam_request_sync, base);
1474 r->status = status;
1475
1476 if (r->resp)
1477 r->resp->length = 0;
1478
1479 if (status) {
1480 rtl_dbg_cond(rtl, "rsp: request failed: %d\n", status);
1481 return;
1482 }
1483
1484 if (!data) /* Handle requests without a response. */
1485 return;
1486
1487 if (!r->resp || !r->resp->pointer) {
1488 if (data->len)
1489 rtl_warn(rtl, "rsp: no response buffer provided, dropping data\n");
1490 return;
1491 }
1492
1493 if (data->len > r->resp->capacity) {
1494 rtl_err(rtl,
1495 "rsp: response buffer too small, capacity: %zu bytes, got: %zu bytes\n",
1496 r->resp->capacity, data->len);
1497 r->status = -ENOSPC;
1498 return;
1499 }
1500
1501 r->resp->length = data->len;
1502 memcpy(r->resp->pointer, data->ptr, data->len);
1503}
1504
1505static void ssam_request_sync_release(struct ssh_request *rqst)
1506{
1507 complete_all(&container_of(rqst, struct ssam_request_sync, base)->comp);
1508}
1509
1510static const struct ssh_request_ops ssam_request_sync_ops = {
1511 .release = ssam_request_sync_release,
1512 .complete = ssam_request_sync_complete,
1513};
1514
1515/**
1516 * ssam_request_sync_alloc() - Allocate a synchronous request.
1517 * @payload_len: The length of the request payload.
1518 * @flags: Flags used for allocation.
1519 * @rqst: Where to store the pointer to the allocated request.
1520 * @buffer: Where to store the buffer descriptor for the message buffer of
1521 * the request.
1522 *
1523 * Allocates a synchronous request with corresponding message buffer. The
1524 * request still needs to be initialized ssam_request_sync_init() before
1525 * it can be submitted, and the message buffer data must still be set to the
1526 * returned buffer via ssam_request_sync_set_data() after it has been filled,
1527 * if need be with adjusted message length.
1528 *
1529 * After use, the request and its corresponding message buffer should be freed
1530 * via ssam_request_sync_free(). The buffer must not be freed separately.
1531 *
1532 * Return: Returns zero on success, %-ENOMEM if the request could not be
1533 * allocated.
1534 */
1535int ssam_request_sync_alloc(size_t payload_len, gfp_t flags,
1536 struct ssam_request_sync **rqst,
1537 struct ssam_span *buffer)
1538{
1539 size_t msglen = SSH_COMMAND_MESSAGE_LENGTH(payload_len);
1540
1541 *rqst = kzalloc(sizeof(**rqst) + msglen, flags);
1542 if (!*rqst)
1543 return -ENOMEM;
1544
1545 buffer->ptr = (u8 *)(*rqst + 1);
1546 buffer->len = msglen;
1547
1548 return 0;
1549}
1550EXPORT_SYMBOL_GPL(ssam_request_sync_alloc);
1551
1552/**
1553 * ssam_request_sync_free() - Free a synchronous request.
1554 * @rqst: The request to be freed.
1555 *
1556 * Free a synchronous request and its corresponding buffer allocated with
1557 * ssam_request_sync_alloc(). Do not use for requests allocated on the stack
1558 * or via any other function.
1559 *
1560 * Warning: The caller must ensure that the request is not in use any more.
1561 * I.e. the caller must ensure that it has the only reference to the request
1562 * and the request is not currently pending. This means that the caller has
1563 * either never submitted the request, request submission has failed, or the
1564 * caller has waited until the submitted request has been completed via
1565 * ssam_request_sync_wait().
1566 */
1567void ssam_request_sync_free(struct ssam_request_sync *rqst)
1568{
1569 kfree(rqst);
1570}
1571EXPORT_SYMBOL_GPL(ssam_request_sync_free);
1572
1573/**
1574 * ssam_request_sync_init() - Initialize a synchronous request struct.
1575 * @rqst: The request to initialize.
1576 * @flags: The request flags.
1577 *
1578 * Initializes the given request struct. Does not initialize the request
1579 * message data. This has to be done explicitly after this call via
1580 * ssam_request_sync_set_data() and the actual message data has to be written
1581 * via ssam_request_write_data().
1582 *
1583 * Return: Returns zero on success or %-EINVAL if the given flags are invalid.
1584 */
1585int ssam_request_sync_init(struct ssam_request_sync *rqst,
1586 enum ssam_request_flags flags)
1587{
1588 int status;
1589
1590 status = ssh_request_init(&rqst->base, flags, &ssam_request_sync_ops);
1591 if (status)
1592 return status;
1593
1594 init_completion(&rqst->comp);
1595 rqst->resp = NULL;
1596 rqst->status = 0;
1597
1598 return 0;
1599}
1600EXPORT_SYMBOL_GPL(ssam_request_sync_init);
1601
1602/**
1603 * ssam_request_sync_submit() - Submit a synchronous request.
1604 * @ctrl: The controller with which to submit the request.
1605 * @rqst: The request to submit.
1606 *
1607 * Submit a synchronous request. The request has to be initialized and
1608 * properly set up, including response buffer (may be %NULL if no response is
1609 * expected) and command message data. This function does not wait for the
1610 * request to be completed.
1611 *
1612 * If this function succeeds, ssam_request_sync_wait() must be used to ensure
1613 * that the request has been completed before the response data can be
1614 * accessed and/or the request can be freed. On failure, the request may
1615 * immediately be freed.
1616 *
1617 * This function may only be used if the controller is active, i.e. has been
1618 * initialized and not suspended.
1619 */
1620int ssam_request_sync_submit(struct ssam_controller *ctrl,
1621 struct ssam_request_sync *rqst)
1622{
1623 int status;
1624
1625 /*
1626 * This is only a superficial check. In general, the caller needs to
1627 * ensure that the controller is initialized and is not (and does not
1628 * get) suspended during use, i.e. until the request has been completed
1629 * (if _absolutely_ necessary, by use of ssam_controller_statelock/
1630 * ssam_controller_stateunlock, but something like ssam_client_link
1631 * should be preferred as this needs to last until the request has been
1632 * completed).
1633 *
1634 * Note that it is actually safe to use this function while the
1635 * controller is in the process of being shut down (as ssh_rtl_submit
1636 * is safe with regards to this), but it is generally discouraged to do
1637 * so.
1638 */
1639 if (WARN_ON(READ_ONCE(ctrl->state) != SSAM_CONTROLLER_STARTED)) {
1640 ssh_request_put(&rqst->base);
1641 return -ENODEV;
1642 }
1643
1644 status = ssh_rtl_submit(&ctrl->rtl, &rqst->base);
1645 ssh_request_put(&rqst->base);
1646
1647 return status;
1648}
1649EXPORT_SYMBOL_GPL(ssam_request_sync_submit);
1650
1651/**
1652 * ssam_request_sync() - Execute a synchronous request.
1653 * @ctrl: The controller via which the request will be submitted.
1654 * @spec: The request specification and payload.
1655 * @rsp: The response buffer.
1656 *
1657 * Allocates a synchronous request with its message data buffer on the heap
1658 * via ssam_request_sync_alloc(), fully initializes it via the provided
1659 * request specification, submits it, and finally waits for its completion
1660 * before freeing it and returning its status.
1661 *
1662 * Return: Returns the status of the request or any failure during setup.
1663 */
1664int ssam_request_sync(struct ssam_controller *ctrl,
1665 const struct ssam_request *spec,
1666 struct ssam_response *rsp)
1667{
1668 struct ssam_request_sync *rqst;
1669 struct ssam_span buf;
1670 ssize_t len;
1671 int status;
1672
1673 status = ssam_request_sync_alloc(spec->length, GFP_KERNEL, &rqst, &buf);
1674 if (status)
1675 return status;
1676
1677 status = ssam_request_sync_init(rqst, spec->flags);
1678 if (status)
1679 return status;
1680
1681 ssam_request_sync_set_resp(rqst, rsp);
1682
1683 len = ssam_request_write_data(&buf, ctrl, spec);
1684 if (len < 0) {
1685 ssam_request_sync_free(rqst);
1686 return len;
1687 }
1688
1689 ssam_request_sync_set_data(rqst, buf.ptr, len);
1690
1691 status = ssam_request_sync_submit(ctrl, rqst);
1692 if (!status)
1693 status = ssam_request_sync_wait(rqst);
1694
1695 ssam_request_sync_free(rqst);
1696 return status;
1697}
1698EXPORT_SYMBOL_GPL(ssam_request_sync);
1699
1700/**
1701 * ssam_request_sync_with_buffer() - Execute a synchronous request with the
1702 * provided buffer as back-end for the message buffer.
1703 * @ctrl: The controller via which the request will be submitted.
1704 * @spec: The request specification and payload.
1705 * @rsp: The response buffer.
1706 * @buf: The buffer for the request message data.
1707 *
1708 * Allocates a synchronous request struct on the stack, fully initializes it
1709 * using the provided buffer as message data buffer, submits it, and then
1710 * waits for its completion before returning its status. The
1711 * SSH_COMMAND_MESSAGE_LENGTH() macro can be used to compute the required
1712 * message buffer size.
1713 *
1714 * This function does essentially the same as ssam_request_sync(), but instead
1715 * of dynamically allocating the request and message data buffer, it uses the
1716 * provided message data buffer and stores the (small) request struct on the
1717 * heap.
1718 *
1719 * Return: Returns the status of the request or any failure during setup.
1720 */
1721int ssam_request_sync_with_buffer(struct ssam_controller *ctrl,
1722 const struct ssam_request *spec,
1723 struct ssam_response *rsp,
1724 struct ssam_span *buf)
1725{
1726 struct ssam_request_sync rqst;
1727 ssize_t len;
1728 int status;
1729
1730 status = ssam_request_sync_init(&rqst, spec->flags);
1731 if (status)
1732 return status;
1733
1734 ssam_request_sync_set_resp(&rqst, rsp);
1735
1736 len = ssam_request_write_data(buf, ctrl, spec);
1737 if (len < 0)
1738 return len;
1739
1740 ssam_request_sync_set_data(&rqst, buf->ptr, len);
1741
1742 status = ssam_request_sync_submit(ctrl, &rqst);
1743 if (!status)
1744 status = ssam_request_sync_wait(&rqst);
1745
1746 return status;
1747}
1748EXPORT_SYMBOL_GPL(ssam_request_sync_with_buffer);
1749
1750
1751/* -- Internal SAM requests. ------------------------------------------------ */
1752
1753static SSAM_DEFINE_SYNC_REQUEST_R(ssam_ssh_get_firmware_version, __le32, {
1754 .target_category = SSAM_SSH_TC_SAM,
1755 .target_id = 0x01,
1756 .command_id = 0x13,
1757 .instance_id = 0x00,
1758});
1759
1760static SSAM_DEFINE_SYNC_REQUEST_R(ssam_ssh_notif_display_off, u8, {
1761 .target_category = SSAM_SSH_TC_SAM,
1762 .target_id = 0x01,
1763 .command_id = 0x15,
1764 .instance_id = 0x00,
1765});
1766
1767static SSAM_DEFINE_SYNC_REQUEST_R(ssam_ssh_notif_display_on, u8, {
1768 .target_category = SSAM_SSH_TC_SAM,
1769 .target_id = 0x01,
1770 .command_id = 0x16,
1771 .instance_id = 0x00,
1772});
1773
1774static SSAM_DEFINE_SYNC_REQUEST_R(ssam_ssh_notif_d0_exit, u8, {
1775 .target_category = SSAM_SSH_TC_SAM,
1776 .target_id = 0x01,
1777 .command_id = 0x33,
1778 .instance_id = 0x00,
1779});
1780
1781static SSAM_DEFINE_SYNC_REQUEST_R(ssam_ssh_notif_d0_entry, u8, {
1782 .target_category = SSAM_SSH_TC_SAM,
1783 .target_id = 0x01,
1784 .command_id = 0x34,
1785 .instance_id = 0x00,
1786});
1787
1788/**
1789 * struct ssh_notification_params - Command payload to enable/disable SSH
1790 * notifications.
1791 * @target_category: The target category for which notifications should be
1792 * enabled/disabled.
1793 * @flags: Flags determining how notifications are being sent.
1794 * @request_id: The request ID that is used to send these notifications.
1795 * @instance_id: The specific instance in the given target category for
1796 * which notifications should be enabled.
1797 */
1798struct ssh_notification_params {
1799 u8 target_category;
1800 u8 flags;
1801 __le16 request_id;
1802 u8 instance_id;
1803} __packed;
1804
1805static_assert(sizeof(struct ssh_notification_params) == 5);
1806
1807static int __ssam_ssh_event_request(struct ssam_controller *ctrl,
1808 struct ssam_event_registry reg, u8 cid,
1809 struct ssam_event_id id, u8 flags)
1810{
1811 struct ssh_notification_params params;
1812 struct ssam_request rqst;
1813 struct ssam_response result;
1814 int status;
1815
1816 u16 rqid = ssh_tc_to_rqid(id.target_category);
1817 u8 buf = 0;
1818
1819 /* Only allow RQIDs that lie within the event spectrum. */
1820 if (!ssh_rqid_is_event(rqid))
1821 return -EINVAL;
1822
1823 params.target_category = id.target_category;
1824 params.instance_id = id.instance;
1825 params.flags = flags;
1826 put_unaligned_le16(rqid, &params.request_id);
1827
1828 rqst.target_category = reg.target_category;
1829 rqst.target_id = reg.target_id;
1830 rqst.command_id = cid;
1831 rqst.instance_id = 0x00;
1832 rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
1833 rqst.length = sizeof(params);
1834 rqst.payload = (u8 *)&params;
1835
1836 result.capacity = sizeof(buf);
1837 result.length = 0;
1838 result.pointer = &buf;
1839
1840 status = ssam_retry(ssam_request_sync_onstack, ctrl, &rqst, &result,
1841 sizeof(params));
1842
1843 return status < 0 ? status : buf;
1844}
1845
1846/**
1847 * ssam_ssh_event_enable() - Enable SSH event.
1848 * @ctrl: The controller for which to enable the event.
1849 * @reg: The event registry describing what request to use for enabling and
1850 * disabling the event.
1851 * @id: The event identifier.
1852 * @flags: The event flags.
1853 *
1854 * Enables the specified event on the EC. This function does not manage
1855 * reference counting of enabled events and is basically only a wrapper for
1856 * the raw EC request. If the specified event is already enabled, the EC will
1857 * ignore this request.
1858 *
1859 * Return: Returns the status of the executed SAM request (zero on success and
1860 * negative on direct failure) or %-EPROTO if the request response indicates a
1861 * failure.
1862 */
1863static int ssam_ssh_event_enable(struct ssam_controller *ctrl,
1864 struct ssam_event_registry reg,
1865 struct ssam_event_id id, u8 flags)
1866{
1867 int status;
1868
1869 status = __ssam_ssh_event_request(ctrl, reg, reg.cid_enable, id, flags);
1870
1871 if (status < 0 && status != -EINVAL) {
1872 ssam_err(ctrl,
1873 "failed to enable event source (tc: %#04x, iid: %#04x, reg: %#04x)\n",
1874 id.target_category, id.instance, reg.target_category);
1875 }
1876
1877 if (status > 0) {
1878 ssam_err(ctrl,
1879 "unexpected result while enabling event source: %#04x (tc: %#04x, iid: %#04x, reg: %#04x)\n",
1880 status, id.target_category, id.instance, reg.target_category);
1881 return -EPROTO;
1882 }
1883
1884 return status;
1885}
1886
1887/**
1888 * ssam_ssh_event_disable() - Disable SSH event.
1889 * @ctrl: The controller for which to disable the event.
1890 * @reg: The event registry describing what request to use for enabling and
1891 * disabling the event (must be same as used when enabling the event).
1892 * @id: The event identifier.
1893 * @flags: The event flags (likely ignored for disabling of events).
1894 *
1895 * Disables the specified event on the EC. This function does not manage
1896 * reference counting of enabled events and is basically only a wrapper for
1897 * the raw EC request. If the specified event is already disabled, the EC will
1898 * ignore this request.
1899 *
1900 * Return: Returns the status of the executed SAM request (zero on success and
1901 * negative on direct failure) or %-EPROTO if the request response indicates a
1902 * failure.
1903 */
1904static int ssam_ssh_event_disable(struct ssam_controller *ctrl,
1905 struct ssam_event_registry reg,
1906 struct ssam_event_id id, u8 flags)
1907{
1908 int status;
1909
1910 status = __ssam_ssh_event_request(ctrl, reg, reg.cid_enable, id, flags);
1911
1912 if (status < 0 && status != -EINVAL) {
1913 ssam_err(ctrl,
1914 "failed to disable event source (tc: %#04x, iid: %#04x, reg: %#04x)\n",
1915 id.target_category, id.instance, reg.target_category);
1916 }
1917
1918 if (status > 0) {
1919 ssam_err(ctrl,
1920 "unexpected result while disabling event source: %#04x (tc: %#04x, iid: %#04x, reg: %#04x)\n",
1921 status, id.target_category, id.instance, reg.target_category);
1922 return -EPROTO;
1923 }
1924
1925 return status;
1926}
1927
1928
1929/* -- Wrappers for internal SAM requests. ----------------------------------- */
1930
1931/**
1932 * ssam_get_firmware_version() - Get the SAM/EC firmware version.
1933 * @ctrl: The controller.
1934 * @version: Where to store the version number.
1935 *
1936 * Return: Returns zero on success or the status of the executed SAM request
1937 * if that request failed.
1938 */
1939int ssam_get_firmware_version(struct ssam_controller *ctrl, u32 *version)
1940{
1941 __le32 __version;
1942 int status;
1943
1944 status = ssam_retry(ssam_ssh_get_firmware_version, ctrl, &__version);
1945 if (status)
1946 return status;
1947
1948 *version = le32_to_cpu(__version);
1949 return 0;
1950}
1951
1952/**
1953 * ssam_ctrl_notif_display_off() - Notify EC that the display has been turned
1954 * off.
1955 * @ctrl: The controller.
1956 *
1957 * Notify the EC that the display has been turned off and the driver may enter
1958 * a lower-power state. This will prevent events from being sent directly.
1959 * Rather, the EC signals an event by pulling the wakeup GPIO high for as long
1960 * as there are pending events. The events then need to be manually released,
1961 * one by one, via the GPIO callback request. All pending events accumulated
1962 * during this state can also be released by issuing the display-on
1963 * notification, e.g. via ssam_ctrl_notif_display_on(), which will also reset
1964 * the GPIO.
1965 *
1966 * On some devices, specifically ones with an integrated keyboard, the keyboard
1967 * backlight will be turned off by this call.
1968 *
1969 * This function will only send the display-off notification command if
1970 * display notifications are supported by the EC. Currently all known devices
1971 * support these notifications.
1972 *
1973 * Use ssam_ctrl_notif_display_on() to reverse the effects of this function.
1974 *
1975 * Return: Returns zero on success or if no request has been executed, the
1976 * status of the executed SAM request if that request failed, or %-EPROTO if
1977 * an unexpected response has been received.
1978 */
1979int ssam_ctrl_notif_display_off(struct ssam_controller *ctrl)
1980{
1981 int status;
1982 u8 response;
1983
1984 ssam_dbg(ctrl, "pm: notifying display off\n");
1985
1986 status = ssam_retry(ssam_ssh_notif_display_off, ctrl, &response);
1987 if (status)
1988 return status;
1989
1990 if (response != 0) {
1991 ssam_err(ctrl, "unexpected response from display-off notification: %#04x\n",
1992 response);
1993 return -EPROTO;
1994 }
1995
1996 return 0;
1997}
1998
1999/**
2000 * ssam_ctrl_notif_display_on() - Notify EC that the display has been turned on.
2001 * @ctrl: The controller.
2002 *
2003 * Notify the EC that the display has been turned back on and the driver has
2004 * exited its lower-power state. This notification is the counterpart to the
2005 * display-off notification sent via ssam_ctrl_notif_display_off() and will
2006 * reverse its effects, including resetting events to their default behavior.
2007 *
2008 * This function will only send the display-on notification command if display
2009 * notifications are supported by the EC. Currently all known devices support
2010 * these notifications.
2011 *
2012 * See ssam_ctrl_notif_display_off() for more details.
2013 *
2014 * Return: Returns zero on success or if no request has been executed, the
2015 * status of the executed SAM request if that request failed, or %-EPROTO if
2016 * an unexpected response has been received.
2017 */
2018int ssam_ctrl_notif_display_on(struct ssam_controller *ctrl)
2019{
2020 int status;
2021 u8 response;
2022
2023 ssam_dbg(ctrl, "pm: notifying display on\n");
2024
2025 status = ssam_retry(ssam_ssh_notif_display_on, ctrl, &response);
2026 if (status)
2027 return status;
2028
2029 if (response != 0) {
2030 ssam_err(ctrl, "unexpected response from display-on notification: %#04x\n",
2031 response);
2032 return -EPROTO;
2033 }
2034
2035 return 0;
2036}
2037
2038/**
2039 * ssam_ctrl_notif_d0_exit() - Notify EC that the driver/device exits the D0
2040 * power state.
2041 * @ctrl: The controller
2042 *
2043 * Notifies the EC that the driver prepares to exit the D0 power state in
2044 * favor of a lower-power state. Exact effects of this function related to the
2045 * EC are currently unknown.
2046 *
2047 * This function will only send the D0-exit notification command if D0-state
2048 * notifications are supported by the EC. Only newer Surface generations
2049 * support these notifications.
2050 *
2051 * Use ssam_ctrl_notif_d0_entry() to reverse the effects of this function.
2052 *
2053 * Return: Returns zero on success or if no request has been executed, the
2054 * status of the executed SAM request if that request failed, or %-EPROTO if
2055 * an unexpected response has been received.
2056 */
2057int ssam_ctrl_notif_d0_exit(struct ssam_controller *ctrl)
2058{
2059 int status;
2060 u8 response;
2061
2062 if (!ctrl->caps.d3_closes_handle)
2063 return 0;
2064
2065 ssam_dbg(ctrl, "pm: notifying D0 exit\n");
2066
2067 status = ssam_retry(ssam_ssh_notif_d0_exit, ctrl, &response);
2068 if (status)
2069 return status;
2070
2071 if (response != 0) {
2072 ssam_err(ctrl, "unexpected response from D0-exit notification: %#04x\n",
2073 response);
2074 return -EPROTO;
2075 }
2076
2077 return 0;
2078}
2079
2080/**
2081 * ssam_ctrl_notif_d0_entry() - Notify EC that the driver/device enters the D0
2082 * power state.
2083 * @ctrl: The controller
2084 *
2085 * Notifies the EC that the driver has exited a lower-power state and entered
2086 * the D0 power state. Exact effects of this function related to the EC are
2087 * currently unknown.
2088 *
2089 * This function will only send the D0-entry notification command if D0-state
2090 * notifications are supported by the EC. Only newer Surface generations
2091 * support these notifications.
2092 *
2093 * See ssam_ctrl_notif_d0_exit() for more details.
2094 *
2095 * Return: Returns zero on success or if no request has been executed, the
2096 * status of the executed SAM request if that request failed, or %-EPROTO if
2097 * an unexpected response has been received.
2098 */
2099int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl)
2100{
2101 int status;
2102 u8 response;
2103
2104 if (!ctrl->caps.d3_closes_handle)
2105 return 0;
2106
2107 ssam_dbg(ctrl, "pm: notifying D0 entry\n");
2108
2109 status = ssam_retry(ssam_ssh_notif_d0_entry, ctrl, &response);
2110 if (status)
2111 return status;
2112
2113 if (response != 0) {
2114 ssam_err(ctrl, "unexpected response from D0-entry notification: %#04x\n",
2115 response);
2116 return -EPROTO;
2117 }
2118
2119 return 0;
2120}
2121
2122
2123/* -- Top-level event registry interface. ----------------------------------- */
2124
2125/**
2126 * ssam_notifier_register() - Register an event notifier.
2127 * @ctrl: The controller to register the notifier on.
2128 * @n: The event notifier to register.
2129 *
2130 * Register an event notifier and increment the usage counter of the
2131 * associated SAM event. If the event was previously not enabled, it will be
2132 * enabled during this call.
2133 *
2134 * Return: Returns zero on success, %-ENOSPC if there have already been
2135 * %INT_MAX notifiers for the event ID/type associated with the notifier block
2136 * registered, %-ENOMEM if the corresponding event entry could not be
2137 * allocated. If this is the first time that a notifier block is registered
2138 * for the specific associated event, returns the status of the event-enable
2139 * EC-command.
2140 */
2141int ssam_notifier_register(struct ssam_controller *ctrl,
2142 struct ssam_event_notifier *n)
2143{
2144 u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
2145 struct ssam_nf_refcount_entry *entry;
2146 struct ssam_nf_head *nf_head;
2147 struct ssam_nf *nf;
2148 int status;
2149
2150 if (!ssh_rqid_is_event(rqid))
2151 return -EINVAL;
2152
2153 nf = &ctrl->cplt.event.notif;
2154 nf_head = &nf->head[ssh_rqid_to_event(rqid)];
2155
2156 mutex_lock(&nf->lock);
2157
2158 entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id);
2159 if (IS_ERR(entry)) {
2160 mutex_unlock(&nf->lock);
2161 return PTR_ERR(entry);
2162 }
2163
2164 ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
2165 n->event.reg.target_category, n->event.id.target_category,
2166 n->event.id.instance, entry->refcount);
2167
2168 status = ssam_nfblk_insert(nf_head, &n->base);
2169 if (status) {
2170 entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
2171 if (entry->refcount == 0)
2172 kfree(entry);
2173
2174 mutex_unlock(&nf->lock);
2175 return status;
2176 }
2177
2178 if (entry->refcount == 1) {
2179 status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id,
2180 n->event.flags);
2181 if (status) {
2182 ssam_nfblk_remove(&n->base);
2183 kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id));
2184 mutex_unlock(&nf->lock);
2185 synchronize_srcu(&nf_head->srcu);
2186 return status;
2187 }
2188
2189 entry->flags = n->event.flags;
2190
2191 } else if (entry->flags != n->event.flags) {
2192 ssam_warn(ctrl,
2193 "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
2194 n->event.flags, entry->flags, n->event.reg.target_category,
2195 n->event.id.target_category, n->event.id.instance);
2196 }
2197
2198 mutex_unlock(&nf->lock);
2199 return 0;
2200}
2201EXPORT_SYMBOL_GPL(ssam_notifier_register);
2202
2203/**
2204 * ssam_notifier_unregister() - Unregister an event notifier.
2205 * @ctrl: The controller the notifier has been registered on.
2206 * @n: The event notifier to unregister.
2207 *
2208 * Unregister an event notifier and decrement the usage counter of the
2209 * associated SAM event. If the usage counter reaches zero, the event will be
2210 * disabled.
2211 *
2212 * Return: Returns zero on success, %-ENOENT if the given notifier block has
2213 * not been registered on the controller. If the given notifier block was the
2214 * last one associated with its specific event, returns the status of the
2215 * event-disable EC-command.
2216 */
2217int ssam_notifier_unregister(struct ssam_controller *ctrl,
2218 struct ssam_event_notifier *n)
2219{
2220 u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
2221 struct ssam_nf_refcount_entry *entry;
2222 struct ssam_nf_head *nf_head;
2223 struct ssam_nf *nf;
2224 int status = 0;
2225
2226 if (!ssh_rqid_is_event(rqid))
2227 return -EINVAL;
2228
2229 nf = &ctrl->cplt.event.notif;
2230 nf_head = &nf->head[ssh_rqid_to_event(rqid)];
2231
2232 mutex_lock(&nf->lock);
2233
2234 if (!ssam_nfblk_find(nf_head, &n->base)) {
2235 mutex_unlock(&nf->lock);
2236 return -ENOENT;
2237 }
2238
2239 entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
2240 if (WARN_ON(!entry)) {
2241 /*
2242 * If this does not return an entry, there's a logic error
2243 * somewhere: The notifier block is registered, but the event
2244 * refcount entry is not there. Remove the notifier block
2245 * anyways.
2246 */
2247 status = -ENOENT;
2248 goto remove;
2249 }
2250
2251 ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
2252 n->event.reg.target_category, n->event.id.target_category,
2253 n->event.id.instance, entry->refcount);
2254
2255 if (entry->flags != n->event.flags) {
2256 ssam_warn(ctrl,
2257 "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
2258 n->event.flags, entry->flags, n->event.reg.target_category,
2259 n->event.id.target_category, n->event.id.instance);
2260 }
2261
2262 if (entry->refcount == 0) {
2263 status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id,
2264 n->event.flags);
2265 kfree(entry);
2266 }
2267
2268remove:
2269 ssam_nfblk_remove(&n->base);
2270 mutex_unlock(&nf->lock);
2271 synchronize_srcu(&nf_head->srcu);
2272
2273 return status;
2274}
2275EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
2276
2277/**
2278 * ssam_notifier_disable_registered() - Disable events for all registered
2279 * notifiers.
2280 * @ctrl: The controller for which to disable the notifiers/events.
2281 *
2282 * Disables events for all currently registered notifiers. In case of an error
2283 * (EC command failing), all previously disabled events will be restored and
2284 * the error code returned.
2285 *
2286 * This function is intended to disable all events prior to hibernation entry.
2287 * See ssam_notifier_restore_registered() to restore/re-enable all events
2288 * disabled with this function.
2289 *
2290 * Note that this function will not disable events for notifiers registered
2291 * after calling this function. It should thus be made sure that no new
2292 * notifiers are going to be added after this call and before the corresponding
2293 * call to ssam_notifier_restore_registered().
2294 *
2295 * Return: Returns zero on success. In case of failure returns the error code
2296 * returned by the failed EC command to disable an event.
2297 */
2298int ssam_notifier_disable_registered(struct ssam_controller *ctrl)
2299{
2300 struct ssam_nf *nf = &ctrl->cplt.event.notif;
2301 struct rb_node *n;
2302 int status;
2303
2304 mutex_lock(&nf->lock);
2305 for (n = rb_first(&nf->refcount); n; n = rb_next(n)) {
2306 struct ssam_nf_refcount_entry *e;
2307
2308 e = rb_entry(n, struct ssam_nf_refcount_entry, node);
2309 status = ssam_ssh_event_disable(ctrl, e->key.reg,
2310 e->key.id, e->flags);
2311 if (status)
2312 goto err;
2313 }
2314 mutex_unlock(&nf->lock);
2315
2316 return 0;
2317
2318err:
2319 for (n = rb_prev(n); n; n = rb_prev(n)) {
2320 struct ssam_nf_refcount_entry *e;
2321
2322 e = rb_entry(n, struct ssam_nf_refcount_entry, node);
2323 ssam_ssh_event_enable(ctrl, e->key.reg, e->key.id, e->flags);
2324 }
2325 mutex_unlock(&nf->lock);
2326
2327 return status;
2328}
2329
2330/**
2331 * ssam_notifier_restore_registered() - Restore/re-enable events for all
2332 * registered notifiers.
2333 * @ctrl: The controller for which to restore the notifiers/events.
2334 *
2335 * Restores/re-enables all events for which notifiers have been registered on
2336 * the given controller. In case of a failure, the error is logged and the
2337 * function continues to try and enable the remaining events.
2338 *
2339 * This function is intended to restore/re-enable all registered events after
2340 * hibernation. See ssam_notifier_disable_registered() for the counter part
2341 * disabling the events and more details.
2342 */
2343void ssam_notifier_restore_registered(struct ssam_controller *ctrl)
2344{
2345 struct ssam_nf *nf = &ctrl->cplt.event.notif;
2346 struct rb_node *n;
2347
2348 mutex_lock(&nf->lock);
2349 for (n = rb_first(&nf->refcount); n; n = rb_next(n)) {
2350 struct ssam_nf_refcount_entry *e;
2351
2352 e = rb_entry(n, struct ssam_nf_refcount_entry, node);
2353
2354 /* Ignore errors, will get logged in call. */
2355 ssam_ssh_event_enable(ctrl, e->key.reg, e->key.id, e->flags);
2356 }
2357 mutex_unlock(&nf->lock);
2358}
2359
2360/**
2361 * ssam_notifier_is_empty() - Check if there are any registered notifiers.
2362 * @ctrl: The controller to check on.
2363 *
2364 * Return: Returns %true if there are currently no notifiers registered on the
2365 * controller, %false otherwise.
2366 */
2367static bool ssam_notifier_is_empty(struct ssam_controller *ctrl)
2368{
2369 struct ssam_nf *nf = &ctrl->cplt.event.notif;
2370 bool result;
2371
2372 mutex_lock(&nf->lock);
2373 result = ssam_nf_refcount_empty(nf);
2374 mutex_unlock(&nf->lock);
2375
2376 return result;
2377}
2378
2379/**
2380 * ssam_notifier_unregister_all() - Unregister all currently registered
2381 * notifiers.
2382 * @ctrl: The controller to unregister the notifiers on.
2383 *
2384 * Unregisters all currently registered notifiers. This function is used to
2385 * ensure that all notifiers will be unregistered and associated
2386 * entries/resources freed when the controller is being shut down.
2387 */
2388static void ssam_notifier_unregister_all(struct ssam_controller *ctrl)
2389{
2390 struct ssam_nf *nf = &ctrl->cplt.event.notif;
2391 struct ssam_nf_refcount_entry *e, *n;
2392
2393 mutex_lock(&nf->lock);
2394 rbtree_postorder_for_each_entry_safe(e, n, &nf->refcount, node) {
2395 /* Ignore errors, will get logged in call. */
2396 ssam_ssh_event_disable(ctrl, e->key.reg, e->key.id, e->flags);
2397 kfree(e);
2398 }
2399 nf->refcount = RB_ROOT;
2400 mutex_unlock(&nf->lock);
2401}
2402
2403
2404/* -- Wakeup IRQ. ----------------------------------------------------------- */
2405
2406static irqreturn_t ssam_irq_handle(int irq, void *dev_id)
2407{
2408 struct ssam_controller *ctrl = dev_id;
2409
2410 ssam_dbg(ctrl, "pm: wake irq triggered\n");
2411
2412 /*
2413 * Note: Proper wakeup detection is currently unimplemented.
2414 * When the EC is in display-off or any other non-D0 state, it
2415 * does not send events/notifications to the host. Instead it
2416 * signals that there are events available via the wakeup IRQ.
2417 * This driver is responsible for calling back to the EC to
2418 * release these events one-by-one.
2419 *
2420 * This IRQ should not cause a full system resume by its own.
2421 * Instead, events should be handled by their respective subsystem
2422 * drivers, which in turn should signal whether a full system
2423 * resume should be performed.
2424 *
2425 * TODO: Send GPIO callback command repeatedly to EC until callback
2426 * returns 0x00. Return flag of callback is "has more events".
2427 * Each time the command is sent, one event is "released". Once
2428 * all events have been released (return = 0x00), the GPIO is
2429 * re-armed. Detect wakeup events during this process, go back to
2430 * sleep if no wakeup event has been received.
2431 */
2432
2433 return IRQ_HANDLED;
2434}
2435
2436/**
2437 * ssam_irq_setup() - Set up SAM EC wakeup-GPIO interrupt.
2438 * @ctrl: The controller for which the IRQ should be set up.
2439 *
2440 * Set up an IRQ for the wakeup-GPIO pin of the SAM EC. This IRQ can be used
2441 * to wake the device from a low power state.
2442 *
2443 * Note that this IRQ can only be triggered while the EC is in the display-off
2444 * state. In this state, events are not sent to the host in the usual way.
2445 * Instead the wakeup-GPIO gets pulled to "high" as long as there are pending
2446 * events and these events need to be released one-by-one via the GPIO
2447 * callback request, either until there are no events left and the GPIO is
2448 * reset, or all at once by transitioning the EC out of the display-off state,
2449 * which will also clear the GPIO.
2450 *
2451 * Not all events, however, should trigger a full system wakeup. Instead the
2452 * driver should, if necessary, inspect and forward each event to the
2453 * corresponding subsystem, which in turn should decide if the system needs to
2454 * be woken up. This logic has not been implemented yet, thus wakeup by this
2455 * IRQ should be disabled by default to avoid spurious wake-ups, caused, for
2456 * example, by the remaining battery percentage changing. Refer to comments in
2457 * this function and comments in the corresponding IRQ handler for more
2458 * details on how this should be implemented.
2459 *
2460 * See also ssam_ctrl_notif_display_off() and ssam_ctrl_notif_display_off()
2461 * for functions to transition the EC into and out of the display-off state as
2462 * well as more details on it.
2463 *
2464 * The IRQ is disabled by default and has to be enabled before it can wake up
2465 * the device from suspend via ssam_irq_arm_for_wakeup(). On teardown, the IRQ
2466 * should be freed via ssam_irq_free().
2467 */
2468int ssam_irq_setup(struct ssam_controller *ctrl)
2469{
2470 struct device *dev = ssam_controller_device(ctrl);
2471 struct gpio_desc *gpiod;
2472 int irq;
2473 int status;
2474
2475 /*
2476 * The actual GPIO interrupt is declared in ACPI as TRIGGER_HIGH.
2477 * However, the GPIO line only gets reset by sending the GPIO callback
2478 * command to SAM (or alternatively the display-on notification). As
2479 * proper handling for this interrupt is not implemented yet, leaving
2480 * the IRQ at TRIGGER_HIGH would cause an IRQ storm (as the callback
2481 * never gets sent and thus the line never gets reset). To avoid this,
2482 * mark the IRQ as TRIGGER_RISING for now, only creating a single
2483 * interrupt, and let the SAM resume callback during the controller
2484 * resume process clear it.
2485 */
2486 const int irqf = IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_RISING;
2487
2488 gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS);
2489 if (IS_ERR(gpiod))
2490 return PTR_ERR(gpiod);
2491
2492 irq = gpiod_to_irq(gpiod);
2493 gpiod_put(gpiod);
2494
2495 if (irq < 0)
2496 return irq;
2497
2498 status = request_threaded_irq(irq, NULL, ssam_irq_handle, irqf,
2499 "ssam_wakeup", ctrl);
2500 if (status)
2501 return status;
2502
2503 ctrl->irq.num = irq;
2504 disable_irq(ctrl->irq.num);
2505 return 0;
2506}
2507
2508/**
2509 * ssam_irq_free() - Free SAM EC wakeup-GPIO interrupt.
2510 * @ctrl: The controller for which the IRQ should be freed.
2511 *
2512 * Free the wakeup-GPIO IRQ previously set-up via ssam_irq_setup().
2513 */
2514void ssam_irq_free(struct ssam_controller *ctrl)
2515{
2516 free_irq(ctrl->irq.num, ctrl);
2517 ctrl->irq.num = -1;
2518}
2519
2520/**
2521 * ssam_irq_arm_for_wakeup() - Arm the EC IRQ for wakeup, if enabled.
2522 * @ctrl: The controller for which the IRQ should be armed.
2523 *
2524 * Sets up the IRQ so that it can be used to wake the device. Specifically,
2525 * this function enables the irq and then, if the device is allowed to wake up
2526 * the system, calls enable_irq_wake(). See ssam_irq_disarm_wakeup() for the
2527 * corresponding function to disable the IRQ.
2528 *
2529 * This function is intended to arm the IRQ before entering S2idle suspend.
2530 *
2531 * Note: calls to ssam_irq_arm_for_wakeup() and ssam_irq_disarm_wakeup() must
2532 * be balanced.
2533 */
2534int ssam_irq_arm_for_wakeup(struct ssam_controller *ctrl)
2535{
2536 struct device *dev = ssam_controller_device(ctrl);
2537 int status;
2538
2539 enable_irq(ctrl->irq.num);
2540 if (device_may_wakeup(dev)) {
2541 status = enable_irq_wake(ctrl->irq.num);
2542 if (status) {
2543 ssam_err(ctrl, "failed to enable wake IRQ: %d\n", status);
2544 disable_irq(ctrl->irq.num);
2545 return status;
2546 }
2547
2548 ctrl->irq.wakeup_enabled = true;
2549 } else {
2550 ctrl->irq.wakeup_enabled = false;
2551 }
2552
2553 return 0;
2554}
2555
2556/**
2557 * ssam_irq_disarm_wakeup() - Disarm the wakeup IRQ.
2558 * @ctrl: The controller for which the IRQ should be disarmed.
2559 *
2560 * Disarm the IRQ previously set up for wake via ssam_irq_arm_for_wakeup().
2561 *
2562 * This function is intended to disarm the IRQ after exiting S2idle suspend.
2563 *
2564 * Note: calls to ssam_irq_arm_for_wakeup() and ssam_irq_disarm_wakeup() must
2565 * be balanced.
2566 */
2567void ssam_irq_disarm_wakeup(struct ssam_controller *ctrl)
2568{
2569 int status;
2570
2571 if (ctrl->irq.wakeup_enabled) {
2572 status = disable_irq_wake(ctrl->irq.num);
2573 if (status)
2574 ssam_err(ctrl, "failed to disable wake IRQ: %d\n", status);
2575
2576 ctrl->irq.wakeup_enabled = false;
2577 }
2578 disable_irq(ctrl->irq.num);
2579}
drivers/platform/surface/aggregator/controller.h+285−0
@@ -0,0 +1,285 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Main SSAM/SSH controller structure and functionality.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
9#define _SURFACE_AGGREGATOR_CONTROLLER_H
10
11#include <linux/kref.h>
12#include <linux/list.h>
13#include <linux/mutex.h>
14#include <linux/rbtree.h>
15#include <linux/rwsem.h>
16#include <linux/serdev.h>
17#include <linux/spinlock.h>
18#include <linux/srcu.h>
19#include <linux/types.h>
20#include <linux/workqueue.h>
21
22#include <linux/surface_aggregator/controller.h>
23#include <linux/surface_aggregator/serial_hub.h>
24
25#include "ssh_request_layer.h"
26
27
28/* -- Safe counters. -------------------------------------------------------- */
29
30/**
31 * struct ssh_seq_counter - Safe counter for SSH sequence IDs.
32 * @value: The current counter value.
33 */
34struct ssh_seq_counter {
35 u8 value;
36};
37
38/**
39 * struct ssh_rqid_counter - Safe counter for SSH request IDs.
40 * @value: The current counter value.
41 */
42struct ssh_rqid_counter {
43 u16 value;
44};
45
46
47/* -- Event/notification system. -------------------------------------------- */
48
49/**
50 * struct ssam_nf_head - Notifier head for SSAM events.
51 * @srcu: The SRCU struct for synchronization.
52 * @head: List-head for notifier blocks registered under this head.
53 */
54struct ssam_nf_head {
55 struct srcu_struct srcu;
56 struct list_head head;
57};
58
59/**
60 * struct ssam_nf - Notifier callback- and activation-registry for SSAM events.
61 * @lock: Lock guarding (de-)registration of notifier blocks. Note: This
62 * lock does not need to be held for notifier calls, only
63 * registration and deregistration.
64 * @refcount: The root of the RB-tree used for reference-counting enabled
65 * events/notifications.
66 * @head: The list of notifier heads for event/notification callbacks.
67 */
68struct ssam_nf {
69 struct mutex lock;
70 struct rb_root refcount;
71 struct ssam_nf_head head[SSH_NUM_EVENTS];
72};
73
74
75/* -- Event/async request completion system. -------------------------------- */
76
77struct ssam_cplt;
78
79/**
80 * struct ssam_event_item - Struct for event queuing and completion.
81 * @node: The node in the queue.
82 * @rqid: The request ID of the event.
83 * @ops: Instance specific functions.
84 * @ops.free: Callback for freeing this event item.
85 * @event: Actual event data.
86 */
87struct ssam_event_item {
88 struct list_head node;
89 u16 rqid;
90
91 struct {
92 void (*free)(struct ssam_event_item *event);
93 } ops;
94
95 struct ssam_event event; /* must be last */
96};
97
98/**
99 * struct ssam_event_queue - Queue for completing received events.
100 * @cplt: Reference to the completion system on which this queue is active.
101 * @lock: The lock for any operation on the queue.
102 * @head: The list-head of the queue.
103 * @work: The &struct work_struct performing completion work for this queue.
104 */
105struct ssam_event_queue {
106 struct ssam_cplt *cplt;
107
108 spinlock_t lock;
109 struct list_head head;
110 struct work_struct work;
111};
112
113/**
114 * struct ssam_event_target - Set of queues for a single SSH target ID.
115 * @queue: The array of queues, one queue per event ID.
116 */
117struct ssam_event_target {
118 struct ssam_event_queue queue[SSH_NUM_EVENTS];
119};
120
121/**
122 * struct ssam_cplt - SSAM event/async request completion system.
123 * @dev: The device with which this system is associated. Only used
124 * for logging.
125 * @wq: The &struct workqueue_struct on which all completion work
126 * items are queued.
127 * @event: Event completion management.
128 * @event.target: Array of &struct ssam_event_target, one for each target.
129 * @event.notif: Notifier callbacks and event activation reference counting.
130 */
131struct ssam_cplt {
132 struct device *dev;
133 struct workqueue_struct *wq;
134
135 struct {
136 struct ssam_event_target target[SSH_NUM_TARGETS];
137 struct ssam_nf notif;
138 } event;
139};
140
141
142/* -- Main SSAM device structures. ------------------------------------------ */
143
144/**
145 * enum ssam_controller_state - State values for &struct ssam_controller.
146 * @SSAM_CONTROLLER_UNINITIALIZED:
147 * The controller has not been initialized yet or has been deinitialized.
148 * @SSAM_CONTROLLER_INITIALIZED:
149 * The controller is initialized, but has not been started yet.
150 * @SSAM_CONTROLLER_STARTED:
151 * The controller has been started and is ready to use.
152 * @SSAM_CONTROLLER_STOPPED:
153 * The controller has been stopped.
154 * @SSAM_CONTROLLER_SUSPENDED:
155 * The controller has been suspended.
156 */
157enum ssam_controller_state {
158 SSAM_CONTROLLER_UNINITIALIZED,
159 SSAM_CONTROLLER_INITIALIZED,
160 SSAM_CONTROLLER_STARTED,
161 SSAM_CONTROLLER_STOPPED,
162 SSAM_CONTROLLER_SUSPENDED,
163};
164
165/**
166 * struct ssam_controller_caps - Controller device capabilities.
167 * @ssh_power_profile: SSH power profile.
168 * @ssh_buffer_size: SSH driver UART buffer size.
169 * @screen_on_sleep_idle_timeout: SAM UART screen-on sleep idle timeout.
170 * @screen_off_sleep_idle_timeout: SAM UART screen-off sleep idle timeout.
171 * @d3_closes_handle: SAM closes UART handle in D3.
172 *
173 * Controller and SSH device capabilities found in ACPI.
174 */
175struct ssam_controller_caps {
176 u32 ssh_power_profile;
177 u32 ssh_buffer_size;
178 u32 screen_on_sleep_idle_timeout;
179 u32 screen_off_sleep_idle_timeout;
180 u32 d3_closes_handle:1;
181};
182
183/**
184 * struct ssam_controller - SSAM controller device.
185 * @kref: Reference count of the controller.
186 * @lock: Main lock for the controller, used to guard state changes.
187 * @state: Controller state.
188 * @rtl: Request transport layer for SSH I/O.
189 * @cplt: Completion system for SSH/SSAM events and asynchronous requests.
190 * @counter: Safe SSH message ID counters.
191 * @counter.seq: Sequence ID counter.
192 * @counter.rqid: Request ID counter.
193 * @irq: Wakeup IRQ resources.
194 * @irq.num: The wakeup IRQ number.
195 * @irq.wakeup_enabled: Whether wakeup by IRQ is enabled during suspend.
196 * @caps: The controller device capabilities.
197 */
198struct ssam_controller {
199 struct kref kref;
200
201 struct rw_semaphore lock;
202 enum ssam_controller_state state;
203
204 struct ssh_rtl rtl;
205 struct ssam_cplt cplt;
206
207 struct {
208 struct ssh_seq_counter seq;
209 struct ssh_rqid_counter rqid;
210 } counter;
211
212 struct {
213 int num;
214 bool wakeup_enabled;
215 } irq;
216
217 struct ssam_controller_caps caps;
218};
219
220#define to_ssam_controller(ptr, member) \
221 container_of(ptr, struct ssam_controller, member)
222
223#define ssam_dbg(ctrl, fmt, ...) rtl_dbg(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
224#define ssam_info(ctrl, fmt, ...) rtl_info(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
225#define ssam_warn(ctrl, fmt, ...) rtl_warn(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
226#define ssam_err(ctrl, fmt, ...) rtl_err(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
227
228/**
229 * ssam_controller_receive_buf() - Provide input-data to the controller.
230 * @ctrl: The controller.
231 * @buf: The input buffer.
232 * @n: The number of bytes in the input buffer.
233 *
234 * Provide input data to be evaluated by the controller, which has been
235 * received via the lower-level transport.
236 *
237 * Return: Returns the number of bytes consumed, or, if the packet transport
238 * layer of the controller has been shut down, %-ESHUTDOWN.
239 */
240static inline
241int ssam_controller_receive_buf(struct ssam_controller *ctrl,
242 const unsigned char *buf, size_t n)
243{
244 return ssh_ptl_rx_rcvbuf(&ctrl->rtl.ptl, buf, n);
245}
246
247/**
248 * ssam_controller_write_wakeup() - Notify the controller that the underlying
249 * device has space available for data to be written.
250 * @ctrl: The controller.
251 */
252static inline void ssam_controller_write_wakeup(struct ssam_controller *ctrl)
253{
254 ssh_ptl_tx_wakeup_transfer(&ctrl->rtl.ptl);
255}
256
257int ssam_controller_init(struct ssam_controller *ctrl, struct serdev_device *s);
258int ssam_controller_start(struct ssam_controller *ctrl);
259void ssam_controller_shutdown(struct ssam_controller *ctrl);
260void ssam_controller_destroy(struct ssam_controller *ctrl);
261
262int ssam_notifier_disable_registered(struct ssam_controller *ctrl);
263void ssam_notifier_restore_registered(struct ssam_controller *ctrl);
264
265int ssam_irq_setup(struct ssam_controller *ctrl);
266void ssam_irq_free(struct ssam_controller *ctrl);
267int ssam_irq_arm_for_wakeup(struct ssam_controller *ctrl);
268void ssam_irq_disarm_wakeup(struct ssam_controller *ctrl);
269
270void ssam_controller_lock(struct ssam_controller *c);
271void ssam_controller_unlock(struct ssam_controller *c);
272
273int ssam_get_firmware_version(struct ssam_controller *ctrl, u32 *version);
274int ssam_ctrl_notif_display_off(struct ssam_controller *ctrl);
275int ssam_ctrl_notif_display_on(struct ssam_controller *ctrl);
276int ssam_ctrl_notif_d0_exit(struct ssam_controller *ctrl);
277int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl);
278
279int ssam_controller_suspend(struct ssam_controller *ctrl);
280int ssam_controller_resume(struct ssam_controller *ctrl);
281
282int ssam_event_item_cache_init(void);
283void ssam_event_item_cache_destroy(void);
284
285#endif /* _SURFACE_AGGREGATOR_CONTROLLER_H */
drivers/platform/surface/aggregator/core.c+839−0
@@ -0,0 +1,839 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Surface Serial Hub (SSH) driver for communication with the Surface/System
4 * Aggregator Module (SSAM/SAM).
5 *
6 * Provides access to a SAM-over-SSH connected EC via a controller device.
7 * Handles communication via requests as well as enabling, disabling, and
8 * relaying of events.
9 *
10 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
11 */
12
13#include <linux/acpi.h>
14#include <linux/atomic.h>
15#include <linux/completion.h>
16#include <linux/gpio/consumer.h>
17#include <linux/kernel.h>
18#include <linux/kref.h>
19#include <linux/module.h>
20#include <linux/pm.h>
21#include <linux/serdev.h>
22#include <linux/sysfs.h>
23
24#include <linux/surface_aggregator/controller.h>
25
26#include "bus.h"
27#include "controller.h"
28
29#define CREATE_TRACE_POINTS
30#include "trace.h"
31
32
33/* -- Static controller reference. ------------------------------------------ */
34
35/*
36 * Main controller reference. The corresponding lock must be held while
37 * accessing (reading/writing) the reference.
38 */
39static struct ssam_controller *__ssam_controller;
40static DEFINE_SPINLOCK(__ssam_controller_lock);
41
42/**
43 * ssam_get_controller() - Get reference to SSAM controller.
44 *
45 * Returns a reference to the SSAM controller of the system or %NULL if there
46 * is none, it hasn't been set up yet, or it has already been unregistered.
47 * This function automatically increments the reference count of the
48 * controller, thus the calling party must ensure that ssam_controller_put()
49 * is called when it doesn't need the controller any more.
50 */
51struct ssam_controller *ssam_get_controller(void)
52{
53 struct ssam_controller *ctrl;
54
55 spin_lock(&__ssam_controller_lock);
56
57 ctrl = __ssam_controller;
58 if (!ctrl)
59 goto out;
60
61 if (WARN_ON(!kref_get_unless_zero(&ctrl->kref)))
62 ctrl = NULL;
63
64out:
65 spin_unlock(&__ssam_controller_lock);
66 return ctrl;
67}
68EXPORT_SYMBOL_GPL(ssam_get_controller);
69
70/**
71 * ssam_try_set_controller() - Try to set the main controller reference.
72 * @ctrl: The controller to which the reference should point.
73 *
74 * Set the main controller reference to the given pointer if the reference
75 * hasn't been set already.
76 *
77 * Return: Returns zero on success or %-EEXIST if the reference has already
78 * been set.
79 */
80static int ssam_try_set_controller(struct ssam_controller *ctrl)
81{
82 int status = 0;
83
84 spin_lock(&__ssam_controller_lock);
85 if (!__ssam_controller)
86 __ssam_controller = ctrl;
87 else
88 status = -EEXIST;
89 spin_unlock(&__ssam_controller_lock);
90
91 return status;
92}
93
94/**
95 * ssam_clear_controller() - Remove/clear the main controller reference.
96 *
97 * Clears the main controller reference, i.e. sets it to %NULL. This function
98 * should be called before the controller is shut down.
99 */
100static void ssam_clear_controller(void)
101{
102 spin_lock(&__ssam_controller_lock);
103 __ssam_controller = NULL;
104 spin_unlock(&__ssam_controller_lock);
105}
106
107/**
108 * ssam_client_link() - Link an arbitrary client device to the controller.
109 * @c: The controller to link to.
110 * @client: The client device.
111 *
112 * Link an arbitrary client device to the controller by creating a device link
113 * between it as consumer and the controller device as provider. This function
114 * can be used for non-SSAM devices (or SSAM devices not registered as child
115 * under the controller) to guarantee that the controller is valid for as long
116 * as the driver of the client device is bound, and that proper suspend and
117 * resume ordering is guaranteed.
118 *
119 * The device link does not have to be destructed manually. It is removed
120 * automatically once the driver of the client device unbinds.
121 *
122 * Return: Returns zero on success, %-ENODEV if the controller is not ready or
123 * going to be removed soon, or %-ENOMEM if the device link could not be
124 * created for other reasons.
125 */
126int ssam_client_link(struct ssam_controller *c, struct device *client)
127{
128 const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;
129 struct device_link *link;
130 struct device *ctrldev;
131
132 ssam_controller_statelock(c);
133
134 if (c->state != SSAM_CONTROLLER_STARTED) {
135 ssam_controller_stateunlock(c);
136 return -ENODEV;
137 }
138
139 ctrldev = ssam_controller_device(c);
140 if (!ctrldev) {
141 ssam_controller_stateunlock(c);
142 return -ENODEV;
143 }
144
145 link = device_link_add(client, ctrldev, flags);
146 if (!link) {
147 ssam_controller_stateunlock(c);
148 return -ENOMEM;
149 }
150
151 /*
152 * Return -ENODEV if supplier driver is on its way to be removed. In
153 * this case, the controller won't be around for much longer and the
154 * device link is not going to save us any more, as unbinding is
155 * already in progress.
156 */
157 if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) {
158 ssam_controller_stateunlock(c);
159 return -ENODEV;
160 }
161
162 ssam_controller_stateunlock(c);
163 return 0;
164}
165EXPORT_SYMBOL_GPL(ssam_client_link);
166
167/**
168 * ssam_client_bind() - Bind an arbitrary client device to the controller.
169 * @client: The client device.
170 *
171 * Link an arbitrary client device to the controller by creating a device link
172 * between it as consumer and the main controller device as provider. This
173 * function can be used for non-SSAM devices to guarantee that the controller
174 * returned by this function is valid for as long as the driver of the client
175 * device is bound, and that proper suspend and resume ordering is guaranteed.
176 *
177 * This function does essentially the same as ssam_client_link(), except that
178 * it first fetches the main controller reference, then creates the link, and
179 * finally returns this reference. Note that this function does not increment
180 * the reference counter of the controller, as, due to the link, the
181 * controller lifetime is assured as long as the driver of the client device
182 * is bound.
183 *
184 * It is not valid to use the controller reference obtained by this method
185 * outside of the driver bound to the client device at the time of calling
186 * this function, without first incrementing the reference count of the
187 * controller via ssam_controller_get(). Even after doing this, care must be
188 * taken that requests are only submitted and notifiers are only
189 * (un-)registered when the controller is active and not suspended. In other
190 * words: The device link only lives as long as the client driver is bound and
191 * any guarantees enforced by this link (e.g. active controller state) can
192 * only be relied upon as long as this link exists and may need to be enforced
193 * in other ways afterwards.
194 *
195 * The created device link does not have to be destructed manually. It is
196 * removed automatically once the driver of the client device unbinds.
197 *
198 * Return: Returns the controller on success, an error pointer with %-ENODEV
199 * if the controller is not present, not ready or going to be removed soon, or
200 * %-ENOMEM if the device link could not be created for other reasons.
201 */
202struct ssam_controller *ssam_client_bind(struct device *client)
203{
204 struct ssam_controller *c;
205 int status;
206
207 c = ssam_get_controller();
208 if (!c)
209 return ERR_PTR(-ENODEV);
210
211 status = ssam_client_link(c, client);
212
213 /*
214 * Note that we can drop our controller reference in both success and
215 * failure cases: On success, we have bound the controller lifetime
216 * inherently to the client driver lifetime, i.e. it the controller is
217 * now guaranteed to outlive the client driver. On failure, we're not
218 * going to use the controller any more.
219 */
220 ssam_controller_put(c);
221
222 return status >= 0 ? c : ERR_PTR(status);
223}
224EXPORT_SYMBOL_GPL(ssam_client_bind);
225
226
227/* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */
228
229static int ssam_receive_buf(struct serdev_device *dev, const unsigned char *buf,
230 size_t n)
231{
232 struct ssam_controller *ctrl;
233
234 ctrl = serdev_device_get_drvdata(dev);
235 return ssam_controller_receive_buf(ctrl, buf, n);
236}
237
238static void ssam_write_wakeup(struct serdev_device *dev)
239{
240 ssam_controller_write_wakeup(serdev_device_get_drvdata(dev));
241}
242
243static const struct serdev_device_ops ssam_serdev_ops = {
244 .receive_buf = ssam_receive_buf,
245 .write_wakeup = ssam_write_wakeup,
246};
247
248
249/* -- SysFS and misc. ------------------------------------------------------- */
250
251static int ssam_log_firmware_version(struct ssam_controller *ctrl)
252{
253 u32 version, a, b, c;
254 int status;
255
256 status = ssam_get_firmware_version(ctrl, &version);
257 if (status)
258 return status;
259
260 a = (version >> 24) & 0xff;
261 b = ((version >> 8) & 0xffff);
262 c = version & 0xff;
263
264 ssam_info(ctrl, "SAM firmware version: %u.%u.%u\n", a, b, c);
265 return 0;
266}
267
268static ssize_t firmware_version_show(struct device *dev,
269 struct device_attribute *attr, char *buf)
270{
271 struct ssam_controller *ctrl = dev_get_drvdata(dev);
272 u32 version, a, b, c;
273 int status;
274
275 status = ssam_get_firmware_version(ctrl, &version);
276 if (status < 0)
277 return status;
278
279 a = (version >> 24) & 0xff;
280 b = ((version >> 8) & 0xffff);
281 c = version & 0xff;
282
283 return sysfs_emit(buf, "%u.%u.%u\n", a, b, c);
284}
285static DEVICE_ATTR_RO(firmware_version);
286
287static struct attribute *ssam_sam_attrs[] = {
288 &dev_attr_firmware_version.attr,
289 NULL
290};
291
292static const struct attribute_group ssam_sam_group = {
293 .name = "sam",
294 .attrs = ssam_sam_attrs,
295};
296
297
298/* -- ACPI based device setup. ---------------------------------------------- */
299
300static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc,
301 void *ctx)
302{
303 struct serdev_device *serdev = ctx;
304 struct acpi_resource_common_serialbus *serial;
305 struct acpi_resource_uart_serialbus *uart;
306 bool flow_control;
307 int status = 0;
308
309 if (rsc->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
310 return AE_OK;
311
312 serial = &rsc->data.common_serial_bus;
313 if (serial->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
314 return AE_OK;
315
316 uart = &rsc->data.uart_serial_bus;
317
318 /* Set up serdev device. */
319 serdev_device_set_baudrate(serdev, uart->default_baud_rate);
320
321 /* serdev currently only supports RTSCTS flow control. */
322 if (uart->flow_control & (~((u8)ACPI_UART_FLOW_CONTROL_HW))) {
323 dev_warn(&serdev->dev, "setup: unsupported flow control (value: %#04x)\n",
324 uart->flow_control);
325 }
326
327 /* Set RTSCTS flow control. */
328 flow_control = uart->flow_control & ACPI_UART_FLOW_CONTROL_HW;
329 serdev_device_set_flow_control(serdev, flow_control);
330
331 /* serdev currently only supports EVEN/ODD parity. */
332 switch (uart->parity) {
333 case ACPI_UART_PARITY_NONE:
334 status = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
335 break;
336 case ACPI_UART_PARITY_EVEN:
337 status = serdev_device_set_parity(serdev, SERDEV_PARITY_EVEN);
338 break;
339 case ACPI_UART_PARITY_ODD:
340 status = serdev_device_set_parity(serdev, SERDEV_PARITY_ODD);
341 break;
342 default:
343 dev_warn(&serdev->dev, "setup: unsupported parity (value: %#04x)\n",
344 uart->parity);
345 break;
346 }
347
348 if (status) {
349 dev_err(&serdev->dev, "setup: failed to set parity (value: %#04x, error: %d)\n",
350 uart->parity, status);
351 return AE_ERROR;
352 }
353
354 /* We've found the resource and are done. */
355 return AE_CTRL_TERMINATE;
356}
357
358static acpi_status ssam_serdev_setup_via_acpi(acpi_handle handle,
359 struct serdev_device *serdev)
360{
361 return acpi_walk_resources(handle, METHOD_NAME__CRS,
362 ssam_serdev_setup_via_acpi_crs, serdev);
363}
364
365
366/* -- Power management. ----------------------------------------------------- */
367
368static void ssam_serial_hub_shutdown(struct device *dev)
369{
370 struct ssam_controller *c = dev_get_drvdata(dev);
371 int status;
372
373 /*
374 * Try to disable notifiers, signal display-off and D0-exit, ignore any
375 * errors.
376 *
377 * Note: It has not been established yet if this is actually
378 * necessary/useful for shutdown.
379 */
380
381 status = ssam_notifier_disable_registered(c);
382 if (status) {
383 ssam_err(c, "pm: failed to disable notifiers for shutdown: %d\n",
384 status);
385 }
386
387 status = ssam_ctrl_notif_display_off(c);
388 if (status)
389 ssam_err(c, "pm: display-off notification failed: %d\n", status);
390
391 status = ssam_ctrl_notif_d0_exit(c);
392 if (status)
393 ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
394}
395
396#ifdef CONFIG_PM_SLEEP
397
398static int ssam_serial_hub_pm_prepare(struct device *dev)
399{
400 struct ssam_controller *c = dev_get_drvdata(dev);
401 int status;
402
403 /*
404 * Try to signal display-off, This will quiesce events.
405 *
406 * Note: Signaling display-off/display-on should normally be done from
407 * some sort of display state notifier. As that is not available,
408 * signal it here.
409 */
410
411 status = ssam_ctrl_notif_display_off(c);
412 if (status)
413 ssam_err(c, "pm: display-off notification failed: %d\n", status);
414
415 return status;
416}
417
418static void ssam_serial_hub_pm_complete(struct device *dev)
419{
420 struct ssam_controller *c = dev_get_drvdata(dev);
421 int status;
422
423 /*
424 * Try to signal display-on. This will restore events.
425 *
426 * Note: Signaling display-off/display-on should normally be done from
427 * some sort of display state notifier. As that is not available,
428 * signal it here.
429 */
430
431 status = ssam_ctrl_notif_display_on(c);
432 if (status)
433 ssam_err(c, "pm: display-on notification failed: %d\n", status);
434}
435
436static int ssam_serial_hub_pm_suspend(struct device *dev)
437{
438 struct ssam_controller *c = dev_get_drvdata(dev);
439 int status;
440
441 /*
442 * Try to signal D0-exit, enable IRQ wakeup if specified. Abort on
443 * error.
444 */
445
446 status = ssam_ctrl_notif_d0_exit(c);
447 if (status) {
448 ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
449 goto err_notif;
450 }
451
452 status = ssam_irq_arm_for_wakeup(c);
453 if (status)
454 goto err_irq;
455
456 WARN_ON(ssam_controller_suspend(c));
457 return 0;
458
459err_irq:
460 ssam_ctrl_notif_d0_entry(c);
461err_notif:
462 ssam_ctrl_notif_display_on(c);
463 return status;
464}
465
466static int ssam_serial_hub_pm_resume(struct device *dev)
467{
468 struct ssam_controller *c = dev_get_drvdata(dev);
469 int status;
470
471 WARN_ON(ssam_controller_resume(c));
472
473 /*
474 * Try to disable IRQ wakeup (if specified) and signal D0-entry. In
475 * case of errors, log them and try to restore normal operation state
476 * as far as possible.
477 *
478 * Note: Signaling display-off/display-on should normally be done from
479 * some sort of display state notifier. As that is not available,
480 * signal it here.
481 */
482
483 ssam_irq_disarm_wakeup(c);
484
485 status = ssam_ctrl_notif_d0_entry(c);
486 if (status)
487 ssam_err(c, "pm: D0-entry notification failed: %d\n", status);
488
489 return 0;
490}
491
492static int ssam_serial_hub_pm_freeze(struct device *dev)
493{
494 struct ssam_controller *c = dev_get_drvdata(dev);
495 int status;
496
497 /*
498 * During hibernation image creation, we only have to ensure that the
499 * EC doesn't send us any events. This is done via the display-off
500 * and D0-exit notifications. Note that this sets up the wakeup IRQ
501 * on the EC side, however, we have disabled it by default on our side
502 * and won't enable it here.
503 *
504 * See ssam_serial_hub_poweroff() for more details on the hibernation
505 * process.
506 */
507
508 status = ssam_ctrl_notif_d0_exit(c);
509 if (status) {
510 ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
511 ssam_ctrl_notif_display_on(c);
512 return status;
513 }
514
515 WARN_ON(ssam_controller_suspend(c));
516 return 0;
517}
518
519static int ssam_serial_hub_pm_thaw(struct device *dev)
520{
521 struct ssam_controller *c = dev_get_drvdata(dev);
522 int status;
523
524 WARN_ON(ssam_controller_resume(c));
525
526 status = ssam_ctrl_notif_d0_entry(c);
527 if (status)
528 ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
529
530 return status;
531}
532
533static int ssam_serial_hub_pm_poweroff(struct device *dev)
534{
535 struct ssam_controller *c = dev_get_drvdata(dev);
536 int status;
537
538 /*
539 * When entering hibernation and powering off the system, the EC, at
540 * least on some models, may disable events. Without us taking care of
541 * that, this leads to events not being enabled/restored when the
542 * system resumes from hibernation, resulting SAM-HID subsystem devices
543 * (i.e. keyboard, touchpad) not working, AC-plug/AC-unplug events being
544 * gone, etc.
545 *
546 * To avoid these issues, we disable all registered events here (this is
547 * likely not actually required) and restore them during the drivers PM
548 * restore callback.
549 *
550 * Wakeup from the EC interrupt is not supported during hibernation,
551 * so don't arm the IRQ here.
552 */
553
554 status = ssam_notifier_disable_registered(c);
555 if (status) {
556 ssam_err(c, "pm: failed to disable notifiers for hibernation: %d\n",
557 status);
558 return status;
559 }
560
561 status = ssam_ctrl_notif_d0_exit(c);
562 if (status) {
563 ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
564 ssam_notifier_restore_registered(c);
565 return status;
566 }
567
568 WARN_ON(ssam_controller_suspend(c));
569 return 0;
570}
571
572static int ssam_serial_hub_pm_restore(struct device *dev)
573{
574 struct ssam_controller *c = dev_get_drvdata(dev);
575 int status;
576
577 /*
578 * Ignore but log errors, try to restore state as much as possible in
579 * case of failures. See ssam_serial_hub_poweroff() for more details on
580 * the hibernation process.
581 */
582
583 WARN_ON(ssam_controller_resume(c));
584
585 status = ssam_ctrl_notif_d0_entry(c);
586 if (status)
587 ssam_err(c, "pm: D0-entry notification failed: %d\n", status);
588
589 ssam_notifier_restore_registered(c);
590 return 0;
591}
592
593static const struct dev_pm_ops ssam_serial_hub_pm_ops = {
594 .prepare = ssam_serial_hub_pm_prepare,
595 .complete = ssam_serial_hub_pm_complete,
596 .suspend = ssam_serial_hub_pm_suspend,
597 .resume = ssam_serial_hub_pm_resume,
598 .freeze = ssam_serial_hub_pm_freeze,
599 .thaw = ssam_serial_hub_pm_thaw,
600 .poweroff = ssam_serial_hub_pm_poweroff,
601 .restore = ssam_serial_hub_pm_restore,
602};
603
604#else /* CONFIG_PM_SLEEP */
605
606static const struct dev_pm_ops ssam_serial_hub_pm_ops = { };
607
608#endif /* CONFIG_PM_SLEEP */
609
610
611/* -- Device/driver setup. -------------------------------------------------- */
612
613static const struct acpi_gpio_params gpio_ssam_wakeup_int = { 0, 0, false };
614static const struct acpi_gpio_params gpio_ssam_wakeup = { 1, 0, false };
615
616static const struct acpi_gpio_mapping ssam_acpi_gpios[] = {
617 { "ssam_wakeup-int-gpio", &gpio_ssam_wakeup_int, 1 },
618 { "ssam_wakeup-gpio", &gpio_ssam_wakeup, 1 },
619 { },
620};
621
622static int ssam_serial_hub_probe(struct serdev_device *serdev)
623{
624 struct ssam_controller *ctrl;
625 acpi_handle *ssh = ACPI_HANDLE(&serdev->dev);
626 acpi_status astatus;
627 int status;
628
629 if (gpiod_count(&serdev->dev, NULL) < 0)
630 return -ENODEV;
631
632 status = devm_acpi_dev_add_driver_gpios(&serdev->dev, ssam_acpi_gpios);
633 if (status)
634 return status;
635
636 /* Allocate controller. */
637 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
638 if (!ctrl)
639 return -ENOMEM;
640
641 /* Initialize controller. */
642 status = ssam_controller_init(ctrl, serdev);
643 if (status)
644 goto err_ctrl_init;
645
646 ssam_controller_lock(ctrl);
647
648 /* Set up serdev device. */
649 serdev_device_set_drvdata(serdev, ctrl);
650 serdev_device_set_client_ops(serdev, &ssam_serdev_ops);
651 status = serdev_device_open(serdev);
652 if (status)
653 goto err_devopen;
654
655 astatus = ssam_serdev_setup_via_acpi(ssh, serdev);
656 if (ACPI_FAILURE(astatus)) {
657 status = -ENXIO;
658 goto err_devinit;
659 }
660
661 /* Start controller. */
662 status = ssam_controller_start(ctrl);
663 if (status)
664 goto err_devinit;
665
666 ssam_controller_unlock(ctrl);
667
668 /*
669 * Initial SAM requests: Log version and notify default/init power
670 * states.
671 */
672 status = ssam_log_firmware_version(ctrl);
673 if (status)
674 goto err_initrq;
675
676 status = ssam_ctrl_notif_d0_entry(ctrl);
677 if (status)
678 goto err_initrq;
679
680 status = ssam_ctrl_notif_display_on(ctrl);
681 if (status)
682 goto err_initrq;
683
684 status = sysfs_create_group(&serdev->dev.kobj, &ssam_sam_group);
685 if (status)
686 goto err_initrq;
687
688 /* Set up IRQ. */
689 status = ssam_irq_setup(ctrl);
690 if (status)
691 goto err_irq;
692
693 /* Finally, set main controller reference. */
694 status = ssam_try_set_controller(ctrl);
695 if (WARN_ON(status)) /* Currently, we're the only provider. */
696 goto err_mainref;
697
698 /*
699 * TODO: The EC can wake up the system via the associated GPIO interrupt
700 * in multiple situations. One of which is the remaining battery
701 * capacity falling below a certain threshold. Normally, we should
702 * use the device_init_wakeup function, however, the EC also seems
703 * to have other reasons for waking up the system and it seems
704 * that Windows has additional checks whether the system should be
705 * resumed. In short, this causes some spurious unwanted wake-ups.
706 * For now let's thus default power/wakeup to false.
707 */
708 device_set_wakeup_capable(&serdev->dev, true);
709 acpi_walk_dep_device_list(ssh);
710
711 return 0;
712
713err_mainref:
714 ssam_irq_free(ctrl);
715err_irq:
716 sysfs_remove_group(&serdev->dev.kobj, &ssam_sam_group);
717err_initrq:
718 ssam_controller_lock(ctrl);
719 ssam_controller_shutdown(ctrl);
720err_devinit:
721 serdev_device_close(serdev);
722err_devopen:
723 ssam_controller_destroy(ctrl);
724 ssam_controller_unlock(ctrl);
725err_ctrl_init:
726 kfree(ctrl);
727 return status;
728}
729
730static void ssam_serial_hub_remove(struct serdev_device *serdev)
731{
732 struct ssam_controller *ctrl = serdev_device_get_drvdata(serdev);
733 int status;
734
735 /* Clear static reference so that no one else can get a new one. */
736 ssam_clear_controller();
737
738 /* Disable and free IRQ. */
739 ssam_irq_free(ctrl);
740
741 sysfs_remove_group(&serdev->dev.kobj, &ssam_sam_group);
742 ssam_controller_lock(ctrl);
743
744 /* Remove all client devices. */
745 ssam_controller_remove_clients(ctrl);
746
747 /* Act as if suspending to silence events. */
748 status = ssam_ctrl_notif_display_off(ctrl);
749 if (status) {
750 dev_err(&serdev->dev, "display-off notification failed: %d\n",
751 status);
752 }
753
754 status = ssam_ctrl_notif_d0_exit(ctrl);
755 if (status) {
756 dev_err(&serdev->dev, "D0-exit notification failed: %d\n",
757 status);
758 }
759
760 /* Shut down controller and remove serdev device reference from it. */
761 ssam_controller_shutdown(ctrl);
762
763 /* Shut down actual transport. */
764 serdev_device_wait_until_sent(serdev, 0);
765 serdev_device_close(serdev);
766
767 /* Drop our controller reference. */
768 ssam_controller_unlock(ctrl);
769 ssam_controller_put(ctrl);
770
771 device_set_wakeup_capable(&serdev->dev, false);
772}
773
774static const struct acpi_device_id ssam_serial_hub_match[] = {
775 { "MSHW0084", 0 },
776 { },
777};
778MODULE_DEVICE_TABLE(acpi, ssam_serial_hub_match);
779
780static struct serdev_device_driver ssam_serial_hub = {
781 .probe = ssam_serial_hub_probe,
782 .remove = ssam_serial_hub_remove,
783 .driver = {
784 .name = "surface_serial_hub",
785 .acpi_match_table = ssam_serial_hub_match,
786 .pm = &ssam_serial_hub_pm_ops,
787 .shutdown = ssam_serial_hub_shutdown,
788 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
789 },
790};
791
792
793/* -- Module setup. --------------------------------------------------------- */
794
795static int __init ssam_core_init(void)
796{
797 int status;
798
799 status = ssam_bus_register();
800 if (status)
801 goto err_bus;
802
803 status = ssh_ctrl_packet_cache_init();
804 if (status)
805 goto err_cpkg;
806
807 status = ssam_event_item_cache_init();
808 if (status)
809 goto err_evitem;
810
811 status = serdev_device_driver_register(&ssam_serial_hub);
812 if (status)
813 goto err_register;
814
815 return 0;
816
817err_register:
818 ssam_event_item_cache_destroy();
819err_evitem:
820 ssh_ctrl_packet_cache_destroy();
821err_cpkg:
822 ssam_bus_unregister();
823err_bus:
824 return status;
825}
826module_init(ssam_core_init);
827
828static void __exit ssam_core_exit(void)
829{
830 serdev_device_driver_unregister(&ssam_serial_hub);
831 ssam_event_item_cache_destroy();
832 ssh_ctrl_packet_cache_destroy();
833 ssam_bus_unregister();
834}
835module_exit(ssam_core_exit);
836
837MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
838MODULE_DESCRIPTION("Subsystem and Surface Serial Hub driver for Surface System Aggregator Module");
839MODULE_LICENSE("GPL");
drivers/platform/surface/aggregator/ssh_msgb.h+205−0
@@ -0,0 +1,205 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * SSH message builder functions.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
9#define _SURFACE_AGGREGATOR_SSH_MSGB_H
10
11#include <asm/unaligned.h>
12#include <linux/types.h>
13
14#include <linux/surface_aggregator/controller.h>
15#include <linux/surface_aggregator/serial_hub.h>
16
17/**
18 * struct msgbuf - Buffer struct to construct SSH messages.
19 * @begin: Pointer to the beginning of the allocated buffer space.
20 * @end: Pointer to the end (one past last element) of the allocated buffer
21 * space.
22 * @ptr: Pointer to the first free element in the buffer.
23 */
24struct msgbuf {
25 u8 *begin;
26 u8 *end;
27 u8 *ptr;
28};
29
30/**
31 * msgb_init() - Initialize the given message buffer struct.
32 * @msgb: The buffer struct to initialize
33 * @ptr: Pointer to the underlying memory by which the buffer will be backed.
34 * @cap: Size of the underlying memory.
35 *
36 * Initialize the given message buffer struct using the provided memory as
37 * backing.
38 */
39static inline void msgb_init(struct msgbuf *msgb, u8 *ptr, size_t cap)
40{
41 msgb->begin = ptr;
42 msgb->end = ptr + cap;
43 msgb->ptr = ptr;
44}
45
46/**
47 * msgb_bytes_used() - Return the current number of bytes used in the buffer.
48 * @msgb: The message buffer.
49 */
50static inline size_t msgb_bytes_used(const struct msgbuf *msgb)
51{
52 return msgb->ptr - msgb->begin;
53}
54
55static inline void __msgb_push_u8(struct msgbuf *msgb, u8 value)
56{
57 *msgb->ptr = value;
58 msgb->ptr += sizeof(u8);
59}
60
61static inline void __msgb_push_u16(struct msgbuf *msgb, u16 value)
62{
63 put_unaligned_le16(value, msgb->ptr);
64 msgb->ptr += sizeof(u16);
65}
66
67/**
68 * msgb_push_u16() - Push a u16 value to the buffer.
69 * @msgb: The message buffer.
70 * @value: The value to push to the buffer.
71 */
72static inline void msgb_push_u16(struct msgbuf *msgb, u16 value)
73{
74 if (WARN_ON(msgb->ptr + sizeof(u16) > msgb->end))
75 return;
76
77 __msgb_push_u16(msgb, value);
78}
79
80/**
81 * msgb_push_syn() - Push SSH SYN bytes to the buffer.
82 * @msgb: The message buffer.
83 */
84static inline void msgb_push_syn(struct msgbuf *msgb)
85{
86 msgb_push_u16(msgb, SSH_MSG_SYN);
87}
88
89/**
90 * msgb_push_buf() - Push raw data to the buffer.
91 * @msgb: The message buffer.
92 * @buf: The data to push to the buffer.
93 * @len: The length of the data to push to the buffer.
94 */
95static inline void msgb_push_buf(struct msgbuf *msgb, const u8 *buf, size_t len)
96{
97 msgb->ptr = memcpy(msgb->ptr, buf, len) + len;
98}
99
100/**
101 * msgb_push_crc() - Compute CRC and push it to the buffer.
102 * @msgb: The message buffer.
103 * @buf: The data for which the CRC should be computed.
104 * @len: The length of the data for which the CRC should be computed.
105 */
106static inline void msgb_push_crc(struct msgbuf *msgb, const u8 *buf, size_t len)
107{
108 msgb_push_u16(msgb, ssh_crc(buf, len));
109}
110
111/**
112 * msgb_push_frame() - Push a SSH message frame header to the buffer.
113 * @msgb: The message buffer
114 * @ty: The type of the frame.
115 * @len: The length of the payload of the frame.
116 * @seq: The sequence ID of the frame/packet.
117 */
118static inline void msgb_push_frame(struct msgbuf *msgb, u8 ty, u16 len, u8 seq)
119{
120 u8 *const begin = msgb->ptr;
121
122 if (WARN_ON(msgb->ptr + sizeof(struct ssh_frame) > msgb->end))
123 return;
124
125 __msgb_push_u8(msgb, ty); /* Frame type. */
126 __msgb_push_u16(msgb, len); /* Frame payload length. */
127 __msgb_push_u8(msgb, seq); /* Frame sequence ID. */
128
129 msgb_push_crc(msgb, begin, msgb->ptr - begin);
130}
131
132/**
133 * msgb_push_ack() - Push a SSH ACK frame to the buffer.
134 * @msgb: The message buffer
135 * @seq: The sequence ID of the frame/packet to be ACKed.
136 */
137static inline void msgb_push_ack(struct msgbuf *msgb, u8 seq)
138{
139 /* SYN. */
140 msgb_push_syn(msgb);
141
142 /* ACK-type frame + CRC. */
143 msgb_push_frame(msgb, SSH_FRAME_TYPE_ACK, 0x00, seq);
144
145 /* Payload CRC (ACK-type frames do not have a payload). */
146 msgb_push_crc(msgb, msgb->ptr, 0);
147}
148
149/**
150 * msgb_push_nak() - Push a SSH NAK frame to the buffer.
151 * @msgb: The message buffer
152 */
153static inline void msgb_push_nak(struct msgbuf *msgb)
154{
155 /* SYN. */
156 msgb_push_syn(msgb);
157
158 /* NAK-type frame + CRC. */
159 msgb_push_frame(msgb, SSH_FRAME_TYPE_NAK, 0x00, 0x00);
160
161 /* Payload CRC (ACK-type frames do not have a payload). */
162 msgb_push_crc(msgb, msgb->ptr, 0);
163}
164
165/**
166 * msgb_push_cmd() - Push a SSH command frame with payload to the buffer.
167 * @msgb: The message buffer.
168 * @seq: The sequence ID (SEQ) of the frame/packet.
169 * @rqid: The request ID (RQID) of the request contained in the frame.
170 * @rqst: The request to wrap in the frame.
171 */
172static inline void msgb_push_cmd(struct msgbuf *msgb, u8 seq, u16 rqid,
173 const struct ssam_request *rqst)
174{
175 const u8 type = SSH_FRAME_TYPE_DATA_SEQ;
176 u8 *cmd;
177
178 /* SYN. */
179 msgb_push_syn(msgb);
180
181 /* Command frame + CRC. */
182 msgb_push_frame(msgb, type, sizeof(struct ssh_command) + rqst->length, seq);
183
184 /* Frame payload: Command struct + payload. */
185 if (WARN_ON(msgb->ptr + sizeof(struct ssh_command) > msgb->end))
186 return;
187
188 cmd = msgb->ptr;
189
190 __msgb_push_u8(msgb, SSH_PLD_TYPE_CMD); /* Payload type. */
191 __msgb_push_u8(msgb, rqst->target_category); /* Target category. */
192 __msgb_push_u8(msgb, rqst->target_id); /* Target ID (out). */
193 __msgb_push_u8(msgb, 0x00); /* Target ID (in). */
194 __msgb_push_u8(msgb, rqst->instance_id); /* Instance ID. */
195 __msgb_push_u16(msgb, rqid); /* Request ID. */
196 __msgb_push_u8(msgb, rqst->command_id); /* Command ID. */
197
198 /* Command payload. */
199 msgb_push_buf(msgb, rqst->payload, rqst->length);
200
201 /* CRC for command struct + payload. */
202 msgb_push_crc(msgb, cmd, msgb->ptr - cmd);
203}
204
205#endif /* _SURFACE_AGGREGATOR_SSH_MSGB_H */
drivers/platform/surface/aggregator/ssh_packet_layer.c+2074−0
@@ -0,0 +1,2074 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * SSH packet transport layer.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#include <asm/unaligned.h>
9#include <linux/atomic.h>
10#include <linux/error-injection.h>
11#include <linux/jiffies.h>
12#include <linux/kfifo.h>
13#include <linux/kref.h>
14#include <linux/kthread.h>
15#include <linux/ktime.h>
16#include <linux/limits.h>
17#include <linux/list.h>
18#include <linux/lockdep.h>
19#include <linux/serdev.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h>
22#include <linux/workqueue.h>
23
24#include <linux/surface_aggregator/serial_hub.h>
25
26#include "ssh_msgb.h"
27#include "ssh_packet_layer.h"
28#include "ssh_parser.h"
29
30#include "trace.h"
31
32/*
33 * To simplify reasoning about the code below, we define a few concepts. The
34 * system below is similar to a state-machine for packets, however, there are
35 * too many states to explicitly write them down. To (somewhat) manage the
36 * states and packets we rely on flags, reference counting, and some simple
37 * concepts. State transitions are triggered by actions.
38 *
39 * >> Actions <<
40 *
41 * - submit
42 * - transmission start (process next item in queue)
43 * - transmission finished (guaranteed to never be parallel to transmission
44 * start)
45 * - ACK received
46 * - NAK received (this is equivalent to issuing re-submit for all pending
47 * packets)
48 * - timeout (this is equivalent to re-issuing a submit or canceling)
49 * - cancel (non-pending and pending)
50 *
51 * >> Data Structures, Packet Ownership, General Overview <<
52 *
53 * The code below employs two main data structures: The packet queue,
54 * containing all packets scheduled for transmission, and the set of pending
55 * packets, containing all packets awaiting an ACK.
56 *
57 * Shared ownership of a packet is controlled via reference counting. Inside
58 * the transport system are a total of five packet owners:
59 *
60 * - the packet queue,
61 * - the pending set,
62 * - the transmitter thread,
63 * - the receiver thread (via ACKing), and
64 * - the timeout work item.
65 *
66 * Normal operation is as follows: The initial reference of the packet is
67 * obtained by submitting the packet and queuing it. The receiver thread takes
68 * packets from the queue. By doing this, it does not increment the refcount
69 * but takes over the reference (removing it from the queue). If the packet is
70 * sequenced (i.e. needs to be ACKed by the client), the transmitter thread
71 * sets-up the timeout and adds the packet to the pending set before starting
72 * to transmit it. As the timeout is handled by a reaper task, no additional
73 * reference for it is needed. After the transmit is done, the reference held
74 * by the transmitter thread is dropped. If the packet is unsequenced (i.e.
75 * does not need an ACK), the packet is completed by the transmitter thread
76 * before dropping that reference.
77 *
78 * On receival of an ACK, the receiver thread removes and obtains the
79 * reference to the packet from the pending set. The receiver thread will then
80 * complete the packet and drop its reference.
81 *
82 * On receival of a NAK, the receiver thread re-submits all currently pending
83 * packets.
84 *
85 * Packet timeouts are detected by the timeout reaper. This is a task,
86 * scheduled depending on the earliest packet timeout expiration date,
87 * checking all currently pending packets if their timeout has expired. If the
88 * timeout of a packet has expired, it is re-submitted and the number of tries
89 * of this packet is incremented. If this number reaches its limit, the packet
90 * will be completed with a failure.
91 *
92 * On transmission failure (such as repeated packet timeouts), the completion
93 * callback is immediately run by on thread on which the error was detected.
94 *
95 * To ensure that a packet eventually leaves the system it is marked as
96 * "locked" directly before it is going to be completed or when it is
97 * canceled. Marking a packet as "locked" has the effect that passing and
98 * creating new references of the packet is disallowed. This means that the
99 * packet cannot be added to the queue, the pending set, and the timeout, or
100 * be picked up by the transmitter thread or receiver thread. To remove a
101 * packet from the system it has to be marked as locked and subsequently all
102 * references from the data structures (queue, pending) have to be removed.
103 * References held by threads will eventually be dropped automatically as
104 * their execution progresses.
105 *
106 * Note that the packet completion callback is, in case of success and for a
107 * sequenced packet, guaranteed to run on the receiver thread, thus providing
108 * a way to reliably identify responses to the packet. The packet completion
109 * callback is only run once and it does not indicate that the packet has
110 * fully left the system (for this, one should rely on the release method,
111 * triggered when the reference count of the packet reaches zero). In case of
112 * re-submission (and with somewhat unlikely timing), it may be possible that
113 * the packet is being re-transmitted while the completion callback runs.
114 * Completion will occur both on success and internal error, as well as when
115 * the packet is canceled.
116 *
117 * >> Flags <<
118 *
119 * Flags are used to indicate the state and progression of a packet. Some flags
120 * have stricter guarantees than other:
121 *
122 * - locked
123 * Indicates if the packet is locked. If the packet is locked, passing and/or
124 * creating additional references to the packet is forbidden. The packet thus
125 * may not be queued, dequeued, or removed or added to the pending set. Note
126 * that the packet state flags may still change (e.g. it may be marked as
127 * ACKed, transmitted, ...).
128 *
129 * - completed
130 * Indicates if the packet completion callback has been executed or is about
131 * to be executed. This flag is used to ensure that the packet completion
132 * callback is only run once.
133 *
134 * - queued
135 * Indicates if a packet is present in the submission queue or not. This flag
136 * must only be modified with the queue lock held, and must be coherent to the
137 * presence of the packet in the queue.
138 *
139 * - pending
140 * Indicates if a packet is present in the set of pending packets or not.
141 * This flag must only be modified with the pending lock held, and must be
142 * coherent to the presence of the packet in the pending set.
143 *
144 * - transmitting
145 * Indicates if the packet is currently transmitting. In case of
146 * re-transmissions, it is only safe to wait on the "transmitted" completion
147 * after this flag has been set. The completion will be set both in success
148 * and error case.
149 *
150 * - transmitted
151 * Indicates if the packet has been transmitted. This flag is not cleared by
152 * the system, thus it indicates the first transmission only.
153 *
154 * - acked
155 * Indicates if the packet has been acknowledged by the client. There are no
156 * other guarantees given. For example, the packet may still be canceled
157 * and/or the completion may be triggered an error even though this bit is
158 * set. Rely on the status provided to the completion callback instead.
159 *
160 * - canceled
161 * Indicates if the packet has been canceled from the outside. There are no
162 * other guarantees given. Specifically, the packet may be completed by
163 * another part of the system before the cancellation attempts to complete it.
164 *
165 * >> General Notes <<
166 *
167 * - To avoid deadlocks, if both queue and pending locks are required, the
168 * pending lock must be acquired before the queue lock.
169 *
170 * - The packet priority must be accessed only while holding the queue lock.
171 *
172 * - The packet timestamp must be accessed only while holding the pending
173 * lock.
174 */
175
176/*
177 * SSH_PTL_MAX_PACKET_TRIES - Maximum transmission attempts for packet.
178 *
179 * Maximum number of transmission attempts per sequenced packet in case of
180 * time-outs. Must be smaller than 16. If the packet times out after this
181 * amount of tries, the packet will be completed with %-ETIMEDOUT as status
182 * code.
183 */
184#define SSH_PTL_MAX_PACKET_TRIES 3
185
186/*
187 * SSH_PTL_TX_TIMEOUT - Packet transmission timeout.
188 *
189 * Timeout in jiffies for packet transmission via the underlying serial
190 * device. If transmitting the packet takes longer than this timeout, the
191 * packet will be completed with -ETIMEDOUT. It will not be re-submitted.
192 */
193#define SSH_PTL_TX_TIMEOUT HZ
194
195/*
196 * SSH_PTL_PACKET_TIMEOUT - Packet response timeout.
197 *
198 * Timeout as ktime_t delta for ACKs. If we have not received an ACK in this
199 * time-frame after starting transmission, the packet will be re-submitted.
200 */
201#define SSH_PTL_PACKET_TIMEOUT ms_to_ktime(1000)
202
203/*
204 * SSH_PTL_PACKET_TIMEOUT_RESOLUTION - Packet timeout granularity.
205 *
206 * Time-resolution for timeouts. Should be larger than one jiffy to avoid
207 * direct re-scheduling of reaper work_struct.
208 */
209#define SSH_PTL_PACKET_TIMEOUT_RESOLUTION ms_to_ktime(max(2000 / HZ, 50))
210
211/*
212 * SSH_PTL_MAX_PENDING - Maximum number of pending packets.
213 *
214 * Maximum number of sequenced packets concurrently waiting for an ACK.
215 * Packets marked as blocking will not be transmitted while this limit is
216 * reached.
217 */
218#define SSH_PTL_MAX_PENDING 1
219
220/*
221 * SSH_PTL_RX_BUF_LEN - Evaluation-buffer size in bytes.
222 */
223#define SSH_PTL_RX_BUF_LEN 4096
224
225/*
226 * SSH_PTL_RX_FIFO_LEN - Fifo input-buffer size in bytes.
227 */
228#define SSH_PTL_RX_FIFO_LEN 4096
229
230#ifdef CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION
231
232/**
233 * ssh_ptl_should_drop_ack_packet() - Error injection hook to drop ACK packets.
234 *
235 * Useful to test detection and handling of automated re-transmits by the EC.
236 * Specifically of packets that the EC considers not-ACKed but the driver
237 * already considers ACKed (due to dropped ACK). In this case, the EC
238 * re-transmits the packet-to-be-ACKed and the driver should detect it as
239 * duplicate/already handled. Note that the driver should still send an ACK
240 * for the re-transmitted packet.
241 */
242static noinline bool ssh_ptl_should_drop_ack_packet(void)
243{
244 return false;
245}
246ALLOW_ERROR_INJECTION(ssh_ptl_should_drop_ack_packet, TRUE);
247
248/**
249 * ssh_ptl_should_drop_nak_packet() - Error injection hook to drop NAK packets.
250 *
251 * Useful to test/force automated (timeout-based) re-transmit by the EC.
252 * Specifically, packets that have not reached the driver completely/with valid
253 * checksums. Only useful in combination with receival of (injected) bad data.
254 */
255static noinline bool ssh_ptl_should_drop_nak_packet(void)
256{
257 return false;
258}
259ALLOW_ERROR_INJECTION(ssh_ptl_should_drop_nak_packet, TRUE);
260
261/**
262 * ssh_ptl_should_drop_dsq_packet() - Error injection hook to drop sequenced
263 * data packet.
264 *
265 * Useful to test re-transmit timeout of the driver. If the data packet has not
266 * been ACKed after a certain time, the driver should re-transmit the packet up
267 * to limited number of times defined in SSH_PTL_MAX_PACKET_TRIES.
268 */
269static noinline bool ssh_ptl_should_drop_dsq_packet(void)
270{
271 return false;
272}
273ALLOW_ERROR_INJECTION(ssh_ptl_should_drop_dsq_packet, TRUE);
274
275/**
276 * ssh_ptl_should_fail_write() - Error injection hook to make
277 * serdev_device_write() fail.
278 *
279 * Hook to simulate errors in serdev_device_write when transmitting packets.
280 */
281static noinline int ssh_ptl_should_fail_write(void)
282{
283 return 0;
284}
285ALLOW_ERROR_INJECTION(ssh_ptl_should_fail_write, ERRNO);
286
287/**
288 * ssh_ptl_should_corrupt_tx_data() - Error injection hook to simulate invalid
289 * data being sent to the EC.
290 *
291 * Hook to simulate corrupt/invalid data being sent from host (driver) to EC.
292 * Causes the packet data to be actively corrupted by overwriting it with
293 * pre-defined values, such that it becomes invalid, causing the EC to respond
294 * with a NAK packet. Useful to test handling of NAK packets received by the
295 * driver.
296 */
297static noinline bool ssh_ptl_should_corrupt_tx_data(void)
298{
299 return false;
300}
301ALLOW_ERROR_INJECTION(ssh_ptl_should_corrupt_tx_data, TRUE);
302
303/**
304 * ssh_ptl_should_corrupt_rx_syn() - Error injection hook to simulate invalid
305 * data being sent by the EC.
306 *
307 * Hook to simulate invalid SYN bytes, i.e. an invalid start of messages and
308 * test handling thereof in the driver.
309 */
310static noinline bool ssh_ptl_should_corrupt_rx_syn(void)
311{
312 return false;
313}
314ALLOW_ERROR_INJECTION(ssh_ptl_should_corrupt_rx_syn, TRUE);
315
316/**
317 * ssh_ptl_should_corrupt_rx_data() - Error injection hook to simulate invalid
318 * data being sent by the EC.
319 *
320 * Hook to simulate invalid data/checksum of the message frame and test handling
321 * thereof in the driver.
322 */
323static noinline bool ssh_ptl_should_corrupt_rx_data(void)
324{
325 return false;
326}
327ALLOW_ERROR_INJECTION(ssh_ptl_should_corrupt_rx_data, TRUE);
328
329static bool __ssh_ptl_should_drop_ack_packet(struct ssh_packet *packet)
330{
331 if (likely(!ssh_ptl_should_drop_ack_packet()))
332 return false;
333
334 trace_ssam_ei_tx_drop_ack_packet(packet);
335 ptl_info(packet->ptl, "packet error injection: dropping ACK packet %p\n",
336 packet);
337
338 return true;
339}
340
341static bool __ssh_ptl_should_drop_nak_packet(struct ssh_packet *packet)
342{
343 if (likely(!ssh_ptl_should_drop_nak_packet()))
344 return false;
345
346 trace_ssam_ei_tx_drop_nak_packet(packet);
347 ptl_info(packet->ptl, "packet error injection: dropping NAK packet %p\n",
348 packet);
349
350 return true;
351}
352
353static bool __ssh_ptl_should_drop_dsq_packet(struct ssh_packet *packet)
354{
355 if (likely(!ssh_ptl_should_drop_dsq_packet()))
356 return false;
357
358 trace_ssam_ei_tx_drop_dsq_packet(packet);
359 ptl_info(packet->ptl,
360 "packet error injection: dropping sequenced data packet %p\n",
361 packet);
362
363 return true;
364}
365
366static bool ssh_ptl_should_drop_packet(struct ssh_packet *packet)
367{
368 /* Ignore packets that don't carry any data (i.e. flush). */
369 if (!packet->data.ptr || !packet->data.len)
370 return false;
371
372 switch (packet->data.ptr[SSH_MSGOFFSET_FRAME(type)]) {
373 case SSH_FRAME_TYPE_ACK:
374 return __ssh_ptl_should_drop_ack_packet(packet);
375
376 case SSH_FRAME_TYPE_NAK:
377 return __ssh_ptl_should_drop_nak_packet(packet);
378
379 case SSH_FRAME_TYPE_DATA_SEQ:
380 return __ssh_ptl_should_drop_dsq_packet(packet);
381
382 default:
383 return false;
384 }
385}
386
387static int ssh_ptl_write_buf(struct ssh_ptl *ptl, struct ssh_packet *packet,
388 const unsigned char *buf, size_t count)
389{
390 int status;
391
392 status = ssh_ptl_should_fail_write();
393 if (unlikely(status)) {
394 trace_ssam_ei_tx_fail_write(packet, status);
395 ptl_info(packet->ptl,
396 "packet error injection: simulating transmit error %d, packet %p\n",
397 status, packet);
398
399 return status;
400 }
401
402 return serdev_device_write_buf(ptl->serdev, buf, count);
403}
404
405static void ssh_ptl_tx_inject_invalid_data(struct ssh_packet *packet)
406{
407 /* Ignore packets that don't carry any data (i.e. flush). */
408 if (!packet->data.ptr || !packet->data.len)
409 return;
410
411 /* Only allow sequenced data packets to be modified. */
412 if (packet->data.ptr[SSH_MSGOFFSET_FRAME(type)] != SSH_FRAME_TYPE_DATA_SEQ)
413 return;
414
415 if (likely(!ssh_ptl_should_corrupt_tx_data()))
416 return;
417
418 trace_ssam_ei_tx_corrupt_data(packet);
419 ptl_info(packet->ptl,
420 "packet error injection: simulating invalid transmit data on packet %p\n",
421 packet);
422
423 /*
424 * NB: The value 0xb3 has been chosen more or less randomly so that it
425 * doesn't have any (major) overlap with the SYN bytes (aa 55) and is
426 * non-trivial (i.e. non-zero, non-0xff).
427 */
428 memset(packet->data.ptr, 0xb3, packet->data.len);
429}
430
431static void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl,
432 struct ssam_span *data)
433{
434 struct ssam_span frame;
435
436 /* Check if there actually is something to corrupt. */
437 if (!sshp_find_syn(data, &frame))
438 return;
439
440 if (likely(!ssh_ptl_should_corrupt_rx_syn()))
441 return;
442
443 trace_ssam_ei_rx_corrupt_syn(data->len);
444
445 data->ptr[1] = 0xb3; /* Set second byte of SYN to "random" value. */
446}
447
448static void ssh_ptl_rx_inject_invalid_data(struct ssh_ptl *ptl,
449 struct ssam_span *frame)
450{
451 size_t payload_len, message_len;
452 struct ssh_frame *sshf;
453
454 /* Ignore incomplete messages, will get handled once it's complete. */
455 if (frame->len < SSH_MESSAGE_LENGTH(0))
456 return;
457
458 /* Ignore incomplete messages, part 2. */
459 payload_len = get_unaligned_le16(&frame->ptr[SSH_MSGOFFSET_FRAME(len)]);
460 message_len = SSH_MESSAGE_LENGTH(payload_len);
461 if (frame->len < message_len)
462 return;
463
464 if (likely(!ssh_ptl_should_corrupt_rx_data()))
465 return;
466
467 sshf = (struct ssh_frame *)&frame->ptr[SSH_MSGOFFSET_FRAME(type)];
468 trace_ssam_ei_rx_corrupt_data(sshf);
469
470 /*
471 * Flip bits in first byte of payload checksum. This is basically
472 * equivalent to a payload/frame data error without us having to worry
473 * about (the, arguably pretty small, probability of) accidental
474 * checksum collisions.
475 */
476 frame->ptr[frame->len - 2] = ~frame->ptr[frame->len - 2];
477}
478
479#else /* CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION */
480
481static inline bool ssh_ptl_should_drop_packet(struct ssh_packet *packet)
482{
483 return false;
484}
485
486static inline int ssh_ptl_write_buf(struct ssh_ptl *ptl,
487 struct ssh_packet *packet,
488 const unsigned char *buf,
489 size_t count)
490{
491 return serdev_device_write_buf(ptl->serdev, buf, count);
492}
493
494static inline void ssh_ptl_tx_inject_invalid_data(struct ssh_packet *packet)
495{
496}
497
498static inline void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl,
499 struct ssam_span *data)
500{
501}
502
503static inline void ssh_ptl_rx_inject_invalid_data(struct ssh_ptl *ptl,
504 struct ssam_span *frame)
505{
506}
507
508#endif /* CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION */
509
510static void __ssh_ptl_packet_release(struct kref *kref)
511{
512 struct ssh_packet *p = container_of(kref, struct ssh_packet, refcnt);
513
514 trace_ssam_packet_release(p);
515
516 ptl_dbg_cond(p->ptl, "ptl: releasing packet %p\n", p);
517 p->ops->release(p);
518}
519
520/**
521 * ssh_packet_get() - Increment reference count of packet.
522 * @packet: The packet to increment the reference count of.
523 *
524 * Increments the reference count of the given packet. See ssh_packet_put()
525 * for the counter-part of this function.
526 *
527 * Return: Returns the packet provided as input.
528 */
529struct ssh_packet *ssh_packet_get(struct ssh_packet *packet)
530{
531 if (packet)
532 kref_get(&packet->refcnt);
533 return packet;
534}
535EXPORT_SYMBOL_GPL(ssh_packet_get);
536
537/**
538 * ssh_packet_put() - Decrement reference count of packet.
539 * @packet: The packet to decrement the reference count of.
540 *
541 * If the reference count reaches zero, the ``release`` callback specified in
542 * the packet's &struct ssh_packet_ops, i.e. ``packet->ops->release``, will be
543 * called.
544 *
545 * See ssh_packet_get() for the counter-part of this function.
546 */
547void ssh_packet_put(struct ssh_packet *packet)
548{
549 if (packet)
550 kref_put(&packet->refcnt, __ssh_ptl_packet_release);
551}
552EXPORT_SYMBOL_GPL(ssh_packet_put);
553
554static u8 ssh_packet_get_seq(struct ssh_packet *packet)
555{
556 return packet->data.ptr[SSH_MSGOFFSET_FRAME(seq)];
557}
558
559/**
560 * ssh_packet_init() - Initialize SSH packet.
561 * @packet: The packet to initialize.
562 * @type: Type-flags of the packet.
563 * @priority: Priority of the packet. See SSH_PACKET_PRIORITY() for details.
564 * @ops: Packet operations.
565 *
566 * Initializes the given SSH packet. Sets the transmission buffer pointer to
567 * %NULL and the transmission buffer length to zero. For data-type packets,
568 * this buffer has to be set separately via ssh_packet_set_data() before
569 * submission, and must contain a valid SSH message, i.e. frame with optional
570 * payload of any type.
571 */
572void ssh_packet_init(struct ssh_packet *packet, unsigned long type,
573 u8 priority, const struct ssh_packet_ops *ops)
574{
575 kref_init(&packet->refcnt);
576
577 packet->ptl = NULL;
578 INIT_LIST_HEAD(&packet->queue_node);
579 INIT_LIST_HEAD(&packet->pending_node);
580
581 packet->state = type & SSH_PACKET_FLAGS_TY_MASK;
582 packet->priority = priority;
583 packet->timestamp = KTIME_MAX;
584
585 packet->data.ptr = NULL;
586 packet->data.len = 0;
587
588 packet->ops = ops;
589}
590
591static struct kmem_cache *ssh_ctrl_packet_cache;
592
593/**
594 * ssh_ctrl_packet_cache_init() - Initialize the control packet cache.
595 */
596int ssh_ctrl_packet_cache_init(void)
597{
598 const unsigned int size = sizeof(struct ssh_packet) + SSH_MSG_LEN_CTRL;
599 const unsigned int align = __alignof__(struct ssh_packet);
600 struct kmem_cache *cache;
601
602 cache = kmem_cache_create("ssam_ctrl_packet", size, align, 0, NULL);
603 if (!cache)
604 return -ENOMEM;
605
606 ssh_ctrl_packet_cache = cache;
607 return 0;
608}
609
610/**
611 * ssh_ctrl_packet_cache_destroy() - Deinitialize the control packet cache.
612 */
613void ssh_ctrl_packet_cache_destroy(void)
614{
615 kmem_cache_destroy(ssh_ctrl_packet_cache);
616 ssh_ctrl_packet_cache = NULL;
617}
618
619/**
620 * ssh_ctrl_packet_alloc() - Allocate packet from control packet cache.
621 * @packet: Where the pointer to the newly allocated packet should be stored.
622 * @buffer: The buffer corresponding to this packet.
623 * @flags: Flags used for allocation.
624 *
625 * Allocates a packet and corresponding transport buffer from the control
626 * packet cache. Sets the packet's buffer reference to the allocated buffer.
627 * The packet must be freed via ssh_ctrl_packet_free(), which will also free
628 * the corresponding buffer. The corresponding buffer must not be freed
629 * separately. Intended to be used with %ssh_ptl_ctrl_packet_ops as packet
630 * operations.
631 *
632 * Return: Returns zero on success, %-ENOMEM if the allocation failed.
633 */
634static int ssh_ctrl_packet_alloc(struct ssh_packet **packet,
635 struct ssam_span *buffer, gfp_t flags)
636{
637 *packet = kmem_cache_alloc(ssh_ctrl_packet_cache, flags);
638 if (!*packet)
639 return -ENOMEM;
640
641 buffer->ptr = (u8 *)(*packet + 1);
642 buffer->len = SSH_MSG_LEN_CTRL;
643
644 trace_ssam_ctrl_packet_alloc(*packet, buffer->len);
645 return 0;
646}
647
648/**
649 * ssh_ctrl_packet_free() - Free packet allocated from control packet cache.
650 * @p: The packet to free.
651 */
652static void ssh_ctrl_packet_free(struct ssh_packet *p)
653{
654 trace_ssam_ctrl_packet_free(p);
655 kmem_cache_free(ssh_ctrl_packet_cache, p);
656}
657
658static const struct ssh_packet_ops ssh_ptl_ctrl_packet_ops = {
659 .complete = NULL,
660 .release = ssh_ctrl_packet_free,
661};
662
663static void ssh_ptl_timeout_reaper_mod(struct ssh_ptl *ptl, ktime_t now,
664 ktime_t expires)
665{
666 unsigned long delta = msecs_to_jiffies(ktime_ms_delta(expires, now));
667 ktime_t aexp = ktime_add(expires, SSH_PTL_PACKET_TIMEOUT_RESOLUTION);
668
669 spin_lock(&ptl->rtx_timeout.lock);
670
671 /* Re-adjust / schedule reaper only if it is above resolution delta. */
672 if (ktime_before(aexp, ptl->rtx_timeout.expires)) {
673 ptl->rtx_timeout.expires = expires;
674 mod_delayed_work(system_wq, &ptl->rtx_timeout.reaper, delta);
675 }
676
677 spin_unlock(&ptl->rtx_timeout.lock);
678}
679
680/* Must be called with queue lock held. */
681static void ssh_packet_next_try(struct ssh_packet *p)
682{
683 u8 base = ssh_packet_priority_get_base(p->priority);
684 u8 try = ssh_packet_priority_get_try(p->priority);
685
686 lockdep_assert_held(&p->ptl->queue.lock);
687
688 /*
689 * Ensure that we write the priority in one go via WRITE_ONCE() so we
690 * can access it via READ_ONCE() for tracing. Note that other access
691 * is guarded by the queue lock, so no need to use READ_ONCE() there.
692 */
693 WRITE_ONCE(p->priority, __SSH_PACKET_PRIORITY(base, try + 1));
694}
695
696/* Must be called with queue lock held. */
697static struct list_head *__ssh_ptl_queue_find_entrypoint(struct ssh_packet *p)
698{
699 struct list_head *head;
700 struct ssh_packet *q;
701
702 lockdep_assert_held(&p->ptl->queue.lock);
703
704 /*
705 * We generally assume that there are less control (ACK/NAK) packets
706 * and re-submitted data packets as there are normal data packets (at
707 * least in situations in which many packets are queued; if there
708 * aren't many packets queued the decision on how to iterate should be
709 * basically irrelevant; the number of control/data packets is more or
710 * less limited via the maximum number of pending packets). Thus, when
711 * inserting a control or re-submitted data packet, (determined by
712 * their priority), we search from front to back. Normal data packets
713 * are, usually queued directly at the tail of the queue, so for those
714 * search from back to front.
715 */
716
717 if (p->priority > SSH_PACKET_PRIORITY(DATA, 0)) {
718 list_for_each(head, &p->ptl->queue.head) {
719 q = list_entry(head, struct ssh_packet, queue_node);
720
721 if (q->priority < p->priority)
722 break;
723 }
724 } else {
725 list_for_each_prev(head, &p->ptl->queue.head) {
726 q = list_entry(head, struct ssh_packet, queue_node);
727
728 if (q->priority >= p->priority) {
729 head = head->next;
730 break;
731 }
732 }
733 }
734
735 return head;
736}
737
738/* Must be called with queue lock held. */
739static int __ssh_ptl_queue_push(struct ssh_packet *packet)
740{
741 struct ssh_ptl *ptl = packet->ptl;
742 struct list_head *head;
743
744 lockdep_assert_held(&ptl->queue.lock);
745
746 if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
747 return -ESHUTDOWN;
748
749 /* Avoid further transitions when canceling/completing. */
750 if (test_bit(SSH_PACKET_SF_LOCKED_BIT, &packet->state))
751 return -EINVAL;
752
753 /* If this packet has already been queued, do not add it. */
754 if (test_and_set_bit(SSH_PACKET_SF_QUEUED_BIT, &packet->state))
755 return -EALREADY;
756
757 head = __ssh_ptl_queue_find_entrypoint(packet);
758
759 list_add_tail(&ssh_packet_get(packet)->queue_node, head);
760 return 0;
761}
762
763static int ssh_ptl_queue_push(struct ssh_packet *packet)
764{
765 int status;
766
767 spin_lock(&packet->ptl->queue.lock);
768 status = __ssh_ptl_queue_push(packet);
769 spin_unlock(&packet->ptl->queue.lock);
770
771 return status;
772}
773
774static void ssh_ptl_queue_remove(struct ssh_packet *packet)
775{
776 struct ssh_ptl *ptl = packet->ptl;
777
778 spin_lock(&ptl->queue.lock);
779
780 if (!test_and_clear_bit(SSH_PACKET_SF_QUEUED_BIT, &packet->state)) {
781 spin_unlock(&ptl->queue.lock);
782 return;
783 }
784
785 list_del(&packet->queue_node);
786
787 spin_unlock(&ptl->queue.lock);
788 ssh_packet_put(packet);
789}
790
791static void ssh_ptl_pending_push(struct ssh_packet *p)
792{
793 struct ssh_ptl *ptl = p->ptl;
794 const ktime_t timestamp = ktime_get_coarse_boottime();
795 const ktime_t timeout = ptl->rtx_timeout.timeout;
796
797 /*
798 * Note: We can get the time for the timestamp before acquiring the
799 * lock as this is the only place we're setting it and this function
800 * is called only from the transmitter thread. Thus it is not possible
801 * to overwrite the timestamp with an outdated value below.
802 */
803
804 spin_lock(&ptl->pending.lock);
805
806 /* If we are canceling/completing this packet, do not add it. */
807 if (test_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state)) {
808 spin_unlock(&ptl->pending.lock);
809 return;
810 }
811
812 /*
813 * On re-submission, the packet has already been added the pending
814 * set. We still need to update the timestamp as the packet timeout is
815 * reset for each (re-)submission.
816 */
817 p->timestamp = timestamp;
818
819 /* In case it is already pending (e.g. re-submission), do not add it. */
820 if (!test_and_set_bit(SSH_PACKET_SF_PENDING_BIT, &p->state)) {
821 atomic_inc(&ptl->pending.count);
822 list_add_tail(&ssh_packet_get(p)->pending_node, &ptl->pending.head);
823 }
824
825 spin_unlock(&ptl->pending.lock);
826
827 /* Arm/update timeout reaper. */
828 ssh_ptl_timeout_reaper_mod(ptl, timestamp, timestamp + timeout);
829}
830
831static void ssh_ptl_pending_remove(struct ssh_packet *packet)
832{
833 struct ssh_ptl *ptl = packet->ptl;
834
835 spin_lock(&ptl->pending.lock);
836
837 if (!test_and_clear_bit(SSH_PACKET_SF_PENDING_BIT, &packet->state)) {
838 spin_unlock(&ptl->pending.lock);
839 return;
840 }
841
842 list_del(&packet->pending_node);
843 atomic_dec(&ptl->pending.count);
844
845 spin_unlock(&ptl->pending.lock);
846
847 ssh_packet_put(packet);
848}
849
850/* Warning: Does not check/set "completed" bit. */
851static void __ssh_ptl_complete(struct ssh_packet *p, int status)
852{
853 struct ssh_ptl *ptl = READ_ONCE(p->ptl);
854
855 trace_ssam_packet_complete(p, status);
856 ptl_dbg_cond(ptl, "ptl: completing packet %p (status: %d)\n", p, status);
857
858 if (p->ops->complete)
859 p->ops->complete(p, status);
860}
861
862static void ssh_ptl_remove_and_complete(struct ssh_packet *p, int status)
863{
864 /*
865 * A call to this function should in general be preceded by
866 * set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->flags) to avoid re-adding the
867 * packet to the structures it's going to be removed from.
868 *
869 * The set_bit call does not need explicit memory barriers as the
870 * implicit barrier of the test_and_set_bit() call below ensure that the
871 * flag is visible before we actually attempt to remove the packet.
872 */
873
874 if (test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state))
875 return;
876
877 ssh_ptl_queue_remove(p);
878 ssh_ptl_pending_remove(p);
879
880 __ssh_ptl_complete(p, status);
881}
882
883static bool ssh_ptl_tx_can_process(struct ssh_packet *packet)
884{
885 struct ssh_ptl *ptl = packet->ptl;
886
887 if (test_bit(SSH_PACKET_TY_FLUSH_BIT, &packet->state))
888 return !atomic_read(&ptl->pending.count);
889
890 /* We can always process non-blocking packets. */
891 if (!test_bit(SSH_PACKET_TY_BLOCKING_BIT, &packet->state))
892 return true;
893
894 /* If we are already waiting for this packet, send it again. */
895 if (test_bit(SSH_PACKET_SF_PENDING_BIT, &packet->state))
896 return true;
897
898 /* Otherwise: Check if we have the capacity to send. */
899 return atomic_read(&ptl->pending.count) < SSH_PTL_MAX_PENDING;
900}
901
902static struct ssh_packet *ssh_ptl_tx_pop(struct ssh_ptl *ptl)
903{
904 struct ssh_packet *packet = ERR_PTR(-ENOENT);
905 struct ssh_packet *p, *n;
906
907 spin_lock(&ptl->queue.lock);
908 list_for_each_entry_safe(p, n, &ptl->queue.head, queue_node) {
909 /*
910 * If we are canceling or completing this packet, ignore it.
911 * It's going to be removed from this queue shortly.
912 */
913 if (test_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state))
914 continue;
915
916 /*
917 * Packets should be ordered non-blocking/to-be-resent first.
918 * If we cannot process this packet, assume that we can't
919 * process any following packet either and abort.
920 */
921 if (!ssh_ptl_tx_can_process(p)) {
922 packet = ERR_PTR(-EBUSY);
923 break;
924 }
925
926 /*
927 * We are allowed to change the state now. Remove it from the
928 * queue and mark it as being transmitted.
929 */
930
931 list_del(&p->queue_node);
932
933 set_bit(SSH_PACKET_SF_TRANSMITTING_BIT, &p->state);
934 /* Ensure that state never gets zero. */
935 smp_mb__before_atomic();
936 clear_bit(SSH_PACKET_SF_QUEUED_BIT, &p->state);
937
938 /*
939 * Update number of tries. This directly influences the
940 * priority in case the packet is re-submitted (e.g. via
941 * timeout/NAK). Note that all reads and writes to the
942 * priority after the first submission are guarded by the
943 * queue lock.
944 */
945 ssh_packet_next_try(p);
946
947 packet = p;
948 break;
949 }
950 spin_unlock(&ptl->queue.lock);
951
952 return packet;
953}
954
955static struct ssh_packet *ssh_ptl_tx_next(struct ssh_ptl *ptl)
956{
957 struct ssh_packet *p;
958
959 p = ssh_ptl_tx_pop(ptl);
960 if (IS_ERR(p))
961 return p;
962
963 if (test_bit(SSH_PACKET_TY_SEQUENCED_BIT, &p->state)) {
964 ptl_dbg(ptl, "ptl: transmitting sequenced packet %p\n", p);
965 ssh_ptl_pending_push(p);
966 } else {
967 ptl_dbg(ptl, "ptl: transmitting non-sequenced packet %p\n", p);
968 }
969
970 return p;
971}
972
973static void ssh_ptl_tx_compl_success(struct ssh_packet *packet)
974{
975 struct ssh_ptl *ptl = packet->ptl;
976
977 ptl_dbg(ptl, "ptl: successfully transmitted packet %p\n", packet);
978
979 /* Transition state to "transmitted". */
980 set_bit(SSH_PACKET_SF_TRANSMITTED_BIT, &packet->state);
981 /* Ensure that state never gets zero. */
982 smp_mb__before_atomic();
983 clear_bit(SSH_PACKET_SF_TRANSMITTING_BIT, &packet->state);
984
985 /* If the packet is unsequenced, we're done: Lock and complete. */
986 if (!test_bit(SSH_PACKET_TY_SEQUENCED_BIT, &packet->state)) {
987 set_bit(SSH_PACKET_SF_LOCKED_BIT, &packet->state);
988 ssh_ptl_remove_and_complete(packet, 0);
989 }
990
991 /*
992 * Notify that a packet transmission has finished. In general we're only
993 * waiting for one packet (if any), so wake_up_all should be fine.
994 */
995 wake_up_all(&ptl->tx.packet_wq);
996}
997
998static void ssh_ptl_tx_compl_error(struct ssh_packet *packet, int status)
999{
1000 /* Transmission failure: Lock the packet and try to complete it. */
1001 set_bit(SSH_PACKET_SF_LOCKED_BIT, &packet->state);
1002 /* Ensure that state never gets zero. */
1003 smp_mb__before_atomic();
1004 clear_bit(SSH_PACKET_SF_TRANSMITTING_BIT, &packet->state);
1005
1006 ptl_err(packet->ptl, "ptl: transmission error: %d\n", status);
1007 ptl_dbg(packet->ptl, "ptl: failed to transmit packet: %p\n", packet);
1008
1009 ssh_ptl_remove_and_complete(packet, status);
1010
1011 /*
1012 * Notify that a packet transmission has finished. In general we're only
1013 * waiting for one packet (if any), so wake_up_all should be fine.
1014 */
1015 wake_up_all(&packet->ptl->tx.packet_wq);
1016}
1017
1018static long ssh_ptl_tx_wait_packet(struct ssh_ptl *ptl)
1019{
1020 int status;
1021
1022 status = wait_for_completion_interruptible(&ptl->tx.thread_cplt_pkt);
1023 reinit_completion(&ptl->tx.thread_cplt_pkt);
1024
1025 /*
1026 * Ensure completion is cleared before continuing to avoid lost update
1027 * problems.
1028 */
1029 smp_mb__after_atomic();
1030
1031 return status;
1032}
1033
1034static long ssh_ptl_tx_wait_transfer(struct ssh_ptl *ptl, long timeout)
1035{
1036 long status;
1037
1038 status = wait_for_completion_interruptible_timeout(&ptl->tx.thread_cplt_tx,
1039 timeout);
1040 reinit_completion(&ptl->tx.thread_cplt_tx);
1041
1042 /*
1043 * Ensure completion is cleared before continuing to avoid lost update
1044 * problems.
1045 */
1046 smp_mb__after_atomic();
1047
1048 return status;
1049}
1050
1051static int ssh_ptl_tx_packet(struct ssh_ptl *ptl, struct ssh_packet *packet)
1052{
1053 long timeout = SSH_PTL_TX_TIMEOUT;
1054 size_t offset = 0;
1055
1056 /* Note: Flush-packets don't have any data. */
1057 if (unlikely(!packet->data.ptr))
1058 return 0;
1059
1060 /* Error injection: drop packet to simulate transmission problem. */
1061 if (ssh_ptl_should_drop_packet(packet))
1062 return 0;
1063
1064 /* Error injection: simulate invalid packet data. */
1065 ssh_ptl_tx_inject_invalid_data(packet);
1066
1067 ptl_dbg(ptl, "tx: sending data (length: %zu)\n", packet->data.len);
1068 print_hex_dump_debug("tx: ", DUMP_PREFIX_OFFSET, 16, 1,
1069 packet->data.ptr, packet->data.len, false);
1070
1071 do {
1072 ssize_t status, len;
1073 u8 *buf;
1074
1075 buf = packet->data.ptr + offset;
1076 len = packet->data.len - offset;
1077
1078 status = ssh_ptl_write_buf(ptl, packet, buf, len);
1079 if (status < 0)
1080 return status;
1081
1082 if (status == len)
1083 return 0;
1084
1085 offset += status;
1086
1087 timeout = ssh_ptl_tx_wait_transfer(ptl, timeout);
1088 if (kthread_should_stop() || !atomic_read(&ptl->tx.running))
1089 return -ESHUTDOWN;
1090
1091 if (timeout < 0)
1092 return -EINTR;
1093
1094 if (timeout == 0)
1095 return -ETIMEDOUT;
1096 } while (true);
1097}
1098
1099static int ssh_ptl_tx_threadfn(void *data)
1100{
1101 struct ssh_ptl *ptl = data;
1102
1103 while (!kthread_should_stop() && atomic_read(&ptl->tx.running)) {
1104 struct ssh_packet *packet;
1105 int status;
1106
1107 /* Try to get the next packet. */
1108 packet = ssh_ptl_tx_next(ptl);
1109
1110 /* If no packet can be processed, we are done. */
1111 if (IS_ERR(packet)) {
1112 ssh_ptl_tx_wait_packet(ptl);
1113 continue;
1114 }
1115
1116 /* Transfer and complete packet. */
1117 status = ssh_ptl_tx_packet(ptl, packet);
1118 if (status)
1119 ssh_ptl_tx_compl_error(packet, status);
1120 else
1121 ssh_ptl_tx_compl_success(packet);
1122
1123 ssh_packet_put(packet);
1124 }
1125
1126 return 0;
1127}
1128
1129/**
1130 * ssh_ptl_tx_wakeup_packet() - Wake up packet transmitter thread for new
1131 * packet.
1132 * @ptl: The packet transport layer.
1133 *
1134 * Wakes up the packet transmitter thread, notifying it that a new packet has
1135 * arrived and is ready for transfer. If the packet transport layer has been
1136 * shut down, calls to this function will be ignored.
1137 */
1138static void ssh_ptl_tx_wakeup_packet(struct ssh_ptl *ptl)
1139{
1140 if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
1141 return;
1142
1143 complete(&ptl->tx.thread_cplt_pkt);
1144}
1145
1146/**
1147 * ssh_ptl_tx_start() - Start packet transmitter thread.
1148 * @ptl: The packet transport layer.
1149 *
1150 * Return: Returns zero on success, a negative error code on failure.
1151 */
1152int ssh_ptl_tx_start(struct ssh_ptl *ptl)
1153{
1154 atomic_set_release(&ptl->tx.running, 1);
1155
1156 ptl->tx.thread = kthread_run(ssh_ptl_tx_threadfn, ptl, "ssam_serial_hub-tx");
1157 if (IS_ERR(ptl->tx.thread))
1158 return PTR_ERR(ptl->tx.thread);
1159
1160 return 0;
1161}
1162
1163/**
1164 * ssh_ptl_tx_stop() - Stop packet transmitter thread.
1165 * @ptl: The packet transport layer.
1166 *
1167 * Return: Returns zero on success, a negative error code on failure.
1168 */
1169int ssh_ptl_tx_stop(struct ssh_ptl *ptl)
1170{
1171 int status = 0;
1172
1173 if (!IS_ERR_OR_NULL(ptl->tx.thread)) {
1174 /* Tell thread to stop. */
1175 atomic_set_release(&ptl->tx.running, 0);
1176
1177 /*
1178 * Wake up thread in case it is paused. Do not use wakeup
1179 * helpers as this may be called when the shutdown bit has
1180 * already been set.
1181 */
1182 complete(&ptl->tx.thread_cplt_pkt);
1183 complete(&ptl->tx.thread_cplt_tx);
1184
1185 /* Finally, wait for thread to stop. */
1186 status = kthread_stop(ptl->tx.thread);
1187 ptl->tx.thread = NULL;
1188 }
1189
1190 return status;
1191}
1192
1193static struct ssh_packet *ssh_ptl_ack_pop(struct ssh_ptl *ptl, u8 seq_id)
1194{
1195 struct ssh_packet *packet = ERR_PTR(-ENOENT);
1196 struct ssh_packet *p, *n;
1197
1198 spin_lock(&ptl->pending.lock);
1199 list_for_each_entry_safe(p, n, &ptl->pending.head, pending_node) {
1200 /*
1201 * We generally expect packets to be in order, so first packet
1202 * to be added to pending is first to be sent, is first to be
1203 * ACKed.
1204 */
1205 if (unlikely(ssh_packet_get_seq(p) != seq_id))
1206 continue;
1207
1208 /*
1209 * In case we receive an ACK while handling a transmission
1210 * error completion. The packet will be removed shortly.
1211 */
1212 if (unlikely(test_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state))) {
1213 packet = ERR_PTR(-EPERM);
1214 break;
1215 }
1216
1217 /*
1218 * Mark the packet as ACKed and remove it from pending by
1219 * removing its node and decrementing the pending counter.
1220 */
1221 set_bit(SSH_PACKET_SF_ACKED_BIT, &p->state);
1222 /* Ensure that state never gets zero. */
1223 smp_mb__before_atomic();
1224 clear_bit(SSH_PACKET_SF_PENDING_BIT, &p->state);
1225
1226 atomic_dec(&ptl->pending.count);
1227 list_del(&p->pending_node);
1228 packet = p;
1229
1230 break;
1231 }
1232 spin_unlock(&ptl->pending.lock);
1233
1234 return packet;
1235}
1236
1237static void ssh_ptl_wait_until_transmitted(struct ssh_packet *packet)
1238{
1239 wait_event(packet->ptl->tx.packet_wq,
1240 test_bit(SSH_PACKET_SF_TRANSMITTED_BIT, &packet->state) ||
1241 test_bit(SSH_PACKET_SF_LOCKED_BIT, &packet->state));
1242}
1243
1244static void ssh_ptl_acknowledge(struct ssh_ptl *ptl, u8 seq)
1245{
1246 struct ssh_packet *p;
1247
1248 p = ssh_ptl_ack_pop(ptl, seq);
1249 if (IS_ERR(p)) {
1250 if (PTR_ERR(p) == -ENOENT) {
1251 /*
1252 * The packet has not been found in the set of pending
1253 * packets.
1254 */
1255 ptl_warn(ptl, "ptl: received ACK for non-pending packet\n");
1256 } else {
1257 /*
1258 * The packet is pending, but we are not allowed to take
1259 * it because it has been locked.
1260 */
1261 WARN_ON(PTR_ERR(p) != -EPERM);
1262 }
1263 return;
1264 }
1265
1266 ptl_dbg(ptl, "ptl: received ACK for packet %p\n", p);
1267
1268 /*
1269 * It is possible that the packet has been transmitted, but the state
1270 * has not been updated from "transmitting" to "transmitted" yet.
1271 * In that case, we need to wait for this transition to occur in order
1272 * to determine between success or failure.
1273 *
1274 * On transmission failure, the packet will be locked after this call.
1275 * On success, the transmitted bit will be set.
1276 */
1277 ssh_ptl_wait_until_transmitted(p);
1278
1279 /*
1280 * The packet will already be locked in case of a transmission error or
1281 * cancellation. Let the transmitter or cancellation issuer complete the
1282 * packet.
1283 */
1284 if (unlikely(test_and_set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state))) {
1285 if (unlikely(!test_bit(SSH_PACKET_SF_TRANSMITTED_BIT, &p->state)))
1286 ptl_err(ptl, "ptl: received ACK before packet had been fully transmitted\n");
1287
1288 ssh_packet_put(p);
1289 return;
1290 }
1291
1292 ssh_ptl_remove_and_complete(p, 0);
1293 ssh_packet_put(p);
1294
1295 if (atomic_read(&ptl->pending.count) < SSH_PTL_MAX_PENDING)
1296 ssh_ptl_tx_wakeup_packet(ptl);
1297}
1298
1299/**
1300 * ssh_ptl_submit() - Submit a packet to the transport layer.
1301 * @ptl: The packet transport layer to submit the packet to.
1302 * @p: The packet to submit.
1303 *
1304 * Submits a new packet to the transport layer, queuing it to be sent. This
1305 * function should not be used for re-submission.
1306 *
1307 * Return: Returns zero on success, %-EINVAL if a packet field is invalid or
1308 * the packet has been canceled prior to submission, %-EALREADY if the packet
1309 * has already been submitted, or %-ESHUTDOWN if the packet transport layer
1310 * has been shut down.
1311 */
1312int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p)
1313{
1314 struct ssh_ptl *ptl_old;
1315 int status;
1316
1317 trace_ssam_packet_submit(p);
1318
1319 /* Validate packet fields. */
1320 if (test_bit(SSH_PACKET_TY_FLUSH_BIT, &p->state)) {
1321 if (p->data.ptr || test_bit(SSH_PACKET_TY_SEQUENCED_BIT, &p->state))
1322 return -EINVAL;
1323 } else if (!p->data.ptr) {
1324 return -EINVAL;
1325 }
1326
1327 /*
1328 * The ptl reference only gets set on or before the first submission.
1329 * After the first submission, it has to be read-only.
1330 *
1331 * Note that ptl may already be set from upper-layer request
1332 * submission, thus we cannot expect it to be NULL.
1333 */
1334 ptl_old = READ_ONCE(p->ptl);
1335 if (!ptl_old)
1336 WRITE_ONCE(p->ptl, ptl);
1337 else if (WARN_ON(ptl_old != ptl))
1338 return -EALREADY; /* Submitted on different PTL. */
1339
1340 status = ssh_ptl_queue_push(p);
1341 if (status)
1342 return status;
1343
1344 if (!test_bit(SSH_PACKET_TY_BLOCKING_BIT, &p->state) ||
1345 (atomic_read(&ptl->pending.count) < SSH_PTL_MAX_PENDING))
1346 ssh_ptl_tx_wakeup_packet(ptl);
1347
1348 return 0;
1349}
1350
1351/*
1352 * __ssh_ptl_resubmit() - Re-submit a packet to the transport layer.
1353 * @packet: The packet to re-submit.
1354 *
1355 * Re-submits the given packet: Checks if it can be re-submitted and queues it
1356 * if it can, resetting the packet timestamp in the process. Must be called
1357 * with the pending lock held.
1358 *
1359 * Return: Returns %-ECANCELED if the packet has exceeded its number of tries,
1360 * %-EINVAL if the packet has been locked, %-EALREADY if the packet is already
1361 * on the queue, and %-ESHUTDOWN if the transmission layer has been shut down.
1362 */
1363static int __ssh_ptl_resubmit(struct ssh_packet *packet)
1364{
1365 int status;
1366 u8 try;
1367
1368 lockdep_assert_held(&packet->ptl->pending.lock);
1369
1370 trace_ssam_packet_resubmit(packet);
1371
1372 spin_lock(&packet->ptl->queue.lock);
1373
1374 /* Check if the packet is out of tries. */
1375 try = ssh_packet_priority_get_try(packet->priority);
1376 if (try >= SSH_PTL_MAX_PACKET_TRIES) {
1377 spin_unlock(&packet->ptl->queue.lock);
1378 return -ECANCELED;
1379 }
1380
1381 status = __ssh_ptl_queue_push(packet);
1382 if (status) {
1383 /*
1384 * An error here indicates that the packet has either already
1385 * been queued, been locked, or the transport layer is being
1386 * shut down. In all cases: Ignore the error.
1387 */
1388 spin_unlock(&packet->ptl->queue.lock);
1389 return status;
1390 }
1391
1392 packet->timestamp = KTIME_MAX;
1393
1394 spin_unlock(&packet->ptl->queue.lock);
1395 return 0;
1396}
1397
1398static void ssh_ptl_resubmit_pending(struct ssh_ptl *ptl)
1399{
1400 struct ssh_packet *p;
1401 bool resub = false;
1402
1403 /*
1404 * Note: We deliberately do not remove/attempt to cancel and complete
1405 * packets that are out of tires in this function. The packet will be
1406 * eventually canceled and completed by the timeout. Removing the packet
1407 * here could lead to overly eager cancellation if the packet has not
1408 * been re-transmitted yet but the tries-counter already updated (i.e
1409 * ssh_ptl_tx_next() removed the packet from the queue and updated the
1410 * counter, but re-transmission for the last try has not actually
1411 * started yet).
1412 */
1413
1414 spin_lock(&ptl->pending.lock);
1415
1416 /* Re-queue all pending packets. */
1417 list_for_each_entry(p, &ptl->pending.head, pending_node) {
1418 /*
1419 * Re-submission fails if the packet is out of tries, has been
1420 * locked, is already queued, or the layer is being shut down.
1421 * No need to re-schedule tx-thread in those cases.
1422 */
1423 if (!__ssh_ptl_resubmit(p))
1424 resub = true;
1425 }
1426
1427 spin_unlock(&ptl->pending.lock);
1428
1429 if (resub)
1430 ssh_ptl_tx_wakeup_packet(ptl);
1431}
1432
1433/**
1434 * ssh_ptl_cancel() - Cancel a packet.
1435 * @p: The packet to cancel.
1436 *
1437 * Cancels a packet. There are no guarantees on when completion and release
1438 * callbacks will be called. This may occur during execution of this function
1439 * or may occur at any point later.
1440 *
1441 * Note that it is not guaranteed that the packet will actually be canceled if
1442 * the packet is concurrently completed by another process. The only guarantee
1443 * of this function is that the packet will be completed (with success,
1444 * failure, or cancellation) and released from the transport layer in a
1445 * reasonable time-frame.
1446 *
1447 * May be called before the packet has been submitted, in which case any later
1448 * packet submission fails.
1449 */
1450void ssh_ptl_cancel(struct ssh_packet *p)
1451{
1452 if (test_and_set_bit(SSH_PACKET_SF_CANCELED_BIT, &p->state))
1453 return;
1454
1455 trace_ssam_packet_cancel(p);
1456
1457 /*
1458 * Lock packet and commit with memory barrier. If this packet has
1459 * already been locked, it's going to be removed and completed by
1460 * another party, which should have precedence.
1461 */
1462 if (test_and_set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state))
1463 return;
1464
1465 /*
1466 * By marking the packet as locked and employing the implicit memory
1467 * barrier of test_and_set_bit, we have guaranteed that, at this point,
1468 * the packet cannot be added to the queue any more.
1469 *
1470 * In case the packet has never been submitted, packet->ptl is NULL. If
1471 * the packet is currently being submitted, packet->ptl may be NULL or
1472 * non-NULL. Due marking the packet as locked above and committing with
1473 * the memory barrier, we have guaranteed that, if packet->ptl is NULL,
1474 * the packet will never be added to the queue. If packet->ptl is
1475 * non-NULL, we don't have any guarantees.
1476 */
1477
1478 if (READ_ONCE(p->ptl)) {
1479 ssh_ptl_remove_and_complete(p, -ECANCELED);
1480
1481 if (atomic_read(&p->ptl->pending.count) < SSH_PTL_MAX_PENDING)
1482 ssh_ptl_tx_wakeup_packet(p->ptl);
1483
1484 } else if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state)) {
1485 __ssh_ptl_complete(p, -ECANCELED);
1486 }
1487}
1488
1489/* Must be called with pending lock held */
1490static ktime_t ssh_packet_get_expiration(struct ssh_packet *p, ktime_t timeout)
1491{
1492 lockdep_assert_held(&p->ptl->pending.lock);
1493
1494 if (p->timestamp != KTIME_MAX)
1495 return ktime_add(p->timestamp, timeout);
1496 else
1497 return KTIME_MAX;
1498}
1499
1500static void ssh_ptl_timeout_reap(struct work_struct *work)
1501{
1502 struct ssh_ptl *ptl = to_ssh_ptl(work, rtx_timeout.reaper.work);
1503 struct ssh_packet *p, *n;
1504 LIST_HEAD(claimed);
1505 ktime_t now = ktime_get_coarse_boottime();
1506 ktime_t timeout = ptl->rtx_timeout.timeout;
1507 ktime_t next = KTIME_MAX;
1508 bool resub = false;
1509 int status;
1510
1511 trace_ssam_ptl_timeout_reap(atomic_read(&ptl->pending.count));
1512
1513 /*
1514 * Mark reaper as "not pending". This is done before checking any
1515 * packets to avoid lost-update type problems.
1516 */
1517 spin_lock(&ptl->rtx_timeout.lock);
1518 ptl->rtx_timeout.expires = KTIME_MAX;
1519 spin_unlock(&ptl->rtx_timeout.lock);
1520
1521 spin_lock(&ptl->pending.lock);
1522
1523 list_for_each_entry_safe(p, n, &ptl->pending.head, pending_node) {
1524 ktime_t expires = ssh_packet_get_expiration(p, timeout);
1525
1526 /*
1527 * Check if the timeout hasn't expired yet. Find out next
1528 * expiration date to be handled after this run.
1529 */
1530 if (ktime_after(expires, now)) {
1531 next = ktime_before(expires, next) ? expires : next;
1532 continue;
1533 }
1534
1535 trace_ssam_packet_timeout(p);
1536
1537 status = __ssh_ptl_resubmit(p);
1538
1539 /*
1540 * Re-submission fails if the packet is out of tries, has been
1541 * locked, is already queued, or the layer is being shut down.
1542 * No need to re-schedule tx-thread in those cases.
1543 */
1544 if (!status)
1545 resub = true;
1546
1547 /* Go to next packet if this packet is not out of tries. */
1548 if (status != -ECANCELED)
1549 continue;
1550
1551 /* No more tries left: Cancel the packet. */
1552
1553 /*
1554 * If someone else has locked the packet already, don't use it
1555 * and let the other party complete it.
1556 */
1557 if (test_and_set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state))
1558 continue;
1559
1560 /*
1561 * We have now marked the packet as locked. Thus it cannot be
1562 * added to the pending list again after we've removed it here.
1563 * We can therefore re-use the pending_node of this packet
1564 * temporarily.
1565 */
1566
1567 clear_bit(SSH_PACKET_SF_PENDING_BIT, &p->state);
1568
1569 atomic_dec(&ptl->pending.count);
1570 list_del(&p->pending_node);
1571
1572 list_add_tail(&p->pending_node, &claimed);
1573 }
1574
1575 spin_unlock(&ptl->pending.lock);
1576
1577 /* Cancel and complete the packet. */
1578 list_for_each_entry_safe(p, n, &claimed, pending_node) {
1579 if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state)) {
1580 ssh_ptl_queue_remove(p);
1581 __ssh_ptl_complete(p, -ETIMEDOUT);
1582 }
1583
1584 /*
1585 * Drop the reference we've obtained by removing it from
1586 * the pending set.
1587 */
1588 list_del(&p->pending_node);
1589 ssh_packet_put(p);
1590 }
1591
1592 /* Ensure that reaper doesn't run again immediately. */
1593 next = max(next, ktime_add(now, SSH_PTL_PACKET_TIMEOUT_RESOLUTION));
1594 if (next != KTIME_MAX)
1595 ssh_ptl_timeout_reaper_mod(ptl, now, next);
1596
1597 if (resub)
1598 ssh_ptl_tx_wakeup_packet(ptl);
1599}
1600
1601static bool ssh_ptl_rx_retransmit_check(struct ssh_ptl *ptl, u8 seq)
1602{
1603 int i;
1604
1605 /*
1606 * Check if SEQ has been seen recently (i.e. packet was
1607 * re-transmitted and we should ignore it).
1608 */
1609 for (i = 0; i < ARRAY_SIZE(ptl->rx.blocked.seqs); i++) {
1610 if (likely(ptl->rx.blocked.seqs[i] != seq))
1611 continue;
1612
1613 ptl_dbg(ptl, "ptl: ignoring repeated data packet\n");
1614 return true;
1615 }
1616
1617 /* Update list of blocked sequence IDs. */
1618 ptl->rx.blocked.seqs[ptl->rx.blocked.offset] = seq;
1619 ptl->rx.blocked.offset = (ptl->rx.blocked.offset + 1)
1620 % ARRAY_SIZE(ptl->rx.blocked.seqs);
1621
1622 return false;
1623}
1624
1625static void ssh_ptl_rx_dataframe(struct ssh_ptl *ptl,
1626 const struct ssh_frame *frame,
1627 const struct ssam_span *payload)
1628{
1629 if (ssh_ptl_rx_retransmit_check(ptl, frame->seq))
1630 return;
1631
1632 ptl->ops.data_received(ptl, payload);
1633}
1634
1635static void ssh_ptl_send_ack(struct ssh_ptl *ptl, u8 seq)
1636{
1637 struct ssh_packet *packet;
1638 struct ssam_span buf;
1639 struct msgbuf msgb;
1640 int status;
1641
1642 status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
1643 if (status) {
1644 ptl_err(ptl, "ptl: failed to allocate ACK packet\n");
1645 return;
1646 }
1647
1648 ssh_packet_init(packet, 0, SSH_PACKET_PRIORITY(ACK, 0),
1649 &ssh_ptl_ctrl_packet_ops);
1650
1651 msgb_init(&msgb, buf.ptr, buf.len);
1652 msgb_push_ack(&msgb, seq);
1653 ssh_packet_set_data(packet, msgb.begin, msgb_bytes_used(&msgb));
1654
1655 ssh_ptl_submit(ptl, packet);
1656 ssh_packet_put(packet);
1657}
1658
1659static void ssh_ptl_send_nak(struct ssh_ptl *ptl)
1660{
1661 struct ssh_packet *packet;
1662 struct ssam_span buf;
1663 struct msgbuf msgb;
1664 int status;
1665
1666 status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
1667 if (status) {
1668 ptl_err(ptl, "ptl: failed to allocate NAK packet\n");
1669 return;
1670 }
1671
1672 ssh_packet_init(packet, 0, SSH_PACKET_PRIORITY(NAK, 0),
1673 &ssh_ptl_ctrl_packet_ops);
1674
1675 msgb_init(&msgb, buf.ptr, buf.len);
1676 msgb_push_nak(&msgb);
1677 ssh_packet_set_data(packet, msgb.begin, msgb_bytes_used(&msgb));
1678
1679 ssh_ptl_submit(ptl, packet);
1680 ssh_packet_put(packet);
1681}
1682
1683static size_t ssh_ptl_rx_eval(struct ssh_ptl *ptl, struct ssam_span *source)
1684{
1685 struct ssh_frame *frame;
1686 struct ssam_span payload;
1687 struct ssam_span aligned;
1688 bool syn_found;
1689 int status;
1690
1691 /* Error injection: Modify data to simulate corrupt SYN bytes. */
1692 ssh_ptl_rx_inject_invalid_syn(ptl, source);
1693
1694 /* Find SYN. */
1695 syn_found = sshp_find_syn(source, &aligned);
1696
1697 if (unlikely(aligned.ptr != source->ptr)) {
1698 /*
1699 * We expect aligned.ptr == source->ptr. If this is not the
1700 * case, then aligned.ptr > source->ptr and we've encountered
1701 * some unexpected data where we'd expect the start of a new
1702 * message (i.e. the SYN sequence).
1703 *
1704 * This can happen when a CRC check for the previous message
1705 * failed and we start actively searching for the next one
1706 * (via the call to sshp_find_syn() above), or the first bytes
1707 * of a message got dropped or corrupted.
1708 *
1709 * In any case, we issue a warning, send a NAK to the EC to
1710 * request re-transmission of any data we haven't acknowledged
1711 * yet, and finally, skip everything up to the next SYN
1712 * sequence.
1713 */
1714
1715 ptl_warn(ptl, "rx: parser: invalid start of frame, skipping\n");
1716
1717 /*
1718 * Notes:
1719 * - This might send multiple NAKs in case the communication
1720 * starts with an invalid SYN and is broken down into multiple
1721 * pieces. This should generally be handled fine, we just
1722 * might receive duplicate data in this case, which is
1723 * detected when handling data frames.
1724 * - This path will also be executed on invalid CRCs: When an
1725 * invalid CRC is encountered, the code below will skip data
1726 * until directly after the SYN. This causes the search for
1727 * the next SYN, which is generally not placed directly after
1728 * the last one.
1729 *
1730 * Open question: Should we send this in case of invalid
1731 * payload CRCs if the frame-type is non-sequential (current
1732 * implementation) or should we drop that frame without
1733 * telling the EC?
1734 */
1735 ssh_ptl_send_nak(ptl);
1736 }
1737
1738 if (unlikely(!syn_found))
1739 return aligned.ptr - source->ptr;
1740
1741 /* Error injection: Modify data to simulate corruption. */
1742 ssh_ptl_rx_inject_invalid_data(ptl, &aligned);
1743
1744 /* Parse and validate frame. */
1745 status = sshp_parse_frame(&ptl->serdev->dev, &aligned, &frame, &payload,
1746 SSH_PTL_RX_BUF_LEN);
1747 if (status) /* Invalid frame: skip to next SYN. */
1748 return aligned.ptr - source->ptr + sizeof(u16);
1749 if (!frame) /* Not enough data. */
1750 return aligned.ptr - source->ptr;
1751
1752 trace_ssam_rx_frame_received(frame);
1753
1754 switch (frame->type) {
1755 case SSH_FRAME_TYPE_ACK:
1756 ssh_ptl_acknowledge(ptl, frame->seq);
1757 break;
1758
1759 case SSH_FRAME_TYPE_NAK:
1760 ssh_ptl_resubmit_pending(ptl);
1761 break;
1762
1763 case SSH_FRAME_TYPE_DATA_SEQ:
1764 ssh_ptl_send_ack(ptl, frame->seq);
1765 fallthrough;
1766
1767 case SSH_FRAME_TYPE_DATA_NSQ:
1768 ssh_ptl_rx_dataframe(ptl, frame, &payload);
1769 break;
1770
1771 default:
1772 ptl_warn(ptl, "ptl: received frame with unknown type %#04x\n",
1773 frame->type);
1774 break;
1775 }
1776
1777 return aligned.ptr - source->ptr + SSH_MESSAGE_LENGTH(payload.len);
1778}
1779
1780static int ssh_ptl_rx_threadfn(void *data)
1781{
1782 struct ssh_ptl *ptl = data;
1783
1784 while (true) {
1785 struct ssam_span span;
1786 size_t offs = 0;
1787 size_t n;
1788
1789 wait_event_interruptible(ptl->rx.wq,
1790 !kfifo_is_empty(&ptl->rx.fifo) ||
1791 kthread_should_stop());
1792 if (kthread_should_stop())
1793 break;
1794
1795 /* Copy from fifo to evaluation buffer. */
1796 n = sshp_buf_read_from_fifo(&ptl->rx.buf, &ptl->rx.fifo);
1797
1798 ptl_dbg(ptl, "rx: received data (size: %zu)\n", n);
1799 print_hex_dump_debug("rx: ", DUMP_PREFIX_OFFSET, 16, 1,
1800 ptl->rx.buf.ptr + ptl->rx.buf.len - n,
1801 n, false);
1802
1803 /* Parse until we need more bytes or buffer is empty. */
1804 while (offs < ptl->rx.buf.len) {
1805 sshp_buf_span_from(&ptl->rx.buf, offs, &span);
1806 n = ssh_ptl_rx_eval(ptl, &span);
1807 if (n == 0)
1808 break; /* Need more bytes. */
1809
1810 offs += n;
1811 }
1812
1813 /* Throw away the evaluated parts. */
1814 sshp_buf_drop(&ptl->rx.buf, offs);
1815 }
1816
1817 return 0;
1818}
1819
1820static void ssh_ptl_rx_wakeup(struct ssh_ptl *ptl)
1821{
1822 wake_up(&ptl->rx.wq);
1823}
1824
1825/**
1826 * ssh_ptl_rx_start() - Start packet transport layer receiver thread.
1827 * @ptl: The packet transport layer.
1828 *
1829 * Return: Returns zero on success, a negative error code on failure.
1830 */
1831int ssh_ptl_rx_start(struct ssh_ptl *ptl)
1832{
1833 if (ptl->rx.thread)
1834 return 0;
1835
1836 ptl->rx.thread = kthread_run(ssh_ptl_rx_threadfn, ptl,
1837 "ssam_serial_hub-rx");
1838 if (IS_ERR(ptl->rx.thread))
1839 return PTR_ERR(ptl->rx.thread);
1840
1841 return 0;
1842}
1843
1844/**
1845 * ssh_ptl_rx_stop() - Stop packet transport layer receiver thread.
1846 * @ptl: The packet transport layer.
1847 *
1848 * Return: Returns zero on success, a negative error code on failure.
1849 */
1850int ssh_ptl_rx_stop(struct ssh_ptl *ptl)
1851{
1852 int status = 0;
1853
1854 if (ptl->rx.thread) {
1855 status = kthread_stop(ptl->rx.thread);
1856 ptl->rx.thread = NULL;
1857 }
1858
1859 return status;
1860}
1861
1862/**
1863 * ssh_ptl_rx_rcvbuf() - Push data from lower-layer transport to the packet
1864 * layer.
1865 * @ptl: The packet transport layer.
1866 * @buf: Pointer to the data to push to the layer.
1867 * @n: Size of the data to push to the layer, in bytes.
1868 *
1869 * Pushes data from a lower-layer transport to the receiver fifo buffer of the
1870 * packet layer and notifies the receiver thread. Calls to this function are
1871 * ignored once the packet layer has been shut down.
1872 *
1873 * Return: Returns the number of bytes transferred (positive or zero) on
1874 * success. Returns %-ESHUTDOWN if the packet layer has been shut down.
1875 */
1876int ssh_ptl_rx_rcvbuf(struct ssh_ptl *ptl, const u8 *buf, size_t n)
1877{
1878 int used;
1879
1880 if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
1881 return -ESHUTDOWN;
1882
1883 used = kfifo_in(&ptl->rx.fifo, buf, n);
1884 if (used)
1885 ssh_ptl_rx_wakeup(ptl);
1886
1887 return used;
1888}
1889
1890/**
1891 * ssh_ptl_shutdown() - Shut down the packet transport layer.
1892 * @ptl: The packet transport layer.
1893 *
1894 * Shuts down the packet transport layer, removing and canceling all queued
1895 * and pending packets. Packets canceled by this operation will be completed
1896 * with %-ESHUTDOWN as status. Receiver and transmitter threads will be
1897 * stopped.
1898 *
1899 * As a result of this function, the transport layer will be marked as shut
1900 * down. Submission of packets after the transport layer has been shut down
1901 * will fail with %-ESHUTDOWN.
1902 */
1903void ssh_ptl_shutdown(struct ssh_ptl *ptl)
1904{
1905 LIST_HEAD(complete_q);
1906 LIST_HEAD(complete_p);
1907 struct ssh_packet *p, *n;
1908 int status;
1909
1910 /* Ensure that no new packets (including ACK/NAK) can be submitted. */
1911 set_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state);
1912 /*
1913 * Ensure that the layer gets marked as shut-down before actually
1914 * stopping it. In combination with the check in ssh_ptl_queue_push(),
1915 * this guarantees that no new packets can be added and all already
1916 * queued packets are properly canceled. In combination with the check
1917 * in ssh_ptl_rx_rcvbuf(), this guarantees that received data is
1918 * properly cut off.
1919 */
1920 smp_mb__after_atomic();
1921
1922 status = ssh_ptl_rx_stop(ptl);
1923 if (status)
1924 ptl_err(ptl, "ptl: failed to stop receiver thread\n");
1925
1926 status = ssh_ptl_tx_stop(ptl);
1927 if (status)
1928 ptl_err(ptl, "ptl: failed to stop transmitter thread\n");
1929
1930 cancel_delayed_work_sync(&ptl->rtx_timeout.reaper);
1931
1932 /*
1933 * At this point, all threads have been stopped. This means that the
1934 * only references to packets from inside the system are in the queue
1935 * and pending set.
1936 *
1937 * Note: We still need locks here because someone could still be
1938 * canceling packets.
1939 *
1940 * Note 2: We can re-use queue_node (or pending_node) if we mark the
1941 * packet as locked an then remove it from the queue (or pending set
1942 * respectively). Marking the packet as locked avoids re-queuing
1943 * (which should already be prevented by having stopped the treads...)
1944 * and not setting QUEUED_BIT (or PENDING_BIT) prevents removal from a
1945 * new list via other threads (e.g. cancellation).
1946 *
1947 * Note 3: There may be overlap between complete_p and complete_q.
1948 * This is handled via test_and_set_bit() on the "completed" flag
1949 * (also handles cancellation).
1950 */
1951
1952 /* Mark queued packets as locked and move them to complete_q. */
1953 spin_lock(&ptl->queue.lock);
1954 list_for_each_entry_safe(p, n, &ptl->queue.head, queue_node) {
1955 set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state);
1956 /* Ensure that state does not get zero. */
1957 smp_mb__before_atomic();
1958 clear_bit(SSH_PACKET_SF_QUEUED_BIT, &p->state);
1959
1960 list_del(&p->queue_node);
1961 list_add_tail(&p->queue_node, &complete_q);
1962 }
1963 spin_unlock(&ptl->queue.lock);
1964
1965 /* Mark pending packets as locked and move them to complete_p. */
1966 spin_lock(&ptl->pending.lock);
1967 list_for_each_entry_safe(p, n, &ptl->pending.head, pending_node) {
1968 set_bit(SSH_PACKET_SF_LOCKED_BIT, &p->state);
1969 /* Ensure that state does not get zero. */
1970 smp_mb__before_atomic();
1971 clear_bit(SSH_PACKET_SF_PENDING_BIT, &p->state);
1972
1973 list_del(&p->pending_node);
1974 list_add_tail(&p->pending_node, &complete_q);
1975 }
1976 atomic_set(&ptl->pending.count, 0);
1977 spin_unlock(&ptl->pending.lock);
1978
1979 /* Complete and drop packets on complete_q. */
1980 list_for_each_entry(p, &complete_q, queue_node) {
1981 if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state))
1982 __ssh_ptl_complete(p, -ESHUTDOWN);
1983
1984 ssh_packet_put(p);
1985 }
1986
1987 /* Complete and drop packets on complete_p. */
1988 list_for_each_entry(p, &complete_p, pending_node) {
1989 if (!test_and_set_bit(SSH_PACKET_SF_COMPLETED_BIT, &p->state))
1990 __ssh_ptl_complete(p, -ESHUTDOWN);
1991
1992 ssh_packet_put(p);
1993 }
1994
1995 /*
1996 * At this point we have guaranteed that the system doesn't reference
1997 * any packets any more.
1998 */
1999}
2000
2001/**
2002 * ssh_ptl_init() - Initialize packet transport layer.
2003 * @ptl: The packet transport layer to initialize.
2004 * @serdev: The underlying serial device, i.e. the lower-level transport.
2005 * @ops: Packet layer operations.
2006 *
2007 * Initializes the given packet transport layer. Transmitter and receiver
2008 * threads must be started separately via ssh_ptl_tx_start() and
2009 * ssh_ptl_rx_start(), after the packet-layer has been initialized and the
2010 * lower-level transport layer has been set up.
2011 *
2012 * Return: Returns zero on success and a nonzero error code on failure.
2013 */
2014int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,
2015 struct ssh_ptl_ops *ops)
2016{
2017 int i, status;
2018
2019 ptl->serdev = serdev;
2020 ptl->state = 0;
2021
2022 spin_lock_init(&ptl->queue.lock);
2023 INIT_LIST_HEAD(&ptl->queue.head);
2024
2025 spin_lock_init(&ptl->pending.lock);
2026 INIT_LIST_HEAD(&ptl->pending.head);
2027 atomic_set_release(&ptl->pending.count, 0);
2028
2029 ptl->tx.thread = NULL;
2030 atomic_set(&ptl->tx.running, 0);
2031 init_completion(&ptl->tx.thread_cplt_pkt);
2032 init_completion(&ptl->tx.thread_cplt_tx);
2033 init_waitqueue_head(&ptl->tx.packet_wq);
2034
2035 ptl->rx.thread = NULL;
2036 init_waitqueue_head(&ptl->rx.wq);
2037
2038 spin_lock_init(&ptl->rtx_timeout.lock);
2039 ptl->rtx_timeout.timeout = SSH_PTL_PACKET_TIMEOUT;
2040 ptl->rtx_timeout.expires = KTIME_MAX;
2041 INIT_DELAYED_WORK(&ptl->rtx_timeout.reaper, ssh_ptl_timeout_reap);
2042
2043 ptl->ops = *ops;
2044
2045 /* Initialize list of recent/blocked SEQs with invalid sequence IDs. */
2046 for (i = 0; i < ARRAY_SIZE(ptl->rx.blocked.seqs); i++)
2047 ptl->rx.blocked.seqs[i] = U16_MAX;
2048 ptl->rx.blocked.offset = 0;
2049
2050 status = kfifo_alloc(&ptl->rx.fifo, SSH_PTL_RX_FIFO_LEN, GFP_KERNEL);
2051 if (status)
2052 return status;
2053
2054 status = sshp_buf_alloc(&ptl->rx.buf, SSH_PTL_RX_BUF_LEN, GFP_KERNEL);
2055 if (status)
2056 kfifo_free(&ptl->rx.fifo);
2057
2058 return status;
2059}
2060
2061/**
2062 * ssh_ptl_destroy() - Deinitialize packet transport layer.
2063 * @ptl: The packet transport layer to deinitialize.
2064 *
2065 * Deinitializes the given packet transport layer and frees resources
2066 * associated with it. If receiver and/or transmitter threads have been
2067 * started, the layer must first be shut down via ssh_ptl_shutdown() before
2068 * this function can be called.
2069 */
2070void ssh_ptl_destroy(struct ssh_ptl *ptl)
2071{
2072 kfifo_free(&ptl->rx.fifo);
2073 sshp_buf_free(&ptl->rx.buf);
2074}
drivers/platform/surface/aggregator/ssh_packet_layer.h+190−0
@@ -0,0 +1,190 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * SSH packet transport layer.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
9#define _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
10
11#include <linux/atomic.h>
12#include <linux/kfifo.h>
13#include <linux/ktime.h>
14#include <linux/list.h>
15#include <linux/serdev.h>
16#include <linux/spinlock.h>
17#include <linux/types.h>
18#include <linux/wait.h>
19#include <linux/workqueue.h>
20
21#include <linux/surface_aggregator/serial_hub.h>
22#include "ssh_parser.h"
23
24/**
25 * enum ssh_ptl_state_flags - State-flags for &struct ssh_ptl.
26 *
27 * @SSH_PTL_SF_SHUTDOWN_BIT:
28 * Indicates that the packet transport layer has been shut down or is
29 * being shut down and should not accept any new packets/data.
30 */
31enum ssh_ptl_state_flags {
32 SSH_PTL_SF_SHUTDOWN_BIT,
33};
34
35/**
36 * struct ssh_ptl_ops - Callback operations for packet transport layer.
37 * @data_received: Function called when a data-packet has been received. Both,
38 * the packet layer on which the packet has been received and
39 * the packet's payload data are provided to this function.
40 */
41struct ssh_ptl_ops {
42 void (*data_received)(struct ssh_ptl *p, const struct ssam_span *data);
43};
44
45/**
46 * struct ssh_ptl - SSH packet transport layer.
47 * @serdev: Serial device providing the underlying data transport.
48 * @state: State(-flags) of the transport layer.
49 * @queue: Packet submission queue.
50 * @queue.lock: Lock for modifying the packet submission queue.
51 * @queue.head: List-head of the packet submission queue.
52 * @pending: Set/list of pending packets.
53 * @pending.lock: Lock for modifying the pending set.
54 * @pending.head: List-head of the pending set/list.
55 * @pending.count: Number of currently pending packets.
56 * @tx: Transmitter subsystem.
57 * @tx.running: Flag indicating (desired) transmitter thread state.
58 * @tx.thread: Transmitter thread.
59 * @tx.thread_cplt_tx: Completion for transmitter thread waiting on transfer.
60 * @tx.thread_cplt_pkt: Completion for transmitter thread waiting on packets.
61 * @tx.packet_wq: Waitqueue-head for packet transmit completion.
62 * @rx: Receiver subsystem.
63 * @rx.thread: Receiver thread.
64 * @rx.wq: Waitqueue-head for receiver thread.
65 * @rx.fifo: Buffer for receiving data/pushing data to receiver thread.
66 * @rx.buf: Buffer for evaluating data on receiver thread.
67 * @rx.blocked: List of recent/blocked sequence IDs to detect retransmission.
68 * @rx.blocked.seqs: Array of blocked sequence IDs.
69 * @rx.blocked.offset: Offset indicating where a new ID should be inserted.
70 * @rtx_timeout: Retransmission timeout subsystem.
71 * @rtx_timeout.lock: Lock for modifying the retransmission timeout reaper.
72 * @rtx_timeout.timeout: Timeout interval for retransmission.
73 * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled.
74 * @rtx_timeout.reaper: Work performing timeout checks and subsequent actions.
75 * @ops: Packet layer operations.
76 */
77struct ssh_ptl {
78 struct serdev_device *serdev;
79 unsigned long state;
80
81 struct {
82 spinlock_t lock;
83 struct list_head head;
84 } queue;
85
86 struct {
87 spinlock_t lock;
88 struct list_head head;
89 atomic_t count;
90 } pending;
91
92 struct {
93 atomic_t running;
94 struct task_struct *thread;
95 struct completion thread_cplt_tx;
96 struct completion thread_cplt_pkt;
97 struct wait_queue_head packet_wq;
98 } tx;
99
100 struct {
101 struct task_struct *thread;
102 struct wait_queue_head wq;
103 struct kfifo fifo;
104 struct sshp_buf buf;
105
106 struct {
107 u16 seqs[8];
108 u16 offset;
109 } blocked;
110 } rx;
111
112 struct {
113 spinlock_t lock;
114 ktime_t timeout;
115 ktime_t expires;
116 struct delayed_work reaper;
117 } rtx_timeout;
118
119 struct ssh_ptl_ops ops;
120};
121
122#define __ssam_prcond(func, p, fmt, ...) \
123 do { \
124 typeof(p) __p = (p); \
125 \
126 if (__p) \
127 func(__p, fmt, ##__VA_ARGS__); \
128 } while (0)
129
130#define ptl_dbg(p, fmt, ...) dev_dbg(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
131#define ptl_info(p, fmt, ...) dev_info(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
132#define ptl_warn(p, fmt, ...) dev_warn(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
133#define ptl_err(p, fmt, ...) dev_err(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
134#define ptl_dbg_cond(p, fmt, ...) __ssam_prcond(ptl_dbg, p, fmt, ##__VA_ARGS__)
135
136#define to_ssh_ptl(ptr, member) \
137 container_of(ptr, struct ssh_ptl, member)
138
139int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,
140 struct ssh_ptl_ops *ops);
141
142void ssh_ptl_destroy(struct ssh_ptl *ptl);
143
144/**
145 * ssh_ptl_get_device() - Get device associated with packet transport layer.
146 * @ptl: The packet transport layer.
147 *
148 * Return: Returns the device on which the given packet transport layer builds
149 * upon.
150 */
151static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl)
152{
153 return ptl->serdev ? &ptl->serdev->dev : NULL;
154}
155
156int ssh_ptl_tx_start(struct ssh_ptl *ptl);
157int ssh_ptl_tx_stop(struct ssh_ptl *ptl);
158int ssh_ptl_rx_start(struct ssh_ptl *ptl);
159int ssh_ptl_rx_stop(struct ssh_ptl *ptl);
160void ssh_ptl_shutdown(struct ssh_ptl *ptl);
161
162int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p);
163void ssh_ptl_cancel(struct ssh_packet *p);
164
165int ssh_ptl_rx_rcvbuf(struct ssh_ptl *ptl, const u8 *buf, size_t n);
166
167/**
168 * ssh_ptl_tx_wakeup_transfer() - Wake up packet transmitter thread for
169 * transfer.
170 * @ptl: The packet transport layer.
171 *
172 * Wakes up the packet transmitter thread, notifying it that the underlying
173 * transport has more space for data to be transmitted. If the packet
174 * transport layer has been shut down, calls to this function will be ignored.
175 */
176static inline void ssh_ptl_tx_wakeup_transfer(struct ssh_ptl *ptl)
177{
178 if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
179 return;
180
181 complete(&ptl->tx.thread_cplt_tx);
182}
183
184void ssh_packet_init(struct ssh_packet *packet, unsigned long type,
185 u8 priority, const struct ssh_packet_ops *ops);
186
187int ssh_ctrl_packet_cache_init(void);
188void ssh_ctrl_packet_cache_destroy(void);
189
190#endif /* _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H */
drivers/platform/surface/aggregator/ssh_parser.c+228−0
@@ -0,0 +1,228 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * SSH message parser.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#include <asm/unaligned.h>
9#include <linux/compiler.h>
10#include <linux/device.h>
11#include <linux/types.h>
12
13#include <linux/surface_aggregator/serial_hub.h>
14#include "ssh_parser.h"
15
16/**
17 * sshp_validate_crc() - Validate a CRC in raw message data.
18 * @src: The span of data over which the CRC should be computed.
19 * @crc: The pointer to the expected u16 CRC value.
20 *
21 * Computes the CRC of the provided data span (@src), compares it to the CRC
22 * stored at the given address (@crc), and returns the result of this
23 * comparison, i.e. %true if equal. This function is intended to run on raw
24 * input/message data.
25 *
26 * Return: Returns %true if the computed CRC matches the stored CRC, %false
27 * otherwise.
28 */
29static bool sshp_validate_crc(const struct ssam_span *src, const u8 *crc)
30{
31 u16 actual = ssh_crc(src->ptr, src->len);
32 u16 expected = get_unaligned_le16(crc);
33
34 return actual == expected;
35}
36
37/**
38 * sshp_starts_with_syn() - Check if the given data starts with SSH SYN bytes.
39 * @src: The data span to check the start of.
40 */
41static bool sshp_starts_with_syn(const struct ssam_span *src)
42{
43 return src->len >= 2 && get_unaligned_le16(src->ptr) == SSH_MSG_SYN;
44}
45
46/**
47 * sshp_find_syn() - Find SSH SYN bytes in the given data span.
48 * @src: The data span to search in.
49 * @rem: The span (output) indicating the remaining data, starting with SSH
50 * SYN bytes, if found.
51 *
52 * Search for SSH SYN bytes in the given source span. If found, set the @rem
53 * span to the remaining data, starting with the first SYN bytes and capped by
54 * the source span length, and return %true. This function does not copy any
55 * data, but rather only sets pointers to the respective start addresses and
56 * length values.
57 *
58 * If no SSH SYN bytes could be found, set the @rem span to the zero-length
59 * span at the end of the source span and return %false.
60 *
61 * If partial SSH SYN bytes could be found at the end of the source span, set
62 * the @rem span to cover these partial SYN bytes, capped by the end of the
63 * source span, and return %false. This function should then be re-run once
64 * more data is available.
65 *
66 * Return: Returns %true if a complete SSH SYN sequence could be found,
67 * %false otherwise.
68 */
69bool sshp_find_syn(const struct ssam_span *src, struct ssam_span *rem)
70{
71 size_t i;
72
73 for (i = 0; i < src->len - 1; i++) {
74 if (likely(get_unaligned_le16(src->ptr + i) == SSH_MSG_SYN)) {
75 rem->ptr = src->ptr + i;
76 rem->len = src->len - i;
77 return true;
78 }
79 }
80
81 if (unlikely(src->ptr[src->len - 1] == (SSH_MSG_SYN & 0xff))) {
82 rem->ptr = src->ptr + src->len - 1;
83 rem->len = 1;
84 return false;
85 }
86
87 rem->ptr = src->ptr + src->len;
88 rem->len = 0;
89 return false;
90}
91
92/**
93 * sshp_parse_frame() - Parse SSH frame.
94 * @dev: The device used for logging.
95 * @source: The source to parse from.
96 * @frame: The parsed frame (output).
97 * @payload: The parsed payload (output).
98 * @maxlen: The maximum supported message length.
99 *
100 * Parses and validates a SSH frame, including its payload, from the given
101 * source. Sets the provided @frame pointer to the start of the frame and
102 * writes the limits of the frame payload to the provided @payload span
103 * pointer.
104 *
105 * This function does not copy any data, but rather only validates the message
106 * data and sets pointers (and length values) to indicate the respective parts.
107 *
108 * If no complete SSH frame could be found, the frame pointer will be set to
109 * the %NULL pointer and the payload span will be set to the null span (start
110 * pointer %NULL, size zero).
111 *
112 * Return: Returns zero on success or if the frame is incomplete, %-ENOMSG if
113 * the start of the message is invalid, %-EBADMSG if any (frame-header or
114 * payload) CRC is invalid, or %-EMSGSIZE if the SSH message is bigger than
115 * the maximum message length specified in the @maxlen parameter.
116 */
117int sshp_parse_frame(const struct device *dev, const struct ssam_span *source,
118 struct ssh_frame **frame, struct ssam_span *payload,
119 size_t maxlen)
120{
121 struct ssam_span sf;
122 struct ssam_span sp;
123
124 /* Initialize output. */
125 *frame = NULL;
126 payload->ptr = NULL;
127 payload->len = 0;
128
129 if (!sshp_starts_with_syn(source)) {
130 dev_warn(dev, "rx: parser: invalid start of frame\n");
131 return -ENOMSG;
132 }
133
134 /* Check for minimum packet length. */
135 if (unlikely(source->len < SSH_MESSAGE_LENGTH(0))) {
136 dev_dbg(dev, "rx: parser: not enough data for frame\n");
137 return 0;
138 }
139
140 /* Pin down frame. */
141 sf.ptr = source->ptr + sizeof(u16);
142 sf.len = sizeof(struct ssh_frame);
143
144 /* Validate frame CRC. */
145 if (unlikely(!sshp_validate_crc(&sf, sf.ptr + sf.len))) {
146 dev_warn(dev, "rx: parser: invalid frame CRC\n");
147 return -EBADMSG;
148 }
149
150 /* Ensure packet does not exceed maximum length. */
151 sp.len = get_unaligned_le16(&((struct ssh_frame *)sf.ptr)->len);
152 if (unlikely(SSH_MESSAGE_LENGTH(sp.len) > maxlen)) {
153 dev_warn(dev, "rx: parser: frame too large: %llu bytes\n",
154 SSH_MESSAGE_LENGTH(sp.len));
155 return -EMSGSIZE;
156 }
157
158 /* Pin down payload. */
159 sp.ptr = sf.ptr + sf.len + sizeof(u16);
160
161 /* Check for frame + payload length. */
162 if (source->len < SSH_MESSAGE_LENGTH(sp.len)) {
163 dev_dbg(dev, "rx: parser: not enough data for payload\n");
164 return 0;
165 }
166
167 /* Validate payload CRC. */
168 if (unlikely(!sshp_validate_crc(&sp, sp.ptr + sp.len))) {
169 dev_warn(dev, "rx: parser: invalid payload CRC\n");
170 return -EBADMSG;
171 }
172
173 *frame = (struct ssh_frame *)sf.ptr;
174 *payload = sp;
175
176 dev_dbg(dev, "rx: parser: valid frame found (type: %#04x, len: %u)\n",
177 (*frame)->type, (*frame)->len);
178
179 return 0;
180}
181
182/**
183 * sshp_parse_command() - Parse SSH command frame payload.
184 * @dev: The device used for logging.
185 * @source: The source to parse from.
186 * @command: The parsed command (output).
187 * @command_data: The parsed command data/payload (output).
188 *
189 * Parses and validates a SSH command frame payload. Sets the @command pointer
190 * to the command header and the @command_data span to the command data (i.e.
191 * payload of the command). This will result in a zero-length span if the
192 * command does not have any associated data/payload. This function does not
193 * check the frame-payload-type field, which should be checked by the caller
194 * before calling this function.
195 *
196 * The @source parameter should be the complete frame payload, e.g. returned
197 * by the sshp_parse_frame() command.
198 *
199 * This function does not copy any data, but rather only validates the frame
200 * payload data and sets pointers (and length values) to indicate the
201 * respective parts.
202 *
203 * Return: Returns zero on success or %-ENOMSG if @source does not represent a
204 * valid command-type frame payload, i.e. is too short.
205 */
206int sshp_parse_command(const struct device *dev, const struct ssam_span *source,
207 struct ssh_command **command,
208 struct ssam_span *command_data)
209{
210 /* Check for minimum length. */
211 if (unlikely(source->len < sizeof(struct ssh_command))) {
212 *command = NULL;
213 command_data->ptr = NULL;
214 command_data->len = 0;
215
216 dev_err(dev, "rx: parser: command payload is too short\n");
217 return -ENOMSG;
218 }
219
220 *command = (struct ssh_command *)source->ptr;
221 command_data->ptr = source->ptr + sizeof(struct ssh_command);
222 command_data->len = source->len - sizeof(struct ssh_command);
223
224 dev_dbg(dev, "rx: parser: valid command found (tc: %#04x, cid: %#04x)\n",
225 (*command)->tc, (*command)->cid);
226
227 return 0;
228}
drivers/platform/surface/aggregator/ssh_parser.h+154−0
@@ -0,0 +1,154 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * SSH message parser.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
9#define _SURFACE_AGGREGATOR_SSH_PARSER_H
10
11#include <linux/device.h>
12#include <linux/kfifo.h>
13#include <linux/slab.h>
14#include <linux/types.h>
15
16#include <linux/surface_aggregator/serial_hub.h>
17
18/**
19 * struct sshp_buf - Parser buffer for SSH messages.
20 * @ptr: Pointer to the beginning of the buffer.
21 * @len: Number of bytes used in the buffer.
22 * @cap: Maximum capacity of the buffer.
23 */
24struct sshp_buf {
25 u8 *ptr;
26 size_t len;
27 size_t cap;
28};
29
30/**
31 * sshp_buf_init() - Initialize a SSH parser buffer.
32 * @buf: The buffer to initialize.
33 * @ptr: The memory backing the buffer.
34 * @cap: The length of the memory backing the buffer, i.e. its capacity.
35 *
36 * Initializes the buffer with the given memory as backing and set its used
37 * length to zero.
38 */
39static inline void sshp_buf_init(struct sshp_buf *buf, u8 *ptr, size_t cap)
40{
41 buf->ptr = ptr;
42 buf->len = 0;
43 buf->cap = cap;
44}
45
46/**
47 * sshp_buf_alloc() - Allocate and initialize a SSH parser buffer.
48 * @buf: The buffer to initialize/allocate to.
49 * @cap: The desired capacity of the buffer.
50 * @flags: The flags used for allocating the memory.
51 *
52 * Allocates @cap bytes and initializes the provided buffer struct with the
53 * allocated memory.
54 *
55 * Return: Returns zero on success and %-ENOMEM if allocation failed.
56 */
57static inline int sshp_buf_alloc(struct sshp_buf *buf, size_t cap, gfp_t flags)
58{
59 u8 *ptr;
60
61 ptr = kzalloc(cap, flags);
62 if (!ptr)
63 return -ENOMEM;
64
65 sshp_buf_init(buf, ptr, cap);
66 return 0;
67}
68
69/**
70 * sshp_buf_free() - Free a SSH parser buffer.
71 * @buf: The buffer to free.
72 *
73 * Frees a SSH parser buffer by freeing the memory backing it and then
74 * resetting its pointer to %NULL and length and capacity to zero. Intended to
75 * free a buffer previously allocated with sshp_buf_alloc().
76 */
77static inline void sshp_buf_free(struct sshp_buf *buf)
78{
79 kfree(buf->ptr);
80 buf->ptr = NULL;
81 buf->len = 0;
82 buf->cap = 0;
83}
84
85/**
86 * sshp_buf_drop() - Drop data from the beginning of the buffer.
87 * @buf: The buffer to drop data from.
88 * @n: The number of bytes to drop.
89 *
90 * Drops the first @n bytes from the buffer. Re-aligns any remaining data to
91 * the beginning of the buffer.
92 */
93static inline void sshp_buf_drop(struct sshp_buf *buf, size_t n)
94{
95 memmove(buf->ptr, buf->ptr + n, buf->len - n);
96 buf->len -= n;
97}
98
99/**
100 * sshp_buf_read_from_fifo() - Transfer data from a fifo to the buffer.
101 * @buf: The buffer to write the data into.
102 * @fifo: The fifo to read the data from.
103 *
104 * Transfers the data contained in the fifo to the buffer, removing it from
105 * the fifo. This function will try to transfer as much data as possible,
106 * limited either by the remaining space in the buffer or by the number of
107 * bytes available in the fifo.
108 *
109 * Return: Returns the number of bytes transferred.
110 */
111static inline size_t sshp_buf_read_from_fifo(struct sshp_buf *buf,
112 struct kfifo *fifo)
113{
114 size_t n;
115
116 n = kfifo_out(fifo, buf->ptr + buf->len, buf->cap - buf->len);
117 buf->len += n;
118
119 return n;
120}
121
122/**
123 * sshp_buf_span_from() - Initialize a span from the given buffer and offset.
124 * @buf: The buffer to create the span from.
125 * @offset: The offset in the buffer at which the span should start.
126 * @span: The span to initialize (output).
127 *
128 * Initializes the provided span to point to the memory at the given offset in
129 * the buffer, with the length of the span being capped by the number of bytes
130 * used in the buffer after the offset (i.e. bytes remaining after the
131 * offset).
132 *
133 * Warning: This function does not validate that @offset is less than or equal
134 * to the number of bytes used in the buffer or the buffer capacity. This must
135 * be guaranteed by the caller.
136 */
137static inline void sshp_buf_span_from(struct sshp_buf *buf, size_t offset,
138 struct ssam_span *span)
139{
140 span->ptr = buf->ptr + offset;
141 span->len = buf->len - offset;
142}
143
144bool sshp_find_syn(const struct ssam_span *src, struct ssam_span *rem);
145
146int sshp_parse_frame(const struct device *dev, const struct ssam_span *source,
147 struct ssh_frame **frame, struct ssam_span *payload,
148 size_t maxlen);
149
150int sshp_parse_command(const struct device *dev, const struct ssam_span *source,
151 struct ssh_command **command,
152 struct ssam_span *command_data);
153
154#endif /* _SURFACE_AGGREGATOR_SSH_PARSER_h */
drivers/platform/surface/aggregator/ssh_request_layer.c+1263−0
@@ -0,0 +1,1263 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * SSH request transport layer.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#include <asm/unaligned.h>
9#include <linux/atomic.h>
10#include <linux/completion.h>
11#include <linux/error-injection.h>
12#include <linux/ktime.h>
13#include <linux/limits.h>
14#include <linux/list.h>
15#include <linux/slab.h>
16#include <linux/spinlock.h>
17#include <linux/types.h>
18#include <linux/workqueue.h>
19
20#include <linux/surface_aggregator/serial_hub.h>
21#include <linux/surface_aggregator/controller.h>
22
23#include "ssh_packet_layer.h"
24#include "ssh_request_layer.h"
25
26#include "trace.h"
27
28/*
29 * SSH_RTL_REQUEST_TIMEOUT - Request timeout.
30 *
31 * Timeout as ktime_t delta for request responses. If we have not received a
32 * response in this time-frame after finishing the underlying packet
33 * transmission, the request will be completed with %-ETIMEDOUT as status
34 * code.
35 */
36#define SSH_RTL_REQUEST_TIMEOUT ms_to_ktime(3000)
37
38/*
39 * SSH_RTL_REQUEST_TIMEOUT_RESOLUTION - Request timeout granularity.
40 *
41 * Time-resolution for timeouts. Should be larger than one jiffy to avoid
42 * direct re-scheduling of reaper work_struct.
43 */
44#define SSH_RTL_REQUEST_TIMEOUT_RESOLUTION ms_to_ktime(max(2000 / HZ, 50))
45
46/*
47 * SSH_RTL_MAX_PENDING - Maximum number of pending requests.
48 *
49 * Maximum number of requests concurrently waiting to be completed (i.e.
50 * waiting for the corresponding packet transmission to finish if they don't
51 * have a response or waiting for a response if they have one).
52 */
53#define SSH_RTL_MAX_PENDING 3
54
55/*
56 * SSH_RTL_TX_BATCH - Maximum number of requests processed per work execution.
57 * Used to prevent livelocking of the workqueue. Value chosen via educated
58 * guess, may be adjusted.
59 */
60#define SSH_RTL_TX_BATCH 10
61
62#ifdef CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION
63
64/**
65 * ssh_rtl_should_drop_response() - Error injection hook to drop request
66 * responses.
67 *
68 * Useful to cause request transmission timeouts in the driver by dropping the
69 * response to a request.
70 */
71static noinline bool ssh_rtl_should_drop_response(void)
72{
73 return false;
74}
75ALLOW_ERROR_INJECTION(ssh_rtl_should_drop_response, TRUE);
76
77#else
78
79static inline bool ssh_rtl_should_drop_response(void)
80{
81 return false;
82}
83
84#endif
85
86static u16 ssh_request_get_rqid(struct ssh_request *rqst)
87{
88 return get_unaligned_le16(rqst->packet.data.ptr
89 + SSH_MSGOFFSET_COMMAND(rqid));
90}
91
92static u32 ssh_request_get_rqid_safe(struct ssh_request *rqst)
93{
94 if (!rqst->packet.data.ptr)
95 return U32_MAX;
96
97 return ssh_request_get_rqid(rqst);
98}
99
100static void ssh_rtl_queue_remove(struct ssh_request *rqst)
101{
102 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
103
104 spin_lock(&rtl->queue.lock);
105
106 if (!test_and_clear_bit(SSH_REQUEST_SF_QUEUED_BIT, &rqst->state)) {
107 spin_unlock(&rtl->queue.lock);
108 return;
109 }
110
111 list_del(&rqst->node);
112
113 spin_unlock(&rtl->queue.lock);
114 ssh_request_put(rqst);
115}
116
117static bool ssh_rtl_queue_empty(struct ssh_rtl *rtl)
118{
119 bool empty;
120
121 spin_lock(&rtl->queue.lock);
122 empty = list_empty(&rtl->queue.head);
123 spin_unlock(&rtl->queue.lock);
124
125 return empty;
126}
127
128static void ssh_rtl_pending_remove(struct ssh_request *rqst)
129{
130 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
131
132 spin_lock(&rtl->pending.lock);
133
134 if (!test_and_clear_bit(SSH_REQUEST_SF_PENDING_BIT, &rqst->state)) {
135 spin_unlock(&rtl->pending.lock);
136 return;
137 }
138
139 atomic_dec(&rtl->pending.count);
140 list_del(&rqst->node);
141
142 spin_unlock(&rtl->pending.lock);
143
144 ssh_request_put(rqst);
145}
146
147static int ssh_rtl_tx_pending_push(struct ssh_request *rqst)
148{
149 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
150
151 spin_lock(&rtl->pending.lock);
152
153 if (test_bit(SSH_REQUEST_SF_LOCKED_BIT, &rqst->state)) {
154 spin_unlock(&rtl->pending.lock);
155 return -EINVAL;
156 }
157
158 if (test_and_set_bit(SSH_REQUEST_SF_PENDING_BIT, &rqst->state)) {
159 spin_unlock(&rtl->pending.lock);
160 return -EALREADY;
161 }
162
163 atomic_inc(&rtl->pending.count);
164 list_add_tail(&ssh_request_get(rqst)->node, &rtl->pending.head);
165
166 spin_unlock(&rtl->pending.lock);
167 return 0;
168}
169
170static void ssh_rtl_complete_with_status(struct ssh_request *rqst, int status)
171{
172 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
173
174 trace_ssam_request_complete(rqst, status);
175
176 /* rtl/ptl may not be set if we're canceling before submitting. */
177 rtl_dbg_cond(rtl, "rtl: completing request (rqid: %#06x, status: %d)\n",
178 ssh_request_get_rqid_safe(rqst), status);
179
180 rqst->ops->complete(rqst, NULL, NULL, status);
181}
182
183static void ssh_rtl_complete_with_rsp(struct ssh_request *rqst,
184 const struct ssh_command *cmd,
185 const struct ssam_span *data)
186{
187 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
188
189 trace_ssam_request_complete(rqst, 0);
190
191 rtl_dbg(rtl, "rtl: completing request with response (rqid: %#06x)\n",
192 ssh_request_get_rqid(rqst));
193
194 rqst->ops->complete(rqst, cmd, data, 0);
195}
196
197static bool ssh_rtl_tx_can_process(struct ssh_request *rqst)
198{
199 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
200
201 if (test_bit(SSH_REQUEST_TY_FLUSH_BIT, &rqst->state))
202 return !atomic_read(&rtl->pending.count);
203
204 return atomic_read(&rtl->pending.count) < SSH_RTL_MAX_PENDING;
205}
206
207static struct ssh_request *ssh_rtl_tx_next(struct ssh_rtl *rtl)
208{
209 struct ssh_request *rqst = ERR_PTR(-ENOENT);
210 struct ssh_request *p, *n;
211
212 spin_lock(&rtl->queue.lock);
213
214 /* Find first non-locked request and remove it. */
215 list_for_each_entry_safe(p, n, &rtl->queue.head, node) {
216 if (unlikely(test_bit(SSH_REQUEST_SF_LOCKED_BIT, &p->state)))
217 continue;
218
219 if (!ssh_rtl_tx_can_process(p)) {
220 rqst = ERR_PTR(-EBUSY);
221 break;
222 }
223
224 /* Remove from queue and mark as transmitting. */
225 set_bit(SSH_REQUEST_SF_TRANSMITTING_BIT, &p->state);
226 /* Ensure state never gets zero. */
227 smp_mb__before_atomic();
228 clear_bit(SSH_REQUEST_SF_QUEUED_BIT, &p->state);
229
230 list_del(&p->node);
231
232 rqst = p;
233 break;
234 }
235
236 spin_unlock(&rtl->queue.lock);
237 return rqst;
238}
239
240static int ssh_rtl_tx_try_process_one(struct ssh_rtl *rtl)
241{
242 struct ssh_request *rqst;
243 int status;
244
245 /* Get and prepare next request for transmit. */
246 rqst = ssh_rtl_tx_next(rtl);
247 if (IS_ERR(rqst))
248 return PTR_ERR(rqst);
249
250 /* Add it to/mark it as pending. */
251 status = ssh_rtl_tx_pending_push(rqst);
252 if (status) {
253 ssh_request_put(rqst);
254 return -EAGAIN;
255 }
256
257 /* Submit packet. */
258 status = ssh_ptl_submit(&rtl->ptl, &rqst->packet);
259 if (status == -ESHUTDOWN) {
260 /*
261 * Packet has been refused due to the packet layer shutting
262 * down. Complete it here.
263 */
264 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &rqst->state);
265 /*
266 * Note: A barrier is not required here, as there are only two
267 * references in the system at this point: The one that we have,
268 * and the other one that belongs to the pending set. Due to the
269 * request being marked as "transmitting", our process is the
270 * only one allowed to remove the pending node and change the
271 * state. Normally, the task would fall to the packet callback,
272 * but as this is a path where submission failed, this callback
273 * will never be executed.
274 */
275
276 ssh_rtl_pending_remove(rqst);
277 ssh_rtl_complete_with_status(rqst, -ESHUTDOWN);
278
279 ssh_request_put(rqst);
280 return -ESHUTDOWN;
281
282 } else if (status) {
283 /*
284 * If submitting the packet failed and the packet layer isn't
285 * shutting down, the packet has either been submitted/queued
286 * before (-EALREADY, which cannot happen as we have
287 * guaranteed that requests cannot be re-submitted), or the
288 * packet was marked as locked (-EINVAL). To mark the packet
289 * locked at this stage, the request, and thus the packets
290 * itself, had to have been canceled. Simply drop the
291 * reference. Cancellation itself will remove it from the set
292 * of pending requests.
293 */
294
295 WARN_ON(status != -EINVAL);
296
297 ssh_request_put(rqst);
298 return -EAGAIN;
299 }
300
301 ssh_request_put(rqst);
302 return 0;
303}
304
305static bool ssh_rtl_tx_schedule(struct ssh_rtl *rtl)
306{
307 if (atomic_read(&rtl->pending.count) >= SSH_RTL_MAX_PENDING)
308 return false;
309
310 if (ssh_rtl_queue_empty(rtl))
311 return false;
312
313 return schedule_work(&rtl->tx.work);
314}
315
316static void ssh_rtl_tx_work_fn(struct work_struct *work)
317{
318 struct ssh_rtl *rtl = to_ssh_rtl(work, tx.work);
319 unsigned int iterations = SSH_RTL_TX_BATCH;
320 int status;
321
322 /*
323 * Try to be nice and not block/live-lock the workqueue: Run a maximum
324 * of 10 tries, then re-submit if necessary. This should not be
325 * necessary for normal execution, but guarantee it anyway.
326 */
327 do {
328 status = ssh_rtl_tx_try_process_one(rtl);
329 if (status == -ENOENT || status == -EBUSY)
330 return; /* No more requests to process. */
331
332 if (status == -ESHUTDOWN) {
333 /*
334 * Packet system shutting down. No new packets can be
335 * transmitted. Return silently, the party initiating
336 * the shutdown should handle the rest.
337 */
338 return;
339 }
340
341 WARN_ON(status != 0 && status != -EAGAIN);
342 } while (--iterations);
343
344 /* Out of tries, reschedule. */
345 ssh_rtl_tx_schedule(rtl);
346}
347
348/**
349 * ssh_rtl_submit() - Submit a request to the transport layer.
350 * @rtl: The request transport layer.
351 * @rqst: The request to submit.
352 *
353 * Submits a request to the transport layer. A single request may not be
354 * submitted multiple times without reinitializing it.
355 *
356 * Return: Returns zero on success, %-EINVAL if the request type is invalid or
357 * the request has been canceled prior to submission, %-EALREADY if the
358 * request has already been submitted, or %-ESHUTDOWN in case the request
359 * transport layer has been shut down.
360 */
361int ssh_rtl_submit(struct ssh_rtl *rtl, struct ssh_request *rqst)
362{
363 trace_ssam_request_submit(rqst);
364
365 /*
366 * Ensure that requests expecting a response are sequenced. If this
367 * invariant ever changes, see the comment in ssh_rtl_complete() on what
368 * is required to be changed in the code.
369 */
370 if (test_bit(SSH_REQUEST_TY_HAS_RESPONSE_BIT, &rqst->state))
371 if (!test_bit(SSH_PACKET_TY_SEQUENCED_BIT, &rqst->packet.state))
372 return -EINVAL;
373
374 spin_lock(&rtl->queue.lock);
375
376 /*
377 * Try to set ptl and check if this request has already been submitted.
378 *
379 * Must be inside lock as we might run into a lost update problem
380 * otherwise: If this were outside of the lock, cancellation in
381 * ssh_rtl_cancel_nonpending() may run after we've set the ptl
382 * reference but before we enter the lock. In that case, we'd detect
383 * that the request is being added to the queue and would try to remove
384 * it from that, but removal might fail because it hasn't actually been
385 * added yet. By putting this cmpxchg in the critical section, we
386 * ensure that the queuing detection only triggers when we are already
387 * in the critical section and the remove process will wait until the
388 * push operation has been completed (via lock) due to that. Only then,
389 * we can safely try to remove it.
390 */
391 if (cmpxchg(&rqst->packet.ptl, NULL, &rtl->ptl)) {
392 spin_unlock(&rtl->queue.lock);
393 return -EALREADY;
394 }
395
396 /*
397 * Ensure that we set ptl reference before we continue modifying state.
398 * This is required for non-pending cancellation. This barrier is paired
399 * with the one in ssh_rtl_cancel_nonpending().
400 *
401 * By setting the ptl reference before we test for "locked", we can
402 * check if the "locked" test may have already run. See comments in
403 * ssh_rtl_cancel_nonpending() for more detail.
404 */
405 smp_mb__after_atomic();
406
407 if (test_bit(SSH_RTL_SF_SHUTDOWN_BIT, &rtl->state)) {
408 spin_unlock(&rtl->queue.lock);
409 return -ESHUTDOWN;
410 }
411
412 if (test_bit(SSH_REQUEST_SF_LOCKED_BIT, &rqst->state)) {
413 spin_unlock(&rtl->queue.lock);
414 return -EINVAL;
415 }
416
417 set_bit(SSH_REQUEST_SF_QUEUED_BIT, &rqst->state);
418 list_add_tail(&ssh_request_get(rqst)->node, &rtl->queue.head);
419
420 spin_unlock(&rtl->queue.lock);
421
422 ssh_rtl_tx_schedule(rtl);
423 return 0;
424}
425
426static void ssh_rtl_timeout_reaper_mod(struct ssh_rtl *rtl, ktime_t now,
427 ktime_t expires)
428{
429 unsigned long delta = msecs_to_jiffies(ktime_ms_delta(expires, now));
430 ktime_t aexp = ktime_add(expires, SSH_RTL_REQUEST_TIMEOUT_RESOLUTION);
431
432 spin_lock(&rtl->rtx_timeout.lock);
433
434 /* Re-adjust / schedule reaper only if it is above resolution delta. */
435 if (ktime_before(aexp, rtl->rtx_timeout.expires)) {
436 rtl->rtx_timeout.expires = expires;
437 mod_delayed_work(system_wq, &rtl->rtx_timeout.reaper, delta);
438 }
439
440 spin_unlock(&rtl->rtx_timeout.lock);
441}
442
443static void ssh_rtl_timeout_start(struct ssh_request *rqst)
444{
445 struct ssh_rtl *rtl = ssh_request_rtl(rqst);
446 ktime_t timestamp = ktime_get_coarse_boottime();
447 ktime_t timeout = rtl->rtx_timeout.timeout;
448
449 if (test_bit(SSH_REQUEST_SF_LOCKED_BIT, &rqst->state))
450 return;
451
452 /*
453 * Note: The timestamp gets set only once. This happens on the packet
454 * callback. All other access to it is read-only.
455 */
456 WRITE_ONCE(rqst->timestamp, timestamp);
457 /*
458 * Ensure timestamp is set before starting the reaper. Paired with
459 * implicit barrier following check on ssh_request_get_expiration() in
460 * ssh_rtl_timeout_reap.
461 */
462 smp_mb__after_atomic();
463
464 ssh_rtl_timeout_reaper_mod(rtl, timestamp, timestamp + timeout);
465}
466
467static void ssh_rtl_complete(struct ssh_rtl *rtl,
468 const struct ssh_command *command,
469 const struct ssam_span *command_data)
470{
471 struct ssh_request *r = NULL;
472 struct ssh_request *p, *n;
473 u16 rqid = get_unaligned_le16(&command->rqid);
474
475 trace_ssam_rx_response_received(command, command_data->len);
476
477 /*
478 * Get request from pending based on request ID and mark it as response
479 * received and locked.
480 */
481 spin_lock(&rtl->pending.lock);
482 list_for_each_entry_safe(p, n, &rtl->pending.head, node) {
483 /* We generally expect requests to be processed in order. */
484 if (unlikely(ssh_request_get_rqid(p) != rqid))
485 continue;
486
487 /* Simulate response timeout. */
488 if (ssh_rtl_should_drop_response()) {
489 spin_unlock(&rtl->pending.lock);
490
491 trace_ssam_ei_rx_drop_response(p);
492 rtl_info(rtl, "request error injection: dropping response for request %p\n",
493 &p->packet);
494 return;
495 }
496
497 /*
498 * Mark as "response received" and "locked" as we're going to
499 * complete it.
500 */
501 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &p->state);
502 set_bit(SSH_REQUEST_SF_RSPRCVD_BIT, &p->state);
503 /* Ensure state never gets zero. */
504 smp_mb__before_atomic();
505 clear_bit(SSH_REQUEST_SF_PENDING_BIT, &p->state);
506
507 atomic_dec(&rtl->pending.count);
508 list_del(&p->node);
509
510 r = p;
511 break;
512 }
513 spin_unlock(&rtl->pending.lock);
514
515 if (!r) {
516 rtl_warn(rtl, "rtl: dropping unexpected command message (rqid = %#06x)\n",
517 rqid);
518 return;
519 }
520
521 /* If the request hasn't been completed yet, we will do this now. */
522 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state)) {
523 ssh_request_put(r);
524 ssh_rtl_tx_schedule(rtl);
525 return;
526 }
527
528 /*
529 * Make sure the request has been transmitted. In case of a sequenced
530 * request, we are guaranteed that the completion callback will run on
531 * the receiver thread directly when the ACK for the packet has been
532 * received. Similarly, this function is guaranteed to run on the
533 * receiver thread. Thus we are guaranteed that if the packet has been
534 * successfully transmitted and received an ACK, the transmitted flag
535 * has been set and is visible here.
536 *
537 * We are currently not handling unsequenced packets here, as those
538 * should never expect a response as ensured in ssh_rtl_submit. If this
539 * ever changes, one would have to test for
540 *
541 * (r->state & (transmitting | transmitted))
542 *
543 * on unsequenced packets to determine if they could have been
544 * transmitted. There are no synchronization guarantees as in the
545 * sequenced case, since, in this case, the callback function will not
546 * run on the same thread. Thus an exact determination is impossible.
547 */
548 if (!test_bit(SSH_REQUEST_SF_TRANSMITTED_BIT, &r->state)) {
549 rtl_err(rtl, "rtl: received response before ACK for request (rqid = %#06x)\n",
550 rqid);
551
552 /*
553 * NB: Timeout has already been canceled, request already been
554 * removed from pending and marked as locked and completed. As
555 * we receive a "false" response, the packet might still be
556 * queued though.
557 */
558 ssh_rtl_queue_remove(r);
559
560 ssh_rtl_complete_with_status(r, -EREMOTEIO);
561 ssh_request_put(r);
562
563 ssh_rtl_tx_schedule(rtl);
564 return;
565 }
566
567 /*
568 * NB: Timeout has already been canceled, request already been
569 * removed from pending and marked as locked and completed. The request
570 * can also not be queued any more, as it has been marked as
571 * transmitting and later transmitted. Thus no need to remove it from
572 * anywhere.
573 */
574
575 ssh_rtl_complete_with_rsp(r, command, command_data);
576 ssh_request_put(r);
577
578 ssh_rtl_tx_schedule(rtl);
579}
580
581static bool ssh_rtl_cancel_nonpending(struct ssh_request *r)
582{
583 struct ssh_rtl *rtl;
584 unsigned long flags, fixed;
585 bool remove;
586
587 /*
588 * Handle unsubmitted request: Try to mark the packet as locked,
589 * expecting the state to be zero (i.e. unsubmitted). Note that, if
590 * setting the state worked, we might still be adding the packet to the
591 * queue in a currently executing submit call. In that case, however,
592 * ptl reference must have been set previously, as locked is checked
593 * after setting ptl. Furthermore, when the ptl reference is set, the
594 * submission process is guaranteed to have entered the critical
595 * section. Thus only if we successfully locked this request and ptl is
596 * NULL, we have successfully removed the request, i.e. we are
597 * guaranteed that, due to the "locked" check in ssh_rtl_submit(), the
598 * packet will never be added. Otherwise, we need to try and grab it
599 * from the queue, where we are now guaranteed that the packet is or has
600 * been due to the critical section.
601 *
602 * Note that if the cmpxchg() fails, we are guaranteed that ptl has
603 * been set and is non-NULL, as states can only be nonzero after this
604 * has been set. Also note that we need to fetch the static (type)
605 * flags to ensure that they don't cause the cmpxchg() to fail.
606 */
607 fixed = READ_ONCE(r->state) & SSH_REQUEST_FLAGS_TY_MASK;
608 flags = cmpxchg(&r->state, fixed, SSH_REQUEST_SF_LOCKED_BIT);
609
610 /*
611 * Force correct ordering with regards to state and ptl reference access
612 * to safe-guard cancellation to concurrent submission against a
613 * lost-update problem. First try to exchange state, then also check
614 * ptl if that worked. This barrier is paired with the
615 * one in ssh_rtl_submit().
616 */
617 smp_mb__after_atomic();
618
619 if (flags == fixed && !READ_ONCE(r->packet.ptl)) {
620 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
621 return true;
622
623 ssh_rtl_complete_with_status(r, -ECANCELED);
624 return true;
625 }
626
627 rtl = ssh_request_rtl(r);
628 spin_lock(&rtl->queue.lock);
629
630 /*
631 * Note: 1) Requests cannot be re-submitted. 2) If a request is
632 * queued, it cannot be "transmitting"/"pending" yet. Thus, if we
633 * successfully remove the request here, we have removed all its
634 * occurrences in the system.
635 */
636
637 remove = test_and_clear_bit(SSH_REQUEST_SF_QUEUED_BIT, &r->state);
638 if (!remove) {
639 spin_unlock(&rtl->queue.lock);
640 return false;
641 }
642
643 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state);
644 list_del(&r->node);
645
646 spin_unlock(&rtl->queue.lock);
647
648 ssh_request_put(r); /* Drop reference obtained from queue. */
649
650 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
651 return true;
652
653 ssh_rtl_complete_with_status(r, -ECANCELED);
654 return true;
655}
656
657static bool ssh_rtl_cancel_pending(struct ssh_request *r)
658{
659 /* If the packet is already locked, it's going to be removed shortly. */
660 if (test_and_set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state))
661 return true;
662
663 /*
664 * Now that we have locked the packet, we have guaranteed that it can't
665 * be added to the system any more. If ptl is NULL, the locked
666 * check in ssh_rtl_submit() has not been run and any submission,
667 * currently in progress or called later, won't add the packet. Thus we
668 * can directly complete it.
669 *
670 * The implicit memory barrier of test_and_set_bit() should be enough
671 * to ensure that the correct order (first lock, then check ptl) is
672 * ensured. This is paired with the barrier in ssh_rtl_submit().
673 */
674 if (!READ_ONCE(r->packet.ptl)) {
675 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
676 return true;
677
678 ssh_rtl_complete_with_status(r, -ECANCELED);
679 return true;
680 }
681
682 /*
683 * Try to cancel the packet. If the packet has not been completed yet,
684 * this will subsequently (and synchronously) call the completion
685 * callback of the packet, which will complete the request.
686 */
687 ssh_ptl_cancel(&r->packet);
688
689 /*
690 * If the packet has been completed with success, i.e. has not been
691 * canceled by the above call, the request may not have been completed
692 * yet (may be waiting for a response). Check if we need to do this
693 * here.
694 */
695 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
696 return true;
697
698 ssh_rtl_queue_remove(r);
699 ssh_rtl_pending_remove(r);
700 ssh_rtl_complete_with_status(r, -ECANCELED);
701
702 return true;
703}
704
705/**
706 * ssh_rtl_cancel() - Cancel request.
707 * @rqst: The request to cancel.
708 * @pending: Whether to also cancel pending requests.
709 *
710 * Cancels the given request. If @pending is %false, this will not cancel
711 * pending requests, i.e. requests that have already been submitted to the
712 * packet layer but not been completed yet. If @pending is %true, this will
713 * cancel the given request regardless of the state it is in.
714 *
715 * If the request has been canceled by calling this function, both completion
716 * and release callbacks of the request will be executed in a reasonable
717 * time-frame. This may happen during execution of this function, however,
718 * there is no guarantee for this. For example, a request currently
719 * transmitting will be canceled/completed only after transmission has
720 * completed, and the respective callbacks will be executed on the transmitter
721 * thread, which may happen during, but also some time after execution of the
722 * cancel function.
723 *
724 * Return: Returns %true if the given request has been canceled or completed,
725 * either by this function or prior to calling this function, %false
726 * otherwise. If @pending is %true, this function will always return %true.
727 */
728bool ssh_rtl_cancel(struct ssh_request *rqst, bool pending)
729{
730 struct ssh_rtl *rtl;
731 bool canceled;
732
733 if (test_and_set_bit(SSH_REQUEST_SF_CANCELED_BIT, &rqst->state))
734 return true;
735
736 trace_ssam_request_cancel(rqst);
737
738 if (pending)
739 canceled = ssh_rtl_cancel_pending(rqst);
740 else
741 canceled = ssh_rtl_cancel_nonpending(rqst);
742
743 /* Note: rtl may be NULL if request has not been submitted yet. */
744 rtl = ssh_request_rtl(rqst);
745 if (canceled && rtl)
746 ssh_rtl_tx_schedule(rtl);
747
748 return canceled;
749}
750
751static void ssh_rtl_packet_callback(struct ssh_packet *p, int status)
752{
753 struct ssh_request *r = to_ssh_request(p);
754
755 if (unlikely(status)) {
756 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state);
757
758 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
759 return;
760
761 /*
762 * The packet may get canceled even though it has not been
763 * submitted yet. The request may still be queued. Check the
764 * queue and remove it if necessary. As the timeout would have
765 * been started in this function on success, there's no need
766 * to cancel it here.
767 */
768 ssh_rtl_queue_remove(r);
769 ssh_rtl_pending_remove(r);
770 ssh_rtl_complete_with_status(r, status);
771
772 ssh_rtl_tx_schedule(ssh_request_rtl(r));
773 return;
774 }
775
776 /* Update state: Mark as transmitted and clear transmitting. */
777 set_bit(SSH_REQUEST_SF_TRANSMITTED_BIT, &r->state);
778 /* Ensure state never gets zero. */
779 smp_mb__before_atomic();
780 clear_bit(SSH_REQUEST_SF_TRANSMITTING_BIT, &r->state);
781
782 /* If we expect a response, we just need to start the timeout. */
783 if (test_bit(SSH_REQUEST_TY_HAS_RESPONSE_BIT, &r->state)) {
784 /*
785 * Note: This is the only place where the timestamp gets set,
786 * all other access to it is read-only.
787 */
788 ssh_rtl_timeout_start(r);
789 return;
790 }
791
792 /*
793 * If we don't expect a response, lock, remove, and complete the
794 * request. Note that, at this point, the request is guaranteed to have
795 * left the queue and no timeout has been started. Thus we only need to
796 * remove it from pending. If the request has already been completed (it
797 * may have been canceled) return.
798 */
799
800 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state);
801 if (test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
802 return;
803
804 ssh_rtl_pending_remove(r);
805 ssh_rtl_complete_with_status(r, 0);
806
807 ssh_rtl_tx_schedule(ssh_request_rtl(r));
808}
809
810static ktime_t ssh_request_get_expiration(struct ssh_request *r, ktime_t timeout)
811{
812 ktime_t timestamp = READ_ONCE(r->timestamp);
813
814 if (timestamp != KTIME_MAX)
815 return ktime_add(timestamp, timeout);
816 else
817 return KTIME_MAX;
818}
819
820static void ssh_rtl_timeout_reap(struct work_struct *work)
821{
822 struct ssh_rtl *rtl = to_ssh_rtl(work, rtx_timeout.reaper.work);
823 struct ssh_request *r, *n;
824 LIST_HEAD(claimed);
825 ktime_t now = ktime_get_coarse_boottime();
826 ktime_t timeout = rtl->rtx_timeout.timeout;
827 ktime_t next = KTIME_MAX;
828
829 trace_ssam_rtl_timeout_reap(atomic_read(&rtl->pending.count));
830
831 /*
832 * Mark reaper as "not pending". This is done before checking any
833 * requests to avoid lost-update type problems.
834 */
835 spin_lock(&rtl->rtx_timeout.lock);
836 rtl->rtx_timeout.expires = KTIME_MAX;
837 spin_unlock(&rtl->rtx_timeout.lock);
838
839 spin_lock(&rtl->pending.lock);
840 list_for_each_entry_safe(r, n, &rtl->pending.head, node) {
841 ktime_t expires = ssh_request_get_expiration(r, timeout);
842
843 /*
844 * Check if the timeout hasn't expired yet. Find out next
845 * expiration date to be handled after this run.
846 */
847 if (ktime_after(expires, now)) {
848 next = ktime_before(expires, next) ? expires : next;
849 continue;
850 }
851
852 /* Avoid further transitions if locked. */
853 if (test_and_set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state))
854 continue;
855
856 /*
857 * We have now marked the packet as locked. Thus it cannot be
858 * added to the pending or queued lists again after we've
859 * removed it here. We can therefore re-use the node of this
860 * packet temporarily.
861 */
862
863 clear_bit(SSH_REQUEST_SF_PENDING_BIT, &r->state);
864
865 atomic_dec(&rtl->pending.count);
866 list_del(&r->node);
867
868 list_add_tail(&r->node, &claimed);
869 }
870 spin_unlock(&rtl->pending.lock);
871
872 /* Cancel and complete the request. */
873 list_for_each_entry_safe(r, n, &claimed, node) {
874 trace_ssam_request_timeout(r);
875
876 /*
877 * At this point we've removed the packet from pending. This
878 * means that we've obtained the last (only) reference of the
879 * system to it. Thus we can just complete it.
880 */
881 if (!test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
882 ssh_rtl_complete_with_status(r, -ETIMEDOUT);
883
884 /*
885 * Drop the reference we've obtained by removing it from the
886 * pending set.
887 */
888 list_del(&r->node);
889 ssh_request_put(r);
890 }
891
892 /* Ensure that the reaper doesn't run again immediately. */
893 next = max(next, ktime_add(now, SSH_RTL_REQUEST_TIMEOUT_RESOLUTION));
894 if (next != KTIME_MAX)
895 ssh_rtl_timeout_reaper_mod(rtl, now, next);
896
897 ssh_rtl_tx_schedule(rtl);
898}
899
900static void ssh_rtl_rx_event(struct ssh_rtl *rtl, const struct ssh_command *cmd,
901 const struct ssam_span *data)
902{
903 trace_ssam_rx_event_received(cmd, data->len);
904
905 rtl_dbg(rtl, "rtl: handling event (rqid: %#06x)\n",
906 get_unaligned_le16(&cmd->rqid));
907
908 rtl->ops.handle_event(rtl, cmd, data);
909}
910
911static void ssh_rtl_rx_command(struct ssh_ptl *p, const struct ssam_span *data)
912{
913 struct ssh_rtl *rtl = to_ssh_rtl(p, ptl);
914 struct device *dev = &p->serdev->dev;
915 struct ssh_command *command;
916 struct ssam_span command_data;
917
918 if (sshp_parse_command(dev, data, &command, &command_data))
919 return;
920
921 if (ssh_rqid_is_event(get_unaligned_le16(&command->rqid)))
922 ssh_rtl_rx_event(rtl, command, &command_data);
923 else
924 ssh_rtl_complete(rtl, command, &command_data);
925}
926
927static void ssh_rtl_rx_data(struct ssh_ptl *p, const struct ssam_span *data)
928{
929 if (!data->len) {
930 ptl_err(p, "rtl: rx: no data frame payload\n");
931 return;
932 }
933
934 switch (data->ptr[0]) {
935 case SSH_PLD_TYPE_CMD:
936 ssh_rtl_rx_command(p, data);
937 break;
938
939 default:
940 ptl_err(p, "rtl: rx: unknown frame payload type (type: %#04x)\n",
941 data->ptr[0]);
942 break;
943 }
944}
945
946static void ssh_rtl_packet_release(struct ssh_packet *p)
947{
948 struct ssh_request *rqst;
949
950 rqst = to_ssh_request(p);
951 rqst->ops->release(rqst);
952}
953
954static const struct ssh_packet_ops ssh_rtl_packet_ops = {
955 .complete = ssh_rtl_packet_callback,
956 .release = ssh_rtl_packet_release,
957};
958
959/**
960 * ssh_request_init() - Initialize SSH request.
961 * @rqst: The request to initialize.
962 * @flags: Request flags, determining the type of the request.
963 * @ops: Request operations.
964 *
965 * Initializes the given SSH request and underlying packet. Sets the message
966 * buffer pointer to %NULL and the message buffer length to zero. This buffer
967 * has to be set separately via ssh_request_set_data() before submission and
968 * must contain a valid SSH request message.
969 *
970 * Return: Returns zero on success or %-EINVAL if the given flags are invalid.
971 */
972int ssh_request_init(struct ssh_request *rqst, enum ssam_request_flags flags,
973 const struct ssh_request_ops *ops)
974{
975 unsigned long type = BIT(SSH_PACKET_TY_BLOCKING_BIT);
976
977 /* Unsequenced requests cannot have a response. */
978 if (flags & SSAM_REQUEST_UNSEQUENCED && flags & SSAM_REQUEST_HAS_RESPONSE)
979 return -EINVAL;
980
981 if (!(flags & SSAM_REQUEST_UNSEQUENCED))
982 type |= BIT(SSH_PACKET_TY_SEQUENCED_BIT);
983
984 ssh_packet_init(&rqst->packet, type, SSH_PACKET_PRIORITY(DATA, 0),
985 &ssh_rtl_packet_ops);
986
987 INIT_LIST_HEAD(&rqst->node);
988
989 rqst->state = 0;
990 if (flags & SSAM_REQUEST_HAS_RESPONSE)
991 rqst->state |= BIT(SSH_REQUEST_TY_HAS_RESPONSE_BIT);
992
993 rqst->timestamp = KTIME_MAX;
994 rqst->ops = ops;
995
996 return 0;
997}
998
999/**
1000 * ssh_rtl_init() - Initialize request transport layer.
1001 * @rtl: The request transport layer to initialize.
1002 * @serdev: The underlying serial device, i.e. the lower-level transport.
1003 * @ops: Request transport layer operations.
1004 *
1005 * Initializes the given request transport layer and associated packet
1006 * transport layer. Transmitter and receiver threads must be started
1007 * separately via ssh_rtl_start(), after the request-layer has been
1008 * initialized and the lower-level serial device layer has been set up.
1009 *
1010 * Return: Returns zero on success and a nonzero error code on failure.
1011 */
1012int ssh_rtl_init(struct ssh_rtl *rtl, struct serdev_device *serdev,
1013 const struct ssh_rtl_ops *ops)
1014{
1015 struct ssh_ptl_ops ptl_ops;
1016 int status;
1017
1018 ptl_ops.data_received = ssh_rtl_rx_data;
1019
1020 status = ssh_ptl_init(&rtl->ptl, serdev, &ptl_ops);
1021 if (status)
1022 return status;
1023
1024 spin_lock_init(&rtl->queue.lock);
1025 INIT_LIST_HEAD(&rtl->queue.head);
1026
1027 spin_lock_init(&rtl->pending.lock);
1028 INIT_LIST_HEAD(&rtl->pending.head);
1029 atomic_set_release(&rtl->pending.count, 0);
1030
1031 INIT_WORK(&rtl->tx.work, ssh_rtl_tx_work_fn);
1032
1033 spin_lock_init(&rtl->rtx_timeout.lock);
1034 rtl->rtx_timeout.timeout = SSH_RTL_REQUEST_TIMEOUT;
1035 rtl->rtx_timeout.expires = KTIME_MAX;
1036 INIT_DELAYED_WORK(&rtl->rtx_timeout.reaper, ssh_rtl_timeout_reap);
1037
1038 rtl->ops = *ops;
1039
1040 return 0;
1041}
1042
1043/**
1044 * ssh_rtl_destroy() - Deinitialize request transport layer.
1045 * @rtl: The request transport layer to deinitialize.
1046 *
1047 * Deinitializes the given request transport layer and frees resources
1048 * associated with it. If receiver and/or transmitter threads have been
1049 * started, the layer must first be shut down via ssh_rtl_shutdown() before
1050 * this function can be called.
1051 */
1052void ssh_rtl_destroy(struct ssh_rtl *rtl)
1053{
1054 ssh_ptl_destroy(&rtl->ptl);
1055}
1056
1057/**
1058 * ssh_rtl_start() - Start request transmitter and receiver.
1059 * @rtl: The request transport layer.
1060 *
1061 * Return: Returns zero on success, a negative error code on failure.
1062 */
1063int ssh_rtl_start(struct ssh_rtl *rtl)
1064{
1065 int status;
1066
1067 status = ssh_ptl_tx_start(&rtl->ptl);
1068 if (status)
1069 return status;
1070
1071 ssh_rtl_tx_schedule(rtl);
1072
1073 status = ssh_ptl_rx_start(&rtl->ptl);
1074 if (status) {
1075 ssh_rtl_flush(rtl, msecs_to_jiffies(5000));
1076 ssh_ptl_tx_stop(&rtl->ptl);
1077 return status;
1078 }
1079
1080 return 0;
1081}
1082
1083struct ssh_flush_request {
1084 struct ssh_request base;
1085 struct completion completion;
1086 int status;
1087};
1088
1089static void ssh_rtl_flush_request_complete(struct ssh_request *r,
1090 const struct ssh_command *cmd,
1091 const struct ssam_span *data,
1092 int status)
1093{
1094 struct ssh_flush_request *rqst;
1095
1096 rqst = container_of(r, struct ssh_flush_request, base);
1097 rqst->status = status;
1098}
1099
1100static void ssh_rtl_flush_request_release(struct ssh_request *r)
1101{
1102 struct ssh_flush_request *rqst;
1103
1104 rqst = container_of(r, struct ssh_flush_request, base);
1105 complete_all(&rqst->completion);
1106}
1107
1108static const struct ssh_request_ops ssh_rtl_flush_request_ops = {
1109 .complete = ssh_rtl_flush_request_complete,
1110 .release = ssh_rtl_flush_request_release,
1111};
1112
1113/**
1114 * ssh_rtl_flush() - Flush the request transport layer.
1115 * @rtl: request transport layer
1116 * @timeout: timeout for the flush operation in jiffies
1117 *
1118 * Queue a special flush request and wait for its completion. This request
1119 * will be completed after all other currently queued and pending requests
1120 * have been completed. Instead of a normal data packet, this request submits
1121 * a special flush packet, meaning that upon completion, also the underlying
1122 * packet transport layer has been flushed.
1123 *
1124 * Flushing the request layer guarantees that all previously submitted
1125 * requests have been fully completed before this call returns. Additionally,
1126 * flushing blocks execution of all later submitted requests until the flush
1127 * has been completed.
1128 *
1129 * If the caller ensures that no new requests are submitted after a call to
1130 * this function, the request transport layer is guaranteed to have no
1131 * remaining requests when this call returns. The same guarantee does not hold
1132 * for the packet layer, on which control packets may still be queued after
1133 * this call.
1134 *
1135 * Return: Returns zero on success, %-ETIMEDOUT if the flush timed out and has
1136 * been canceled as a result of the timeout, or %-ESHUTDOWN if the packet
1137 * and/or request transport layer has been shut down before this call. May
1138 * also return %-EINTR if the underlying packet transmission has been
1139 * interrupted.
1140 */
1141int ssh_rtl_flush(struct ssh_rtl *rtl, unsigned long timeout)
1142{
1143 const unsigned int init_flags = SSAM_REQUEST_UNSEQUENCED;
1144 struct ssh_flush_request rqst;
1145 int status;
1146
1147 ssh_request_init(&rqst.base, init_flags, &ssh_rtl_flush_request_ops);
1148 rqst.base.packet.state |= BIT(SSH_PACKET_TY_FLUSH_BIT);
1149 rqst.base.packet.priority = SSH_PACKET_PRIORITY(FLUSH, 0);
1150 rqst.base.state |= BIT(SSH_REQUEST_TY_FLUSH_BIT);
1151
1152 init_completion(&rqst.completion);
1153
1154 status = ssh_rtl_submit(rtl, &rqst.base);
1155 if (status)
1156 return status;
1157
1158 ssh_request_put(&rqst.base);
1159
1160 if (!wait_for_completion_timeout(&rqst.completion, timeout)) {
1161 ssh_rtl_cancel(&rqst.base, true);
1162 wait_for_completion(&rqst.completion);
1163 }
1164
1165 WARN_ON(rqst.status != 0 && rqst.status != -ECANCELED &&
1166 rqst.status != -ESHUTDOWN && rqst.status != -EINTR);
1167
1168 return rqst.status == -ECANCELED ? -ETIMEDOUT : rqst.status;
1169}
1170
1171/**
1172 * ssh_rtl_shutdown() - Shut down request transport layer.
1173 * @rtl: The request transport layer.
1174 *
1175 * Shuts down the request transport layer, removing and canceling all queued
1176 * and pending requests. Requests canceled by this operation will be completed
1177 * with %-ESHUTDOWN as status. Receiver and transmitter threads will be
1178 * stopped, the lower-level packet layer will be shutdown.
1179 *
1180 * As a result of this function, the transport layer will be marked as shut
1181 * down. Submission of requests after the transport layer has been shut down
1182 * will fail with %-ESHUTDOWN.
1183 */
1184void ssh_rtl_shutdown(struct ssh_rtl *rtl)
1185{
1186 struct ssh_request *r, *n;
1187 LIST_HEAD(claimed);
1188 int pending;
1189
1190 set_bit(SSH_RTL_SF_SHUTDOWN_BIT, &rtl->state);
1191 /*
1192 * Ensure that the layer gets marked as shut-down before actually
1193 * stopping it. In combination with the check in ssh_rtl_submit(),
1194 * this guarantees that no new requests can be added and all already
1195 * queued requests are properly canceled.
1196 */
1197 smp_mb__after_atomic();
1198
1199 /* Remove requests from queue. */
1200 spin_lock(&rtl->queue.lock);
1201 list_for_each_entry_safe(r, n, &rtl->queue.head, node) {
1202 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state);
1203 /* Ensure state never gets zero. */
1204 smp_mb__before_atomic();
1205 clear_bit(SSH_REQUEST_SF_QUEUED_BIT, &r->state);
1206
1207 list_del(&r->node);
1208 list_add_tail(&r->node, &claimed);
1209 }
1210 spin_unlock(&rtl->queue.lock);
1211
1212 /*
1213 * We have now guaranteed that the queue is empty and no more new
1214 * requests can be submitted (i.e. it will stay empty). This means that
1215 * calling ssh_rtl_tx_schedule() will not schedule tx.work any more. So
1216 * we can simply call cancel_work_sync() on tx.work here and when that
1217 * returns, we've locked it down. This also means that after this call,
1218 * we don't submit any more packets to the underlying packet layer, so
1219 * we can also shut that down.
1220 */
1221
1222 cancel_work_sync(&rtl->tx.work);
1223 ssh_ptl_shutdown(&rtl->ptl);
1224 cancel_delayed_work_sync(&rtl->rtx_timeout.reaper);
1225
1226 /*
1227 * Shutting down the packet layer should also have canceled all
1228 * requests. Thus the pending set should be empty. Attempt to handle
1229 * this gracefully anyways, even though this should be dead code.
1230 */
1231
1232 pending = atomic_read(&rtl->pending.count);
1233 if (WARN_ON(pending)) {
1234 spin_lock(&rtl->pending.lock);
1235 list_for_each_entry_safe(r, n, &rtl->pending.head, node) {
1236 set_bit(SSH_REQUEST_SF_LOCKED_BIT, &r->state);
1237 /* Ensure state never gets zero. */
1238 smp_mb__before_atomic();
1239 clear_bit(SSH_REQUEST_SF_PENDING_BIT, &r->state);
1240
1241 list_del(&r->node);
1242 list_add_tail(&r->node, &claimed);
1243 }
1244 spin_unlock(&rtl->pending.lock);
1245 }
1246
1247 /* Finally, cancel and complete the requests we claimed before. */
1248 list_for_each_entry_safe(r, n, &claimed, node) {
1249 /*
1250 * We need test_and_set() because we still might compete with
1251 * cancellation.
1252 */
1253 if (!test_and_set_bit(SSH_REQUEST_SF_COMPLETED_BIT, &r->state))
1254 ssh_rtl_complete_with_status(r, -ESHUTDOWN);
1255
1256 /*
1257 * Drop the reference we've obtained by removing it from the
1258 * lists.
1259 */
1260 list_del(&r->node);
1261 ssh_request_put(r);
1262 }
1263}
drivers/platform/surface/aggregator/ssh_request_layer.h+143−0
@@ -0,0 +1,143 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * SSH request transport layer.
4 *
5 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
9#define _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
10
11#include <linux/atomic.h>
12#include <linux/ktime.h>
13#include <linux/list.h>
14#include <linux/spinlock.h>
15#include <linux/workqueue.h>
16
17#include <linux/surface_aggregator/serial_hub.h>
18#include <linux/surface_aggregator/controller.h>
19
20#include "ssh_packet_layer.h"
21
22/**
23 * enum ssh_rtl_state_flags - State-flags for &struct ssh_rtl.
24 *
25 * @SSH_RTL_SF_SHUTDOWN_BIT:
26 * Indicates that the request transport layer has been shut down or is
27 * being shut down and should not accept any new requests.
28 */
29enum ssh_rtl_state_flags {
30 SSH_RTL_SF_SHUTDOWN_BIT,
31};
32
33/**
34 * struct ssh_rtl_ops - Callback operations for request transport layer.
35 * @handle_event: Function called when a SSH event has been received. The
36 * specified function takes the request layer, received command
37 * struct, and corresponding payload as arguments. If the event
38 * has no payload, the payload span is empty (not %NULL).
39 */
40struct ssh_rtl_ops {
41 void (*handle_event)(struct ssh_rtl *rtl, const struct ssh_command *cmd,
42 const struct ssam_span *data);
43};
44
45/**
46 * struct ssh_rtl - SSH request transport layer.
47 * @ptl: Underlying packet transport layer.
48 * @state: State(-flags) of the transport layer.
49 * @queue: Request submission queue.
50 * @queue.lock: Lock for modifying the request submission queue.
51 * @queue.head: List-head of the request submission queue.
52 * @pending: Set/list of pending requests.
53 * @pending.lock: Lock for modifying the request set.
54 * @pending.head: List-head of the pending set/list.
55 * @pending.count: Number of currently pending requests.
56 * @tx: Transmitter subsystem.
57 * @tx.work: Transmitter work item.
58 * @rtx_timeout: Retransmission timeout subsystem.
59 * @rtx_timeout.lock: Lock for modifying the retransmission timeout reaper.
60 * @rtx_timeout.timeout: Timeout interval for retransmission.
61 * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled.
62 * @rtx_timeout.reaper: Work performing timeout checks and subsequent actions.
63 * @ops: Request layer operations.
64 */
65struct ssh_rtl {
66 struct ssh_ptl ptl;
67 unsigned long state;
68
69 struct {
70 spinlock_t lock;
71 struct list_head head;
72 } queue;
73
74 struct {
75 spinlock_t lock;
76 struct list_head head;
77 atomic_t count;
78 } pending;
79
80 struct {
81 struct work_struct work;
82 } tx;
83
84 struct {
85 spinlock_t lock;
86 ktime_t timeout;
87 ktime_t expires;
88 struct delayed_work reaper;
89 } rtx_timeout;
90
91 struct ssh_rtl_ops ops;
92};
93
94#define rtl_dbg(r, fmt, ...) ptl_dbg(&(r)->ptl, fmt, ##__VA_ARGS__)
95#define rtl_info(p, fmt, ...) ptl_info(&(p)->ptl, fmt, ##__VA_ARGS__)
96#define rtl_warn(r, fmt, ...) ptl_warn(&(r)->ptl, fmt, ##__VA_ARGS__)
97#define rtl_err(r, fmt, ...) ptl_err(&(r)->ptl, fmt, ##__VA_ARGS__)
98#define rtl_dbg_cond(r, fmt, ...) __ssam_prcond(rtl_dbg, r, fmt, ##__VA_ARGS__)
99
100#define to_ssh_rtl(ptr, member) \
101 container_of(ptr, struct ssh_rtl, member)
102
103/**
104 * ssh_rtl_get_device() - Get device associated with request transport layer.
105 * @rtl: The request transport layer.
106 *
107 * Return: Returns the device on which the given request transport layer
108 * builds upon.
109 */
110static inline struct device *ssh_rtl_get_device(struct ssh_rtl *rtl)
111{
112 return ssh_ptl_get_device(&rtl->ptl);
113}
114
115/**
116 * ssh_request_rtl() - Get request transport layer associated with request.
117 * @rqst: The request to get the request transport layer reference for.
118 *
119 * Return: Returns the &struct ssh_rtl associated with the given SSH request.
120 */
121static inline struct ssh_rtl *ssh_request_rtl(struct ssh_request *rqst)
122{
123 struct ssh_ptl *ptl;
124
125 ptl = READ_ONCE(rqst->packet.ptl);
126 return likely(ptl) ? to_ssh_rtl(ptl, ptl) : NULL;
127}
128
129int ssh_rtl_submit(struct ssh_rtl *rtl, struct ssh_request *rqst);
130bool ssh_rtl_cancel(struct ssh_request *rqst, bool pending);
131
132int ssh_rtl_init(struct ssh_rtl *rtl, struct serdev_device *serdev,
133 const struct ssh_rtl_ops *ops);
134
135int ssh_rtl_start(struct ssh_rtl *rtl);
136int ssh_rtl_flush(struct ssh_rtl *rtl, unsigned long timeout);
137void ssh_rtl_shutdown(struct ssh_rtl *rtl);
138void ssh_rtl_destroy(struct ssh_rtl *rtl);
139
140int ssh_request_init(struct ssh_request *rqst, enum ssam_request_flags flags,
141 const struct ssh_request_ops *ops);
142
143#endif /* _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H */
drivers/platform/surface/aggregator/trace.h+632−0
@@ -0,0 +1,632 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Trace points for SSAM/SSH.
4 *
5 * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
6 */
7
8#undef TRACE_SYSTEM
9#define TRACE_SYSTEM surface_aggregator
10
11#if !defined(_SURFACE_AGGREGATOR_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
12#define _SURFACE_AGGREGATOR_TRACE_H
13
14#include <linux/surface_aggregator/serial_hub.h>
15
16#include <asm/unaligned.h>
17#include <linux/tracepoint.h>
18
19TRACE_DEFINE_ENUM(SSH_FRAME_TYPE_DATA_SEQ);
20TRACE_DEFINE_ENUM(SSH_FRAME_TYPE_DATA_NSQ);
21TRACE_DEFINE_ENUM(SSH_FRAME_TYPE_ACK);
22TRACE_DEFINE_ENUM(SSH_FRAME_TYPE_NAK);
23
24TRACE_DEFINE_ENUM(SSH_PACKET_SF_LOCKED_BIT);
25TRACE_DEFINE_ENUM(SSH_PACKET_SF_QUEUED_BIT);
26TRACE_DEFINE_ENUM(SSH_PACKET_SF_PENDING_BIT);
27TRACE_DEFINE_ENUM(SSH_PACKET_SF_TRANSMITTING_BIT);
28TRACE_DEFINE_ENUM(SSH_PACKET_SF_TRANSMITTED_BIT);
29TRACE_DEFINE_ENUM(SSH_PACKET_SF_ACKED_BIT);
30TRACE_DEFINE_ENUM(SSH_PACKET_SF_CANCELED_BIT);
31TRACE_DEFINE_ENUM(SSH_PACKET_SF_COMPLETED_BIT);
32
33TRACE_DEFINE_ENUM(SSH_PACKET_TY_FLUSH_BIT);
34TRACE_DEFINE_ENUM(SSH_PACKET_TY_SEQUENCED_BIT);
35TRACE_DEFINE_ENUM(SSH_PACKET_TY_BLOCKING_BIT);
36
37TRACE_DEFINE_ENUM(SSH_PACKET_FLAGS_SF_MASK);
38TRACE_DEFINE_ENUM(SSH_PACKET_FLAGS_TY_MASK);
39
40TRACE_DEFINE_ENUM(SSH_REQUEST_SF_LOCKED_BIT);
41TRACE_DEFINE_ENUM(SSH_REQUEST_SF_QUEUED_BIT);
42TRACE_DEFINE_ENUM(SSH_REQUEST_SF_PENDING_BIT);
43TRACE_DEFINE_ENUM(SSH_REQUEST_SF_TRANSMITTING_BIT);
44TRACE_DEFINE_ENUM(SSH_REQUEST_SF_TRANSMITTED_BIT);
45TRACE_DEFINE_ENUM(SSH_REQUEST_SF_RSPRCVD_BIT);
46TRACE_DEFINE_ENUM(SSH_REQUEST_SF_CANCELED_BIT);
47TRACE_DEFINE_ENUM(SSH_REQUEST_SF_COMPLETED_BIT);
48
49TRACE_DEFINE_ENUM(SSH_REQUEST_TY_FLUSH_BIT);
50TRACE_DEFINE_ENUM(SSH_REQUEST_TY_HAS_RESPONSE_BIT);
51
52TRACE_DEFINE_ENUM(SSH_REQUEST_FLAGS_SF_MASK);
53TRACE_DEFINE_ENUM(SSH_REQUEST_FLAGS_TY_MASK);
54
55TRACE_DEFINE_ENUM(SSAM_SSH_TC_SAM);
56TRACE_DEFINE_ENUM(SSAM_SSH_TC_BAT);
57TRACE_DEFINE_ENUM(SSAM_SSH_TC_TMP);
58TRACE_DEFINE_ENUM(SSAM_SSH_TC_PMC);
59TRACE_DEFINE_ENUM(SSAM_SSH_TC_FAN);
60TRACE_DEFINE_ENUM(SSAM_SSH_TC_PoM);
61TRACE_DEFINE_ENUM(SSAM_SSH_TC_DBG);
62TRACE_DEFINE_ENUM(SSAM_SSH_TC_KBD);
63TRACE_DEFINE_ENUM(SSAM_SSH_TC_FWU);
64TRACE_DEFINE_ENUM(SSAM_SSH_TC_UNI);
65TRACE_DEFINE_ENUM(SSAM_SSH_TC_LPC);
66TRACE_DEFINE_ENUM(SSAM_SSH_TC_TCL);
67TRACE_DEFINE_ENUM(SSAM_SSH_TC_SFL);
68TRACE_DEFINE_ENUM(SSAM_SSH_TC_KIP);
69TRACE_DEFINE_ENUM(SSAM_SSH_TC_EXT);
70TRACE_DEFINE_ENUM(SSAM_SSH_TC_BLD);
71TRACE_DEFINE_ENUM(SSAM_SSH_TC_BAS);
72TRACE_DEFINE_ENUM(SSAM_SSH_TC_SEN);
73TRACE_DEFINE_ENUM(SSAM_SSH_TC_SRQ);
74TRACE_DEFINE_ENUM(SSAM_SSH_TC_MCU);
75TRACE_DEFINE_ENUM(SSAM_SSH_TC_HID);
76TRACE_DEFINE_ENUM(SSAM_SSH_TC_TCH);
77TRACE_DEFINE_ENUM(SSAM_SSH_TC_BKL);
78TRACE_DEFINE_ENUM(SSAM_SSH_TC_TAM);
79TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC);
80TRACE_DEFINE_ENUM(SSAM_SSH_TC_UFI);
81TRACE_DEFINE_ENUM(SSAM_SSH_TC_USC);
82TRACE_DEFINE_ENUM(SSAM_SSH_TC_PEN);
83TRACE_DEFINE_ENUM(SSAM_SSH_TC_VID);
84TRACE_DEFINE_ENUM(SSAM_SSH_TC_AUD);
85TRACE_DEFINE_ENUM(SSAM_SSH_TC_SMC);
86TRACE_DEFINE_ENUM(SSAM_SSH_TC_KPD);
87TRACE_DEFINE_ENUM(SSAM_SSH_TC_REG);
88
89#define SSAM_PTR_UID_LEN 9
90#define SSAM_U8_FIELD_NOT_APPLICABLE ((u16)-1)
91#define SSAM_SEQ_NOT_APPLICABLE ((u16)-1)
92#define SSAM_RQID_NOT_APPLICABLE ((u32)-1)
93#define SSAM_SSH_TC_NOT_APPLICABLE 0
94
95#ifndef _SURFACE_AGGREGATOR_TRACE_HELPERS
96#define _SURFACE_AGGREGATOR_TRACE_HELPERS
97
98/**
99 * ssam_trace_ptr_uid() - Convert the pointer to a non-pointer UID string.
100 * @ptr: The pointer to convert.
101 * @uid_str: A buffer of length SSAM_PTR_UID_LEN where the UID will be stored.
102 *
103 * Converts the given pointer into a UID string that is safe to be shared
104 * with userspace and logs, i.e. doesn't give away the real memory location.
105 */
106static inline void ssam_trace_ptr_uid(const void *ptr, char *uid_str)
107{
108 char buf[2 * sizeof(void *) + 1];
109
110 BUILD_BUG_ON(ARRAY_SIZE(buf) < SSAM_PTR_UID_LEN);
111
112 snprintf(buf, ARRAY_SIZE(buf), "%p", ptr);
113 memcpy(uid_str, &buf[ARRAY_SIZE(buf) - SSAM_PTR_UID_LEN],
114 SSAM_PTR_UID_LEN);
115}
116
117/**
118 * ssam_trace_get_packet_seq() - Read the packet's sequence ID.
119 * @p: The packet.
120 *
121 * Return: Returns the packet's sequence ID (SEQ) field if present, or
122 * %SSAM_SEQ_NOT_APPLICABLE if not (e.g. flush packet).
123 */
124static inline u16 ssam_trace_get_packet_seq(const struct ssh_packet *p)
125{
126 if (!p->data.ptr || p->data.len < SSH_MESSAGE_LENGTH(0))
127 return SSAM_SEQ_NOT_APPLICABLE;
128
129 return p->data.ptr[SSH_MSGOFFSET_FRAME(seq)];
130}
131
132/**
133 * ssam_trace_get_request_id() - Read the packet's request ID.
134 * @p: The packet.
135 *
136 * Return: Returns the packet's request ID (RQID) field if the packet
137 * represents a request with command data, or %SSAM_RQID_NOT_APPLICABLE if not
138 * (e.g. flush request, control packet).
139 */
140static inline u32 ssam_trace_get_request_id(const struct ssh_packet *p)
141{
142 if (!p->data.ptr || p->data.len < SSH_COMMAND_MESSAGE_LENGTH(0))
143 return SSAM_RQID_NOT_APPLICABLE;
144
145 return get_unaligned_le16(&p->data.ptr[SSH_MSGOFFSET_COMMAND(rqid)]);
146}
147
148/**
149 * ssam_trace_get_request_tc() - Read the packet's request target category.
150 * @p: The packet.
151 *
152 * Return: Returns the packet's request target category (TC) field if the
153 * packet represents a request with command data, or %SSAM_TC_NOT_APPLICABLE
154 * if not (e.g. flush request, control packet).
155 */
156static inline u32 ssam_trace_get_request_tc(const struct ssh_packet *p)
157{
158 if (!p->data.ptr || p->data.len < SSH_COMMAND_MESSAGE_LENGTH(0))
159 return SSAM_SSH_TC_NOT_APPLICABLE;
160
161 return get_unaligned_le16(&p->data.ptr[SSH_MSGOFFSET_COMMAND(tc)]);
162}
163
164#endif /* _SURFACE_AGGREGATOR_TRACE_HELPERS */
165
166#define ssam_trace_get_command_field_u8(packet, field) \
167 ((!(packet) || (packet)->data.len < SSH_COMMAND_MESSAGE_LENGTH(0)) \
168 ? 0 : (packet)->data.ptr[SSH_MSGOFFSET_COMMAND(field)])
169
170#define ssam_show_generic_u8_field(value) \
171 __print_symbolic(value, \
172 { SSAM_U8_FIELD_NOT_APPLICABLE, "N/A" } \
173 )
174
175#define ssam_show_frame_type(ty) \
176 __print_symbolic(ty, \
177 { SSH_FRAME_TYPE_DATA_SEQ, "DSEQ" }, \
178 { SSH_FRAME_TYPE_DATA_NSQ, "DNSQ" }, \
179 { SSH_FRAME_TYPE_ACK, "ACK" }, \
180 { SSH_FRAME_TYPE_NAK, "NAK" } \
181 )
182
183#define ssam_show_packet_type(type) \
184 __print_flags(flags & SSH_PACKET_FLAGS_TY_MASK, "", \
185 { BIT(SSH_PACKET_TY_FLUSH_BIT), "F" }, \
186 { BIT(SSH_PACKET_TY_SEQUENCED_BIT), "S" }, \
187 { BIT(SSH_PACKET_TY_BLOCKING_BIT), "B" } \
188 )
189
190#define ssam_show_packet_state(state) \
191 __print_flags(flags & SSH_PACKET_FLAGS_SF_MASK, "", \
192 { BIT(SSH_PACKET_SF_LOCKED_BIT), "L" }, \
193 { BIT(SSH_PACKET_SF_QUEUED_BIT), "Q" }, \
194 { BIT(SSH_PACKET_SF_PENDING_BIT), "P" }, \
195 { BIT(SSH_PACKET_SF_TRANSMITTING_BIT), "S" }, \
196 { BIT(SSH_PACKET_SF_TRANSMITTED_BIT), "T" }, \
197 { BIT(SSH_PACKET_SF_ACKED_BIT), "A" }, \
198 { BIT(SSH_PACKET_SF_CANCELED_BIT), "C" }, \
199 { BIT(SSH_PACKET_SF_COMPLETED_BIT), "F" } \
200 )
201
202#define ssam_show_packet_seq(seq) \
203 __print_symbolic(seq, \
204 { SSAM_SEQ_NOT_APPLICABLE, "N/A" } \
205 )
206
207#define ssam_show_request_type(flags) \
208 __print_flags((flags) & SSH_REQUEST_FLAGS_TY_MASK, "", \
209 { BIT(SSH_REQUEST_TY_FLUSH_BIT), "F" }, \
210 { BIT(SSH_REQUEST_TY_HAS_RESPONSE_BIT), "R" } \
211 )
212
213#define ssam_show_request_state(flags) \
214 __print_flags((flags) & SSH_REQUEST_FLAGS_SF_MASK, "", \
215 { BIT(SSH_REQUEST_SF_LOCKED_BIT), "L" }, \
216 { BIT(SSH_REQUEST_SF_QUEUED_BIT), "Q" }, \
217 { BIT(SSH_REQUEST_SF_PENDING_BIT), "P" }, \
218 { BIT(SSH_REQUEST_SF_TRANSMITTING_BIT), "S" }, \
219 { BIT(SSH_REQUEST_SF_TRANSMITTED_BIT), "T" }, \
220 { BIT(SSH_REQUEST_SF_RSPRCVD_BIT), "A" }, \
221 { BIT(SSH_REQUEST_SF_CANCELED_BIT), "C" }, \
222 { BIT(SSH_REQUEST_SF_COMPLETED_BIT), "F" } \
223 )
224
225#define ssam_show_request_id(rqid) \
226 __print_symbolic(rqid, \
227 { SSAM_RQID_NOT_APPLICABLE, "N/A" } \
228 )
229
230#define ssam_show_ssh_tc(rqid) \
231 __print_symbolic(rqid, \
232 { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
233 { SSAM_SSH_TC_SAM, "SAM" }, \
234 { SSAM_SSH_TC_BAT, "BAT" }, \
235 { SSAM_SSH_TC_TMP, "TMP" }, \
236 { SSAM_SSH_TC_PMC, "PMC" }, \
237 { SSAM_SSH_TC_FAN, "FAN" }, \
238 { SSAM_SSH_TC_PoM, "PoM" }, \
239 { SSAM_SSH_TC_DBG, "DBG" }, \
240 { SSAM_SSH_TC_KBD, "KBD" }, \
241 { SSAM_SSH_TC_FWU, "FWU" }, \
242 { SSAM_SSH_TC_UNI, "UNI" }, \
243 { SSAM_SSH_TC_LPC, "LPC" }, \
244 { SSAM_SSH_TC_TCL, "TCL" }, \
245 { SSAM_SSH_TC_SFL, "SFL" }, \
246 { SSAM_SSH_TC_KIP, "KIP" }, \
247 { SSAM_SSH_TC_EXT, "EXT" }, \
248 { SSAM_SSH_TC_BLD, "BLD" }, \
249 { SSAM_SSH_TC_BAS, "BAS" }, \
250 { SSAM_SSH_TC_SEN, "SEN" }, \
251 { SSAM_SSH_TC_SRQ, "SRQ" }, \
252 { SSAM_SSH_TC_MCU, "MCU" }, \
253 { SSAM_SSH_TC_HID, "HID" }, \
254 { SSAM_SSH_TC_TCH, "TCH" }, \
255 { SSAM_SSH_TC_BKL, "BKL" }, \
256 { SSAM_SSH_TC_TAM, "TAM" }, \
257 { SSAM_SSH_TC_ACC, "ACC" }, \
258 { SSAM_SSH_TC_UFI, "UFI" }, \
259 { SSAM_SSH_TC_USC, "USC" }, \
260 { SSAM_SSH_TC_PEN, "PEN" }, \
261 { SSAM_SSH_TC_VID, "VID" }, \
262 { SSAM_SSH_TC_AUD, "AUD" }, \
263 { SSAM_SSH_TC_SMC, "SMC" }, \
264 { SSAM_SSH_TC_KPD, "KPD" }, \
265 { SSAM_SSH_TC_REG, "REG" } \
266 )
267
268DECLARE_EVENT_CLASS(ssam_frame_class,
269 TP_PROTO(const struct ssh_frame *frame),
270
271 TP_ARGS(frame),
272
273 TP_STRUCT__entry(
274 __field(u8, type)
275 __field(u8, seq)
276 __field(u16, len)
277 ),
278
279 TP_fast_assign(
280 __entry->type = frame->type;
281 __entry->seq = frame->seq;
282 __entry->len = get_unaligned_le16(&frame->len);
283 ),
284
285 TP_printk("ty=%s, seq=%#04x, len=%u",
286 ssam_show_frame_type(__entry->type),
287 __entry->seq,
288 __entry->len
289 )
290);
291
292#define DEFINE_SSAM_FRAME_EVENT(name) \
293 DEFINE_EVENT(ssam_frame_class, ssam_##name, \
294 TP_PROTO(const struct ssh_frame *frame), \
295 TP_ARGS(frame) \
296 )
297
298DECLARE_EVENT_CLASS(ssam_command_class,
299 TP_PROTO(const struct ssh_command *cmd, u16 len),
300
301 TP_ARGS(cmd, len),
302
303 TP_STRUCT__entry(
304 __field(u16, rqid)
305 __field(u16, len)
306 __field(u8, tc)
307 __field(u8, cid)
308 __field(u8, iid)
309 ),
310
311 TP_fast_assign(
312 __entry->rqid = get_unaligned_le16(&cmd->rqid);
313 __entry->tc = cmd->tc;
314 __entry->cid = cmd->cid;
315 __entry->iid = cmd->iid;
316 __entry->len = len;
317 ),
318
319 TP_printk("rqid=%#06x, tc=%s, cid=%#04x, iid=%#04x, len=%u",
320 __entry->rqid,
321 ssam_show_ssh_tc(__entry->tc),
322 __entry->cid,
323 __entry->iid,
324 __entry->len
325 )
326);
327
328#define DEFINE_SSAM_COMMAND_EVENT(name) \
329 DEFINE_EVENT(ssam_command_class, ssam_##name, \
330 TP_PROTO(const struct ssh_command *cmd, u16 len), \
331 TP_ARGS(cmd, len) \
332 )
333
334DECLARE_EVENT_CLASS(ssam_packet_class,
335 TP_PROTO(const struct ssh_packet *packet),
336
337 TP_ARGS(packet),
338
339 TP_STRUCT__entry(
340 __field(unsigned long, state)
341 __array(char, uid, SSAM_PTR_UID_LEN)
342 __field(u8, priority)
343 __field(u16, length)
344 __field(u16, seq)
345 ),
346
347 TP_fast_assign(
348 __entry->state = READ_ONCE(packet->state);
349 ssam_trace_ptr_uid(packet, __entry->uid);
350 __entry->priority = READ_ONCE(packet->priority);
351 __entry->length = packet->data.len;
352 __entry->seq = ssam_trace_get_packet_seq(packet);
353 ),
354
355 TP_printk("uid=%s, seq=%s, ty=%s, pri=%#04x, len=%u, sta=%s",
356 __entry->uid,
357 ssam_show_packet_seq(__entry->seq),
358 ssam_show_packet_type(__entry->state),
359 __entry->priority,
360 __entry->length,
361 ssam_show_packet_state(__entry->state)
362 )
363);
364
365#define DEFINE_SSAM_PACKET_EVENT(name) \
366 DEFINE_EVENT(ssam_packet_class, ssam_##name, \
367 TP_PROTO(const struct ssh_packet *packet), \
368 TP_ARGS(packet) \
369 )
370
371DECLARE_EVENT_CLASS(ssam_packet_status_class,
372 TP_PROTO(const struct ssh_packet *packet, int status),
373
374 TP_ARGS(packet, status),
375
376 TP_STRUCT__entry(
377 __field(unsigned long, state)
378 __field(int, status)
379 __array(char, uid, SSAM_PTR_UID_LEN)
380 __field(u8, priority)
381 __field(u16, length)
382 __field(u16, seq)
383 ),
384
385 TP_fast_assign(
386 __entry->state = READ_ONCE(packet->state);
387 __entry->status = status;
388 ssam_trace_ptr_uid(packet, __entry->uid);
389 __entry->priority = READ_ONCE(packet->priority);
390 __entry->length = packet->data.len;
391 __entry->seq = ssam_trace_get_packet_seq(packet);
392 ),
393
394 TP_printk("uid=%s, seq=%s, ty=%s, pri=%#04x, len=%u, sta=%s, status=%d",
395 __entry->uid,
396 ssam_show_packet_seq(__entry->seq),
397 ssam_show_packet_type(__entry->state),
398 __entry->priority,
399 __entry->length,
400 ssam_show_packet_state(__entry->state),
401 __entry->status
402 )
403);
404
405#define DEFINE_SSAM_PACKET_STATUS_EVENT(name) \
406 DEFINE_EVENT(ssam_packet_status_class, ssam_##name, \
407 TP_PROTO(const struct ssh_packet *packet, int status), \
408 TP_ARGS(packet, status) \
409 )
410
411DECLARE_EVENT_CLASS(ssam_request_class,
412 TP_PROTO(const struct ssh_request *request),
413
414 TP_ARGS(request),
415
416 TP_STRUCT__entry(
417 __field(unsigned long, state)
418 __field(u32, rqid)
419 __array(char, uid, SSAM_PTR_UID_LEN)
420 __field(u8, tc)
421 __field(u16, cid)
422 __field(u16, iid)
423 ),
424
425 TP_fast_assign(
426 const struct ssh_packet *p = &request->packet;
427
428 /* Use packet for UID so we can match requests to packets. */
429 __entry->state = READ_ONCE(request->state);
430 __entry->rqid = ssam_trace_get_request_id(p);
431 ssam_trace_ptr_uid(p, __entry->uid);
432 __entry->tc = ssam_trace_get_request_tc(p);
433 __entry->cid = ssam_trace_get_command_field_u8(p, cid);
434 __entry->iid = ssam_trace_get_command_field_u8(p, iid);
435 ),
436
437 TP_printk("uid=%s, rqid=%s, ty=%s, sta=%s, tc=%s, cid=%s, iid=%s",
438 __entry->uid,
439 ssam_show_request_id(__entry->rqid),
440 ssam_show_request_type(__entry->state),
441 ssam_show_request_state(__entry->state),
442 ssam_show_ssh_tc(__entry->tc),
443 ssam_show_generic_u8_field(__entry->cid),
444 ssam_show_generic_u8_field(__entry->iid)
445 )
446);
447
448#define DEFINE_SSAM_REQUEST_EVENT(name) \
449 DEFINE_EVENT(ssam_request_class, ssam_##name, \
450 TP_PROTO(const struct ssh_request *request), \
451 TP_ARGS(request) \
452 )
453
454DECLARE_EVENT_CLASS(ssam_request_status_class,
455 TP_PROTO(const struct ssh_request *request, int status),
456
457 TP_ARGS(request, status),
458
459 TP_STRUCT__entry(
460 __field(unsigned long, state)
461 __field(u32, rqid)
462 __field(int, status)
463 __array(char, uid, SSAM_PTR_UID_LEN)
464 __field(u8, tc)
465 __field(u16, cid)
466 __field(u16, iid)
467 ),
468
469 TP_fast_assign(
470 const struct ssh_packet *p = &request->packet;
471
472 /* Use packet for UID so we can match requests to packets. */
473 __entry->state = READ_ONCE(request->state);
474 __entry->rqid = ssam_trace_get_request_id(p);
475 __entry->status = status;
476 ssam_trace_ptr_uid(p, __entry->uid);
477 __entry->tc = ssam_trace_get_request_tc(p);
478 __entry->cid = ssam_trace_get_command_field_u8(p, cid);
479 __entry->iid = ssam_trace_get_command_field_u8(p, iid);
480 ),
481
482 TP_printk("uid=%s, rqid=%s, ty=%s, sta=%s, tc=%s, cid=%s, iid=%s, status=%d",
483 __entry->uid,
484 ssam_show_request_id(__entry->rqid),
485 ssam_show_request_type(__entry->state),
486 ssam_show_request_state(__entry->state),
487 ssam_show_ssh_tc(__entry->tc),
488 ssam_show_generic_u8_field(__entry->cid),
489 ssam_show_generic_u8_field(__entry->iid),
490 __entry->status
491 )
492);
493
494#define DEFINE_SSAM_REQUEST_STATUS_EVENT(name) \
495 DEFINE_EVENT(ssam_request_status_class, ssam_##name, \
496 TP_PROTO(const struct ssh_request *request, int status),\
497 TP_ARGS(request, status) \
498 )
499
500DECLARE_EVENT_CLASS(ssam_alloc_class,
501 TP_PROTO(void *ptr, size_t len),
502
503 TP_ARGS(ptr, len),
504
505 TP_STRUCT__entry(
506 __field(size_t, len)
507 __array(char, uid, SSAM_PTR_UID_LEN)
508 ),
509
510 TP_fast_assign(
511 __entry->len = len;
512 ssam_trace_ptr_uid(ptr, __entry->uid);
513 ),
514
515 TP_printk("uid=%s, len=%zu", __entry->uid, __entry->len)
516);
517
518#define DEFINE_SSAM_ALLOC_EVENT(name) \
519 DEFINE_EVENT(ssam_alloc_class, ssam_##name, \
520 TP_PROTO(void *ptr, size_t len), \
521 TP_ARGS(ptr, len) \
522 )
523
524DECLARE_EVENT_CLASS(ssam_free_class,
525 TP_PROTO(void *ptr),
526
527 TP_ARGS(ptr),
528
529 TP_STRUCT__entry(
530 __array(char, uid, SSAM_PTR_UID_LEN)
531 ),
532
533 TP_fast_assign(
534 ssam_trace_ptr_uid(ptr, __entry->uid);
535 ),
536
537 TP_printk("uid=%s", __entry->uid)
538);
539
540#define DEFINE_SSAM_FREE_EVENT(name) \
541 DEFINE_EVENT(ssam_free_class, ssam_##name, \
542 TP_PROTO(void *ptr), \
543 TP_ARGS(ptr) \
544 )
545
546DECLARE_EVENT_CLASS(ssam_pending_class,
547 TP_PROTO(unsigned int pending),
548
549 TP_ARGS(pending),
550
551 TP_STRUCT__entry(
552 __field(unsigned int, pending)
553 ),
554
555 TP_fast_assign(
556 __entry->pending = pending;
557 ),
558
559 TP_printk("pending=%u", __entry->pending)
560);
561
562#define DEFINE_SSAM_PENDING_EVENT(name) \
563 DEFINE_EVENT(ssam_pending_class, ssam_##name, \
564 TP_PROTO(unsigned int pending), \
565 TP_ARGS(pending) \
566 )
567
568DECLARE_EVENT_CLASS(ssam_data_class,
569 TP_PROTO(size_t length),
570
571 TP_ARGS(length),
572
573 TP_STRUCT__entry(
574 __field(size_t, length)
575 ),
576
577 TP_fast_assign(
578 __entry->length = length;
579 ),
580
581 TP_printk("length=%zu", __entry->length)
582);
583
584#define DEFINE_SSAM_DATA_EVENT(name) \
585 DEFINE_EVENT(ssam_data_class, ssam_##name, \
586 TP_PROTO(size_t length), \
587 TP_ARGS(length) \
588 )
589
590DEFINE_SSAM_FRAME_EVENT(rx_frame_received);
591DEFINE_SSAM_COMMAND_EVENT(rx_response_received);
592DEFINE_SSAM_COMMAND_EVENT(rx_event_received);
593
594DEFINE_SSAM_PACKET_EVENT(packet_release);
595DEFINE_SSAM_PACKET_EVENT(packet_submit);
596DEFINE_SSAM_PACKET_EVENT(packet_resubmit);
597DEFINE_SSAM_PACKET_EVENT(packet_timeout);
598DEFINE_SSAM_PACKET_EVENT(packet_cancel);
599DEFINE_SSAM_PACKET_STATUS_EVENT(packet_complete);
600DEFINE_SSAM_PENDING_EVENT(ptl_timeout_reap);
601
602DEFINE_SSAM_REQUEST_EVENT(request_submit);
603DEFINE_SSAM_REQUEST_EVENT(request_timeout);
604DEFINE_SSAM_REQUEST_EVENT(request_cancel);
605DEFINE_SSAM_REQUEST_STATUS_EVENT(request_complete);
606DEFINE_SSAM_PENDING_EVENT(rtl_timeout_reap);
607
608DEFINE_SSAM_PACKET_EVENT(ei_tx_drop_ack_packet);
609DEFINE_SSAM_PACKET_EVENT(ei_tx_drop_nak_packet);
610DEFINE_SSAM_PACKET_EVENT(ei_tx_drop_dsq_packet);
611DEFINE_SSAM_PACKET_STATUS_EVENT(ei_tx_fail_write);
612DEFINE_SSAM_PACKET_EVENT(ei_tx_corrupt_data);
613DEFINE_SSAM_DATA_EVENT(ei_rx_corrupt_syn);
614DEFINE_SSAM_FRAME_EVENT(ei_rx_corrupt_data);
615DEFINE_SSAM_REQUEST_EVENT(ei_rx_drop_response);
616
617DEFINE_SSAM_ALLOC_EVENT(ctrl_packet_alloc);
618DEFINE_SSAM_FREE_EVENT(ctrl_packet_free);
619
620DEFINE_SSAM_ALLOC_EVENT(event_item_alloc);
621DEFINE_SSAM_FREE_EVENT(event_item_free);
622
623#endif /* _SURFACE_AGGREGATOR_TRACE_H */
624
625/* This part must be outside protection */
626#undef TRACE_INCLUDE_PATH
627#undef TRACE_INCLUDE_FILE
628
629#define TRACE_INCLUDE_PATH .
630#define TRACE_INCLUDE_FILE trace
631
632#include <trace/define_trace.h>
drivers/platform/surface/surface3-wmi.c+5−1
@@ -57,12 +57,16 @@ static DEFINE_MUTEX(s3_wmi_lock); · 56 unmodified lines
57static int s3_wmi_query_block(const char *guid, int instance, int *ret)57static int s3_wmi_query_block(const char *guid, int instance, int *ret)
58{58{
59 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };59 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
60 union acpi_object *obj = NULL;
60 acpi_status status;61 acpi_status status;
61 union acpi_object *obj;
62 int error = 0;62 int error = 0;
63 63
64 mutex_lock(&s3_wmi_lock);64 mutex_lock(&s3_wmi_lock);
65 status = wmi_query_block(guid, instance, &output);65 status = wmi_query_block(guid, instance, &output);
66 if (ACPI_FAILURE(status)) {
67 error = -EIO;
68 goto out_free_unlock;
69 }
66 70
67 obj = output.pointer;71 obj = output.pointer;
68 72
drivers/platform/surface/surface_acpi_notify.c+886−0
@@ -0,0 +1,886 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Driver for the Surface ACPI Notify (SAN) interface/shim.
4 *
5 * Translates communication from ACPI to Surface System Aggregator Module
6 * (SSAM/SAM) requests and back, specifically SAM-over-SSH. Translates SSAM
7 * events back to ACPI notifications. Allows handling of discrete GPU
8 * notifications sent from ACPI via the SAN interface by providing them to any
9 * registered external driver.
10 *
11 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
12 */
13
14#include <asm/unaligned.h>
15#include <linux/acpi.h>
16#include <linux/delay.h>
17#include <linux/jiffies.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/notifier.h>
21#include <linux/platform_device.h>
22#include <linux/rwsem.h>
23
24#include <linux/surface_aggregator/controller.h>
25#include <linux/surface_acpi_notify.h>
26
27struct san_data {
28 struct device *dev;
29 struct ssam_controller *ctrl;
30
31 struct acpi_connection_info info;
32
33 struct ssam_event_notifier nf_bat;
34 struct ssam_event_notifier nf_tmp;
35};
36
37#define to_san_data(ptr, member) \
38 container_of(ptr, struct san_data, member)
39
40
41/* -- dGPU notifier interface. ---------------------------------------------- */
42
43struct san_rqsg_if {
44 struct rw_semaphore lock;
45 struct device *dev;
46 struct blocking_notifier_head nh;
47};
48
49static struct san_rqsg_if san_rqsg_if = {
50 .lock = __RWSEM_INITIALIZER(san_rqsg_if.lock),
51 .dev = NULL,
52 .nh = BLOCKING_NOTIFIER_INIT(san_rqsg_if.nh),
53};
54
55static int san_set_rqsg_interface_device(struct device *dev)
56{
57 int status = 0;
58
59 down_write(&san_rqsg_if.lock);
60 if (!san_rqsg_if.dev && dev)
61 san_rqsg_if.dev = dev;
62 else
63 status = -EBUSY;
64 up_write(&san_rqsg_if.lock);
65
66 return status;
67}
68
69/**
70 * san_client_link() - Link client as consumer to SAN device.
71 * @client: The client to link.
72 *
73 * Sets up a device link between the provided client device as consumer and
74 * the SAN device as provider. This function can be used to ensure that the
75 * SAN interface has been set up and will be set up for as long as the driver
76 * of the client device is bound. This guarantees that, during that time, all
77 * dGPU events will be received by any registered notifier.
78 *
79 * The link will be automatically removed once the client device's driver is
80 * unbound.
81 *
82 * Return: Returns zero on success, %-ENXIO if the SAN interface has not been
83 * set up yet, and %-ENOMEM if device link creation failed.
84 */
85int san_client_link(struct device *client)
86{
87 const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;
88 struct device_link *link;
89
90 down_read(&san_rqsg_if.lock);
91
92 if (!san_rqsg_if.dev) {
93 up_read(&san_rqsg_if.lock);
94 return -ENXIO;
95 }
96
97 link = device_link_add(client, san_rqsg_if.dev, flags);
98 if (!link) {
99 up_read(&san_rqsg_if.lock);
100 return -ENOMEM;
101 }
102
103 if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) {
104 up_read(&san_rqsg_if.lock);
105 return -ENXIO;
106 }
107
108 up_read(&san_rqsg_if.lock);
109 return 0;
110}
111EXPORT_SYMBOL_GPL(san_client_link);
112
113/**
114 * san_dgpu_notifier_register() - Register a SAN dGPU notifier.
115 * @nb: The notifier-block to register.
116 *
117 * Registers a SAN dGPU notifier, receiving any new SAN dGPU events sent from
118 * ACPI. The registered notifier will be called with &struct san_dgpu_event
119 * as notifier data and the command ID of that event as notifier action.
120 */
121int san_dgpu_notifier_register(struct notifier_block *nb)
122{
123 return blocking_notifier_chain_register(&san_rqsg_if.nh, nb);
124}
125EXPORT_SYMBOL_GPL(san_dgpu_notifier_register);
126
127/**
128 * san_dgpu_notifier_unregister() - Unregister a SAN dGPU notifier.
129 * @nb: The notifier-block to unregister.
130 */
131int san_dgpu_notifier_unregister(struct notifier_block *nb)
132{
133 return blocking_notifier_chain_unregister(&san_rqsg_if.nh, nb);
134}
135EXPORT_SYMBOL_GPL(san_dgpu_notifier_unregister);
136
137static int san_dgpu_notifier_call(struct san_dgpu_event *evt)
138{
139 int ret;
140
141 ret = blocking_notifier_call_chain(&san_rqsg_if.nh, evt->command, evt);
142 return notifier_to_errno(ret);
143}
144
145
146/* -- ACPI _DSM event relay. ------------------------------------------------ */
147
148#define SAN_DSM_REVISION 0
149
150/* 93b666c5-70c6-469f-a215-3d487c91ab3c */
151static const guid_t SAN_DSM_UUID =
152 GUID_INIT(0x93b666c5, 0x70c6, 0x469f, 0xa2, 0x15, 0x3d,
153 0x48, 0x7c, 0x91, 0xab, 0x3c);
154
155enum san_dsm_event_fn {
156 SAN_DSM_EVENT_FN_BAT1_STAT = 0x03,
157 SAN_DSM_EVENT_FN_BAT1_INFO = 0x04,
158 SAN_DSM_EVENT_FN_ADP1_STAT = 0x05,
159 SAN_DSM_EVENT_FN_ADP1_INFO = 0x06,
160 SAN_DSM_EVENT_FN_BAT2_STAT = 0x07,
161 SAN_DSM_EVENT_FN_BAT2_INFO = 0x08,
162 SAN_DSM_EVENT_FN_THERMAL = 0x09,
163 SAN_DSM_EVENT_FN_DPTF = 0x0a,
164};
165
166enum sam_event_cid_bat {
167 SAM_EVENT_CID_BAT_BIX = 0x15,
168 SAM_EVENT_CID_BAT_BST = 0x16,
169 SAM_EVENT_CID_BAT_ADP = 0x17,
170 SAM_EVENT_CID_BAT_PROT = 0x18,
171 SAM_EVENT_CID_BAT_DPTF = 0x4f,
172};
173
174enum sam_event_cid_tmp {
175 SAM_EVENT_CID_TMP_TRIP = 0x0b,
176};
177
178struct san_event_work {
179 struct delayed_work work;
180 struct device *dev;
181 struct ssam_event event; /* must be last */
182};
183
184static int san_acpi_notify_event(struct device *dev, u64 func,
185 union acpi_object *param)
186{
187 acpi_handle san = ACPI_HANDLE(dev);
188 union acpi_object *obj;
189 int status = 0;
190
191 if (!acpi_check_dsm(san, &SAN_DSM_UUID, SAN_DSM_REVISION, BIT_ULL(func)))
192 return 0;
193
194 dev_dbg(dev, "notify event %#04llx\n", func);
195
196 obj = acpi_evaluate_dsm_typed(san, &SAN_DSM_UUID, SAN_DSM_REVISION,
197 func, param, ACPI_TYPE_BUFFER);
198 if (!obj)
199 return -EFAULT;
200
201 if (obj->buffer.length != 1 || obj->buffer.pointer[0] != 0) {
202 dev_err(dev, "got unexpected result from _DSM\n");
203 status = -EPROTO;
204 }
205
206 ACPI_FREE(obj);
207 return status;
208}
209
210static int san_evt_bat_adp(struct device *dev, const struct ssam_event *event)
211{
212 int status;
213
214 status = san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_ADP1_STAT, NULL);
215 if (status)
216 return status;
217
218 /*
219 * Ensure that the battery states get updated correctly. When the
220 * battery is fully charged and an adapter is plugged in, it sometimes
221 * is not updated correctly, instead showing it as charging.
222 * Explicitly trigger battery updates to fix this.
223 */
224
225 status = san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_BAT1_STAT, NULL);
226 if (status)
227 return status;
228
229 return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_BAT2_STAT, NULL);
230}
231
232static int san_evt_bat_bix(struct device *dev, const struct ssam_event *event)
233{
234 enum san_dsm_event_fn fn;
235
236 if (event->instance_id == 0x02)
237 fn = SAN_DSM_EVENT_FN_BAT2_INFO;
238 else
239 fn = SAN_DSM_EVENT_FN_BAT1_INFO;
240
241 return san_acpi_notify_event(dev, fn, NULL);
242}
243
244static int san_evt_bat_bst(struct device *dev, const struct ssam_event *event)
245{
246 enum san_dsm_event_fn fn;
247
248 if (event->instance_id == 0x02)
249 fn = SAN_DSM_EVENT_FN_BAT2_STAT;
250 else
251 fn = SAN_DSM_EVENT_FN_BAT1_STAT;
252
253 return san_acpi_notify_event(dev, fn, NULL);
254}
255
256static int san_evt_bat_dptf(struct device *dev, const struct ssam_event *event)
257{
258 union acpi_object payload;
259
260 /*
261 * The Surface ACPI expects a buffer and not a package. It specifically
262 * checks for ObjectType (Arg3) == 0x03. This will cause a warning in
263 * acpica/nsarguments.c, but that warning can be safely ignored.
264 */
265 payload.type = ACPI_TYPE_BUFFER;
266 payload.buffer.length = event->length;
267 payload.buffer.pointer = (u8 *)&event->data[0];
268
269 return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_DPTF, &payload);
270}
271
272static unsigned long san_evt_bat_delay(u8 cid)
273{
274 switch (cid) {
275 case SAM_EVENT_CID_BAT_ADP:
276 /*
277 * Wait for battery state to update before signaling adapter
278 * change.
279 */
280 return msecs_to_jiffies(5000);
281
282 case SAM_EVENT_CID_BAT_BST:
283 /* Ensure we do not miss anything important due to caching. */
284 return msecs_to_jiffies(2000);
285
286 default:
287 return 0;
288 }
289}
290
291static bool san_evt_bat(const struct ssam_event *event, struct device *dev)
292{
293 int status;
294
295 switch (event->command_id) {
296 case SAM_EVENT_CID_BAT_BIX:
297 status = san_evt_bat_bix(dev, event);
298 break;
299
300 case SAM_EVENT_CID_BAT_BST:
301 status = san_evt_bat_bst(dev, event);
302 break;
303
304 case SAM_EVENT_CID_BAT_ADP:
305 status = san_evt_bat_adp(dev, event);
306 break;
307
308 case SAM_EVENT_CID_BAT_PROT:
309 /*
310 * TODO: Implement support for battery protection status change
311 * event.
312 */
313 return true;
314
315 case SAM_EVENT_CID_BAT_DPTF:
316 status = san_evt_bat_dptf(dev, event);
317 break;
318
319 default:
320 return false;
321 }
322
323 if (status) {
324 dev_err(dev, "error handling power event (cid = %#04x)\n",
325 event->command_id);
326 }
327
328 return true;
329}
330
331static void san_evt_bat_workfn(struct work_struct *work)
332{
333 struct san_event_work *ev;
334
335 ev = container_of(work, struct san_event_work, work.work);
336 san_evt_bat(&ev->event, ev->dev);
337 kfree(ev);
338}
339
340static u32 san_evt_bat_nf(struct ssam_event_notifier *nf,
341 const struct ssam_event *event)
342{
343 struct san_data *d = to_san_data(nf, nf_bat);
344 struct san_event_work *work;
345 unsigned long delay = san_evt_bat_delay(event->command_id);
346
347 if (delay == 0)
348 return san_evt_bat(event, d->dev) ? SSAM_NOTIF_HANDLED : 0;
349
350 work = kzalloc(sizeof(*work) + event->length, GFP_KERNEL);
351 if (!work)
352 return ssam_notifier_from_errno(-ENOMEM);
353
354 INIT_DELAYED_WORK(&work->work, san_evt_bat_workfn);
355 work->dev = d->dev;
356
357 memcpy(&work->event, event, sizeof(struct ssam_event) + event->length);
358
359 schedule_delayed_work(&work->work, delay);
360 return SSAM_NOTIF_HANDLED;
361}
362
363static int san_evt_tmp_trip(struct device *dev, const struct ssam_event *event)
364{
365 union acpi_object param;
366
367 /*
368 * The Surface ACPI expects an integer and not a package. This will
369 * cause a warning in acpica/nsarguments.c, but that warning can be
370 * safely ignored.
371 */
372 param.type = ACPI_TYPE_INTEGER;
373 param.integer.value = event->instance_id;
374
375 return san_acpi_notify_event(dev, SAN_DSM_EVENT_FN_THERMAL, &param);
376}
377
378static bool san_evt_tmp(const struct ssam_event *event, struct device *dev)
379{
380 int status;
381
382 switch (event->command_id) {
383 case SAM_EVENT_CID_TMP_TRIP:
384 status = san_evt_tmp_trip(dev, event);
385 break;
386
387 default:
388 return false;
389 }
390
391 if (status) {
392 dev_err(dev, "error handling thermal event (cid = %#04x)\n",
393 event->command_id);
394 }
395
396 return true;
397}
398
399static u32 san_evt_tmp_nf(struct ssam_event_notifier *nf,
400 const struct ssam_event *event)
401{
402 struct san_data *d = to_san_data(nf, nf_tmp);
403
404 return san_evt_tmp(event, d->dev) ? SSAM_NOTIF_HANDLED : 0;
405}
406
407
408/* -- ACPI GSB OperationRegion handler -------------------------------------- */
409
410struct gsb_data_in {
411 u8 cv;
412} __packed;
413
414struct gsb_data_rqsx {
415 u8 cv; /* Command value (san_gsb_request_cv). */
416 u8 tc; /* Target category. */
417 u8 tid; /* Target ID. */
418 u8 iid; /* Instance ID. */
419 u8 snc; /* Expect-response-flag. */
420 u8 cid; /* Command ID. */
421 u16 cdl; /* Payload length. */
422 u8 pld[]; /* Payload. */
423} __packed;
424
425struct gsb_data_etwl {
426 u8 cv; /* Command value (should be 0x02). */
427 u8 etw3; /* Unknown. */
428 u8 etw4; /* Unknown. */
429 u8 msg[]; /* Error message (ASCIIZ). */
430} __packed;
431
432struct gsb_data_out {
433 u8 status; /* _SSH communication status. */
434 u8 len; /* _SSH payload length. */
435 u8 pld[]; /* _SSH payload. */
436} __packed;
437
438union gsb_buffer_data {
439 struct gsb_data_in in; /* Common input. */
440 struct gsb_data_rqsx rqsx; /* RQSX input. */
441 struct gsb_data_etwl etwl; /* ETWL input. */
442 struct gsb_data_out out; /* Output. */
443};
444
445struct gsb_buffer {
446 u8 status; /* GSB AttribRawProcess status. */
447 u8 len; /* GSB AttribRawProcess length. */
448 union gsb_buffer_data data;
449} __packed;
450
451#define SAN_GSB_MAX_RQSX_PAYLOAD (U8_MAX - 2 - sizeof(struct gsb_data_rqsx))
452#define SAN_GSB_MAX_RESPONSE (U8_MAX - 2 - sizeof(struct gsb_data_out))
453
454#define SAN_GSB_COMMAND 0
455
456enum san_gsb_request_cv {
457 SAN_GSB_REQUEST_CV_RQST = 0x01,
458 SAN_GSB_REQUEST_CV_ETWL = 0x02,
459 SAN_GSB_REQUEST_CV_RQSG = 0x03,
460};
461
462#define SAN_REQUEST_NUM_TRIES 5
463
464static acpi_status san_etwl(struct san_data *d, struct gsb_buffer *b)
465{
466 struct gsb_data_etwl *etwl = &b->data.etwl;
467
468 if (b->len < sizeof(struct gsb_data_etwl)) {
469 dev_err(d->dev, "invalid ETWL package (len = %d)\n", b->len);
470 return AE_OK;
471 }
472
473 dev_err(d->dev, "ETWL(%#04x, %#04x): %.*s\n", etwl->etw3, etwl->etw4,
474 (unsigned int)(b->len - sizeof(struct gsb_data_etwl)),
475 (char *)etwl->msg);
476
477 /* Indicate success. */
478 b->status = 0x00;
479 b->len = 0x00;
480
481 return AE_OK;
482}
483
484static
485struct gsb_data_rqsx *san_validate_rqsx(struct device *dev, const char *type,
486 struct gsb_buffer *b)
487{
488 struct gsb_data_rqsx *rqsx = &b->data.rqsx;
489
490 if (b->len < sizeof(struct gsb_data_rqsx)) {
491 dev_err(dev, "invalid %s package (len = %d)\n", type, b->len);
492 return NULL;
493 }
494
495 if (get_unaligned(&rqsx->cdl) != b->len - sizeof(struct gsb_data_rqsx)) {
496 dev_err(dev, "bogus %s package (len = %d, cdl = %d)\n",
497 type, b->len, get_unaligned(&rqsx->cdl));
498 return NULL;
499 }
500
501 if (get_unaligned(&rqsx->cdl) > SAN_GSB_MAX_RQSX_PAYLOAD) {
502 dev_err(dev, "payload for %s package too large (cdl = %d)\n",
503 type, get_unaligned(&rqsx->cdl));
504 return NULL;
505 }
506
507 return rqsx;
508}
509
510static void gsb_rqsx_response_error(struct gsb_buffer *gsb, int status)
511{
512 gsb->status = 0x00;
513 gsb->len = 0x02;
514 gsb->data.out.status = (u8)(-status);
515 gsb->data.out.len = 0x00;
516}
517
518static void gsb_rqsx_response_success(struct gsb_buffer *gsb, u8 *ptr, size_t len)
519{
520 gsb->status = 0x00;
521 gsb->len = len + 2;
522 gsb->data.out.status = 0x00;
523 gsb->data.out.len = len;
524
525 if (len)
526 memcpy(&gsb->data.out.pld[0], ptr, len);
527}
528
529static acpi_status san_rqst_fixup_suspended(struct san_data *d,
530 struct ssam_request *rqst,
531 struct gsb_buffer *gsb)
532{
533 if (rqst->target_category == SSAM_SSH_TC_BAS && rqst->command_id == 0x0D) {
534 u8 base_state = 1;
535
536 /* Base state quirk:
537 * The base state may be queried from ACPI when the EC is still
538 * suspended. In this case it will return '-EPERM'. This query
539 * will only be triggered from the ACPI lid GPE interrupt, thus
540 * we are either in laptop or studio mode (base status 0x01 or
541 * 0x02). Furthermore, we will only get here if the device (and
542 * EC) have been suspended.
543 *
544 * We now assume that the device is in laptop mode (0x01). This
545 * has the drawback that it will wake the device when unfolding
546 * it in studio mode, but it also allows us to avoid actively
547 * waiting for the EC to wake up, which may incur a notable
548 * delay.
549 */
550
551 dev_dbg(d->dev, "rqst: fixup: base-state quirk\n");
552
553 gsb_rqsx_response_success(gsb, &base_state, sizeof(base_state));
554 return AE_OK;
555 }
556
557 gsb_rqsx_response_error(gsb, -ENXIO);
558 return AE_OK;
559}
560
561static acpi_status san_rqst(struct san_data *d, struct gsb_buffer *buffer)
562{
563 u8 rspbuf[SAN_GSB_MAX_RESPONSE];
564 struct gsb_data_rqsx *gsb_rqst;
565 struct ssam_request rqst;
566 struct ssam_response rsp;
567 int status = 0;
568
569 gsb_rqst = san_validate_rqsx(d->dev, "RQST", buffer);
570 if (!gsb_rqst)
571 return AE_OK;
572
573 rqst.target_category = gsb_rqst->tc;
574 rqst.target_id = gsb_rqst->tid;
575 rqst.command_id = gsb_rqst->cid;
576 rqst.instance_id = gsb_rqst->iid;
577 rqst.flags = gsb_rqst->snc ? SSAM_REQUEST_HAS_RESPONSE : 0;
578 rqst.length = get_unaligned(&gsb_rqst->cdl);
579 rqst.payload = &gsb_rqst->pld[0];
580
581 rsp.capacity = ARRAY_SIZE(rspbuf);
582 rsp.length = 0;
583 rsp.pointer = &rspbuf[0];
584
585 /* Handle suspended device. */
586 if (d->dev->power.is_suspended) {
587 dev_warn(d->dev, "rqst: device is suspended, not executing\n");
588 return san_rqst_fixup_suspended(d, &rqst, buffer);
589 }
590
591 status = __ssam_retry(ssam_request_sync_onstack, SAN_REQUEST_NUM_TRIES,
592 d->ctrl, &rqst, &rsp, SAN_GSB_MAX_RQSX_PAYLOAD);
593
594 if (!status) {
595 gsb_rqsx_response_success(buffer, rsp.pointer, rsp.length);
596 } else {
597 dev_err(d->dev, "rqst: failed with error %d\n", status);
598 gsb_rqsx_response_error(buffer, status);
599 }
600
601 return AE_OK;
602}
603
604static acpi_status san_rqsg(struct san_data *d, struct gsb_buffer *buffer)
605{
606 struct gsb_data_rqsx *gsb_rqsg;
607 struct san_dgpu_event evt;
608 int status;
609
610 gsb_rqsg = san_validate_rqsx(d->dev, "RQSG", buffer);
611 if (!gsb_rqsg)
612 return AE_OK;
613
614 evt.category = gsb_rqsg->tc;
615 evt.target = gsb_rqsg->tid;
616 evt.command = gsb_rqsg->cid;
617 evt.instance = gsb_rqsg->iid;
618 evt.length = get_unaligned(&gsb_rqsg->cdl);
619 evt.payload = &gsb_rqsg->pld[0];
620
621 status = san_dgpu_notifier_call(&evt);
622 if (!status) {
623 gsb_rqsx_response_success(buffer, NULL, 0);
624 } else {
625 dev_err(d->dev, "rqsg: failed with error %d\n", status);
626 gsb_rqsx_response_error(buffer, status);
627 }
628
629 return AE_OK;
630}
631
632static acpi_status san_opreg_handler(u32 function, acpi_physical_address command,
633 u32 bits, u64 *value64, void *opreg_context,
634 void *region_context)
635{
636 struct san_data *d = to_san_data(opreg_context, info);
637 struct gsb_buffer *buffer = (struct gsb_buffer *)value64;
638 int accessor_type = (function & 0xFFFF0000) >> 16;
639
640 if (command != SAN_GSB_COMMAND) {
641 dev_warn(d->dev, "unsupported command: %#04llx\n", command);
642 return AE_OK;
643 }
644
645 if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
646 dev_err(d->dev, "invalid access type: %#04x\n", accessor_type);
647 return AE_OK;
648 }
649
650 /* Buffer must have at least contain the command-value. */
651 if (buffer->len == 0) {
652 dev_err(d->dev, "request-package too small\n");
653 return AE_OK;
654 }
655
656 switch (buffer->data.in.cv) {
657 case SAN_GSB_REQUEST_CV_RQST:
658 return san_rqst(d, buffer);
659
660 case SAN_GSB_REQUEST_CV_ETWL:
661 return san_etwl(d, buffer);
662
663 case SAN_GSB_REQUEST_CV_RQSG:
664 return san_rqsg(d, buffer);
665
666 default:
667 dev_warn(d->dev, "unsupported SAN0 request (cv: %#04x)\n",
668 buffer->data.in.cv);
669 return AE_OK;
670 }
671}
672
673
674/* -- Driver setup. --------------------------------------------------------- */
675
676static int san_events_register(struct platform_device *pdev)
677{
678 struct san_data *d = platform_get_drvdata(pdev);
679 int status;
680
681 d->nf_bat.base.priority = 1;
682 d->nf_bat.base.fn = san_evt_bat_nf;
683 d->nf_bat.event.reg = SSAM_EVENT_REGISTRY_SAM;
684 d->nf_bat.event.id.target_category = SSAM_SSH_TC_BAT;
685 d->nf_bat.event.id.instance = 0;
686 d->nf_bat.event.mask = SSAM_EVENT_MASK_TARGET;
687 d->nf_bat.event.flags = SSAM_EVENT_SEQUENCED;
688
689 d->nf_tmp.base.priority = 1;
690 d->nf_tmp.base.fn = san_evt_tmp_nf;
691 d->nf_tmp.event.reg = SSAM_EVENT_REGISTRY_SAM;
692 d->nf_tmp.event.id.target_category = SSAM_SSH_TC_TMP;
693 d->nf_tmp.event.id.instance = 0;
694 d->nf_tmp.event.mask = SSAM_EVENT_MASK_TARGET;
695 d->nf_tmp.event.flags = SSAM_EVENT_SEQUENCED;
696
697 status = ssam_notifier_register(d->ctrl, &d->nf_bat);
698 if (status)
699 return status;
700
701 status = ssam_notifier_register(d->ctrl, &d->nf_tmp);
702 if (status)
703 ssam_notifier_unregister(d->ctrl, &d->nf_bat);
704
705 return status;
706}
707
708static void san_events_unregister(struct platform_device *pdev)
709{
710 struct san_data *d = platform_get_drvdata(pdev);
711
712 ssam_notifier_unregister(d->ctrl, &d->nf_bat);
713 ssam_notifier_unregister(d->ctrl, &d->nf_tmp);
714}
715
716#define san_consumer_printk(level, dev, handle, fmt, ...) \
717do { \
718 char *path = "<error getting consumer path>"; \
719 struct acpi_buffer buffer = { \
720 .length = ACPI_ALLOCATE_BUFFER, \
721 .pointer = NULL, \
722 }; \
723 \
724 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) \
725 path = buffer.pointer; \
726 \
727 dev_##level(dev, "[%s]: " fmt, path, ##__VA_ARGS__); \
728 kfree(buffer.pointer); \
729} while (0)
730
731#define san_consumer_dbg(dev, handle, fmt, ...) \
732 san_consumer_printk(dbg, dev, handle, fmt, ##__VA_ARGS__)
733
734#define san_consumer_warn(dev, handle, fmt, ...) \
735 san_consumer_printk(warn, dev, handle, fmt, ##__VA_ARGS__)
736
737static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle)
738{
739 struct acpi_handle_list dep_devices;
740 acpi_handle supplier = ACPI_HANDLE(&pdev->dev);
741 acpi_status status;
742 int i;
743
744 if (!acpi_has_method(handle, "_DEP"))
745 return false;
746
747 status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_devices);
748 if (ACPI_FAILURE(status)) {
749 san_consumer_dbg(&pdev->dev, handle, "failed to evaluate _DEP\n");
750 return false;
751 }
752
753 for (i = 0; i < dep_devices.count; i++) {
754 if (dep_devices.handles[i] == supplier)
755 return true;
756 }
757
758 return false;
759}
760
761static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl,
762 void *context, void **rv)
763{
764 const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER;
765 struct platform_device *pdev = context;
766 struct acpi_device *adev;
767 struct device_link *link;
768
769 if (!is_san_consumer(pdev, handle))
770 return AE_OK;
771
772 /* Ignore ACPI devices that are not present. */
773 if (acpi_bus_get_device(handle, &adev) != 0)
774 return AE_OK;
775
776 san_consumer_dbg(&pdev->dev, handle, "creating device link\n");
777
778 /* Try to set up device links, ignore but log errors. */
779 link = device_link_add(&adev->dev, &pdev->dev, flags);
780 if (!link) {
781 san_consumer_warn(&pdev->dev, handle, "failed to create device link\n");
782 return AE_OK;
783 }
784
785 return AE_OK;
786}
787
788static int san_consumer_links_setup(struct platform_device *pdev)
789{
790 acpi_status status;
791
792 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
793 ACPI_UINT32_MAX, san_consumer_setup, NULL,
794 pdev, NULL);
795
796 return status ? -EFAULT : 0;
797}
798
799static int san_probe(struct platform_device *pdev)
800{
801 acpi_handle san = ACPI_HANDLE(&pdev->dev);
802 struct ssam_controller *ctrl;
803 struct san_data *data;
804 acpi_status astatus;
805 int status;
806
807 ctrl = ssam_client_bind(&pdev->dev);
808 if (IS_ERR(ctrl))
809 return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl);
810
811 status = san_consumer_links_setup(pdev);
812 if (status)
813 return status;
814
815 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
816 if (!data)
817 return -ENOMEM;
818
819 data->dev = &pdev->dev;
820 data->ctrl = ctrl;
821
822 platform_set_drvdata(pdev, data);
823
824 astatus = acpi_install_address_space_handler(san, ACPI_ADR_SPACE_GSBUS,
825 &san_opreg_handler, NULL,
826 &data->info);
827 if (ACPI_FAILURE(astatus))
828 return -ENXIO;
829
830 status = san_events_register(pdev);
831 if (status)
832 goto err_enable_events;
833
834 status = san_set_rqsg_interface_device(&pdev->dev);
835 if (status)
836 goto err_install_dev;
837
838 acpi_walk_dep_device_list(san);
839 return 0;
840
841err_install_dev:
842 san_events_unregister(pdev);
843err_enable_events:
844 acpi_remove_address_space_handler(san, ACPI_ADR_SPACE_GSBUS,
845 &san_opreg_handler);
846 return status;
847}
848
849static int san_remove(struct platform_device *pdev)
850{
851 acpi_handle san = ACPI_HANDLE(&pdev->dev);
852
853 san_set_rqsg_interface_device(NULL);
854 acpi_remove_address_space_handler(san, ACPI_ADR_SPACE_GSBUS,
855 &san_opreg_handler);
856 san_events_unregister(pdev);
857
858 /*
859 * We have unregistered our event sources. Now we need to ensure that
860 * all delayed works they may have spawned are run to completion.
861 */
862 flush_scheduled_work();
863
864 return 0;
865}
866
867static const struct acpi_device_id san_match[] = {
868 { "MSHW0091" },
869 { },
870};
871MODULE_DEVICE_TABLE(acpi, san_match);
872
873static struct platform_driver surface_acpi_notify = {
874 .probe = san_probe,
875 .remove = san_remove,
876 .driver = {
877 .name = "surface_acpi_notify",
878 .acpi_match_table = san_match,
879 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
880 },
881};
882module_platform_driver(surface_acpi_notify);
883
884MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
885MODULE_DESCRIPTION("Surface ACPI Notify driver for Surface System Aggregator Module");
886MODULE_LICENSE("GPL");
drivers/platform/surface/surface_aggregator_cdev.c+322−0
@@ -0,0 +1,322 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
4 * misc device. Intended for debugging and development.
5 *
6 * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
7 */
8
9#include <linux/fs.h>
10#include <linux/kernel.h>
11#include <linux/kref.h>
12#include <linux/miscdevice.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/rwsem.h>
16#include <linux/slab.h>
17#include <linux/uaccess.h>
18
19#include <linux/surface_aggregator/cdev.h>
20#include <linux/surface_aggregator/controller.h>
21
22#define SSAM_CDEV_DEVICE_NAME "surface_aggregator_cdev"
23
24struct ssam_cdev {
25 struct kref kref;
26 struct rw_semaphore lock;
27 struct ssam_controller *ctrl;
28 struct miscdevice mdev;
29};
30
31static void __ssam_cdev_release(struct kref *kref)
32{
33 kfree(container_of(kref, struct ssam_cdev, kref));
34}
35
36static struct ssam_cdev *ssam_cdev_get(struct ssam_cdev *cdev)
37{
38 if (cdev)
39 kref_get(&cdev->kref);
40
41 return cdev;
42}
43
44static void ssam_cdev_put(struct ssam_cdev *cdev)
45{
46 if (cdev)
47 kref_put(&cdev->kref, __ssam_cdev_release);
48}
49
50static int ssam_cdev_device_open(struct inode *inode, struct file *filp)
51{
52 struct miscdevice *mdev = filp->private_data;
53 struct ssam_cdev *cdev = container_of(mdev, struct ssam_cdev, mdev);
54
55 filp->private_data = ssam_cdev_get(cdev);
56 return stream_open(inode, filp);
57}
58
59static int ssam_cdev_device_release(struct inode *inode, struct file *filp)
60{
61 ssam_cdev_put(filp->private_data);
62 return 0;
63}
64
65static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg)
66{
67 struct ssam_cdev_request __user *r;
68 struct ssam_cdev_request rqst;
69 struct ssam_request spec = {};
70 struct ssam_response rsp = {};
71 const void __user *plddata;
72 void __user *rspdata;
73 int status = 0, ret = 0, tmp;
74
75 r = (struct ssam_cdev_request __user *)arg;
76 ret = copy_struct_from_user(&rqst, sizeof(rqst), r, sizeof(*r));
77 if (ret)
78 goto out;
79
80 plddata = u64_to_user_ptr(rqst.payload.data);
81 rspdata = u64_to_user_ptr(rqst.response.data);
82
83 /* Setup basic request fields. */
84 spec.target_category = rqst.target_category;
85 spec.target_id = rqst.target_id;
86 spec.command_id = rqst.command_id;
87 spec.instance_id = rqst.instance_id;
88 spec.flags = 0;
89 spec.length = rqst.payload.length;
90 spec.payload = NULL;
91
92 if (rqst.flags & SSAM_CDEV_REQUEST_HAS_RESPONSE)
93 spec.flags |= SSAM_REQUEST_HAS_RESPONSE;
94
95 if (rqst.flags & SSAM_CDEV_REQUEST_UNSEQUENCED)
96 spec.flags |= SSAM_REQUEST_UNSEQUENCED;
97
98 rsp.capacity = rqst.response.length;
99 rsp.length = 0;
100 rsp.pointer = NULL;
101
102 /* Get request payload from user-space. */
103 if (spec.length) {
104 if (!plddata) {
105 ret = -EINVAL;
106 goto out;
107 }
108
109 /*
110 * Note: spec.length is limited to U16_MAX bytes via struct
111 * ssam_cdev_request. This is slightly larger than the
112 * theoretical maximum (SSH_COMMAND_MAX_PAYLOAD_SIZE) of the
113 * underlying protocol (note that nothing remotely this size
114 * should ever be allocated in any normal case). This size is
115 * validated later in ssam_request_sync(), for allocation the
116 * bound imposed by u16 should be enough.
117 */
118 spec.payload = kzalloc(spec.length, GFP_KERNEL);
119 if (!spec.payload) {
120 ret = -ENOMEM;
121 goto out;
122 }
123
124 if (copy_from_user((void *)spec.payload, plddata, spec.length)) {
125 ret = -EFAULT;
126 goto out;
127 }
128 }
129
130 /* Allocate response buffer. */
131 if (rsp.capacity) {
132 if (!rspdata) {
133 ret = -EINVAL;
134 goto out;
135 }
136
137 /*
138 * Note: rsp.capacity is limited to U16_MAX bytes via struct
139 * ssam_cdev_request. This is slightly larger than the
140 * theoretical maximum (SSH_COMMAND_MAX_PAYLOAD_SIZE) of the
141 * underlying protocol (note that nothing remotely this size
142 * should ever be allocated in any normal case). In later use,
143 * this capacity does not have to be strictly bounded, as it
144 * is only used as an output buffer to be written to. For
145 * allocation the bound imposed by u16 should be enough.
146 */
147 rsp.pointer = kzalloc(rsp.capacity, GFP_KERNEL);
148 if (!rsp.pointer) {
149 ret = -ENOMEM;
150 goto out;
151 }
152 }
153
154 /* Perform request. */
155 status = ssam_request_sync(cdev->ctrl, &spec, &rsp);
156 if (status)
157 goto out;
158
159 /* Copy response to user-space. */
160 if (rsp.length && copy_to_user(rspdata, rsp.pointer, rsp.length))
161 ret = -EFAULT;
162
163out:
164 /* Always try to set response-length and status. */
165 tmp = put_user(rsp.length, &r->response.length);
166 if (tmp)
167 ret = tmp;
168
169 tmp = put_user(status, &r->status);
170 if (tmp)
171 ret = tmp;
172
173 /* Cleanup. */
174 kfree(spec.payload);
175 kfree(rsp.pointer);
176
177 return ret;
178}
179
180static long __ssam_cdev_device_ioctl(struct ssam_cdev *cdev, unsigned int cmd,
181 unsigned long arg)
182{
183 switch (cmd) {
184 case SSAM_CDEV_REQUEST:
185 return ssam_cdev_request(cdev, arg);
186
187 default:
188 return -ENOTTY;
189 }
190}
191
192static long ssam_cdev_device_ioctl(struct file *file, unsigned int cmd,
193 unsigned long arg)
194{
195 struct ssam_cdev *cdev = file->private_data;
196 long status;
197
198 /* Ensure that controller is valid for as long as we need it. */
199 if (down_read_killable(&cdev->lock))
200 return -ERESTARTSYS;
201
202 if (!cdev->ctrl) {
203 up_read(&cdev->lock);
204 return -ENODEV;
205 }
206
207 status = __ssam_cdev_device_ioctl(cdev, cmd, arg);
208
209 up_read(&cdev->lock);
210 return status;
211}
212
213static const struct file_operations ssam_controller_fops = {
214 .owner = THIS_MODULE,
215 .open = ssam_cdev_device_open,
216 .release = ssam_cdev_device_release,
217 .unlocked_ioctl = ssam_cdev_device_ioctl,
218 .compat_ioctl = ssam_cdev_device_ioctl,
219 .llseek = noop_llseek,
220};
221
222static int ssam_dbg_device_probe(struct platform_device *pdev)
223{
224 struct ssam_controller *ctrl;
225 struct ssam_cdev *cdev;
226 int status;
227
228 ctrl = ssam_client_bind(&pdev->dev);
229 if (IS_ERR(ctrl))
230 return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl);
231
232 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
233 if (!cdev)
234 return -ENOMEM;
235
236 kref_init(&cdev->kref);
237 init_rwsem(&cdev->lock);
238 cdev->ctrl = ctrl;
239
240 cdev->mdev.parent = &pdev->dev;
241 cdev->mdev.minor = MISC_DYNAMIC_MINOR;
242 cdev->mdev.name = "surface_aggregator";
243 cdev->mdev.nodename = "surface/aggregator";
244 cdev->mdev.fops = &ssam_controller_fops;
245
246 status = misc_register(&cdev->mdev);
247 if (status) {
248 kfree(cdev);
249 return status;
250 }
251
252 platform_set_drvdata(pdev, cdev);
253 return 0;
254}
255
256static int ssam_dbg_device_remove(struct platform_device *pdev)
257{
258 struct ssam_cdev *cdev = platform_get_drvdata(pdev);
259
260 misc_deregister(&cdev->mdev);
261
262 /*
263 * The controller is only guaranteed to be valid for as long as the
264 * driver is bound. Remove controller so that any lingering open files
265 * cannot access it any more after we're gone.
266 */
267 down_write(&cdev->lock);
268 cdev->ctrl = NULL;
269 up_write(&cdev->lock);
270
271 ssam_cdev_put(cdev);
272 return 0;
273}
274
275static struct platform_device *ssam_cdev_device;
276
277static struct platform_driver ssam_cdev_driver = {
278 .probe = ssam_dbg_device_probe,
279 .remove = ssam_dbg_device_remove,
280 .driver = {
281 .name = SSAM_CDEV_DEVICE_NAME,
282 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
283 },
284};
285
286static int __init ssam_debug_init(void)
287{
288 int status;
289
290 ssam_cdev_device = platform_device_alloc(SSAM_CDEV_DEVICE_NAME,
291 PLATFORM_DEVID_NONE);
292 if (!ssam_cdev_device)
293 return -ENOMEM;
294
295 status = platform_device_add(ssam_cdev_device);
296 if (status)
297 goto err_device;
298
299 status = platform_driver_register(&ssam_cdev_driver);
300 if (status)
301 goto err_driver;
302
303 return 0;
304
305err_driver:
306 platform_device_del(ssam_cdev_device);
307err_device:
308 platform_device_put(ssam_cdev_device);
309 return status;
310}
311module_init(ssam_debug_init);
312
313static void __exit ssam_debug_exit(void)
314{
315 platform_driver_unregister(&ssam_cdev_driver);
316 platform_device_unregister(ssam_cdev_device);
317}
318module_exit(ssam_debug_exit);
319
320MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
321MODULE_DESCRIPTION("User-space interface for Surface System Aggregator Module");
322MODULE_LICENSE("GPL");
drivers/platform/surface/surface_hotplug.c+282−0
@@ -0,0 +1,282 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Surface Book (2 and later) hot-plug driver.
4 *
5 * Surface Book devices (can) have a hot-pluggable discrete GPU (dGPU). This
6 * driver is responsible for out-of-band hot-plug event signaling on these
7 * devices. It is specifically required when the hot-plug device is in D3cold
8 * and can thus not generate PCIe hot-plug events itself.
9 *
10 * Event signaling is handled via ACPI, which will generate the appropriate
11 * device-check notifications to be picked up by the PCIe hot-plug driver.
12 *
13 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
14 */
15
16#include <linux/acpi.h>
17#include <linux/gpio.h>
18#include <linux/interrupt.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/mutex.h>
22#include <linux/platform_device.h>
23
24static const struct acpi_gpio_params shps_base_presence_int = { 0, 0, false };
25static const struct acpi_gpio_params shps_base_presence = { 1, 0, false };
26static const struct acpi_gpio_params shps_device_power_int = { 2, 0, false };
27static const struct acpi_gpio_params shps_device_power = { 3, 0, false };
28static const struct acpi_gpio_params shps_device_presence_int = { 4, 0, false };
29static const struct acpi_gpio_params shps_device_presence = { 5, 0, false };
30
31static const struct acpi_gpio_mapping shps_acpi_gpios[] = {
32 { "base_presence-int-gpio", &shps_base_presence_int, 1 },
33 { "base_presence-gpio", &shps_base_presence, 1 },
34 { "device_power-int-gpio", &shps_device_power_int, 1 },
35 { "device_power-gpio", &shps_device_power, 1 },
36 { "device_presence-int-gpio", &shps_device_presence_int, 1 },
37 { "device_presence-gpio", &shps_device_presence, 1 },
38 { },
39};
40
41/* 5515a847-ed55-4b27-8352-cd320e10360a */
42static const guid_t shps_dsm_guid =
43 GUID_INIT(0x5515a847, 0xed55, 0x4b27, 0x83, 0x52, 0xcd, 0x32, 0x0e, 0x10, 0x36, 0x0a);
44
45#define SHPS_DSM_REVISION 1
46
47enum shps_dsm_fn {
48 SHPS_DSM_FN_PCI_NUM_ENTRIES = 0x01,
49 SHPS_DSM_FN_PCI_GET_ENTRIES = 0x02,
50 SHPS_DSM_FN_IRQ_BASE_PRESENCE = 0x03,
51 SHPS_DSM_FN_IRQ_DEVICE_POWER = 0x04,
52 SHPS_DSM_FN_IRQ_DEVICE_PRESENCE = 0x05,
53};
54
55enum shps_irq_type {
56 /* NOTE: Must be in order of enum shps_dsm_fn above. */
57 SHPS_IRQ_TYPE_BASE_PRESENCE = 0,
58 SHPS_IRQ_TYPE_DEVICE_POWER = 1,
59 SHPS_IRQ_TYPE_DEVICE_PRESENCE = 2,
60 SHPS_NUM_IRQS,
61};
62
63static const char *const shps_gpio_names[] = {
64 [SHPS_IRQ_TYPE_BASE_PRESENCE] = "base_presence",
65 [SHPS_IRQ_TYPE_DEVICE_POWER] = "device_power",
66 [SHPS_IRQ_TYPE_DEVICE_PRESENCE] = "device_presence",
67};
68
69struct shps_device {
70 struct mutex lock[SHPS_NUM_IRQS]; /* Protects update in shps_dsm_notify_irq() */
71 struct gpio_desc *gpio[SHPS_NUM_IRQS];
72 unsigned int irq[SHPS_NUM_IRQS];
73};
74
75#define SHPS_IRQ_NOT_PRESENT ((unsigned int)-1)
76
77static enum shps_dsm_fn shps_dsm_fn_for_irq(enum shps_irq_type type)
78{
79 return SHPS_DSM_FN_IRQ_BASE_PRESENCE + type;
80}
81
82static void shps_dsm_notify_irq(struct platform_device *pdev, enum shps_irq_type type)
83{
84 struct shps_device *sdev = platform_get_drvdata(pdev);
85 acpi_handle handle = ACPI_HANDLE(&pdev->dev);
86 union acpi_object *result;
87 union acpi_object param;
88 int value;
89
90 mutex_lock(&sdev->lock[type]);
91
92 value = gpiod_get_value_cansleep(sdev->gpio[type]);
93 if (value < 0) {
94 mutex_unlock(&sdev->lock[type]);
95 dev_err(&pdev->dev, "failed to get gpio: %d (irq=%d)\n", type, value);
96 return;
97 }
98
99 dev_dbg(&pdev->dev, "IRQ notification via DSM (irq=%d, value=%d)\n", type, value);
100
101 param.type = ACPI_TYPE_INTEGER;
102 param.integer.value = value;
103
104 result = acpi_evaluate_dsm(handle, &shps_dsm_guid, SHPS_DSM_REVISION,
105 shps_dsm_fn_for_irq(type), &param);
106
107 if (!result) {
108 dev_err(&pdev->dev, "IRQ notification via DSM failed (irq=%d, gpio=%d)\n",
109 type, value);
110
111 } else if (result->type != ACPI_TYPE_BUFFER) {
112 dev_err(&pdev->dev,
113 "IRQ notification via DSM failed: unexpected result type (irq=%d, gpio=%d)\n",
114 type, value);
115
116 } else if (result->buffer.length != 1 || result->buffer.pointer[0] != 0) {
117 dev_err(&pdev->dev,
118 "IRQ notification via DSM failed: unexpected result value (irq=%d, gpio=%d)\n",
119 type, value);
120 }
121
122 mutex_unlock(&sdev->lock[type]);
123
124 if (result)
125 ACPI_FREE(result);
126}
127
128static irqreturn_t shps_handle_irq(int irq, void *data)
129{
130 struct platform_device *pdev = data;
131 struct shps_device *sdev = platform_get_drvdata(pdev);
132 int type;
133
134 /* Figure out which IRQ we're handling. */
135 for (type = 0; type < SHPS_NUM_IRQS; type++)
136 if (irq == sdev->irq[type])
137 break;
138
139 /* We should have found our interrupt, if not: this is a bug. */
140 if (WARN(type >= SHPS_NUM_IRQS, "invalid IRQ number: %d\n", irq))
141 return IRQ_HANDLED;
142
143 /* Forward interrupt to ACPI via DSM. */
144 shps_dsm_notify_irq(pdev, type);
145 return IRQ_HANDLED;
146}
147
148static int shps_setup_irq(struct platform_device *pdev, enum shps_irq_type type)
149{
150 unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
151 struct shps_device *sdev = platform_get_drvdata(pdev);
152 struct gpio_desc *gpiod;
153 acpi_handle handle = ACPI_HANDLE(&pdev->dev);
154 const char *irq_name;
155 const int dsm = shps_dsm_fn_for_irq(type);
156 int status, irq;
157
158 /*
159 * Only set up interrupts that we actually need: The Surface Book 3
160 * does not have a DSM for base presence, so don't set up an interrupt
161 * for that.
162 */
163 if (!acpi_check_dsm(handle, &shps_dsm_guid, SHPS_DSM_REVISION, BIT(dsm))) {
164 dev_dbg(&pdev->dev, "IRQ notification via DSM not present (irq=%d)\n", type);
165 return 0;
166 }
167
168 gpiod = devm_gpiod_get(&pdev->dev, shps_gpio_names[type], GPIOD_ASIS);
169 if (IS_ERR(gpiod))
170 return PTR_ERR(gpiod);
171
172 irq = gpiod_to_irq(gpiod);
173 if (irq < 0)
174 return irq;
175
176 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "shps-irq-%d", type);
177 if (!irq_name)
178 return -ENOMEM;
179
180 status = devm_request_threaded_irq(&pdev->dev, irq, NULL, shps_handle_irq,
181 flags, irq_name, pdev);
182 if (status)
183 return status;
184
185 dev_dbg(&pdev->dev, "set up irq %d as type %d\n", irq, type);
186
187 sdev->gpio[type] = gpiod;
188 sdev->irq[type] = irq;
189
190 return 0;
191}
192
193static int surface_hotplug_remove(struct platform_device *pdev)
194{
195 struct shps_device *sdev = platform_get_drvdata(pdev);
196 int i;
197
198 /* Ensure that IRQs have been fully handled and won't trigger any more. */
199 for (i = 0; i < SHPS_NUM_IRQS; i++) {
200 if (sdev->irq[i] != SHPS_IRQ_NOT_PRESENT)
201 disable_irq(sdev->irq[i]);
202
203 mutex_destroy(&sdev->lock[i]);
204 }
205
206 return 0;
207}
208
209static int surface_hotplug_probe(struct platform_device *pdev)
210{
211 struct shps_device *sdev;
212 int status, i;
213
214 /*
215 * The MSHW0153 device is also present on the Surface Laptop 3,
216 * however that doesn't have a hot-pluggable PCIe device. It also
217 * doesn't have any GPIO interrupts/pins under the MSHW0153, so filter
218 * it out here.
219 */
220 if (gpiod_count(&pdev->dev, NULL) < 0)
221 return -ENODEV;
222
223 status = devm_acpi_dev_add_driver_gpios(&pdev->dev, shps_acpi_gpios);
224 if (status)
225 return status;
226
227 sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);
228 if (!sdev)
229 return -ENOMEM;
230
231 platform_set_drvdata(pdev, sdev);
232
233 /*
234 * Initialize IRQs so that we can safely call surface_hotplug_remove()
235 * on errors.
236 */
237 for (i = 0; i < SHPS_NUM_IRQS; i++)
238 sdev->irq[i] = SHPS_IRQ_NOT_PRESENT;
239
240 /* Set up IRQs. */
241 for (i = 0; i < SHPS_NUM_IRQS; i++) {
242 mutex_init(&sdev->lock[i]);
243
244 status = shps_setup_irq(pdev, i);
245 if (status) {
246 dev_err(&pdev->dev, "failed to set up IRQ %d: %d\n", i, status);
247 goto err;
248 }
249 }
250
251 /* Ensure everything is up-to-date. */
252 for (i = 0; i < SHPS_NUM_IRQS; i++)
253 if (sdev->irq[i] != SHPS_IRQ_NOT_PRESENT)
254 shps_dsm_notify_irq(pdev, i);
255
256 return 0;
257
258err:
259 surface_hotplug_remove(pdev);
260 return status;
261}
262
263static const struct acpi_device_id surface_hotplug_acpi_match[] = {
264 { "MSHW0153", 0 },
265 { },
266};
267MODULE_DEVICE_TABLE(acpi, surface_hotplug_acpi_match);
268
269static struct platform_driver surface_hotplug_driver = {
270 .probe = surface_hotplug_probe,
271 .remove = surface_hotplug_remove,
272 .driver = {
273 .name = "surface_hotplug",
274 .acpi_match_table = surface_hotplug_acpi_match,
275 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
276 },
277};
278module_platform_driver(surface_hotplug_driver);
279
280MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
281MODULE_DESCRIPTION("Surface Hot-Plug Signaling Driver for Surface Book Devices");
282MODULE_LICENSE("GPL");
drivers/platform/x86/Kconfig+16−191
@@ -49,18 +49,6 @@ config WMI_BMOF · 48 unmodified lines
49 To compile this driver as a module, choose M here: the module will49 To compile this driver as a module, choose M here: the module will
50 be called wmi-bmof.50 be called wmi-bmof.
51 51
52config ALIENWARE_WMI
53 tristate "Alienware Special feature control"
54 depends on ACPI
55 depends on LEDS_CLASS
56 depends on NEW_LEDS
57 depends on ACPI_WMI
58 help
59 This is a driver for controlling Alienware BIOS driven
60 features. It exposes an interface for controlling the AlienFX
61 zones on Alienware machines that don't contain a dedicated AlienFX
62 USB MCU such as the X51 and X51-R2.
63
64config HUAWEI_WMI52config HUAWEI_WMI
65 tristate "Huawei WMI laptop extras driver"53 tristate "Huawei WMI laptop extras driver"
66 depends on ACPI_BATTERY54 depends on ACPI_BATTERY
@@ -327,169 +315,7 @@ config EEEPC_WMI · 260 unmodified lines
327 If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M315 If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M
328 here.316 here.
329 317
330config DCDBAS318source "drivers/platform/x86/dell/Kconfig"
331 tristate "Dell Systems Management Base Driver"
332 depends on X86
333 help
334 The Dell Systems Management Base Driver provides a sysfs interface
335 for systems management software to perform System Management
336 Interrupts (SMIs) and Host Control Actions (system power cycle or
337 power off after OS shutdown) on certain Dell systems.
338
339 See <file:Documentation/driver-api/dcdbas.rst> for more details on the driver
340 and the Dell systems on which Dell systems management software makes
341 use of this driver.
342
343 Say Y or M here to enable the driver for use by Dell systems
344 management software such as Dell OpenManage.
345
346#
347# The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
348# backends are selected. The "depends" line prevents a configuration
349# where DELL_SMBIOS=y while either of those dependencies =m.
350#
351config DELL_SMBIOS
352 tristate "Dell SMBIOS driver"
353 depends on DCDBAS || DCDBAS=n
354 depends on ACPI_WMI || ACPI_WMI=n
355 help
356 This provides support for the Dell SMBIOS calling interface.
357 If you have a Dell computer you should enable this option.
358
359 Be sure to select at least one backend for it to work properly.
360
361config DELL_SMBIOS_WMI
362 bool "Dell SMBIOS driver WMI backend"
363 default y
364 depends on ACPI_WMI
365 select DELL_WMI_DESCRIPTOR
366 depends on DELL_SMBIOS
367 help
368 This provides an implementation for the Dell SMBIOS calling interface
369 communicated over ACPI-WMI.
370
371 If you have a Dell computer from >2007 you should say Y here.
372 If you aren't sure and this module doesn't work for your computer
373 it just won't load.
374
375config DELL_SMBIOS_SMM
376 bool "Dell SMBIOS driver SMM backend"
377 default y
378 depends on DCDBAS
379 depends on DELL_SMBIOS
380 help
381 This provides an implementation for the Dell SMBIOS calling interface
382 communicated over SMI/SMM.
383
384 If you have a Dell computer from <=2017 you should say Y here.
385 If you aren't sure and this module doesn't work for your computer
386 it just won't load.
387
388config DELL_LAPTOP
389 tristate "Dell Laptop Extras"
390 depends on DMI
391 depends on BACKLIGHT_CLASS_DEVICE
392 depends on ACPI_VIDEO || ACPI_VIDEO = n
393 depends on RFKILL || RFKILL = n
394 depends on SERIO_I8042
395 depends on DELL_SMBIOS
396 select POWER_SUPPLY
397 select LEDS_CLASS
398 select NEW_LEDS
399 select LEDS_TRIGGERS
400 select LEDS_TRIGGER_AUDIO
401 help
402 This driver adds support for rfkill and backlight control to Dell
403 laptops (except for some models covered by the Compal driver).
404
405config DELL_RBTN
406 tristate "Dell Airplane Mode Switch driver"
407 depends on ACPI
408 depends on INPUT
409 depends on RFKILL
410 help
411 Say Y here if you want to support Dell Airplane Mode Switch ACPI
412 device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN.
413 This driver register rfkill device or input hotkey device depending
414 on hardware type (hw switch slider or keyboard toggle button). For
415 rfkill devices it receive HW switch events and set correct hard
416 rfkill state.
417
418 To compile this driver as a module, choose M here: the module will
419 be called dell-rbtn.
420
421config DELL_RBU
422 tristate "BIOS update support for DELL systems via sysfs"
423 depends on X86
424 select FW_LOADER
425 select FW_LOADER_USER_HELPER
426 help
427 Say m if you want to have the option of updating the BIOS for your
428 DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
429 supporting application to communicate with the BIOS regarding the new
430 image for the image update to take effect.
431 See <file:Documentation/admin-guide/dell_rbu.rst> for more details on the driver.
432
433config DELL_SMO8800
434 tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
435 depends on ACPI
436 help
437 Say Y here if you want to support SMO88XX freefall devices
438 on Dell Latitude laptops.
439
440 To compile this driver as a module, choose M here: the module will
441 be called dell-smo8800.
442
443config DELL_WMI
444 tristate "Dell WMI notifications"
445 depends on ACPI_WMI
446 depends on DMI
447 depends on INPUT
448 depends on ACPI_VIDEO || ACPI_VIDEO = n
449 depends on DELL_SMBIOS
450 select DELL_WMI_DESCRIPTOR
451 select INPUT_SPARSEKMAP
452 help
453 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
454
455 To compile this driver as a module, choose M here: the module will
456 be called dell-wmi.
457
458config DELL_WMI_SYSMAN
459 tristate "Dell WMI-based Systems management driver"
460 depends on ACPI_WMI
461 depends on DMI
462 select NLS
463 help
464 This driver allows changing BIOS settings on many Dell machines from
465 2018 and newer without the use of any additional software.
466
467 To compile this driver as a module, choose M here: the module will
468 be called dell-wmi-sysman.
469
470config DELL_WMI_DESCRIPTOR
471 tristate
472 depends on ACPI_WMI
473
474config DELL_WMI_AIO
475 tristate "WMI Hotkeys for Dell All-In-One series"
476 depends on ACPI_WMI
477 depends on INPUT
478 select INPUT_SPARSEKMAP
479 help
480 Say Y here if you want to support WMI-based hotkeys on Dell
481 All-In-One machines.
482
483 To compile this driver as a module, choose M here: the module will
484 be called dell-wmi-aio.
485
486config DELL_WMI_LED
487 tristate "External LED on Dell Business Netbooks"
488 depends on LEDS_CLASS
489 depends on ACPI_WMI
490 help
491 This adds support for the Latitude 2100 and similar
492 notebooks that have an external LED.
493 319
494config AMILO_RFKILL320config AMILO_RFKILL
495 tristate "Fujitsu-Siemens Amilo rfkill support"321 tristate "Fujitsu-Siemens Amilo rfkill support"
@@ -624,7 +450,10 @@ config IDEAPAD_LAPTOP · 128 unmodified lines
624 depends on BACKLIGHT_CLASS_DEVICE450 depends on BACKLIGHT_CLASS_DEVICE
625 depends on ACPI_VIDEO || ACPI_VIDEO = n451 depends on ACPI_VIDEO || ACPI_VIDEO = n
626 depends on ACPI_WMI || ACPI_WMI = n452 depends on ACPI_WMI || ACPI_WMI = n
453 depends on ACPI_PLATFORM_PROFILE
627 select INPUT_SPARSEKMAP454 select INPUT_SPARSEKMAP
455 select NEW_LEDS
456 select LEDS_CLASS
628 help457 help
629 This is a driver for Lenovo IdeaPad netbooks contains drivers for458 This is a driver for Lenovo IdeaPad netbooks contains drivers for
630 rfkill switch, hotkey, fan control and backlight control.459 rfkill switch, hotkey, fan control and backlight control.
@@ -655,6 +484,7 @@ config THINKPAD_ACPI · 24 unmodified lines
655 depends on RFKILL || RFKILL = n484 depends on RFKILL || RFKILL = n
656 depends on ACPI_VIDEO || ACPI_VIDEO = n485 depends on ACPI_VIDEO || ACPI_VIDEO = n
657 depends on BACKLIGHT_CLASS_DEVICE486 depends on BACKLIGHT_CLASS_DEVICE
487 depends on ACPI_PLATFORM_PROFILE
658 select HWMON488 select HWMON
659 select NVRAM489 select NVRAM
660 select NEW_LEDS490 select NEW_LEDS
@@ -1327,21 +1157,6 @@ config INTEL_CHTDC_TI_PWRBTN · 666 unmodified lines
1327 To compile this driver as a module, choose M here: the module1157 To compile this driver as a module, choose M here: the module
1328 will be called intel_chtdc_ti_pwrbtn.1158 will be called intel_chtdc_ti_pwrbtn.
1329 1159
1330config INTEL_MFLD_THERMAL
1331 tristate "Thermal driver for Intel Medfield platform"
1332 depends on MFD_INTEL_MSIC && THERMAL
1333 help
1334 Say Y here to enable thermal driver support for the Intel Medfield
1335 platform.
1336
1337config INTEL_MID_POWER_BUTTON
1338 tristate "power button driver for Intel MID platforms"
1339 depends on INTEL_SCU && INPUT
1340 help
1341 This driver handles the power button on the Intel MID platforms.
1342
1343 If unsure, say N.
1344
1345config INTEL_MRFLD_PWRBTN1160config INTEL_MRFLD_PWRBTN
1346 tristate "Intel Merrifield Basin Cove power button driver"1161 tristate "Intel Merrifield Basin Cove power button driver"
1347 depends on INTEL_SOC_PMIC_MRFLD1162 depends on INTEL_SOC_PMIC_MRFLD
@@ -1369,7 +1184,7 @@ config INTEL_PMC_CORE · 21 unmodified lines
1369 - MPHY/PLL gating status (Sunrisepoint PCH only)1184 - MPHY/PLL gating status (Sunrisepoint PCH only)
1370 1185
1371config INTEL_PMT_CLASS1186config INTEL_PMT_CLASS
1372 tristate "Intel Platform Monitoring Technology (PMT) Class driver"1187 tristate
1373 help1188 help
1374 The Intel Platform Monitoring Technology (PMT) class driver provides1189 The Intel Platform Monitoring Technology (PMT) class driver provides
1375 the basic sysfs interface and file hierarchy uses by PMT devices.1190 the basic sysfs interface and file hierarchy uses by PMT devices.
@@ -1382,6 +1197,7 @@ config INTEL_PMT_CLASS · 6 unmodified lines
1382 1197
1383config INTEL_PMT_TELEMETRY1198config INTEL_PMT_TELEMETRY
1384 tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"1199 tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
1200 depends on MFD_INTEL_PMT
1385 select INTEL_PMT_CLASS1201 select INTEL_PMT_CLASS
1386 help1202 help
1387 The Intel Platform Monitory Technology (PMT) Telemetry driver provides1203 The Intel Platform Monitory Technology (PMT) Telemetry driver provides
@@ -1393,6 +1209,7 @@ config INTEL_PMT_TELEMETRY · 5 unmodified lines
1393 1209
1394config INTEL_PMT_CRASHLOG1210config INTEL_PMT_CRASHLOG
1395 tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"1211 tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
1212 depends on MFD_INTEL_PMT
1396 select INTEL_PMT_CLASS1213 select INTEL_PMT_CLASS
1397 help1214 help
1398 The Intel Platform Monitoring Technology (PMT) crashlog driver provides1215 The Intel Platform Monitoring Technology (PMT) crashlog driver provides
@@ -1439,6 +1256,14 @@ config INTEL_SCU_PLATFORM · 40 unmodified lines
1439 and SCU (sometimes called PMC as well). The driver currently1256 and SCU (sometimes called PMC as well). The driver currently
1440 supports Intel Elkhart Lake and compatible platforms.1257 supports Intel Elkhart Lake and compatible platforms.
1441 1258
1259config INTEL_SCU_WDT
1260 bool
1261 default INTEL_SCU_PCI
1262 depends on INTEL_MID_WATCHDOG
1263 help
1264 This is a specific platform code to instantiate watchdog device
1265 on ACPI-based Intel MID platforms.
1266
1442config INTEL_SCU_IPC_UTIL1267config INTEL_SCU_IPC_UTIL
1443 tristate "Intel SCU IPC utility driver"1268 tristate "Intel SCU IPC utility driver"
1444 depends on INTEL_SCU1269 depends on INTEL_SCU
drivers/platform/x86/Makefile+2−17
@@ -9,7 +9,6 @@ obj-$(CONFIG_ACPI_WMI) += wmi.o · 8 unmodified lines
9obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o9obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
10 10
11# WMI drivers11# WMI drivers
12obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
13obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o12obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
14obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o13obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
15obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o14obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
@@ -37,20 +36,7 @@ obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o · 21 unmodified lines
37obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o36obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
38 37
39# Dell38# Dell
40obj-$(CONFIG_DCDBAS) += dcdbas.o39obj-$(CONFIG_X86_PLATFORM_DRIVERS_DELL) += dell/
41obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
42dell-smbios-objs := dell-smbios-base.o
43dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
44dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
45obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
46obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
47obj-$(CONFIG_DELL_RBU) += dell_rbu.o
48obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
49obj-$(CONFIG_DELL_WMI) += dell-wmi.o
50obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
51obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
52obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
53obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
54 40
55# Fujitsu41# Fujitsu
56obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o42obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o
@@ -137,8 +123,6 @@ obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o · 80 unmodified lines
137# Intel PMIC / PMC / P-Unit devices123# Intel PMIC / PMC / P-Unit devices
138obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o124obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
139obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o125obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
140obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
141obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
142obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o126obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
143obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o127obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o
144obj-$(CONFIG_INTEL_PMT_CLASS) += intel_pmt_class.o128obj-$(CONFIG_INTEL_PMT_CLASS) += intel_pmt_class.o
@@ -148,6 +132,7 @@ obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o · 3 unmodified lines
148obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o132obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
149obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o133obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o
150obj-$(CONFIG_INTEL_SCU_PLATFORM) += intel_scu_pltdrv.o134obj-$(CONFIG_INTEL_SCU_PLATFORM) += intel_scu_pltdrv.o
135obj-$(CONFIG_INTEL_SCU_WDT) += intel_scu_wdt.o
151obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o136obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
152obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \137obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
153 intel_telemetry_pltdrv.o \138 intel_telemetry_pltdrv.o \
drivers/platform/x86/acer-wmi.c+2−2
@@ -30,7 +30,6 @@ · 29 unmodified lines
30#include <linux/input/sparse-keymap.h>30#include <linux/input/sparse-keymap.h>
31#include <acpi/video.h>31#include <acpi/video.h>
32 32
33ACPI_MODULE_NAME(KBUILD_MODNAME);
34MODULE_AUTHOR("Carlos Corbacho");33MODULE_AUTHOR("Carlos Corbacho");
35MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");34MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
36MODULE_LICENSE("GPL");35MODULE_LICENSE("GPL");
@@ -1605,7 +1604,8 @@ static void acer_kbd_dock_get_initial_state(void) · 1568 unmodified lines
1605 1604
1606 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);1605 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);
1607 if (ACPI_FAILURE(status)) {1606 if (ACPI_FAILURE(status)) {
1608 ACPI_EXCEPTION((AE_INFO, status, "Error getting keyboard-dock initial status"));1607 pr_err("Error getting keyboard-dock initial status: %s\n",
1608 acpi_format_exception(status));
1609 return;1609 return;
1610 }1610 }
1611 1611
drivers/platform/x86/amd-pmc.c+11−3
@@ -210,31 +210,39 @@ static int amd_pmc_probe(struct platform_device *pdev) · 209 unmodified lines
210 dev->dev = &pdev->dev;210 dev->dev = &pdev->dev;
211 211
212 rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));212 rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
213 if (!rdev || !pci_match_id(pmc_pci_ids, rdev))213 if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) {
214 pci_dev_put(rdev);
214 return -ENODEV;215 return -ENODEV;
216 }
215 217
216 dev->cpu_id = rdev->device;218 dev->cpu_id = rdev->device;
217 err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO);219 err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO);
218 if (err) {220 if (err) {
219 dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);221 dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);
222 pci_dev_put(rdev);
220 return pcibios_err_to_errno(err);223 return pcibios_err_to_errno(err);
221 }224 }
222 225
223 err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);226 err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);
224 if (err)227 if (err) {
228 pci_dev_put(rdev);
225 return pcibios_err_to_errno(err);229 return pcibios_err_to_errno(err);
230 }
226 231
227 base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK;232 base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK;
228 233
229 err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_HI);234 err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_HI);
230 if (err) {235 if (err) {
231 dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);236 dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);
237 pci_dev_put(rdev);
232 return pcibios_err_to_errno(err);238 return pcibios_err_to_errno(err);
233 }239 }
234 240
235 err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);241 err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);
236 if (err)242 if (err) {
243 pci_dev_put(rdev);
237 return pcibios_err_to_errno(err);244 return pcibios_err_to_errno(err);
245 }
238 246
239 base_addr_hi = val & AMD_PMC_BASE_ADDR_LO_MASK;247 base_addr_hi = val & AMD_PMC_BASE_ADDR_LO_MASK;
240 pci_dev_put(rdev);248 pci_dev_put(rdev);
drivers/platform/x86/dell/Kconfig+207−0
@@ -0,0 +1,207 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Dell X86 Platform Specific Drivers
4#
5
6menuconfig X86_PLATFORM_DRIVERS_DELL
7 bool "Dell X86 Platform Specific Device Drivers"
8 default n
9 depends on X86_PLATFORM_DEVICES
10 help
11 Say Y here to get to see options for device drivers for various
12 Dell x86 platforms, including vendor-specific laptop extension drivers.
13 This option alone does not add any kernel code.
14
15 If you say N, all options in this submenu will be skipped and disabled.
16
17if X86_PLATFORM_DRIVERS_DELL
18
19config ALIENWARE_WMI
20 tristate "Alienware Special feature control"
21 default m
22 depends on ACPI
23 depends on LEDS_CLASS
24 depends on NEW_LEDS
25 depends on ACPI_WMI
26 help
27 This is a driver for controlling Alienware BIOS driven
28 features. It exposes an interface for controlling the AlienFX
29 zones on Alienware machines that don't contain a dedicated AlienFX
30 USB MCU such as the X51 and X51-R2.
31
32config DCDBAS
33 tristate "Dell Systems Management Base Driver"
34 default m
35 depends on X86
36 help
37 The Dell Systems Management Base Driver provides a sysfs interface
38 for systems management software to perform System Management
39 Interrupts (SMIs) and Host Control Actions (system power cycle or
40 power off after OS shutdown) on certain Dell systems.
41
42 See <file:Documentation/driver-api/dcdbas.rst> for more details on the driver
43 and the Dell systems on which Dell systems management software makes
44 use of this driver.
45
46 Say Y or M here to enable the driver for use by Dell systems
47 management software such as Dell OpenManage.
48
49config DELL_LAPTOP
50 tristate "Dell Laptop Extras"
51 default m
52 depends on DMI
53 depends on BACKLIGHT_CLASS_DEVICE
54 depends on ACPI_VIDEO || ACPI_VIDEO = n
55 depends on RFKILL || RFKILL = n
56 depends on SERIO_I8042
57 depends on DELL_SMBIOS
58 select POWER_SUPPLY
59 select LEDS_CLASS
60 select NEW_LEDS
61 select LEDS_TRIGGERS
62 select LEDS_TRIGGER_AUDIO
63 help
64 This driver adds support for rfkill and backlight control to Dell
65 laptops (except for some models covered by the Compal driver).
66
67config DELL_RBU
68 tristate "BIOS update support for DELL systems via sysfs"
69 default m
70 depends on X86
71 select FW_LOADER
72 select FW_LOADER_USER_HELPER
73 help
74 Say m if you want to have the option of updating the BIOS for your
75 DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
76 supporting application to communicate with the BIOS regarding the new
77 image for the image update to take effect.
78 See <file:Documentation/admin-guide/dell_rbu.rst> for more details on the driver.
79
80config DELL_RBTN
81 tristate "Dell Airplane Mode Switch driver"
82 default m
83 depends on ACPI
84 depends on INPUT
85 depends on RFKILL
86 help
87 Say Y here if you want to support Dell Airplane Mode Switch ACPI
88 device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN.
89 This driver register rfkill device or input hotkey device depending
90 on hardware type (hw switch slider or keyboard toggle button). For
91 rfkill devices it receive HW switch events and set correct hard
92 rfkill state.
93
94 To compile this driver as a module, choose M here: the module will
95 be called dell-rbtn.
96
97#
98# The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
99# backends are selected. The "depends" line prevents a configuration
100# where DELL_SMBIOS=y while either of those dependencies =m.
101#
102config DELL_SMBIOS
103 tristate "Dell SMBIOS driver"
104 default m
105 depends on DCDBAS || DCDBAS=n
106 depends on ACPI_WMI || ACPI_WMI=n
107 help
108 This provides support for the Dell SMBIOS calling interface.
109 If you have a Dell computer you should enable this option.
110
111 Be sure to select at least one backend for it to work properly.
112
113config DELL_SMBIOS_WMI
114 bool "Dell SMBIOS driver WMI backend"
115 default y
116 depends on ACPI_WMI
117 select DELL_WMI_DESCRIPTOR
118 depends on DELL_SMBIOS
119 help
120 This provides an implementation for the Dell SMBIOS calling interface
121 communicated over ACPI-WMI.
122
123 If you have a Dell computer from >2007 you should say Y here.
124 If you aren't sure and this module doesn't work for your computer
125 it just won't load.
126
127config DELL_SMBIOS_SMM
128 bool "Dell SMBIOS driver SMM backend"
129 default y
130 depends on DCDBAS
131 depends on DELL_SMBIOS
132 help
133 This provides an implementation for the Dell SMBIOS calling interface
134 communicated over SMI/SMM.
135
136 If you have a Dell computer from <=2017 you should say Y here.
137 If you aren't sure and this module doesn't work for your computer
138 it just won't load.
139
140config DELL_SMO8800
141 tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
142 default m
143 depends on ACPI
144 help
145 Say Y here if you want to support SMO88XX freefall devices
146 on Dell Latitude laptops.
147
148 To compile this driver as a module, choose M here: the module will
149 be called dell-smo8800.
150
151config DELL_WMI
152 tristate "Dell WMI notifications"
153 default m
154 depends on ACPI_WMI
155 depends on DMI
156 depends on INPUT
157 depends on ACPI_VIDEO || ACPI_VIDEO = n
158 depends on DELL_SMBIOS
159 select DELL_WMI_DESCRIPTOR
160 select INPUT_SPARSEKMAP
161 help
162 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
163
164 To compile this driver as a module, choose M here: the module will
165 be called dell-wmi.
166
167config DELL_WMI_AIO
168 tristate "WMI Hotkeys for Dell All-In-One series"
169 default m
170 depends on ACPI_WMI
171 depends on INPUT
172 select INPUT_SPARSEKMAP
173 help
174 Say Y here if you want to support WMI-based hotkeys on Dell
175 All-In-One machines.
176
177 To compile this driver as a module, choose M here: the module will
178 be called dell-wmi-aio.
179
180config DELL_WMI_DESCRIPTOR
181 tristate
182 default m
183 depends on ACPI_WMI
184
185config DELL_WMI_LED
186 tristate "External LED on Dell Business Netbooks"
187 default m
188 depends on LEDS_CLASS
189 depends on ACPI_WMI
190 help
191 This adds support for the Latitude 2100 and similar
192 notebooks that have an external LED.
193
194config DELL_WMI_SYSMAN
195 tristate "Dell WMI-based Systems management driver"
196 default m
197 depends on ACPI_WMI
198 depends on DMI
199 select NLS
200 help
201 This driver allows changing BIOS settings on many Dell machines from
202 2018 and newer without the use of any additional software.
203
204 To compile this driver as a module, choose M here: the module will
205 be called dell-wmi-sysman.
206
207endif # X86_PLATFORM_DRIVERS_DELL
drivers/platform/x86/dell/Makefile+21−0
@@ -0,0 +1,21 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Makefile for linux/drivers/platform/x86/dell
4# Dell x86 Platform-Specific Drivers
5#
6
7obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
8obj-$(CONFIG_DCDBAS) += dcdbas.o
9obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
10obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
11obj-$(CONFIG_DELL_RBU) += dell_rbu.o
12obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
13dell-smbios-objs := dell-smbios-base.o
14dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
15dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
16obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
17obj-$(CONFIG_DELL_WMI) += dell-wmi.o
18obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
19obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
20obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
21obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
drivers/platform/x86/dell/alienware-wmi.crenamed from drivers/platform/x86/alienware-wmi.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dcdbas.crenamed from drivers/platform/x86/dcdbas.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dcdbas.hrenamed from drivers/platform/x86/dcdbas.h+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-laptop.crenamed from drivers/platform/x86/dell-laptop.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-rbtn.crenamed from drivers/platform/x86/dell-rbtn.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-rbtn.hrenamed from drivers/platform/x86/dell-rbtn.h+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-smbios-base.crenamed from drivers/platform/x86/dell-smbios-base.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-smbios-smm.crenamed from drivers/platform/x86/dell-smbios-smm.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-smbios-wmi.crenamed from drivers/platform/x86/dell-smbios-wmi.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-smbios.hrenamed from drivers/platform/x86/dell-smbios.h+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-smo8800.crenamed from drivers/platform/x86/dell-smo8800.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-aio.crenamed from drivers/platform/x86/dell-wmi-aio.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-descriptor.crenamed from drivers/platform/x86/dell-wmi-descriptor.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-descriptor.hrenamed from drivers/platform/x86/dell-wmi-descriptor.h+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-led.crenamed from drivers/platform/x86/dell-wmi-led.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/Makefilerenamed from drivers/platform/x86/dell-wmi-sysman/Makefile+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/biosattr-interface.crenamed from drivers/platform/x86/dell-wmi-sysman/biosattr-interface.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.hrenamed from drivers/platform/x86/dell-wmi-sysman/dell-wmi-sysman.h+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.crenamed from drivers/platform/x86/dell-wmi-sysman/enum-attributes.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.crenamed from drivers/platform/x86/dell-wmi-sysman/int-attributes.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.crenamed from drivers/platform/x86/dell-wmi-sysman/passobj-attributes.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.crenamed from drivers/platform/x86/dell-wmi-sysman/passwordattr-interface.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.crenamed from drivers/platform/x86/dell-wmi-sysman/string-attributes.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi-sysman/sysman.crenamed from drivers/platform/x86/dell-wmi-sysman/sysman.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell-wmi.crenamed from drivers/platform/x86/dell-wmi.c+0−0

File renamed without changes.

drivers/platform/x86/dell/dell_rbu.crenamed from drivers/platform/x86/dell_rbu.c+0−0

File renamed without changes.

drivers/platform/x86/ideapad-laptop.c+1017−439
@@ -8,33 +8,34 @@ · 7 unmodified lines
8 8
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/types.h>
15#include <linux/acpi.h>11#include <linux/acpi.h>
16#include <linux/rfkill.h>
17#include <linux/platform_device.h>
18#include <linux/input.h>
19#include <linux/input/sparse-keymap.h>
20#include <linux/backlight.h>12#include <linux/backlight.h>
21#include <linux/fb.h>13#include <linux/bitops.h>
14#include <linux/bug.h>
22#include <linux/debugfs.h>15#include <linux/debugfs.h>
23#include <linux/seq_file.h>
24#include <linux/i8042.h>
25#include <linux/dmi.h>
26#include <linux/device.h>16#include <linux/device.h>
27#include <acpi/video.h>17#include <linux/dmi.h>
18#include <linux/fb.h>
19#include <linux/i8042.h>
20#include <linux/init.h>
21#include <linux/input.h>
22#include <linux/input/sparse-keymap.h>
23#include <linux/jiffies.h>
24#include <linux/kernel.h>
25#include <linux/leds.h>
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/platform_profile.h>
29#include <linux/rfkill.h>
30#include <linux/seq_file.h>
31#include <linux/sysfs.h>
32#include <linux/types.h>
28 33
29#define IDEAPAD_RFKILL_DEV_NUM (3)34#include <acpi/video.h>
30 35
31#define BM_CONSERVATION_BIT (5)36#include <dt-bindings/leds/common.h>
32#define HA_FNLOCK_BIT (10)
33 37
34#define CFG_BT_BIT (16)38#define IDEAPAD_RFKILL_DEV_NUM 3
35#define CFG_3G_BIT (17)
36#define CFG_WIFI_BIT (18)
37#define CFG_CAMERA_BIT (19)
38 39
39#if IS_ENABLED(CONFIG_ACPI_WMI)40#if IS_ENABLED(CONFIG_ACPI_WMI)
40static const char *const ideapad_wmi_fnesc_events[] = {41static const char *const ideapad_wmi_fnesc_events[] = {
@@ -44,10 +45,39 @@ static const char *const ideapad_wmi_fnesc_events[] = { · 3 unmodified lines
44#endif45#endif
45 46
46enum {47enum {
47 BMCMD_CONSERVATION_ON = 3,48 CFG_CAP_BT_BIT = 16,
48 BMCMD_CONSERVATION_OFF = 5,49 CFG_CAP_3G_BIT = 17,
49 HACMD_FNLOCK_ON = 0xe,50 CFG_CAP_WIFI_BIT = 18,
50 HACMD_FNLOCK_OFF = 0xf,51 CFG_CAP_CAM_BIT = 19,
52 CFG_CAP_TOUCHPAD_BIT = 30,
53};
54
55enum {
56 GBMD_CONSERVATION_STATE_BIT = 5,
57};
58
59enum {
60 SMBC_CONSERVATION_ON = 3,
61 SMBC_CONSERVATION_OFF = 5,
62};
63
64enum {
65 HALS_KBD_BL_SUPPORT_BIT = 4,
66 HALS_KBD_BL_STATE_BIT = 5,
67 HALS_USB_CHARGING_SUPPORT_BIT = 6,
68 HALS_USB_CHARGING_STATE_BIT = 7,
69 HALS_FNLOCK_SUPPORT_BIT = 9,
70 HALS_FNLOCK_STATE_BIT = 10,
71 HALS_HOTKEYS_PRIMARY_BIT = 11,
72};
73
74enum {
75 SALS_KBD_BL_ON = 0x8,
76 SALS_KBD_BL_OFF = 0x9,
77 SALS_USB_CHARGING_ON = 0xa,
78 SALS_USB_CHARGING_OFF = 0xb,
79 SALS_FNLOCK_ON = 0xe,
80 SALS_FNLOCK_OFF = 0xf,
51};81};
52 82
53enum {83enum {
@@ -77,6 +107,13 @@ enum { · 23 unmodified lines
77 VPCCMD_W_BL_POWER = 0x33,107 VPCCMD_W_BL_POWER = 0x33,
78};108};
79 109
110struct ideapad_dytc_priv {
111 enum platform_profile_option current_profile;
112 struct platform_profile_handler pprof;
113 struct mutex mutex; /* protects the DYTC interface */
114 struct ideapad_private *priv;
115};
116
80struct ideapad_rfk_priv {117struct ideapad_rfk_priv {
81 int dev;118 int dev;
82 struct ideapad_private *priv;119 struct ideapad_private *priv;
@@ -89,11 +126,25 @@ struct ideapad_private { · 6 unmodified lines
89 struct platform_device *platform_device;126 struct platform_device *platform_device;
90 struct input_dev *inputdev;127 struct input_dev *inputdev;
91 struct backlight_device *blightdev;128 struct backlight_device *blightdev;
129 struct ideapad_dytc_priv *dytc;
92 struct dentry *debug;130 struct dentry *debug;
93 unsigned long cfg;131 unsigned long cfg;
94 bool has_hw_rfkill_switch;
95 bool has_touchpad_switch;
96 const char *fnesc_guid;132 const char *fnesc_guid;
133 struct {
134 bool conservation_mode : 1;
135 bool dytc : 1;
136 bool fan_mode : 1;
137 bool fn_lock : 1;
138 bool hw_rfkill_switch : 1;
139 bool kbd_bl : 1;
140 bool touchpad_ctrl_via_ec : 1;
141 bool usb_charging : 1;
142 } features;
143 struct {
144 bool initialized;
145 struct led_classdev led;
146 unsigned int last_brightness;
147 } kbd_bl;
97};148};
98 149
99static bool no_bt_rfkill;150static bool no_bt_rfkill;
@@ -103,64 +154,82 @@ MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); · 3 unmodified lines
103/*154/*
104 * ACPI Helpers155 * ACPI Helpers
105 */156 */
106#define IDEAPAD_EC_TIMEOUT (200) /* in ms */157#define IDEAPAD_EC_TIMEOUT 200 /* in ms */
107 158
108static int read_method_int(acpi_handle handle, const char *method, int *val)159static int eval_int(acpi_handle handle, const char *name, unsigned long *res)
109{160{
110 acpi_status status;
111 unsigned long long result;161 unsigned long long result;
162 acpi_status status;
163
164 status = acpi_evaluate_integer(handle, (char *)name, NULL, &result);
165 if (ACPI_FAILURE(status))
166 return -EIO;
167
168 *res = result;
112 169
113 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
114 if (ACPI_FAILURE(status)) {
115 *val = -1;
116 return -1;
117 }
118 *val = result;
119 return 0;170 return 0;
171}
172
173static int exec_simple_method(acpi_handle handle, const char *name, unsigned long arg)
174{
175 acpi_status status = acpi_execute_simple_method(handle, (char *)name, arg);
120 176
177 return ACPI_FAILURE(status) ? -EIO : 0;
121}178}
122 179
123static int method_gbmd(acpi_handle handle, unsigned long *ret)180static int eval_gbmd(acpi_handle handle, unsigned long *res)
124{181{
125 int result, val;182 return eval_int(handle, "GBMD", res);
183}
126 184
127 result = read_method_int(handle, "GBMD", &val);185static int exec_smbc(acpi_handle handle, unsigned long arg)
128 *ret = val;186{
129 return result;187 return exec_simple_method(handle, "SMBC", arg);
130}188}
131 189
132static int method_int1(acpi_handle handle, char *method, int cmd)190static int eval_hals(acpi_handle handle, unsigned long *res)
133{191{
134 acpi_status status;192 return eval_int(handle, "HALS", res);
193}
135 194
136 status = acpi_execute_simple_method(handle, method, cmd);195static int exec_sals(acpi_handle handle, unsigned long arg)
137 return ACPI_FAILURE(status) ? -1 : 0;196{
197 return exec_simple_method(handle, "SALS", arg);
138}198}
139 199
140static int method_vpcr(acpi_handle handle, int cmd, int *ret)200static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, unsigned long *res)
141{201{
142 acpi_status status;
143 unsigned long long result;
144 struct acpi_object_list params;202 struct acpi_object_list params;
203 unsigned long long result;
145 union acpi_object in_obj;204 union acpi_object in_obj;
205 acpi_status status;
146 206
147 params.count = 1;207 params.count = 1;
148 params.pointer = &in_obj;208 params.pointer = &in_obj;
149 in_obj.type = ACPI_TYPE_INTEGER;209 in_obj.type = ACPI_TYPE_INTEGER;
150 in_obj.integer.value = cmd;210 in_obj.integer.value = arg;
211
212 status = acpi_evaluate_integer(handle, (char *)name, &params, &result);
213 if (ACPI_FAILURE(status))
214 return -EIO;
151 215
152 status = acpi_evaluate_integer(handle, "VPCR", &params, &result);216 if (res)
217 *res = result;
153 218
154 if (ACPI_FAILURE(status)) {
155 *ret = -1;
156 return -1;
157 }
158 *ret = result;
159 return 0;219 return 0;
220}
160 221
222static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res)
223{
224 return eval_int_with_arg(handle, "DYTC", cmd, res);
161}225}
162 226
163static int method_vpcw(acpi_handle handle, int cmd, int data)227static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res)
228{
229 return eval_int_with_arg(handle, "VPCR", cmd, res);
230}
231
232static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data)
164{233{
165 struct acpi_object_list params;234 struct acpi_object_list params;
166 union acpi_object in_obj[2];235 union acpi_object in_obj[2];
@@ -174,55 +243,68 @@ static int method_vpcw(acpi_handle handle, int cmd, int data) · 7 unmodified lines
174 in_obj[1].integer.value = data;243 in_obj[1].integer.value = data;
175 244
176 status = acpi_evaluate_object(handle, "VPCW", &params, NULL);245 status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
177 if (status != AE_OK)246 if (ACPI_FAILURE(status))
178 return -1;247 return -EIO;
248
179 return 0;249 return 0;
180}250}
181 251
182static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)252static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data)
183{253{
184 int val;254 unsigned long end_jiffies, val;
185 unsigned long int end_jiffies;255 int err;
256
257 err = eval_vpcw(handle, 1, cmd);
258 if (err)
259 return err;
186 260
187 if (method_vpcw(handle, 1, cmd))261 end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
188 return -1;
189 262
190 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;263 while (time_before(jiffies, end_jiffies)) {
191 time_before(jiffies, end_jiffies);) {
192 schedule();264 schedule();
193 if (method_vpcr(handle, 1, &val))265
194 return -1;266 err = eval_vpcr(handle, 1, &val);
195 if (val == 0) {267 if (err)
196 if (method_vpcr(handle, 0, &val))268 return err;
197 return -1;269
198 *data = val;270 if (val == 0)
199 return 0;271 return eval_vpcr(handle, 0, data);
200 }
201 }272 }
202 pr_err("timeout in %s\n", __func__);273
203 return -1;274 acpi_handle_err(handle, "timeout in %s\n", __func__);
275
276 return -ETIMEDOUT;
204}277}
205 278
206static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)279static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data)
207{280{
208 int val;281 unsigned long end_jiffies, val;
209 unsigned long int end_jiffies;282 int err;
283
284 err = eval_vpcw(handle, 0, data);
285 if (err)
286 return err;
287
288 err = eval_vpcw(handle, 1, cmd);
289 if (err)
290 return err;
210 291
211 if (method_vpcw(handle, 0, data))292 end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
212 return -1;
213 if (method_vpcw(handle, 1, cmd))
214 return -1;
215 293
216 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;294 while (time_before(jiffies, end_jiffies)) {
217 time_before(jiffies, end_jiffies);) {
218 schedule();295 schedule();
219 if (method_vpcr(handle, 1, &val))296
220 return -1;297 err = eval_vpcr(handle, 1, &val);
298 if (err)
299 return err;
300
221 if (val == 0)301 if (val == 0)
222 return 0;302 return 0;
223 }303 }
224 pr_err("timeout in %s\n", __func__);304
225 return -1;305 acpi_handle_err(handle, "timeout in %s\n", __func__);
306
307 return -ETIMEDOUT;
226}308}
227 309
228/*310/*
@@ -233,44 +315,37 @@ static int debugfs_status_show(struct seq_file *s, void *data) · 4 unmodified lines
233 struct ideapad_private *priv = s->private;315 struct ideapad_private *priv = s->private;
234 unsigned long value;316 unsigned long value;
235 317
236 if (!priv)
237 return -EINVAL;
238
239 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))318 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
240 seq_printf(s, "Backlight max:\t%lu\n", value);319 seq_printf(s, "Backlight max: %lu\n", value);
241 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))320 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
242 seq_printf(s, "Backlight now:\t%lu\n", value);321 seq_printf(s, "Backlight now: %lu\n", value);
243 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))322 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
244 seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");323 seq_printf(s, "BL power value: %s (%lu)\n", value ? "on" : "off", value);
245 seq_printf(s, "=====================\n");324
325 seq_puts(s, "=====================\n");
246 326
247 if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))327 if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
248 seq_printf(s, "Radio status:\t%s(%lu)\n",328 seq_printf(s, "Radio status: %s (%lu)\n", value ? "on" : "off", value);
249 value ? "On" : "Off", value);
250 if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))329 if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
251 seq_printf(s, "Wifi status:\t%s(%lu)\n",330 seq_printf(s, "Wifi status: %s (%lu)\n", value ? "on" : "off", value);
252 value ? "On" : "Off", value);
253 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))331 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
254 seq_printf(s, "BT status:\t%s(%lu)\n",332 seq_printf(s, "BT status: %s (%lu)\n", value ? "on" : "off", value);
255 value ? "On" : "Off", value);
256 if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))333 if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
257 seq_printf(s, "3G status:\t%s(%lu)\n",334 seq_printf(s, "3G status: %s (%lu)\n", value ? "on" : "off", value);
258 value ? "On" : "Off", value);335
259 seq_printf(s, "=====================\n");336 seq_puts(s, "=====================\n");
260 337
261 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))338 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
262 seq_printf(s, "Touchpad status:%s(%lu)\n",339 seq_printf(s, "Touchpad status: %s (%lu)\n", value ? "on" : "off", value);
263 value ? "On" : "Off", value);
264 if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))340 if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
265 seq_printf(s, "Camera status:\t%s(%lu)\n",341 seq_printf(s, "Camera status: %s (%lu)\n", value ? "on" : "off", value);
266 value ? "On" : "Off", value);342
267 seq_puts(s, "=====================\n");343 seq_puts(s, "=====================\n");
268 344
269 if (!method_gbmd(priv->adev->handle, &value)) {345 if (!eval_gbmd(priv->adev->handle, &value))
270 seq_printf(s, "Conservation mode:\t%s(%lu)\n",346 seq_printf(s, "GBMD: %#010lx\n", value);
271 test_bit(BM_CONSERVATION_BIT, &value) ? "On" : "Off",347 if (!eval_hals(priv->adev->handle, &value))
272 value);348 seq_printf(s, "HALS: %#010lx\n", value);
273 }
274 349
275 return 0;350 return 0;
276}351}
@@ -280,39 +355,41 @@ static int debugfs_cfg_show(struct seq_file *s, void *data) · 3 unmodified lines
280{355{
281 struct ideapad_private *priv = s->private;356 struct ideapad_private *priv = s->private;
282 357
283 if (!priv) {358 seq_printf(s, "_CFG: %#010lx\n\n", priv->cfg);
284 seq_printf(s, "cfg: N/A\n");359
285 } else {360 seq_puts(s, "Capabilities:");
286 seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",361 if (test_bit(CFG_CAP_BT_BIT, &priv->cfg))
287 priv->cfg);362 seq_puts(s, " bluetooth");
288 if (test_bit(CFG_BT_BIT, &priv->cfg))363 if (test_bit(CFG_CAP_3G_BIT, &priv->cfg))
289 seq_printf(s, "Bluetooth ");364 seq_puts(s, " 3G");
290 if (test_bit(CFG_3G_BIT, &priv->cfg))365 if (test_bit(CFG_CAP_WIFI_BIT, &priv->cfg))
291 seq_printf(s, "3G ");366 seq_puts(s, " wifi");
292 if (test_bit(CFG_WIFI_BIT, &priv->cfg))367 if (test_bit(CFG_CAP_CAM_BIT, &priv->cfg))
293 seq_printf(s, "Wireless ");368 seq_puts(s, " camera");
294 if (test_bit(CFG_CAMERA_BIT, &priv->cfg))369 if (test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg))
295 seq_printf(s, "Camera ");370 seq_puts(s, " touchpad");
296 seq_printf(s, "\nGraphic: ");371 seq_puts(s, "\n");
297 switch ((priv->cfg)&0x700) {372
298 case 0x100:373 seq_puts(s, "Graphics: ");
299 seq_printf(s, "Intel");374 switch (priv->cfg & 0x700) {
300 break;375 case 0x100:
301 case 0x200:376 seq_puts(s, "Intel");
302 seq_printf(s, "ATI");377 break;
303 break;378 case 0x200:
304 case 0x300:379 seq_puts(s, "ATI");
305 seq_printf(s, "Nvidia");380 break;
306 break;381 case 0x300:
307 case 0x400:382 seq_puts(s, "Nvidia");
308 seq_printf(s, "Intel and ATI");383 break;
309 break;384 case 0x400:
310 case 0x500:385 seq_puts(s, "Intel and ATI");
311 seq_printf(s, "Intel and Nvidia");386 break;
312 break;387 case 0x500:
313 }388 seq_puts(s, "Intel and Nvidia");
314 seq_printf(s, "\n");389 break;
315 }390 }
391 seq_puts(s, "\n");
392
316 return 0;393 return 0;
317}394}
318DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);395DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
@@ -324,8 +401,8 @@ static void ideapad_debugfs_init(struct ideapad_private *priv) · 5 unmodified lines
324 dir = debugfs_create_dir("ideapad", NULL);401 dir = debugfs_create_dir("ideapad", NULL);
325 priv->debug = dir;402 priv->debug = dir;
326 403
327 debugfs_create_file("cfg", S_IRUGO, dir, priv, &debugfs_cfg_fops);404 debugfs_create_file("cfg", 0444, dir, priv, &debugfs_cfg_fops);
328 debugfs_create_file("status", S_IRUGO, dir, priv, &debugfs_status_fops);405 debugfs_create_file("status", 0444, dir, priv, &debugfs_status_fops);
329}406}
330 407
331static void ideapad_debugfs_exit(struct ideapad_private *priv)408static void ideapad_debugfs_exit(struct ideapad_private *priv)
@@ -337,209 +414,256 @@ static void ideapad_debugfs_exit(struct ideapad_private *priv) · 5 unmodified lines
337/*414/*
338 * sysfs415 * sysfs
339 */416 */
340static ssize_t show_ideapad_cam(struct device *dev,417static ssize_t camera_power_show(struct device *dev,
341 struct device_attribute *attr,418 struct device_attribute *attr,
342 char *buf)419 char *buf)
343{420{
344 unsigned long result;
345 struct ideapad_private *priv = dev_get_drvdata(dev);421 struct ideapad_private *priv = dev_get_drvdata(dev);
422 unsigned long result;
423 int err;
346 424
347 if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))425 err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result);
348 return sprintf(buf, "-1\n");426 if (err)
349 return sprintf(buf, "%lu\n", result);427 return err;
428
429 return sysfs_emit(buf, "%d\n", !!result);
350}430}
351 431
352static ssize_t store_ideapad_cam(struct device *dev,432static ssize_t camera_power_store(struct device *dev,
353 struct device_attribute *attr,433 struct device_attribute *attr,
354 const char *buf, size_t count)434 const char *buf, size_t count)
355{435{
356 int ret, state;
357 struct ideapad_private *priv = dev_get_drvdata(dev);436 struct ideapad_private *priv = dev_get_drvdata(dev);
437 bool state;
438 int err;
439
440 err = kstrtobool(buf, &state);
441 if (err)
442 return err;
443
444 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
445 if (err)
446 return err;
358 447
359 if (!count)
360 return 0;
361 if (sscanf(buf, "%i", &state) != 1)
362 return -EINVAL;
363 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
364 if (ret < 0)
365 return -EIO;
366 return count;448 return count;
367}449}
368 450
369static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);451static DEVICE_ATTR_RW(camera_power);
370 452
371static ssize_t show_ideapad_fan(struct device *dev,453static ssize_t conservation_mode_show(struct device *dev,
372 struct device_attribute *attr,454 struct device_attribute *attr,
373 char *buf)455 char *buf)
374{456{
375 unsigned long result;
376 struct ideapad_private *priv = dev_get_drvdata(dev);457 struct ideapad_private *priv = dev_get_drvdata(dev);
458 unsigned long result;
459 int err;
460
461 err = eval_gbmd(priv->adev->handle, &result);
462 if (err)
463 return err;
377 464
378 if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))465 return sysfs_emit(buf, "%d\n", !!test_bit(GBMD_CONSERVATION_STATE_BIT, &result));
379 return sprintf(buf, "-1\n");
380 return sprintf(buf, "%lu\n", result);
381}466}
382 467
383static ssize_t store_ideapad_fan(struct device *dev,468static ssize_t conservation_mode_store(struct device *dev,
384 struct device_attribute *attr,469 struct device_attribute *attr,
385 const char *buf, size_t count)470 const char *buf, size_t count)
386{471{
387 int ret, state;
388 struct ideapad_private *priv = dev_get_drvdata(dev);472 struct ideapad_private *priv = dev_get_drvdata(dev);
473 bool state;
474 int err;
475
476 err = kstrtobool(buf, &state);
477 if (err)
478 return err;
479
480 err = exec_smbc(priv->adev->handle, state ? SMBC_CONSERVATION_ON : SMBC_CONSERVATION_OFF);
481 if (err)
482 return err;
389 483
390 if (!count)
391 return 0;
392 if (sscanf(buf, "%i", &state) != 1)
393 return -EINVAL;
394 if (state < 0 || state > 4 || state == 3)
395 return -EINVAL;
396 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
397 if (ret < 0)
398 return -EIO;
399 return count;484 return count;
400}485}
401 486
402static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);487static DEVICE_ATTR_RW(conservation_mode);
403 488
404static ssize_t touchpad_show(struct device *dev,489static ssize_t fan_mode_show(struct device *dev,
405 struct device_attribute *attr,490 struct device_attribute *attr,
406 char *buf)491 char *buf)
407{492{
408 struct ideapad_private *priv = dev_get_drvdata(dev);493 struct ideapad_private *priv = dev_get_drvdata(dev);
409 unsigned long result;494 unsigned long result;
495 int err;
496
497 err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result);
498 if (err)
499 return err;
410 500
411 if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))501 return sysfs_emit(buf, "%lu\n", result);
412 return sprintf(buf, "-1\n");
413 return sprintf(buf, "%lu\n", result);
414}502}
415 503
416/* Switch to RO for now: It might be revisited in the future */504static ssize_t fan_mode_store(struct device *dev,
417static ssize_t __maybe_unused touchpad_store(struct device *dev,505 struct device_attribute *attr,
418 struct device_attribute *attr,506 const char *buf, size_t count)
419 const char *buf, size_t count)
420{507{
421 struct ideapad_private *priv = dev_get_drvdata(dev);508 struct ideapad_private *priv = dev_get_drvdata(dev);
422 bool state;509 unsigned int state;
423 int ret;510 int err;
424 511
425 ret = kstrtobool(buf, &state);512 err = kstrtouint(buf, 0, &state);
426 if (ret)513 if (err)
427 return ret;514 return err;
515
516 if (state > 4 || state == 3)
517 return -EINVAL;
518
519 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
520 if (err)
521 return err;
428 522
429 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
430 if (ret < 0)
431 return -EIO;
432 return count;523 return count;
433}524}
434 525
435static DEVICE_ATTR_RO(touchpad);526static DEVICE_ATTR_RW(fan_mode);
436 527
437static ssize_t conservation_mode_show(struct device *dev,528static ssize_t fn_lock_show(struct device *dev,
438 struct device_attribute *attr,529 struct device_attribute *attr,
439 char *buf)530 char *buf)
440{531{
441 struct ideapad_private *priv = dev_get_drvdata(dev);532 struct ideapad_private *priv = dev_get_drvdata(dev);
442 unsigned long result;533 unsigned long hals;
534 int err;
443 535
444 if (method_gbmd(priv->adev->handle, &result))536 err = eval_hals(priv->adev->handle, &hals);
445 return sprintf(buf, "-1\n");537 if (err)
446 return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result));538 return err;
539
540 return sysfs_emit(buf, "%d\n", !!test_bit(HALS_FNLOCK_STATE_BIT, &hals));
447}541}
448 542
449static ssize_t conservation_mode_store(struct device *dev,543static ssize_t fn_lock_store(struct device *dev,
450 struct device_attribute *attr,544 struct device_attribute *attr,
451 const char *buf, size_t count)545 const char *buf, size_t count)
452{546{
453 struct ideapad_private *priv = dev_get_drvdata(dev);547 struct ideapad_private *priv = dev_get_drvdata(dev);
454 bool state;548 bool state;
455 int ret;549 int err;
456 550
457 ret = kstrtobool(buf, &state);551 err = kstrtobool(buf, &state);
458 if (ret)552 if (err)
459 return ret;553 return err;
554
555 err = exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
556 if (err)
557 return err;
460 558
461 ret = method_int1(priv->adev->handle, "SBMC", state ?
462 BMCMD_CONSERVATION_ON :
463 BMCMD_CONSERVATION_OFF);
464 if (ret < 0)
465 return -EIO;
466 return count;559 return count;
467}560}
468 561
469static DEVICE_ATTR_RW(conservation_mode);562static DEVICE_ATTR_RW(fn_lock);
470 563
471static ssize_t fn_lock_show(struct device *dev,564static ssize_t touchpad_show(struct device *dev,
472 struct device_attribute *attr,565 struct device_attribute *attr,
473 char *buf)566 char *buf)
474{567{
475 struct ideapad_private *priv = dev_get_drvdata(dev);568 struct ideapad_private *priv = dev_get_drvdata(dev);
476 unsigned long result;569 unsigned long result;
477 int hals;570 int err;
478 int fail = read_method_int(priv->adev->handle, "HALS", &hals);
479 571
480 if (fail)572 err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result);
481 return sprintf(buf, "-1\n");573 if (err)
574 return err;
482 575
483 result = hals;576 return sysfs_emit(buf, "%d\n", !!result);
484 return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
485}577}
486 578
487static ssize_t fn_lock_store(struct device *dev,579static ssize_t touchpad_store(struct device *dev,
488 struct device_attribute *attr,580 struct device_attribute *attr,
489 const char *buf, size_t count)581 const char *buf, size_t count)
490{582{
491 struct ideapad_private *priv = dev_get_drvdata(dev);583 struct ideapad_private *priv = dev_get_drvdata(dev);
492 bool state;584 bool state;
493 int ret;585 int err;
494 586
495 ret = kstrtobool(buf, &state);587 err = kstrtobool(buf, &state);
496 if (ret)588 if (err)
497 return ret;589 return err;
590
591 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
592 if (err)
593 return err;
498 594
499 ret = method_int1(priv->adev->handle, "SALS", state ?
500 HACMD_FNLOCK_ON :
501 HACMD_FNLOCK_OFF);
502 if (ret < 0)
503 return -EIO;
504 return count;595 return count;
505}596}
506 597
507static DEVICE_ATTR_RW(fn_lock);598static DEVICE_ATTR_RW(touchpad);
599
600static ssize_t usb_charging_show(struct device *dev,
601 struct device_attribute *attr,
602 char *buf)
603{
604 struct ideapad_private *priv = dev_get_drvdata(dev);
605 unsigned long hals;
606 int err;
607
608 err = eval_hals(priv->adev->handle, &hals);
609 if (err)
610 return err;
611
612 return sysfs_emit(buf, "%d\n", !!test_bit(HALS_USB_CHARGING_STATE_BIT, &hals));
613}
508 614
615static ssize_t usb_charging_store(struct device *dev,
616 struct device_attribute *attr,
617 const char *buf, size_t count)
618{
619 struct ideapad_private *priv = dev_get_drvdata(dev);
620 bool state;
621 int err;
622
623 err = kstrtobool(buf, &state);
624 if (err)
625 return err;
626
627 err = exec_sals(priv->adev->handle, state ? SALS_USB_CHARGING_ON : SALS_USB_CHARGING_OFF);
628 if (err)
629 return err;
630
631 return count;
632}
633
634static DEVICE_ATTR_RW(usb_charging);
509 635
510static struct attribute *ideapad_attributes[] = {636static struct attribute *ideapad_attributes[] = {
511 &dev_attr_camera_power.attr,637 &dev_attr_camera_power.attr,
512 &dev_attr_fan_mode.attr,
513 &dev_attr_touchpad.attr,
514 &dev_attr_conservation_mode.attr,638 &dev_attr_conservation_mode.attr,
639 &dev_attr_fan_mode.attr,
515 &dev_attr_fn_lock.attr,640 &dev_attr_fn_lock.attr,
641 &dev_attr_touchpad.attr,
642 &dev_attr_usb_charging.attr,
516 NULL643 NULL
517};644};
518 645
519static umode_t ideapad_is_visible(struct kobject *kobj,646static umode_t ideapad_is_visible(struct kobject *kobj,
520 struct attribute *attr,647 struct attribute *attr,
521 int idx)648 int idx)
522{649{
523 struct device *dev = container_of(kobj, struct device, kobj);650 struct device *dev = kobj_to_dev(kobj);
524 struct ideapad_private *priv = dev_get_drvdata(dev);651 struct ideapad_private *priv = dev_get_drvdata(dev);
525 bool supported;652 bool supported = true;
526 653
527 if (attr == &dev_attr_camera_power.attr)654 if (attr == &dev_attr_camera_power.attr)
528 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));655 supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg);
529 else if (attr == &dev_attr_fan_mode.attr) {656 else if (attr == &dev_attr_conservation_mode.attr)
530 unsigned long value;657 supported = priv->features.conservation_mode;
531 supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,658 else if (attr == &dev_attr_fan_mode.attr)
532 &value);659 supported = priv->features.fan_mode;
533 } else if (attr == &dev_attr_conservation_mode.attr) {660 else if (attr == &dev_attr_fn_lock.attr)
534 supported = acpi_has_method(priv->adev->handle, "GBMD") &&661 supported = priv->features.fn_lock;
535 acpi_has_method(priv->adev->handle, "SBMC");662 else if (attr == &dev_attr_touchpad.attr)
536 } else if (attr == &dev_attr_fn_lock.attr) {663 supported = priv->features.touchpad_ctrl_via_ec &&
537 supported = acpi_has_method(priv->adev->handle, "HALS") &&664 test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg);
538 acpi_has_method(priv->adev->handle, "SALS");665 else if (attr == &dev_attr_usb_charging.attr)
539 } else if (attr == &dev_attr_touchpad.attr)666 supported = priv->features.usb_charging;
540 supported = priv->has_touchpad_switch;
541 else
542 supported = true;
543 667
544 return supported ? attr->mode : 0;668 return supported ? attr->mode : 0;
545}669}
@@ -549,6 +673,265 @@ static const struct attribute_group ideapad_attribute_group = { · 3 unmodified lines
549 .attrs = ideapad_attributes673 .attrs = ideapad_attributes
550};674};
551 675
676/*
677 * DYTC Platform profile
678 */
679#define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */
680#define DYTC_CMD_SET 1 /* To enable/disable IC function mode */
681#define DYTC_CMD_GET 2 /* To get current IC function and mode */
682#define DYTC_CMD_RESET 0x1ff /* To reset back to default */
683
684#define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */
685#define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
686#define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */
687
688#define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */
689#define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */
690
691#define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - function setting */
692#define DYTC_SET_MODE_BIT 16 /* Bits 16-19 - mode setting */
693#define DYTC_SET_VALID_BIT 20 /* Bit 20 - 1 = on, 0 = off */
694
695#define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */
696#define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */
697#define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */
698
699#define DYTC_MODE_PERFORM 2 /* High power mode aka performance */
700#define DYTC_MODE_LOW_POWER 3 /* Low power mode aka quiet */
701#define DYTC_MODE_BALANCE 0xF /* Default mode aka balanced */
702
703#define DYTC_SET_COMMAND(function, mode, on) \
704 (DYTC_CMD_SET | (function) << DYTC_SET_FUNCTION_BIT | \
705 (mode) << DYTC_SET_MODE_BIT | \
706 (on) << DYTC_SET_VALID_BIT)
707
708#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0)
709
710#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1)
711
712static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
713{
714 switch (dytcmode) {
715 case DYTC_MODE_LOW_POWER:
716 *profile = PLATFORM_PROFILE_LOW_POWER;
717 break;
718 case DYTC_MODE_BALANCE:
719 *profile = PLATFORM_PROFILE_BALANCED;
720 break;
721 case DYTC_MODE_PERFORM:
722 *profile = PLATFORM_PROFILE_PERFORMANCE;
723 break;
724 default: /* Unknown mode */
725 return -EINVAL;
726 }
727
728 return 0;
729}
730
731static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode)
732{
733 switch (profile) {
734 case PLATFORM_PROFILE_LOW_POWER:
735 *perfmode = DYTC_MODE_LOW_POWER;
736 break;
737 case PLATFORM_PROFILE_BALANCED:
738 *perfmode = DYTC_MODE_BALANCE;
739 break;
740 case PLATFORM_PROFILE_PERFORMANCE:
741 *perfmode = DYTC_MODE_PERFORM;
742 break;
743 default: /* Unknown profile */
744 return -EOPNOTSUPP;
745 }
746
747 return 0;
748}
749
750/*
751 * dytc_profile_get: Function to register with platform_profile
752 * handler. Returns current platform profile.
753 */
754static int dytc_profile_get(struct platform_profile_handler *pprof,
755 enum platform_profile_option *profile)
756{
757 struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
758
759 *profile = dytc->current_profile;
760 return 0;
761}
762
763/*
764 * Helper function - check if we are in CQL mode and if we are
765 * - disable CQL,
766 * - run the command
767 * - enable CQL
768 * If not in CQL mode, just run the command
769 */
770static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
771 unsigned long *output)
772{
773 int err, cmd_err, cur_funcmode;
774
775 /* Determine if we are in CQL mode. This alters the commands we do */
776 err = eval_dytc(priv->adev->handle, DYTC_CMD_GET, output);
777 if (err)
778 return err;
779
780 cur_funcmode = (*output >> DYTC_GET_FUNCTION_BIT) & 0xF;
781 /* Check if we're OK to return immediately */
782 if (cmd == DYTC_CMD_GET && cur_funcmode != DYTC_FUNCTION_CQL)
783 return 0;
784
785 if (cur_funcmode == DYTC_FUNCTION_CQL) {
786 err = eval_dytc(priv->adev->handle, DYTC_DISABLE_CQL, NULL);
787 if (err)
788 return err;
789 }
790
791 cmd_err = eval_dytc(priv->adev->handle, cmd, output);
792 /* Check return condition after we've restored CQL state */
793
794 if (cur_funcmode == DYTC_FUNCTION_CQL) {
795 err = eval_dytc(priv->adev->handle, DYTC_ENABLE_CQL, NULL);
796 if (err)
797 return err;
798 }
799
800 return cmd_err;
801}
802
803/*
804 * dytc_profile_set: Function to register with platform_profile
805 * handler. Sets current platform profile.
806 */
807static int dytc_profile_set(struct platform_profile_handler *pprof,
808 enum platform_profile_option profile)
809{
810 struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
811 struct ideapad_private *priv = dytc->priv;
812 int err;
813
814 err = mutex_lock_interruptible(&dytc->mutex);
815 if (err)
816 return err;
817
818 if (profile == PLATFORM_PROFILE_BALANCED) {
819 /* To get back to balanced mode we just issue a reset command */
820 err = eval_dytc(priv->adev->handle, DYTC_CMD_RESET, NULL);
821 if (err)
822 goto unlock;
823 } else {
824 int perfmode;
825
826 err = convert_profile_to_dytc(profile, &perfmode);
827 if (err)
828 goto unlock;
829
830 /* Determine if we are in CQL mode. This alters the commands we do */
831 err = dytc_cql_command(priv, DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1),
832 NULL);
833 if (err)
834 goto unlock;
835 }
836
837 /* Success - update current profile */
838 dytc->current_profile = profile;
839
840unlock:
841 mutex_unlock(&dytc->mutex);
842
843 return err;
844}
845
846static void dytc_profile_refresh(struct ideapad_private *priv)
847{
848 enum platform_profile_option profile;
849 unsigned long output;
850 int err, perfmode;
851
852 mutex_lock(&priv->dytc->mutex);
853 err = dytc_cql_command(priv, DYTC_CMD_GET, &output);
854 mutex_unlock(&priv->dytc->mutex);
855 if (err)
856 return;
857
858 perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
859
860 if (convert_dytc_to_profile(perfmode, &profile))
861 return;
862
863 if (profile != priv->dytc->current_profile) {
864 priv->dytc->current_profile = profile;
865 platform_profile_notify();
866 }
867}
868
869static int ideapad_dytc_profile_init(struct ideapad_private *priv)
870{
871 int err, dytc_version;
872 unsigned long output;
873
874 if (!priv->features.dytc)
875 return -ENODEV;
876
877 err = eval_dytc(priv->adev->handle, DYTC_CMD_QUERY, &output);
878 /* For all other errors we can flag the failure */
879 if (err)
880 return err;
881
882 /* Check DYTC is enabled and supports mode setting */
883 if (!test_bit(DYTC_QUERY_ENABLE_BIT, &output))
884 return -ENODEV;
885
886 dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
887 if (dytc_version < 5)
888 return -ENODEV;
889
890 priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
891 if (!priv->dytc)
892 return -ENOMEM;
893
894 mutex_init(&priv->dytc->mutex);
895
896 priv->dytc->priv = priv;
897 priv->dytc->pprof.profile_get = dytc_profile_get;
898 priv->dytc->pprof.profile_set = dytc_profile_set;
899
900 /* Setup supported modes */
901 set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
902 set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
903 set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
904
905 /* Create platform_profile structure and register */
906 err = platform_profile_register(&priv->dytc->pprof);
907 if (err)
908 goto pp_reg_failed;
909
910 /* Ensure initial values are correct */
911 dytc_profile_refresh(priv);
912
913 return 0;
914
915pp_reg_failed:
916 mutex_destroy(&priv->dytc->mutex);
917 kfree(priv->dytc);
918 priv->dytc = NULL;
919
920 return err;
921}
922
923static void ideapad_dytc_profile_exit(struct ideapad_private *priv)
924{
925 if (!priv->dytc)
926 return;
927
928 platform_profile_remove();
929 mutex_destroy(&priv->dytc->mutex);
930 kfree(priv->dytc);
931
932 priv->dytc = NULL;
933}
934
552/*935/*
553 * Rfkill936 * Rfkill
554 */937 */
@@ -560,9 +943,9 @@ struct ideapad_rfk_data { · 5 unmodified lines
560};943};
561 944
562static const struct ideapad_rfk_data ideapad_rfk_data[] = {945static const struct ideapad_rfk_data ideapad_rfk_data[] = {
563 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },946 { "ideapad_wlan", CFG_CAP_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
564 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },947 { "ideapad_bluetooth", CFG_CAP_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
565 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },948 { "ideapad_3g", CFG_CAP_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
566};949};
567 950
568static int ideapad_rfk_set(void *data, bool blocked)951static int ideapad_rfk_set(void *data, bool blocked)
@@ -582,7 +965,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) · 13 unmodified lines
582 unsigned long hw_blocked = 0;965 unsigned long hw_blocked = 0;
583 int i;966 int i;
584 967
585 if (priv->has_hw_rfkill_switch) {968 if (priv->features.hw_rfkill_switch) {
586 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))969 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
587 return;970 return;
588 hw_blocked = !hw_blocked;971 hw_blocked = !hw_blocked;
@@ -595,16 +978,15 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) · 6 unmodified lines
595 978
596static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)979static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
597{980{
598 int ret;981 unsigned long rf_enabled;
599 unsigned long sw_blocked;982 int err;
600 983
601 if (no_bt_rfkill &&984 if (no_bt_rfkill && ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH) {
602 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
603 /* Force to enable bluetooth when no_bt_rfkill=1 */985 /* Force to enable bluetooth when no_bt_rfkill=1 */
604 write_ec_cmd(priv->adev->handle,986 write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1);
605 ideapad_rfk_data[dev].opcode, 1);
606 return 0;987 return 0;
607 }988 }
989
608 priv->rfk_priv[dev].dev = dev;990 priv->rfk_priv[dev].dev = dev;
609 priv->rfk_priv[dev].priv = priv;991 priv->rfk_priv[dev].priv = priv;
610 992
@@ -616,20 +998,17 @@ static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) · 5 unmodified lines
616 if (!priv->rfk[dev])998 if (!priv->rfk[dev])
617 return -ENOMEM;999 return -ENOMEM;
618 1000
619 if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,1001 err = read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode - 1, &rf_enabled);
620 &sw_blocked)) {1002 if (err)
621 rfkill_init_sw_state(priv->rfk[dev], 0);1003 rf_enabled = 1;
622 } else {1004
623 sw_blocked = !sw_blocked;1005 rfkill_init_sw_state(priv->rfk[dev], !rf_enabled);
624 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
625 }
626 1006
627 ret = rfkill_register(priv->rfk[dev]);1007 err = rfkill_register(priv->rfk[dev]);
628 if (ret) {1008 if (err)
629 rfkill_destroy(priv->rfk[dev]);1009 rfkill_destroy(priv->rfk[dev]);
630 return ret;1010
631 }1011 return err;
632 return 0;
633}1012}
634 1013
635static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)1014static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
@@ -646,40 +1025,39 @@ static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) · 10 unmodified lines
646 */1025 */
647static int ideapad_sysfs_init(struct ideapad_private *priv)1026static int ideapad_sysfs_init(struct ideapad_private *priv)
648{1027{
649 return sysfs_create_group(&priv->platform_device->dev.kobj,1028 return device_add_group(&priv->platform_device->dev,
650 &ideapad_attribute_group);1029 &ideapad_attribute_group);
651}1030}
652 1031
653static void ideapad_sysfs_exit(struct ideapad_private *priv)1032static void ideapad_sysfs_exit(struct ideapad_private *priv)
654{1033{
655 sysfs_remove_group(&priv->platform_device->dev.kobj,1034 device_remove_group(&priv->platform_device->dev,
656 &ideapad_attribute_group);1035 &ideapad_attribute_group);
657}1036}
658 1037
659/*1038/*
660 * input device1039 * input device
661 */1040 */
662static const struct key_entry ideapad_keymap[] = {1041static const struct key_entry ideapad_keymap[] = {
663 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },1042 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
664 { KE_KEY, 7, { KEY_CAMERA } },1043 { KE_KEY, 7, { KEY_CAMERA } },
665 { KE_KEY, 8, { KEY_MICMUTE } },1044 { KE_KEY, 8, { KEY_MICMUTE } },
666 { KE_KEY, 11, { KEY_F16 } },1045 { KE_KEY, 11, { KEY_F16 } },
667 { KE_KEY, 13, { KEY_WLAN } },1046 { KE_KEY, 13, { KEY_WLAN } },
668 { KE_KEY, 16, { KEY_PROG1 } },1047 { KE_KEY, 16, { KEY_PROG1 } },
669 { KE_KEY, 17, { KEY_PROG2 } },1048 { KE_KEY, 17, { KEY_PROG2 } },
670 { KE_KEY, 64, { KEY_PROG3 } },1049 { KE_KEY, 64, { KEY_PROG3 } },
671 { KE_KEY, 65, { KEY_PROG4 } },1050 { KE_KEY, 65, { KEY_PROG4 } },
672 { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },1051 { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
673 { KE_KEY, 67, { KEY_TOUCHPAD_ON } },1052 { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
674 { KE_KEY, 128, { KEY_ESC } },1053 { KE_KEY, 128, { KEY_ESC } },
675 1054 { KE_END },
676 { KE_END, 0 },
677};1055};
678 1056
679static int ideapad_input_init(struct ideapad_private *priv)1057static int ideapad_input_init(struct ideapad_private *priv)
680{1058{
681 struct input_dev *inputdev;1059 struct input_dev *inputdev;
682 int error;1060 int err;
683 1061
684 inputdev = input_allocate_device();1062 inputdev = input_allocate_device();
685 if (!inputdev)1063 if (!inputdev)
@@ -690,24 +1068,28 @@ static int ideapad_input_init(struct ideapad_private *priv) · 4 unmodified lines
690 inputdev->id.bustype = BUS_HOST;1068 inputdev->id.bustype = BUS_HOST;
691 inputdev->dev.parent = &priv->platform_device->dev;1069 inputdev->dev.parent = &priv->platform_device->dev;
692 1070
693 error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);1071 err = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
694 if (error) {1072 if (err) {
695 pr_err("Unable to setup input device keymap\n");1073 dev_err(&priv->platform_device->dev,
1074 "Could not set up input device keymap: %d\n", err);
696 goto err_free_dev;1075 goto err_free_dev;
697 }1076 }
698 1077
699 error = input_register_device(inputdev);1078 err = input_register_device(inputdev);
700 if (error) {1079 if (err) {
701 pr_err("Unable to register input device\n");1080 dev_err(&priv->platform_device->dev,
1081 "Could not register input device: %d\n", err);
702 goto err_free_dev;1082 goto err_free_dev;
703 }1083 }
704 1084
705 priv->inputdev = inputdev;1085 priv->inputdev = inputdev;
1086
706 return 0;1087 return 0;
707 1088
708err_free_dev:1089err_free_dev:
709 input_free_device(inputdev);1090 input_free_device(inputdev);
710 return error;1091
1092 return err;
711}1093}
712 1094
713static void ideapad_input_exit(struct ideapad_private *priv)1095static void ideapad_input_exit(struct ideapad_private *priv)
@@ -728,6 +1110,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv) · 14 unmodified lines
728 1110
729 if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))1111 if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
730 return;1112 return;
1113
731 if (long_pressed)1114 if (long_pressed)
732 ideapad_input_report(priv, 17);1115 ideapad_input_report(priv, 17);
733 else1116 else
@@ -738,24 +1121,24 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) · 4 unmodified lines
738{1121{
739 unsigned long bit, value;1122 unsigned long bit, value;
740 1123
741 read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);1124 if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value))
742 1125 return;
743 for (bit = 0; bit < 16; bit++) {1126
744 if (test_bit(bit, &value)) {1127 for_each_set_bit (bit, &value, 16) {
745 switch (bit) {1128 switch (bit) {
746 case 0: /* Z580 */1129 case 6: /* Z570 */
747 case 6: /* Z570 */1130 case 0: /* Z580 */
748 /* Thermal Management button */1131 /* Thermal Management button */
749 ideapad_input_report(priv, 65);1132 ideapad_input_report(priv, 65);
750 break;1133 break;
751 case 1:1134 case 1:
752 /* OneKey Theater button */1135 /* OneKey Theater button */
753 ideapad_input_report(priv, 64);1136 ideapad_input_report(priv, 64);
754 break;1137 break;
755 default:1138 default:
756 pr_info("Unknown special button: %lu\n", bit);1139 dev_info(&priv->platform_device->dev,
757 break;1140 "Unknown special button: %lu\n", bit);
758 }1141 break;
759 }1142 }
760 }1143 }
761}1144}
@@ -767,28 +1150,29 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) · 5 unmodified lines
767{1150{
768 struct ideapad_private *priv = bl_get_data(blightdev);1151 struct ideapad_private *priv = bl_get_data(blightdev);
769 unsigned long now;1152 unsigned long now;
1153 int err;
770 1154
771 if (!priv)1155 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
772 return -EINVAL;1156 if (err)
1157 return err;
773 1158
774 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
775 return -EIO;
776 return now;1159 return now;
777}1160}
778 1161
779static int ideapad_backlight_update_status(struct backlight_device *blightdev)1162static int ideapad_backlight_update_status(struct backlight_device *blightdev)
780{1163{
781 struct ideapad_private *priv = bl_get_data(blightdev);1164 struct ideapad_private *priv = bl_get_data(blightdev);
1165 int err;
782 1166
783 if (!priv)1167 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
784 return -EINVAL;1168 blightdev->props.brightness);
1169 if (err)
1170 return err;
785 1171
786 if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,1172 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
787 blightdev->props.brightness))1173 blightdev->props.power != FB_BLANK_POWERDOWN);
788 return -EIO;1174 if (err)
789 if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,1175 return err;
790 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
791 return -EIO;
792 1176
793 return 0;1177 return 0;
794}1178}
@@ -803,30 +1187,41 @@ static int ideapad_backlight_init(struct ideapad_private *priv) · 8 unmodified lines
803 struct backlight_device *blightdev;1187 struct backlight_device *blightdev;
804 struct backlight_properties props;1188 struct backlight_properties props;
805 unsigned long max, now, power;1189 unsigned long max, now, power;
1190 int err;
806 1191
807 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))1192 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max);
808 return -EIO;1193 if (err)
809 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))1194 return err;
810 return -EIO;1195
811 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))1196 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
812 return -EIO;1197 if (err)
1198 return err;
1199
1200 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power);
1201 if (err)
1202 return err;
1203
1204 memset(&props, 0, sizeof(props));
813 1205
814 memset(&props, 0, sizeof(struct backlight_properties));
815 props.max_brightness = max;1206 props.max_brightness = max;
816 props.type = BACKLIGHT_PLATFORM;1207 props.type = BACKLIGHT_PLATFORM;
1208
817 blightdev = backlight_device_register("ideapad",1209 blightdev = backlight_device_register("ideapad",
818 &priv->platform_device->dev,1210 &priv->platform_device->dev,
819 priv,1211 priv,
820 &ideapad_backlight_ops,1212 &ideapad_backlight_ops,
821 &props);1213 &props);
822 if (IS_ERR(blightdev)) {1214 if (IS_ERR(blightdev)) {
823 pr_err("Could not register backlight device\n");1215 err = PTR_ERR(blightdev);
824 return PTR_ERR(blightdev);1216 dev_err(&priv->platform_device->dev,
1217 "Could not register backlight device: %d\n", err);
1218 return err;
825 }1219 }
826 1220
827 priv->blightdev = blightdev;1221 priv->blightdev = blightdev;
828 blightdev->props.brightness = now;1222 blightdev->props.brightness = now;
829 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;1223 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1224
830 backlight_update_status(blightdev);1225 backlight_update_status(blightdev);
831 1226
832 return 0;1227 return 0;
@@ -840,13 +1235,15 @@ static void ideapad_backlight_exit(struct ideapad_private *priv) · 7 unmodified lines
840 1235
841static void ideapad_backlight_notify_power(struct ideapad_private *priv)1236static void ideapad_backlight_notify_power(struct ideapad_private *priv)
842{1237{
843 unsigned long power;
844 struct backlight_device *blightdev = priv->blightdev;1238 struct backlight_device *blightdev = priv->blightdev;
1239 unsigned long power;
845 1240
846 if (!blightdev)1241 if (!blightdev)
847 return;1242 return;
1243
848 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))1244 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
849 return;1245 return;
1246
850 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;1247 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
851}1248}
852 1249
@@ -855,12 +1252,112 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) · 2 unmodified lines
855 unsigned long now;1252 unsigned long now;
856 1253
857 /* if we control brightness via acpi video driver */1254 /* if we control brightness via acpi video driver */
858 if (priv->blightdev == NULL) {1255 if (!priv->blightdev)
859 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);1256 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1257 else
1258 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
1259}
1260
1261/*
1262 * keyboard backlight
1263 */
1264static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv)
1265{
1266 unsigned long hals;
1267 int err;
1268
1269 err = eval_hals(priv->adev->handle, &hals);
1270 if (err)
1271 return err;
1272
1273 return !!test_bit(HALS_KBD_BL_STATE_BIT, &hals);
1274}
1275
1276static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev)
1277{
1278 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1279
1280 return ideapad_kbd_bl_brightness_get(priv);
1281}
1282
1283static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness)
1284{
1285 int err = exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF);
1286
1287 if (err)
1288 return err;
1289
1290 priv->kbd_bl.last_brightness = brightness;
1291
1292 return 0;
1293}
1294
1295static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev,
1296 enum led_brightness brightness)
1297{
1298 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1299
1300 return ideapad_kbd_bl_brightness_set(priv, brightness);
1301}
1302
1303static void ideapad_kbd_bl_notify(struct ideapad_private *priv)
1304{
1305 int brightness;
1306
1307 if (!priv->kbd_bl.initialized)
860 return;1308 return;
861 }
862 1309
863 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);1310 brightness = ideapad_kbd_bl_brightness_get(priv);
1311 if (brightness < 0)
1312 return;
1313
1314 if (brightness == priv->kbd_bl.last_brightness)
1315 return;
1316
1317 priv->kbd_bl.last_brightness = brightness;
1318
1319 led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness);
1320}
1321
1322static int ideapad_kbd_bl_init(struct ideapad_private *priv)
1323{
1324 int brightness, err;
1325
1326 if (!priv->features.kbd_bl)
1327 return -ENODEV;
1328
1329 if (WARN_ON(priv->kbd_bl.initialized))
1330 return -EEXIST;
1331
1332 brightness = ideapad_kbd_bl_brightness_get(priv);
1333 if (brightness < 0)
1334 return brightness;
1335
1336 priv->kbd_bl.last_brightness = brightness;
1337
1338 priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
1339 priv->kbd_bl.led.max_brightness = 1;
1340 priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get;
1341 priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
1342 priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED;
1343
1344 err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led);
1345 if (err)
1346 return err;
1347
1348 priv->kbd_bl.initialized = true;
1349
1350 return 0;
1351}
1352
1353static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
1354{
1355 if (!priv->kbd_bl.initialized)
1356 return;
1357
1358 priv->kbd_bl.initialized = false;
1359
1360 led_classdev_unregister(&priv->kbd_bl.led);
864}1361}
865 1362
866/*1363/*
@@ -870,71 +1367,77 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) · 3 unmodified lines
870{1367{
871 unsigned long value;1368 unsigned long value;
872 1369
873 if (!priv->has_touchpad_switch)1370 if (!priv->features.touchpad_ctrl_via_ec)
874 return;1371 return;
875 1372
876 /* Without reading from EC touchpad LED doesn't switch state */1373 /* Without reading from EC touchpad LED doesn't switch state */
877 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {1374 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
878 /* Some IdeaPads don't really turn off touchpad - they only1375 unsigned char param;
1376 /*
1377 * Some IdeaPads don't really turn off touchpad - they only
879 * switch the LED state. We (de)activate KBC AUX port to turn1378 * switch the LED state. We (de)activate KBC AUX port to turn
880 * touchpad off and on. We send KEY_TOUCHPAD_OFF and1379 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
881 * KEY_TOUCHPAD_ON to not to get out of sync with LED */1380 * KEY_TOUCHPAD_ON to not to get out of sync with LED
882 unsigned char param;1381 */
883 i8042_command(&param, value ? I8042_CMD_AUX_ENABLE :1382 i8042_command(&param, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
884 I8042_CMD_AUX_DISABLE);
885 ideapad_input_report(priv, value ? 67 : 66);1383 ideapad_input_report(priv, value ? 67 : 66);
1384 sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
886 }1385 }
887}1386}
888 1387
889static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)1388static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
890{1389{
891 struct ideapad_private *priv = data;1390 struct ideapad_private *priv = data;
892 unsigned long vpc1, vpc2, vpc_bit;1391 unsigned long vpc1, vpc2, bit;
893 1392
894 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))1393 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
895 return;1394 return;
1395
896 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))1396 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
897 return;1397 return;
898 1398
899 vpc1 = (vpc2 << 8) | vpc1;1399 vpc1 = (vpc2 << 8) | vpc1;
900 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {1400
901 if (test_bit(vpc_bit, &vpc1)) {1401 for_each_set_bit (bit, &vpc1, 16) {
902 switch (vpc_bit) {1402 switch (bit) {
903 case 9:1403 case 13:
904 ideapad_sync_rfk_state(priv);1404 case 11:
905 break;1405 case 8:
906 case 13:1406 case 7:
907 case 11:1407 case 6:
908 case 8:1408 ideapad_input_report(priv, bit);
909 case 7:1409 break;
910 case 6:1410 case 9:
911 ideapad_input_report(priv, vpc_bit);1411 ideapad_sync_rfk_state(priv);
912 break;1412 break;
913 case 5:1413 case 5:
914 ideapad_sync_touchpad_state(priv);1414 ideapad_sync_touchpad_state(priv);
915 break;1415 break;
916 case 4:1416 case 4:
917 ideapad_backlight_notify_brightness(priv);1417 ideapad_backlight_notify_brightness(priv);
918 break;1418 break;
919 case 3:1419 case 3:
920 ideapad_input_novokey(priv);1420 ideapad_input_novokey(priv);
921 break;1421 break;
922 case 2:1422 case 2:
923 ideapad_backlight_notify_power(priv);1423 ideapad_backlight_notify_power(priv);
924 break;1424 break;
925 case 0:1425 case 1:
926 ideapad_check_special_buttons(priv);1426 /*
927 break;1427 * Some IdeaPads report event 1 every ~20
928 case 1:1428 * seconds while on battery power; some
929 /* Some IdeaPads report event 1 every ~201429 * report this when changing to/from tablet
930 * seconds while on battery power; some1430 * mode; some report this when the keyboard
931 * report this when changing to/from tablet1431 * backlight has changed.
932 * mode. Squelch this event.1432 */
933 */1433 ideapad_kbd_bl_notify(priv);
934 break;1434 break;
935 default:1435 case 0:
936 pr_info("Unknown event: %lu\n", vpc_bit);1436 ideapad_check_special_buttons(priv);
937 }1437 break;
1438 default:
1439 dev_info(&priv->platform_device->dev,
1440 "Unknown event: %lu\n", bit);
938 }1441 }
939 }1442 }
940}1443}
@@ -942,12 +1445,15 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) · 1 unmodified line
942#if IS_ENABLED(CONFIG_ACPI_WMI)1445#if IS_ENABLED(CONFIG_ACPI_WMI)
943static void ideapad_wmi_notify(u32 value, void *context)1446static void ideapad_wmi_notify(u32 value, void *context)
944{1447{
1448 struct ideapad_private *priv = context;
1449
945 switch (value) {1450 switch (value) {
946 case 128:1451 case 128:
947 ideapad_input_report(context, value);1452 ideapad_input_report(priv, value);
948 break;1453 break;
949 default:1454 default:
950 pr_info("Unknown WMI event %u\n", value);1455 dev_info(&priv->platform_device->dev,
1456 "Unknown WMI event: %u\n", value);
951 }1457 }
952}1458}
953#endif1459#endif
@@ -971,18 +1477,52 @@ static const struct dmi_system_id hw_rfkill_list[] = { · 17 unmodified lines
971 {}1477 {}
972};1478};
973 1479
1480static void ideapad_check_features(struct ideapad_private *priv)
1481{
1482 acpi_handle handle = priv->adev->handle;
1483 unsigned long val;
1484
1485 priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
1486
1487 /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
1488 priv->features.touchpad_ctrl_via_ec = !acpi_dev_present("ELAN0634", NULL, -1);
1489
1490 if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
1491 priv->features.fan_mode = true;
1492
1493 if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC"))
1494 priv->features.conservation_mode = true;
1495
1496 if (acpi_has_method(handle, "DYTC"))
1497 priv->features.dytc = true;
1498
1499 if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) {
1500 if (!eval_hals(handle, &val)) {
1501 if (test_bit(HALS_FNLOCK_SUPPORT_BIT, &val))
1502 priv->features.fn_lock = true;
1503
1504 if (test_bit(HALS_KBD_BL_SUPPORT_BIT, &val))
1505 priv->features.kbd_bl = true;
1506
1507 if (test_bit(HALS_USB_CHARGING_SUPPORT_BIT, &val))
1508 priv->features.usb_charging = true;
1509 }
1510 }
1511}
1512
974static int ideapad_acpi_add(struct platform_device *pdev)1513static int ideapad_acpi_add(struct platform_device *pdev)
975{1514{
976 int ret, i;
977 int cfg;
978 struct ideapad_private *priv;1515 struct ideapad_private *priv;
979 struct acpi_device *adev;1516 struct acpi_device *adev;
1517 acpi_status status;
1518 unsigned long cfg;
1519 int err, i;
980 1520
981 ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);1521 err = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
982 if (ret)1522 if (err)
983 return -ENODEV;1523 return -ENODEV;
984 1524
985 if (read_method_int(adev->handle, "_CFG", &cfg))1525 if (eval_int(adev->handle, "_CFG", &cfg))
986 return -ENODEV;1526 return -ENODEV;
987 1527
988 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);1528 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -990,33 +1530,40 @@ static int ideapad_acpi_add(struct platform_device *pdev) · 1 unmodified line
990 return -ENOMEM;1530 return -ENOMEM;
991 1531
992 dev_set_drvdata(&pdev->dev, priv);1532 dev_set_drvdata(&pdev->dev, priv);
1533
993 priv->cfg = cfg;1534 priv->cfg = cfg;
994 priv->adev = adev;1535 priv->adev = adev;
995 priv->platform_device = pdev;1536 priv->platform_device = pdev;
996 priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
997 1537
998 /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */1538 ideapad_check_features(priv);
999 priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
1000 1539
1001 ret = ideapad_sysfs_init(priv);1540 err = ideapad_sysfs_init(priv);
1002 if (ret)1541 if (err)
1003 return ret;1542 return err;
1004 1543
1005 ideapad_debugfs_init(priv);1544 ideapad_debugfs_init(priv);
1006 1545
1007 ret = ideapad_input_init(priv);1546 err = ideapad_input_init(priv);
1008 if (ret)1547 if (err)
1009 goto input_failed;1548 goto input_failed;
1010 1549
1550 err = ideapad_kbd_bl_init(priv);
1551 if (err) {
1552 if (err != -ENODEV)
1553 dev_warn(&pdev->dev, "Could not set up keyboard backlight LED: %d\n", err);
1554 else
1555 dev_info(&pdev->dev, "Keyboard backlight control not available\n");
1556 }
1557
1011 /*1558 /*
1012 * On some models without a hw-switch (the yoga 2 13 at least)1559 * On some models without a hw-switch (the yoga 2 13 at least)
1013 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.1560 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1014 */1561 */
1015 if (!priv->has_hw_rfkill_switch)1562 if (!priv->features.hw_rfkill_switch)
1016 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);1563 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1017 1564
1018 /* The same for Touchpad */1565 /* The same for Touchpad */
1019 if (!priv->has_touchpad_switch)1566 if (!priv->features.touchpad_ctrl_via_ec)
1020 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);1567 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
1021 1568
1022 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)1569 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
@@ -1026,45 +1573,70 @@ static int ideapad_acpi_add(struct platform_device *pdev) · 3 unmodified lines
1026 ideapad_sync_rfk_state(priv);1573 ideapad_sync_rfk_state(priv);
1027 ideapad_sync_touchpad_state(priv);1574 ideapad_sync_touchpad_state(priv);
1028 1575
1576 err = ideapad_dytc_profile_init(priv);
1577 if (err) {
1578 if (err != -ENODEV)
1579 dev_warn(&pdev->dev, "Could not set up DYTC interface: %d\n", err);
1580 else
1581 dev_info(&pdev->dev, "DYTC interface is not available\n");
1582 }
1583
1029 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {1584 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1030 ret = ideapad_backlight_init(priv);1585 err = ideapad_backlight_init(priv);
1031 if (ret && ret != -ENODEV)1586 if (err && err != -ENODEV)
1032 goto backlight_failed;1587 goto backlight_failed;
1033 }1588 }
1034 ret = acpi_install_notify_handler(adev->handle,1589
1035 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);1590 status = acpi_install_notify_handler(adev->handle,
1036 if (ret)1591 ACPI_DEVICE_NOTIFY,
1592 ideapad_acpi_notify, priv);
1593 if (ACPI_FAILURE(status)) {
1594 err = -EIO;
1037 goto notification_failed;1595 goto notification_failed;
1596 }
1038 1597
1039#if IS_ENABLED(CONFIG_ACPI_WMI)1598#if IS_ENABLED(CONFIG_ACPI_WMI)
1040 for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {1599 for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1041 ret = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],1600 status = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1042 ideapad_wmi_notify, priv);1601 ideapad_wmi_notify, priv);
1043 if (ret == AE_OK) {1602 if (ACPI_SUCCESS(status)) {
1044 priv->fnesc_guid = ideapad_wmi_fnesc_events[i];1603 priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1045 break;1604 break;
1046 }1605 }
1047 }1606 }
1048 if (ret != AE_OK && ret != AE_NOT_EXIST)1607
1608 if (ACPI_FAILURE(status) && status != AE_NOT_EXIST) {
1609 err = -EIO;
1049 goto notification_failed_wmi;1610 goto notification_failed_wmi;
1611 }
1050#endif1612#endif
1051 1613
1052 return 0;1614 return 0;
1615
1053#if IS_ENABLED(CONFIG_ACPI_WMI)1616#if IS_ENABLED(CONFIG_ACPI_WMI)
1054notification_failed_wmi:1617notification_failed_wmi:
1055 acpi_remove_notify_handler(priv->adev->handle,1618 acpi_remove_notify_handler(priv->adev->handle,
1056 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);1619 ACPI_DEVICE_NOTIFY,
1620 ideapad_acpi_notify);
1057#endif1621#endif
1622
1058notification_failed:1623notification_failed:
1059 ideapad_backlight_exit(priv);1624 ideapad_backlight_exit(priv);
1625
1060backlight_failed:1626backlight_failed:
1627 ideapad_dytc_profile_exit(priv);
1628
1061 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)1629 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1062 ideapad_unregister_rfkill(priv, i);1630 ideapad_unregister_rfkill(priv, i);
1631
1632 ideapad_kbd_bl_exit(priv);
1063 ideapad_input_exit(priv);1633 ideapad_input_exit(priv);
1634
1064input_failed:1635input_failed:
1065 ideapad_debugfs_exit(priv);1636 ideapad_debugfs_exit(priv);
1066 ideapad_sysfs_exit(priv);1637 ideapad_sysfs_exit(priv);
1067 return ret;1638
1639 return err;
1068}1640}
1069 1641
1070static int ideapad_acpi_remove(struct platform_device *pdev)1642static int ideapad_acpi_remove(struct platform_device *pdev)
@@ -1076,38 +1648,44 @@ static int ideapad_acpi_remove(struct platform_device *pdev) · 5 unmodified lines
1076 if (priv->fnesc_guid)1648 if (priv->fnesc_guid)
1077 wmi_remove_notify_handler(priv->fnesc_guid);1649 wmi_remove_notify_handler(priv->fnesc_guid);
1078#endif1650#endif
1651
1079 acpi_remove_notify_handler(priv->adev->handle,1652 acpi_remove_notify_handler(priv->adev->handle,
1080 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);1653 ACPI_DEVICE_NOTIFY,
1654 ideapad_acpi_notify);
1655
1081 ideapad_backlight_exit(priv);1656 ideapad_backlight_exit(priv);
1657 ideapad_dytc_profile_exit(priv);
1658
1082 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)1659 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1083 ideapad_unregister_rfkill(priv, i);1660 ideapad_unregister_rfkill(priv, i);
1661
1662 ideapad_kbd_bl_exit(priv);
1084 ideapad_input_exit(priv);1663 ideapad_input_exit(priv);
1085 ideapad_debugfs_exit(priv);1664 ideapad_debugfs_exit(priv);
1086 ideapad_sysfs_exit(priv);1665 ideapad_sysfs_exit(priv);
1087 dev_set_drvdata(&pdev->dev, NULL);
1088 1666
1089 return 0;1667 return 0;
1090}1668}
1091 1669
1092#ifdef CONFIG_PM_SLEEP1670#ifdef CONFIG_PM_SLEEP
1093static int ideapad_acpi_resume(struct device *device)1671static int ideapad_acpi_resume(struct device *dev)
1094{1672{
1095 struct ideapad_private *priv;1673 struct ideapad_private *priv = dev_get_drvdata(dev);
1096
1097 if (!device)
1098 return -EINVAL;
1099 priv = dev_get_drvdata(device);
1100 1674
1101 ideapad_sync_rfk_state(priv);1675 ideapad_sync_rfk_state(priv);
1102 ideapad_sync_touchpad_state(priv);1676 ideapad_sync_touchpad_state(priv);
1677
1678 if (priv->dytc)
1679 dytc_profile_refresh(priv);
1680
1103 return 0;1681 return 0;
1104}1682}
1105#endif1683#endif
1106static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);1684static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1107 1685
1108static const struct acpi_device_id ideapad_device_ids[] = {1686static const struct acpi_device_id ideapad_device_ids[] = {
1109 { "VPC2004", 0},1687 {"VPC2004", 0},
1110 { "", 0},1688 {"", 0},
1111};1689};
1112MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);1690MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1113 1691
drivers/platform/x86/intel-uncore-frequency.c+1−0
@@ -377,6 +377,7 @@ static const struct x86_cpu_id intel_uncore_cpu_ids[] = { · 376 unmodified lines
377 X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, NULL),377 X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, NULL),
378 X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, NULL),378 X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, NULL),
379 X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, NULL),379 X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, NULL),
380 X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, NULL),
380 {}381 {}
381};382};
382 383
drivers/platform/x86/intel-vbtn.c+81−57
@@ -44,6 +44,7 @@ static const struct key_entry intel_vbtn_keymap[] = { · 43 unmodified lines
44 { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */44 { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
45 { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */45 { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */
46 { KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */46 { KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */
47 { KE_END }
47};48};
48 49
49static const struct key_entry intel_vbtn_switchmap[] = {50static const struct key_entry intel_vbtn_switchmap[] = {
@@ -51,14 +52,15 @@ static const struct key_entry intel_vbtn_switchmap[] = { · 1 unmodified line
51 { KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */52 { KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
52 { KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */53 { KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
53 { KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */54 { KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
55 { KE_END }
54};56};
55 57
56#define KEYMAP_LEN \58#define KEYMAP_LEN \
57 (ARRAY_SIZE(intel_vbtn_keymap) + ARRAY_SIZE(intel_vbtn_switchmap) + 1)59 (ARRAY_SIZE(intel_vbtn_keymap) + ARRAY_SIZE(intel_vbtn_switchmap) + 1)
58 60
59struct intel_vbtn_priv {61struct intel_vbtn_priv {
60 struct key_entry keymap[KEYMAP_LEN];62 struct input_dev *buttons_dev;
61 struct input_dev *input_dev;63 struct input_dev *switches_dev;
62 bool has_buttons;64 bool has_buttons;
63 bool has_switches;65 bool has_switches;
64 bool wakeup_mode;66 bool wakeup_mode;
@@ -77,48 +79,62 @@ static void detect_tablet_mode(struct platform_device *device) · 12 unmodified lines
77 return;79 return;
78 80
79 m = !(vgbs & VGBS_TABLET_MODE_FLAGS);81 m = !(vgbs & VGBS_TABLET_MODE_FLAGS);
80 input_report_switch(priv->input_dev, SW_TABLET_MODE, m);82 input_report_switch(priv->switches_dev, SW_TABLET_MODE, m);
81 m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;83 m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;
82 input_report_switch(priv->input_dev, SW_DOCK, m);84 input_report_switch(priv->switches_dev, SW_DOCK, m);
83}85}
84 86
87/*
88 * Note this unconditionally creates the 2 input_dev-s and sets up
89 * the sparse-keymaps. Only the registration is conditional on
90 * have_buttons / have_switches. This is done so that the notify
91 * handler can always call sparse_keymap_entry_from_scancode()
92 * on the input_dev-s do determine the event type.
93 */
85static int intel_vbtn_input_setup(struct platform_device *device)94static int intel_vbtn_input_setup(struct platform_device *device)
86{95{
87 struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);96 struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
88 int ret, keymap_len = 0;97 int ret;
89 98
90 if (priv->has_buttons) {99 priv->buttons_dev = devm_input_allocate_device(&device->dev);
91 memcpy(&priv->keymap[keymap_len], intel_vbtn_keymap,100 if (!priv->buttons_dev)
92 ARRAY_SIZE(intel_vbtn_keymap) *101 return -ENOMEM;
93 sizeof(struct key_entry));
94 keymap_len += ARRAY_SIZE(intel_vbtn_keymap);
95 }
96 102
97 if (priv->has_switches) {103 ret = sparse_keymap_setup(priv->buttons_dev, intel_vbtn_keymap, NULL);
98 memcpy(&priv->keymap[keymap_len], intel_vbtn_switchmap,104 if (ret)
99 ARRAY_SIZE(intel_vbtn_switchmap) *105 return ret;
100 sizeof(struct key_entry));
101 keymap_len += ARRAY_SIZE(intel_vbtn_switchmap);
102 }
103 106
104 priv->keymap[keymap_len].type = KE_END;107 priv->buttons_dev->dev.parent = &device->dev;
108 priv->buttons_dev->name = "Intel Virtual Buttons";
109 priv->buttons_dev->id.bustype = BUS_HOST;
105 110
106 priv->input_dev = devm_input_allocate_device(&device->dev);111 if (priv->has_buttons) {
107 if (!priv->input_dev)112 ret = input_register_device(priv->buttons_dev);
113 if (ret)
114 return ret;
115 }
116
117 priv->switches_dev = devm_input_allocate_device(&device->dev);
118 if (!priv->switches_dev)
108 return -ENOMEM;119 return -ENOMEM;
109 120
110 ret = sparse_keymap_setup(priv->input_dev, priv->keymap, NULL);121 ret = sparse_keymap_setup(priv->switches_dev, intel_vbtn_switchmap, NULL);
111 if (ret)122 if (ret)
112 return ret;123 return ret;
113 124
114 priv->input_dev->dev.parent = &device->dev;125 priv->switches_dev->dev.parent = &device->dev;
115 priv->input_dev->name = "Intel Virtual Button driver";126 priv->switches_dev->name = "Intel Virtual Switches";
116 priv->input_dev->id.bustype = BUS_HOST;127 priv->switches_dev->id.bustype = BUS_HOST;
117 128
118 if (priv->has_switches)129 if (priv->has_switches) {
119 detect_tablet_mode(device);130 detect_tablet_mode(device);
120 131
121 return input_register_device(priv->input_dev);132 ret = input_register_device(priv->switches_dev);
133 if (ret)
134 return ret;
135 }
136
137 return 0;
122}138}
123 139
124static void notify_handler(acpi_handle handle, u32 event, void *context)140static void notify_handler(acpi_handle handle, u32 event, void *context)
@@ -127,48 +143,50 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) · 2 unmodified lines
127 struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);143 struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
128 unsigned int val = !(event & 1); /* Even=press, Odd=release */144 unsigned int val = !(event & 1); /* Even=press, Odd=release */
129 const struct key_entry *ke, *ke_rel;145 const struct key_entry *ke, *ke_rel;
146 struct input_dev *input_dev;
130 bool autorelease;147 bool autorelease;
148 int ret;
131 149
132 if (priv->wakeup_mode) {150 if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) {
133 ke = sparse_keymap_entry_from_scancode(priv->input_dev, event);151 if (!priv->has_buttons) {
134 if (ke) {152 dev_warn(&device->dev, "Warning: received a button event on a device without buttons, please report this.\n");
135 pm_wakeup_hard_event(&device->dev);
136
137 /*
138 * Switch events like tablet mode will wake the device
139 * and report the new switch position to the input
140 * subsystem.
141 */
142 if (ke->type == KE_SW)
143 sparse_keymap_report_event(priv->input_dev,
144 event,
145 val,
146 0);
147 return;153 return;
148 }154 }
149 goto out_unknown;155 input_dev = priv->buttons_dev;
156 } else if ((ke = sparse_keymap_entry_from_scancode(priv->switches_dev, event))) {
157 if (!priv->has_switches) {
158 dev_info(&device->dev, "Registering Intel Virtual Switches input-dev after receiving a switch event\n");
159 ret = input_register_device(priv->switches_dev);
160 if (ret)
161 return;
162
163 priv->has_switches = true;
164 }
165 input_dev = priv->switches_dev;
166 } else {
167 dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
168 return;
169 }
170
171 if (priv->wakeup_mode) {
172 pm_wakeup_hard_event(&device->dev);
173
174 /*
175 * Skip reporting an evdev event for button wake events,
176 * mirroring how the drivers/acpi/button.c code skips this too.
177 */
178 if (ke->type == KE_KEY)
179 return;
150 }180 }
151 181
152 /*182 /*
153 * Even press events are autorelease if there is no corresponding odd183 * Even press events are autorelease if there is no corresponding odd
154 * release event, or if the odd event is KE_IGNORE.184 * release event, or if the odd event is KE_IGNORE.
155 */185 */
156 ke_rel = sparse_keymap_entry_from_scancode(priv->input_dev, event | 1);186 ke_rel = sparse_keymap_entry_from_scancode(input_dev, event | 1);
157 autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);187 autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
158 188
159 if (sparse_keymap_report_event(priv->input_dev, event, val, autorelease))189 sparse_keymap_report_event(input_dev, event, val, autorelease);
160 return;
161
162out_unknown:
163 dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
164}
165
166static bool intel_vbtn_has_buttons(acpi_handle handle)
167{
168 acpi_status status;
169
170 status = acpi_evaluate_object(handle, "VBDL", NULL, NULL);
171 return ACPI_SUCCESS(status);
172}190}
173 191
174/*192/*
@@ -245,7 +263,7 @@ static int intel_vbtn_probe(struct platform_device *device) · 70 unmodified lines
245 acpi_status status;263 acpi_status status;
246 int err;264 int err;
247 265
248 has_buttons = intel_vbtn_has_buttons(handle);266 has_buttons = acpi_has_method(handle, "VBDL");
249 has_switches = intel_vbtn_has_switches(handle);267 has_switches = intel_vbtn_has_switches(handle);
250 268
251 if (!has_buttons && !has_switches) {269 if (!has_buttons && !has_switches) {
@@ -274,6 +292,12 @@ static int intel_vbtn_probe(struct platform_device *device) · 22 unmodified lines
274 if (ACPI_FAILURE(status))292 if (ACPI_FAILURE(status))
275 return -EBUSY;293 return -EBUSY;
276 294
295 if (has_buttons) {
296 status = acpi_evaluate_object(handle, "VBDL", NULL, NULL);
297 if (ACPI_FAILURE(status))
298 dev_err(&device->dev, "Error VBDL failed with ACPI status %d\n", status);
299 }
300
277 device_init_wakeup(&device->dev, true);301 device_init_wakeup(&device->dev, true);
278 /*302 /*
279 * In order for system wakeup to work, the EC GPE has to be marked as303 * In order for system wakeup to work, the EC GPE has to be marked as
drivers/platform/x86/intel_mid_powerbtn.c+0−233
@@ -1,233 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Power button driver for Intel MID platforms.
4 *
5 * Copyright (C) 2010,2017 Intel Corp
6 *
7 * Author: Hong Liu <hong.liu@intel.com>
8 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
9 */
10
11#include <linux/input.h>
12#include <linux/interrupt.h>
13#include <linux/mfd/intel_msic.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/pm_wakeirq.h>
17#include <linux/slab.h>
18
19#include <asm/cpu_device_id.h>
20#include <asm/intel-family.h>
21#include <asm/intel_scu_ipc.h>
22
23#define DRIVER_NAME "msic_power_btn"
24
25#define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
26
27/*
28 * MSIC document ti_datasheet defines the 1st bit reg 0x21 is used to mask
29 * power button interrupt
30 */
31#define MSIC_PWRBTNM (1 << 0)
32
33/* Intel Tangier */
34#define BCOVE_PB_LEVEL (1 << 4) /* 1 - release, 0 - press */
35
36/* Basin Cove PMIC */
37#define BCOVE_PBIRQ 0x02
38#define BCOVE_IRQLVL1MSK 0x0c
39#define BCOVE_PBIRQMASK 0x0d
40#define BCOVE_PBSTATUS 0x27
41
42struct mid_pb_ddata {
43 struct device *dev;
44 int irq;
45 struct input_dev *input;
46 unsigned short mirqlvl1_addr;
47 unsigned short pbstat_addr;
48 u8 pbstat_mask;
49 struct intel_scu_ipc_dev *scu;
50 int (*setup)(struct mid_pb_ddata *ddata);
51};
52
53static int mid_pbstat(struct mid_pb_ddata *ddata, int *value)
54{
55 struct input_dev *input = ddata->input;
56 int ret;
57 u8 pbstat;
58
59 ret = intel_scu_ipc_dev_ioread8(ddata->scu, ddata->pbstat_addr,
60 &pbstat);
61 if (ret)
62 return ret;
63
64 dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat);
65
66 *value = !(pbstat & ddata->pbstat_mask);
67 return 0;
68}
69
70static int mid_irq_ack(struct mid_pb_ddata *ddata)
71{
72 return intel_scu_ipc_dev_update(ddata->scu, ddata->mirqlvl1_addr, 0,
73 MSIC_PWRBTNM);
74}
75
76static int mrfld_setup(struct mid_pb_ddata *ddata)
77{
78 /* Unmask the PBIRQ and MPBIRQ on Tangier */
79 intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQ, 0, MSIC_PWRBTNM);
80 intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM);
81
82 return 0;
83}
84
85static irqreturn_t mid_pb_isr(int irq, void *dev_id)
86{
87 struct mid_pb_ddata *ddata = dev_id;
88 struct input_dev *input = ddata->input;
89 int value = 0;
90 int ret;
91
92 ret = mid_pbstat(ddata, &value);
93 if (ret < 0) {
94 dev_err(input->dev.parent,
95 "Read error %d while reading MSIC_PB_STATUS\n", ret);
96 } else {
97 input_event(input, EV_KEY, KEY_POWER, value);
98 input_sync(input);
99 }
100
101 mid_irq_ack(ddata);
102 return IRQ_HANDLED;
103}
104
105static const struct mid_pb_ddata mfld_ddata = {
106 .mirqlvl1_addr = INTEL_MSIC_IRQLVL1MSK,
107 .pbstat_addr = INTEL_MSIC_PBSTATUS,
108 .pbstat_mask = MSIC_PB_LEVEL,
109};
110
111static const struct mid_pb_ddata mrfld_ddata = {
112 .mirqlvl1_addr = BCOVE_IRQLVL1MSK,
113 .pbstat_addr = BCOVE_PBSTATUS,
114 .pbstat_mask = BCOVE_PB_LEVEL,
115 .setup = mrfld_setup,
116};
117
118static const struct x86_cpu_id mid_pb_cpu_ids[] = {
119 X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL_MID, &mfld_ddata),
120 X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &mrfld_ddata),
121 {}
122};
123
124static int mid_pb_probe(struct platform_device *pdev)
125{
126 const struct x86_cpu_id *id;
127 struct mid_pb_ddata *ddata;
128 struct input_dev *input;
129 int irq = platform_get_irq(pdev, 0);
130 int error;
131
132 id = x86_match_cpu(mid_pb_cpu_ids);
133 if (!id)
134 return -ENODEV;
135
136 if (irq < 0) {
137 dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
138 return irq;
139 }
140
141 input = devm_input_allocate_device(&pdev->dev);
142 if (!input)
143 return -ENOMEM;
144
145 input->name = pdev->name;
146 input->phys = "power-button/input0";
147 input->id.bustype = BUS_HOST;
148 input->dev.parent = &pdev->dev;
149
150 input_set_capability(input, EV_KEY, KEY_POWER);
151
152 ddata = devm_kmemdup(&pdev->dev, (void *)id->driver_data,
153 sizeof(*ddata), GFP_KERNEL);
154 if (!ddata)
155 return -ENOMEM;
156
157 ddata->dev = &pdev->dev;
158 ddata->irq = irq;
159 ddata->input = input;
160
161 if (ddata->setup) {
162 error = ddata->setup(ddata);
163 if (error)
164 return error;
165 }
166
167 ddata->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);
168 if (!ddata->scu)
169 return -EPROBE_DEFER;
170
171 error = devm_request_threaded_irq(&pdev->dev, irq, NULL, mid_pb_isr,
172 IRQF_ONESHOT, DRIVER_NAME, ddata);
173 if (error) {
174 dev_err(&pdev->dev,
175 "Unable to request irq %d for MID power button\n", irq);
176 return error;
177 }
178
179 error = input_register_device(input);
180 if (error) {
181 dev_err(&pdev->dev,
182 "Unable to register input dev, error %d\n", error);
183 return error;
184 }
185
186 platform_set_drvdata(pdev, ddata);
187
188 /*
189 * SCU firmware might send power button interrupts to IA core before
190 * kernel boots and doesn't get EOI from IA core. The first bit of
191 * MSIC reg 0x21 is kept masked, and SCU firmware doesn't send new
192 * power interrupt to Android kernel. Unmask the bit when probing
193 * power button in kernel.
194 * There is a very narrow race between irq handler and power button
195 * initialization. The race happens rarely. So we needn't worry
196 * about it.
197 */
198 error = mid_irq_ack(ddata);
199 if (error) {
200 dev_err(&pdev->dev,
201 "Unable to clear power button interrupt, error: %d\n",
202 error);
203 return error;
204 }
205
206 device_init_wakeup(&pdev->dev, true);
207 dev_pm_set_wake_irq(&pdev->dev, irq);
208
209 return 0;
210}
211
212static int mid_pb_remove(struct platform_device *pdev)
213{
214 dev_pm_clear_wake_irq(&pdev->dev);
215 device_init_wakeup(&pdev->dev, false);
216
217 return 0;
218}
219
220static struct platform_driver mid_pb_driver = {
221 .driver = {
222 .name = DRIVER_NAME,
223 },
224 .probe = mid_pb_probe,
225 .remove = mid_pb_remove,
226};
227
228module_platform_driver(mid_pb_driver);
229
230MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
231MODULE_DESCRIPTION("Intel MID Power Button Driver");
232MODULE_LICENSE("GPL v2");
233MODULE_ALIAS("platform:" DRIVER_NAME);
drivers/platform/x86/intel_mid_thermal.c+0−560
@@ -1,560 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel MID platform thermal driver
4 *
5 * Copyright (C) 2011 Intel Corporation
6 *
7 * Author: Durgadoss R <durgadoss.r@intel.com>
8 */
9
10#define pr_fmt(fmt) "intel_mid_thermal: " fmt
11
12#include <linux/device.h>
13#include <linux/err.h>
14#include <linux/mfd/intel_msic.h>
15#include <linux/module.h>
16#include <linux/param.h>
17#include <linux/platform_device.h>
18#include <linux/pm.h>
19#include <linux/slab.h>
20#include <linux/thermal.h>
21
22/* Number of thermal sensors */
23#define MSIC_THERMAL_SENSORS 4
24
25/* ADC1 - thermal registers */
26#define MSIC_ADC_ENBL 0x10
27#define MSIC_ADC_START 0x08
28
29#define MSIC_ADCTHERM_ENBL 0x04
30#define MSIC_ADCRRDATA_ENBL 0x05
31#define MSIC_CHANL_MASK_VAL 0x0F
32
33#define MSIC_STOPBIT_MASK 16
34#define MSIC_ADCTHERM_MASK 4
35/* Number of ADC channels */
36#define ADC_CHANLS_MAX 15
37#define ADC_LOOP_MAX (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
38
39/* ADC channel code values */
40#define SKIN_SENSOR0_CODE 0x08
41#define SKIN_SENSOR1_CODE 0x09
42#define SYS_SENSOR_CODE 0x0A
43#define MSIC_DIE_SENSOR_CODE 0x03
44
45#define SKIN_THERM_SENSOR0 0
46#define SKIN_THERM_SENSOR1 1
47#define SYS_THERM_SENSOR2 2
48#define MSIC_DIE_THERM_SENSOR3 3
49
50/* ADC code range */
51#define ADC_MAX 977
52#define ADC_MIN 162
53#define ADC_VAL0C 887
54#define ADC_VAL20C 720
55#define ADC_VAL40C 508
56#define ADC_VAL60C 315
57
58/* ADC base addresses */
59#define ADC_CHNL_START_ADDR INTEL_MSIC_ADC1ADDR0 /* increments by 1 */
60#define ADC_DATA_START_ADDR INTEL_MSIC_ADC1SNS0H /* increments by 2 */
61
62/* MSIC die attributes */
63#define MSIC_DIE_ADC_MIN 488
64#define MSIC_DIE_ADC_MAX 1004
65
66/* This holds the address of the first free ADC channel,
67 * among the 15 channels
68 */
69static int channel_index;
70
71struct platform_info {
72 struct platform_device *pdev;
73 struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
74};
75
76struct thermal_device_info {
77 unsigned int chnl_addr;
78 int direct;
79 /* This holds the current temperature in millidegree celsius */
80 long curr_temp;
81};
82
83/**
84 * to_msic_die_temp - converts adc_val to msic_die temperature
85 * @adc_val: ADC value to be converted
86 *
87 * Can sleep
88 */
89static int to_msic_die_temp(uint16_t adc_val)
90{
91 return (368 * (adc_val) / 1000) - 220;
92}
93
94/**
95 * is_valid_adc - checks whether the adc code is within the defined range
96 * @min: minimum value for the sensor
97 * @max: maximum value for the sensor
98 *
99 * Can sleep
100 */
101static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
102{
103 return (adc_val >= min) && (adc_val <= max);
104}
105
106/**
107 * adc_to_temp - converts the ADC code to temperature in C
108 * @direct: true if ths channel is direct index
109 * @adc_val: the adc_val that needs to be converted
110 * @tp: temperature return value
111 *
112 * Linear approximation is used to covert the skin adc value into temperature.
113 * This technique is used to avoid very long look-up table to get
114 * the appropriate temp value from ADC value.
115 * The adc code vs sensor temp curve is split into five parts
116 * to achieve very close approximate temp value with less than
117 * 0.5C error
118 */
119static int adc_to_temp(int direct, uint16_t adc_val, int *tp)
120{
121 int temp;
122
123 /* Direct conversion for die temperature */
124 if (direct) {
125 if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
126 *tp = to_msic_die_temp(adc_val) * 1000;
127 return 0;
128 }
129 return -ERANGE;
130 }
131
132 if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
133 return -ERANGE;
134
135 /* Linear approximation for skin temperature */
136 if (adc_val > ADC_VAL0C)
137 temp = 177 - (adc_val/5);
138 else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
139 temp = 111 - (adc_val/8);
140 else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
141 temp = 92 - (adc_val/10);
142 else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
143 temp = 91 - (adc_val/10);
144 else
145 temp = 112 - (adc_val/6);
146
147 /* Convert temperature in celsius to milli degree celsius */
148 *tp = temp * 1000;
149 return 0;
150}
151
152/**
153 * mid_read_temp - read sensors for temperature
154 * @temp: holds the current temperature for the sensor after reading
155 *
156 * reads the adc_code from the channel and converts it to real
157 * temperature. The converted value is stored in temp.
158 *
159 * Can sleep
160 */
161static int mid_read_temp(struct thermal_zone_device *tzd, int *temp)
162{
163 struct thermal_device_info *td_info = tzd->devdata;
164 uint16_t adc_val, addr;
165 uint8_t data = 0;
166 int ret;
167 int curr_temp;
168
169 addr = td_info->chnl_addr;
170
171 /* Enable the msic for conversion before reading */
172 ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
173 if (ret)
174 return ret;
175
176 /* Re-toggle the RRDATARD bit (temporary workaround) */
177 ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
178 if (ret)
179 return ret;
180
181 /* Read the higher bits of data */
182 ret = intel_msic_reg_read(addr, &data);
183 if (ret)
184 return ret;
185
186 /* Shift bits to accommodate the lower two data bits */
187 adc_val = (data << 2);
188 addr++;
189
190 ret = intel_msic_reg_read(addr, &data);/* Read lower bits */
191 if (ret)
192 return ret;
193
194 /* Adding lower two bits to the higher bits */
195 data &= 03;
196 adc_val += data;
197
198 /* Convert ADC value to temperature */
199 ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
200 if (ret == 0)
201 *temp = td_info->curr_temp = curr_temp;
202 return ret;
203}
204
205/**
206 * configure_adc - enables/disables the ADC for conversion
207 * @val: zero: disables the ADC non-zero:enables the ADC
208 *
209 * Enable/Disable the ADC depending on the argument
210 *
211 * Can sleep
212 */
213static int configure_adc(int val)
214{
215 int ret;
216 uint8_t data;
217
218 ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
219 if (ret)
220 return ret;
221
222 if (val) {
223 /* Enable and start the ADC */
224 data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
225 } else {
226 /* Just stop the ADC */
227 data &= (~MSIC_ADC_START);
228 }
229 return intel_msic_reg_write(INTEL_MSIC_ADC1CNTL1, data);
230}
231
232/**
233 * set_up_therm_channel - enable thermal channel for conversion
234 * @base_addr: index of free msic ADC channel
235 *
236 * Enable all the three channels for conversion
237 *
238 * Can sleep
239 */
240static int set_up_therm_channel(u16 base_addr)
241{
242 int ret;
243
244 /* Enable all the sensor channels */
245 ret = intel_msic_reg_write(base_addr, SKIN_SENSOR0_CODE);
246 if (ret)
247 return ret;
248
249 ret = intel_msic_reg_write(base_addr + 1, SKIN_SENSOR1_CODE);
250 if (ret)
251 return ret;
252
253 ret = intel_msic_reg_write(base_addr + 2, SYS_SENSOR_CODE);
254 if (ret)
255 return ret;
256
257 /* Since this is the last channel, set the stop bit
258 * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
259 ret = intel_msic_reg_write(base_addr + 3,
260 (MSIC_DIE_SENSOR_CODE | 0x10));
261 if (ret)
262 return ret;
263
264 /* Enable ADC and start it */
265 return configure_adc(1);
266}
267
268/**
269 * reset_stopbit - sets the stop bit to 0 on the given channel
270 * @addr: address of the channel
271 *
272 * Can sleep
273 */
274static int reset_stopbit(uint16_t addr)
275{
276 int ret;
277 uint8_t data;
278 ret = intel_msic_reg_read(addr, &data);
279 if (ret)
280 return ret;
281 /* Set the stop bit to zero */
282 return intel_msic_reg_write(addr, (data & 0xEF));
283}
284
285/**
286 * find_free_channel - finds an empty channel for conversion
287 *
288 * If the ADC is not enabled then start using 0th channel
289 * itself. Otherwise find an empty channel by looking for a
290 * channel in which the stopbit is set to 1. returns the index
291 * of the first free channel if succeeds or an error code.
292 *
293 * Context: can sleep
294 *
295 * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
296 * code.
297 */
298static int find_free_channel(void)
299{
300 int ret;
301 int i;
302 uint8_t data;
303
304 /* check whether ADC is enabled */
305 ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
306 if (ret)
307 return ret;
308
309 if ((data & MSIC_ADC_ENBL) == 0)
310 return 0;
311
312 /* ADC is already enabled; Looking for an empty channel */
313 for (i = 0; i < ADC_CHANLS_MAX; i++) {
314 ret = intel_msic_reg_read(ADC_CHNL_START_ADDR + i, &data);
315 if (ret)
316 return ret;
317
318 if (data & MSIC_STOPBIT_MASK) {
319 ret = i;
320 break;
321 }
322 }
323 return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
324}
325
326/**
327 * mid_initialize_adc - initializing the ADC
328 * @dev: our device structure
329 *
330 * Initialize the ADC for reading thermistor values. Can sleep.
331 */
332static int mid_initialize_adc(struct device *dev)
333{
334 u8 data;
335 u16 base_addr;
336 int ret;
337
338 /*
339 * Ensure that adctherm is disabled before we
340 * initialize the ADC
341 */
342 ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL3, &data);
343 if (ret)
344 return ret;
345
346 data &= ~MSIC_ADCTHERM_MASK;
347 ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, data);
348 if (ret)
349 return ret;
350
351 /* Index of the first channel in which the stop bit is set */
352 channel_index = find_free_channel();
353 if (channel_index < 0) {
354 dev_err(dev, "No free ADC channels");
355 return channel_index;
356 }
357
358 base_addr = ADC_CHNL_START_ADDR + channel_index;
359
360 if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
361 /* Reset stop bit for channels other than 0 and 12 */
362 ret = reset_stopbit(base_addr);
363 if (ret)
364 return ret;
365
366 /* Index of the first free channel */
367 base_addr++;
368 channel_index++;
369 }
370
371 ret = set_up_therm_channel(base_addr);
372 if (ret) {
373 dev_err(dev, "unable to enable ADC");
374 return ret;
375 }
376 dev_dbg(dev, "ADC initialization successful");
377 return ret;
378}
379
380/**
381 * initialize_sensor - sets default temp and timer ranges
382 * @index: index of the sensor
383 *
384 * Context: can sleep
385 */
386static struct thermal_device_info *initialize_sensor(int index)
387{
388 struct thermal_device_info *td_info =
389 kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
390
391 if (!td_info)
392 return NULL;
393
394 /* Set the base addr of the channel for this sensor */
395 td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
396 /* Sensor 3 is direct conversion */
397 if (index == 3)
398 td_info->direct = 1;
399 return td_info;
400}
401
402#ifdef CONFIG_PM_SLEEP
403/**
404 * mid_thermal_resume - resume routine
405 * @dev: device structure
406 *
407 * mid thermal resume: re-initializes the adc. Can sleep.
408 */
409static int mid_thermal_resume(struct device *dev)
410{
411 return mid_initialize_adc(dev);
412}
413
414/**
415 * mid_thermal_suspend - suspend routine
416 * @dev: device structure
417 *
418 * mid thermal suspend implements the suspend functionality
419 * by stopping the ADC. Can sleep.
420 */
421static int mid_thermal_suspend(struct device *dev)
422{
423 /*
424 * This just stops the ADC and does not disable it.
425 * temporary workaround until we have a generic ADC driver.
426 * If 0 is passed, it disables the ADC.
427 */
428 return configure_adc(0);
429}
430#endif
431
432static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
433 mid_thermal_suspend, mid_thermal_resume);
434
435/**
436 * read_curr_temp - reads the current temperature and stores in temp
437 * @temp: holds the current temperature value after reading
438 *
439 * Can sleep
440 */
441static int read_curr_temp(struct thermal_zone_device *tzd, int *temp)
442{
443 WARN_ON(tzd == NULL);
444 return mid_read_temp(tzd, temp);
445}
446
447/* Can't be const */
448static struct thermal_zone_device_ops tzd_ops = {
449 .get_temp = read_curr_temp,
450};
451
452/**
453 * mid_thermal_probe - mfld thermal initialize
454 * @pdev: platform device structure
455 *
456 * mid thermal probe initializes the hardware and registers
457 * all the sensors with the generic thermal framework. Can sleep.
458 */
459static int mid_thermal_probe(struct platform_device *pdev)
460{
461 static char *name[MSIC_THERMAL_SENSORS] = {
462 "skin0", "skin1", "sys", "msicdie"
463 };
464
465 int ret;
466 int i;
467 struct platform_info *pinfo;
468
469 pinfo = devm_kzalloc(&pdev->dev, sizeof(struct platform_info),
470 GFP_KERNEL);
471 if (!pinfo)
472 return -ENOMEM;
473
474 /* Initializing the hardware */
475 ret = mid_initialize_adc(&pdev->dev);
476 if (ret) {
477 dev_err(&pdev->dev, "ADC init failed");
478 return ret;
479 }
480
481 /* Register each sensor with the generic thermal framework*/
482 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
483 struct thermal_device_info *td_info = initialize_sensor(i);
484
485 if (!td_info) {
486 ret = -ENOMEM;
487 goto err;
488 }
489 pinfo->tzd[i] = thermal_zone_device_register(name[i],
490 0, 0, td_info, &tzd_ops, NULL, 0, 0);
491 if (IS_ERR(pinfo->tzd[i])) {
492 kfree(td_info);
493 ret = PTR_ERR(pinfo->tzd[i]);
494 goto err;
495 }
496 ret = thermal_zone_device_enable(pinfo->tzd[i]);
497 if (ret) {
498 kfree(td_info);
499 thermal_zone_device_unregister(pinfo->tzd[i]);
500 goto err;
501 }
502 }
503
504 pinfo->pdev = pdev;
505 platform_set_drvdata(pdev, pinfo);
506 return 0;
507
508err:
509 while (--i >= 0) {
510 kfree(pinfo->tzd[i]->devdata);
511 thermal_zone_device_unregister(pinfo->tzd[i]);
512 }
513 configure_adc(0);
514 return ret;
515}
516
517/**
518 * mid_thermal_remove - mfld thermal finalize
519 * @dev: platform device structure
520 *
521 * MLFD thermal remove unregisters all the sensors from the generic
522 * thermal framework. Can sleep.
523 */
524static int mid_thermal_remove(struct platform_device *pdev)
525{
526 int i;
527 struct platform_info *pinfo = platform_get_drvdata(pdev);
528
529 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
530 kfree(pinfo->tzd[i]->devdata);
531 thermal_zone_device_unregister(pinfo->tzd[i]);
532 }
533
534 /* Stop the ADC */
535 return configure_adc(0);
536}
537
538#define DRIVER_NAME "msic_thermal"
539
540static const struct platform_device_id therm_id_table[] = {
541 { DRIVER_NAME, 1 },
542 { }
543};
544MODULE_DEVICE_TABLE(platform, therm_id_table);
545
546static struct platform_driver mid_thermal_driver = {
547 .driver = {
548 .name = DRIVER_NAME,
549 .pm = &mid_thermal_pm,
550 },
551 .probe = mid_thermal_probe,
552 .remove = mid_thermal_remove,
553 .id_table = therm_id_table,
554};
555
556module_platform_driver(mid_thermal_driver);
557
558MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
559MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
560MODULE_LICENSE("GPL v2");
drivers/platform/x86/intel_scu_ipc.c+1−1
@@ -75,7 +75,7 @@ struct intel_scu_ipc_dev { · 74 unmodified lines
75#define IPC_READ_BUFFER 0x9075#define IPC_READ_BUFFER 0x90
76 76
77/* Timeout in jiffies */77/* Timeout in jiffies */
78#define IPC_TIMEOUT (3 * HZ)78#define IPC_TIMEOUT (5 * HZ)
79 79
80static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */80static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */
81static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */81static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
drivers/platform/x86/intel_scu_wdt.crenamed from arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c+17−24
@@ -11,8 +11,9 @@ · 10 unmodified lines
11#include <linux/platform_device.h>11#include <linux/platform_device.h>
12#include <linux/platform_data/intel-mid_wdt.h>12#include <linux/platform_data/intel-mid_wdt.h>
13 13
14#include <asm/cpu_device_id.h>
15#include <asm/intel-family.h>
14#include <asm/intel-mid.h>16#include <asm/intel-mid.h>
15#include <asm/intel_scu_ipc.h>
16#include <asm/io_apic.h>17#include <asm/io_apic.h>
17#include <asm/hw_irq.h>18#include <asm/hw_irq.h>
18 19
@@ -49,34 +50,26 @@ static struct intel_mid_wdt_pdata tangier_pdata = { · 30 unmodified lines
49 .probe = tangier_probe,50 .probe = tangier_probe,
50};51};
51 52
52static int wdt_scu_status_change(struct notifier_block *nb,53static const struct x86_cpu_id intel_mid_cpu_ids[] = {
53 unsigned long code, void *data)54 X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tangier_pdata),
54{55 {}
55 if (code == SCU_DOWN) {
56 platform_device_unregister(&wdt_dev);
57 return 0;
58 }
59
60 return platform_device_register(&wdt_dev);
61}
62
63static struct notifier_block wdt_scu_notifier = {
64 .notifier_call = wdt_scu_status_change,
65};56};
66 57
67static int __init register_mid_wdt(void)58static int __init register_mid_wdt(void)
68{59{
69 if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)60 const struct x86_cpu_id *id;
70 return -ENODEV;
71 61
72 wdt_dev.dev.platform_data = &tangier_pdata;62 id = x86_match_cpu(intel_mid_cpu_ids);
73 63 if (!id)
74 /*64 return -ENODEV;
75 * We need to be sure that the SCU IPC is ready before watchdog device
76 * can be registered:
77 */
78 intel_scu_notifier_add(&wdt_scu_notifier);
79 65
80 return 0;66 wdt_dev.dev.platform_data = (struct intel_mid_wdt_pdata *)id->driver_data;
67 return platform_device_register(&wdt_dev);
81}68}
82arch_initcall(register_mid_wdt);69arch_initcall(register_mid_wdt);
70
71static void __exit unregister_mid_wdt(void)
72{
73 platform_device_unregister(&wdt_dev);
74}
75__exitcall(unregister_mid_wdt);
drivers/platform/x86/msi-wmi.c+2−0
@@ -96,6 +96,8 @@ static int msi_wmi_query_block(int instance, int *ret) · 95 unmodified lines
96 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };96 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
97 97
98 status = wmi_query_block(MSIWMI_BIOS_GUID, instance, &output);98 status = wmi_query_block(MSIWMI_BIOS_GUID, instance, &output);
99 if (ACPI_FAILURE(status))
100 return -EIO;
99 101
100 obj = output.pointer;102 obj = output.pointer;
101 103
drivers/platform/x86/thinkpad_acpi.c+458−6
@@ -66,6 +66,7 @@ · 65 unmodified lines
66#include <linux/acpi.h>66#include <linux/acpi.h>
67#include <linux/pci.h>67#include <linux/pci.h>
68#include <linux/power_supply.h>68#include <linux/power_supply.h>
69#include <linux/platform_profile.h>
69#include <sound/core.h>70#include <sound/core.h>
70#include <sound/control.h>71#include <sound/control.h>
71#include <sound/initval.h>72#include <sound/initval.h>
@@ -9855,16 +9856,27 @@ static bool has_lapsensor; · 9783 unmodified lines
9855static bool palm_state;9856static bool palm_state;
9856static bool lap_state;9857static bool lap_state;
9857 9858
9858static int lapsensor_get(bool *present, bool *state)9859static int dytc_command(int command, int *output)
9859{9860{
9860 acpi_handle dytc_handle;9861 acpi_handle dytc_handle;
9861 int output;
9862 9862
9863 *present = false;9863 if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) {
9864 if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle)))9864 /* Platform doesn't support DYTC */
9865 return -ENODEV;9865 return -ENODEV;
9866 if (!acpi_evalf(dytc_handle, &output, NULL, "dd", DYTC_CMD_GET))9866 }
9867 if (!acpi_evalf(dytc_handle, output, NULL, "dd", command))
9867 return -EIO;9868 return -EIO;
9869 return 0;
9870}
9871
9872static int lapsensor_get(bool *present, bool *state)
9873{
9874 int output, err;
9875
9876 *present = false;
9877 err = dytc_command(DYTC_CMD_GET, &output);
9878 if (err)
9879 return err;
9868 9880
9869 *present = true; /*If we get his far, we have lapmode support*/9881 *present = true; /*If we get his far, we have lapmode support*/
9870 *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;9882 *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
@@ -9983,6 +9995,434 @@ static struct ibm_struct proxsensor_driver_data = { · 112 unmodified lines
9983 .exit = proxsensor_exit,9995 .exit = proxsensor_exit,
9984};9996};
9985 9997
9998/*************************************************************************
9999 * DYTC Platform Profile interface
10000 */
10001
10002#define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */
10003#define DYTC_CMD_SET 1 /* To enable/disable IC function mode */
10004#define DYTC_CMD_RESET 0x1ff /* To reset back to default */
10005
10006#define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */
10007#define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
10008#define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */
10009
10010#define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */
10011#define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */
10012
10013#define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - function setting */
10014#define DYTC_SET_MODE_BIT 16 /* Bits 16-19 - mode setting */
10015#define DYTC_SET_VALID_BIT 20 /* Bit 20 - 1 = on, 0 = off */
10016
10017#define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */
10018#define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */
10019#define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */
10020
10021#define DYTC_MODE_PERFORM 2 /* High power mode aka performance */
10022#define DYTC_MODE_LOWPOWER 3 /* Low power mode */
10023#define DYTC_MODE_BALANCE 0xF /* Default mode aka balanced */
10024
10025#define DYTC_SET_COMMAND(function, mode, on) \
10026 (DYTC_CMD_SET | (function) << DYTC_SET_FUNCTION_BIT | \
10027 (mode) << DYTC_SET_MODE_BIT | \
10028 (on) << DYTC_SET_VALID_BIT)
10029
10030#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0)
10031
10032#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1)
10033
10034static bool dytc_profile_available;
10035static enum platform_profile_option dytc_current_profile;
10036static atomic_t dytc_ignore_event = ATOMIC_INIT(0);
10037static DEFINE_MUTEX(dytc_mutex);
10038
10039static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
10040{
10041 switch (dytcmode) {
10042 case DYTC_MODE_LOWPOWER:
10043 *profile = PLATFORM_PROFILE_LOW_POWER;
10044 break;
10045 case DYTC_MODE_BALANCE:
10046 *profile = PLATFORM_PROFILE_BALANCED;
10047 break;
10048 case DYTC_MODE_PERFORM:
10049 *profile = PLATFORM_PROFILE_PERFORMANCE;
10050 break;
10051 default: /* Unknown mode */
10052 return -EINVAL;
10053 }
10054 return 0;
10055}
10056
10057static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode)
10058{
10059 switch (profile) {
10060 case PLATFORM_PROFILE_LOW_POWER:
10061 *perfmode = DYTC_MODE_LOWPOWER;
10062 break;
10063 case PLATFORM_PROFILE_BALANCED:
10064 *perfmode = DYTC_MODE_BALANCE;
10065 break;
10066 case PLATFORM_PROFILE_PERFORMANCE:
10067 *perfmode = DYTC_MODE_PERFORM;
10068 break;
10069 default: /* Unknown profile */
10070 return -EOPNOTSUPP;
10071 }
10072 return 0;
10073}
10074
10075/*
10076 * dytc_profile_get: Function to register with platform_profile
10077 * handler. Returns current platform profile.
10078 */
10079static int dytc_profile_get(struct platform_profile_handler *pprof,
10080 enum platform_profile_option *profile)
10081{
10082 *profile = dytc_current_profile;
10083 return 0;
10084}
10085
10086/*
10087 * Helper function - check if we are in CQL mode and if we are
10088 * - disable CQL,
10089 * - run the command
10090 * - enable CQL
10091 * If not in CQL mode, just run the command
10092 */
10093static int dytc_cql_command(int command, int *output)
10094{
10095 int err, cmd_err, dummy;
10096 int cur_funcmode;
10097
10098 /* Determine if we are in CQL mode. This alters the commands we do */
10099 err = dytc_command(DYTC_CMD_GET, output);
10100 if (err)
10101 return err;
10102
10103 cur_funcmode = (*output >> DYTC_GET_FUNCTION_BIT) & 0xF;
10104 /* Check if we're OK to return immediately */
10105 if ((command == DYTC_CMD_GET) && (cur_funcmode != DYTC_FUNCTION_CQL))
10106 return 0;
10107
10108 if (cur_funcmode == DYTC_FUNCTION_CQL) {
10109 atomic_inc(&dytc_ignore_event);
10110 err = dytc_command(DYTC_DISABLE_CQL, &dummy);
10111 if (err)
10112 return err;
10113 }
10114
10115 cmd_err = dytc_command(command, output);
10116 /* Check return condition after we've restored CQL state */
10117
10118 if (cur_funcmode == DYTC_FUNCTION_CQL) {
10119 err = dytc_command(DYTC_ENABLE_CQL, &dummy);
10120 if (err)
10121 return err;
10122 }
10123
10124 return cmd_err;
10125}
10126
10127/*
10128 * dytc_profile_set: Function to register with platform_profile
10129 * handler. Sets current platform profile.
10130 */
10131static int dytc_profile_set(struct platform_profile_handler *pprof,
10132 enum platform_profile_option profile)
10133{
10134 int output;
10135 int err;
10136
10137 if (!dytc_profile_available)
10138 return -ENODEV;
10139
10140 err = mutex_lock_interruptible(&dytc_mutex);
10141 if (err)
10142 return err;
10143
10144 if (profile == PLATFORM_PROFILE_BALANCED) {
10145 /* To get back to balanced mode we just issue a reset command */
10146 err = dytc_command(DYTC_CMD_RESET, &output);
10147 if (err)
10148 goto unlock;
10149 } else {
10150 int perfmode;
10151
10152 err = convert_profile_to_dytc(profile, &perfmode);
10153 if (err)
10154 goto unlock;
10155
10156 /* Determine if we are in CQL mode. This alters the commands we do */
10157 err = dytc_cql_command(DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), &output);
10158 if (err)
10159 goto unlock;
10160 }
10161 /* Success - update current profile */
10162 dytc_current_profile = profile;
10163unlock:
10164 mutex_unlock(&dytc_mutex);
10165 return err;
10166}
10167
10168static void dytc_profile_refresh(void)
10169{
10170 enum platform_profile_option profile;
10171 int output, err;
10172 int perfmode;
10173
10174 mutex_lock(&dytc_mutex);
10175 err = dytc_cql_command(DYTC_CMD_GET, &output);
10176 mutex_unlock(&dytc_mutex);
10177 if (err)
10178 return;
10179
10180 perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
10181 convert_dytc_to_profile(perfmode, &profile);
10182 if (profile != dytc_current_profile) {
10183 dytc_current_profile = profile;
10184 platform_profile_notify();
10185 }
10186}
10187
10188static struct platform_profile_handler dytc_profile = {
10189 .profile_get = dytc_profile_get,
10190 .profile_set = dytc_profile_set,
10191};
10192
10193static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
10194{
10195 int err, output;
10196
10197 /* Setup supported modes */
10198 set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices);
10199 set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
10200 set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
10201
10202 dytc_profile_available = false;
10203 err = dytc_command(DYTC_CMD_QUERY, &output);
10204 /*
10205 * If support isn't available (ENODEV) then don't return an error
10206 * and don't create the sysfs group
10207 */
10208 if (err == -ENODEV)
10209 return 0;
10210 /* For all other errors we can flag the failure */
10211 if (err)
10212 return err;
10213
10214 /* Check DYTC is enabled and supports mode setting */
10215 if (output & BIT(DYTC_QUERY_ENABLE_BIT)) {
10216 /* Only DYTC v5.0 and later has this feature. */
10217 int dytc_version;
10218
10219 dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
10220 if (dytc_version >= 5) {
10221 dbg_printk(TPACPI_DBG_INIT,
10222 "DYTC version %d: thermal mode available\n", dytc_version);
10223 /* Create platform_profile structure and register */
10224 err = platform_profile_register(&dytc_profile);
10225 /*
10226 * If for some reason platform_profiles aren't enabled
10227 * don't quit terminally.
10228 */
10229 if (err)
10230 return 0;
10231
10232 dytc_profile_available = true;
10233 /* Ensure initial values are correct */
10234 dytc_profile_refresh();
10235 }
10236 }
10237 return 0;
10238}
10239
10240static void dytc_profile_exit(void)
10241{
10242 if (dytc_profile_available) {
10243 dytc_profile_available = false;
10244 platform_profile_remove();
10245 }
10246}
10247
10248static struct ibm_struct dytc_profile_driver_data = {
10249 .name = "dytc-profile",
10250 .exit = dytc_profile_exit,
10251};
10252
10253/*************************************************************************
10254 * Keyboard language interface
10255 */
10256
10257struct keyboard_lang_data {
10258 const char *lang_str;
10259 int lang_code;
10260};
10261
10262static const struct keyboard_lang_data keyboard_lang_data[] = {
10263 {"be", 0x080c},
10264 {"cz", 0x0405},
10265 {"da", 0x0406},
10266 {"de", 0x0c07},
10267 {"en", 0x0000},
10268 {"es", 0x2c0a},
10269 {"et", 0x0425},
10270 {"fr", 0x040c},
10271 {"fr-ch", 0x100c},
10272 {"hu", 0x040e},
10273 {"it", 0x0410},
10274 {"jp", 0x0411},
10275 {"nl", 0x0413},
10276 {"nn", 0x0414},
10277 {"pl", 0x0415},
10278 {"pt", 0x0816},
10279 {"sl", 0x041b},
10280 {"sv", 0x081d},
10281 {"tr", 0x041f},
10282};
10283
10284static int set_keyboard_lang_command(int command)
10285{
10286 acpi_handle sskl_handle;
10287 int output;
10288
10289 if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "SSKL", &sskl_handle))) {
10290 /* Platform doesn't support SSKL */
10291 return -ENODEV;
10292 }
10293
10294 if (!acpi_evalf(sskl_handle, &output, NULL, "dd", command))
10295 return -EIO;
10296
10297 return 0;
10298}
10299
10300static int get_keyboard_lang(int *output)
10301{
10302 acpi_handle gskl_handle;
10303 int kbd_lang;
10304
10305 if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GSKL", &gskl_handle))) {
10306 /* Platform doesn't support GSKL */
10307 return -ENODEV;
10308 }
10309
10310 if (!acpi_evalf(gskl_handle, &kbd_lang, NULL, "dd", 0x02000000))
10311 return -EIO;
10312
10313 /*
10314 * METHOD_ERR gets returned on devices where there are no special (e.g. '=',
10315 * '(' and ')') keys which use layout dependent key-press emulation.
10316 */
10317 if (kbd_lang & METHOD_ERR)
10318 return -ENODEV;
10319
10320 *output = kbd_lang;
10321
10322 return 0;
10323}
10324
10325/* sysfs keyboard language entry */
10326static ssize_t keyboard_lang_show(struct device *dev,
10327 struct device_attribute *attr,
10328 char *buf)
10329{
10330 int output, err, i, len = 0;
10331
10332 err = get_keyboard_lang(&output);
10333 if (err)
10334 return err;
10335
10336 for (i = 0; i < ARRAY_SIZE(keyboard_lang_data); i++) {
10337 if (i)
10338 len += sysfs_emit_at(buf, len, "%s", " ");
10339
10340 if (output == keyboard_lang_data[i].lang_code) {
10341 len += sysfs_emit_at(buf, len, "[%s]", keyboard_lang_data[i].lang_str);
10342 } else {
10343 len += sysfs_emit_at(buf, len, "%s", keyboard_lang_data[i].lang_str);
10344 }
10345 }
10346 len += sysfs_emit_at(buf, len, "\n");
10347
10348 return len;
10349}
10350
10351static ssize_t keyboard_lang_store(struct device *dev,
10352 struct device_attribute *attr,
10353 const char *buf, size_t count)
10354{
10355 int err, i;
10356 bool lang_found = false;
10357 int lang_code = 0;
10358
10359 for (i = 0; i < ARRAY_SIZE(keyboard_lang_data); i++) {
10360 if (sysfs_streq(buf, keyboard_lang_data[i].lang_str)) {
10361 lang_code = keyboard_lang_data[i].lang_code;
10362 lang_found = true;
10363 break;
10364 }
10365 }
10366
10367 if (lang_found) {
10368 lang_code = lang_code | 1 << 24;
10369
10370 /* Set language code */
10371 err = set_keyboard_lang_command(lang_code);
10372 if (err)
10373 return err;
10374 } else {
10375 dev_err(&tpacpi_pdev->dev, "Unknown Keyboard language. Ignoring\n");
10376 return -EINVAL;
10377 }
10378
10379 tpacpi_disclose_usertask(attr->attr.name,
10380 "keyboard language is set to %s\n", buf);
10381
10382 sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "keyboard_lang");
10383
10384 return count;
10385}
10386static DEVICE_ATTR_RW(keyboard_lang);
10387
10388static struct attribute *kbdlang_attributes[] = {
10389 &dev_attr_keyboard_lang.attr,
10390 NULL
10391};
10392
10393static const struct attribute_group kbdlang_attr_group = {
10394 .attrs = kbdlang_attributes,
10395};
10396
10397static int tpacpi_kbdlang_init(struct ibm_init_struct *iibm)
10398{
10399 int err, output;
10400
10401 err = get_keyboard_lang(&output);
10402 /*
10403 * If support isn't available (ENODEV) then don't return an error
10404 * just don't create the sysfs group.
10405 */
10406 if (err == -ENODEV)
10407 return 0;
10408
10409 if (err)
10410 return err;
10411
10412 /* Platform supports this feature - create the sysfs file */
10413 return sysfs_create_group(&tpacpi_pdev->dev.kobj, &kbdlang_attr_group);
10414}
10415
10416static void kbdlang_exit(void)
10417{
10418 sysfs_remove_group(&tpacpi_pdev->dev.kobj, &kbdlang_attr_group);
10419}
10420
10421static struct ibm_struct kbdlang_driver_data = {
10422 .name = "kbdlang",
10423 .exit = kbdlang_exit,
10424};
10425
9986/****************************************************************************10426/****************************************************************************
9987 ****************************************************************************10427 ****************************************************************************
9988 *10428 *
@@ -10031,8 +10471,12 @@ static void tpacpi_driver_event(const unsigned int hkey_event) · 42 unmodified lines
10031 mutex_unlock(&kbdlight_mutex);10471 mutex_unlock(&kbdlight_mutex);
10032 }10472 }
10033 10473
10034 if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED)10474 if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED) {
10035 lapsensor_refresh();10475 lapsensor_refresh();
10476 /* If we are already accessing DYTC then skip dytc update */
10477 if (!atomic_add_unless(&dytc_ignore_event, -1, 0))
10478 dytc_profile_refresh();
10479 }
10036}10480}
10037 10481
10038static void hotkey_driver_event(const unsigned int scancode)10482static void hotkey_driver_event(const unsigned int scancode)
@@ -10475,6 +10919,14 @@ static struct ibm_init_struct ibms_init[] __initdata = { · 436 unmodified lines
10475 .init = tpacpi_proxsensor_init,10919 .init = tpacpi_proxsensor_init,
10476 .data = &proxsensor_driver_data,10920 .data = &proxsensor_driver_data,
10477 },10921 },
10922 {
10923 .init = tpacpi_dytc_profile_init,
10924 .data = &dytc_profile_driver_data,
10925 },
10926 {
10927 .init = tpacpi_kbdlang_init,
10928 .data = &kbdlang_driver_data,
10929 },
10478};10930};
10479 10931
10480static int __init set_ibm_param(const char *val, const struct kernel_param *kp)10932static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
drivers/platform/x86/touchscreen_dmi.c+27−0
@@ -382,6 +382,23 @@ static const struct ts_dmi_data jumper_ezpad_6_m4_data = { · 381 unmodified lines
382 .properties = jumper_ezpad_6_m4_props,382 .properties = jumper_ezpad_6_m4_props,
383};383};
384 384
385static const struct property_entry jumper_ezpad_7_props[] = {
386 PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
387 PROPERTY_ENTRY_U32("touchscreen-min-y", 10),
388 PROPERTY_ENTRY_U32("touchscreen-size-x", 2044),
389 PROPERTY_ENTRY_U32("touchscreen-size-y", 1526),
390 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
391 PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-jumper-ezpad-7.fw"),
392 PROPERTY_ENTRY_U32("silead,max-fingers", 10),
393 PROPERTY_ENTRY_BOOL("silead,stuck-controller-bug"),
394 { }
395};
396
397static const struct ts_dmi_data jumper_ezpad_7_data = {
398 .acpi_name = "MSSL1680:00",
399 .properties = jumper_ezpad_7_props,
400};
401
385static const struct property_entry jumper_ezpad_mini3_props[] = {402static const struct property_entry jumper_ezpad_mini3_props[] = {
386 PROPERTY_ENTRY_U32("touchscreen-min-x", 23),403 PROPERTY_ENTRY_U32("touchscreen-min-x", 23),
387 PROPERTY_ENTRY_U32("touchscreen-min-y", 16),404 PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
@@ -1034,6 +1051,16 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 646 unmodified lines
1034 DMI_MATCH(DMI_BIOS_VERSION, "Jumper8.S106x"),1051 DMI_MATCH(DMI_BIOS_VERSION, "Jumper8.S106x"),
1035 },1052 },
1036 },1053 },
1054 {
1055 /* Jumper EZpad 7 */
1056 .driver_data = (void *)&jumper_ezpad_7_data,
1057 .matches = {
1058 DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
1059 DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
1060 /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
1061 DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
1062 },
1063 },
1037 {1064 {
1038 /* Jumper EZpad mini3 */1065 /* Jumper EZpad mini3 */
1039 .driver_data = (void *)&jumper_ezpad_mini3_data,1066 .driver_data = (void *)&jumper_ezpad_mini3_data,
drivers/rtc/Kconfig+0−12
@@ -973,18 +973,6 @@ config RTC_DRV_ALPHA · 972 unmodified lines
973 Direct support for the real-time clock found on every Alpha973 Direct support for the real-time clock found on every Alpha
974 system, specifically MC146818 compatibles. If in doubt, say Y.974 system, specifically MC146818 compatibles. If in doubt, say Y.
975 975
976config RTC_DRV_VRTC
977 tristate "Virtual RTC for Intel MID platforms"
978 depends on X86_INTEL_MID
979 default y if X86_INTEL_MID
980
981 help
982 Say "yes" here to get direct support for the real time clock
983 found on Moorestown platforms. The VRTC is a emulated RTC that
984 derives its clock source from a real RTC in the PMIC. The MC146818
985 style programming interface is mostly conserved, but any
986 updates are done via IPC calls to the system controller FW.
987
988config RTC_DRV_DS1216976config RTC_DRV_DS1216
989 tristate "Dallas DS1216"977 tristate "Dallas DS1216"
990 depends on SNI_RM978 depends on SNI_RM
drivers/rtc/Makefile+0−1
@@ -174,7 +174,6 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o · 173 unmodified lines
174obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o174obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
175obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o175obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
176obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o176obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
177obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
178obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o177obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
179obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o178obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o
180obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o179obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
drivers/rtc/rtc-mrst.c+0−521
@@ -1,521 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * rtc-mrst.c: Driver for Moorestown virtual RTC
4 *
5 * (C) Copyright 2009 Intel Corporation
6 * Author: Jacob Pan (jacob.jun.pan@intel.com)
7 * Feng Tang (feng.tang@intel.com)
8 *
9 * Note:
10 * VRTC is emulated by system controller firmware, the real HW
11 * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
12 * in a memory mapped IO space that is visible to the host IA
13 * processor.
14 *
15 * This driver is based upon drivers/rtc/rtc-cmos.c
16 */
17
18/*
19 * Note:
20 * * vRTC only supports binary mode and 24H mode
21 * * vRTC only support PIE and AIE, no UIE, and its PIE only happens
22 * at 23:59:59pm everyday, no support for adjustable frequency
23 * * Alarm function is also limited to hr/min/sec.
24 */
25
26#include <linux/mod_devicetable.h>
27#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/spinlock.h>
30#include <linux/kernel.h>
31#include <linux/mc146818rtc.h>
32#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/sfi.h>
35
36#include <asm/intel_scu_ipc.h>
37#include <asm/intel-mid.h>
38#include <asm/intel_mid_vrtc.h>
39
40struct mrst_rtc {
41 struct rtc_device *rtc;
42 struct device *dev;
43 int irq;
44
45 u8 enabled_wake;
46 u8 suspend_ctrl;
47};
48
49static const char driver_name[] = "rtc_mrst";
50
51#define RTC_IRQMASK (RTC_PF | RTC_AF)
52
53static inline int is_intr(u8 rtc_intr)
54{
55 if (!(rtc_intr & RTC_IRQF))
56 return 0;
57 return rtc_intr & RTC_IRQMASK;
58}
59
60static inline unsigned char vrtc_is_updating(void)
61{
62 unsigned char uip;
63 unsigned long flags;
64
65 spin_lock_irqsave(&rtc_lock, flags);
66 uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
67 spin_unlock_irqrestore(&rtc_lock, flags);
68 return uip;
69}
70
71/*
72 * rtc_time's year contains the increment over 1900, but vRTC's YEAR
73 * register can't be programmed to value larger than 0x64, so vRTC
74 * driver chose to use 1972 (1970 is UNIX time start point) as the base,
75 * and does the translation at read/write time.
76 *
77 * Why not just use 1970 as the offset? it's because using 1972 will
78 * make it consistent in leap year setting for both vrtc and low-level
79 * physical rtc devices. Then why not use 1960 as the offset? If we use
80 * 1960, for a device's first use, its YEAR register is 0 and the system
81 * year will be parsed as 1960 which is not a valid UNIX time and will
82 * cause many applications to fail mysteriously.
83 */
84static int mrst_read_time(struct device *dev, struct rtc_time *time)
85{
86 unsigned long flags;
87
88 if (vrtc_is_updating())
89 msleep(20);
90
91 spin_lock_irqsave(&rtc_lock, flags);
92 time->tm_sec = vrtc_cmos_read(RTC_SECONDS);
93 time->tm_min = vrtc_cmos_read(RTC_MINUTES);
94 time->tm_hour = vrtc_cmos_read(RTC_HOURS);
95 time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
96 time->tm_mon = vrtc_cmos_read(RTC_MONTH);
97 time->tm_year = vrtc_cmos_read(RTC_YEAR);
98 spin_unlock_irqrestore(&rtc_lock, flags);
99
100 /* Adjust for the 1972/1900 */
101 time->tm_year += 72;
102 time->tm_mon--;
103 return 0;
104}
105
106static int mrst_set_time(struct device *dev, struct rtc_time *time)
107{
108 int ret;
109 unsigned long flags;
110 unsigned char mon, day, hrs, min, sec;
111 unsigned int yrs;
112
113 yrs = time->tm_year;
114 mon = time->tm_mon + 1; /* tm_mon starts at zero */
115 day = time->tm_mday;
116 hrs = time->tm_hour;
117 min = time->tm_min;
118 sec = time->tm_sec;
119
120 if (yrs < 72 || yrs > 172)
121 return -EINVAL;
122 yrs -= 72;
123
124 spin_lock_irqsave(&rtc_lock, flags);
125
126 vrtc_cmos_write(yrs, RTC_YEAR);
127 vrtc_cmos_write(mon, RTC_MONTH);
128 vrtc_cmos_write(day, RTC_DAY_OF_MONTH);
129 vrtc_cmos_write(hrs, RTC_HOURS);
130 vrtc_cmos_write(min, RTC_MINUTES);
131 vrtc_cmos_write(sec, RTC_SECONDS);
132
133 spin_unlock_irqrestore(&rtc_lock, flags);
134
135 ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME);
136 return ret;
137}
138
139static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
140{
141 struct mrst_rtc *mrst = dev_get_drvdata(dev);
142 unsigned char rtc_control;
143
144 if (mrst->irq <= 0)
145 return -EIO;
146
147 /* vRTC only supports binary mode */
148 spin_lock_irq(&rtc_lock);
149 t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
150 t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM);
151 t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM);
152
153 rtc_control = vrtc_cmos_read(RTC_CONTROL);
154 spin_unlock_irq(&rtc_lock);
155
156 t->enabled = !!(rtc_control & RTC_AIE);
157 t->pending = 0;
158
159 return 0;
160}
161
162static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control)
163{
164 unsigned char rtc_intr;
165
166 /*
167 * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
168 * allegedly some older rtcs need that to handle irqs properly
169 */
170 rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS);
171 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
172 if (is_intr(rtc_intr))
173 rtc_update_irq(mrst->rtc, 1, rtc_intr);
174}
175
176static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask)
177{
178 unsigned char rtc_control;
179
180 /*
181 * Flush any pending IRQ status, notably for update irqs,
182 * before we enable new IRQs
183 */
184 rtc_control = vrtc_cmos_read(RTC_CONTROL);
185 mrst_checkintr(mrst, rtc_control);
186
187 rtc_control |= mask;
188 vrtc_cmos_write(rtc_control, RTC_CONTROL);
189
190 mrst_checkintr(mrst, rtc_control);
191}
192
193static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask)
194{
195 unsigned char rtc_control;
196
197 rtc_control = vrtc_cmos_read(RTC_CONTROL);
198 rtc_control &= ~mask;
199 vrtc_cmos_write(rtc_control, RTC_CONTROL);
200 mrst_checkintr(mrst, rtc_control);
201}
202
203static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)
204{
205 struct mrst_rtc *mrst = dev_get_drvdata(dev);
206 unsigned char hrs, min, sec;
207 int ret = 0;
208
209 if (!mrst->irq)
210 return -EIO;
211
212 hrs = t->time.tm_hour;
213 min = t->time.tm_min;
214 sec = t->time.tm_sec;
215
216 spin_lock_irq(&rtc_lock);
217 /* Next rtc irq must not be from previous alarm setting */
218 mrst_irq_disable(mrst, RTC_AIE);
219
220 /* Update alarm */
221 vrtc_cmos_write(hrs, RTC_HOURS_ALARM);
222 vrtc_cmos_write(min, RTC_MINUTES_ALARM);
223 vrtc_cmos_write(sec, RTC_SECONDS_ALARM);
224
225 spin_unlock_irq(&rtc_lock);
226
227 ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM);
228 if (ret)
229 return ret;
230
231 spin_lock_irq(&rtc_lock);
232 if (t->enabled)
233 mrst_irq_enable(mrst, RTC_AIE);
234
235 spin_unlock_irq(&rtc_lock);
236
237 return 0;
238}
239
240/* Currently, the vRTC doesn't support UIE ON/OFF */
241static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
242{
243 struct mrst_rtc *mrst = dev_get_drvdata(dev);
244 unsigned long flags;
245
246 spin_lock_irqsave(&rtc_lock, flags);
247 if (enabled)
248 mrst_irq_enable(mrst, RTC_AIE);
249 else
250 mrst_irq_disable(mrst, RTC_AIE);
251 spin_unlock_irqrestore(&rtc_lock, flags);
252 return 0;
253}
254
255
256#if IS_ENABLED(CONFIG_RTC_INTF_PROC)
257
258static int mrst_procfs(struct device *dev, struct seq_file *seq)
259{
260 unsigned char rtc_control;
261
262 spin_lock_irq(&rtc_lock);
263 rtc_control = vrtc_cmos_read(RTC_CONTROL);
264 spin_unlock_irq(&rtc_lock);
265
266 seq_printf(seq,
267 "periodic_IRQ\t: %s\n"
268 "alarm\t\t: %s\n"
269 "BCD\t\t: no\n"
270 "periodic_freq\t: daily (not adjustable)\n",
271 (rtc_control & RTC_PIE) ? "on" : "off",
272 (rtc_control & RTC_AIE) ? "on" : "off");
273
274 return 0;
275}
276
277#else
278#define mrst_procfs NULL
279#endif
280
281static const struct rtc_class_ops mrst_rtc_ops = {
282 .read_time = mrst_read_time,
283 .set_time = mrst_set_time,
284 .read_alarm = mrst_read_alarm,
285 .set_alarm = mrst_set_alarm,
286 .proc = mrst_procfs,
287 .alarm_irq_enable = mrst_rtc_alarm_irq_enable,
288};
289
290static struct mrst_rtc mrst_rtc;
291
292/*
293 * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in
294 * Reg B, so no need for this driver to clear it
295 */
296static irqreturn_t mrst_rtc_irq(int irq, void *p)
297{
298 u8 irqstat;
299
300 spin_lock(&rtc_lock);
301 /* This read will clear all IRQ flags inside Reg C */
302 irqstat = vrtc_cmos_read(RTC_INTR_FLAGS);
303 spin_unlock(&rtc_lock);
304
305 irqstat &= RTC_IRQMASK | RTC_IRQF;
306 if (is_intr(irqstat)) {
307 rtc_update_irq(p, 1, irqstat);
308 return IRQ_HANDLED;
309 }
310 return IRQ_NONE;
311}
312
313static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
314 int rtc_irq)
315{
316 int retval = 0;
317 unsigned char rtc_control;
318
319 /* There can be only one ... */
320 if (mrst_rtc.dev)
321 return -EBUSY;
322
323 if (!iomem)
324 return -ENODEV;
325
326 iomem = devm_request_mem_region(dev, iomem->start, resource_size(iomem),
327 driver_name);
328 if (!iomem) {
329 dev_dbg(dev, "i/o mem already in use.\n");
330 return -EBUSY;
331 }
332
333 mrst_rtc.irq = rtc_irq;
334 mrst_rtc.dev = dev;
335 dev_set_drvdata(dev, &mrst_rtc);
336
337 mrst_rtc.rtc = devm_rtc_allocate_device(dev);
338 if (IS_ERR(mrst_rtc.rtc))
339 return PTR_ERR(mrst_rtc.rtc);
340
341 mrst_rtc.rtc->ops = &mrst_rtc_ops;
342
343 rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
344
345 spin_lock_irq(&rtc_lock);
346 mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE);
347 rtc_control = vrtc_cmos_read(RTC_CONTROL);
348 spin_unlock_irq(&rtc_lock);
349
350 if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))
351 dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n");
352
353 if (rtc_irq) {
354 retval = devm_request_irq(dev, rtc_irq, mrst_rtc_irq,
355 0, dev_name(&mrst_rtc.rtc->dev),
356 mrst_rtc.rtc);
357 if (retval < 0) {
358 dev_dbg(dev, "IRQ %d is already in use, err %d\n",
359 rtc_irq, retval);
360 goto cleanup0;
361 }
362 }
363
364 retval = devm_rtc_register_device(mrst_rtc.rtc);
365 if (retval)
366 goto cleanup0;
367
368 dev_dbg(dev, "initialised\n");
369 return 0;
370
371cleanup0:
372 mrst_rtc.dev = NULL;
373 dev_err(dev, "rtc-mrst: unable to initialise\n");
374 return retval;
375}
376
377static void rtc_mrst_do_shutdown(void)
378{
379 spin_lock_irq(&rtc_lock);
380 mrst_irq_disable(&mrst_rtc, RTC_IRQMASK);
381 spin_unlock_irq(&rtc_lock);
382}
383
384static void rtc_mrst_do_remove(struct device *dev)
385{
386 struct mrst_rtc *mrst = dev_get_drvdata(dev);
387
388 rtc_mrst_do_shutdown();
389
390 mrst->rtc = NULL;
391 mrst->dev = NULL;
392}
393
394#ifdef CONFIG_PM_SLEEP
395static int mrst_suspend(struct device *dev)
396{
397 struct mrst_rtc *mrst = dev_get_drvdata(dev);
398 unsigned char tmp;
399
400 /* Only the alarm might be a wakeup event source */
401 spin_lock_irq(&rtc_lock);
402 mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL);
403 if (tmp & (RTC_PIE | RTC_AIE)) {
404 unsigned char mask;
405
406 if (device_may_wakeup(dev))
407 mask = RTC_IRQMASK & ~RTC_AIE;
408 else
409 mask = RTC_IRQMASK;
410 tmp &= ~mask;
411 vrtc_cmos_write(tmp, RTC_CONTROL);
412
413 mrst_checkintr(mrst, tmp);
414 }
415 spin_unlock_irq(&rtc_lock);
416
417 if (tmp & RTC_AIE) {
418 mrst->enabled_wake = 1;
419 enable_irq_wake(mrst->irq);
420 }
421
422 dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n",
423 (tmp & RTC_AIE) ? ", alarm may wake" : "",
424 tmp);
425
426 return 0;
427}
428
429/*
430 * We want RTC alarms to wake us from the deep power saving state
431 */
432static inline int mrst_poweroff(struct device *dev)
433{
434 return mrst_suspend(dev);
435}
436
437static int mrst_resume(struct device *dev)
438{
439 struct mrst_rtc *mrst = dev_get_drvdata(dev);
440 unsigned char tmp = mrst->suspend_ctrl;
441
442 /* Re-enable any irqs previously active */
443 if (tmp & RTC_IRQMASK) {
444 unsigned char mask;
445
446 if (mrst->enabled_wake) {
447 disable_irq_wake(mrst->irq);
448 mrst->enabled_wake = 0;
449 }
450
451 spin_lock_irq(&rtc_lock);
452 do {
453 vrtc_cmos_write(tmp, RTC_CONTROL);
454
455 mask = vrtc_cmos_read(RTC_INTR_FLAGS);
456 mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
457 if (!is_intr(mask))
458 break;
459
460 rtc_update_irq(mrst->rtc, 1, mask);
461 tmp &= ~RTC_AIE;
462 } while (mask & RTC_AIE);
463 spin_unlock_irq(&rtc_lock);
464 }
465
466 dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp);
467
468 return 0;
469}
470
471static SIMPLE_DEV_PM_OPS(mrst_pm_ops, mrst_suspend, mrst_resume);
472#define MRST_PM_OPS (&mrst_pm_ops)
473
474#else
475#define MRST_PM_OPS NULL
476
477static inline int mrst_poweroff(struct device *dev)
478{
479 return -ENOSYS;
480}
481
482#endif
483
484static int vrtc_mrst_platform_probe(struct platform_device *pdev)
485{
486 return vrtc_mrst_do_probe(&pdev->dev,
487 platform_get_resource(pdev, IORESOURCE_MEM, 0),
488 platform_get_irq(pdev, 0));
489}
490
491static int vrtc_mrst_platform_remove(struct platform_device *pdev)
492{
493 rtc_mrst_do_remove(&pdev->dev);
494 return 0;
495}
496
497static void vrtc_mrst_platform_shutdown(struct platform_device *pdev)
498{
499 if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev))
500 return;
501
502 rtc_mrst_do_shutdown();
503}
504
505MODULE_ALIAS("platform:vrtc_mrst");
506
507static struct platform_driver vrtc_mrst_platform_driver = {
508 .probe = vrtc_mrst_platform_probe,
509 .remove = vrtc_mrst_platform_remove,
510 .shutdown = vrtc_mrst_platform_shutdown,
511 .driver = {
512 .name = driver_name,
513 .pm = MRST_PM_OPS,
514 }
515};
516
517module_platform_driver(vrtc_mrst_platform_driver);
518
519MODULE_AUTHOR("Jacob Pan; Feng Tang");
520MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
521MODULE_LICENSE("GPL");
drivers/watchdog/Kconfig+0−9
@@ -1219,15 +1219,6 @@ config IE6XX_WDT · 1218 unmodified lines
1219 To compile this driver as a module, choose M here: the1219 To compile this driver as a module, choose M here: the
1220 module will be called ie6xx_wdt.1220 module will be called ie6xx_wdt.
1221 1221
1222config INTEL_SCU_WATCHDOG
1223 bool "Intel SCU Watchdog for Mobile Platforms"
1224 depends on X86_INTEL_MID
1225 help
1226 Hardware driver for the watchdog time built into the Intel SCU
1227 for Intel Mobile Platforms.
1228
1229 To compile this driver as a module, choose M here.
1230
1231config INTEL_MID_WATCHDOG1222config INTEL_MID_WATCHDOG
1232 tristate "Intel MID Watchdog Timer"1223 tristate "Intel MID Watchdog Timer"
1233 depends on X86_INTEL_MID1224 depends on X86_INTEL_MID
drivers/watchdog/Makefile+0−1
@@ -140,7 +140,6 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o · 139 unmodified lines
140obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o140obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
141obj-$(CONFIG_MACHZ_WDT) += machzwd.o141obj-$(CONFIG_MACHZ_WDT) += machzwd.o
142obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o142obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
143obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
144obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o143obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o
145obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o144obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o
146obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o145obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o
drivers/watchdog/intel-mid_wdt.c+4−4
@@ -154,6 +154,10 @@ static int mid_wdt_probe(struct platform_device *pdev) · 153 unmodified lines
154 watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);154 watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);
155 watchdog_set_drvdata(wdt_dev, mid);155 watchdog_set_drvdata(wdt_dev, mid);
156 156
157 mid->scu = devm_intel_scu_ipc_dev_get(dev);
158 if (!mid->scu)
159 return -EPROBE_DEFER;
160
157 ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,161 ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,
158 IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",162 IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",
159 wdt_dev);163 wdt_dev);
@@ -162,10 +166,6 @@ static int mid_wdt_probe(struct platform_device *pdev) · 2 unmodified lines
162 return ret;166 return ret;
163 }167 }
164 168
165 mid->scu = devm_intel_scu_ipc_dev_get(dev);
166 if (!mid->scu)
167 return -EPROBE_DEFER;
168
169 /*169 /*
170 * The firmware followed by U-Boot leaves the watchdog running170 * The firmware followed by U-Boot leaves the watchdog running
171 * with the default threshold which may vary. When we get here171 * with the default threshold which may vary. When we get here
drivers/watchdog/intel_scu_watchdog.c+0−533
@@ -1,533 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
4 * for Intel part #(s):
5 * - AF82MP20 PCH
6 *
7 * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12#include <linux/compiler.h>
13#include <linux/kernel.h>
14#include <linux/moduleparam.h>
15#include <linux/types.h>
16#include <linux/miscdevice.h>
17#include <linux/watchdog.h>
18#include <linux/fs.h>
19#include <linux/notifier.h>
20#include <linux/reboot.h>
21#include <linux/init.h>
22#include <linux/jiffies.h>
23#include <linux/uaccess.h>
24#include <linux/slab.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/delay.h>
28#include <linux/sched.h>
29#include <linux/signal.h>
30#include <linux/sfi.h>
31#include <asm/irq.h>
32#include <linux/atomic.h>
33#include <asm/intel_scu_ipc.h>
34#include <asm/apb_timer.h>
35#include <asm/intel-mid.h>
36
37#include "intel_scu_watchdog.h"
38
39/* Bounds number of times we will retry loading time count */
40/* This retry is a work around for a silicon bug. */
41#define MAX_RETRY 16
42
43#define IPC_SET_WATCHDOG_TIMER 0xF8
44
45static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN;
46module_param(timer_margin, int, 0);
47MODULE_PARM_DESC(timer_margin,
48 "Watchdog timer margin"
49 "Time between interrupt and resetting the system"
50 "The range is from 1 to 160"
51 "This is the time for all keep alives to arrive");
52
53static int timer_set = DEFAULT_TIME;
54module_param(timer_set, int, 0);
55MODULE_PARM_DESC(timer_set,
56 "Default Watchdog timer setting"
57 "Complete cycle time"
58 "The range is from 1 to 170"
59 "This is the time for all keep alives to arrive");
60
61/* After watchdog device is closed, check force_boot. If:
62 * force_boot == 0, then force boot on next watchdog interrupt after close,
63 * force_boot == 1, then force boot immediately when device is closed.
64 */
65static int force_boot;
66module_param(force_boot, int, 0);
67MODULE_PARM_DESC(force_boot,
68 "A value of 1 means that the driver will reboot"
69 "the system immediately if the /dev/watchdog device is closed"
70 "A value of 0 means that when /dev/watchdog device is closed"
71 "the watchdog timer will be refreshed for one more interval"
72 "of length: timer_set. At the end of this interval, the"
73 "watchdog timer will reset the system."
74 );
75
76/* there is only one device in the system now; this can be made into
77 * an array in the future if we have more than one device */
78
79static struct intel_scu_watchdog_dev watchdog_device;
80
81/* Forces restart, if force_reboot is set */
82static void watchdog_fire(void)
83{
84 if (force_boot) {
85 pr_crit("Initiating system reboot\n");
86 emergency_restart();
87 pr_crit("Reboot didn't ?????\n");
88 }
89
90 else {
91 pr_crit("Immediate Reboot Disabled\n");
92 pr_crit("System will reset when watchdog timer times out!\n");
93 }
94}
95
96static int check_timer_margin(int new_margin)
97{
98 if ((new_margin < MIN_TIME_CYCLE) ||
99 (new_margin > MAX_TIME - timer_set)) {
100 pr_debug("value of new_margin %d is out of the range %d to %d\n",
101 new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
102 return -EINVAL;
103 }
104 return 0;
105}
106
107/*
108 * IPC operations
109 */
110static int watchdog_set_ipc(int soft_threshold, int threshold)
111{
112 u32 *ipc_wbuf;
113 u8 cbuf[16] = { '\0' };
114 int ipc_ret = 0;
115
116 ipc_wbuf = (u32 *)&cbuf;
117 ipc_wbuf[0] = soft_threshold;
118 ipc_wbuf[1] = threshold;
119
120 ipc_ret = intel_scu_ipc_command(
121 IPC_SET_WATCHDOG_TIMER,
122 0,
123 ipc_wbuf,
124 2,
125 NULL,
126 0);
127
128 if (ipc_ret != 0)
129 pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);
130
131 return ipc_ret;
132};
133
134/*
135 * Intel_SCU operations
136 */
137
138/* timer interrupt handler */
139static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
140{
141 int int_status;
142 int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
143
144 pr_debug("irq, int_status: %x\n", int_status);
145
146 if (int_status != 0)
147 return IRQ_NONE;
148
149 /* has the timer been started? If not, then this is spurious */
150 if (watchdog_device.timer_started == 0) {
151 pr_debug("spurious interrupt received\n");
152 return IRQ_HANDLED;
153 }
154
155 /* temporarily disable the timer */
156 iowrite32(0x00000002, watchdog_device.timer_control_addr);
157
158 /* set the timer to the threshold */
159 iowrite32(watchdog_device.threshold,
160 watchdog_device.timer_load_count_addr);
161
162 /* allow the timer to run */
163 iowrite32(0x00000003, watchdog_device.timer_control_addr);
164
165 return IRQ_HANDLED;
166}
167
168static int intel_scu_keepalive(void)
169{
170
171 /* read eoi register - clears interrupt */
172 ioread32(watchdog_device.timer_clear_interrupt_addr);
173
174 /* temporarily disable the timer */
175 iowrite32(0x00000002, watchdog_device.timer_control_addr);
176
177 /* set the timer to the soft_threshold */
178 iowrite32(watchdog_device.soft_threshold,
179 watchdog_device.timer_load_count_addr);
180
181 /* allow the timer to run */
182 iowrite32(0x00000003, watchdog_device.timer_control_addr);
183
184 return 0;
185}
186
187static int intel_scu_stop(void)
188{
189 iowrite32(0, watchdog_device.timer_control_addr);
190 return 0;
191}
192
193static int intel_scu_set_heartbeat(u32 t)
194{
195 int ipc_ret;
196 int retry_count;
197 u32 soft_value;
198 u32 hw_value;
199
200 watchdog_device.timer_set = t;
201 watchdog_device.threshold =
202 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
203 watchdog_device.soft_threshold =
204 (watchdog_device.timer_set - timer_margin)
205 * watchdog_device.timer_tbl_ptr->freq_hz;
206
207 pr_debug("set_heartbeat: timer freq is %d\n",
208 watchdog_device.timer_tbl_ptr->freq_hz);
209 pr_debug("set_heartbeat: timer_set is %x (hex)\n",
210 watchdog_device.timer_set);
211 pr_debug("set_heartbeat: timer_margin is %x (hex)\n", timer_margin);
212 pr_debug("set_heartbeat: threshold is %x (hex)\n",
213 watchdog_device.threshold);
214 pr_debug("set_heartbeat: soft_threshold is %x (hex)\n",
215 watchdog_device.soft_threshold);
216
217 /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
218 /* watchdog timing come out right. */
219 watchdog_device.threshold =
220 watchdog_device.threshold / FREQ_ADJUSTMENT;
221 watchdog_device.soft_threshold =
222 watchdog_device.soft_threshold / FREQ_ADJUSTMENT;
223
224 /* temporarily disable the timer */
225 iowrite32(0x00000002, watchdog_device.timer_control_addr);
226
227 /* send the threshold and soft_threshold via IPC to the processor */
228 ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold,
229 watchdog_device.threshold);
230
231 if (ipc_ret != 0) {
232 /* Make sure the watchdog timer is stopped */
233 intel_scu_stop();
234 return ipc_ret;
235 }
236
237 /* Soft Threshold set loop. Early versions of silicon did */
238 /* not always set this count correctly. This loop checks */
239 /* the value and retries if it was not set correctly. */
240
241 retry_count = 0;
242 soft_value = watchdog_device.soft_threshold & 0xFFFF0000;
243 do {
244
245 /* Make sure timer is stopped */
246 intel_scu_stop();
247
248 if (MAX_RETRY < retry_count++) {
249 /* Unable to set timer value */
250 pr_err("Unable to set timer\n");
251 return -ENODEV;
252 }
253
254 /* set the timer to the soft threshold */
255 iowrite32(watchdog_device.soft_threshold,
256 watchdog_device.timer_load_count_addr);
257
258 /* read count value before starting timer */
259 ioread32(watchdog_device.timer_load_count_addr);
260
261 /* Start the timer */
262 iowrite32(0x00000003, watchdog_device.timer_control_addr);
263
264 /* read the value the time loaded into its count reg */
265 hw_value = ioread32(watchdog_device.timer_load_count_addr);
266 hw_value = hw_value & 0xFFFF0000;
267
268
269 } while (soft_value != hw_value);
270
271 watchdog_device.timer_started = 1;
272
273 return 0;
274}
275
276/*
277 * /dev/watchdog handling
278 */
279
280static int intel_scu_open(struct inode *inode, struct file *file)
281{
282
283 /* Set flag to indicate that watchdog device is open */
284 if (test_and_set_bit(0, &watchdog_device.driver_open))
285 return -EBUSY;
286
287 /* Check for reopen of driver. Reopens are not allowed */
288 if (watchdog_device.driver_closed)
289 return -EPERM;
290
291 return stream_open(inode, file);
292}
293
294static int intel_scu_release(struct inode *inode, struct file *file)
295{
296 /*
297 * This watchdog should not be closed, after the timer
298 * is started with the WDIPC_SETTIMEOUT ioctl
299 * If force_boot is set watchdog_fire() will cause an
300 * immediate reset. If force_boot is not set, the watchdog
301 * timer is refreshed for one more interval. At the end
302 * of that interval, the watchdog timer will reset the system.
303 */
304
305 if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
306 pr_debug("intel_scu_release, without open\n");
307 return -ENOTTY;
308 }
309
310 if (!watchdog_device.timer_started) {
311 /* Just close, since timer has not been started */
312 pr_debug("closed, without starting timer\n");
313 return 0;
314 }
315
316 pr_crit("Unexpected close of /dev/watchdog!\n");
317
318 /* Since the timer was started, prevent future reopens */
319 watchdog_device.driver_closed = 1;
320
321 /* Refresh the timer for one more interval */
322 intel_scu_keepalive();
323
324 /* Reboot system (if force_boot is set) */
325 watchdog_fire();
326
327 /* We should only reach this point if force_boot is not set */
328 return 0;
329}
330
331static ssize_t intel_scu_write(struct file *file,
332 char const *data,
333 size_t len,
334 loff_t *ppos)
335{
336
337 if (watchdog_device.timer_started)
338 /* Watchdog already started, keep it alive */
339 intel_scu_keepalive();
340 else
341 /* Start watchdog with timer value set by init */
342 intel_scu_set_heartbeat(watchdog_device.timer_set);
343
344 return len;
345}
346
347static long intel_scu_ioctl(struct file *file,
348 unsigned int cmd,
349 unsigned long arg)
350{
351 void __user *argp = (void __user *)arg;
352 u32 __user *p = argp;
353 u32 new_margin;
354
355
356 static const struct watchdog_info ident = {
357 .options = WDIOF_SETTIMEOUT
358 | WDIOF_KEEPALIVEPING,
359 .firmware_version = 0, /* @todo Get from SCU via
360 ipc_get_scu_fw_version()? */
361 .identity = "Intel_SCU IOH Watchdog" /* len < 32 */
362 };
363
364 switch (cmd) {
365 case WDIOC_GETSUPPORT:
366 return copy_to_user(argp,
367 &ident,
368 sizeof(ident)) ? -EFAULT : 0;
369 case WDIOC_GETSTATUS:
370 case WDIOC_GETBOOTSTATUS:
371 return put_user(0, p);
372 case WDIOC_KEEPALIVE:
373 intel_scu_keepalive();
374
375 return 0;
376 case WDIOC_SETTIMEOUT:
377 if (get_user(new_margin, p))
378 return -EFAULT;
379
380 if (check_timer_margin(new_margin))
381 return -EINVAL;
382
383 if (intel_scu_set_heartbeat(new_margin))
384 return -EINVAL;
385 return 0;
386 case WDIOC_GETTIMEOUT:
387 return put_user(watchdog_device.soft_threshold, p);
388
389 default:
390 return -ENOTTY;
391 }
392}
393
394/*
395 * Notifier for system down
396 */
397static int intel_scu_notify_sys(struct notifier_block *this,
398 unsigned long code,
399 void *another_unused)
400{
401 if (code == SYS_DOWN || code == SYS_HALT)
402 /* Turn off the watchdog timer. */
403 intel_scu_stop();
404 return NOTIFY_DONE;
405}
406
407/*
408 * Kernel Interfaces
409 */
410static const struct file_operations intel_scu_fops = {
411 .owner = THIS_MODULE,
412 .llseek = no_llseek,
413 .write = intel_scu_write,
414 .unlocked_ioctl = intel_scu_ioctl,
415 .compat_ioctl = compat_ptr_ioctl,
416 .open = intel_scu_open,
417 .release = intel_scu_release,
418};
419
420static int __init intel_scu_watchdog_init(void)
421{
422 int ret;
423 u32 __iomem *tmp_addr;
424
425 /*
426 * We don't really need to check this as the SFI timer get will fail
427 * but if we do so we can exit with a clearer reason and no noise.
428 *
429 * If it isn't an intel MID device then it doesn't have this watchdog
430 */
431 if (!intel_mid_identify_cpu())
432 return -ENODEV;
433
434 /* Check boot parameters to verify that their initial values */
435 /* are in range. */
436 /* Check value of timer_set boot parameter */
437 if ((timer_set < MIN_TIME_CYCLE) ||
438 (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
439 pr_err("value of timer_set %x (hex) is out of range from %x to %x (hex)\n",
440 timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
441 return -EINVAL;
442 }
443
444 /* Check value of timer_margin boot parameter */
445 if (check_timer_margin(timer_margin))
446 return -EINVAL;
447
448 watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
449
450 if (watchdog_device.timer_tbl_ptr == NULL) {
451 pr_debug("timer is not available\n");
452 return -ENODEV;
453 }
454 /* make sure the timer exists */
455 if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
456 pr_debug("timer %d does not have valid physical memory\n",
457 sfi_mtimer_num);
458 return -ENODEV;
459 }
460
461 if (watchdog_device.timer_tbl_ptr->irq == 0) {
462 pr_debug("timer %d invalid irq\n", sfi_mtimer_num);
463 return -ENODEV;
464 }
465
466 tmp_addr = ioremap(watchdog_device.timer_tbl_ptr->phys_addr,
467 20);
468
469 if (tmp_addr == NULL) {
470 pr_debug("timer unable to ioremap\n");
471 return -ENOMEM;
472 }
473
474 watchdog_device.timer_load_count_addr = tmp_addr++;
475 watchdog_device.timer_current_value_addr = tmp_addr++;
476 watchdog_device.timer_control_addr = tmp_addr++;
477 watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
478 watchdog_device.timer_interrupt_status_addr = tmp_addr++;
479
480 /* Set the default time values in device structure */
481
482 watchdog_device.timer_set = timer_set;
483 watchdog_device.threshold =
484 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
485 watchdog_device.soft_threshold =
486 (watchdog_device.timer_set - timer_margin)
487 * watchdog_device.timer_tbl_ptr->freq_hz;
488
489
490 watchdog_device.intel_scu_notifier.notifier_call =
491 intel_scu_notify_sys;
492
493 ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
494 if (ret) {
495 pr_err("cannot register notifier %d)\n", ret);
496 goto register_reboot_error;
497 }
498
499 watchdog_device.miscdev.minor = WATCHDOG_MINOR;
500 watchdog_device.miscdev.name = "watchdog";
501 watchdog_device.miscdev.fops = &intel_scu_fops;
502
503 ret = misc_register(&watchdog_device.miscdev);
504 if (ret) {
505 pr_err("cannot register miscdev %d err =%d\n",
506 WATCHDOG_MINOR, ret);
507 goto misc_register_error;
508 }
509
510 ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
511 watchdog_timer_interrupt,
512 IRQF_SHARED, "watchdog",
513 &watchdog_device.timer_load_count_addr);
514 if (ret) {
515 pr_err("error requesting irq %d\n", ret);
516 goto request_irq_error;
517 }
518 /* Make sure timer is disabled before returning */
519 intel_scu_stop();
520 return 0;
521
522/* error cleanup */
523
524request_irq_error:
525 misc_deregister(&watchdog_device.miscdev);
526misc_register_error:
527 unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
528register_reboot_error:
529 intel_scu_stop();
530 iounmap(watchdog_device.timer_load_count_addr);
531 return ret;
532}
533late_initcall(intel_scu_watchdog_init);
drivers/watchdog/intel_scu_watchdog.h+0−50
@@ -1,50 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
4 * for Intel part #(s):
5 * - AF82MP20 PCH
6 *
7 * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
8 */
9
10#ifndef __INTEL_SCU_WATCHDOG_H
11#define __INTEL_SCU_WATCHDOG_H
12
13#define WDT_VER "0.3"
14
15/* minimum time between interrupts */
16#define MIN_TIME_CYCLE 1
17
18/* Time from warning to reboot is 2 seconds */
19#define DEFAULT_SOFT_TO_HARD_MARGIN 2
20
21#define MAX_TIME 170
22
23#define DEFAULT_TIME 5
24
25#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE)
26
27/* Ajustment to clock tick frequency to make timing come out right */
28#define FREQ_ADJUSTMENT 8
29
30struct intel_scu_watchdog_dev {
31 ulong driver_open;
32 ulong driver_closed;
33 u32 timer_started;
34 u32 timer_set;
35 u32 threshold;
36 u32 soft_threshold;
37 u32 __iomem *timer_load_count_addr;
38 u32 __iomem *timer_current_value_addr;
39 u32 __iomem *timer_control_addr;
40 u32 __iomem *timer_clear_interrupt_addr;
41 u32 __iomem *timer_interrupt_status_addr;
42 struct sfi_timer_table_entry *timer_tbl_ptr;
43 struct notifier_block intel_scu_notifier;
44 struct miscdevice miscdev;
45};
46
47extern int sfi_mtimer_num;
48
49/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */
50#endif /* __INTEL_SCU_WATCHDOG_H */
include/linux/mod_devicetable.h+18−0
@@ -846,4 +846,22 @@ struct auxiliary_device_id { · 845 unmodified lines
846 kernel_ulong_t driver_data;846 kernel_ulong_t driver_data;
847};847};
848 848
849/* Surface System Aggregator Module */
850
851#define SSAM_MATCH_TARGET 0x1
852#define SSAM_MATCH_INSTANCE 0x2
853#define SSAM_MATCH_FUNCTION 0x4
854
855struct ssam_device_id {
856 __u8 match_flags;
857
858 __u8 domain;
859 __u8 category;
860 __u8 target;
861 __u8 instance;
862 __u8 function;
863
864 kernel_ulong_t driver_data;
865};
866
849#endif /* LINUX_MOD_DEVICETABLE_H */867#endif /* LINUX_MOD_DEVICETABLE_H */
include/linux/sony-laptop.h+1−1
@@ -31,7 +31,7 @@ · 30 unmodified lines
31#if IS_ENABLED(CONFIG_SONY_LAPTOP)31#if IS_ENABLED(CONFIG_SONY_LAPTOP)
32int sony_pic_camera_command(int command, u8 value);32int sony_pic_camera_command(int command, u8 value);
33#else33#else
34static inline int sony_pic_camera_command(int command, u8 value) { return 0; };34static inline int sony_pic_camera_command(int command, u8 value) { return 0; }
35#endif35#endif
36 36
37#endif /* __KERNEL__ */37#endif /* __KERNEL__ */
include/linux/surface_acpi_notify.h+39−0
@@ -0,0 +1,39 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Interface for Surface ACPI Notify (SAN) driver.
4 *
5 * Provides access to discrete GPU notifications sent from ACPI via the SAN
6 * driver, which are not handled by this driver directly.
7 *
8 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
9 */
10
11#ifndef _LINUX_SURFACE_ACPI_NOTIFY_H
12#define _LINUX_SURFACE_ACPI_NOTIFY_H
13
14#include <linux/notifier.h>
15#include <linux/types.h>
16
17/**
18 * struct san_dgpu_event - Discrete GPU ACPI event.
19 * @category: Category of the event.
20 * @target: Target ID of the event source.
21 * @command: Command ID of the event.
22 * @instance: Instance ID of the event source.
23 * @length: Length of the event's payload data (in bytes).
24 * @payload: Pointer to the event's payload data.
25 */
26struct san_dgpu_event {
27 u8 category;
28 u8 target;
29 u8 command;
30 u8 instance;
31 u16 length;
32 u8 *payload;
33};
34
35int san_client_link(struct device *client);
36int san_dgpu_notifier_register(struct notifier_block *nb);
37int san_dgpu_notifier_unregister(struct notifier_block *nb);
38
39#endif /* _LINUX_SURFACE_ACPI_NOTIFY_H */
include/linux/surface_aggregator/controller.h+824−0
@@ -0,0 +1,824 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Surface System Aggregator Module (SSAM) controller interface.
4 *
5 * Main communication interface for the SSAM EC. Provides a controller
6 * managing access and communication to and from the SSAM EC, as well as main
7 * communication structures and definitions.
8 *
9 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
10 */
11
12#ifndef _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
13#define _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
14
15#include <linux/completion.h>
16#include <linux/device.h>
17#include <linux/types.h>
18
19#include <linux/surface_aggregator/serial_hub.h>
20
21
22/* -- Main data types and definitions --------------------------------------- */
23
24/**
25 * enum ssam_event_flags - Flags for enabling/disabling SAM events
26 * @SSAM_EVENT_SEQUENCED: The event will be sent via a sequenced data frame.
27 */
28enum ssam_event_flags {
29 SSAM_EVENT_SEQUENCED = BIT(0),
30};
31
32/**
33 * struct ssam_event - SAM event sent from the EC to the host.
34 * @target_category: Target category of the event source. See &enum ssam_ssh_tc.
35 * @target_id: Target ID of the event source.
36 * @command_id: Command ID of the event.
37 * @instance_id: Instance ID of the event source.
38 * @length: Length of the event payload in bytes.
39 * @data: Event payload data.
40 */
41struct ssam_event {
42 u8 target_category;
43 u8 target_id;
44 u8 command_id;
45 u8 instance_id;
46 u16 length;
47 u8 data[];
48};
49
50/**
51 * enum ssam_request_flags - Flags for SAM requests.
52 *
53 * @SSAM_REQUEST_HAS_RESPONSE:
54 * Specifies that the request expects a response. If not set, the request
55 * will be directly completed after its underlying packet has been
56 * transmitted. If set, the request transport system waits for a response
57 * of the request.
58 *
59 * @SSAM_REQUEST_UNSEQUENCED:
60 * Specifies that the request should be transmitted via an unsequenced
61 * packet. If set, the request must not have a response, meaning that this
62 * flag and the %SSAM_REQUEST_HAS_RESPONSE flag are mutually exclusive.
63 */
64enum ssam_request_flags {
65 SSAM_REQUEST_HAS_RESPONSE = BIT(0),
66 SSAM_REQUEST_UNSEQUENCED = BIT(1),
67};
68
69/**
70 * struct ssam_request - SAM request description.
71 * @target_category: Category of the request's target. See &enum ssam_ssh_tc.
72 * @target_id: ID of the request's target.
73 * @command_id: Command ID of the request.
74 * @instance_id: Instance ID of the request's target.
75 * @flags: Flags for the request. See &enum ssam_request_flags.
76 * @length: Length of the request payload in bytes.
77 * @payload: Request payload data.
78 *
79 * This struct fully describes a SAM request with payload. It is intended to
80 * help set up the actual transport struct, e.g. &struct ssam_request_sync,
81 * and specifically its raw message data via ssam_request_write_data().
82 */
83struct ssam_request {
84 u8 target_category;
85 u8 target_id;
86 u8 command_id;
87 u8 instance_id;
88 u16 flags;
89 u16 length;
90 const u8 *payload;
91};
92
93/**
94 * struct ssam_response - Response buffer for SAM request.
95 * @capacity: Capacity of the buffer, in bytes.
96 * @length: Length of the actual data stored in the memory pointed to by
97 * @pointer, in bytes. Set by the transport system.
98 * @pointer: Pointer to the buffer's memory, storing the response payload data.
99 */
100struct ssam_response {
101 size_t capacity;
102 size_t length;
103 u8 *pointer;
104};
105
106struct ssam_controller;
107
108struct ssam_controller *ssam_get_controller(void);
109struct ssam_controller *ssam_client_bind(struct device *client);
110int ssam_client_link(struct ssam_controller *ctrl, struct device *client);
111
112struct device *ssam_controller_device(struct ssam_controller *c);
113
114struct ssam_controller *ssam_controller_get(struct ssam_controller *c);
115void ssam_controller_put(struct ssam_controller *c);
116
117void ssam_controller_statelock(struct ssam_controller *c);
118void ssam_controller_stateunlock(struct ssam_controller *c);
119
120ssize_t ssam_request_write_data(struct ssam_span *buf,
121 struct ssam_controller *ctrl,
122 const struct ssam_request *spec);
123
124
125/* -- Synchronous request interface. ---------------------------------------- */
126
127/**
128 * struct ssam_request_sync - Synchronous SAM request struct.
129 * @base: Underlying SSH request.
130 * @comp: Completion used to signal full completion of the request. After the
131 * request has been submitted, this struct may only be modified or
132 * deallocated after the completion has been signaled.
133 * request has been submitted,
134 * @resp: Buffer to store the response.
135 * @status: Status of the request, set after the base request has been
136 * completed or has failed.
137 */
138struct ssam_request_sync {
139 struct ssh_request base;
140 struct completion comp;
141 struct ssam_response *resp;
142 int status;
143};
144
145int ssam_request_sync_alloc(size_t payload_len, gfp_t flags,
146 struct ssam_request_sync **rqst,
147 struct ssam_span *buffer);
148
149void ssam_request_sync_free(struct ssam_request_sync *rqst);
150
151int ssam_request_sync_init(struct ssam_request_sync *rqst,
152 enum ssam_request_flags flags);
153
154/**
155 * ssam_request_sync_set_data - Set message data of a synchronous request.
156 * @rqst: The request.
157 * @ptr: Pointer to the request message data.
158 * @len: Length of the request message data.
159 *
160 * Set the request message data of a synchronous request. The provided buffer
161 * needs to live until the request has been completed.
162 */
163static inline void ssam_request_sync_set_data(struct ssam_request_sync *rqst,
164 u8 *ptr, size_t len)
165{
166 ssh_request_set_data(&rqst->base, ptr, len);
167}
168
169/**
170 * ssam_request_sync_set_resp - Set response buffer of a synchronous request.
171 * @rqst: The request.
172 * @resp: The response buffer.
173 *
174 * Sets the response buffer of a synchronous request. This buffer will store
175 * the response of the request after it has been completed. May be %NULL if no
176 * response is expected.
177 */
178static inline void ssam_request_sync_set_resp(struct ssam_request_sync *rqst,
179 struct ssam_response *resp)
180{
181 rqst->resp = resp;
182}
183
184int ssam_request_sync_submit(struct ssam_controller *ctrl,
185 struct ssam_request_sync *rqst);
186
187/**
188 * ssam_request_sync_wait - Wait for completion of a synchronous request.
189 * @rqst: The request to wait for.
190 *
191 * Wait for completion and release of a synchronous request. After this
192 * function terminates, the request is guaranteed to have left the transport
193 * system. After successful submission of a request, this function must be
194 * called before accessing the response of the request, freeing the request,
195 * or freeing any of the buffers associated with the request.
196 *
197 * This function must not be called if the request has not been submitted yet
198 * and may lead to a deadlock/infinite wait if a subsequent request submission
199 * fails in that case, due to the completion never triggering.
200 *
201 * Return: Returns the status of the given request, which is set on completion
202 * of the packet. This value is zero on success and negative on failure.
203 */
204static inline int ssam_request_sync_wait(struct ssam_request_sync *rqst)
205{
206 wait_for_completion(&rqst->comp);
207 return rqst->status;
208}
209
210int ssam_request_sync(struct ssam_controller *ctrl,
211 const struct ssam_request *spec,
212 struct ssam_response *rsp);
213
214int ssam_request_sync_with_buffer(struct ssam_controller *ctrl,
215 const struct ssam_request *spec,
216 struct ssam_response *rsp,
217 struct ssam_span *buf);
218
219/**
220 * ssam_request_sync_onstack - Execute a synchronous request on the stack.
221 * @ctrl: The controller via which the request is submitted.
222 * @rqst: The request specification.
223 * @rsp: The response buffer.
224 * @payload_len: The (maximum) request payload length.
225 *
226 * Allocates a synchronous request with specified payload length on the stack,
227 * fully initializes it via the provided request specification, submits it,
228 * and finally waits for its completion before returning its status. This
229 * helper macro essentially allocates the request message buffer on the stack
230 * and then calls ssam_request_sync_with_buffer().
231 *
232 * Note: The @payload_len parameter specifies the maximum payload length, used
233 * for buffer allocation. The actual payload length may be smaller.
234 *
235 * Return: Returns the status of the request or any failure during setup, i.e.
236 * zero on success and a negative value on failure.
237 */
238#define ssam_request_sync_onstack(ctrl, rqst, rsp, payload_len) \
239 ({ \
240 u8 __data[SSH_COMMAND_MESSAGE_LENGTH(payload_len)]; \
241 struct ssam_span __buf = { &__data[0], ARRAY_SIZE(__data) }; \
242 \
243 ssam_request_sync_with_buffer(ctrl, rqst, rsp, &__buf); \
244 })
245
246/**
247 * __ssam_retry - Retry request in case of I/O errors or timeouts.
248 * @request: The request function to execute. Must return an integer.
249 * @n: Number of tries.
250 * @args: Arguments for the request function.
251 *
252 * Executes the given request function, i.e. calls @request. In case the
253 * request returns %-EREMOTEIO (indicates I/O error) or %-ETIMEDOUT (request
254 * or underlying packet timed out), @request will be re-executed again, up to
255 * @n times in total.
256 *
257 * Return: Returns the return value of the last execution of @request.
258 */
259#define __ssam_retry(request, n, args...) \
260 ({ \
261 int __i, __s = 0; \
262 \
263 for (__i = (n); __i > 0; __i--) { \
264 __s = request(args); \
265 if (__s != -ETIMEDOUT && __s != -EREMOTEIO) \
266 break; \
267 } \
268 __s; \
269 })
270
271/**
272 * ssam_retry - Retry request in case of I/O errors or timeouts up to three
273 * times in total.
274 * @request: The request function to execute. Must return an integer.
275 * @args: Arguments for the request function.
276 *
277 * Executes the given request function, i.e. calls @request. In case the
278 * request returns %-EREMOTEIO (indicates I/O error) or -%ETIMEDOUT (request
279 * or underlying packet timed out), @request will be re-executed again, up to
280 * three times in total.
281 *
282 * See __ssam_retry() for a more generic macro for this purpose.
283 *
284 * Return: Returns the return value of the last execution of @request.
285 */
286#define ssam_retry(request, args...) \
287 __ssam_retry(request, 3, args)
288
289/**
290 * struct ssam_request_spec - Blue-print specification of SAM request.
291 * @target_category: Category of the request's target. See &enum ssam_ssh_tc.
292 * @target_id: ID of the request's target.
293 * @command_id: Command ID of the request.
294 * @instance_id: Instance ID of the request's target.
295 * @flags: Flags for the request. See &enum ssam_request_flags.
296 *
297 * Blue-print specification for a SAM request. This struct describes the
298 * unique static parameters of a request (i.e. type) without specifying any of
299 * its instance-specific data (e.g. payload). It is intended to be used as base
300 * for defining simple request functions via the
301 * ``SSAM_DEFINE_SYNC_REQUEST_x()`` family of macros.
302 */
303struct ssam_request_spec {
304 u8 target_category;
305 u8 target_id;
306 u8 command_id;
307 u8 instance_id;
308 u8 flags;
309};
310
311/**
312 * struct ssam_request_spec_md - Blue-print specification for multi-device SAM
313 * request.
314 * @target_category: Category of the request's target. See &enum ssam_ssh_tc.
315 * @command_id: Command ID of the request.
316 * @flags: Flags for the request. See &enum ssam_request_flags.
317 *
318 * Blue-print specification for a multi-device SAM request, i.e. a request
319 * that is applicable to multiple device instances, described by their
320 * individual target and instance IDs. This struct describes the unique static
321 * parameters of a request (i.e. type) without specifying any of its
322 * instance-specific data (e.g. payload) and without specifying any of its
323 * device specific IDs (i.e. target and instance ID). It is intended to be
324 * used as base for defining simple multi-device request functions via the
325 * ``SSAM_DEFINE_SYNC_REQUEST_MD_x()`` and ``SSAM_DEFINE_SYNC_REQUEST_CL_x()``
326 * families of macros.
327 */
328struct ssam_request_spec_md {
329 u8 target_category;
330 u8 command_id;
331 u8 flags;
332};
333
334/**
335 * SSAM_DEFINE_SYNC_REQUEST_N() - Define synchronous SAM request function
336 * with neither argument nor return value.
337 * @name: Name of the generated function.
338 * @spec: Specification (&struct ssam_request_spec) defining the request.
339 *
340 * Defines a function executing the synchronous SAM request specified by
341 * @spec, with the request having neither argument nor return value. The
342 * generated function takes care of setting up the request struct and buffer
343 * allocation, as well as execution of the request itself, returning once the
344 * request has been fully completed. The required transport buffer will be
345 * allocated on the stack.
346 *
347 * The generated function is defined as ``int name(struct ssam_controller
348 * *ctrl)``, returning the status of the request, which is zero on success and
349 * negative on failure. The ``ctrl`` parameter is the controller via which the
350 * request is being sent.
351 *
352 * Refer to ssam_request_sync_onstack() for more details on the behavior of
353 * the generated function.
354 */
355#define SSAM_DEFINE_SYNC_REQUEST_N(name, spec...) \
356 int name(struct ssam_controller *ctrl) \
357 { \
358 struct ssam_request_spec s = (struct ssam_request_spec)spec; \
359 struct ssam_request rqst; \
360 \
361 rqst.target_category = s.target_category; \
362 rqst.target_id = s.target_id; \
363 rqst.command_id = s.command_id; \
364 rqst.instance_id = s.instance_id; \
365 rqst.flags = s.flags; \
366 rqst.length = 0; \
367 rqst.payload = NULL; \
368 \
369 return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
370 }
371
372/**
373 * SSAM_DEFINE_SYNC_REQUEST_W() - Define synchronous SAM request function with
374 * argument.
375 * @name: Name of the generated function.
376 * @atype: Type of the request's argument.
377 * @spec: Specification (&struct ssam_request_spec) defining the request.
378 *
379 * Defines a function executing the synchronous SAM request specified by
380 * @spec, with the request taking an argument of type @atype and having no
381 * return value. The generated function takes care of setting up the request
382 * struct, buffer allocation, as well as execution of the request itself,
383 * returning once the request has been fully completed. The required transport
384 * buffer will be allocated on the stack.
385 *
386 * The generated function is defined as ``int name(struct ssam_controller
387 * *ctrl, const atype *arg)``, returning the status of the request, which is
388 * zero on success and negative on failure. The ``ctrl`` parameter is the
389 * controller via which the request is sent. The request argument is specified
390 * via the ``arg`` pointer.
391 *
392 * Refer to ssam_request_sync_onstack() for more details on the behavior of
393 * the generated function.
394 */
395#define SSAM_DEFINE_SYNC_REQUEST_W(name, atype, spec...) \
396 int name(struct ssam_controller *ctrl, const atype *arg) \
397 { \
398 struct ssam_request_spec s = (struct ssam_request_spec)spec; \
399 struct ssam_request rqst; \
400 \
401 rqst.target_category = s.target_category; \
402 rqst.target_id = s.target_id; \
403 rqst.command_id = s.command_id; \
404 rqst.instance_id = s.instance_id; \
405 rqst.flags = s.flags; \
406 rqst.length = sizeof(atype); \
407 rqst.payload = (u8 *)arg; \
408 \
409 return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
410 sizeof(atype)); \
411 }
412
413/**
414 * SSAM_DEFINE_SYNC_REQUEST_R() - Define synchronous SAM request function with
415 * return value.
416 * @name: Name of the generated function.
417 * @rtype: Type of the request's return value.
418 * @spec: Specification (&struct ssam_request_spec) defining the request.
419 *
420 * Defines a function executing the synchronous SAM request specified by
421 * @spec, with the request taking no argument but having a return value of
422 * type @rtype. The generated function takes care of setting up the request
423 * and response structs, buffer allocation, as well as execution of the
424 * request itself, returning once the request has been fully completed. The
425 * required transport buffer will be allocated on the stack.
426 *
427 * The generated function is defined as ``int name(struct ssam_controller
428 * *ctrl, rtype *ret)``, returning the status of the request, which is zero on
429 * success and negative on failure. The ``ctrl`` parameter is the controller
430 * via which the request is sent. The request's return value is written to the
431 * memory pointed to by the ``ret`` parameter.
432 *
433 * Refer to ssam_request_sync_onstack() for more details on the behavior of
434 * the generated function.
435 */
436#define SSAM_DEFINE_SYNC_REQUEST_R(name, rtype, spec...) \
437 int name(struct ssam_controller *ctrl, rtype *ret) \
438 { \
439 struct ssam_request_spec s = (struct ssam_request_spec)spec; \
440 struct ssam_request rqst; \
441 struct ssam_response rsp; \
442 int status; \
443 \
444 rqst.target_category = s.target_category; \
445 rqst.target_id = s.target_id; \
446 rqst.command_id = s.command_id; \
447 rqst.instance_id = s.instance_id; \
448 rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
449 rqst.length = 0; \
450 rqst.payload = NULL; \
451 \
452 rsp.capacity = sizeof(rtype); \
453 rsp.length = 0; \
454 rsp.pointer = (u8 *)ret; \
455 \
456 status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
457 if (status) \
458 return status; \
459 \
460 if (rsp.length != sizeof(rtype)) { \
461 struct device *dev = ssam_controller_device(ctrl); \
462 dev_err(dev, \
463 "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
464 sizeof(rtype), rsp.length, rqst.target_category,\
465 rqst.command_id); \
466 return -EIO; \
467 } \
468 \
469 return 0; \
470 }
471
472/**
473 * SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM
474 * request function with neither argument nor return value.
475 * @name: Name of the generated function.
476 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
477 *
478 * Defines a function executing the synchronous SAM request specified by
479 * @spec, with the request having neither argument nor return value. Device
480 * specifying parameters are not hard-coded, but instead must be provided to
481 * the function. The generated function takes care of setting up the request
482 * struct, buffer allocation, as well as execution of the request itself,
483 * returning once the request has been fully completed. The required transport
484 * buffer will be allocated on the stack.
485 *
486 * The generated function is defined as ``int name(struct ssam_controller
487 * *ctrl, u8 tid, u8 iid)``, returning the status of the request, which is
488 * zero on success and negative on failure. The ``ctrl`` parameter is the
489 * controller via which the request is sent, ``tid`` the target ID for the
490 * request, and ``iid`` the instance ID.
491 *
492 * Refer to ssam_request_sync_onstack() for more details on the behavior of
493 * the generated function.
494 */
495#define SSAM_DEFINE_SYNC_REQUEST_MD_N(name, spec...) \
496 int name(struct ssam_controller *ctrl, u8 tid, u8 iid) \
497 { \
498 struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
499 struct ssam_request rqst; \
500 \
501 rqst.target_category = s.target_category; \
502 rqst.target_id = tid; \
503 rqst.command_id = s.command_id; \
504 rqst.instance_id = iid; \
505 rqst.flags = s.flags; \
506 rqst.length = 0; \
507 rqst.payload = NULL; \
508 \
509 return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
510 }
511
512/**
513 * SSAM_DEFINE_SYNC_REQUEST_MD_W() - Define synchronous multi-device SAM
514 * request function with argument.
515 * @name: Name of the generated function.
516 * @atype: Type of the request's argument.
517 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
518 *
519 * Defines a function executing the synchronous SAM request specified by
520 * @spec, with the request taking an argument of type @atype and having no
521 * return value. Device specifying parameters are not hard-coded, but instead
522 * must be provided to the function. The generated function takes care of
523 * setting up the request struct, buffer allocation, as well as execution of
524 * the request itself, returning once the request has been fully completed.
525 * The required transport buffer will be allocated on the stack.
526 *
527 * The generated function is defined as ``int name(struct ssam_controller
528 * *ctrl, u8 tid, u8 iid, const atype *arg)``, returning the status of the
529 * request, which is zero on success and negative on failure. The ``ctrl``
530 * parameter is the controller via which the request is sent, ``tid`` the
531 * target ID for the request, and ``iid`` the instance ID. The request argument
532 * is specified via the ``arg`` pointer.
533 *
534 * Refer to ssam_request_sync_onstack() for more details on the behavior of
535 * the generated function.
536 */
537#define SSAM_DEFINE_SYNC_REQUEST_MD_W(name, atype, spec...) \
538 int name(struct ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg)\
539 { \
540 struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
541 struct ssam_request rqst; \
542 \
543 rqst.target_category = s.target_category; \
544 rqst.target_id = tid; \
545 rqst.command_id = s.command_id; \
546 rqst.instance_id = iid; \
547 rqst.flags = s.flags; \
548 rqst.length = sizeof(atype); \
549 rqst.payload = (u8 *)arg; \
550 \
551 return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
552 sizeof(atype)); \
553 }
554
555/**
556 * SSAM_DEFINE_SYNC_REQUEST_MD_R() - Define synchronous multi-device SAM
557 * request function with return value.
558 * @name: Name of the generated function.
559 * @rtype: Type of the request's return value.
560 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
561 *
562 * Defines a function executing the synchronous SAM request specified by
563 * @spec, with the request taking no argument but having a return value of
564 * type @rtype. Device specifying parameters are not hard-coded, but instead
565 * must be provided to the function. The generated function takes care of
566 * setting up the request and response structs, buffer allocation, as well as
567 * execution of the request itself, returning once the request has been fully
568 * completed. The required transport buffer will be allocated on the stack.
569 *
570 * The generated function is defined as ``int name(struct ssam_controller
571 * *ctrl, u8 tid, u8 iid, rtype *ret)``, returning the status of the request,
572 * which is zero on success and negative on failure. The ``ctrl`` parameter is
573 * the controller via which the request is sent, ``tid`` the target ID for the
574 * request, and ``iid`` the instance ID. The request's return value is written
575 * to the memory pointed to by the ``ret`` parameter.
576 *
577 * Refer to ssam_request_sync_onstack() for more details on the behavior of
578 * the generated function.
579 */
580#define SSAM_DEFINE_SYNC_REQUEST_MD_R(name, rtype, spec...) \
581 int name(struct ssam_controller *ctrl, u8 tid, u8 iid, rtype *ret) \
582 { \
583 struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
584 struct ssam_request rqst; \
585 struct ssam_response rsp; \
586 int status; \
587 \
588 rqst.target_category = s.target_category; \
589 rqst.target_id = tid; \
590 rqst.command_id = s.command_id; \
591 rqst.instance_id = iid; \
592 rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
593 rqst.length = 0; \
594 rqst.payload = NULL; \
595 \
596 rsp.capacity = sizeof(rtype); \
597 rsp.length = 0; \
598 rsp.pointer = (u8 *)ret; \
599 \
600 status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
601 if (status) \
602 return status; \
603 \
604 if (rsp.length != sizeof(rtype)) { \
605 struct device *dev = ssam_controller_device(ctrl); \
606 dev_err(dev, \
607 "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
608 sizeof(rtype), rsp.length, rqst.target_category,\
609 rqst.command_id); \
610 return -EIO; \
611 } \
612 \
613 return 0; \
614 }
615
616
617/* -- Event notifier/callbacks. --------------------------------------------- */
618
619#define SSAM_NOTIF_STATE_SHIFT 2
620#define SSAM_NOTIF_STATE_MASK ((1 << SSAM_NOTIF_STATE_SHIFT) - 1)
621
622/**
623 * enum ssam_notif_flags - Flags used in return values from SSAM notifier
624 * callback functions.
625 *
626 * @SSAM_NOTIF_HANDLED:
627 * Indicates that the notification has been handled. This flag should be
628 * set by the handler if the handler can act/has acted upon the event
629 * provided to it. This flag should not be set if the handler is not a
630 * primary handler intended for the provided event.
631 *
632 * If this flag has not been set by any handler after the notifier chain
633 * has been traversed, a warning will be emitted, stating that the event
634 * has not been handled.
635 *
636 * @SSAM_NOTIF_STOP:
637 * Indicates that the notifier traversal should stop. If this flag is
638 * returned from a notifier callback, notifier chain traversal will
639 * immediately stop and any remaining notifiers will not be called. This
640 * flag is automatically set when ssam_notifier_from_errno() is called
641 * with a negative error value.
642 */
643enum ssam_notif_flags {
644 SSAM_NOTIF_HANDLED = BIT(0),
645 SSAM_NOTIF_STOP = BIT(1),
646};
647
648struct ssam_event_notifier;
649
650typedef u32 (*ssam_notifier_fn_t)(struct ssam_event_notifier *nf,
651 const struct ssam_event *event);
652
653/**
654 * struct ssam_notifier_block - Base notifier block for SSAM event
655 * notifications.
656 * @node: The node for the list of notifiers.
657 * @fn: The callback function of this notifier. This function takes the
658 * respective notifier block and event as input and should return
659 * a notifier value, which can either be obtained from the flags
660 * provided in &enum ssam_notif_flags, converted from a standard
661 * error value via ssam_notifier_from_errno(), or a combination of
662 * both (e.g. ``ssam_notifier_from_errno(e) | SSAM_NOTIF_HANDLED``).
663 * @priority: Priority value determining the order in which notifier callbacks
664 * will be called. A higher value means higher priority, i.e. the
665 * associated callback will be executed earlier than other (lower
666 * priority) callbacks.
667 */
668struct ssam_notifier_block {
669 struct list_head node;
670 ssam_notifier_fn_t fn;
671 int priority;
672};
673
674/**
675 * ssam_notifier_from_errno() - Convert standard error value to notifier
676 * return code.
677 * @err: The error code to convert, must be negative (in case of failure) or
678 * zero (in case of success).
679 *
680 * Return: Returns the notifier return value obtained by converting the
681 * specified @err value. In case @err is negative, the %SSAM_NOTIF_STOP flag
682 * will be set, causing notifier call chain traversal to abort.
683 */
684static inline u32 ssam_notifier_from_errno(int err)
685{
686 if (WARN_ON(err > 0) || err == 0)
687 return 0;
688 else
689 return ((-err) << SSAM_NOTIF_STATE_SHIFT) | SSAM_NOTIF_STOP;
690}
691
692/**
693 * ssam_notifier_to_errno() - Convert notifier return code to standard error
694 * value.
695 * @ret: The notifier return value to convert.
696 *
697 * Return: Returns the negative error value encoded in @ret or zero if @ret
698 * indicates success.
699 */
700static inline int ssam_notifier_to_errno(u32 ret)
701{
702 return -(ret >> SSAM_NOTIF_STATE_SHIFT);
703}
704
705
706/* -- Event/notification registry. ------------------------------------------ */
707
708/**
709 * struct ssam_event_registry - Registry specification used for enabling events.
710 * @target_category: Target category for the event registry requests.
711 * @target_id: Target ID for the event registry requests.
712 * @cid_enable: Command ID for the event-enable request.
713 * @cid_disable: Command ID for the event-disable request.
714 *
715 * This struct describes a SAM event registry via the minimal collection of
716 * SAM IDs specifying the requests to use for enabling and disabling an event.
717 * The individual event to be enabled/disabled itself is specified via &struct
718 * ssam_event_id.
719 */
720struct ssam_event_registry {
721 u8 target_category;
722 u8 target_id;
723 u8 cid_enable;
724 u8 cid_disable;
725};
726
727/**
728 * struct ssam_event_id - Unique event ID used for enabling events.
729 * @target_category: Target category of the event source.
730 * @instance: Instance ID of the event source.
731 *
732 * This struct specifies the event to be enabled/disabled via an externally
733 * provided registry. It does not specify the registry to be used itself, this
734 * is done via &struct ssam_event_registry.
735 */
736struct ssam_event_id {
737 u8 target_category;
738 u8 instance;
739};
740
741/**
742 * enum ssam_event_mask - Flags specifying how events are matched to notifiers.
743 *
744 * @SSAM_EVENT_MASK_NONE:
745 * Run the callback for any event with matching target category. Do not
746 * do any additional filtering.
747 *
748 * @SSAM_EVENT_MASK_TARGET:
749 * In addition to filtering by target category, only execute the notifier
750 * callback for events with a target ID matching to the one of the
751 * registry used for enabling/disabling the event.
752 *
753 * @SSAM_EVENT_MASK_INSTANCE:
754 * In addition to filtering by target category, only execute the notifier
755 * callback for events with an instance ID matching to the instance ID
756 * used when enabling the event.
757 *
758 * @SSAM_EVENT_MASK_STRICT:
759 * Do all the filtering above.
760 */
761enum ssam_event_mask {
762 SSAM_EVENT_MASK_TARGET = BIT(0),
763 SSAM_EVENT_MASK_INSTANCE = BIT(1),
764
765 SSAM_EVENT_MASK_NONE = 0,
766 SSAM_EVENT_MASK_STRICT =
767 SSAM_EVENT_MASK_TARGET
768 | SSAM_EVENT_MASK_INSTANCE,
769};
770
771/**
772 * SSAM_EVENT_REGISTRY() - Define a new event registry.
773 * @tc: Target category for the event registry requests.
774 * @tid: Target ID for the event registry requests.
775 * @cid_en: Command ID for the event-enable request.
776 * @cid_dis: Command ID for the event-disable request.
777 *
778 * Return: Returns the &struct ssam_event_registry specified by the given
779 * parameters.
780 */
781#define SSAM_EVENT_REGISTRY(tc, tid, cid_en, cid_dis) \
782 ((struct ssam_event_registry) { \
783 .target_category = (tc), \
784 .target_id = (tid), \
785 .cid_enable = (cid_en), \
786 .cid_disable = (cid_dis), \
787 })
788
789#define SSAM_EVENT_REGISTRY_SAM \
790 SSAM_EVENT_REGISTRY(SSAM_SSH_TC_SAM, 0x01, 0x0b, 0x0c)
791
792#define SSAM_EVENT_REGISTRY_KIP \
793 SSAM_EVENT_REGISTRY(SSAM_SSH_TC_KIP, 0x02, 0x27, 0x28)
794
795#define SSAM_EVENT_REGISTRY_REG \
796 SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02)
797
798/**
799 * struct ssam_event_notifier - Notifier block for SSAM events.
800 * @base: The base notifier block with callback function and priority.
801 * @event: The event for which this block will receive notifications.
802 * @event.reg: Registry via which the event will be enabled/disabled.
803 * @event.id: ID specifying the event.
804 * @event.mask: Flags determining how events are matched to the notifier.
805 * @event.flags: Flags used for enabling the event.
806 */
807struct ssam_event_notifier {
808 struct ssam_notifier_block base;
809
810 struct {
811 struct ssam_event_registry reg;
812 struct ssam_event_id id;
813 enum ssam_event_mask mask;
814 u8 flags;
815 } event;
816};
817
818int ssam_notifier_register(struct ssam_controller *ctrl,
819 struct ssam_event_notifier *n);
820
821int ssam_notifier_unregister(struct ssam_controller *ctrl,
822 struct ssam_event_notifier *n);
823
824#endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */
include/linux/surface_aggregator/device.h+423−0
@@ -0,0 +1,423 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
4 *
5 * Main interface for the surface-aggregator bus, surface-aggregator client
6 * devices, and respective drivers building on top of the SSAM controller.
7 * Provides support for non-platform/non-ACPI SSAM clients via dedicated
8 * subsystem.
9 *
10 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
11 */
12
13#ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
14#define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
15
16#include <linux/device.h>
17#include <linux/mod_devicetable.h>
18#include <linux/types.h>
19
20#include <linux/surface_aggregator/controller.h>
21
22
23/* -- Surface System Aggregator Module bus. --------------------------------- */
24
25/**
26 * enum ssam_device_domain - SAM device domain.
27 * @SSAM_DOMAIN_VIRTUAL: Virtual device.
28 * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
29 */
30enum ssam_device_domain {
31 SSAM_DOMAIN_VIRTUAL = 0x00,
32 SSAM_DOMAIN_SERIALHUB = 0x01,
33};
34
35/**
36 * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
37 * @SSAM_VIRTUAL_TC_HUB: Device hub category.
38 */
39enum ssam_virtual_tc {
40 SSAM_VIRTUAL_TC_HUB = 0x00,
41};
42
43/**
44 * struct ssam_device_uid - Unique identifier for SSAM device.
45 * @domain: Domain of the device.
46 * @category: Target category of the device.
47 * @target: Target ID of the device.
48 * @instance: Instance ID of the device.
49 * @function: Sub-function of the device. This field can be used to split a
50 * single SAM device into multiple virtual subdevices to separate
51 * different functionality of that device and allow one driver per
52 * such functionality.
53 */
54struct ssam_device_uid {
55 u8 domain;
56 u8 category;
57 u8 target;
58 u8 instance;
59 u8 function;
60};
61
62/*
63 * Special values for device matching.
64 *
65 * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
66 * SSAM_SDEV() exclusively. Specifically, they are used to initialize the
67 * match_flags member of the device ID structure. Do not use them directly
68 * with struct ssam_device_id or struct ssam_device_uid.
69 */
70#define SSAM_ANY_TID 0xffff
71#define SSAM_ANY_IID 0xffff
72#define SSAM_ANY_FUN 0xffff
73
74/**
75 * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
76 * parameters.
77 * @d: Domain of the device.
78 * @cat: Target category of the device.
79 * @tid: Target ID of the device.
80 * @iid: Instance ID of the device.
81 * @fun: Sub-function of the device.
82 *
83 * Initializes a &struct ssam_device_id with the given parameters. See &struct
84 * ssam_device_uid for details regarding the parameters. The special values
85 * %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be used to specify that
86 * matching should ignore target ID, instance ID, and/or sub-function,
87 * respectively. This macro initializes the ``match_flags`` field based on the
88 * given parameters.
89 *
90 * Note: The parameters @d and @cat must be valid &u8 values, the parameters
91 * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
92 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
93 * allowed.
94 */
95#define SSAM_DEVICE(d, cat, tid, iid, fun) \
96 .match_flags = (((tid) != SSAM_ANY_TID) ? SSAM_MATCH_TARGET : 0) \
97 | (((iid) != SSAM_ANY_IID) ? SSAM_MATCH_INSTANCE : 0) \
98 | (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0), \
99 .domain = d, \
100 .category = cat, \
101 .target = ((tid) != SSAM_ANY_TID) ? (tid) : 0, \
102 .instance = ((iid) != SSAM_ANY_IID) ? (iid) : 0, \
103 .function = ((fun) != SSAM_ANY_FUN) ? (fun) : 0 \
104
105/**
106 * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
107 * the given parameters.
108 * @cat: Target category of the device.
109 * @tid: Target ID of the device.
110 * @iid: Instance ID of the device.
111 * @fun: Sub-function of the device.
112 *
113 * Initializes a &struct ssam_device_id with the given parameters in the
114 * virtual domain. See &struct ssam_device_uid for details regarding the
115 * parameters. The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and
116 * %SSAM_ANY_FUN can be used to specify that matching should ignore target ID,
117 * instance ID, and/or sub-function, respectively. This macro initializes the
118 * ``match_flags`` field based on the given parameters.
119 *
120 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
121 * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
122 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
123 * allowed.
124 */
125#define SSAM_VDEV(cat, tid, iid, fun) \
126 SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, tid, iid, fun)
127
128/**
129 * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
130 * with the given parameters.
131 * @cat: Target category of the device.
132 * @tid: Target ID of the device.
133 * @iid: Instance ID of the device.
134 * @fun: Sub-function of the device.
135 *
136 * Initializes a &struct ssam_device_id with the given parameters in the SSH
137 * domain. See &struct ssam_device_uid for details regarding the parameters.
138 * The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be
139 * used to specify that matching should ignore target ID, instance ID, and/or
140 * sub-function, respectively. This macro initializes the ``match_flags``
141 * field based on the given parameters.
142 *
143 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
144 * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
145 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
146 * allowed.
147 */

276 more lines aren’t shown here.

include/linux/surface_aggregator/serial_hub.h+672−0

This diff is large: its 673 lines aren’t shown here.

include/uapi/linux/surface_aggregator/cdev.h+78−0

This diff is large: its 79 lines aren’t shown here.

scripts/mod/devicetable-offsets.c+8−0

This diff is large: its 14 lines aren’t shown here.

scripts/mod/file2alias.c+23−0

This diff is large: its 37 lines aren’t shown here.

tools/power/x86/intel-speed-select/isst-config.c+113−2

This diff is large: its 157 lines aren’t shown here.

tools/power/x86/intel-speed-select/isst-core.c+11−0

This diff is large: its 18 lines aren’t shown here.

tools/power/x86/intel-speed-select/isst-display.c+18−0

This diff is large: its 22 lines aren’t shown here.

tools/power/x86/intel-speed-select/isst.h+2−0

This diff is large: its 14 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t