Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'platform-drivers-x86-v6.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver updates from Ilpo Järvinen:

- alienware WMAX thermal interface support

- Split ACPI and platform device based amd/hsmp drivers

- AMD X3D frequency/cache mode switching support

- asus thermal policy fixes

- Disable C1 auto-demotion in suspend to allow entering the deepest
C-states

- Fix volume buttons on Thinkpad X12 Detachable Tablet Gen 1

- Replace intel_scu_ipc "workaround" with 32-bit IO

- Correct *_show() function error handling in panasonic-laptop

- Gemini Lake P2SB devfn correction

- think-lmi Admin/System certificate authentication support

- Disable WMI devices for shutdown, refactoring continues

- Vexia EDU ATLA 10 tablet support

- Surface Pro 9 5G (Arm/QCOM) support

- Misc cleanups / refactoring / improvements

* tag 'platform-drivers-x86-v6.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (69 commits)
platform/x86: p2sb: Cache correct PCI bar for P2SB on Gemini Lake
platform/x86: panasonic-laptop: Return errno correctly in show callback
Documentation: alienware-wmi: Describe THERMAL_INFORMATION operation 0x02
alienware-wmi: create_thermal_profile() no longer brute-forces IDs
alienware-wmi: Adds support to Alienware x17 R2
alienware-wmi: extends the list of supported models
alienware-wmi: order alienware_quirks[] alphabetically
platform/x86/intel/pmt: allow user offset for PMT callbacks
platform/x86/amd/hsmp: Change the error type
platform/x86/amd/hsmp: Add new error code and error logs
platform/x86/amd: amd_3d_vcache: Add sysfs ABI documentation
platform/x86/amd: amd_3d_vcache: Add AMD 3D V-Cache optimizer driver
intel-hid: fix volume buttons on Thinkpad X12 Detachable Tablet Gen 1
platform/x86/amd/hsmp: mark hsmp_msg_desc_table[] as maybe_unused
platform/x86: asus-wmi: Use platform_profile_cycle()
platform/x86: asus-wmi: Fix inconsistent use of thermal policies
platform/x86: hp: hp-bioscfg: remove redundant if statement
MAINTAINERS: Update ISHTP ECLITE maintainer entry
platform/x86: x86-android-tablets: Add support for Vexia EDU ATLA 10 tablet
platform/x86: x86-android-tablets: Add support for getting i2c_adapter by PCI parent devname()
...

+3194 -1517
+12
Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache
··· 1 + What: /sys/bus/platform/drivers/amd_x3d_vcache/AMDI0101:00/amd_x3d_mode 2 + Date: November 2024 3 + KernelVersion: 6.13 4 + Contact: Basavaraj Natikar <Basavaraj.Natikar@amd.com> 5 + Description: (RW) AMD 3D V-Cache optimizer allows users to switch CPU core 6 + rankings dynamically. 7 + 8 + This file switches between these two modes: 9 + - "frequency" cores within the faster CCD are prioritized before 10 + those in the slower CCD. 11 + - "cache" cores within the larger L3 CCD are prioritized before 12 + those in the smaller L3 CCD.
+2 -1
Documentation/ABI/testing/sysfs-class-firmware-attributes
··· 193 193 194 194 mechanism: 195 195 The means of authentication. This attribute is mandatory. 196 - Only supported type currently is "password". 196 + Supported types are "password" or "certificate". 197 197 198 198 max_password_length: 199 199 A file that can be read to obtain the ··· 303 303 being configured allowing anyone to make changes. 304 304 After any of these operations the system must reboot for the changes to 305 305 take effect. 306 + Admin and System certificates are supported from 2025 systems onward. 306 307 307 308 certificate_thumbprint: 308 309 Read only attribute used to display the MD5, SHA1 and SHA256 thumbprints
+62 -5
Documentation/arch/x86/amd_hsmp.rst
··· 4 4 AMD HSMP interface 5 5 ============================================ 6 6 7 - Newer Fam19h EPYC server line of processors from AMD support system 8 - management functionality via HSMP (Host System Management Port). 7 + Newer Fam19h(model 0x00-0x1f, 0x30-0x3f, 0x90-0x9f, 0xa0-0xaf), 8 + Fam1Ah(model 0x00-0x1f) EPYC server line of processors from AMD support 9 + system management functionality via HSMP (Host System Management Port). 9 10 10 11 The Host System Management Port (HSMP) is an interface to provide 11 12 OS-level software with access to system management functions via a ··· 17 16 Eg: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip 18 17 19 18 20 - HSMP interface is supported on EPYC server CPU models only. 19 + HSMP interface is supported on EPYC line of server CPUs and MI300A (APU). 21 20 22 21 23 22 HSMP device 24 23 ============================================ 25 24 26 - amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice 27 - /dev/hsmp to let user space programs run hsmp mailbox commands. 25 + amd_hsmp driver under drivers/platforms/x86/amd/hsmp/ has separate driver files 26 + for ACPI object based probing, platform device based probing and for the common 27 + code for these two drivers. 28 + 29 + Kconfig option CONFIG_AMD_HSMP_PLAT compiles plat.c and creates amd_hsmp.ko. 30 + Kconfig option CONFIG_AMD_HSMP_ACPI compiles acpi.c and creates hsmp_acpi.ko. 31 + Selecting any of these two configs automatically selects CONFIG_AMD_HSMP. This 32 + compiles common code hsmp.c and creates hsmp_common.ko module. 33 + 34 + Both the ACPI and plat drivers create the miscdevice /dev/hsmp to let 35 + user space programs run hsmp mailbox commands. 36 + 37 + The ACPI object format supported by the driver is defined below. 28 38 29 39 $ ls -al /dev/hsmp 30 40 crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp ··· 70 58 71 59 Metrics table definitions will be documented as part of Public PPR. 72 60 The same is defined in the amd_hsmp.h header. 61 + 62 + ACPI device object format 63 + ========================= 64 + The ACPI object format expected from the amd_hsmp driver 65 + for socket with ID00 is given below:: 66 + 67 + Device(HSMP) 68 + { 69 + Name(_HID, "AMDI0097") 70 + Name(_UID, "ID00") 71 + Name(HSE0, 0x00000001) 72 + Name(RBF0, ResourceTemplate() 73 + { 74 + Memory32Fixed(ReadWrite, 0xxxxxxx, 0x00100000) 75 + }) 76 + Method(_CRS, 0, NotSerialized) 77 + { 78 + Return(RBF0) 79 + } 80 + Method(_STA, 0, NotSerialized) 81 + { 82 + If(LEqual(HSE0, One)) 83 + { 84 + Return(0x0F) 85 + } 86 + Else 87 + { 88 + Return(Zero) 89 + } 90 + } 91 + Name(_DSD, Package(2) 92 + { 93 + Buffer(0x10) 94 + { 95 + 0x9D, 0x61, 0x4D, 0xB7, 0x07, 0x57, 0xBD, 0x48, 96 + 0xA6, 0x9F, 0x4E, 0xA2, 0x87, 0x1F, 0xC2, 0xF6 97 + }, 98 + Package(3) 99 + { 100 + Package(2) {"MsgIdOffset", 0x00010934}, 101 + Package(2) {"MsgRspOffset", 0x00010980}, 102 + Package(2) {"MsgArgOffset", 0x000109E0} 103 + } 104 + }) 105 + } 73 106 74 107 75 108 An example
+397
Documentation/wmi/devices/alienware-wmi.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + ============================================== 4 + Dell AWCC WMI interface driver (alienware-wmi) 5 + ============================================== 6 + 7 + Introduction 8 + ============ 9 + 10 + The WMI device WMAX has been implemented for many Alienware and Dell's G-Series 11 + models. Throughout these models, two implementations have been identified. The 12 + first one, used by older systems, deals with HDMI, brightness, RGB, amplifier 13 + and deep sleep control. The second one used by newer systems deals primarily 14 + with thermal, overclocking, and GPIO control. 15 + 16 + It is suspected that the latter is used by Alienware Command Center (AWCC) to 17 + manage manufacturer predefined thermal profiles. The alienware-wmi driver 18 + exposes Thermal_Information and Thermal_Control methods through the Platform 19 + Profile API to mimic AWCC's behavior. 20 + 21 + This newer interface, named AWCCMethodFunction has been reverse engineered, as 22 + Dell has not provided any official documentation. We will try to describe to the 23 + best of our ability its discovered inner workings. 24 + 25 + .. note:: 26 + The following method description may be incomplete and some operations have 27 + different implementations between devices. 28 + 29 + WMI interface description 30 + ------------------------- 31 + 32 + The WMI interface description can be decoded from the embedded binary MOF (bmof) 33 + data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 34 + 35 + :: 36 + 37 + [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{A70591CE-A997-11DA-B012-B622A1EF5492}")] 38 + class AWCCWmiMethodFunction { 39 + [key, read] string InstanceName; 40 + [read] boolean Active; 41 + 42 + [WmiMethodId(13), Implemented, read, write, Description("Return Overclocking Report.")] void Return_OverclockingReport([out] uint32 argr); 43 + [WmiMethodId(14), Implemented, read, write, Description("Set OCUIBIOS Control.")] void Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr); 44 + [WmiMethodId(15), Implemented, read, write, Description("Clear OC FailSafe Flag.")] void Clear_OCFailSafeFlag([out] uint32 argr); 45 + [WmiMethodId(19), Implemented, read, write, Description("Get Fan Sensors.")] void GetFanSensors([in] uint32 arg2, [out] uint32 argr); 46 + [WmiMethodId(20), Implemented, read, write, Description("Thermal Information.")] void Thermal_Information([in] uint32 arg2, [out] uint32 argr); 47 + [WmiMethodId(21), Implemented, read, write, Description("Thermal Control.")] void Thermal_Control([in] uint32 arg2, [out] uint32 argr); 48 + [WmiMethodId(23), Implemented, read, write, Description("MemoryOCControl.")] void MemoryOCControl([in] uint32 arg2, [out] uint32 argr); 49 + [WmiMethodId(26), Implemented, read, write, Description("System Information.")] void SystemInformation([in] uint32 arg2, [out] uint32 argr); 50 + [WmiMethodId(28), Implemented, read, write, Description("Power Information.")] void PowerInformation([in] uint32 arg2, [out] uint32 argr); 51 + [WmiMethodId(32), Implemented, read, write, Description("FW Update GPIO toggle.")] void FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr); 52 + [WmiMethodId(33), Implemented, read, write, Description("Read Total of GPIOs.")] void ReadTotalofGPIOs([out] uint32 argr); 53 + [WmiMethodId(34), Implemented, read, write, Description("Read GPIO pin Status.")] void ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr); 54 + [WmiMethodId(35), Implemented, read, write, Description("Read Chassis Color.")] void ReadChassisColor([out] uint32 argr); 55 + [WmiMethodId(36), Implemented, read, write, Description("Read Platform Properties.")] void ReadPlatformProperties([out] uint32 argr); 56 + [WmiMethodId(37), Implemented, read, write, Description("Game Shift Status.")] void GameShiftStatus([in] uint32 arg2, [out] uint32 argr); 57 + [WmiMethodId(128), Implemented, read, write, Description("Caldera SW installation.")] void CalderaSWInstallation([out] uint32 argr); 58 + [WmiMethodId(129), Implemented, read, write, Description("Caldera SW is released.")] void CalderaSWReleased([out] uint32 argr); 59 + [WmiMethodId(130), Implemented, read, write, Description("Caldera Connection Status.")] void CalderaConnectionStatus([in] uint32 arg2, [out] uint32 argr); 60 + [WmiMethodId(131), Implemented, read, write, Description("Surprise Unplugged Flag Status.")] void SurpriseUnpluggedFlagStatus([out] uint32 argr); 61 + [WmiMethodId(132), Implemented, read, write, Description("Clear Surprise Unplugged Flag.")] void ClearSurpriseUnpluggedFlag([out] uint32 argr); 62 + [WmiMethodId(133), Implemented, read, write, Description("Cancel Undock Request.")] void CancelUndockRequest([out] uint32 argr); 63 + [WmiMethodId(135), Implemented, read, write, Description("Devices in Caldera.")] void DevicesInCaldera([in] uint32 arg2, [out] uint32 argr); 64 + [WmiMethodId(136), Implemented, read, write, Description("Notify BIOS for SW ready to disconnect Caldera.")] void NotifyBIOSForSWReadyToDisconnectCaldera([out] uint32 argr); 65 + [WmiMethodId(160), Implemented, read, write, Description("Tobii SW installation.")] void TobiiSWinstallation([out] uint32 argr); 66 + [WmiMethodId(161), Implemented, read, write, Description("Tobii SW Released.")] void TobiiSWReleased([out] uint32 argr); 67 + [WmiMethodId(162), Implemented, read, write, Description("Tobii Camera Power Reset.")] void TobiiCameraPowerReset([out] uint32 argr); 68 + [WmiMethodId(163), Implemented, read, write, Description("Tobii Camera Power On.")] void TobiiCameraPowerOn([out] uint32 argr); 69 + [WmiMethodId(164), Implemented, read, write, Description("Tobii Camera Power Off.")] void TobiiCameraPowerOff([out] uint32 argr); 70 + }; 71 + 72 + Some of these methods get quite intricate so we will describe them using 73 + pseudo-code that vaguely resembles the original ASL code. 74 + 75 + Methods not described in the following document have unknown behavior. 76 + 77 + Argument Structure 78 + ------------------ 79 + 80 + All input arguments have type **uint32** and their structure is very similar 81 + between methods. Usually, the first byte corresponds to a specific *operation* 82 + the method performs, and the subsequent bytes correspond to *arguments* passed 83 + to this *operation*. For example, if an operation has code 0x01 and requires an 84 + ID 0xA0, the argument you would pass to the method is 0xA001. 85 + 86 + 87 + Thermal Methods 88 + =============== 89 + 90 + WMI method Thermal_Information([in] uint32 arg2, [out] uint32 argr) 91 + ------------------------------------------------------------------- 92 + 93 + :: 94 + 95 + if BYTE_0(arg2) == 0x01: 96 + argr = 1 97 + 98 + if BYTE_0(arg2) == 0x02: 99 + argr = SYSTEM_DESCRIPTION 100 + 101 + if BYTE_0(arg2) == 0x03: 102 + if BYTE_1(arg2) == 0x00: 103 + argr = FAN_ID_0 104 + 105 + if BYTE_1(arg2) == 0x01: 106 + argr = FAN_ID_1 107 + 108 + if BYTE_1(arg2) == 0x02: 109 + argr = FAN_ID_2 110 + 111 + if BYTE_1(arg2) == 0x03: 112 + argr = FAN_ID_3 113 + 114 + if BYTE_1(arg2) == 0x04: 115 + argr = SENSOR_ID_CPU | 0x0100 116 + 117 + if BYTE_1(arg2) == 0x05: 118 + argr = SENSOR_ID_GPU | 0x0100 119 + 120 + if BYTE_1(arg2) == 0x06: 121 + argr = THERMAL_MODE_QUIET_ID 122 + 123 + if BYTE_1(arg2) == 0x07: 124 + argr = THERMAL_MODE_BALANCED_ID 125 + 126 + if BYTE_1(arg2) == 0x08: 127 + argr = THERMAL_MODE_BALANCED_PERFORMANCE_ID 128 + 129 + if BYTE_1(arg2) == 0x09: 130 + argr = THERMAL_MODE_PERFORMANCE_ID 131 + 132 + if BYTE_1(arg2) == 0x0A: 133 + argr = THERMAL_MODE_LOW_POWER_ID 134 + 135 + if BYTE_1(arg2) == 0x0B: 136 + argr = THERMAL_MODE_GMODE_ID 137 + 138 + else: 139 + argr = 0xFFFFFFFF 140 + 141 + if BYTE_0(arg2) == 0x04: 142 + if is_valid_sensor(BYTE_1(arg2)): 143 + argr = SENSOR_TEMP_C 144 + else: 145 + argr = 0xFFFFFFFF 146 + 147 + if BYTE_0(arg2) == 0x05: 148 + if is_valid_fan(BYTE_1(arg2)): 149 + argr = FAN_RPM() 150 + 151 + if BYTE_0(arg2) == 0x06: 152 + skip 153 + 154 + if BYTE_0(arg2) == 0x07: 155 + argr = 0 156 + 157 + If BYTE_0(arg2) == 0x08: 158 + if is_valid_fan(BYTE_1(arg2)): 159 + argr = 0 160 + else: 161 + argr = 0xFFFFFFFF 162 + 163 + if BYTE_0(arg2) == 0x09: 164 + if is_valid_fan(BYTE_1(arg2)): 165 + argr = FAN_UNKNOWN_STAT_0() 166 + 167 + else: 168 + argr = 0xFFFFFFFF 169 + 170 + if BYTE_0(arg2) == 0x0A: 171 + argr = THERMAL_MODE_BALANCED_ID 172 + 173 + if BYTE_0(arg2) == 0x0B: 174 + argr = CURRENT_THERMAL_MODE() 175 + 176 + if BYTE_0(arg2) == 0x0C: 177 + if is_valid_fan(BYTE_1(arg2)): 178 + argr = FAN_UNKNOWN_STAT_1() 179 + else: 180 + argr = 0xFFFFFFFF 181 + 182 + Operation 0x02 returns a *system description* buffer with the following 183 + structure: 184 + 185 + :: 186 + 187 + out[0] -> Number of fans 188 + out[1] -> Number of sensors 189 + out[2] -> 0x00 190 + out[3] -> Number of thermal modes 191 + 192 + Operation 0x03 list all available fan IDs, sensor IDs and thermal profile 193 + codes in order, but different models may have different number of fans and 194 + thermal profiles. These are the known ranges: 195 + 196 + * Fan IDs: from 2 up to 4 197 + * Sensor IDs: 2 198 + * Thermal profile codes: from 1 up to 7 199 + 200 + In total BYTE_1(ARG2) may range from 0x5 up to 0xD depending on the model. 201 + 202 + WMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr) 203 + --------------------------------------------------------------- 204 + 205 + :: 206 + 207 + if BYTE_0(arg2) == 0x01: 208 + if is_valid_thermal_profile(BYTE_1(arg2)): 209 + SET_THERMAL_PROFILE(BYTE_1(arg2)) 210 + argr = 0 211 + 212 + if BYTE_0(arg2) == 0x02: 213 + if is_valid_fan(BYTE_1(arg2)): 214 + SET_FAN_SPEED_MULTIPLIER(BYTE_2(arg2)) 215 + argr = 0 216 + else: 217 + argr = 0xFFFFFFFF 218 + 219 + .. note:: 220 + While you can manually change the fan speed multiplier with this method, 221 + Dell's BIOS tends to overwrite this changes anyway. 222 + 223 + These are the known thermal profile codes: 224 + 225 + :: 226 + 227 + CUSTOM 0x00 228 + 229 + BALANCED_USTT 0xA0 230 + BALANCED_PERFORMANCE_USTT 0xA1 231 + COOL_USTT 0xA2 232 + QUIET_USTT 0xA3 233 + PERFORMANCE_USTT 0xA4 234 + LOW_POWER_USTT 0xA5 235 + 236 + QUIET 0x96 237 + BALANCED 0x97 238 + BALANCED_PERFORMANCE 0x98 239 + PERFORMANCE 0x99 240 + 241 + GMODE 0xAB 242 + 243 + Usually if a model doesn't support the first four profiles they will support 244 + the User Selectable Thermal Tables (USTT) profiles and vice-versa. 245 + 246 + GMODE replaces PERFORMANCE in G-Series laptops. 247 + 248 + WMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr) 249 + --------------------------------------------------------------- 250 + 251 + :: 252 + 253 + if BYTE_0(arg2) == 0x1: 254 + TOGGLE_GAME_SHIFT() 255 + argr = GET_GAME_SHIFT_STATUS() 256 + 257 + if BYTE_0(arg2) == 0x2: 258 + argr = GET_GAME_SHIFT_STATUS() 259 + 260 + Game Shift Status does not change the fan speed profile but it could be some 261 + sort of CPU/GPU power profile. Benchmarks have not been done. 262 + 263 + This method is only present on Dell's G-Series laptops and it's implementation 264 + implies GMODE thermal profile is available, even if operation 0x03 of 265 + Thermal_Information does not list it. 266 + 267 + G-key on Dell's G-Series laptops also changes Game Shift status, so both are 268 + directly related. 269 + 270 + WMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr) 271 + ------------------------------------------------------------- 272 + 273 + :: 274 + 275 + if BYTE_0(arg2) == 0x1: 276 + if is_valid_fan(BYTE_1(arg2)): 277 + argr = 1 278 + else: 279 + argr = 0 280 + 281 + if BYTE_0(arg2) == 0x2: 282 + if is_valid_fan(BYTE_1(arg2)): 283 + if BYTE_2(arg2) == 0: 284 + argr == SENSOR_ID 285 + else 286 + argr == 0xFFFFFFFF 287 + else: 288 + argr = 0 289 + 290 + Overclocking Methods 291 + ==================== 292 + 293 + .. warning:: 294 + These methods have not been tested and are only partially reverse 295 + engineered. 296 + 297 + WMI method Return_OverclockingReport([out] uint32 argr) 298 + ------------------------------------------------------- 299 + 300 + :: 301 + 302 + CSMI (0xE3, 0x99) 303 + argr = 0 304 + 305 + CSMI is an unknown operation. 306 + 307 + WMI method Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr) 308 + ------------------------------------------------------------------- 309 + 310 + :: 311 + 312 + CSMI (0xE3, 0x99) 313 + argr = 0 314 + 315 + CSMI is an unknown operation. 316 + 317 + WMI method Clear_OCFailSafeFlag([out] uint32 argr) 318 + -------------------------------------------------- 319 + 320 + :: 321 + 322 + CSMI (0xE3, 0x99) 323 + argr = 0 324 + 325 + CSMI is an unknown operation. 326 + 327 + 328 + WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) 329 + --------------------------------------------------------------- 330 + 331 + AWCC supports memory overclocking, but this method is very intricate and has 332 + not been deciphered yet. 333 + 334 + GPIO methods 335 + ============ 336 + 337 + These methods are probably related to some kind of firmware update system, 338 + through a GPIO device. 339 + 340 + .. warning:: 341 + These methods have not been tested and are only partially reverse 342 + engineered. 343 + 344 + WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) 345 + ------------------------------------------------------------------ 346 + 347 + :: 348 + 349 + if BYTE_0(arg2) == 0: 350 + if BYTE_1(arg2) == 1: 351 + SET_PIN_A_HIGH() 352 + else: 353 + SET_PIN_A_LOW() 354 + 355 + if BYTE_0(arg2) == 1: 356 + if BYTE_1(arg2) == 1: 357 + SET_PIN_B_HIGH() 358 + 359 + else: 360 + SET_PIN_B_LOW() 361 + 362 + else: 363 + argr = 1 364 + 365 + WMI method ReadTotalofGPIOs([out] uint32 argr) 366 + ---------------------------------------------- 367 + 368 + :: 369 + 370 + argr = 0x02 371 + 372 + WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) 373 + ------------------------------------------------------------------ 374 + 375 + :: 376 + 377 + if BYTE_0(arg2) == 0: 378 + argr = PIN_A_STATUS 379 + 380 + if BYTE_0(arg2) == 1: 381 + argr = PIN_B_STATUS 382 + 383 + Other information Methods 384 + ========================= 385 + 386 + WMI method ReadChassisColor([out] uint32 argr) 387 + ---------------------------------------------- 388 + 389 + :: 390 + 391 + argr = CHASSIS_COLOR_ID 392 + 393 + Acknowledgements 394 + ================ 395 + 396 + Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ for documenting 397 + and testing available thermal profile codes.
+6 -1
Documentation/wmi/driver-development-guide.rst
··· 64 64 .id_table = foo_id_table, 65 65 .probe = foo_probe, 66 66 .remove = foo_remove, /* optional, devres is preferred */ 67 + .shutdown = foo_shutdown, /* optional, called during shutdown */ 67 68 .notify = foo_notify, /* optional, for event handling */ 68 69 .no_notify_data = true, /* optional, enables events containing no additional data */ 69 70 .no_singleton = true, /* required for new WMI drivers */ ··· 79 78 to unregister interfaces to other kernel subsystems and release resources, devres should be used. 80 79 This simplifies error handling during probe and often allows to omit this callback entirely, see 81 80 Documentation/driver-api/driver-model/devres.rst for details. 81 + 82 + The shutdown() callback is called during shutdown, reboot or kexec. Its sole purpose is to disable 83 + the WMI device and put it in a well-known state for the WMI driver to pick up later after reboot 84 + or kexec. Most WMI drivers need no special shutdown handling and can thus omit this callback. 82 85 83 86 Please note that new WMI drivers are required to be able to be instantiated multiple times, 84 87 and are forbidden from using any deprecated GUID-based WMI functions. This means that the ··· 128 123 129 124 The WMI driver core will take care that the notify() callback will only be called after 130 125 the probe() callback has been called, and that no events are being received by the driver 131 - right before and after calling its remove() callback. 126 + right before and after calling its remove() or shutdown() callback. 132 127 133 128 However WMI driver developers should be aware that multiple WMI events can be received concurrently, 134 129 so any locking (if necessary) needs to be provided by the WMI driver itself.
+13 -4
MAINTAINERS
··· 786 786 ALIENWARE WMI DRIVER 787 787 L: Dell.Client.Kernel@dell.com 788 788 S: Maintained 789 + F: Documentation/wmi/devices/alienware-wmi.rst 789 790 F: drivers/platform/x86/dell/alienware-wmi.c 790 791 791 792 ALLEGRO DVT VIDEO IP CORE DRIVER ··· 966 965 F: drivers/infiniband/hw/efa/ 967 966 F: include/uapi/rdma/efa-abi.h 968 967 968 + AMD 3D V-CACHE PERFORMANCE OPTIMIZER DRIVER 969 + M: Basavaraj Natikar <Basavaraj.Natikar@amd.com> 970 + R: Mario Limonciello <mario.limonciello@amd.com> 971 + L: platform-driver-x86@vger.kernel.org 972 + S: Supported 973 + F: Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache 974 + F: drivers/platform/x86/amd/x3d_vcache.c 975 + 969 976 AMD ADDRESS TRANSLATION LIBRARY (ATL) 970 977 M: Yazen Ghannam <Yazen.Ghannam@amd.com> 971 978 L: linux-edac@vger.kernel.org ··· 1083 1074 F: Documentation/arch/x86/amd_hsmp.rst 1084 1075 F: arch/x86/include/asm/amd_hsmp.h 1085 1076 F: arch/x86/include/uapi/asm/amd_hsmp.h 1086 - F: drivers/platform/x86/amd/hsmp.c 1077 + F: drivers/platform/x86/amd/hsmp/ 1087 1078 1088 1079 AMD IOMMU (AMD-VI) 1089 1080 M: Joerg Roedel <joro@8bytes.org> ··· 1133 1124 AMD PMF DRIVER 1134 1125 M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 1135 1126 L: platform-driver-x86@vger.kernel.org 1136 - S: Maintained 1127 + S: Supported 1137 1128 F: Documentation/ABI/testing/sysfs-amd-pmf 1138 1129 F: drivers/platform/x86/amd/pmf/ 1139 1130 ··· 11547 11538 F: drivers/media/pci/intel/ipu6/ 11548 11539 11549 11540 INTEL ISHTP ECLITE DRIVER 11550 - M: Sumesh K Naduvalath <sumesh.k.naduvalath@intel.com> 11541 + M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 11551 11542 L: platform-driver-x86@vger.kernel.org 11552 11543 S: Supported 11553 11544 F: drivers/platform/x86/intel/ishtp_eclite.c ··· 11780 11771 L: platform-driver-x86@vger.kernel.org 11781 11772 S: Maintained 11782 11773 F: Documentation/ABI/testing/debugfs-tpmi 11783 - F: drivers/platform/x86/intel/tpmi.c 11774 + F: drivers/platform/x86/intel/vsec_tpmi.c 11784 11775 F: include/linux/intel_tpmi.h 11785 11776 11786 11777 INTEL UNCORE FREQUENCY CONTROL
+2 -1
arch/x86/include/uapi/asm/amd_hsmp.h
··· 88 88 * 89 89 * Not supported messages would return -ENOMSG. 90 90 */ 91 - static const struct hsmp_msg_desc hsmp_msg_desc_table[] = { 91 + static const struct hsmp_msg_desc hsmp_msg_desc_table[] 92 + __attribute__((unused)) = { 92 93 /* RESERVED */ 93 94 {0, 0, HSMP_RSVD}, 94 95
+18 -1
drivers/platform/surface/surface_aggregator_registry.c
··· 371 371 NULL, 372 372 }; 373 373 374 - /* Devices for Surface Pro 9 and 10 */ 374 + /* Devices for Surface Pro 9 (Intel/x86) and 10 */ 375 375 static const struct software_node *ssam_node_group_sp9[] = { 376 376 &ssam_node_root, 377 377 &ssam_node_hub_kip, ··· 390 390 NULL, 391 391 }; 392 392 393 + /* Devices for Surface Pro 9 5G (ARM/QCOM) */ 394 + static const struct software_node *ssam_node_group_sp9_5g[] = { 395 + &ssam_node_root, 396 + &ssam_node_hub_kip, 397 + &ssam_node_bat_ac, 398 + &ssam_node_bat_main, 399 + &ssam_node_tmp_sensors, 400 + &ssam_node_hid_kip_keyboard, 401 + &ssam_node_hid_kip_penstash, 402 + &ssam_node_hid_kip_touchpad, 403 + &ssam_node_hid_kip_fwupd, 404 + &ssam_node_hid_sam_sensors, 405 + &ssam_node_kip_tablet_switch, 406 + NULL, 407 + }; 393 408 394 409 /* -- SSAM platform/meta-hub driver. ---------------------------------------- */ 395 410 ··· 477 462 MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_acpi_match); 478 463 479 464 static const struct of_device_id ssam_platform_hub_of_match[] __maybe_unused = { 465 + /* Surface Pro 9 5G (ARM/QCOM) */ 466 + { .compatible = "microsoft,arcata", (void *)ssam_node_group_sp9_5g }, 480 467 /* Surface Laptop 7 */ 481 468 { .compatible = "microsoft,romulus13", (void *)ssam_node_group_sl7 }, 482 469 { .compatible = "microsoft,romulus15", (void *)ssam_node_group_sl7 },
+1 -6
drivers/platform/x86/acer-wmi.c
··· 258 258 ACER_WMID_v2, 259 259 }; 260 260 261 - #define ACER_DEFAULT_WIRELESS 0 262 - #define ACER_DEFAULT_BLUETOOTH 0 263 - #define ACER_DEFAULT_MAILLED 0 264 - #define ACER_DEFAULT_THREEG 0 265 - 266 261 static int max_brightness = 0xF; 267 262 268 263 static int mailled = -1; ··· 2636 2641 .pm = &acer_pm, 2637 2642 }, 2638 2643 .probe = acer_platform_probe, 2639 - .remove_new = acer_platform_remove, 2644 + .remove = acer_platform_remove, 2640 2645 .shutdown = acer_platform_shutdown, 2641 2646 }; 2642 2647
+1 -1
drivers/platform/x86/adv_swbutton.c
··· 110 110 .acpi_match_table = button_device_ids, 111 111 }, 112 112 .probe = adv_swbutton_probe, 113 - .remove_new = adv_swbutton_remove, 113 + .remove = adv_swbutton_remove, 114 114 }; 115 115 module_platform_driver(adv_swbutton_driver); 116 116
+9 -9
drivers/platform/x86/amd/Kconfig
··· 3 3 # AMD x86 Platform Specific Drivers 4 4 # 5 5 6 + source "drivers/platform/x86/amd/hsmp/Kconfig" 6 7 source "drivers/platform/x86/amd/pmf/Kconfig" 7 8 source "drivers/platform/x86/amd/pmc/Kconfig" 8 9 9 - config AMD_HSMP 10 - tristate "AMD HSMP Driver" 11 - depends on AMD_NB && X86_64 && ACPI 10 + config AMD_3D_VCACHE 11 + tristate "AMD 3D V-Cache Performance Optimizer Driver" 12 + depends on X86_64 && ACPI 12 13 help 13 - The driver provides a way for user space tools to monitor and manage 14 - system management functionality on EPYC server CPUs from AMD. 15 - 16 - Host System Management Port (HSMP) interface is a mailbox interface 17 - between the x86 core and the System Management Unit (SMU) firmware. 14 + The driver provides a sysfs interface, enabling the setting of a bias 15 + that alters CPU core reordering. This bias prefers cores with higher 16 + frequencies or larger L3 caches on processors supporting AMD 3D V-Cache 17 + technology. 18 18 19 19 If you choose to compile this driver as a module the module will be 20 - called amd_hsmp. 20 + called amd_3d_vcache. 21 21 22 22 config AMD_WBRF 23 23 bool "AMD Wifi RF Band mitigations (WBRF)"
+3 -2
drivers/platform/x86/amd/Makefile
··· 4 4 # AMD x86 Platform-Specific Drivers 5 5 # 6 6 7 + obj-$(CONFIG_AMD_3D_VCACHE) += amd_3d_vcache.o 8 + amd_3d_vcache-objs := x3d_vcache.o 7 9 obj-$(CONFIG_AMD_PMC) += pmc/ 8 - amd_hsmp-y := hsmp.o 9 - obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o 10 + obj-$(CONFIG_AMD_HSMP) += hsmp/ 10 11 obj-$(CONFIG_AMD_PMF) += pmf/ 11 12 obj-$(CONFIG_AMD_WBRF) += wbrf.o
-988
drivers/platform/x86/amd/hsmp.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * AMD HSMP Platform Driver 4 - * Copyright (c) 2022, AMD. 5 - * All Rights Reserved. 6 - * 7 - * This file provides a device implementation for HSMP interface 8 - */ 9 - 10 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 - 12 - #include <asm/amd_hsmp.h> 13 - #include <asm/amd_nb.h> 14 - #include <linux/delay.h> 15 - #include <linux/io.h> 16 - #include <linux/miscdevice.h> 17 - #include <linux/module.h> 18 - #include <linux/pci.h> 19 - #include <linux/platform_device.h> 20 - #include <linux/semaphore.h> 21 - #include <linux/acpi.h> 22 - 23 - #define DRIVER_NAME "amd_hsmp" 24 - #define DRIVER_VERSION "2.2" 25 - #define ACPI_HSMP_DEVICE_HID "AMDI0097" 26 - 27 - /* HSMP Status / Error codes */ 28 - #define HSMP_STATUS_NOT_READY 0x00 29 - #define HSMP_STATUS_OK 0x01 30 - #define HSMP_ERR_INVALID_MSG 0xFE 31 - #define HSMP_ERR_INVALID_INPUT 0xFF 32 - 33 - /* Timeout in millsec */ 34 - #define HSMP_MSG_TIMEOUT 100 35 - #define HSMP_SHORT_SLEEP 1 36 - 37 - #define HSMP_WR true 38 - #define HSMP_RD false 39 - 40 - /* 41 - * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox 42 - * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg. 43 - * Below are required SMN address for HSMP Mailbox register offsets in SMU address space 44 - */ 45 - #define SMN_HSMP_BASE 0x3B00000 46 - #define SMN_HSMP_MSG_ID 0x0010534 47 - #define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934 48 - #define SMN_HSMP_MSG_RESP 0x0010980 49 - #define SMN_HSMP_MSG_DATA 0x00109E0 50 - 51 - #define HSMP_INDEX_REG 0xc4 52 - #define HSMP_DATA_REG 0xc8 53 - 54 - #define HSMP_CDEV_NAME "hsmp_cdev" 55 - #define HSMP_DEVNODE_NAME "hsmp" 56 - #define HSMP_METRICS_TABLE_NAME "metrics_bin" 57 - 58 - #define HSMP_ATTR_GRP_NAME_SIZE 10 59 - 60 - /* These are the strings specified in ACPI table */ 61 - #define MSG_IDOFF_STR "MsgIdOffset" 62 - #define MSG_ARGOFF_STR "MsgArgOffset" 63 - #define MSG_RESPOFF_STR "MsgRspOffset" 64 - 65 - #define MAX_AMD_SOCKETS 8 66 - 67 - struct hsmp_mbaddr_info { 68 - u32 base_addr; 69 - u32 msg_id_off; 70 - u32 msg_resp_off; 71 - u32 msg_arg_off; 72 - u32 size; 73 - }; 74 - 75 - struct hsmp_socket { 76 - struct bin_attribute hsmp_attr; 77 - struct hsmp_mbaddr_info mbinfo; 78 - void __iomem *metric_tbl_addr; 79 - void __iomem *virt_base_addr; 80 - struct semaphore hsmp_sem; 81 - char name[HSMP_ATTR_GRP_NAME_SIZE]; 82 - struct pci_dev *root; 83 - struct device *dev; 84 - u16 sock_ind; 85 - }; 86 - 87 - struct hsmp_plat_device { 88 - struct miscdevice hsmp_device; 89 - struct hsmp_socket *sock; 90 - u32 proto_ver; 91 - u16 num_sockets; 92 - bool is_acpi_device; 93 - bool is_probed; 94 - }; 95 - 96 - static struct hsmp_plat_device plat_dev; 97 - 98 - static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset, 99 - u32 *value, bool write) 100 - { 101 - int ret; 102 - 103 - if (!sock->root) 104 - return -ENODEV; 105 - 106 - ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, 107 - sock->mbinfo.base_addr + offset); 108 - if (ret) 109 - return ret; 110 - 111 - ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value) 112 - : pci_read_config_dword(sock->root, HSMP_DATA_REG, value)); 113 - 114 - return ret; 115 - } 116 - 117 - static void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset, 118 - u32 *value, bool write) 119 - { 120 - if (write) 121 - iowrite32(*value, sock->virt_base_addr + offset); 122 - else 123 - *value = ioread32(sock->virt_base_addr + offset); 124 - } 125 - 126 - static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 offset, 127 - u32 *value, bool write) 128 - { 129 - if (plat_dev.is_acpi_device) 130 - amd_hsmp_acpi_rdwr(sock, offset, value, write); 131 - else 132 - return amd_hsmp_pci_rdwr(sock, offset, value, write); 133 - 134 - return 0; 135 - } 136 - 137 - /* 138 - * Send a message to the HSMP port via PCI-e config space registers 139 - * or by writing to MMIO space. 140 - * 141 - * The caller is expected to zero out any unused arguments. 142 - * If a response is expected, the number of response words should be greater than 0. 143 - * 144 - * Returns 0 for success and populates the requested number of arguments. 145 - * Returns a negative error code for failure. 146 - */ 147 - static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg) 148 - { 149 - struct hsmp_mbaddr_info *mbinfo; 150 - unsigned long timeout, short_sleep; 151 - u32 mbox_status; 152 - u32 index; 153 - int ret; 154 - 155 - mbinfo = &sock->mbinfo; 156 - 157 - /* Clear the status register */ 158 - mbox_status = HSMP_STATUS_NOT_READY; 159 - ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_WR); 160 - if (ret) { 161 - pr_err("Error %d clearing mailbox status register\n", ret); 162 - return ret; 163 - } 164 - 165 - index = 0; 166 - /* Write any message arguments */ 167 - while (index < msg->num_args) { 168 - ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2), 169 - &msg->args[index], HSMP_WR); 170 - if (ret) { 171 - pr_err("Error %d writing message argument %d\n", ret, index); 172 - return ret; 173 - } 174 - index++; 175 - } 176 - 177 - /* Write the message ID which starts the operation */ 178 - ret = amd_hsmp_rdwr(sock, mbinfo->msg_id_off, &msg->msg_id, HSMP_WR); 179 - if (ret) { 180 - pr_err("Error %d writing message ID %u\n", ret, msg->msg_id); 181 - return ret; 182 - } 183 - 184 - /* 185 - * Depending on when the trigger write completes relative to the SMU 186 - * firmware 1 ms cycle, the operation may take from tens of us to 1 ms 187 - * to complete. Some operations may take more. Therefore we will try 188 - * a few short duration sleeps and switch to long sleeps if we don't 189 - * succeed quickly. 190 - */ 191 - short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP); 192 - timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT); 193 - 194 - while (time_before(jiffies, timeout)) { 195 - ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD); 196 - if (ret) { 197 - pr_err("Error %d reading mailbox status\n", ret); 198 - return ret; 199 - } 200 - 201 - if (mbox_status != HSMP_STATUS_NOT_READY) 202 - break; 203 - if (time_before(jiffies, short_sleep)) 204 - usleep_range(50, 100); 205 - else 206 - usleep_range(1000, 2000); 207 - } 208 - 209 - if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) { 210 - return -ETIMEDOUT; 211 - } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) { 212 - return -ENOMSG; 213 - } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) { 214 - return -EINVAL; 215 - } else if (unlikely(mbox_status != HSMP_STATUS_OK)) { 216 - pr_err("Message ID %u unknown failure (status = 0x%X)\n", 217 - msg->msg_id, mbox_status); 218 - return -EIO; 219 - } 220 - 221 - /* 222 - * SMU has responded OK. Read response data. 223 - * SMU reads the input arguments from eight 32 bit registers starting 224 - * from SMN_HSMP_MSG_DATA and writes the response data to the same 225 - * SMN_HSMP_MSG_DATA address. 226 - * We copy the response data if any, back to the args[]. 227 - */ 228 - index = 0; 229 - while (index < msg->response_sz) { 230 - ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2), 231 - &msg->args[index], HSMP_RD); 232 - if (ret) { 233 - pr_err("Error %d reading response %u for message ID:%u\n", 234 - ret, index, msg->msg_id); 235 - break; 236 - } 237 - index++; 238 - } 239 - 240 - return ret; 241 - } 242 - 243 - static int validate_message(struct hsmp_message *msg) 244 - { 245 - /* msg_id against valid range of message IDs */ 246 - if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX) 247 - return -ENOMSG; 248 - 249 - /* msg_id is a reserved message ID */ 250 - if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD) 251 - return -ENOMSG; 252 - 253 - /* num_args and response_sz against the HSMP spec */ 254 - if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args || 255 - msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz) 256 - return -EINVAL; 257 - 258 - return 0; 259 - } 260 - 261 - int hsmp_send_message(struct hsmp_message *msg) 262 - { 263 - struct hsmp_socket *sock; 264 - int ret; 265 - 266 - if (!msg) 267 - return -EINVAL; 268 - ret = validate_message(msg); 269 - if (ret) 270 - return ret; 271 - 272 - if (!plat_dev.sock || msg->sock_ind >= plat_dev.num_sockets) 273 - return -ENODEV; 274 - sock = &plat_dev.sock[msg->sock_ind]; 275 - 276 - /* 277 - * The time taken by smu operation to complete is between 278 - * 10us to 1ms. Sometime it may take more time. 279 - * In SMP system timeout of 100 millisecs should 280 - * be enough for the previous thread to finish the operation 281 - */ 282 - ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT)); 283 - if (ret < 0) 284 - return ret; 285 - 286 - ret = __hsmp_send_message(sock, msg); 287 - 288 - up(&sock->hsmp_sem); 289 - 290 - return ret; 291 - } 292 - EXPORT_SYMBOL_GPL(hsmp_send_message); 293 - 294 - static int hsmp_test(u16 sock_ind, u32 value) 295 - { 296 - struct hsmp_message msg = { 0 }; 297 - int ret; 298 - 299 - /* 300 - * Test the hsmp port by performing TEST command. The test message 301 - * takes one argument and returns the value of that argument + 1. 302 - */ 303 - msg.msg_id = HSMP_TEST; 304 - msg.num_args = 1; 305 - msg.response_sz = 1; 306 - msg.args[0] = value; 307 - msg.sock_ind = sock_ind; 308 - 309 - ret = hsmp_send_message(&msg); 310 - if (ret) 311 - return ret; 312 - 313 - /* Check the response value */ 314 - if (msg.args[0] != (value + 1)) { 315 - dev_err(plat_dev.sock[sock_ind].dev, 316 - "Socket %d test message failed, Expected 0x%08X, received 0x%08X\n", 317 - sock_ind, (value + 1), msg.args[0]); 318 - return -EBADE; 319 - } 320 - 321 - return ret; 322 - } 323 - 324 - static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 325 - { 326 - int __user *arguser = (int __user *)arg; 327 - struct hsmp_message msg = { 0 }; 328 - int ret; 329 - 330 - if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message))) 331 - return -EFAULT; 332 - 333 - /* 334 - * Check msg_id is within the range of supported msg ids 335 - * i.e within the array bounds of hsmp_msg_desc_table 336 - */ 337 - if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX) 338 - return -ENOMSG; 339 - 340 - switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) { 341 - case FMODE_WRITE: 342 - /* 343 - * Device is opened in O_WRONLY mode 344 - * Execute only set/configure commands 345 - */ 346 - if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET) 347 - return -EINVAL; 348 - break; 349 - case FMODE_READ: 350 - /* 351 - * Device is opened in O_RDONLY mode 352 - * Execute only get/monitor commands 353 - */ 354 - if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET) 355 - return -EINVAL; 356 - break; 357 - case FMODE_READ | FMODE_WRITE: 358 - /* 359 - * Device is opened in O_RDWR mode 360 - * Execute both get/monitor and set/configure commands 361 - */ 362 - break; 363 - default: 364 - return -EINVAL; 365 - } 366 - 367 - ret = hsmp_send_message(&msg); 368 - if (ret) 369 - return ret; 370 - 371 - if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) { 372 - /* Copy results back to user for get/monitor commands */ 373 - if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message))) 374 - return -EFAULT; 375 - } 376 - 377 - return 0; 378 - } 379 - 380 - static const struct file_operations hsmp_fops = { 381 - .owner = THIS_MODULE, 382 - .unlocked_ioctl = hsmp_ioctl, 383 - .compat_ioctl = hsmp_ioctl, 384 - }; 385 - 386 - /* This is the UUID used for HSMP */ 387 - static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd, 388 - 0xa6, 0x9f, 0x4e, 0xa2, 389 - 0x87, 0x1f, 0xc2, 0xf6); 390 - 391 - static inline bool is_acpi_hsmp_uuid(union acpi_object *obj) 392 - { 393 - if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE) 394 - return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid); 395 - 396 - return false; 397 - } 398 - 399 - static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind) 400 - { 401 - char *uid; 402 - 403 - /* 404 - * UID (ID00, ID01..IDXX) is used for differentiating sockets, 405 - * read it and strip the "ID" part of it and convert the remaining 406 - * bytes to integer. 407 - */ 408 - uid = acpi_device_uid(ACPI_COMPANION(dev)); 409 - 410 - return kstrtou16(uid + 2, 10, sock_ind); 411 - } 412 - 413 - static acpi_status hsmp_resource(struct acpi_resource *res, void *data) 414 - { 415 - struct hsmp_socket *sock = data; 416 - struct resource r; 417 - 418 - switch (res->type) { 419 - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 420 - if (!acpi_dev_resource_memory(res, &r)) 421 - return AE_ERROR; 422 - if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE)) 423 - return AE_ERROR; 424 - sock->mbinfo.base_addr = r.start; 425 - sock->mbinfo.size = resource_size(&r); 426 - break; 427 - case ACPI_RESOURCE_TYPE_END_TAG: 428 - break; 429 - default: 430 - return AE_ERROR; 431 - } 432 - 433 - return AE_OK; 434 - } 435 - 436 - static int hsmp_read_acpi_dsd(struct hsmp_socket *sock) 437 - { 438 - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 439 - union acpi_object *guid, *mailbox_package; 440 - union acpi_object *dsd; 441 - acpi_status status; 442 - int ret = 0; 443 - int j; 444 - 445 - status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL, 446 - &buf, ACPI_TYPE_PACKAGE); 447 - if (ACPI_FAILURE(status)) { 448 - dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n", 449 - acpi_format_exception(status)); 450 - return -ENODEV; 451 - } 452 - 453 - dsd = buf.pointer; 454 - 455 - /* HSMP _DSD property should contain 2 objects. 456 - * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER 457 - * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE 458 - * This mailbox object contains 3 more acpi objects of type 459 - * ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets 460 - * these packages inturn contain 2 acpi objects of type 461 - * ACPI_TYPE_STRING and ACPI_TYPE_INTEGER 462 - */ 463 - if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) { 464 - ret = -EINVAL; 465 - goto free_buf; 466 - } 467 - 468 - guid = &dsd->package.elements[0]; 469 - mailbox_package = &dsd->package.elements[1]; 470 - if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) { 471 - dev_err(sock->dev, "Invalid hsmp _DSD table data\n"); 472 - ret = -EINVAL; 473 - goto free_buf; 474 - } 475 - 476 - for (j = 0; j < mailbox_package->package.count; j++) { 477 - union acpi_object *msgobj, *msgstr, *msgint; 478 - 479 - msgobj = &mailbox_package->package.elements[j]; 480 - msgstr = &msgobj->package.elements[0]; 481 - msgint = &msgobj->package.elements[1]; 482 - 483 - /* package should have 1 string and 1 integer object */ 484 - if (msgobj->type != ACPI_TYPE_PACKAGE || 485 - msgstr->type != ACPI_TYPE_STRING || 486 - msgint->type != ACPI_TYPE_INTEGER) { 487 - ret = -EINVAL; 488 - goto free_buf; 489 - } 490 - 491 - if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR, 492 - msgstr->string.length)) { 493 - sock->mbinfo.msg_id_off = msgint->integer.value; 494 - } else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR, 495 - msgstr->string.length)) { 496 - sock->mbinfo.msg_resp_off = msgint->integer.value; 497 - } else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR, 498 - msgstr->string.length)) { 499 - sock->mbinfo.msg_arg_off = msgint->integer.value; 500 - } else { 501 - ret = -ENOENT; 502 - goto free_buf; 503 - } 504 - } 505 - 506 - if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off || 507 - !sock->mbinfo.msg_arg_off) 508 - ret = -EINVAL; 509 - 510 - free_buf: 511 - ACPI_FREE(buf.pointer); 512 - return ret; 513 - } 514 - 515 - static int hsmp_read_acpi_crs(struct hsmp_socket *sock) 516 - { 517 - acpi_status status; 518 - 519 - status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS, 520 - hsmp_resource, sock); 521 - if (ACPI_FAILURE(status)) { 522 - dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n", 523 - acpi_format_exception(status)); 524 - return -EINVAL; 525 - } 526 - if (!sock->mbinfo.base_addr || !sock->mbinfo.size) 527 - return -EINVAL; 528 - 529 - /* The mapped region should be un cached */ 530 - sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr, 531 - sock->mbinfo.size); 532 - if (!sock->virt_base_addr) { 533 - dev_err(sock->dev, "Failed to ioremap MP1 base address\n"); 534 - return -ENOMEM; 535 - } 536 - 537 - return 0; 538 - } 539 - 540 - /* Parse the ACPI table to read the data */ 541 - static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind) 542 - { 543 - struct hsmp_socket *sock = &plat_dev.sock[sock_ind]; 544 - int ret; 545 - 546 - sock->sock_ind = sock_ind; 547 - sock->dev = dev; 548 - plat_dev.is_acpi_device = true; 549 - 550 - sema_init(&sock->hsmp_sem, 1); 551 - 552 - /* Read MP1 base address from CRS method */ 553 - ret = hsmp_read_acpi_crs(sock); 554 - if (ret) 555 - return ret; 556 - 557 - /* Read mailbox offsets from DSD table */ 558 - return hsmp_read_acpi_dsd(sock); 559 - } 560 - 561 - static ssize_t hsmp_metric_tbl_read(struct file *filp, struct kobject *kobj, 562 - struct bin_attribute *bin_attr, char *buf, 563 - loff_t off, size_t count) 564 - { 565 - struct hsmp_socket *sock = bin_attr->private; 566 - struct hsmp_message msg = { 0 }; 567 - int ret; 568 - 569 - if (!sock) 570 - return -EINVAL; 571 - 572 - /* Do not support lseek(), reads entire metric table */ 573 - if (count < bin_attr->size) { 574 - dev_err(sock->dev, "Wrong buffer size\n"); 575 - return -EINVAL; 576 - } 577 - 578 - msg.msg_id = HSMP_GET_METRIC_TABLE; 579 - msg.sock_ind = sock->sock_ind; 580 - 581 - ret = hsmp_send_message(&msg); 582 - if (ret) 583 - return ret; 584 - memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size); 585 - 586 - return bin_attr->size; 587 - } 588 - 589 - static int hsmp_get_tbl_dram_base(u16 sock_ind) 590 - { 591 - struct hsmp_socket *sock = &plat_dev.sock[sock_ind]; 592 - struct hsmp_message msg = { 0 }; 593 - phys_addr_t dram_addr; 594 - int ret; 595 - 596 - msg.sock_ind = sock_ind; 597 - msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz; 598 - msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR; 599 - 600 - ret = hsmp_send_message(&msg); 601 - if (ret) 602 - return ret; 603 - 604 - /* 605 - * calculate the metric table DRAM address from lower and upper 32 bits 606 - * sent from SMU and ioremap it to virtual address. 607 - */ 608 - dram_addr = msg.args[0] | ((u64)(msg.args[1]) << 32); 609 - if (!dram_addr) { 610 - dev_err(sock->dev, "Invalid DRAM address for metric table\n"); 611 - return -ENOMEM; 612 - } 613 - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, 614 - sizeof(struct hsmp_metric_table)); 615 - if (!sock->metric_tbl_addr) { 616 - dev_err(sock->dev, "Failed to ioremap metric table addr\n"); 617 - return -ENOMEM; 618 - } 619 - return 0; 620 - } 621 - 622 - static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 623 - struct bin_attribute *battr, int id) 624 - { 625 - if (plat_dev.proto_ver == HSMP_PROTO_VER6) 626 - return battr->attr.mode; 627 - else 628 - return 0; 629 - } 630 - 631 - static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind) 632 - { 633 - struct bin_attribute *hattr = &plat_dev.sock[sock_ind].hsmp_attr; 634 - 635 - sysfs_bin_attr_init(hattr); 636 - hattr->attr.name = HSMP_METRICS_TABLE_NAME; 637 - hattr->attr.mode = 0444; 638 - hattr->read = hsmp_metric_tbl_read; 639 - hattr->size = sizeof(struct hsmp_metric_table); 640 - hattr->private = &plat_dev.sock[sock_ind]; 641 - hattrs[0] = hattr; 642 - 643 - if (plat_dev.proto_ver == HSMP_PROTO_VER6) 644 - return hsmp_get_tbl_dram_base(sock_ind); 645 - else 646 - return 0; 647 - } 648 - 649 - /* One bin sysfs for metrics table */ 650 - #define NUM_HSMP_ATTRS 1 651 - 652 - static int hsmp_create_attr_list(struct attribute_group *attr_grp, 653 - struct device *dev, u16 sock_ind) 654 - { 655 - struct bin_attribute **hsmp_bin_attrs; 656 - 657 - /* Null terminated list of attributes */ 658 - hsmp_bin_attrs = devm_kcalloc(dev, NUM_HSMP_ATTRS + 1, 659 - sizeof(*hsmp_bin_attrs), 660 - GFP_KERNEL); 661 - if (!hsmp_bin_attrs) 662 - return -ENOMEM; 663 - 664 - attr_grp->bin_attrs = hsmp_bin_attrs; 665 - 666 - return hsmp_init_metric_tbl_bin_attr(hsmp_bin_attrs, sock_ind); 667 - } 668 - 669 - static int hsmp_create_non_acpi_sysfs_if(struct device *dev) 670 - { 671 - const struct attribute_group **hsmp_attr_grps; 672 - struct attribute_group *attr_grp; 673 - u16 i; 674 - 675 - hsmp_attr_grps = devm_kcalloc(dev, plat_dev.num_sockets + 1, 676 - sizeof(*hsmp_attr_grps), 677 - GFP_KERNEL); 678 - if (!hsmp_attr_grps) 679 - return -ENOMEM; 680 - 681 - /* Create a sysfs directory for each socket */ 682 - for (i = 0; i < plat_dev.num_sockets; i++) { 683 - attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group), 684 - GFP_KERNEL); 685 - if (!attr_grp) 686 - return -ENOMEM; 687 - 688 - snprintf(plat_dev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i); 689 - attr_grp->name = plat_dev.sock[i].name; 690 - attr_grp->is_bin_visible = hsmp_is_sock_attr_visible; 691 - hsmp_attr_grps[i] = attr_grp; 692 - 693 - hsmp_create_attr_list(attr_grp, dev, i); 694 - } 695 - 696 - return device_add_groups(dev, hsmp_attr_grps); 697 - } 698 - 699 - static int hsmp_create_acpi_sysfs_if(struct device *dev) 700 - { 701 - struct attribute_group *attr_grp; 702 - u16 sock_ind; 703 - int ret; 704 - 705 - attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group), GFP_KERNEL); 706 - if (!attr_grp) 707 - return -ENOMEM; 708 - 709 - attr_grp->is_bin_visible = hsmp_is_sock_attr_visible; 710 - 711 - ret = hsmp_get_uid(dev, &sock_ind); 712 - if (ret) 713 - return ret; 714 - 715 - ret = hsmp_create_attr_list(attr_grp, dev, sock_ind); 716 - if (ret) 717 - return ret; 718 - 719 - return devm_device_add_group(dev, attr_grp); 720 - } 721 - 722 - static int hsmp_cache_proto_ver(u16 sock_ind) 723 - { 724 - struct hsmp_message msg = { 0 }; 725 - int ret; 726 - 727 - msg.msg_id = HSMP_GET_PROTO_VER; 728 - msg.sock_ind = sock_ind; 729 - msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz; 730 - 731 - ret = hsmp_send_message(&msg); 732 - if (!ret) 733 - plat_dev.proto_ver = msg.args[0]; 734 - 735 - return ret; 736 - } 737 - 738 - static inline bool is_f1a_m0h(void) 739 - { 740 - if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F) 741 - return true; 742 - 743 - return false; 744 - } 745 - 746 - static int init_platform_device(struct device *dev) 747 - { 748 - struct hsmp_socket *sock; 749 - int ret, i; 750 - 751 - for (i = 0; i < plat_dev.num_sockets; i++) { 752 - if (!node_to_amd_nb(i)) 753 - return -ENODEV; 754 - sock = &plat_dev.sock[i]; 755 - sock->root = node_to_amd_nb(i)->root; 756 - sock->sock_ind = i; 757 - sock->dev = dev; 758 - sock->mbinfo.base_addr = SMN_HSMP_BASE; 759 - 760 - /* 761 - * This is a transitional change from non-ACPI to ACPI, only 762 - * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI. 763 - */ 764 - if (is_f1a_m0h()) 765 - sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H; 766 - else 767 - sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID; 768 - 769 - sock->mbinfo.msg_resp_off = SMN_HSMP_MSG_RESP; 770 - sock->mbinfo.msg_arg_off = SMN_HSMP_MSG_DATA; 771 - sema_init(&sock->hsmp_sem, 1); 772 - 773 - /* Test the hsmp interface on each socket */ 774 - ret = hsmp_test(i, 0xDEADBEEF); 775 - if (ret) { 776 - dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 777 - boot_cpu_data.x86, boot_cpu_data.x86_model); 778 - dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 779 - return ret; 780 - } 781 - } 782 - 783 - return 0; 784 - } 785 - 786 - static const struct acpi_device_id amd_hsmp_acpi_ids[] = { 787 - {ACPI_HSMP_DEVICE_HID, 0}, 788 - {} 789 - }; 790 - MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids); 791 - 792 - static int hsmp_pltdrv_probe(struct platform_device *pdev) 793 - { 794 - struct acpi_device *adev; 795 - u16 sock_ind = 0; 796 - int ret; 797 - 798 - /* 799 - * On ACPI supported BIOS, there is an ACPI HSMP device added for 800 - * each socket, so the per socket probing, but the memory allocated for 801 - * sockets should be contiguous to access it as an array, 802 - * Hence allocate memory for all the sockets at once instead of allocating 803 - * on each probe. 804 - */ 805 - if (!plat_dev.is_probed) { 806 - plat_dev.sock = devm_kcalloc(&pdev->dev, plat_dev.num_sockets, 807 - sizeof(*plat_dev.sock), 808 - GFP_KERNEL); 809 - if (!plat_dev.sock) 810 - return -ENOMEM; 811 - } 812 - adev = ACPI_COMPANION(&pdev->dev); 813 - if (adev && !acpi_match_device_ids(adev, amd_hsmp_acpi_ids)) { 814 - ret = hsmp_get_uid(&pdev->dev, &sock_ind); 815 - if (ret) 816 - return ret; 817 - if (sock_ind >= plat_dev.num_sockets) 818 - return -EINVAL; 819 - ret = hsmp_parse_acpi_table(&pdev->dev, sock_ind); 820 - if (ret) { 821 - dev_err(&pdev->dev, "Failed to parse ACPI table\n"); 822 - return ret; 823 - } 824 - /* Test the hsmp interface */ 825 - ret = hsmp_test(sock_ind, 0xDEADBEEF); 826 - if (ret) { 827 - dev_err(&pdev->dev, "HSMP test message failed on Fam:%x model:%x\n", 828 - boot_cpu_data.x86, boot_cpu_data.x86_model); 829 - dev_err(&pdev->dev, "Is HSMP disabled in BIOS ?\n"); 830 - return ret; 831 - } 832 - } else { 833 - ret = init_platform_device(&pdev->dev); 834 - if (ret) { 835 - dev_err(&pdev->dev, "Failed to init HSMP mailbox\n"); 836 - return ret; 837 - } 838 - } 839 - 840 - ret = hsmp_cache_proto_ver(sock_ind); 841 - if (ret) { 842 - dev_err(&pdev->dev, "Failed to read HSMP protocol version\n"); 843 - return ret; 844 - } 845 - 846 - if (plat_dev.is_acpi_device) 847 - ret = hsmp_create_acpi_sysfs_if(&pdev->dev); 848 - else 849 - ret = hsmp_create_non_acpi_sysfs_if(&pdev->dev); 850 - if (ret) 851 - dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n"); 852 - 853 - if (!plat_dev.is_probed) { 854 - plat_dev.hsmp_device.name = HSMP_CDEV_NAME; 855 - plat_dev.hsmp_device.minor = MISC_DYNAMIC_MINOR; 856 - plat_dev.hsmp_device.fops = &hsmp_fops; 857 - plat_dev.hsmp_device.parent = &pdev->dev; 858 - plat_dev.hsmp_device.nodename = HSMP_DEVNODE_NAME; 859 - plat_dev.hsmp_device.mode = 0644; 860 - 861 - ret = misc_register(&plat_dev.hsmp_device); 862 - if (ret) 863 - return ret; 864 - 865 - plat_dev.is_probed = true; 866 - } 867 - 868 - return 0; 869 - 870 - } 871 - 872 - static void hsmp_pltdrv_remove(struct platform_device *pdev) 873 - { 874 - /* 875 - * We register only one misc_device even on multi socket system. 876 - * So, deregister should happen only once. 877 - */ 878 - if (plat_dev.is_probed) { 879 - misc_deregister(&plat_dev.hsmp_device); 880 - plat_dev.is_probed = false; 881 - } 882 - } 883 - 884 - static struct platform_driver amd_hsmp_driver = { 885 - .probe = hsmp_pltdrv_probe, 886 - .remove_new = hsmp_pltdrv_remove, 887 - .driver = { 888 - .name = DRIVER_NAME, 889 - .acpi_match_table = amd_hsmp_acpi_ids, 890 - }, 891 - }; 892 - 893 - static struct platform_device *amd_hsmp_platdev; 894 - 895 - static int hsmp_plat_dev_register(void) 896 - { 897 - int ret; 898 - 899 - amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE); 900 - if (!amd_hsmp_platdev) 901 - return -ENOMEM; 902 - 903 - ret = platform_device_add(amd_hsmp_platdev); 904 - if (ret) 905 - platform_device_put(amd_hsmp_platdev); 906 - 907 - return ret; 908 - } 909 - 910 - /* 911 - * This check is only needed for backward compatibility of previous platforms. 912 - * All new platforms are expected to support ACPI based probing. 913 - */ 914 - static bool legacy_hsmp_support(void) 915 - { 916 - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) 917 - return false; 918 - 919 - switch (boot_cpu_data.x86) { 920 - case 0x19: 921 - switch (boot_cpu_data.x86_model) { 922 - case 0x00 ... 0x1F: 923 - case 0x30 ... 0x3F: 924 - case 0x90 ... 0x9F: 925 - case 0xA0 ... 0xAF: 926 - return true; 927 - default: 928 - return false; 929 - } 930 - case 0x1A: 931 - switch (boot_cpu_data.x86_model) { 932 - case 0x00 ... 0x1F: 933 - return true; 934 - default: 935 - return false; 936 - } 937 - default: 938 - return false; 939 - } 940 - 941 - return false; 942 - } 943 - 944 - static int __init hsmp_plt_init(void) 945 - { 946 - int ret = -ENODEV; 947 - 948 - /* 949 - * amd_nb_num() returns number of SMN/DF interfaces present in the system 950 - * if we have N SMN/DF interfaces that ideally means N sockets 951 - */ 952 - plat_dev.num_sockets = amd_nb_num(); 953 - if (plat_dev.num_sockets == 0 || plat_dev.num_sockets > MAX_AMD_SOCKETS) 954 - return ret; 955 - 956 - ret = platform_driver_register(&amd_hsmp_driver); 957 - if (ret) 958 - return ret; 959 - 960 - if (!plat_dev.is_acpi_device) { 961 - if (legacy_hsmp_support()) { 962 - /* Not ACPI device, but supports HSMP, register a plat_dev */ 963 - ret = hsmp_plat_dev_register(); 964 - } else { 965 - /* Not ACPI, Does not support HSMP */ 966 - pr_info("HSMP is not supported on Family:%x model:%x\n", 967 - boot_cpu_data.x86, boot_cpu_data.x86_model); 968 - ret = -ENODEV; 969 - } 970 - if (ret) 971 - platform_driver_unregister(&amd_hsmp_driver); 972 - } 973 - 974 - return ret; 975 - } 976 - 977 - static void __exit hsmp_plt_exit(void) 978 - { 979 - platform_device_unregister(amd_hsmp_platdev); 980 - platform_driver_unregister(&amd_hsmp_driver); 981 - } 982 - 983 - device_initcall(hsmp_plt_init); 984 - module_exit(hsmp_plt_exit); 985 - 986 - MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 987 - MODULE_VERSION(DRIVER_VERSION); 988 - MODULE_LICENSE("GPL v2");
+47
drivers/platform/x86/amd/hsmp/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + # AMD HSMP Driver 4 + # 5 + 6 + config AMD_HSMP 7 + tristate 8 + 9 + menu "AMD HSMP Driver" 10 + depends on AMD_NB || COMPILE_TEST 11 + 12 + config AMD_HSMP_ACPI 13 + tristate "AMD HSMP ACPI device driver" 14 + depends on ACPI 15 + select AMD_HSMP 16 + help 17 + Host System Management Port (HSMP) interface is a mailbox interface 18 + between the x86 core and the System Management Unit (SMU) firmware. 19 + The driver provides a way for user space tools to monitor and manage 20 + system management functionality on EPYC and MI300A server CPUs 21 + from AMD. 22 + 23 + This option supports ACPI based probing. 24 + You may enable this, if your platform BIOS provides an ACPI object 25 + as described in amd_hsmp.rst document. 26 + 27 + If you choose to compile this driver as a module the module will be 28 + called hsmp_acpi. 29 + 30 + config AMD_HSMP_PLAT 31 + tristate "AMD HSMP platform device driver" 32 + select AMD_HSMP 33 + help 34 + Host System Management Port (HSMP) interface is a mailbox interface 35 + between the x86 core and the System Management Unit (SMU) firmware. 36 + The driver provides a way for user space tools to monitor and manage 37 + system management functionality on EPYC and MI300A server CPUs 38 + from AMD. 39 + 40 + This option supports platform device based probing. 41 + You may enable this, if your platform BIOS does not provide 42 + HSMP ACPI object. 43 + 44 + If you choose to compile this driver as a module the module will be 45 + called amd_hsmp. 46 + 47 + endmenu
+12
drivers/platform/x86/amd/hsmp/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile for drivers/platform/x86/amd/hsmp 4 + # AMD HSMP Driver 5 + # 6 + 7 + obj-$(CONFIG_AMD_HSMP) += hsmp_common.o 8 + hsmp_common-objs := hsmp.o 9 + obj-$(CONFIG_AMD_HSMP_PLAT) += amd_hsmp.o 10 + amd_hsmp-objs := plat.o 11 + obj-$(CONFIG_AMD_HSMP_ACPI) += hsmp_acpi.o 12 + hsmp_acpi-objs := acpi.o
+378
drivers/platform/x86/amd/hsmp/acpi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * AMD HSMP Platform Driver 4 + * Copyright (c) 2024, AMD. 5 + * All Rights Reserved. 6 + * 7 + * This file provides an ACPI based driver implementation for HSMP interface. 8 + */ 9 + 10 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 + 12 + #include <asm/amd_hsmp.h> 13 + #include <asm/amd_nb.h> 14 + 15 + #include <linux/acpi.h> 16 + #include <linux/device.h> 17 + #include <linux/dev_printk.h> 18 + #include <linux/ioport.h> 19 + #include <linux/kstrtox.h> 20 + #include <linux/module.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/sysfs.h> 23 + #include <linux/uuid.h> 24 + 25 + #include <uapi/asm-generic/errno-base.h> 26 + 27 + #include "hsmp.h" 28 + 29 + #define DRIVER_NAME "amd_hsmp" 30 + #define DRIVER_VERSION "2.3" 31 + #define ACPI_HSMP_DEVICE_HID "AMDI0097" 32 + 33 + /* These are the strings specified in ACPI table */ 34 + #define MSG_IDOFF_STR "MsgIdOffset" 35 + #define MSG_ARGOFF_STR "MsgArgOffset" 36 + #define MSG_RESPOFF_STR "MsgRspOffset" 37 + 38 + static struct hsmp_plat_device *hsmp_pdev; 39 + 40 + static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset, 41 + u32 *value, bool write) 42 + { 43 + if (write) 44 + iowrite32(*value, sock->virt_base_addr + offset); 45 + else 46 + *value = ioread32(sock->virt_base_addr + offset); 47 + 48 + return 0; 49 + } 50 + 51 + /* This is the UUID used for HSMP */ 52 + static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd, 53 + 0xa6, 0x9f, 0x4e, 0xa2, 54 + 0x87, 0x1f, 0xc2, 0xf6); 55 + 56 + static inline bool is_acpi_hsmp_uuid(union acpi_object *obj) 57 + { 58 + if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE) 59 + return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid); 60 + 61 + return false; 62 + } 63 + 64 + static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind) 65 + { 66 + char *uid; 67 + 68 + /* 69 + * UID (ID00, ID01..IDXX) is used for differentiating sockets, 70 + * read it and strip the "ID" part of it and convert the remaining 71 + * bytes to integer. 72 + */ 73 + uid = acpi_device_uid(ACPI_COMPANION(dev)); 74 + 75 + return kstrtou16(uid + 2, 10, sock_ind); 76 + } 77 + 78 + static acpi_status hsmp_resource(struct acpi_resource *res, void *data) 79 + { 80 + struct hsmp_socket *sock = data; 81 + struct resource r; 82 + 83 + switch (res->type) { 84 + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 85 + if (!acpi_dev_resource_memory(res, &r)) 86 + return AE_ERROR; 87 + if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE)) 88 + return AE_ERROR; 89 + sock->mbinfo.base_addr = r.start; 90 + sock->mbinfo.size = resource_size(&r); 91 + break; 92 + case ACPI_RESOURCE_TYPE_END_TAG: 93 + break; 94 + default: 95 + return AE_ERROR; 96 + } 97 + 98 + return AE_OK; 99 + } 100 + 101 + static int hsmp_read_acpi_dsd(struct hsmp_socket *sock) 102 + { 103 + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 104 + union acpi_object *guid, *mailbox_package; 105 + union acpi_object *dsd; 106 + acpi_status status; 107 + int ret = 0; 108 + int j; 109 + 110 + status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL, 111 + &buf, ACPI_TYPE_PACKAGE); 112 + if (ACPI_FAILURE(status)) { 113 + dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n", 114 + acpi_format_exception(status)); 115 + return -ENODEV; 116 + } 117 + 118 + dsd = buf.pointer; 119 + 120 + /* HSMP _DSD property should contain 2 objects. 121 + * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER 122 + * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE 123 + * This mailbox object contains 3 more acpi objects of type 124 + * ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets 125 + * these packages inturn contain 2 acpi objects of type 126 + * ACPI_TYPE_STRING and ACPI_TYPE_INTEGER 127 + */ 128 + if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) { 129 + ret = -EINVAL; 130 + goto free_buf; 131 + } 132 + 133 + guid = &dsd->package.elements[0]; 134 + mailbox_package = &dsd->package.elements[1]; 135 + if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) { 136 + dev_err(sock->dev, "Invalid hsmp _DSD table data\n"); 137 + ret = -EINVAL; 138 + goto free_buf; 139 + } 140 + 141 + for (j = 0; j < mailbox_package->package.count; j++) { 142 + union acpi_object *msgobj, *msgstr, *msgint; 143 + 144 + msgobj = &mailbox_package->package.elements[j]; 145 + msgstr = &msgobj->package.elements[0]; 146 + msgint = &msgobj->package.elements[1]; 147 + 148 + /* package should have 1 string and 1 integer object */ 149 + if (msgobj->type != ACPI_TYPE_PACKAGE || 150 + msgstr->type != ACPI_TYPE_STRING || 151 + msgint->type != ACPI_TYPE_INTEGER) { 152 + ret = -EINVAL; 153 + goto free_buf; 154 + } 155 + 156 + if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR, 157 + msgstr->string.length)) { 158 + sock->mbinfo.msg_id_off = msgint->integer.value; 159 + } else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR, 160 + msgstr->string.length)) { 161 + sock->mbinfo.msg_resp_off = msgint->integer.value; 162 + } else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR, 163 + msgstr->string.length)) { 164 + sock->mbinfo.msg_arg_off = msgint->integer.value; 165 + } else { 166 + ret = -ENOENT; 167 + goto free_buf; 168 + } 169 + } 170 + 171 + if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off || 172 + !sock->mbinfo.msg_arg_off) 173 + ret = -EINVAL; 174 + 175 + free_buf: 176 + ACPI_FREE(buf.pointer); 177 + return ret; 178 + } 179 + 180 + static int hsmp_read_acpi_crs(struct hsmp_socket *sock) 181 + { 182 + acpi_status status; 183 + 184 + status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS, 185 + hsmp_resource, sock); 186 + if (ACPI_FAILURE(status)) { 187 + dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n", 188 + acpi_format_exception(status)); 189 + return -EINVAL; 190 + } 191 + if (!sock->mbinfo.base_addr || !sock->mbinfo.size) 192 + return -EINVAL; 193 + 194 + /* The mapped region should be un-cached */ 195 + sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr, 196 + sock->mbinfo.size); 197 + if (!sock->virt_base_addr) { 198 + dev_err(sock->dev, "Failed to ioremap MP1 base address\n"); 199 + return -ENOMEM; 200 + } 201 + 202 + return 0; 203 + } 204 + 205 + /* Parse the ACPI table to read the data */ 206 + static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind) 207 + { 208 + struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind]; 209 + int ret; 210 + 211 + sock->sock_ind = sock_ind; 212 + sock->dev = dev; 213 + sock->amd_hsmp_rdwr = amd_hsmp_acpi_rdwr; 214 + 215 + sema_init(&sock->hsmp_sem, 1); 216 + 217 + dev_set_drvdata(dev, sock); 218 + 219 + /* Read MP1 base address from CRS method */ 220 + ret = hsmp_read_acpi_crs(sock); 221 + if (ret) 222 + return ret; 223 + 224 + /* Read mailbox offsets from DSD table */ 225 + return hsmp_read_acpi_dsd(sock); 226 + } 227 + 228 + static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj, 229 + struct bin_attribute *bin_attr, char *buf, 230 + loff_t off, size_t count) 231 + { 232 + struct device *dev = container_of(kobj, struct device, kobj); 233 + struct hsmp_socket *sock = dev_get_drvdata(dev); 234 + 235 + return hsmp_metric_tbl_read(sock, buf, count); 236 + } 237 + 238 + static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 239 + struct bin_attribute *battr, int id) 240 + { 241 + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) 242 + return battr->attr.mode; 243 + 244 + return 0; 245 + } 246 + 247 + static int init_acpi(struct device *dev) 248 + { 249 + u16 sock_ind; 250 + int ret; 251 + 252 + ret = hsmp_get_uid(dev, &sock_ind); 253 + if (ret) 254 + return ret; 255 + if (sock_ind >= hsmp_pdev->num_sockets) 256 + return -EINVAL; 257 + 258 + ret = hsmp_parse_acpi_table(dev, sock_ind); 259 + if (ret) { 260 + dev_err(dev, "Failed to parse ACPI table\n"); 261 + return ret; 262 + } 263 + 264 + /* Test the hsmp interface */ 265 + ret = hsmp_test(sock_ind, 0xDEADBEEF); 266 + if (ret) { 267 + dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 268 + boot_cpu_data.x86, boot_cpu_data.x86_model); 269 + dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 270 + return ret; 271 + } 272 + 273 + ret = hsmp_cache_proto_ver(sock_ind); 274 + if (ret) { 275 + dev_err(dev, "Failed to read HSMP protocol version\n"); 276 + return ret; 277 + } 278 + 279 + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 280 + ret = hsmp_get_tbl_dram_base(sock_ind); 281 + if (ret) 282 + dev_err(dev, "Failed to init metric table\n"); 283 + } 284 + 285 + return ret; 286 + } 287 + 288 + static struct bin_attribute hsmp_metric_tbl_attr = { 289 + .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, 290 + .read = hsmp_metric_tbl_acpi_read, 291 + .size = sizeof(struct hsmp_metric_table), 292 + }; 293 + 294 + static struct bin_attribute *hsmp_attr_list[] = { 295 + &hsmp_metric_tbl_attr, 296 + NULL 297 + }; 298 + 299 + static struct attribute_group hsmp_attr_grp = { 300 + .bin_attrs = hsmp_attr_list, 301 + .is_bin_visible = hsmp_is_sock_attr_visible, 302 + }; 303 + 304 + static const struct attribute_group *hsmp_groups[] = { 305 + &hsmp_attr_grp, 306 + NULL 307 + }; 308 + 309 + static const struct acpi_device_id amd_hsmp_acpi_ids[] = { 310 + {ACPI_HSMP_DEVICE_HID, 0}, 311 + {} 312 + }; 313 + MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids); 314 + 315 + static int hsmp_acpi_probe(struct platform_device *pdev) 316 + { 317 + int ret; 318 + 319 + hsmp_pdev = get_hsmp_pdev(); 320 + if (!hsmp_pdev) 321 + return -ENOMEM; 322 + 323 + if (!hsmp_pdev->is_probed) { 324 + hsmp_pdev->num_sockets = amd_nb_num(); 325 + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) 326 + return -ENODEV; 327 + 328 + hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, 329 + sizeof(*hsmp_pdev->sock), 330 + GFP_KERNEL); 331 + if (!hsmp_pdev->sock) 332 + return -ENOMEM; 333 + } 334 + 335 + ret = init_acpi(&pdev->dev); 336 + if (ret) { 337 + dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n"); 338 + return ret; 339 + } 340 + 341 + if (!hsmp_pdev->is_probed) { 342 + ret = hsmp_misc_register(&pdev->dev); 343 + if (ret) 344 + return ret; 345 + hsmp_pdev->is_probed = true; 346 + } 347 + 348 + return 0; 349 + } 350 + 351 + static void hsmp_acpi_remove(struct platform_device *pdev) 352 + { 353 + /* 354 + * We register only one misc_device even on multi-socket system. 355 + * So, deregister should happen only once. 356 + */ 357 + if (hsmp_pdev->is_probed) { 358 + hsmp_misc_deregister(); 359 + hsmp_pdev->is_probed = false; 360 + } 361 + } 362 + 363 + static struct platform_driver amd_hsmp_driver = { 364 + .probe = hsmp_acpi_probe, 365 + .remove = hsmp_acpi_remove, 366 + .driver = { 367 + .name = DRIVER_NAME, 368 + .acpi_match_table = amd_hsmp_acpi_ids, 369 + .dev_groups = hsmp_groups, 370 + }, 371 + }; 372 + 373 + module_platform_driver(amd_hsmp_driver); 374 + 375 + MODULE_IMPORT_NS(AMD_HSMP); 376 + MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 377 + MODULE_VERSION(DRIVER_VERSION); 378 + MODULE_LICENSE("GPL");
+408
drivers/platform/x86/amd/hsmp/hsmp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * AMD HSMP Platform Driver 4 + * Copyright (c) 2022, AMD. 5 + * All Rights Reserved. 6 + * 7 + * This file provides a device implementation for HSMP interface 8 + */ 9 + 10 + #include <asm/amd_hsmp.h> 11 + #include <asm/amd_nb.h> 12 + 13 + #include <linux/acpi.h> 14 + #include <linux/delay.h> 15 + #include <linux/device.h> 16 + #include <linux/semaphore.h> 17 + #include <linux/sysfs.h> 18 + 19 + #include "hsmp.h" 20 + 21 + /* HSMP Status / Error codes */ 22 + #define HSMP_STATUS_NOT_READY 0x00 23 + #define HSMP_STATUS_OK 0x01 24 + #define HSMP_ERR_INVALID_MSG 0xFE 25 + #define HSMP_ERR_INVALID_INPUT 0xFF 26 + #define HSMP_ERR_PREREQ_NOT_SATISFIED 0xFD 27 + #define HSMP_ERR_SMU_BUSY 0xFC 28 + 29 + /* Timeout in millsec */ 30 + #define HSMP_MSG_TIMEOUT 100 31 + #define HSMP_SHORT_SLEEP 1 32 + 33 + #define HSMP_WR true 34 + #define HSMP_RD false 35 + 36 + #define DRIVER_VERSION "2.3" 37 + 38 + static struct hsmp_plat_device hsmp_pdev; 39 + 40 + /* 41 + * Send a message to the HSMP port via PCI-e config space registers 42 + * or by writing to MMIO space. 43 + * 44 + * The caller is expected to zero out any unused arguments. 45 + * If a response is expected, the number of response words should be greater than 0. 46 + * 47 + * Returns 0 for success and populates the requested number of arguments. 48 + * Returns a negative error code for failure. 49 + */ 50 + static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg) 51 + { 52 + struct hsmp_mbaddr_info *mbinfo; 53 + unsigned long timeout, short_sleep; 54 + u32 mbox_status; 55 + u32 index; 56 + int ret; 57 + 58 + mbinfo = &sock->mbinfo; 59 + 60 + /* Clear the status register */ 61 + mbox_status = HSMP_STATUS_NOT_READY; 62 + ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_WR); 63 + if (ret) { 64 + dev_err(sock->dev, "Error %d clearing mailbox status register\n", ret); 65 + return ret; 66 + } 67 + 68 + index = 0; 69 + /* Write any message arguments */ 70 + while (index < msg->num_args) { 71 + ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2), 72 + &msg->args[index], HSMP_WR); 73 + if (ret) { 74 + dev_err(sock->dev, "Error %d writing message argument %d\n", ret, index); 75 + return ret; 76 + } 77 + index++; 78 + } 79 + 80 + /* Write the message ID which starts the operation */ 81 + ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_id_off, &msg->msg_id, HSMP_WR); 82 + if (ret) { 83 + dev_err(sock->dev, "Error %d writing message ID %u\n", ret, msg->msg_id); 84 + return ret; 85 + } 86 + 87 + /* 88 + * Depending on when the trigger write completes relative to the SMU 89 + * firmware 1 ms cycle, the operation may take from tens of us to 1 ms 90 + * to complete. Some operations may take more. Therefore we will try 91 + * a few short duration sleeps and switch to long sleeps if we don't 92 + * succeed quickly. 93 + */ 94 + short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP); 95 + timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT); 96 + 97 + while (time_before(jiffies, timeout)) { 98 + ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD); 99 + if (ret) { 100 + dev_err(sock->dev, "Error %d reading mailbox status\n", ret); 101 + return ret; 102 + } 103 + 104 + if (mbox_status != HSMP_STATUS_NOT_READY) 105 + break; 106 + if (time_before(jiffies, short_sleep)) 107 + usleep_range(50, 100); 108 + else 109 + usleep_range(1000, 2000); 110 + } 111 + 112 + if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) { 113 + dev_err(sock->dev, "Message ID 0x%X failure : SMU tmeout (status = 0x%X)\n", 114 + msg->msg_id, mbox_status); 115 + return -ETIMEDOUT; 116 + } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) { 117 + dev_err(sock->dev, "Message ID 0x%X failure : Invalid message (status = 0x%X)\n", 118 + msg->msg_id, mbox_status); 119 + return -ENOMSG; 120 + } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) { 121 + dev_err(sock->dev, "Message ID 0x%X failure : Invalid arguments (status = 0x%X)\n", 122 + msg->msg_id, mbox_status); 123 + return -EINVAL; 124 + } else if (unlikely(mbox_status == HSMP_ERR_PREREQ_NOT_SATISFIED)) { 125 + dev_err(sock->dev, "Message ID 0x%X failure : Prerequisite not satisfied (status = 0x%X)\n", 126 + msg->msg_id, mbox_status); 127 + return -EREMOTEIO; 128 + } else if (unlikely(mbox_status == HSMP_ERR_SMU_BUSY)) { 129 + dev_err(sock->dev, "Message ID 0x%X failure : SMU BUSY (status = 0x%X)\n", 130 + msg->msg_id, mbox_status); 131 + return -EBUSY; 132 + } else if (unlikely(mbox_status != HSMP_STATUS_OK)) { 133 + dev_err(sock->dev, "Message ID 0x%X unknown failure (status = 0x%X)\n", 134 + msg->msg_id, mbox_status); 135 + return -EIO; 136 + } 137 + 138 + /* 139 + * SMU has responded OK. Read response data. 140 + * SMU reads the input arguments from eight 32 bit registers starting 141 + * from SMN_HSMP_MSG_DATA and writes the response data to the same 142 + * SMN_HSMP_MSG_DATA address. 143 + * We copy the response data if any, back to the args[]. 144 + */ 145 + index = 0; 146 + while (index < msg->response_sz) { 147 + ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2), 148 + &msg->args[index], HSMP_RD); 149 + if (ret) { 150 + dev_err(sock->dev, "Error %d reading response %u for message ID:%u\n", 151 + ret, index, msg->msg_id); 152 + break; 153 + } 154 + index++; 155 + } 156 + 157 + return ret; 158 + } 159 + 160 + static int validate_message(struct hsmp_message *msg) 161 + { 162 + /* msg_id against valid range of message IDs */ 163 + if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX) 164 + return -ENOMSG; 165 + 166 + /* msg_id is a reserved message ID */ 167 + if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD) 168 + return -ENOMSG; 169 + 170 + /* num_args and response_sz against the HSMP spec */ 171 + if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args || 172 + msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz) 173 + return -EINVAL; 174 + 175 + return 0; 176 + } 177 + 178 + int hsmp_send_message(struct hsmp_message *msg) 179 + { 180 + struct hsmp_socket *sock; 181 + int ret; 182 + 183 + if (!msg) 184 + return -EINVAL; 185 + ret = validate_message(msg); 186 + if (ret) 187 + return ret; 188 + 189 + if (!hsmp_pdev.sock || msg->sock_ind >= hsmp_pdev.num_sockets) 190 + return -ENODEV; 191 + sock = &hsmp_pdev.sock[msg->sock_ind]; 192 + 193 + /* 194 + * The time taken by smu operation to complete is between 195 + * 10us to 1ms. Sometime it may take more time. 196 + * In SMP system timeout of 100 millisecs should 197 + * be enough for the previous thread to finish the operation 198 + */ 199 + ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT)); 200 + if (ret < 0) 201 + return ret; 202 + 203 + ret = __hsmp_send_message(sock, msg); 204 + 205 + up(&sock->hsmp_sem); 206 + 207 + return ret; 208 + } 209 + EXPORT_SYMBOL_NS_GPL(hsmp_send_message, AMD_HSMP); 210 + 211 + int hsmp_test(u16 sock_ind, u32 value) 212 + { 213 + struct hsmp_message msg = { 0 }; 214 + int ret; 215 + 216 + /* 217 + * Test the hsmp port by performing TEST command. The test message 218 + * takes one argument and returns the value of that argument + 1. 219 + */ 220 + msg.msg_id = HSMP_TEST; 221 + msg.num_args = 1; 222 + msg.response_sz = 1; 223 + msg.args[0] = value; 224 + msg.sock_ind = sock_ind; 225 + 226 + ret = hsmp_send_message(&msg); 227 + if (ret) 228 + return ret; 229 + 230 + /* Check the response value */ 231 + if (msg.args[0] != (value + 1)) { 232 + dev_err(hsmp_pdev.sock[sock_ind].dev, 233 + "Socket %d test message failed, Expected 0x%08X, received 0x%08X\n", 234 + sock_ind, (value + 1), msg.args[0]); 235 + return -EBADE; 236 + } 237 + 238 + return ret; 239 + } 240 + EXPORT_SYMBOL_NS_GPL(hsmp_test, AMD_HSMP); 241 + 242 + long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 243 + { 244 + int __user *arguser = (int __user *)arg; 245 + struct hsmp_message msg = { 0 }; 246 + int ret; 247 + 248 + if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message))) 249 + return -EFAULT; 250 + 251 + /* 252 + * Check msg_id is within the range of supported msg ids 253 + * i.e within the array bounds of hsmp_msg_desc_table 254 + */ 255 + if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX) 256 + return -ENOMSG; 257 + 258 + switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) { 259 + case FMODE_WRITE: 260 + /* 261 + * Device is opened in O_WRONLY mode 262 + * Execute only set/configure commands 263 + */ 264 + if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET) 265 + return -EPERM; 266 + break; 267 + case FMODE_READ: 268 + /* 269 + * Device is opened in O_RDONLY mode 270 + * Execute only get/monitor commands 271 + */ 272 + if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET) 273 + return -EPERM; 274 + break; 275 + case FMODE_READ | FMODE_WRITE: 276 + /* 277 + * Device is opened in O_RDWR mode 278 + * Execute both get/monitor and set/configure commands 279 + */ 280 + break; 281 + default: 282 + return -EPERM; 283 + } 284 + 285 + ret = hsmp_send_message(&msg); 286 + if (ret) 287 + return ret; 288 + 289 + if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) { 290 + /* Copy results back to user for get/monitor commands */ 291 + if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message))) 292 + return -EFAULT; 293 + } 294 + 295 + return 0; 296 + } 297 + 298 + ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) 299 + { 300 + struct hsmp_message msg = { 0 }; 301 + int ret; 302 + 303 + if (!sock || !buf) 304 + return -EINVAL; 305 + 306 + /* Do not support lseek(), also don't allow more than the size of metric table */ 307 + if (size != sizeof(struct hsmp_metric_table)) { 308 + dev_err(sock->dev, "Wrong buffer size\n"); 309 + return -EINVAL; 310 + } 311 + 312 + msg.msg_id = HSMP_GET_METRIC_TABLE; 313 + msg.sock_ind = sock->sock_ind; 314 + 315 + ret = hsmp_send_message(&msg); 316 + if (ret) 317 + return ret; 318 + memcpy_fromio(buf, sock->metric_tbl_addr, size); 319 + 320 + return size; 321 + } 322 + EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, AMD_HSMP); 323 + 324 + int hsmp_get_tbl_dram_base(u16 sock_ind) 325 + { 326 + struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind]; 327 + struct hsmp_message msg = { 0 }; 328 + phys_addr_t dram_addr; 329 + int ret; 330 + 331 + msg.sock_ind = sock_ind; 332 + msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz; 333 + msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR; 334 + 335 + ret = hsmp_send_message(&msg); 336 + if (ret) 337 + return ret; 338 + 339 + /* 340 + * calculate the metric table DRAM address from lower and upper 32 bits 341 + * sent from SMU and ioremap it to virtual address. 342 + */ 343 + dram_addr = msg.args[0] | ((u64)(msg.args[1]) << 32); 344 + if (!dram_addr) { 345 + dev_err(sock->dev, "Invalid DRAM address for metric table\n"); 346 + return -ENOMEM; 347 + } 348 + sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, 349 + sizeof(struct hsmp_metric_table)); 350 + if (!sock->metric_tbl_addr) { 351 + dev_err(sock->dev, "Failed to ioremap metric table addr\n"); 352 + return -ENOMEM; 353 + } 354 + return 0; 355 + } 356 + EXPORT_SYMBOL_NS_GPL(hsmp_get_tbl_dram_base, AMD_HSMP); 357 + 358 + int hsmp_cache_proto_ver(u16 sock_ind) 359 + { 360 + struct hsmp_message msg = { 0 }; 361 + int ret; 362 + 363 + msg.msg_id = HSMP_GET_PROTO_VER; 364 + msg.sock_ind = sock_ind; 365 + msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz; 366 + 367 + ret = hsmp_send_message(&msg); 368 + if (!ret) 369 + hsmp_pdev.proto_ver = msg.args[0]; 370 + 371 + return ret; 372 + } 373 + EXPORT_SYMBOL_NS_GPL(hsmp_cache_proto_ver, AMD_HSMP); 374 + 375 + static const struct file_operations hsmp_fops = { 376 + .owner = THIS_MODULE, 377 + .unlocked_ioctl = hsmp_ioctl, 378 + .compat_ioctl = hsmp_ioctl, 379 + }; 380 + 381 + int hsmp_misc_register(struct device *dev) 382 + { 383 + hsmp_pdev.mdev.name = HSMP_CDEV_NAME; 384 + hsmp_pdev.mdev.minor = MISC_DYNAMIC_MINOR; 385 + hsmp_pdev.mdev.fops = &hsmp_fops; 386 + hsmp_pdev.mdev.parent = dev; 387 + hsmp_pdev.mdev.nodename = HSMP_DEVNODE_NAME; 388 + hsmp_pdev.mdev.mode = 0644; 389 + 390 + return misc_register(&hsmp_pdev.mdev); 391 + } 392 + EXPORT_SYMBOL_NS_GPL(hsmp_misc_register, AMD_HSMP); 393 + 394 + void hsmp_misc_deregister(void) 395 + { 396 + misc_deregister(&hsmp_pdev.mdev); 397 + } 398 + EXPORT_SYMBOL_NS_GPL(hsmp_misc_deregister, AMD_HSMP); 399 + 400 + struct hsmp_plat_device *get_hsmp_pdev(void) 401 + { 402 + return &hsmp_pdev; 403 + } 404 + EXPORT_SYMBOL_NS_GPL(get_hsmp_pdev, AMD_HSMP); 405 + 406 + MODULE_DESCRIPTION("AMD HSMP Common driver"); 407 + MODULE_VERSION(DRIVER_VERSION); 408 + MODULE_LICENSE("GPL");
+66
drivers/platform/x86/amd/hsmp/hsmp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * AMD HSMP Platform Driver 4 + * Copyright (c) 2024, AMD. 5 + * All Rights Reserved. 6 + * 7 + * Header file for HSMP driver 8 + */ 9 + 10 + #ifndef HSMP_H 11 + #define HSMP_H 12 + 13 + #include <linux/compiler_types.h> 14 + #include <linux/device.h> 15 + #include <linux/miscdevice.h> 16 + #include <linux/pci.h> 17 + #include <linux/semaphore.h> 18 + #include <linux/sysfs.h> 19 + 20 + #define HSMP_METRICS_TABLE_NAME "metrics_bin" 21 + 22 + #define HSMP_ATTR_GRP_NAME_SIZE 10 23 + 24 + #define MAX_AMD_SOCKETS 8 25 + 26 + #define HSMP_CDEV_NAME "hsmp_cdev" 27 + #define HSMP_DEVNODE_NAME "hsmp" 28 + 29 + struct hsmp_mbaddr_info { 30 + u32 base_addr; 31 + u32 msg_id_off; 32 + u32 msg_resp_off; 33 + u32 msg_arg_off; 34 + u32 size; 35 + }; 36 + 37 + struct hsmp_socket { 38 + struct bin_attribute hsmp_attr; 39 + struct hsmp_mbaddr_info mbinfo; 40 + void __iomem *metric_tbl_addr; 41 + void __iomem *virt_base_addr; 42 + struct semaphore hsmp_sem; 43 + char name[HSMP_ATTR_GRP_NAME_SIZE]; 44 + struct pci_dev *root; 45 + struct device *dev; 46 + u16 sock_ind; 47 + int (*amd_hsmp_rdwr)(struct hsmp_socket *sock, u32 off, u32 *val, bool rw); 48 + }; 49 + 50 + struct hsmp_plat_device { 51 + struct miscdevice mdev; 52 + struct hsmp_socket *sock; 53 + u32 proto_ver; 54 + u16 num_sockets; 55 + bool is_probed; 56 + }; 57 + 58 + int hsmp_cache_proto_ver(u16 sock_ind); 59 + int hsmp_test(u16 sock_ind, u32 value); 60 + long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); 61 + void hsmp_misc_deregister(void); 62 + int hsmp_misc_register(struct device *dev); 63 + int hsmp_get_tbl_dram_base(u16 sock_ind); 64 + ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size); 65 + struct hsmp_plat_device *get_hsmp_pdev(void); 66 + #endif /* HSMP_H */
+338
drivers/platform/x86/amd/hsmp/plat.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * AMD HSMP Platform Driver 4 + * Copyright (c) 2024, AMD. 5 + * All Rights Reserved. 6 + * 7 + * This file provides platform device implementations. 8 + */ 9 + 10 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 + 12 + #include <asm/amd_hsmp.h> 13 + #include <asm/amd_nb.h> 14 + 15 + #include <linux/device.h> 16 + #include <linux/module.h> 17 + #include <linux/pci.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/sysfs.h> 20 + 21 + #include "hsmp.h" 22 + 23 + #define DRIVER_NAME "amd_hsmp" 24 + #define DRIVER_VERSION "2.3" 25 + 26 + /* 27 + * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox 28 + * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg. 29 + * Below are required SMN address for HSMP Mailbox register offsets in SMU address space 30 + */ 31 + #define SMN_HSMP_BASE 0x3B00000 32 + #define SMN_HSMP_MSG_ID 0x0010534 33 + #define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934 34 + #define SMN_HSMP_MSG_RESP 0x0010980 35 + #define SMN_HSMP_MSG_DATA 0x00109E0 36 + 37 + #define HSMP_INDEX_REG 0xc4 38 + #define HSMP_DATA_REG 0xc8 39 + 40 + static struct hsmp_plat_device *hsmp_pdev; 41 + 42 + static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset, 43 + u32 *value, bool write) 44 + { 45 + int ret; 46 + 47 + if (!sock->root) 48 + return -ENODEV; 49 + 50 + ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, 51 + sock->mbinfo.base_addr + offset); 52 + if (ret) 53 + return ret; 54 + 55 + ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value) 56 + : pci_read_config_dword(sock->root, HSMP_DATA_REG, value)); 57 + 58 + return ret; 59 + } 60 + 61 + static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj, 62 + struct bin_attribute *bin_attr, char *buf, 63 + loff_t off, size_t count) 64 + { 65 + struct hsmp_socket *sock; 66 + u16 sock_ind; 67 + 68 + sock_ind = (uintptr_t)bin_attr->private; 69 + if (sock_ind >= hsmp_pdev->num_sockets) 70 + return -EINVAL; 71 + 72 + sock = &hsmp_pdev->sock[sock_ind]; 73 + 74 + return hsmp_metric_tbl_read(sock, buf, count); 75 + } 76 + 77 + static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 78 + struct bin_attribute *battr, int id) 79 + { 80 + u16 sock_ind; 81 + 82 + sock_ind = (uintptr_t)battr->private; 83 + 84 + if (id == 0 && sock_ind >= hsmp_pdev->num_sockets) 85 + return SYSFS_GROUP_INVISIBLE; 86 + 87 + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) 88 + return battr->attr.mode; 89 + 90 + return 0; 91 + } 92 + 93 + /* 94 + * AMD supports maximum of 8 sockets in a system. 95 + * Static array of 8 + 1(for NULL) elements is created below 96 + * to create sysfs groups for sockets. 97 + * is_bin_visible function is used to show / hide the necessary groups. 98 + */ 99 + #define HSMP_BIN_ATTR(index, _list) \ 100 + static struct bin_attribute attr##index = { \ 101 + .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ 102 + .private = (void *)index, \ 103 + .read = hsmp_metric_tbl_plat_read, \ 104 + .size = sizeof(struct hsmp_metric_table), \ 105 + }; \ 106 + static struct bin_attribute _list[] = { \ 107 + &attr##index, \ 108 + NULL \ 109 + } 110 + 111 + HSMP_BIN_ATTR(0, *sock0_attr_list); 112 + HSMP_BIN_ATTR(1, *sock1_attr_list); 113 + HSMP_BIN_ATTR(2, *sock2_attr_list); 114 + HSMP_BIN_ATTR(3, *sock3_attr_list); 115 + HSMP_BIN_ATTR(4, *sock4_attr_list); 116 + HSMP_BIN_ATTR(5, *sock5_attr_list); 117 + HSMP_BIN_ATTR(6, *sock6_attr_list); 118 + HSMP_BIN_ATTR(7, *sock7_attr_list); 119 + 120 + #define HSMP_BIN_ATTR_GRP(index, _list, _name) \ 121 + static struct attribute_group sock##index##_attr_grp = { \ 122 + .bin_attrs = _list, \ 123 + .is_bin_visible = hsmp_is_sock_attr_visible, \ 124 + .name = #_name, \ 125 + } 126 + 127 + HSMP_BIN_ATTR_GRP(0, sock0_attr_list, socket0); 128 + HSMP_BIN_ATTR_GRP(1, sock1_attr_list, socket1); 129 + HSMP_BIN_ATTR_GRP(2, sock2_attr_list, socket2); 130 + HSMP_BIN_ATTR_GRP(3, sock3_attr_list, socket3); 131 + HSMP_BIN_ATTR_GRP(4, sock4_attr_list, socket4); 132 + HSMP_BIN_ATTR_GRP(5, sock5_attr_list, socket5); 133 + HSMP_BIN_ATTR_GRP(6, sock6_attr_list, socket6); 134 + HSMP_BIN_ATTR_GRP(7, sock7_attr_list, socket7); 135 + 136 + static const struct attribute_group *hsmp_groups[] = { 137 + &sock0_attr_grp, 138 + &sock1_attr_grp, 139 + &sock2_attr_grp, 140 + &sock3_attr_grp, 141 + &sock4_attr_grp, 142 + &sock5_attr_grp, 143 + &sock6_attr_grp, 144 + &sock7_attr_grp, 145 + NULL 146 + }; 147 + 148 + static inline bool is_f1a_m0h(void) 149 + { 150 + if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F) 151 + return true; 152 + 153 + return false; 154 + } 155 + 156 + static int init_platform_device(struct device *dev) 157 + { 158 + struct hsmp_socket *sock; 159 + int ret, i; 160 + 161 + for (i = 0; i < hsmp_pdev->num_sockets; i++) { 162 + if (!node_to_amd_nb(i)) 163 + return -ENODEV; 164 + sock = &hsmp_pdev->sock[i]; 165 + sock->root = node_to_amd_nb(i)->root; 166 + sock->sock_ind = i; 167 + sock->dev = dev; 168 + sock->mbinfo.base_addr = SMN_HSMP_BASE; 169 + sock->amd_hsmp_rdwr = amd_hsmp_pci_rdwr; 170 + 171 + /* 172 + * This is a transitional change from non-ACPI to ACPI, only 173 + * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI. 174 + */ 175 + if (is_f1a_m0h()) 176 + sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H; 177 + else 178 + sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID; 179 + 180 + sock->mbinfo.msg_resp_off = SMN_HSMP_MSG_RESP; 181 + sock->mbinfo.msg_arg_off = SMN_HSMP_MSG_DATA; 182 + sema_init(&sock->hsmp_sem, 1); 183 + 184 + /* Test the hsmp interface on each socket */ 185 + ret = hsmp_test(i, 0xDEADBEEF); 186 + if (ret) { 187 + dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 188 + boot_cpu_data.x86, boot_cpu_data.x86_model); 189 + dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 190 + return ret; 191 + } 192 + 193 + ret = hsmp_cache_proto_ver(i); 194 + if (ret) { 195 + dev_err(dev, "Failed to read HSMP protocol version\n"); 196 + return ret; 197 + } 198 + 199 + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 200 + ret = hsmp_get_tbl_dram_base(i); 201 + if (ret) 202 + dev_err(dev, "Failed to init metric table\n"); 203 + } 204 + } 205 + 206 + return 0; 207 + } 208 + 209 + static int hsmp_pltdrv_probe(struct platform_device *pdev) 210 + { 211 + int ret; 212 + 213 + hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, 214 + sizeof(*hsmp_pdev->sock), 215 + GFP_KERNEL); 216 + if (!hsmp_pdev->sock) 217 + return -ENOMEM; 218 + 219 + ret = init_platform_device(&pdev->dev); 220 + if (ret) { 221 + dev_err(&pdev->dev, "Failed to init HSMP mailbox\n"); 222 + return ret; 223 + } 224 + 225 + return hsmp_misc_register(&pdev->dev); 226 + } 227 + 228 + static void hsmp_pltdrv_remove(struct platform_device *pdev) 229 + { 230 + hsmp_misc_deregister(); 231 + } 232 + 233 + static struct platform_driver amd_hsmp_driver = { 234 + .probe = hsmp_pltdrv_probe, 235 + .remove = hsmp_pltdrv_remove, 236 + .driver = { 237 + .name = DRIVER_NAME, 238 + .dev_groups = hsmp_groups, 239 + }, 240 + }; 241 + 242 + static struct platform_device *amd_hsmp_platdev; 243 + 244 + static int hsmp_plat_dev_register(void) 245 + { 246 + int ret; 247 + 248 + amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE); 249 + if (!amd_hsmp_platdev) 250 + return -ENOMEM; 251 + 252 + ret = platform_device_add(amd_hsmp_platdev); 253 + if (ret) 254 + platform_device_put(amd_hsmp_platdev); 255 + 256 + return ret; 257 + } 258 + 259 + /* 260 + * This check is only needed for backward compatibility of previous platforms. 261 + * All new platforms are expected to support ACPI based probing. 262 + */ 263 + static bool legacy_hsmp_support(void) 264 + { 265 + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) 266 + return false; 267 + 268 + switch (boot_cpu_data.x86) { 269 + case 0x19: 270 + switch (boot_cpu_data.x86_model) { 271 + case 0x00 ... 0x1F: 272 + case 0x30 ... 0x3F: 273 + case 0x90 ... 0x9F: 274 + case 0xA0 ... 0xAF: 275 + return true; 276 + default: 277 + return false; 278 + } 279 + case 0x1A: 280 + switch (boot_cpu_data.x86_model) { 281 + case 0x00 ... 0x1F: 282 + return true; 283 + default: 284 + return false; 285 + } 286 + default: 287 + return false; 288 + } 289 + 290 + return false; 291 + } 292 + 293 + static int __init hsmp_plt_init(void) 294 + { 295 + int ret = -ENODEV; 296 + 297 + if (!legacy_hsmp_support()) { 298 + pr_info("HSMP is not supported on Family:%x model:%x\n", 299 + boot_cpu_data.x86, boot_cpu_data.x86_model); 300 + return ret; 301 + } 302 + 303 + hsmp_pdev = get_hsmp_pdev(); 304 + if (!hsmp_pdev) 305 + return -ENOMEM; 306 + 307 + /* 308 + * amd_nb_num() returns number of SMN/DF interfaces present in the system 309 + * if we have N SMN/DF interfaces that ideally means N sockets 310 + */ 311 + hsmp_pdev->num_sockets = amd_nb_num(); 312 + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) 313 + return ret; 314 + 315 + ret = platform_driver_register(&amd_hsmp_driver); 316 + if (ret) 317 + return ret; 318 + 319 + ret = hsmp_plat_dev_register(); 320 + if (ret) 321 + platform_driver_unregister(&amd_hsmp_driver); 322 + 323 + return ret; 324 + } 325 + 326 + static void __exit hsmp_plt_exit(void) 327 + { 328 + platform_device_unregister(amd_hsmp_platdev); 329 + platform_driver_unregister(&amd_hsmp_driver); 330 + } 331 + 332 + device_initcall(hsmp_plt_init); 333 + module_exit(hsmp_plt_exit); 334 + 335 + MODULE_IMPORT_NS(AMD_HSMP); 336 + MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 337 + MODULE_VERSION(DRIVER_VERSION); 338 + MODULE_LICENSE("GPL");
+1 -1
drivers/platform/x86/amd/pmc/pmc.c
··· 1161 1161 .pm = pm_sleep_ptr(&amd_pmc_pm), 1162 1162 }, 1163 1163 .probe = amd_pmc_probe, 1164 - .remove_new = amd_pmc_remove, 1164 + .remove = amd_pmc_remove, 1165 1165 }; 1166 1166 module_platform_driver(amd_pmc_driver); 1167 1167
+1
drivers/platform/x86/amd/pmf/Kconfig
··· 11 11 select ACPI_PLATFORM_PROFILE 12 12 depends on TEE && AMDTEE 13 13 depends on AMD_SFH_HID 14 + depends on HAS_IOMEM 14 15 help 15 16 This driver provides support for the AMD Platform Management Framework. 16 17 The goal is to enhance end user experience by making AMD PCs smarter,
+20 -28
drivers/platform/x86/amd/pmf/acpi.c
··· 433 433 return 0; 434 434 } 435 435 436 - static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data) 437 - { 438 - struct amd_pmf_dev *dev = data; 439 - 440 - switch (res->type) { 441 - case ACPI_RESOURCE_TYPE_ADDRESS64: 442 - dev->policy_addr = res->data.address64.address.minimum; 443 - dev->policy_sz = res->data.address64.address.address_length; 444 - break; 445 - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 446 - dev->policy_addr = res->data.fixed_memory32.address; 447 - dev->policy_sz = res->data.fixed_memory32.address_length; 448 - break; 449 - } 450 - 451 - if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) { 452 - pr_err("Incorrect Policy params, possibly a SBIOS bug\n"); 453 - return AE_ERROR; 454 - } 455 - 456 - return AE_OK; 457 - } 458 - 459 436 int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev) 460 437 { 461 - acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev); 462 - acpi_status status; 438 + struct platform_device *pdev = to_platform_device(pmf_dev->dev); 463 439 464 - status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev); 465 - if (ACPI_FAILURE(status)) { 466 - dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status); 440 + pmf_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 441 + if (!pmf_dev->res) { 442 + dev_dbg(pmf_dev->dev, "Failed to get I/O memory resource\n"); 443 + return -EINVAL; 444 + } 445 + 446 + pmf_dev->policy_addr = pmf_dev->res->start; 447 + /* 448 + * We cannot use resource_size() here because it adds an extra byte to round off the size. 449 + * In the case of PMF ResourceTemplate(), this rounding is already handled within the _CRS. 450 + * Using resource_size() would increase the resource size by 1, causing a mismatch with the 451 + * length field and leading to issues. Therefore, simply use end-start of the ACPI resource 452 + * to obtain the actual length. 453 + */ 454 + pmf_dev->policy_sz = pmf_dev->res->end - pmf_dev->res->start; 455 + 456 + if (!pmf_dev->policy_addr || pmf_dev->policy_sz > POLICY_BUF_MAX_SZ || 457 + pmf_dev->policy_sz == 0) { 458 + dev_err(pmf_dev->dev, "Incorrect policy params, possibly a SBIOS bug\n"); 467 459 return -EINVAL; 468 460 } 469 461
+5 -5
drivers/platform/x86/amd/pmf/core.c
··· 430 430 431 431 err = amd_smn_read(0, AMD_PMF_BASE_ADDR_LO, &val); 432 432 if (err) { 433 - dev_err(dev->dev, "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_LO); 434 433 pci_dev_put(rdev); 435 - return pcibios_err_to_errno(err); 434 + return dev_err_probe(dev->dev, pcibios_err_to_errno(err), 435 + "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_LO); 436 436 } 437 437 438 438 base_addr_lo = val & AMD_PMF_BASE_ADDR_HI_MASK; 439 439 440 440 err = amd_smn_read(0, AMD_PMF_BASE_ADDR_HI, &val); 441 441 if (err) { 442 - dev_err(dev->dev, "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_HI); 443 442 pci_dev_put(rdev); 444 - return pcibios_err_to_errno(err); 443 + return dev_err_probe(dev->dev, pcibios_err_to_errno(err), 444 + "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_HI); 445 445 } 446 446 447 447 base_addr_hi = val & AMD_PMF_BASE_ADDR_LO_MASK; ··· 497 497 .pm = pm_sleep_ptr(&amd_pmf_pm), 498 498 }, 499 499 .probe = amd_pmf_probe, 500 - .remove_new = amd_pmf_remove, 500 + .remove = amd_pmf_remove, 501 501 }; 502 502 module_platform_driver(amd_pmf_driver); 503 503
+4 -2
drivers/platform/x86/amd/pmf/pmf.h
··· 13 13 14 14 #include <linux/acpi.h> 15 15 #include <linux/input.h> 16 + #include <linux/platform_device.h> 16 17 #include <linux/platform_profile.h> 17 18 18 19 #define POLICY_BUF_MAX_SZ 0x4b000 ··· 356 355 /* Smart PC solution builder */ 357 356 struct dentry *esbin; 358 357 unsigned char *policy_buf; 359 - u32 policy_sz; 358 + resource_size_t policy_sz; 360 359 struct tee_context *tee_ctx; 361 360 struct tee_shm *fw_shm_pool; 362 361 u32 session_id; 363 362 void *shbuf; 364 363 struct delayed_work pb_work; 365 364 struct pmf_action_table *prev_data; 366 - u64 policy_addr; 365 + resource_size_t policy_addr; 367 366 void __iomem *policy_base; 368 367 bool smart_pc_enabled; 369 368 u16 pmf_if_version; 370 369 struct input_dev *pmf_idev; 371 370 size_t mtable_size; 371 + struct resource *res; 372 372 }; 373 373 374 374 struct apmf_sps_prop_granular_v2 {
+4 -4
drivers/platform/x86/amd/pmf/tee-if.c
··· 257 257 return -ENODEV; 258 258 } 259 259 260 - dev_dbg(dev->dev, "Policy Binary size: %u bytes\n", dev->policy_sz); 260 + dev_dbg(dev->dev, "Policy Binary size: %llu bytes\n", (unsigned long long)dev->policy_sz); 261 261 memset(dev->shbuf, 0, dev->policy_sz); 262 262 ta_sm = dev->shbuf; 263 263 in = &ta_sm->pmf_input.init_table; ··· 512 512 if (ret) 513 513 goto error; 514 514 515 - dev->policy_base = devm_ioremap(dev->dev, dev->policy_addr, dev->policy_sz); 516 - if (!dev->policy_base) { 517 - ret = -ENOMEM; 515 + dev->policy_base = devm_ioremap_resource(dev->dev, dev->res); 516 + if (IS_ERR(dev->policy_base)) { 517 + ret = PTR_ERR(dev->policy_base); 518 518 goto error; 519 519 } 520 520
+176
drivers/platform/x86/amd/x3d_vcache.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * AMD 3D V-Cache Performance Optimizer Driver 4 + * 5 + * Copyright (c) 2024, Advanced Micro Devices, Inc. 6 + * All Rights Reserved. 7 + * 8 + * Authors: Basavaraj Natikar <Basavaraj.Natikar@amd.com> 9 + * Perry Yuan <perry.yuan@amd.com> 10 + * Mario Limonciello <mario.limonciello@amd.com> 11 + */ 12 + 13 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 + 15 + #include <linux/acpi.h> 16 + #include <linux/array_size.h> 17 + #include <linux/device.h> 18 + #include <linux/errno.h> 19 + #include <linux/module.h> 20 + #include <linux/mutex.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/pm.h> 23 + #include <linux/sysfs.h> 24 + #include <linux/uuid.h> 25 + 26 + static char *x3d_mode = "frequency"; 27 + module_param(x3d_mode, charp, 0); 28 + MODULE_PARM_DESC(x3d_mode, "Initial 3D-VCache mode; 'frequency' (default) or 'cache'"); 29 + 30 + #define DSM_REVISION_ID 0 31 + #define DSM_SET_X3D_MODE 1 32 + 33 + static guid_t x3d_guid = GUID_INIT(0xdff8e55f, 0xbcfd, 0x46fb, 0xba, 0x0a, 34 + 0xef, 0xd0, 0x45, 0x0f, 0x34, 0xee); 35 + 36 + enum amd_x3d_mode_type { 37 + MODE_INDEX_FREQ, 38 + MODE_INDEX_CACHE, 39 + }; 40 + 41 + static const char * const amd_x3d_mode_strings[] = { 42 + [MODE_INDEX_FREQ] = "frequency", 43 + [MODE_INDEX_CACHE] = "cache", 44 + }; 45 + 46 + struct amd_x3d_dev { 47 + struct device *dev; 48 + acpi_handle ahandle; 49 + /* To protect x3d mode setting */ 50 + struct mutex lock; 51 + enum amd_x3d_mode_type curr_mode; 52 + }; 53 + 54 + static int amd_x3d_get_mode(struct amd_x3d_dev *data) 55 + { 56 + guard(mutex)(&data->lock); 57 + 58 + return data->curr_mode; 59 + } 60 + 61 + static int amd_x3d_mode_switch(struct amd_x3d_dev *data, int new_state) 62 + { 63 + union acpi_object *out, argv; 64 + 65 + guard(mutex)(&data->lock); 66 + argv.type = ACPI_TYPE_INTEGER; 67 + argv.integer.value = new_state; 68 + 69 + out = acpi_evaluate_dsm(data->ahandle, &x3d_guid, DSM_REVISION_ID, 70 + DSM_SET_X3D_MODE, &argv); 71 + if (!out) { 72 + dev_err(data->dev, "failed to evaluate _DSM\n"); 73 + return -EINVAL; 74 + } 75 + 76 + data->curr_mode = new_state; 77 + 78 + kfree(out); 79 + 80 + return 0; 81 + } 82 + 83 + static ssize_t amd_x3d_mode_store(struct device *dev, struct device_attribute *attr, 84 + const char *buf, size_t count) 85 + { 86 + struct amd_x3d_dev *data = dev_get_drvdata(dev); 87 + int ret; 88 + 89 + ret = sysfs_match_string(amd_x3d_mode_strings, buf); 90 + if (ret < 0) 91 + return ret; 92 + 93 + ret = amd_x3d_mode_switch(data, ret); 94 + if (ret < 0) 95 + return ret; 96 + 97 + return count; 98 + } 99 + 100 + static ssize_t amd_x3d_mode_show(struct device *dev, struct device_attribute *attr, char *buf) 101 + { 102 + struct amd_x3d_dev *data = dev_get_drvdata(dev); 103 + int mode = amd_x3d_get_mode(data); 104 + 105 + return sysfs_emit(buf, "%s\n", amd_x3d_mode_strings[mode]); 106 + } 107 + static DEVICE_ATTR_RW(amd_x3d_mode); 108 + 109 + static struct attribute *amd_x3d_attrs[] = { 110 + &dev_attr_amd_x3d_mode.attr, 111 + NULL 112 + }; 113 + ATTRIBUTE_GROUPS(amd_x3d); 114 + 115 + static int amd_x3d_resume_handler(struct device *dev) 116 + { 117 + struct amd_x3d_dev *data = dev_get_drvdata(dev); 118 + int ret = amd_x3d_get_mode(data); 119 + 120 + return amd_x3d_mode_switch(data, ret); 121 + } 122 + 123 + static DEFINE_SIMPLE_DEV_PM_OPS(amd_x3d_pm, NULL, amd_x3d_resume_handler); 124 + 125 + static const struct acpi_device_id amd_x3d_acpi_ids[] = { 126 + {"AMDI0101"}, 127 + { }, 128 + }; 129 + MODULE_DEVICE_TABLE(acpi, amd_x3d_acpi_ids); 130 + 131 + static int amd_x3d_probe(struct platform_device *pdev) 132 + { 133 + struct amd_x3d_dev *data; 134 + acpi_handle handle; 135 + int ret; 136 + 137 + handle = ACPI_HANDLE(&pdev->dev); 138 + if (!handle) 139 + return -ENODEV; 140 + 141 + if (!acpi_check_dsm(handle, &x3d_guid, DSM_REVISION_ID, BIT(DSM_SET_X3D_MODE))) 142 + return -ENODEV; 143 + 144 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 145 + if (!data) 146 + return -ENOMEM; 147 + 148 + data->dev = &pdev->dev; 149 + 150 + ret = devm_mutex_init(data->dev, &data->lock); 151 + if (ret) 152 + return ret; 153 + 154 + data->ahandle = handle; 155 + platform_set_drvdata(pdev, data); 156 + 157 + ret = match_string(amd_x3d_mode_strings, ARRAY_SIZE(amd_x3d_mode_strings), x3d_mode); 158 + if (ret < 0) 159 + return dev_err_probe(&pdev->dev, -EINVAL, "invalid mode %s\n", x3d_mode); 160 + 161 + return amd_x3d_mode_switch(data, ret); 162 + } 163 + 164 + static struct platform_driver amd_3d_vcache_driver = { 165 + .driver = { 166 + .name = "amd_x3d_vcache", 167 + .dev_groups = amd_x3d_groups, 168 + .acpi_match_table = amd_x3d_acpi_ids, 169 + .pm = pm_sleep_ptr(&amd_x3d_pm), 170 + }, 171 + .probe = amd_x3d_probe, 172 + }; 173 + module_platform_driver(amd_3d_vcache_driver); 174 + 175 + MODULE_DESCRIPTION("AMD 3D V-Cache Performance Optimizer Driver"); 176 + MODULE_LICENSE("GPL");
+3 -3
drivers/platform/x86/amilo-rfkill.c
··· 132 132 133 133 static struct platform_driver amilo_rfkill_driver = { 134 134 .driver = { 135 - .name = KBUILD_MODNAME, 135 + .name = KBUILD_MODNAME, 136 136 }, 137 - .probe = amilo_rfkill_probe, 138 - .remove_new = amilo_rfkill_remove, 137 + .probe = amilo_rfkill_probe, 138 + .remove = amilo_rfkill_remove, 139 139 }; 140 140 141 141 static int __init amilo_rfkill_init(void)
+2 -2
drivers/platform/x86/asus-laptop.c
··· 1832 1832 if (!asus) 1833 1833 return -ENOMEM; 1834 1834 asus->handle = device->handle; 1835 - strcpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME); 1836 - strcpy(acpi_device_class(device), ASUS_LAPTOP_CLASS); 1835 + strscpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME); 1836 + strscpy(acpi_device_class(device), ASUS_LAPTOP_CLASS); 1837 1837 device->driver_data = asus; 1838 1838 asus->device = device; 1839 1839
+23 -67
drivers/platform/x86/asus-wmi.c
··· 3696 3696 /* Throttle thermal policy ****************************************************/ 3697 3697 static int throttle_thermal_policy_write(struct asus_wmi *asus) 3698 3698 { 3699 - u8 value = asus->throttle_thermal_policy_mode; 3700 3699 u32 retval; 3700 + u8 value; 3701 3701 int err; 3702 + 3703 + if (asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO) { 3704 + switch (asus->throttle_thermal_policy_mode) { 3705 + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: 3706 + value = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; 3707 + break; 3708 + case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: 3709 + value = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; 3710 + break; 3711 + case ASUS_THROTTLE_THERMAL_POLICY_SILENT: 3712 + value = ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; 3713 + break; 3714 + default: 3715 + return -EINVAL; 3716 + } 3717 + } else { 3718 + value = asus->throttle_thermal_policy_mode; 3719 + } 3702 3720 3703 3721 err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, 3704 3722 value, &retval); ··· 3753 3735 3754 3736 asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; 3755 3737 return throttle_thermal_policy_write(asus); 3756 - } 3757 - 3758 - static int throttle_thermal_policy_switch_next(struct asus_wmi *asus) 3759 - { 3760 - u8 new_mode = asus->throttle_thermal_policy_mode + 1; 3761 - int err; 3762 - 3763 - if (new_mode > PLATFORM_PROFILE_MAX) 3764 - new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; 3765 - 3766 - asus->throttle_thermal_policy_mode = new_mode; 3767 - err = throttle_thermal_policy_write(asus); 3768 - if (err) 3769 - return err; 3770 - 3771 - /* 3772 - * Ensure that platform_profile updates userspace with the change to ensure 3773 - * that platform_profile and throttle_thermal_policy_mode are in sync. 3774 - */ 3775 - platform_profile_notify(); 3776 - 3777 - return 0; 3778 3738 } 3779 3739 3780 3740 static ssize_t throttle_thermal_policy_show(struct device *dev, ··· 3800 3804 static DEVICE_ATTR_RW(throttle_thermal_policy); 3801 3805 3802 3806 /* Platform profile ***********************************************************/ 3803 - static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode) 3804 - { 3805 - bool vivo; 3806 - 3807 - vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; 3808 - 3809 - if (vivo) { 3810 - switch (mode) { 3811 - case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: 3812 - return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; 3813 - case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: 3814 - return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; 3815 - case ASUS_THROTTLE_THERMAL_POLICY_SILENT: 3816 - return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; 3817 - } 3818 - } 3819 - 3820 - return mode; 3821 - } 3822 - 3823 - static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode) 3824 - { 3825 - bool vivo; 3826 - 3827 - vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; 3828 - 3829 - if (vivo) { 3830 - switch (mode) { 3831 - case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO: 3832 - return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; 3833 - case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO: 3834 - return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST; 3835 - case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO: 3836 - return ASUS_THROTTLE_THERMAL_POLICY_SILENT; 3837 - } 3838 - } 3839 - 3840 - return mode; 3841 - } 3842 - 3843 3807 static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, 3844 3808 enum platform_profile_option *profile) 3845 3809 { ··· 3809 3853 asus = container_of(pprof, struct asus_wmi, platform_profile_handler); 3810 3854 tp = asus->throttle_thermal_policy_mode; 3811 3855 3812 - switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) { 3856 + switch (tp) { 3813 3857 case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: 3814 3858 *profile = PLATFORM_PROFILE_BALANCED; 3815 3859 break; ··· 3848 3892 return -EOPNOTSUPP; 3849 3893 } 3850 3894 3851 - asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp); 3895 + asus->throttle_thermal_policy_mode = tp; 3852 3896 return throttle_thermal_policy_write(asus); 3853 3897 } 3854 3898 ··· 4279 4323 if (asus->fan_boost_mode_available) 4280 4324 fan_boost_mode_switch_next(asus); 4281 4325 if (asus->throttle_thermal_policy_dev) 4282 - throttle_thermal_policy_switch_next(asus); 4326 + platform_profile_cycle(); 4283 4327 return; 4284 4328 4285 4329 } ··· 5032 5076 return -EBUSY; 5033 5077 5034 5078 platform_driver = &driver->platform_driver; 5035 - platform_driver->remove_new = asus_wmi_remove; 5079 + platform_driver->remove = asus_wmi_remove; 5036 5080 platform_driver->driver.owner = driver->owner; 5037 5081 platform_driver->driver.name = driver->name; 5038 5082 platform_driver->driver.pm = &asus_pm_ops;
+1 -1
drivers/platform/x86/barco-p50-gpio.c
··· 385 385 .name = DRIVER_NAME, 386 386 }, 387 387 .probe = p50_gpio_probe, 388 - .remove_new = p50_gpio_remove, 388 + .remove = p50_gpio_remove, 389 389 }; 390 390 391 391 /* Board setup */
+4 -3
drivers/platform/x86/classmate-laptop.c
··· 12 12 #include <linux/backlight.h> 13 13 #include <linux/input.h> 14 14 #include <linux/rfkill.h> 15 + #include <linux/sysfs.h> 15 16 16 17 struct cmpc_accel { 17 18 int sensitivity; ··· 209 208 inputdev = dev_get_drvdata(&acpi->dev); 210 209 accel = dev_get_drvdata(&inputdev->dev); 211 210 212 - return sprintf(buf, "%d\n", accel->sensitivity); 211 + return sysfs_emit(buf, "%d\n", accel->sensitivity); 213 212 } 214 213 215 214 static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, ··· 258 257 inputdev = dev_get_drvdata(&acpi->dev); 259 258 accel = dev_get_drvdata(&inputdev->dev); 260 259 261 - return sprintf(buf, "%d\n", accel->g_select); 260 + return sysfs_emit(buf, "%d\n", accel->g_select); 262 261 } 263 262 264 263 static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, ··· 551 550 inputdev = dev_get_drvdata(&acpi->dev); 552 551 accel = dev_get_drvdata(&inputdev->dev); 553 552 554 - return sprintf(buf, "%d\n", accel->sensitivity); 553 + return sysfs_emit(buf, "%d\n", accel->sensitivity); 555 554 } 556 555 557 556 static ssize_t cmpc_accel_sensitivity_store(struct device *dev,
+31 -30
drivers/platform/x86/compal-laptop.c
··· 68 68 #include <linux/hwmon.h> 69 69 #include <linux/hwmon-sysfs.h> 70 70 #include <linux/power_supply.h> 71 + #include <linux/sysfs.h> 71 72 #include <linux/fb.h> 72 73 #include <acpi/video.h> 73 74 ··· 365 364 366 365 367 366 /* Wake_up interface */ 368 - #define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK) \ 369 - static ssize_t NAME##_show(struct device *dev, \ 370 - struct device_attribute *attr, char *buf) \ 371 - { \ 372 - return sprintf(buf, "%d\n", ((ec_read_u8(ADDR) & MASK) != 0)); \ 373 - } \ 374 - static ssize_t NAME##_store(struct device *dev, \ 375 - struct device_attribute *attr, const char *buf, size_t count) \ 376 - { \ 377 - int state; \ 378 - u8 old_val = ec_read_u8(ADDR); \ 379 - if (sscanf(buf, "%d", &state) != 1 || (state < 0 || state > 1)) \ 380 - return -EINVAL; \ 381 - ec_write(ADDR, state ? (old_val | MASK) : (old_val & ~MASK)); \ 382 - return count; \ 367 + #define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK) \ 368 + static ssize_t NAME##_show(struct device *dev, \ 369 + struct device_attribute *attr, char *buf) \ 370 + { \ 371 + return sysfs_emit(buf, "%d\n", ((ec_read_u8(ADDR) & MASK) != 0)); \ 372 + } \ 373 + static ssize_t NAME##_store(struct device *dev, \ 374 + struct device_attribute *attr, const char *buf, size_t count) \ 375 + { \ 376 + int state; \ 377 + u8 old_val = ec_read_u8(ADDR); \ 378 + if (sscanf(buf, "%d", &state) != 1 || (state < 0 || state > 1)) \ 379 + return -EINVAL; \ 380 + ec_write(ADDR, state ? (old_val | MASK) : (old_val & ~MASK)); \ 381 + return count; \ 383 382 } 384 383 385 384 SIMPLE_MASKED_STORE_SHOW(wake_up_pme, WAKE_UP_ADDR, WAKE_UP_PME) ··· 394 393 struct device_attribute *attr, char *buf) 395 394 { 396 395 struct compal_data *data = dev_get_drvdata(dev); 397 - return sprintf(buf, "%d\n", data->pwm_enable); 396 + return sysfs_emit(buf, "%d\n", data->pwm_enable); 398 397 } 399 398 400 399 static ssize_t pwm_enable_store(struct device *dev, ··· 433 432 char *buf) 434 433 { 435 434 struct compal_data *data = dev_get_drvdata(dev); 436 - return sprintf(buf, "%hhu\n", data->curr_pwm); 435 + return sysfs_emit(buf, "%hhu\n", data->curr_pwm); 437 436 } 438 437 439 438 static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, ··· 461 460 static ssize_t fan_show(struct device *dev, struct device_attribute *attr, 462 461 char *buf) 463 462 { 464 - return sprintf(buf, "%d\n", get_fan_rpm()); 463 + return sysfs_emit(buf, "%d\n", get_fan_rpm()); 465 464 } 466 465 467 466 468 467 /* Temperature interface */ 469 - #define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL) \ 470 - static ssize_t temp_##POSTFIX(struct device *dev, \ 471 - struct device_attribute *attr, char *buf) \ 472 - { \ 473 - return sprintf(buf, "%d\n", 1000 * (int)ec_read_s8(ADDRESS)); \ 474 - } \ 475 - static ssize_t label_##POSTFIX(struct device *dev, \ 476 - struct device_attribute *attr, char *buf) \ 477 - { \ 478 - return sprintf(buf, "%s\n", LABEL); \ 468 + #define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL) \ 469 + static ssize_t temp_##POSTFIX(struct device *dev, \ 470 + struct device_attribute *attr, char *buf) \ 471 + { \ 472 + return sysfs_emit(buf, "%d\n", 1000 * (int)ec_read_s8(ADDRESS)); \ 473 + } \ 474 + static ssize_t label_##POSTFIX(struct device *dev, \ 475 + struct device_attribute *attr, char *buf) \ 476 + { \ 477 + return sysfs_emit(buf, "%s\n", LABEL); \ 479 478 } 480 479 481 480 /* Labels as in service guide */ ··· 1024 1023 .driver = { 1025 1024 .name = DRIVER_NAME, 1026 1025 }, 1027 - .probe = compal_probe, 1028 - .remove_new = compal_remove, 1026 + .probe = compal_probe, 1027 + .remove = compal_remove, 1029 1028 }; 1030 1029 1031 1030 static int __init compal_init(void)
+1
drivers/platform/x86/dell/Kconfig
··· 21 21 depends on LEDS_CLASS 22 22 depends on NEW_LEDS 23 23 depends on ACPI_WMI 24 + select ACPI_PLATFORM_PROFILE 24 25 help 25 26 This is a driver for controlling Alienware BIOS driven 26 27 features. It exposes an interface for controlling the AlienFX
+501 -76
drivers/platform/x86/dell/alienware-wmi.c
··· 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 9 10 10 #include <linux/acpi.h> 11 + #include <linux/bitfield.h> 12 + #include <linux/bits.h> 11 13 #include <linux/module.h> 12 14 #include <linux/platform_device.h> 15 + #include <linux/platform_profile.h> 13 16 #include <linux/dmi.h> 14 17 #include <linux/leds.h> 15 18 ··· 28 25 #define WMAX_METHOD_AMPLIFIER_CABLE 0x6 29 26 #define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B 30 27 #define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C 28 + #define WMAX_METHOD_THERMAL_INFORMATION 0x14 29 + #define WMAX_METHOD_THERMAL_CONTROL 0x15 30 + #define WMAX_METHOD_GAME_SHIFT_STATUS 0x25 31 + 32 + #define WMAX_THERMAL_MODE_GMODE 0xAB 33 + 34 + #define WMAX_FAILURE_CODE 0xFFFFFFFF 31 35 32 36 MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>"); 33 37 MODULE_DESCRIPTION("Alienware special feature control"); 34 38 MODULE_LICENSE("GPL"); 35 39 MODULE_ALIAS("wmi:" LEGACY_CONTROL_GUID); 36 40 MODULE_ALIAS("wmi:" WMAX_CONTROL_GUID); 41 + 42 + static bool force_platform_profile; 43 + module_param_unsafe(force_platform_profile, bool, 0); 44 + MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available"); 45 + 46 + static bool force_gmode; 47 + module_param_unsafe(force_gmode, bool, 0); 48 + MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected"); 37 49 38 50 enum INTERFACE_FLAGS { 39 51 LEGACY, ··· 67 49 WMAX_SUSPEND = 3, 68 50 }; 69 51 52 + enum WMAX_THERMAL_INFORMATION_OPERATIONS { 53 + WMAX_OPERATION_SYS_DESCRIPTION = 0x02, 54 + WMAX_OPERATION_LIST_IDS = 0x03, 55 + WMAX_OPERATION_CURRENT_PROFILE = 0x0B, 56 + }; 57 + 58 + enum WMAX_THERMAL_CONTROL_OPERATIONS { 59 + WMAX_OPERATION_ACTIVATE_PROFILE = 0x01, 60 + }; 61 + 62 + enum WMAX_GAME_SHIFT_STATUS_OPERATIONS { 63 + WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01, 64 + WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02, 65 + }; 66 + 67 + enum WMAX_THERMAL_TABLES { 68 + WMAX_THERMAL_TABLE_BASIC = 0x90, 69 + WMAX_THERMAL_TABLE_USTT = 0xA0, 70 + }; 71 + 72 + enum wmax_thermal_mode { 73 + THERMAL_MODE_USTT_BALANCED, 74 + THERMAL_MODE_USTT_BALANCED_PERFORMANCE, 75 + THERMAL_MODE_USTT_COOL, 76 + THERMAL_MODE_USTT_QUIET, 77 + THERMAL_MODE_USTT_PERFORMANCE, 78 + THERMAL_MODE_USTT_LOW_POWER, 79 + THERMAL_MODE_BASIC_QUIET, 80 + THERMAL_MODE_BASIC_BALANCED, 81 + THERMAL_MODE_BASIC_BALANCED_PERFORMANCE, 82 + THERMAL_MODE_BASIC_PERFORMANCE, 83 + THERMAL_MODE_LAST, 84 + }; 85 + 86 + static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = { 87 + [THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED, 88 + [THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, 89 + [THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL, 90 + [THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET, 91 + [THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, 92 + [THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER, 93 + [THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET, 94 + [THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED, 95 + [THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, 96 + [THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, 97 + }; 98 + 70 99 struct quirk_entry { 71 100 u8 num_zones; 72 101 u8 hdmi_mux; 73 102 u8 amplifier; 74 103 u8 deepslp; 104 + bool thermal; 105 + bool gmode; 75 106 }; 76 107 77 108 static struct quirk_entry *quirks; ··· 131 64 .hdmi_mux = 0, 132 65 .amplifier = 0, 133 66 .deepslp = 0, 67 + .thermal = false, 68 + .gmode = false, 134 69 }; 135 70 136 71 static struct quirk_entry quirk_unknown = { ··· 140 71 .hdmi_mux = 0, 141 72 .amplifier = 0, 142 73 .deepslp = 0, 74 + .thermal = false, 75 + .gmode = false, 143 76 }; 144 77 145 78 static struct quirk_entry quirk_x51_r1_r2 = { ··· 149 78 .hdmi_mux = 0, 150 79 .amplifier = 0, 151 80 .deepslp = 0, 81 + .thermal = false, 82 + .gmode = false, 152 83 }; 153 84 154 85 static struct quirk_entry quirk_x51_r3 = { ··· 158 85 .hdmi_mux = 0, 159 86 .amplifier = 1, 160 87 .deepslp = 0, 88 + .thermal = false, 89 + .gmode = false, 161 90 }; 162 91 163 92 static struct quirk_entry quirk_asm100 = { ··· 167 92 .hdmi_mux = 1, 168 93 .amplifier = 0, 169 94 .deepslp = 0, 95 + .thermal = false, 96 + .gmode = false, 170 97 }; 171 98 172 99 static struct quirk_entry quirk_asm200 = { ··· 176 99 .hdmi_mux = 1, 177 100 .amplifier = 0, 178 101 .deepslp = 1, 102 + .thermal = false, 103 + .gmode = false, 179 104 }; 180 105 181 106 static struct quirk_entry quirk_asm201 = { ··· 185 106 .hdmi_mux = 1, 186 107 .amplifier = 1, 187 108 .deepslp = 1, 109 + .thermal = false, 110 + .gmode = false, 111 + }; 112 + 113 + static struct quirk_entry quirk_g_series = { 114 + .num_zones = 2, 115 + .hdmi_mux = 0, 116 + .amplifier = 0, 117 + .deepslp = 0, 118 + .thermal = true, 119 + .gmode = true, 120 + }; 121 + 122 + static struct quirk_entry quirk_x_series = { 123 + .num_zones = 2, 124 + .hdmi_mux = 0, 125 + .amplifier = 0, 126 + .deepslp = 0, 127 + .thermal = true, 128 + .gmode = false, 188 129 }; 189 130 190 131 static int __init dmi_matched(const struct dmi_system_id *dmi) ··· 215 116 216 117 static const struct dmi_system_id alienware_quirks[] __initconst = { 217 118 { 218 - .callback = dmi_matched, 219 - .ident = "Alienware X51 R3", 220 - .matches = { 221 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 222 - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), 223 - }, 224 - .driver_data = &quirk_x51_r3, 225 - }, 119 + .callback = dmi_matched, 120 + .ident = "Alienware ASM100", 121 + .matches = { 122 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 123 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 124 + }, 125 + .driver_data = &quirk_asm100, 126 + }, 226 127 { 227 - .callback = dmi_matched, 228 - .ident = "Alienware X51 R2", 229 - .matches = { 230 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 231 - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), 232 - }, 233 - .driver_data = &quirk_x51_r1_r2, 234 - }, 128 + .callback = dmi_matched, 129 + .ident = "Alienware ASM200", 130 + .matches = { 131 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 132 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), 133 + }, 134 + .driver_data = &quirk_asm200, 135 + }, 235 136 { 236 - .callback = dmi_matched, 237 - .ident = "Alienware X51 R1", 238 - .matches = { 239 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 240 - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), 241 - }, 242 - .driver_data = &quirk_x51_r1_r2, 243 - }, 137 + .callback = dmi_matched, 138 + .ident = "Alienware ASM201", 139 + .matches = { 140 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 141 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), 142 + }, 143 + .driver_data = &quirk_asm201, 144 + }, 244 145 { 245 - .callback = dmi_matched, 246 - .ident = "Alienware ASM100", 247 - .matches = { 248 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 249 - DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 250 - }, 251 - .driver_data = &quirk_asm100, 252 - }, 146 + .callback = dmi_matched, 147 + .ident = "Alienware m17 R5", 148 + .matches = { 149 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 150 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), 151 + }, 152 + .driver_data = &quirk_x_series, 153 + }, 253 154 { 254 - .callback = dmi_matched, 255 - .ident = "Alienware ASM200", 256 - .matches = { 257 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 258 - DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), 259 - }, 260 - .driver_data = &quirk_asm200, 261 - }, 155 + .callback = dmi_matched, 156 + .ident = "Alienware m18 R2", 157 + .matches = { 158 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 159 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"), 160 + }, 161 + .driver_data = &quirk_x_series, 162 + }, 262 163 { 263 - .callback = dmi_matched, 264 - .ident = "Alienware ASM201", 265 - .matches = { 266 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 267 - DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), 268 - }, 269 - .driver_data = &quirk_asm201, 270 - }, 271 - { 272 - .callback = dmi_matched, 273 - .ident = "Dell Inc. Inspiron 5675", 274 - .matches = { 275 - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 276 - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"), 277 - }, 278 - .driver_data = &quirk_inspiron5675, 279 - }, 164 + .callback = dmi_matched, 165 + .ident = "Alienware x15 R1", 166 + .matches = { 167 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 168 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"), 169 + }, 170 + .driver_data = &quirk_x_series, 171 + }, 172 + { 173 + .callback = dmi_matched, 174 + .ident = "Alienware x17 R2", 175 + .matches = { 176 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 177 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"), 178 + }, 179 + .driver_data = &quirk_x_series, 180 + }, 181 + { 182 + .callback = dmi_matched, 183 + .ident = "Alienware X51 R1", 184 + .matches = { 185 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 186 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), 187 + }, 188 + .driver_data = &quirk_x51_r1_r2, 189 + }, 190 + { 191 + .callback = dmi_matched, 192 + .ident = "Alienware X51 R2", 193 + .matches = { 194 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 195 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), 196 + }, 197 + .driver_data = &quirk_x51_r1_r2, 198 + }, 199 + { 200 + .callback = dmi_matched, 201 + .ident = "Alienware X51 R3", 202 + .matches = { 203 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 204 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), 205 + }, 206 + .driver_data = &quirk_x51_r3, 207 + }, 208 + { 209 + .callback = dmi_matched, 210 + .ident = "Dell Inc. G15 5510", 211 + .matches = { 212 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 213 + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"), 214 + }, 215 + .driver_data = &quirk_g_series, 216 + }, 217 + { 218 + .callback = dmi_matched, 219 + .ident = "Dell Inc. G15 5511", 220 + .matches = { 221 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 222 + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"), 223 + }, 224 + .driver_data = &quirk_g_series, 225 + }, 226 + { 227 + .callback = dmi_matched, 228 + .ident = "Dell Inc. G15 5515", 229 + .matches = { 230 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 231 + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"), 232 + }, 233 + .driver_data = &quirk_g_series, 234 + }, 235 + { 236 + .callback = dmi_matched, 237 + .ident = "Dell Inc. G3 3500", 238 + .matches = { 239 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 240 + DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"), 241 + }, 242 + .driver_data = &quirk_g_series, 243 + }, 244 + { 245 + .callback = dmi_matched, 246 + .ident = "Dell Inc. G3 3590", 247 + .matches = { 248 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 249 + DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"), 250 + }, 251 + .driver_data = &quirk_g_series, 252 + }, 253 + { 254 + .callback = dmi_matched, 255 + .ident = "Dell Inc. G5 5500", 256 + .matches = { 257 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 258 + DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"), 259 + }, 260 + .driver_data = &quirk_g_series, 261 + }, 262 + { 263 + .callback = dmi_matched, 264 + .ident = "Dell Inc. Inspiron 5675", 265 + .matches = { 266 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 267 + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"), 268 + }, 269 + .driver_data = &quirk_inspiron5675, 270 + }, 280 271 {} 281 272 }; 282 273 ··· 403 214 u8 state; 404 215 } __packed; 405 216 217 + struct wmax_u32_args { 218 + u8 operation; 219 + u8 arg1; 220 + u8 arg2; 221 + u8 arg3; 222 + }; 223 + 406 224 static struct platform_device *platform_device; 407 225 static struct device_attribute *zone_dev_attrs; 408 226 static struct attribute **zone_attrs; 409 227 static struct platform_zone *zone_data; 228 + static struct platform_profile_handler pp_handler; 229 + static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; 410 230 411 231 static struct platform_driver platform_driver = { 412 232 .driver = { 413 - .name = "alienware-wmi", 414 - } 233 + .name = "alienware-wmi", 234 + } 415 235 }; 416 236 417 237 static struct attribute_group zone_attribute_group = { ··· 490 292 guid = WMAX_CONTROL_GUID; 491 293 method_id = WMAX_METHOD_ZONE_CONTROL; 492 294 493 - input.length = (acpi_size) sizeof(wmax_basic_args); 295 + input.length = sizeof(wmax_basic_args); 494 296 input.pointer = &wmax_basic_args; 495 297 } else { 496 298 legacy_args.colors = zone->colors; ··· 504 306 guid = LEGACY_CONTROL_GUID; 505 307 method_id = zone->location + 1; 506 308 507 - input.length = (acpi_size) sizeof(legacy_args); 309 + input.length = sizeof(legacy_args); 508 310 input.pointer = &legacy_args; 509 311 } 510 312 pr_debug("alienware-wmi: guid %s method %d\n", guid, method_id); ··· 556 358 .led_mask = 0xFF, 557 359 .percentage = brightness, 558 360 }; 559 - input.length = (acpi_size) sizeof(args); 361 + input.length = sizeof(args); 560 362 input.pointer = &args; 561 363 status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0, 562 364 WMAX_METHOD_BRIGHTNESS, &input, NULL); ··· 698 500 kfree(zone_attrs); 699 501 } 700 502 701 - static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args, 702 - u32 command, int *out_data) 503 + static acpi_status alienware_wmax_command(void *in_args, size_t in_size, 504 + u32 command, u32 *out_data) 703 505 { 704 506 acpi_status status; 705 507 union acpi_object *obj; 706 508 struct acpi_buffer input; 707 509 struct acpi_buffer output; 708 510 709 - input.length = (acpi_size) sizeof(*in_args); 511 + input.length = in_size; 710 512 input.pointer = in_args; 711 513 if (out_data) { 712 514 output.length = ACPI_ALLOCATE_BUFFER; ··· 739 541 .arg = 0, 740 542 }; 741 543 status = 742 - alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_CABLE, 743 - (u32 *) &out_data); 544 + alienware_wmax_command(&in_args, sizeof(in_args), 545 + WMAX_METHOD_HDMI_CABLE, &out_data); 744 546 if (ACPI_SUCCESS(status)) { 745 547 if (out_data == 0) 746 548 return sysfs_emit(buf, "[unconnected] connected unknown\n"); ··· 760 562 .arg = 0, 761 563 }; 762 564 status = 763 - alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_STATUS, 764 - (u32 *) &out_data); 565 + alienware_wmax_command(&in_args, sizeof(in_args), 566 + WMAX_METHOD_HDMI_STATUS, &out_data); 765 567 766 568 if (ACPI_SUCCESS(status)) { 767 569 if (out_data == 1) ··· 787 589 args.arg = 3; 788 590 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); 789 591 790 - status = alienware_wmax_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); 592 + status = alienware_wmax_command(&args, sizeof(args), 593 + WMAX_METHOD_HDMI_SOURCE, NULL); 791 594 792 595 if (ACPI_FAILURE(status)) 793 596 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ··· 841 642 .arg = 0, 842 643 }; 843 644 status = 844 - alienware_wmax_command(&in_args, WMAX_METHOD_AMPLIFIER_CABLE, 845 - (u32 *) &out_data); 645 + alienware_wmax_command(&in_args, sizeof(in_args), 646 + WMAX_METHOD_AMPLIFIER_CABLE, &out_data); 846 647 if (ACPI_SUCCESS(status)) { 847 648 if (out_data == 0) 848 649 return sysfs_emit(buf, "[unconnected] connected unknown\n"); ··· 893 694 struct wmax_basic_args in_args = { 894 695 .arg = 0, 895 696 }; 896 - status = alienware_wmax_command(&in_args, WMAX_METHOD_DEEP_SLEEP_STATUS, 897 - (u32 *) &out_data); 697 + status = alienware_wmax_command(&in_args, sizeof(in_args), 698 + WMAX_METHOD_DEEP_SLEEP_STATUS, &out_data); 898 699 if (ACPI_SUCCESS(status)) { 899 700 if (out_data == 0) 900 701 return sysfs_emit(buf, "[disabled] s5 s5_s4\n"); ··· 922 723 args.arg = 2; 923 724 pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); 924 725 925 - status = alienware_wmax_command(&args, WMAX_METHOD_DEEP_SLEEP_CONTROL, 926 - NULL); 726 + status = alienware_wmax_command(&args, sizeof(args), 727 + WMAX_METHOD_DEEP_SLEEP_CONTROL, NULL); 927 728 928 729 if (ACPI_FAILURE(status)) 929 730 pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ··· 959 760 return ret; 960 761 } 961 762 763 + /* 764 + * Thermal Profile control 765 + * - Provides thermal profile control through the Platform Profile API 766 + */ 767 + #define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4) 768 + #define WMAX_THERMAL_MODE_MASK GENMASK(3, 0) 769 + #define WMAX_SENSOR_ID_MASK BIT(8) 770 + 771 + static bool is_wmax_thermal_code(u32 code) 772 + { 773 + if (code & WMAX_SENSOR_ID_MASK) 774 + return false; 775 + 776 + if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST) 777 + return false; 778 + 779 + if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC && 780 + (code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET) 781 + return true; 782 + 783 + if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT && 784 + (code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER) 785 + return true; 786 + 787 + return false; 788 + } 789 + 790 + static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data) 791 + { 792 + acpi_status status; 793 + struct wmax_u32_args in_args = { 794 + .operation = operation, 795 + .arg1 = arg, 796 + .arg2 = 0, 797 + .arg3 = 0, 798 + }; 799 + 800 + status = alienware_wmax_command(&in_args, sizeof(in_args), 801 + WMAX_METHOD_THERMAL_INFORMATION, 802 + out_data); 803 + 804 + if (ACPI_FAILURE(status)) 805 + return -EIO; 806 + 807 + if (*out_data == WMAX_FAILURE_CODE) 808 + return -EBADRQC; 809 + 810 + return 0; 811 + } 812 + 813 + static int wmax_thermal_control(u8 profile) 814 + { 815 + acpi_status status; 816 + struct wmax_u32_args in_args = { 817 + .operation = WMAX_OPERATION_ACTIVATE_PROFILE, 818 + .arg1 = profile, 819 + .arg2 = 0, 820 + .arg3 = 0, 821 + }; 822 + u32 out_data; 823 + 824 + status = alienware_wmax_command(&in_args, sizeof(in_args), 825 + WMAX_METHOD_THERMAL_CONTROL, 826 + &out_data); 827 + 828 + if (ACPI_FAILURE(status)) 829 + return -EIO; 830 + 831 + if (out_data == WMAX_FAILURE_CODE) 832 + return -EBADRQC; 833 + 834 + return 0; 835 + } 836 + 837 + static int wmax_game_shift_status(u8 operation, u32 *out_data) 838 + { 839 + acpi_status status; 840 + struct wmax_u32_args in_args = { 841 + .operation = operation, 842 + .arg1 = 0, 843 + .arg2 = 0, 844 + .arg3 = 0, 845 + }; 846 + 847 + status = alienware_wmax_command(&in_args, sizeof(in_args), 848 + WMAX_METHOD_GAME_SHIFT_STATUS, 849 + out_data); 850 + 851 + if (ACPI_FAILURE(status)) 852 + return -EIO; 853 + 854 + if (*out_data == WMAX_FAILURE_CODE) 855 + return -EOPNOTSUPP; 856 + 857 + return 0; 858 + } 859 + 860 + static int thermal_profile_get(struct platform_profile_handler *pprof, 861 + enum platform_profile_option *profile) 862 + { 863 + u32 out_data; 864 + int ret; 865 + 866 + ret = wmax_thermal_information(WMAX_OPERATION_CURRENT_PROFILE, 867 + 0, &out_data); 868 + 869 + if (ret < 0) 870 + return ret; 871 + 872 + if (out_data == WMAX_THERMAL_MODE_GMODE) { 873 + *profile = PLATFORM_PROFILE_PERFORMANCE; 874 + return 0; 875 + } 876 + 877 + if (!is_wmax_thermal_code(out_data)) 878 + return -ENODATA; 879 + 880 + out_data &= WMAX_THERMAL_MODE_MASK; 881 + *profile = wmax_mode_to_platform_profile[out_data]; 882 + 883 + return 0; 884 + } 885 + 886 + static int thermal_profile_set(struct platform_profile_handler *pprof, 887 + enum platform_profile_option profile) 888 + { 889 + if (quirks->gmode) { 890 + u32 gmode_status; 891 + int ret; 892 + 893 + ret = wmax_game_shift_status(WMAX_OPERATION_GET_GAME_SHIFT_STATUS, 894 + &gmode_status); 895 + 896 + if (ret < 0) 897 + return ret; 898 + 899 + if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) || 900 + (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) { 901 + ret = wmax_game_shift_status(WMAX_OPERATION_TOGGLE_GAME_SHIFT, 902 + &gmode_status); 903 + 904 + if (ret < 0) 905 + return ret; 906 + } 907 + } 908 + 909 + return wmax_thermal_control(supported_thermal_profiles[profile]); 910 + } 911 + 912 + static int create_thermal_profile(void) 913 + { 914 + u32 out_data; 915 + u8 sys_desc[4]; 916 + u32 first_mode; 917 + enum wmax_thermal_mode mode; 918 + enum platform_profile_option profile; 919 + int ret; 920 + 921 + ret = wmax_thermal_information(WMAX_OPERATION_SYS_DESCRIPTION, 922 + 0, (u32 *) &sys_desc); 923 + if (ret < 0) 924 + return ret; 925 + 926 + first_mode = sys_desc[0] + sys_desc[1]; 927 + 928 + for (u32 i = 0; i < sys_desc[3]; i++) { 929 + ret = wmax_thermal_information(WMAX_OPERATION_LIST_IDS, 930 + i + first_mode, &out_data); 931 + 932 + if (ret == -EIO) 933 + return ret; 934 + 935 + if (ret == -EBADRQC) 936 + break; 937 + 938 + if (!is_wmax_thermal_code(out_data)) 939 + continue; 940 + 941 + mode = out_data & WMAX_THERMAL_MODE_MASK; 942 + profile = wmax_mode_to_platform_profile[mode]; 943 + supported_thermal_profiles[profile] = out_data; 944 + 945 + set_bit(profile, pp_handler.choices); 946 + } 947 + 948 + if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST)) 949 + return -ENODEV; 950 + 951 + if (quirks->gmode) { 952 + supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] = 953 + WMAX_THERMAL_MODE_GMODE; 954 + 955 + set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices); 956 + } 957 + 958 + pp_handler.profile_get = thermal_profile_get; 959 + pp_handler.profile_set = thermal_profile_set; 960 + 961 + return platform_profile_register(&pp_handler); 962 + } 963 + 964 + static void remove_thermal_profile(void) 965 + { 966 + if (quirks->thermal) 967 + platform_profile_remove(); 968 + } 969 + 962 970 static int __init alienware_wmi_init(void) 963 971 { 964 972 int ret; ··· 1182 776 dmi_check_system(alienware_quirks); 1183 777 if (quirks == NULL) 1184 778 quirks = &quirk_unknown; 779 + 780 + if (force_platform_profile) 781 + quirks->thermal = true; 782 + 783 + if (force_gmode) { 784 + if (quirks->thermal) 785 + quirks->gmode = true; 786 + else 787 + pr_warn("force_gmode requires platform profile support\n"); 788 + } 1185 789 1186 790 ret = platform_driver_register(&platform_driver); 1187 791 if (ret) ··· 1223 807 goto fail_prep_deepsleep; 1224 808 } 1225 809 810 + if (quirks->thermal) { 811 + ret = create_thermal_profile(); 812 + if (ret) 813 + goto fail_prep_thermal_profile; 814 + } 815 + 1226 816 ret = alienware_zone_init(platform_device); 1227 817 if (ret) 1228 818 goto fail_prep_zones; ··· 1237 815 1238 816 fail_prep_zones: 1239 817 alienware_zone_exit(platform_device); 818 + remove_thermal_profile(); 819 + fail_prep_thermal_profile: 1240 820 fail_prep_deepsleep: 1241 821 fail_prep_amplifier: 1242 822 fail_prep_hdmi: ··· 1258 834 if (platform_device) { 1259 835 alienware_zone_exit(platform_device); 1260 836 remove_hdmi(platform_device); 837 + remove_thermal_profile(); 1261 838 platform_device_unregister(platform_device); 1262 839 platform_driver_unregister(&platform_driver); 1263 840 }
+7 -6
drivers/platform/x86/dell/dcdbas.c
··· 29 29 #include <linux/smp.h> 30 30 #include <linux/spinlock.h> 31 31 #include <linux/string.h> 32 + #include <linux/sysfs.h> 32 33 #include <linux/types.h> 33 34 #include <linux/mutex.h> 34 35 ··· 133 132 struct device_attribute *attr, 134 133 char *buf) 135 134 { 136 - return sprintf(buf, "%x\n", (u32)smi_buf.dma); 135 + return sysfs_emit(buf, "%x\n", (u32)smi_buf.dma); 137 136 } 138 137 139 138 static ssize_t smi_data_buf_size_show(struct device *dev, 140 139 struct device_attribute *attr, 141 140 char *buf) 142 141 { 143 - return sprintf(buf, "%lu\n", smi_buf.size); 142 + return sysfs_emit(buf, "%lu\n", smi_buf.size); 144 143 } 145 144 146 145 static ssize_t smi_data_buf_size_store(struct device *dev, ··· 201 200 struct device_attribute *attr, 202 201 char *buf) 203 202 { 204 - return sprintf(buf, "%u\n", host_control_action); 203 + return sysfs_emit(buf, "%u\n", host_control_action); 205 204 } 206 205 207 206 static ssize_t host_control_action_store(struct device *dev, ··· 225 224 struct device_attribute *attr, 226 225 char *buf) 227 226 { 228 - return sprintf(buf, "%u\n", host_control_smi_type); 227 + return sysfs_emit(buf, "%u\n", host_control_smi_type); 229 228 } 230 229 231 230 static ssize_t host_control_smi_type_store(struct device *dev, ··· 240 239 struct device_attribute *attr, 241 240 char *buf) 242 241 { 243 - return sprintf(buf, "%u\n", host_control_on_shutdown); 242 + return sysfs_emit(buf, "%u\n", host_control_on_shutdown); 244 243 } 245 244 246 245 static ssize_t host_control_on_shutdown_store(struct device *dev, ··· 710 709 .name = DRIVER_NAME, 711 710 }, 712 711 .probe = dcdbas_probe, 713 - .remove_new = dcdbas_remove, 712 + .remove = dcdbas_remove, 714 713 }; 715 714 716 715 static const struct platform_device_info dcdbas_dev_info __initconst = {
+1 -1
drivers/platform/x86/dell/dell-smo8800.c
··· 179 179 180 180 static struct platform_driver smo8800_driver = { 181 181 .probe = smo8800_probe, 182 - .remove_new = smo8800_remove, 182 + .remove = smo8800_remove, 183 183 .driver = { 184 184 .name = DRIVER_NAME, 185 185 .acpi_match_table = smo8800_ids,
+1 -1
drivers/platform/x86/dell/dell-uart-backlight.c
··· 393 393 394 394 static struct platform_driver dell_uart_bl_pdev_driver = { 395 395 .probe = dell_uart_bl_pdev_probe, 396 - .remove_new = dell_uart_bl_pdev_remove, 396 + .remove = dell_uart_bl_pdev_remove, 397 397 .driver = { 398 398 .name = "dell-uart-backlight", 399 399 },
+5 -4
drivers/platform/x86/eeepc-laptop.c
··· 25 25 #include <linux/rfkill.h> 26 26 #include <linux/pci.h> 27 27 #include <linux/pci_hotplug.h> 28 + #include <linux/sysfs.h> 28 29 #include <linux/leds.h> 29 30 #include <linux/dmi.h> 30 31 #include <acpi/video.h> ··· 286 285 287 286 if (value < 0) 288 287 return -EIO; 289 - return sprintf(buf, "%d\n", value); 288 + return sysfs_emit(buf, "%d\n", value); 290 289 } 291 290 292 291 #define EEEPC_ACPI_SHOW_FUNC(_name, _cm) \ ··· 362 361 363 362 if (get_cpufv(eeepc, &c)) 364 363 return -ENODEV; 365 - return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 364 + return sysfs_emit(buf, "%#x\n", (c.num << 8) | c.cur); 366 365 } 367 366 368 367 static ssize_t cpufv_store(struct device *dev, ··· 394 393 { 395 394 struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 396 395 397 - return sprintf(buf, "%d\n", eeepc->cpufv_disabled); 396 + return sysfs_emit(buf, "%d\n", eeepc->cpufv_disabled); 398 397 } 399 398 400 399 static ssize_t cpufv_disabled_store(struct device *dev, ··· 1026 1025 1027 1026 static ssize_t show_sys_hwmon(int (*get)(void), char *buf) 1028 1027 { 1029 - return sprintf(buf, "%d\n", get()); 1028 + return sysfs_emit(buf, "%d\n", get()); 1030 1029 } 1031 1030 1032 1031 #define EEEPC_SENSOR_SHOW_FUNC(_name, _get) \
+3 -8
drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
··· 531 531 struct kobject *attr_name_kobj = 532 532 bioscfg_drv.password_data[instance_id].attr_name_kobj; 533 533 534 - if (attr_name_kobj) { 535 - if (!strcmp(attr_name_kobj->name, SETUP_PASSWD)) 536 - sysfs_remove_group(attr_name_kobj, 537 - &password_attr_group); 538 - else 539 - sysfs_remove_group(attr_name_kobj, 540 - &password_attr_group); 541 - } 534 + if (attr_name_kobj) 535 + sysfs_remove_group(attr_name_kobj, 536 + &password_attr_group); 542 537 } 543 538 bioscfg_drv.password_instances_count = 0; 544 539 kfree(bioscfg_drv.password_data);
+1 -1
drivers/platform/x86/hp/hp-wmi.c
··· 1748 1748 .pm = &hp_wmi_pm_ops, 1749 1749 .dev_groups = hp_wmi_groups, 1750 1750 }, 1751 - .remove_new = __exit_p(hp_wmi_bios_remove), 1751 + .remove = __exit_p(hp_wmi_bios_remove), 1752 1752 }; 1753 1753 1754 1754 static umode_t hp_wmi_hwmon_is_visible(const void *data,
+1 -1
drivers/platform/x86/hp/hp_accel.c
··· 372 372 /* For the HP MDPS aka 3D Driveguard */ 373 373 static struct platform_driver lis3lv02d_driver = { 374 374 .probe = lis3lv02d_probe, 375 - .remove_new = lis3lv02d_remove, 375 + .remove = lis3lv02d_remove, 376 376 .driver = { 377 377 .name = "hp_accel", 378 378 .pm = &hp_accel_pm,
+1 -1
drivers/platform/x86/hp/tc1100-wmi.c
··· 221 221 .pm = &tc1100_pm_ops, 222 222 #endif 223 223 }, 224 - .remove_new = tc1100_remove, 224 + .remove = tc1100_remove, 225 225 }; 226 226 227 227 static int __init tc1100_init(void)
+1 -1
drivers/platform/x86/huawei-wmi.c
··· 842 842 .name = "huawei-wmi", 843 843 }, 844 844 .probe = huawei_wmi_probe, 845 - .remove_new = huawei_wmi_remove, 845 + .remove = huawei_wmi_remove, 846 846 }; 847 847 848 848 static __init int huawei_wmi_init(void)
+1 -1
drivers/platform/x86/ideapad-laptop.c
··· 2309 2309 2310 2310 static struct platform_driver ideapad_acpi_driver = { 2311 2311 .probe = ideapad_acpi_add, 2312 - .remove_new = ideapad_acpi_remove, 2312 + .remove = ideapad_acpi_remove, 2313 2313 .driver = { 2314 2314 .name = "ideapad_acpi", 2315 2315 .pm = &ideapad_pm,
+29 -39
drivers/platform/x86/intel/Makefile
··· 17 17 18 18 19 19 # Intel input drivers 20 - intel-hid-y := hid.o 21 - obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o 22 - intel-vbtn-y := vbtn.o 23 - obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o 20 + intel-target-$(CONFIG_INTEL_HID_EVENT) += hid.o 21 + intel-target-$(CONFIG_INTEL_VBTN) += vbtn.o 24 22 25 23 # Intel miscellaneous drivers 26 - obj-$(CONFIG_INTEL_ISHTP_ECLITE) += ishtp_eclite.o 27 - intel_int0002_vgpio-y := int0002_vgpio.o 28 - obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o 29 - intel_oaktrail-y := oaktrail.o 30 - obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o 31 - intel_sdsi-y := sdsi.o 32 - obj-$(CONFIG_INTEL_SDSI) += intel_sdsi.o 33 - intel_vsec-y := vsec.o 34 - obj-$(CONFIG_INTEL_VSEC) += intel_vsec.o 24 + intel-target-$(CONFIG_INTEL_INT0002_VGPIO) += int0002_vgpio.o 25 + intel-target-$(CONFIG_INTEL_ISHTP_ECLITE) += ishtp_eclite.o 26 + intel-target-$(CONFIG_INTEL_OAKTRAIL) += oaktrail.o 27 + intel-target-$(CONFIG_INTEL_SDSI) += sdsi.o 28 + intel-target-$(CONFIG_INTEL_VSEC) += vsec.o 35 29 36 30 # Intel PMIC / PMC / P-Unit drivers 37 - intel_bxtwc_tmu-y := bxtwc_tmu.o 38 - obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o 39 - intel_crystal_cove_charger-y := crystal_cove_charger.o 40 - obj-$(CONFIG_X86_ANDROID_TABLETS) += intel_crystal_cove_charger.o 41 - intel_bytcrc_pwrsrc-y := bytcrc_pwrsrc.o 42 - obj-$(CONFIG_INTEL_BYTCRC_PWRSRC) += intel_bytcrc_pwrsrc.o 43 - intel_chtdc_ti_pwrbtn-y := chtdc_ti_pwrbtn.o 44 - obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o 45 - intel_chtwc_int33fe-y := chtwc_int33fe.o 46 - obj-$(CONFIG_INTEL_CHTWC_INT33FE) += intel_chtwc_int33fe.o 47 - intel_mrfld_pwrbtn-y := mrfld_pwrbtn.o 48 - obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o 49 - intel_punit_ipc-y := punit_ipc.o 50 - obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o 31 + intel-target-$(CONFIG_INTEL_BYTCRC_PWRSRC) += bytcrc_pwrsrc.o 32 + intel-target-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += bxtwc_tmu.o 33 + intel-target-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += chtdc_ti_pwrbtn.o 34 + intel-target-$(CONFIG_INTEL_CHTWC_INT33FE) += chtwc_int33fe.o 35 + intel-target-$(CONFIG_X86_ANDROID_TABLETS) += crystal_cove_charger.o 36 + intel-target-$(CONFIG_INTEL_MRFLD_PWRBTN) += mrfld_pwrbtn.o 37 + intel-target-$(CONFIG_INTEL_PUNIT_IPC) += punit_ipc.o 51 38 52 39 # TPMI drivers 53 - intel_vsec_tpmi-y := tpmi.o 54 - obj-$(CONFIG_INTEL_TPMI) += intel_vsec_tpmi.o 55 - obj-$(CONFIG_INTEL_PLR_TPMI) += intel_plr_tpmi.o 56 - 57 - intel_tpmi_power_domains-y := tpmi_power_domains.o 58 - obj-$(CONFIG_INTEL_TPMI_POWER_DOMAINS) += intel_tpmi_power_domains.o 40 + intel-target-$(CONFIG_INTEL_PLR_TPMI) += plr_tpmi.o 41 + intel-target-$(CONFIG_INTEL_TPMI_POWER_DOMAINS) += tpmi_power_domains.o 42 + intel-target-$(CONFIG_INTEL_TPMI) += vsec_tpmi.o 59 43 60 44 # Intel Uncore drivers 61 - intel-rst-y := rst.o 62 - obj-$(CONFIG_INTEL_RST) += intel-rst.o 63 - intel-smartconnect-y := smartconnect.o 64 - obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o 65 - intel_turbo_max_3-y := turbo_max_3.o 66 - obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o 45 + intel-target-$(CONFIG_INTEL_RST) += rst.o 46 + intel-target-$(CONFIG_INTEL_SMARTCONNECT) += smartconnect.o 47 + intel-target-$(CONFIG_INTEL_TURBO_MAX_3) += turbo_max_3.o 48 + 49 + # Add 'intel' prefix to each module listed in intel-target-* 50 + define INTEL_OBJ_TARGET 51 + intel-$(1)-y := $(1).o 52 + obj-$(2) += intel-$(1).o 53 + endef 54 + 55 + $(foreach target, $(basename $(intel-target-y)), $(eval $(call INTEL_OBJ_TARGET,$(target),y))) 56 + $(foreach target, $(basename $(intel-target-m)), $(eval $(call INTEL_OBJ_TARGET,$(target),m)))
+1 -1
drivers/platform/x86/intel/bxtwc_tmu.c
··· 131 131 132 132 static struct platform_driver bxt_wcove_tmu_driver = { 133 133 .probe = bxt_wcove_tmu_probe, 134 - .remove_new = bxt_wcove_tmu_remove, 134 + .remove = bxt_wcove_tmu_remove, 135 135 .driver = { 136 136 .name = "bxt_wcove_tmu", 137 137 .pm = &bxtwc_tmu_pm_ops,
+1 -1
drivers/platform/x86/intel/bytcrc_pwrsrc.c
··· 167 167 168 168 static struct platform_driver crc_pwrsrc_driver = { 169 169 .probe = crc_pwrsrc_probe, 170 - .remove_new = crc_pwrsrc_remove, 170 + .remove = crc_pwrsrc_remove, 171 171 .driver = { 172 172 .name = "crystal_cove_pwrsrc", 173 173 },
+1 -1
drivers/platform/x86/intel/chtdc_ti_pwrbtn.c
··· 84 84 .name = KBUILD_MODNAME, 85 85 }, 86 86 .probe = chtdc_ti_pwrbtn_probe, 87 - .remove_new = chtdc_ti_pwrbtn_remove, 87 + .remove = chtdc_ti_pwrbtn_remove, 88 88 .id_table = chtdc_ti_pwrbtn_id_table, 89 89 }; 90 90 module_platform_driver(chtdc_ti_pwrbtn_driver);
+1 -1
drivers/platform/x86/intel/chtwc_int33fe.c
··· 427 427 .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), 428 428 }, 429 429 .probe = cht_int33fe_typec_probe, 430 - .remove_new = cht_int33fe_typec_remove, 430 + .remove = cht_int33fe_typec_remove, 431 431 }; 432 432 433 433 module_platform_driver(cht_int33fe_typec_driver);
+8 -1
drivers/platform/x86/intel/hid.c
··· 119 119 }, 120 120 }, 121 121 { 122 + .ident = "Lenovo ThinkPad X1 Tablet Gen 1", 123 + .matches = { 124 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 125 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X12 Detachable Gen 1"), 126 + }, 127 + }, 128 + { 122 129 .ident = "Lenovo ThinkPad X1 Tablet Gen 2", 123 130 .matches = { 124 131 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ··· 754 747 .pm = &intel_hid_pl_pm_ops, 755 748 }, 756 749 .probe = intel_hid_probe, 757 - .remove_new = intel_hid_remove, 750 + .remove = intel_hid_remove, 758 751 }; 759 752 760 753 /*
+2 -2
drivers/platform/x86/intel/int0002_vgpio.c
··· 266 266 MODULE_DEVICE_TABLE(acpi, int0002_acpi_ids); 267 267 268 268 static struct platform_driver int0002_driver = { 269 - .driver = { 269 + .driver = { 270 270 .name = DRV_NAME, 271 271 .acpi_match_table = int0002_acpi_ids, 272 272 .pm = &int0002_pm_ops, 273 273 }, 274 274 .probe = int0002_probe, 275 - .remove_new = int0002_remove, 275 + .remove = int0002_remove, 276 276 }; 277 277 278 278 module_platform_driver(int0002_driver);
+1 -1
drivers/platform/x86/intel/int1092/intel_sar.c
··· 308 308 309 309 static struct platform_driver sar_driver = { 310 310 .probe = sar_probe, 311 - .remove_new = sar_remove, 311 + .remove = sar_remove, 312 312 .driver = { 313 313 .name = DRVNAME, 314 314 .acpi_match_table = ACPI_PTR(sar_device_ids)
+1 -1
drivers/platform/x86/intel/int3472/discrete.c
··· 392 392 .acpi_match_table = int3472_device_id, 393 393 }, 394 394 .probe = skl_int3472_discrete_probe, 395 - .remove_new = skl_int3472_discrete_remove, 395 + .remove = skl_int3472_discrete_remove, 396 396 }; 397 397 module_platform_driver(int3472_discrete); 398 398
drivers/platform/x86/intel/intel_plr_tpmi.c drivers/platform/x86/intel/plr_tpmi.c
+1 -1
drivers/platform/x86/intel/mrfld_pwrbtn.c
··· 97 97 .name = "mrfld_bcove_pwrbtn", 98 98 }, 99 99 .probe = mrfld_pwrbtn_probe, 100 - .remove_new = mrfld_pwrbtn_remove, 100 + .remove = mrfld_pwrbtn_remove, 101 101 .id_table = mrfld_pwrbtn_id_table, 102 102 }; 103 103 module_platform_driver(mrfld_pwrbtn_driver);
+1 -2
drivers/platform/x86/intel/pmc/arl.c
··· 687 687 static int arl_resume(struct pmc_dev *pmcdev) 688 688 { 689 689 arl_d3_fixup(); 690 - pmc_core_send_ltr_ignore(pmcdev, 3, 0); 691 690 692 - return pmc_core_resume_common(pmcdev); 691 + return cnl_resume(pmcdev); 693 692 } 694 693 695 694 int arl_core_init(struct pmc_dev *pmcdev)
+53
drivers/platform/x86/intel/pmc/cnp.c
··· 8 8 * 9 9 */ 10 10 11 + #include <linux/smp.h> 12 + #include <linux/suspend.h> 11 13 #include "core.h" 12 14 13 15 /* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */ ··· 206 204 .etr3_offset = ETR3_OFFSET, 207 205 }; 208 206 207 + 208 + /* 209 + * Disable C1 auto-demotion 210 + * 211 + * Aggressive C1 auto-demotion may lead to failure to enter the deepest C-state 212 + * during suspend-to-idle, causing high power consumption. To prevent this, we 213 + * disable C1 auto-demotion during suspend and re-enable on resume. 214 + * 215 + * Note that, although MSR_PKG_CST_CONFIG_CONTROL has 'package' in its name, it 216 + * is actually a per-core MSR on client platforms, affecting only a single CPU. 217 + * Therefore, it must be configured on all online CPUs. The online cpu mask is 218 + * unchanged during the phase of suspend/resume as user space is frozen. 219 + */ 220 + 221 + static DEFINE_PER_CPU(u64, pkg_cst_config); 222 + 223 + static void disable_c1_auto_demote(void *unused) 224 + { 225 + int cpunum = smp_processor_id(); 226 + u64 val; 227 + 228 + rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, val); 229 + per_cpu(pkg_cst_config, cpunum) = val; 230 + val &= ~NHM_C1_AUTO_DEMOTE; 231 + wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, val); 232 + 233 + pr_debug("%s: cpu:%d cst %llx\n", __func__, cpunum, val); 234 + } 235 + 236 + static void restore_c1_auto_demote(void *unused) 237 + { 238 + int cpunum = smp_processor_id(); 239 + 240 + wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, per_cpu(pkg_cst_config, cpunum)); 241 + 242 + pr_debug("%s: cpu:%d cst %llx\n", __func__, cpunum, 243 + per_cpu(pkg_cst_config, cpunum)); 244 + } 245 + 246 + static void s2idle_cpu_quirk(smp_call_func_t func) 247 + { 248 + if (pm_suspend_via_firmware()) 249 + return; 250 + 251 + on_each_cpu(func, NULL, true); 252 + } 253 + 209 254 void cnl_suspend(struct pmc_dev *pmcdev) 210 255 { 256 + s2idle_cpu_quirk(disable_c1_auto_demote); 257 + 211 258 /* 212 259 * Due to a hardware limitation, the GBE LTR blocks PC10 213 260 * when a cable is attached. To unblock PC10 during suspend, ··· 267 216 268 217 int cnl_resume(struct pmc_dev *pmcdev) 269 218 { 219 + s2idle_cpu_quirk(restore_c1_auto_demote); 220 + 270 221 pmc_core_send_ltr_ignore(pmcdev, 3, 0); 271 222 272 223 return pmc_core_resume_common(pmcdev);
+1 -1
drivers/platform/x86/intel/pmc/core.c
··· 1676 1676 .dev_groups = pmc_dev_groups, 1677 1677 }, 1678 1678 .probe = pmc_core_probe, 1679 - .remove_new = pmc_core_remove, 1679 + .remove = pmc_core_remove, 1680 1680 }; 1681 1681 1682 1682 module_platform_driver(pmc_core_driver);
+1 -2
drivers/platform/x86/intel/pmc/lnl.c
··· 546 546 static int lnl_resume(struct pmc_dev *pmcdev) 547 547 { 548 548 lnl_d3_fixup(); 549 - pmc_core_send_ltr_ignore(pmcdev, 3, 0); 550 549 551 - return pmc_core_resume_common(pmcdev); 550 + return cnl_resume(pmcdev); 552 551 } 553 552 554 553 int lnl_core_init(struct pmc_dev *pmcdev)
+1 -2
drivers/platform/x86/intel/pmc/mtl.c
··· 986 986 static int mtl_resume(struct pmc_dev *pmcdev) 987 987 { 988 988 mtl_d3_fixup(); 989 - pmc_core_send_ltr_ignore(pmcdev, 3, 0); 990 989 991 - return pmc_core_resume_common(pmcdev); 990 + return cnl_resume(pmcdev); 992 991 } 993 992 994 993 int mtl_core_init(struct pmc_dev *pmcdev)
+6 -4
drivers/platform/x86/intel/pmt/class.c
··· 59 59 } 60 60 61 61 int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, 62 - void __iomem *addr, u32 count) 62 + void __iomem *addr, loff_t off, u32 count) 63 63 { 64 64 if (cb && cb->read_telem) 65 - return cb->read_telem(pdev, guid, buf, count); 65 + return cb->read_telem(pdev, guid, buf, off, count); 66 + 67 + addr += off; 66 68 67 69 if (guid == GUID_SPR_PUNIT) 68 70 /* PUNIT on SPR only supports aligned 64-bit read */ ··· 98 96 count = entry->size - off; 99 97 100 98 count = pmt_telem_read_mmio(entry->ep->pcidev, entry->cb, entry->header.guid, buf, 101 - entry->base + off, count); 99 + entry->base, off, count); 102 100 103 101 return count; 104 102 } ··· 209 207 /* 210 208 * Some hardware use a different calculation for the base address 211 209 * when access_type == ACCESS_LOCAL. On the these systems 212 - * ACCCESS_LOCAL refers to an address in the same BAR as the 210 + * ACCESS_LOCAL refers to an address in the same BAR as the 213 211 * header but at a fixed offset. But as the header address was 214 212 * supplied to the driver, we don't know which BAR it was in. 215 213 * So search for the bar whose range includes the header address.
+1 -1
drivers/platform/x86/intel/pmt/class.h
··· 62 62 }; 63 63 64 64 int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, 65 - void __iomem *addr, u32 count); 65 + void __iomem *addr, loff_t off, u32 count); 66 66 bool intel_pmt_is_early_client_hw(struct device *dev); 67 67 int intel_pmt_dev_create(struct intel_pmt_entry *entry, 68 68 struct intel_pmt_namespace *ns,
+1 -1
drivers/platform/x86/intel/pmt/telemetry.c
··· 219 219 if (offset + NUM_BYTES_QWORD(count) > size) 220 220 return -EINVAL; 221 221 222 - pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base + offset, 222 + pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base, offset, 223 223 NUM_BYTES_QWORD(count)); 224 224 225 225 return ep->present ? 0 : -EPIPE;
+1 -1
drivers/platform/x86/intel/telemetry/pltdrv.c
··· 1163 1163 1164 1164 static struct platform_driver telemetry_soc_driver = { 1165 1165 .probe = telemetry_pltdrv_probe, 1166 - .remove_new = telemetry_pltdrv_remove, 1166 + .remove = telemetry_pltdrv_remove, 1167 1167 .driver = { 1168 1168 .name = DRIVER_NAME, 1169 1169 },
+1 -1
drivers/platform/x86/intel/tpmi.c drivers/platform/x86/intel/vsec_tpmi.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * intel-tpmi : Driver to enumerate TPMI features and create devices 3 + * Driver to enumerate TPMI features and create devices 4 4 * 5 5 * Copyright (c) 2023, Intel Corporation. 6 6 * All Rights Reserved.
+1 -1
drivers/platform/x86/intel/vbtn.c
··· 387 387 .pm = &intel_vbtn_pm_ops, 388 388 }, 389 389 .probe = intel_vbtn_probe, 390 - .remove_new = intel_vbtn_remove, 390 + .remove = intel_vbtn_remove, 391 391 }; 392 392 393 393 static acpi_status __init
-6
drivers/platform/x86/intel/vsec.c
··· 79 79 auxiliary_device_uninit(data); 80 80 } 81 81 82 - static DEFINE_MUTEX(vsec_ida_lock); 83 - 84 82 static void intel_vsec_dev_release(struct device *dev) 85 83 { 86 84 struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev); 87 85 88 86 xa_erase(&auxdev_array, intel_vsec_dev->id); 89 87 90 - mutex_lock(&vsec_ida_lock); 91 88 ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); 92 - mutex_unlock(&vsec_ida_lock); 93 89 94 90 kfree(intel_vsec_dev->resource); 95 91 kfree(intel_vsec_dev); ··· 109 113 return ret; 110 114 } 111 115 112 - mutex_lock(&vsec_ida_lock); 113 116 id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); 114 - mutex_unlock(&vsec_ida_lock); 115 117 if (id < 0) { 116 118 xa_erase(&auxdev_array, intel_vsec_dev->id); 117 119 kfree(intel_vsec_dev->resource);
+61 -81
drivers/platform/x86/intel_scu_ipc.c
··· 13 13 * along with other APIs. 14 14 */ 15 15 16 + #include <linux/cleanup.h> 16 17 #include <linux/delay.h> 17 18 #include <linux/device.h> 18 19 #include <linux/errno.h> ··· 57 56 58 57 struct intel_scu_ipc_dev { 59 58 struct device dev; 60 - struct resource mem; 61 59 struct module *owner; 62 - int irq; 63 60 void __iomem *ipc_base; 64 61 struct completion cmd_complete; 62 + 63 + struct intel_scu_ipc_data data; 65 64 }; 66 65 67 66 #define IPC_STATUS 0x04 ··· 100 99 */ 101 100 struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void) 102 101 { 103 - struct intel_scu_ipc_dev *scu = NULL; 102 + guard(mutex)(&ipclock); 104 103 105 - mutex_lock(&ipclock); 106 104 if (ipcdev) { 107 105 get_device(&ipcdev->dev); 108 106 /* 109 107 * Prevent the IPC provider from being unloaded while it 110 108 * is being used. 111 109 */ 112 - if (!try_module_get(ipcdev->owner)) 113 - put_device(&ipcdev->dev); 114 - else 115 - scu = ipcdev; 110 + if (try_module_get(ipcdev->owner)) 111 + return ipcdev; 112 + 113 + put_device(&ipcdev->dev); 116 114 } 117 115 118 - mutex_unlock(&ipclock); 119 - return scu; 116 + return NULL; 120 117 } 121 118 EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_get); 122 119 ··· 216 217 return __raw_readl(scu->ipc_base + IPC_STATUS); 217 218 } 218 219 219 - /* Read ipc byte data */ 220 - static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset) 221 - { 222 - return readb(scu->ipc_base + IPC_READ_BUFFER + offset); 223 - } 224 - 225 220 /* Read ipc u32 data */ 226 221 static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) 227 222 { ··· 255 262 256 263 static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) 257 264 { 258 - return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); 265 + return scu->data.irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); 259 266 } 260 267 261 268 static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu) ··· 288 295 289 296 memset(cbuf, 0, sizeof(cbuf)); 290 297 291 - mutex_lock(&ipclock); 298 + guard(mutex)(&ipclock); 299 + 292 300 scu = intel_scu_ipc_get(scu); 293 - if (IS_ERR(scu)) { 294 - mutex_unlock(&ipclock); 301 + if (IS_ERR(scu)) 295 302 return PTR_ERR(scu); 296 - } 297 303 298 304 for (nc = 0; nc < count; nc++, offset += 2) { 299 305 cbuf[offset] = addr[nc]; ··· 317 325 } 318 326 319 327 err = intel_scu_ipc_check_status(scu); 320 - if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ 321 - /* Workaround: values are read as 0 without memcpy_fromio */ 322 - memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16); 323 - for (nc = 0; nc < count; nc++) 324 - data[nc] = ipc_data_readb(scu, nc); 325 - } 326 - mutex_unlock(&ipclock); 327 - return err; 328 + if (err) 329 + return err; 330 + 331 + /* Read rbuf */ 332 + for (nc = 0, offset = 0; nc < 4; nc++, offset += 4) 333 + wbuf[nc] = ipc_data_readl(scu, offset); 334 + memcpy(data, wbuf, count); 335 + 336 + return 0; 328 337 } 329 338 330 339 /** ··· 446 453 u32 cmdval; 447 454 int err; 448 455 449 - mutex_lock(&ipclock); 456 + guard(mutex)(&ipclock); 457 + 450 458 scu = intel_scu_ipc_get(scu); 451 - if (IS_ERR(scu)) { 452 - mutex_unlock(&ipclock); 459 + if (IS_ERR(scu)) 453 460 return PTR_ERR(scu); 454 - } 455 461 456 462 cmdval = sub << 12 | cmd; 457 463 ipc_command(scu, cmdval); 458 464 err = intel_scu_ipc_check_status(scu); 459 - mutex_unlock(&ipclock); 460 465 if (err) 461 466 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 462 467 return err; ··· 483 492 { 484 493 size_t outbuflen = DIV_ROUND_UP(outlen, sizeof(u32)); 485 494 size_t inbuflen = DIV_ROUND_UP(inlen, sizeof(u32)); 486 - u32 cmdval, inbuf[4] = {}; 495 + u32 cmdval, inbuf[4] = {}, outbuf[4] = {}; 487 496 int i, err; 488 497 489 498 if (inbuflen > 4 || outbuflen > 4) 490 499 return -EINVAL; 491 500 492 - mutex_lock(&ipclock); 501 + guard(mutex)(&ipclock); 502 + 493 503 scu = intel_scu_ipc_get(scu); 494 - if (IS_ERR(scu)) { 495 - mutex_unlock(&ipclock); 504 + if (IS_ERR(scu)) 496 505 return PTR_ERR(scu); 497 - } 498 506 499 507 memcpy(inbuf, in, inlen); 500 508 for (i = 0; i < inbuflen; i++) ··· 502 512 cmdval = (size << 16) | (sub << 12) | cmd; 503 513 ipc_command(scu, cmdval); 504 514 err = intel_scu_ipc_check_status(scu); 505 - 506 - if (!err) { 507 - u32 outbuf[4] = {}; 508 - 509 - for (i = 0; i < outbuflen; i++) 510 - outbuf[i] = ipc_data_readl(scu, 4 * i); 511 - 512 - memcpy(out, outbuf, outlen); 515 + if (err) { 516 + dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 517 + return err; 513 518 } 514 519 515 - mutex_unlock(&ipclock); 516 - if (err) 517 - dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 518 - return err; 520 + for (i = 0; i < outbuflen; i++) 521 + outbuf[i] = ipc_data_readl(scu, 4 * i); 522 + 523 + memcpy(out, outbuf, outlen); 524 + 525 + return 0; 519 526 } 520 527 EXPORT_SYMBOL(intel_scu_ipc_dev_command_with_size); 521 528 ··· 536 549 537 550 static void intel_scu_ipc_release(struct device *dev) 538 551 { 539 - struct intel_scu_ipc_dev *scu; 552 + struct intel_scu_ipc_dev *scu = container_of(dev, struct intel_scu_ipc_dev, dev); 553 + struct intel_scu_ipc_data *data = &scu->data; 540 554 541 - scu = container_of(dev, struct intel_scu_ipc_dev, dev); 542 - if (scu->irq > 0) 543 - free_irq(scu->irq, scu); 555 + if (data->irq > 0) 556 + free_irq(data->irq, scu); 544 557 iounmap(scu->ipc_base); 545 - release_mem_region(scu->mem.start, resource_size(&scu->mem)); 558 + release_mem_region(data->mem.start, resource_size(&data->mem)); 546 559 kfree(scu); 547 560 } 548 561 ··· 563 576 struct module *owner) 564 577 { 565 578 int err; 579 + struct intel_scu_ipc_data *data; 566 580 struct intel_scu_ipc_dev *scu; 567 581 void __iomem *ipc_base; 568 582 569 - mutex_lock(&ipclock); 583 + guard(mutex)(&ipclock); 584 + 570 585 /* We support only one IPC */ 571 - if (ipcdev) { 572 - err = -EBUSY; 573 - goto err_unlock; 574 - } 586 + if (ipcdev) 587 + return ERR_PTR(-EBUSY); 575 588 576 589 scu = kzalloc(sizeof(*scu), GFP_KERNEL); 577 - if (!scu) { 578 - err = -ENOMEM; 579 - goto err_unlock; 580 - } 590 + if (!scu) 591 + return ERR_PTR(-ENOMEM); 581 592 582 593 scu->owner = owner; 583 594 scu->dev.parent = parent; 584 595 scu->dev.class = &intel_scu_ipc_class; 585 596 scu->dev.release = intel_scu_ipc_release; 586 597 587 - if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem), 588 - "intel_scu_ipc")) { 598 + memcpy(&scu->data, scu_data, sizeof(scu->data)); 599 + data = &scu->data; 600 + 601 + if (!request_mem_region(data->mem.start, resource_size(&data->mem), "intel_scu_ipc")) { 589 602 err = -EBUSY; 590 603 goto err_free; 591 604 } 592 605 593 - ipc_base = ioremap(scu_data->mem.start, resource_size(&scu_data->mem)); 606 + ipc_base = ioremap(data->mem.start, resource_size(&data->mem)); 594 607 if (!ipc_base) { 595 608 err = -ENOMEM; 596 609 goto err_release; 597 610 } 598 611 599 612 scu->ipc_base = ipc_base; 600 - scu->mem = scu_data->mem; 601 - scu->irq = scu_data->irq; 602 613 init_completion(&scu->cmd_complete); 603 614 604 - if (scu->irq > 0) { 605 - err = request_irq(scu->irq, ioc, 0, "intel_scu_ipc", scu); 615 + if (data->irq > 0) { 616 + err = request_irq(data->irq, ioc, 0, "intel_scu_ipc", scu); 606 617 if (err) 607 618 goto err_unmap; 608 619 } ··· 613 628 err = device_register(&scu->dev); 614 629 if (err) { 615 630 put_device(&scu->dev); 616 - goto err_unlock; 631 + return ERR_PTR(err); 617 632 } 618 633 619 634 /* Assign device at last */ 620 635 ipcdev = scu; 621 - mutex_unlock(&ipclock); 622 - 623 636 return scu; 624 637 625 638 err_unmap: 626 639 iounmap(ipc_base); 627 640 err_release: 628 - release_mem_region(scu_data->mem.start, resource_size(&scu_data->mem)); 641 + release_mem_region(data->mem.start, resource_size(&data->mem)); 629 642 err_free: 630 643 kfree(scu); 631 - err_unlock: 632 - mutex_unlock(&ipclock); 633 - 634 644 return ERR_PTR(err); 635 645 } 636 646 EXPORT_SYMBOL_GPL(__intel_scu_ipc_register); ··· 639 659 */ 640 660 void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu) 641 661 { 642 - mutex_lock(&ipclock); 662 + guard(mutex)(&ipclock); 663 + 643 664 if (!WARN_ON(!ipcdev)) { 644 665 ipcdev = NULL; 645 666 device_unregister(&scu->dev); 646 667 } 647 - mutex_unlock(&ipclock); 648 668 } 649 669 EXPORT_SYMBOL_GPL(intel_scu_ipc_unregister); 650 670
+1 -1
drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c
··· 298 298 299 299 static struct platform_driver yt2_1380_fc_pdev_driver = { 300 300 .probe = yt2_1380_fc_pdev_probe, 301 - .remove_new = yt2_1380_fc_pdev_remove, 301 + .remove = yt2_1380_fc_pdev_remove, 302 302 .driver = { 303 303 .name = YT2_1380_FC_PDEV_NAME, 304 304 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+1 -1
drivers/platform/x86/lenovo-yogabook.c
··· 536 536 537 537 static struct platform_driver yogabook_pdev_driver = { 538 538 .probe = yogabook_pdev_probe, 539 - .remove_new = yogabook_pdev_remove, 539 + .remove = yogabook_pdev_remove, 540 540 .driver = { 541 541 .name = YB_PDEV_NAME, 542 542 .pm = pm_sleep_ptr(&yogabook_pm_ops),
+1 -1
drivers/platform/x86/mlx-platform.c
··· 6633 6633 .probe_type = PROBE_FORCE_SYNCHRONOUS, 6634 6634 }, 6635 6635 .probe = mlxplat_probe, 6636 - .remove_new = mlxplat_remove, 6636 + .remove = mlxplat_remove, 6637 6637 }; 6638 6638 6639 6639 static int __init mlxplat_init(void)
+1
drivers/platform/x86/p2sb.c
··· 25 25 26 26 static const struct x86_cpu_id p2sb_cpu_ids[] = { 27 27 X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, P2SB_DEVFN_GOLDMONT), 28 + X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS, P2SB_DEVFN_GOLDMONT), 28 29 {} 29 30 }; 30 31
+7 -3
drivers/platform/x86/panasonic-laptop.c
··· 614 614 result = 1; 615 615 break; 616 616 default: 617 - result = -EIO; 618 - break; 617 + return -EIO; 619 618 } 620 619 return sysfs_emit(buf, "%u\n", result); 621 620 } ··· 760 761 static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr, 761 762 char *buf) 762 763 { 763 - return sysfs_emit(buf, "%d\n", get_optd_power_state()); 764 + int state = get_optd_power_state(); 765 + 766 + if (state < 0) 767 + return state; 768 + 769 + return sysfs_emit(buf, "%d\n", state); 764 770 } 765 771 766 772 static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr,
+1 -1
drivers/platform/x86/samsung-q10.c
··· 78 78 .name = KBUILD_MODNAME, 79 79 }, 80 80 .probe = samsungq10_probe, 81 - .remove_new = samsungq10_remove, 81 + .remove = samsungq10_remove, 82 82 }; 83 83 84 84 static struct platform_device *samsungq10_device;
+1 -1
drivers/platform/x86/sel3350-platform.c
··· 235 235 236 236 static struct platform_driver sel3350_platform_driver = { 237 237 .probe = sel3350_probe, 238 - .remove_new = sel3350_remove, 238 + .remove = sel3350_remove, 239 239 .driver = { 240 240 .name = "sel3350-platform", 241 241 .acpi_match_table = sel3350_device_ids,
+1 -1
drivers/platform/x86/serial-multi-instantiate.c
··· 409 409 .acpi_match_table = smi_acpi_ids, 410 410 }, 411 411 .probe = smi_probe, 412 - .remove_new = smi_remove, 412 + .remove = smi_remove, 413 413 }; 414 414 module_platform_driver(smi_driver); 415 415
+1 -1
drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c
··· 37 37 38 38 static struct platform_driver simatic_ipc_batt_driver = { 39 39 .probe = simatic_ipc_batt_apollolake_probe, 40 - .remove_new = simatic_ipc_batt_apollolake_remove, 40 + .remove = simatic_ipc_batt_apollolake_remove, 41 41 .driver = { 42 42 .name = KBUILD_MODNAME, 43 43 },
+1 -1
drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c
··· 37 37 38 38 static struct platform_driver simatic_ipc_batt_driver = { 39 39 .probe = simatic_ipc_batt_elkhartlake_probe, 40 - .remove_new = simatic_ipc_batt_elkhartlake_remove, 40 + .remove = simatic_ipc_batt_elkhartlake_remove, 41 41 .driver = { 42 42 .name = KBUILD_MODNAME, 43 43 },
+1 -1
drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c
··· 73 73 74 74 static struct platform_driver simatic_ipc_batt_driver = { 75 75 .probe = simatic_ipc_batt_f7188x_probe, 76 - .remove_new = simatic_ipc_batt_f7188x_remove, 76 + .remove = simatic_ipc_batt_f7188x_remove, 77 77 .driver = { 78 78 .name = KBUILD_MODNAME, 79 79 },
+1 -1
drivers/platform/x86/siemens/simatic-ipc-batt.c
··· 239 239 240 240 static struct platform_driver simatic_ipc_batt_driver = { 241 241 .probe = simatic_ipc_batt_io_probe, 242 - .remove_new = simatic_ipc_batt_io_remove, 242 + .remove = simatic_ipc_batt_io_remove, 243 243 .driver = { 244 244 .name = KBUILD_MODNAME, 245 245 },
+111 -38
drivers/platform/x86/think-lmi.c
··· 12 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 13 14 14 #include <linux/acpi.h> 15 + #include <linux/array_size.h> 15 16 #include <linux/errno.h> 16 17 #include <linux/fs.h> 17 18 #include <linux/mutex.h> ··· 170 169 */ 171 170 #define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4" 172 171 173 - #define TLMI_POP_PWD BIT(0) /* Supervisor */ 174 - #define TLMI_PAP_PWD BIT(1) /* Power-on */ 175 - #define TLMI_HDD_PWD BIT(2) /* HDD/NVME */ 176 - #define TLMI_SMP_PWD BIT(6) /* System Management */ 177 - #define TLMI_CERT BIT(7) /* Certificate Based */ 172 + #define TLMI_POP_PWD BIT(0) /* Supervisor */ 173 + #define TLMI_PAP_PWD BIT(1) /* Power-on */ 174 + #define TLMI_HDD_PWD BIT(2) /* HDD/NVME */ 175 + #define TLMI_SMP_PWD BIT(6) /* System Management */ 176 + #define TLMI_CERT_SVC BIT(7) /* Admin Certificate Based */ 177 + #define TLMI_CERT_SMC BIT(8) /* System Certificate Based */ 178 178 179 179 static const struct tlmi_err_codes tlmi_errs[] = { 180 180 {"Success", 0}, ··· 393 391 { 394 392 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 395 393 396 - return sysfs_emit(buf, "%d\n", setting->valid); 394 + return sysfs_emit(buf, "%d\n", setting->pwd_enabled || setting->cert_installed); 397 395 } 398 396 399 397 static struct kobj_attribute auth_is_pass_set = __ATTR_RO(is_enabled); ··· 471 469 if (ret) 472 470 goto out; 473 471 474 - if (tlmi_priv.pwd_admin->valid) { 472 + /* 473 + * Note admin password is not always required if SMPControl enabled in BIOS, 474 + * So only set if it's configured. 475 + * Let BIOS figure it out - we'll get an error if operation is not permitted 476 + */ 477 + if (tlmi_priv.pwd_admin->pwd_enabled && strlen(tlmi_priv.pwd_admin->password)) { 475 478 ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", 476 479 tlmi_priv.pwd_admin->password); 477 480 if (ret) ··· 531 524 static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr, 532 525 char *buf) 533 526 { 527 + struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 528 + 529 + if (setting->cert_installed) 530 + return sysfs_emit(buf, "certificate\n"); 534 531 return sysfs_emit(buf, "password\n"); 535 532 } 536 533 static struct kobj_attribute auth_mechanism = __ATTR_RO(mechanism); ··· 655 644 656 645 static struct kobj_attribute auth_level = __ATTR_RW(level); 657 646 647 + static char *cert_command(struct tlmi_pwd_setting *setting, const char *arg1, const char *arg2) 648 + { 649 + /* Prepend with SVC or SMC if multicert supported */ 650 + if (tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) 651 + return kasprintf(GFP_KERNEL, "%s,%s,%s", 652 + setting == tlmi_priv.pwd_admin ? "SVC" : "SMC", 653 + arg1, arg2); 654 + else 655 + return kasprintf(GFP_KERNEL, "%s,%s", arg1, arg2); 656 + } 657 + 658 658 static ssize_t cert_thumbprint(char *buf, const char *arg, int count) 659 659 { 660 660 const struct acpi_buffer input = { strlen(arg), (char *)arg }; ··· 691 669 return count; 692 670 } 693 671 672 + static char *thumbtypes[] = {"Md5", "Sha1", "Sha256"}; 673 + 694 674 static ssize_t certificate_thumbprint_show(struct kobject *kobj, struct kobj_attribute *attr, 695 675 char *buf) 696 676 { 697 677 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 678 + unsigned int i; 698 679 int count = 0; 680 + char *wmistr; 699 681 700 682 if (!tlmi_priv.certificate_support || !setting->cert_installed) 701 683 return -EOPNOTSUPP; 702 684 703 - count += cert_thumbprint(buf, "Md5", count); 704 - count += cert_thumbprint(buf, "Sha1", count); 705 - count += cert_thumbprint(buf, "Sha256", count); 685 + for (i = 0; i < ARRAY_SIZE(thumbtypes); i++) { 686 + if (tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) { 687 + /* Format: 'SVC | SMC, Thumbtype' */ 688 + wmistr = kasprintf(GFP_KERNEL, "%s,%s", 689 + setting == tlmi_priv.pwd_admin ? "SVC" : "SMC", 690 + thumbtypes[i]); 691 + } else { 692 + /* Format: 'Thumbtype' */ 693 + wmistr = kasprintf(GFP_KERNEL, "%s", thumbtypes[i]); 694 + } 695 + if (!wmistr) 696 + return -ENOMEM; 697 + count += cert_thumbprint(buf, wmistr, count); 698 + kfree(wmistr); 699 + } 700 + 706 701 return count; 707 702 } 708 703 ··· 751 712 return -ENOMEM; 752 713 753 714 /* Format: 'Password,Signature' */ 754 - auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature); 715 + auth_str = cert_command(setting, passwd, setting->signature); 755 716 if (!auth_str) { 756 717 kfree_sensitive(passwd); 757 718 return -ENOMEM; ··· 765 726 766 727 static struct kobj_attribute auth_cert_to_password = __ATTR_WO(cert_to_password); 767 728 729 + enum cert_install_mode { 730 + TLMI_CERT_INSTALL, 731 + TLMI_CERT_UPDATE, 732 + }; 733 + 768 734 static ssize_t certificate_store(struct kobject *kobj, 769 735 struct kobj_attribute *attr, 770 736 const char *buf, size_t count) 771 737 { 772 738 struct tlmi_pwd_setting *setting = to_tlmi_pwd_setting(kobj); 739 + enum cert_install_mode install_mode = TLMI_CERT_INSTALL; 773 740 char *auth_str, *new_cert; 741 + char *signature; 774 742 char *guid; 775 743 int ret; 776 744 ··· 794 748 return -EACCES; 795 749 796 750 /* Format: 'serial#, signature' */ 797 - auth_str = kasprintf(GFP_KERNEL, "%s,%s", 798 - dmi_get_system_info(DMI_PRODUCT_SERIAL), 799 - setting->signature); 751 + auth_str = cert_command(setting, 752 + dmi_get_system_info(DMI_PRODUCT_SERIAL), 753 + setting->signature); 800 754 if (!auth_str) 801 755 return -ENOMEM; 802 756 ··· 813 767 814 768 if (setting->cert_installed) { 815 769 /* Certificate is installed so this is an update */ 816 - if (!setting->signature || !setting->signature[0]) { 770 + install_mode = TLMI_CERT_UPDATE; 771 + /* If admin account enabled - need to use its signature */ 772 + if (tlmi_priv.pwd_admin->pwd_enabled) 773 + signature = tlmi_priv.pwd_admin->signature; 774 + else 775 + signature = setting->signature; 776 + } else { /* Cert install */ 777 + /* Check if SMC and SVC already installed */ 778 + if ((setting == tlmi_priv.pwd_system) && tlmi_priv.pwd_admin->cert_installed) { 779 + /* This gets treated as a cert update */ 780 + install_mode = TLMI_CERT_UPDATE; 781 + signature = tlmi_priv.pwd_admin->signature; 782 + } else { /* Regular cert install */ 783 + install_mode = TLMI_CERT_INSTALL; 784 + signature = setting->signature; 785 + } 786 + } 787 + 788 + if (install_mode == TLMI_CERT_UPDATE) { 789 + /* This is a certificate update */ 790 + if (!signature || !signature[0]) { 817 791 kfree(new_cert); 818 792 return -EACCES; 819 793 } 820 794 guid = LENOVO_UPDATE_BIOS_CERT_GUID; 821 795 /* Format: 'Certificate,Signature' */ 822 - auth_str = kasprintf(GFP_KERNEL, "%s,%s", 823 - new_cert, setting->signature); 796 + auth_str = cert_command(setting, new_cert, signature); 824 797 } else { 825 798 /* This is a fresh install */ 826 - if (!setting->valid || !setting->password[0]) { 799 + /* To set admin cert, a password must be enabled */ 800 + if ((setting == tlmi_priv.pwd_admin) && 801 + (!setting->pwd_enabled || !setting->password[0])) { 827 802 kfree(new_cert); 828 803 return -EACCES; 829 804 } 830 805 guid = LENOVO_SET_BIOS_CERT_GUID; 831 - /* Format: 'Certificate,Admin-password' */ 832 - auth_str = kasprintf(GFP_KERNEL, "%s,%s", 833 - new_cert, setting->password); 806 + /* Format: 'Certificate, password' */ 807 + auth_str = cert_command(setting, new_cert, setting->password); 834 808 } 835 809 kfree(new_cert); 836 810 if (!auth_str) ··· 930 864 return 0; 931 865 } 932 866 933 - /* We only display certificates on Admin account, if supported */ 867 + /* We only display certificates, if supported */ 934 868 if (attr == &auth_certificate.attr || 935 869 attr == &auth_signature.attr || 936 870 attr == &auth_save_signature.attr || 937 871 attr == &auth_cert_thumb.attr || 938 872 attr == &auth_cert_to_password.attr) { 939 - if ((setting == tlmi_priv.pwd_admin) && tlmi_priv.certificate_support) 940 - return attr->mode; 873 + if (tlmi_priv.certificate_support) { 874 + if (setting == tlmi_priv.pwd_admin) 875 + return attr->mode; 876 + if ((tlmi_priv.pwdcfg.core.password_mode >= TLMI_PWDCFG_MODE_MULTICERT) && 877 + (setting == tlmi_priv.pwd_system)) 878 + return attr->mode; 879 + } 941 880 return 0; 942 881 } 943 882 ··· 1090 1019 * Workstation's require the opcode to be set before changing the 1091 1020 * attribute. 1092 1021 */ 1093 - if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 1022 + if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) { 1094 1023 ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", 1095 1024 tlmi_priv.pwd_admin->password); 1096 1025 if (ret) ··· 1113 1042 else 1114 1043 ret = tlmi_save_bios_settings(""); 1115 1044 } else { /* old non-opcode based authentication method (deprecated) */ 1116 - if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 1045 + if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) { 1117 1046 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 1118 1047 tlmi_priv.pwd_admin->password, 1119 1048 encoding_options[tlmi_priv.pwd_admin->encoding], ··· 1286 1215 if (ret) 1287 1216 goto out; 1288 1217 } else if (tlmi_priv.opcode_support) { 1289 - if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 1218 + if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) { 1290 1219 ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", 1291 1220 tlmi_priv.pwd_admin->password); 1292 1221 if (ret) ··· 1294 1223 } 1295 1224 ret = tlmi_save_bios_settings(""); 1296 1225 } else { /* old non-opcode based authentication method (deprecated) */ 1297 - if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 1226 + if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) { 1298 1227 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 1299 1228 tlmi_priv.pwd_admin->password, 1300 1229 encoding_options[tlmi_priv.pwd_admin->encoding], ··· 1344 1273 if (!new_setting) 1345 1274 return -ENOMEM; 1346 1275 1347 - if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { 1276 + if (tlmi_priv.pwd_admin->pwd_enabled && tlmi_priv.pwd_admin->password[0]) { 1348 1277 auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", 1349 1278 tlmi_priv.pwd_admin->password, 1350 1279 encoding_options[tlmi_priv.pwd_admin->encoding], ··· 1708 1637 goto fail_clear_attr; 1709 1638 1710 1639 if (tlmi_priv.pwdcfg.core.password_state & TLMI_PAP_PWD) 1711 - tlmi_priv.pwd_admin->valid = true; 1640 + tlmi_priv.pwd_admin->pwd_enabled = true; 1712 1641 1713 1642 tlmi_priv.pwd_power = tlmi_create_auth("pop", "power-on"); 1714 1643 if (!tlmi_priv.pwd_power) 1715 1644 goto fail_clear_attr; 1716 1645 1717 1646 if (tlmi_priv.pwdcfg.core.password_state & TLMI_POP_PWD) 1718 - tlmi_priv.pwd_power->valid = true; 1647 + tlmi_priv.pwd_power->pwd_enabled = true; 1719 1648 1720 1649 if (tlmi_priv.opcode_support) { 1721 1650 tlmi_priv.pwd_system = tlmi_create_auth("smp", "system"); ··· 1723 1652 goto fail_clear_attr; 1724 1653 1725 1654 if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD) 1726 - tlmi_priv.pwd_system->valid = true; 1655 + tlmi_priv.pwd_system->pwd_enabled = true; 1727 1656 1728 1657 tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); 1729 1658 if (!tlmi_priv.pwd_hdd) ··· 1741 1670 /* Check if PWD is configured and set index to first drive found */ 1742 1671 if (tlmi_priv.pwdcfg.ext.hdd_user_password || 1743 1672 tlmi_priv.pwdcfg.ext.hdd_master_password) { 1744 - tlmi_priv.pwd_hdd->valid = true; 1673 + tlmi_priv.pwd_hdd->pwd_enabled = true; 1745 1674 if (tlmi_priv.pwdcfg.ext.hdd_master_password) 1746 1675 tlmi_priv.pwd_hdd->index = 1747 1676 ffs(tlmi_priv.pwdcfg.ext.hdd_master_password) - 1; ··· 1751 1680 } 1752 1681 if (tlmi_priv.pwdcfg.ext.nvme_user_password || 1753 1682 tlmi_priv.pwdcfg.ext.nvme_master_password) { 1754 - tlmi_priv.pwd_nvme->valid = true; 1683 + tlmi_priv.pwd_nvme->pwd_enabled = true; 1755 1684 if (tlmi_priv.pwdcfg.ext.nvme_master_password) 1756 1685 tlmi_priv.pwd_nvme->index = 1757 1686 ffs(tlmi_priv.pwdcfg.ext.nvme_master_password) - 1; ··· 1762 1691 } 1763 1692 } 1764 1693 1765 - if (tlmi_priv.certificate_support && 1766 - (tlmi_priv.pwdcfg.core.password_state & TLMI_CERT)) 1767 - tlmi_priv.pwd_admin->cert_installed = true; 1768 - 1694 + if (tlmi_priv.certificate_support) { 1695 + tlmi_priv.pwd_admin->cert_installed = 1696 + tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SVC; 1697 + tlmi_priv.pwd_system->cert_installed = 1698 + tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SMC; 1699 + } 1769 1700 return 0; 1770 1701 1771 1702 fail_clear_attr:
+5 -1
drivers/platform/x86/think-lmi.h
··· 41 41 }; 42 42 43 43 /* password configuration details */ 44 + #define TLMI_PWDCFG_MODE_LEGACY 0 45 + #define TLMI_PWDCFG_MODE_PASSWORD 1 46 + #define TLMI_PWDCFG_MODE_MULTICERT 3 47 + 44 48 struct tlmi_pwdcfg_core { 45 49 uint32_t password_mode; 46 50 uint32_t password_state; ··· 69 65 /* password setting details */ 70 66 struct tlmi_pwd_setting { 71 67 struct kobject kobj; 72 - bool valid; 68 + bool pwd_enabled; 73 69 char password[TLMI_PWD_BUFSIZE]; 74 70 const char *pwd_type; 75 71 const char *role;
+64 -34
drivers/platform/x86/wmi.c
··· 22 22 #include <linux/device.h> 23 23 #include <linux/init.h> 24 24 #include <linux/kernel.h> 25 - #include <linux/list.h> 26 25 #include <linux/module.h> 27 26 #include <linux/platform_device.h> 28 27 #include <linux/rwsem.h> ··· 35 36 MODULE_AUTHOR("Carlos Corbacho"); 36 37 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver"); 37 38 MODULE_LICENSE("GPL"); 38 - 39 - static LIST_HEAD(wmi_block_list); 40 39 41 40 struct guid_block { 42 41 guid_t guid; ··· 60 63 61 64 struct wmi_block { 62 65 struct wmi_device dev; 63 - struct list_head list; 64 66 struct guid_block gblock; 65 67 struct acpi_device *acpi_device; 66 68 struct rw_semaphore notify_lock; /* Protects notify callback add/remove */ ··· 69 73 unsigned long flags; 70 74 }; 71 75 76 + struct wmi_guid_count_context { 77 + const guid_t *guid; 78 + int count; 79 + }; 72 80 73 81 /* 74 82 * If the GUID data block is marked as expensive, we must enable and ··· 91 91 MODULE_DEVICE_TABLE(acpi, wmi_device_ids); 92 92 93 93 #define dev_to_wblock(__dev) container_of_const(__dev, struct wmi_block, dev.dev) 94 - #define dev_to_wdev(__dev) container_of_const(__dev, struct wmi_device, dev) 95 94 96 95 /* 97 96 * GUID parsing functions ··· 198 199 if (!dev) 199 200 return ERR_PTR(-ENODEV); 200 201 201 - return dev_to_wdev(dev); 202 + return to_wmi_device(dev); 202 203 } 203 204 204 205 static void wmi_device_put(struct wmi_device *wdev) ··· 653 654 } 654 655 EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid); 655 656 656 - #define drv_to_wdrv(__drv) container_of_const(__drv, struct wmi_driver, driver) 657 - 658 657 /* 659 658 * sysfs interface 660 659 */ ··· 758 761 static ssize_t setable_show(struct device *dev, struct device_attribute *attr, 759 762 char *buf) 760 763 { 761 - struct wmi_device *wdev = dev_to_wdev(dev); 764 + struct wmi_device *wdev = to_wmi_device(dev); 762 765 763 766 return sysfs_emit(buf, "%d\n", (int)wdev->setable); 764 767 } ··· 800 803 801 804 static int wmi_dev_match(struct device *dev, const struct device_driver *driver) 802 805 { 803 - const struct wmi_driver *wmi_driver = drv_to_wdrv(driver); 806 + const struct wmi_driver *wmi_driver = to_wmi_driver(driver); 804 807 struct wmi_block *wblock = dev_to_wblock(dev); 805 808 const struct wmi_device_id *id = wmi_driver->id_table; 806 809 ··· 824 827 static int wmi_dev_probe(struct device *dev) 825 828 { 826 829 struct wmi_block *wblock = dev_to_wblock(dev); 827 - struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); 830 + struct wmi_driver *wdriver = to_wmi_driver(dev->driver); 828 831 int ret = 0; 829 832 830 833 /* Some older WMI drivers will break if instantiated multiple times, ··· 848 851 dev_warn(dev, "failed to enable device -- probing anyway\n"); 849 852 850 853 if (wdriver->probe) { 851 - ret = wdriver->probe(dev_to_wdev(dev), 854 + ret = wdriver->probe(to_wmi_device(dev), 852 855 find_guid_context(wblock, wdriver)); 853 856 if (ret) { 854 857 if (ACPI_FAILURE(wmi_method_enable(wblock, false))) ··· 868 871 static void wmi_dev_remove(struct device *dev) 869 872 { 870 873 struct wmi_block *wblock = dev_to_wblock(dev); 871 - struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); 874 + struct wmi_driver *wdriver = to_wmi_driver(dev->driver); 872 875 873 876 down_write(&wblock->notify_lock); 874 877 wblock->driver_ready = false; 875 878 up_write(&wblock->notify_lock); 876 879 877 880 if (wdriver->remove) 878 - wdriver->remove(dev_to_wdev(dev)); 881 + wdriver->remove(to_wmi_device(dev)); 879 882 880 883 if (ACPI_FAILURE(wmi_method_enable(wblock, false))) 881 884 dev_warn(dev, "failed to disable device\n"); 885 + } 886 + 887 + static void wmi_dev_shutdown(struct device *dev) 888 + { 889 + struct wmi_driver *wdriver; 890 + struct wmi_block *wblock; 891 + 892 + if (dev->driver) { 893 + wdriver = to_wmi_driver(dev->driver); 894 + wblock = dev_to_wblock(dev); 895 + 896 + /* 897 + * Some machines return bogus WMI event data when disabling 898 + * the WMI event. Because of this we must prevent the associated 899 + * WMI driver from receiving new WMI events before disabling it. 900 + */ 901 + down_write(&wblock->notify_lock); 902 + wblock->driver_ready = false; 903 + up_write(&wblock->notify_lock); 904 + 905 + if (wdriver->shutdown) 906 + wdriver->shutdown(to_wmi_device(dev)); 907 + 908 + if (ACPI_FAILURE(wmi_method_enable(wblock, false))) 909 + dev_warn(dev, "Failed to disable device\n"); 910 + } 882 911 } 883 912 884 913 static struct class wmi_bus_class = { ··· 918 895 .uevent = wmi_dev_uevent, 919 896 .probe = wmi_dev_probe, 920 897 .remove = wmi_dev_remove, 898 + .shutdown = wmi_dev_shutdown, 921 899 }; 922 900 923 901 static const struct device_type wmi_type_event = { ··· 939 915 .release = wmi_dev_release, 940 916 }; 941 917 942 - /* 943 - * _WDG is a static list that is only parsed at startup, 944 - * so it's safe to count entries without extra protection. 945 - */ 918 + static int wmi_count_guids(struct device *dev, void *data) 919 + { 920 + struct wmi_guid_count_context *context = data; 921 + struct wmi_block *wblock = dev_to_wblock(dev); 922 + 923 + if (guid_equal(&wblock->gblock.guid, context->guid)) 924 + context->count++; 925 + 926 + return 0; 927 + } 928 + 946 929 static int guid_count(const guid_t *guid) 947 930 { 948 - struct wmi_block *wblock; 949 - int count = 0; 931 + struct wmi_guid_count_context context = { 932 + .guid = guid, 933 + .count = 0, 934 + }; 935 + int ret; 950 936 951 - list_for_each_entry(wblock, &wmi_block_list, list) { 952 - if (guid_equal(&wblock->gblock.guid, guid)) 953 - count++; 954 - } 937 + ret = bus_for_each_dev(&wmi_bus_type, NULL, &context, wmi_count_guids); 938 + if (ret < 0) 939 + return ret; 955 940 956 - return count; 941 + return context.count; 957 942 } 958 943 959 944 static int wmi_create_device(struct device *wmi_bus_dev, ··· 973 940 struct acpi_device_info *info; 974 941 acpi_handle method_handle; 975 942 acpi_status status; 976 - uint count; 943 + int count; 977 944 978 945 if (wblock->gblock.flags & ACPI_WMI_EVENT) { 979 946 wblock->dev.dev.type = &wmi_type_event; ··· 1041 1008 wblock->dev.dev.parent = wmi_bus_dev; 1042 1009 1043 1010 count = guid_count(&wblock->gblock.guid); 1011 + if (count < 0) 1012 + return count; 1013 + 1044 1014 if (count) { 1045 1015 dev_set_name(&wblock->dev.dev, "%pUL-%d", &wblock->gblock.guid, count); 1046 1016 set_bit(WMI_GUID_DUPLICATED, &wblock->flags); ··· 1129 1093 continue; 1130 1094 } 1131 1095 1132 - list_add_tail(&wblock->list, &wmi_block_list); 1133 - 1134 1096 retval = wmi_add_device(pdev, &wblock->dev); 1135 1097 if (retval) { 1136 1098 dev_err(wmi_bus_dev, "failed to register %pUL\n", 1137 1099 &wblock->gblock.guid); 1138 1100 1139 - list_del(&wblock->list); 1140 1101 put_device(&wblock->dev.dev); 1141 1102 } 1142 1103 } ··· 1171 1138 1172 1139 static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj) 1173 1140 { 1174 - struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver); 1141 + struct wmi_driver *driver = to_wmi_driver(wblock->dev.dev.driver); 1175 1142 1176 1143 if (!obj && !driver->no_notify_data) { 1177 1144 dev_warn(&wblock->dev.dev, "Event contains no event data\n"); ··· 1233 1200 1234 1201 static int wmi_remove_device(struct device *dev, void *data) 1235 1202 { 1236 - struct wmi_block *wblock = dev_to_wblock(dev); 1237 - 1238 - list_del(&wblock->list); 1239 1203 device_unregister(dev); 1240 1204 1241 1205 return 0; ··· 1331 1301 .acpi_match_table = wmi_device_ids, 1332 1302 }, 1333 1303 .probe = acpi_wmi_probe, 1334 - .remove_new = acpi_wmi_remove, 1304 + .remove = acpi_wmi_remove, 1335 1305 }; 1336 1306 1337 1307 static int __init acpi_wmi_init(void)
+3 -1
drivers/platform/x86/x86-android-tablets/Kconfig
··· 5 5 6 6 config X86_ANDROID_TABLETS 7 7 tristate "X86 Android tablet support" 8 - depends on I2C && SPI && SERIAL_DEV_BUS && ACPI && EFI && GPIOLIB && PMIC_OPREGION 8 + depends on I2C && SPI && SERIAL_DEV_BUS 9 + depends on GPIOLIB && PMIC_OPREGION 10 + depends on ACPI && EFI && PCI 9 11 select NEW_LEDS 10 12 select LEDS_CLASS 11 13 help
+51 -9
drivers/platform/x86/x86-android-tablets/core.c
··· 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 13 #include <linux/acpi.h> 14 + #include <linux/device.h> 14 15 #include <linux/dmi.h> 15 16 #include <linux/gpio/consumer.h> 16 17 #include <linux/gpio/machine.h> 17 18 #include <linux/irq.h> 18 19 #include <linux/module.h> 20 + #include <linux/pci.h> 19 21 #include <linux/platform_device.h> 20 22 #include <linux/serdev.h> 21 23 #include <linux/string.h> ··· 157 155 static const struct software_node *bat_swnode; 158 156 static void (*exit_handler)(void); 159 157 158 + static struct i2c_adapter * 159 + get_i2c_adap_by_handle(const struct x86_i2c_client_info *client_info) 160 + { 161 + acpi_handle handle; 162 + acpi_status status; 163 + 164 + status = acpi_get_handle(NULL, client_info->adapter_path, &handle); 165 + if (ACPI_FAILURE(status)) { 166 + pr_err("Error could not get %s handle\n", client_info->adapter_path); 167 + return NULL; 168 + } 169 + 170 + return i2c_acpi_find_adapter_by_handle(handle); 171 + } 172 + 173 + static __init int match_parent(struct device *dev, const void *data) 174 + { 175 + return dev->parent == data; 176 + } 177 + 178 + static struct i2c_adapter * 179 + get_i2c_adap_by_pci_parent(const struct x86_i2c_client_info *client_info) 180 + { 181 + struct i2c_adapter *adap = NULL; 182 + struct device *pdev, *adap_dev; 183 + 184 + pdev = bus_find_device_by_name(&pci_bus_type, NULL, client_info->adapter_path); 185 + if (!pdev) { 186 + pr_err("Error could not find %s PCI device\n", client_info->adapter_path); 187 + return NULL; 188 + } 189 + 190 + adap_dev = bus_find_device(&i2c_bus_type, NULL, pdev, match_parent); 191 + if (adap_dev) { 192 + adap = i2c_verify_adapter(adap_dev); 193 + if (!adap) 194 + put_device(adap_dev); 195 + } 196 + 197 + put_device(pdev); 198 + 199 + return adap; 200 + } 201 + 160 202 static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info, 161 203 int idx) 162 204 { 163 205 const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx]; 164 206 struct i2c_board_info board_info = client_info->board_info; 165 207 struct i2c_adapter *adap; 166 - acpi_handle handle; 167 - acpi_status status; 168 208 169 209 board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data); 170 210 if (board_info.irq < 0) 171 211 return board_info.irq; 172 212 173 - status = acpi_get_handle(NULL, client_info->adapter_path, &handle); 174 - if (ACPI_FAILURE(status)) { 175 - pr_err("Error could not get %s handle\n", client_info->adapter_path); 176 - return -ENODEV; 177 - } 213 + if (dev_info->use_pci_devname) 214 + adap = get_i2c_adap_by_pci_parent(client_info); 215 + else 216 + adap = get_i2c_adap_by_handle(client_info); 178 217 179 - adap = i2c_acpi_find_adapter_by_handle(handle); 180 218 if (!adap) { 181 219 pr_err("error could not get %s adapter\n", client_info->adapter_path); 182 220 return -ENODEV; ··· 500 458 .driver = { 501 459 .name = KBUILD_MODNAME, 502 460 }, 503 - .remove_new = x86_android_tablet_remove, 461 + .remove = x86_android_tablet_remove, 504 462 }; 505 463 506 464 static int __init x86_android_tablet_init(void)
+10
drivers/platform/x86/x86-android-tablets/dmi.c
··· 180 180 .driver_data = (void *)&peaq_c1010_info, 181 181 }, 182 182 { 183 + /* Vexia Edu Atla 10 tablet 9V version */ 184 + .matches = { 185 + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 186 + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 187 + /* Above strings are too generic, also match on BIOS date */ 188 + DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"), 189 + }, 190 + .driver_data = (void *)&vexia_edu_atla10_info, 191 + }, 192 + { 183 193 /* Whitelabel (sold as various brands) TM800A550L */ 184 194 .matches = { 185 195 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+163
drivers/platform/x86/x86-android-tablets/other.c
··· 12 12 #include <linux/gpio/machine.h> 13 13 #include <linux/input.h> 14 14 #include <linux/leds.h> 15 + #include <linux/pci.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/pwm.h> 17 18 ··· 596 595 .i2c_client_info = whitelabel_tm800a550l_i2c_clients, 597 596 .i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients), 598 597 .gpiod_lookup_tables = whitelabel_tm800a550l_gpios, 598 + }; 599 + 600 + /* 601 + * Vexia EDU ATLA 10 tablet, Android 4.2 / 4.4 + Guadalinex Ubuntu tablet 602 + * distributed to schools in the Spanish Andalucía region. 603 + */ 604 + const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" }; 605 + 606 + static const struct property_entry vexia_edu_atla10_ulpmc_props[] = { 607 + PROPERTY_ENTRY_STRING_ARRAY("supplied-from", crystal_cove_pwrsrc_psy), 608 + { } 609 + }; 610 + 611 + const struct software_node vexia_edu_atla10_ulpmc_node = { 612 + .properties = vexia_edu_atla10_ulpmc_props, 613 + }; 614 + 615 + static const char * const vexia_edu_atla10_accel_mount_matrix[] = { 616 + "0", "-1", "0", 617 + "1", "0", "0", 618 + "0", "0", "1" 619 + }; 620 + 621 + static const struct property_entry vexia_edu_atla10_accel_props[] = { 622 + PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", vexia_edu_atla10_accel_mount_matrix), 623 + { } 624 + }; 625 + 626 + static const struct software_node vexia_edu_atla10_accel_node = { 627 + .properties = vexia_edu_atla10_accel_props, 628 + }; 629 + 630 + static const struct property_entry vexia_edu_atla10_touchscreen_props[] = { 631 + PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000), 632 + PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), 633 + { } 634 + }; 635 + 636 + static const struct software_node vexia_edu_atla10_touchscreen_node = { 637 + .properties = vexia_edu_atla10_touchscreen_props, 638 + }; 639 + 640 + static const struct property_entry vexia_edu_atla10_pmic_props[] = { 641 + PROPERTY_ENTRY_BOOL("linux,register-pwrsrc-power_supply"), 642 + { } 643 + }; 644 + 645 + static const struct software_node vexia_edu_atla10_pmic_node = { 646 + .properties = vexia_edu_atla10_pmic_props, 647 + }; 648 + 649 + static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initconst = { 650 + { 651 + /* I2C attached embedded controller, used to access fuel-gauge */ 652 + .board_info = { 653 + .type = "vexia_atla10_ec", 654 + .addr = 0x76, 655 + .dev_name = "ulpmc", 656 + .swnode = &vexia_edu_atla10_ulpmc_node, 657 + }, 658 + .adapter_path = "0000:00:18.1", 659 + }, { 660 + /* RT5642 audio codec */ 661 + .board_info = { 662 + .type = "rt5640", 663 + .addr = 0x1c, 664 + .dev_name = "rt5640", 665 + }, 666 + .adapter_path = "0000:00:18.2", 667 + .irq_data = { 668 + .type = X86_ACPI_IRQ_TYPE_GPIOINT, 669 + .chip = "INT33FC:02", 670 + .index = 4, 671 + .trigger = ACPI_EDGE_SENSITIVE, 672 + .polarity = ACPI_ACTIVE_HIGH, 673 + .con_id = "rt5640_irq", 674 + }, 675 + }, { 676 + /* kxtj21009 accelerometer */ 677 + .board_info = { 678 + .type = "kxtj21009", 679 + .addr = 0x0f, 680 + .dev_name = "kxtj21009", 681 + .swnode = &vexia_edu_atla10_accel_node, 682 + }, 683 + .adapter_path = "0000:00:18.5", 684 + }, { 685 + /* FT5416DQ9 touchscreen controller */ 686 + .board_info = { 687 + .type = "hid-over-i2c", 688 + .addr = 0x38, 689 + .dev_name = "FTSC1000", 690 + .swnode = &vexia_edu_atla10_touchscreen_node, 691 + }, 692 + .adapter_path = "0000:00:18.6", 693 + .irq_data = { 694 + .type = X86_ACPI_IRQ_TYPE_APIC, 695 + .index = 0x45, 696 + .trigger = ACPI_LEVEL_SENSITIVE, 697 + .polarity = ACPI_ACTIVE_HIGH, 698 + }, 699 + }, { 700 + /* Crystal Cove PMIC */ 701 + .board_info = { 702 + .type = "intel_soc_pmic_crc", 703 + .addr = 0x6e, 704 + .dev_name = "intel_soc_pmic_crc", 705 + .swnode = &vexia_edu_atla10_pmic_node, 706 + }, 707 + .adapter_path = "0000:00:18.7", 708 + .irq_data = { 709 + .type = X86_ACPI_IRQ_TYPE_APIC, 710 + .index = 0x43, 711 + .trigger = ACPI_LEVEL_SENSITIVE, 712 + .polarity = ACPI_ACTIVE_HIGH, 713 + }, 714 + } 715 + }; 716 + 717 + static struct gpiod_lookup_table vexia_edu_atla10_ft5416_gpios = { 718 + .dev_id = "i2c-FTSC1000", 719 + .table = { 720 + GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_LOW), 721 + { } 722 + }, 723 + }; 724 + 725 + static struct gpiod_lookup_table * const vexia_edu_atla10_gpios[] = { 726 + &vexia_edu_atla10_ft5416_gpios, 727 + NULL 728 + }; 729 + 730 + static int __init vexia_edu_atla10_init(struct device *dev) 731 + { 732 + struct pci_dev *pdev; 733 + int ret; 734 + 735 + /* Enable the Wifi module by setting the wifi_enable pin to 1 */ 736 + ret = x86_android_tablet_get_gpiod("INT33FC:02", 20, "wifi_enable", 737 + false, GPIOD_OUT_HIGH, NULL); 738 + if (ret) 739 + return ret; 740 + 741 + /* Reprobe the SDIO controller to enumerate the now enabled Wifi module */ 742 + pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x11, 0)); 743 + if (!pdev) 744 + return -EPROBE_DEFER; 745 + 746 + ret = device_reprobe(&pdev->dev); 747 + if (ret) 748 + pci_warn(pdev, "Reprobing error: %d\n", ret); 749 + 750 + pci_dev_put(pdev); 751 + return 0; 752 + } 753 + 754 + const struct x86_dev_info vexia_edu_atla10_info __initconst = { 755 + .i2c_client_info = vexia_edu_atla10_i2c_clients, 756 + .i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_i2c_clients), 757 + .gpiod_lookup_tables = vexia_edu_atla10_gpios, 758 + .init = vexia_edu_atla10_init, 759 + .use_pci_devname = true, 599 760 }; 600 761 601 762 /*
+2
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
··· 91 91 int gpio_button_count; 92 92 int (*init)(struct device *dev); 93 93 void (*exit)(void); 94 + bool use_pci_devname; 94 95 }; 95 96 96 97 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, ··· 120 119 extern const struct x86_dev_info nextbook_ares8a_info; 121 120 extern const struct x86_dev_info peaq_c1010_info; 122 121 extern const struct x86_dev_info whitelabel_tm800a550l_info; 122 + extern const struct x86_dev_info vexia_edu_atla10_info; 123 123 extern const struct x86_dev_info xiaomi_mipad2_info; 124 124 extern const struct dmi_system_id x86_android_tablet_ids[]; 125 125
+1 -1
drivers/platform/x86/xo1-rfkill.c
··· 68 68 .name = "xo1-rfkill", 69 69 }, 70 70 .probe = xo1_rfkill_probe, 71 - .remove_new = xo1_rfkill_remove, 71 + .remove = xo1_rfkill_remove, 72 72 }; 73 73 74 74 module_platform_driver(xo1_rfkill_driver);
+2 -1
include/linux/intel_vsec.h
··· 74 74 * @pdev: PCI device reference for the callback's use 75 75 * @guid: ID of data to acccss 76 76 * @data: buffer for the data to be copied 77 + * @off: offset into the requested buffer 77 78 * @count: size of buffer 78 79 */ 79 80 struct pmt_callbacks { 80 - int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, u32 count); 81 + int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, loff_t off, u32 count); 81 82 }; 82 83 83 84 /**
+4
include/linux/platform_data/x86/intel_scu_ipc.h
··· 2 2 #ifndef __PLATFORM_X86_INTEL_SCU_IPC_H_ 3 3 #define __PLATFORM_X86_INTEL_SCU_IPC_H_ 4 4 5 + #include <linux/init.h> 5 6 #include <linux/ioport.h> 7 + #include <linux/types.h> 6 8 7 9 struct device; 10 + struct module; 11 + 8 12 struct intel_scu_ipc_dev; 9 13 10 14 /**
+11 -1
include/linux/wmi.h
··· 34 34 * 35 35 * Cast a struct device to a struct wmi_device. 36 36 */ 37 - #define to_wmi_device(device) container_of(device, struct wmi_device, dev) 37 + #define to_wmi_device(device) container_of_const(device, struct wmi_device, dev) 38 38 39 39 extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev, 40 40 u8 instance, u32 method_id, ··· 56 56 * @no_singleton: Driver can be instantiated multiple times 57 57 * @probe: Callback for device binding 58 58 * @remove: Callback for device unbinding 59 + * @shutdown: Callback for device shutdown 59 60 * @notify: Callback for receiving WMI events 60 61 * 61 62 * This represents WMI drivers which handle WMI devices. ··· 69 68 70 69 int (*probe)(struct wmi_device *wdev, const void *context); 71 70 void (*remove)(struct wmi_device *wdev); 71 + void (*shutdown)(struct wmi_device *wdev); 72 72 void (*notify)(struct wmi_device *device, union acpi_object *data); 73 73 }; 74 + 75 + /** 76 + * to_wmi_driver() - Helper macro to cast a driver to a wmi_driver 77 + * @drv: driver struct 78 + * 79 + * Cast a struct device_driver to a struct wmi_driver. 80 + */ 81 + #define to_wmi_driver(drv) container_of_const(drv, struct wmi_driver, driver) 74 82 75 83 extern int __must_check __wmi_driver_register(struct wmi_driver *driver, 76 84 struct module *owner);