diff --git a/MAINTAINERS b/MAINTAINERS index 78b53ce0adfb..1b718c05ad3e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -303,8 +303,8 @@ F: drivers/net/ethernet/alteon/acenic* ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER M: Peter Kaestle L: platform-driver-x86@vger.kernel.org -W: http://piie.net/?section=acerhdf S: Maintained +W: http://piie.net/?section=acerhdf F: drivers/platform/x86/acerhdf.c ACER WMI LAPTOP EXTRAS @@ -2766,8 +2766,8 @@ ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS M: Corentin Chary L: acpi4asus-user@lists.sourceforge.net L: platform-driver-x86@vger.kernel.org -W: http://acpi4asus.sf.net S: Maintained +W: http://acpi4asus.sf.net F: drivers/platform/x86/asus*.c F: drivers/platform/x86/eeepc*.c @@ -4745,26 +4745,6 @@ S: Maintained F: drivers/media/platform/sunxi/sun8i-di/ F: Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml -DELL SMBIOS DRIVER -M: Pali Rohár -M: Mario Limonciello -L: platform-driver-x86@vger.kernel.org -S: Maintained -F: drivers/platform/x86/dell-smbios.* - -DELL SMBIOS SMM DRIVER -M: Mario Limonciello -L: platform-driver-x86@vger.kernel.org -S: Maintained -F: drivers/platform/x86/dell-smbios-smm.c - -DELL SMBIOS WMI DRIVER -M: Mario Limonciello -L: platform-driver-x86@vger.kernel.org -S: Maintained -F: drivers/platform/x86/dell-smbios-wmi.c -F: tools/wmi/dell-smbios-example.c - DEFZA FDDI NETWORK DRIVER M: "Maciej W. Rozycki" S: Maintained @@ -4787,17 +4767,37 @@ M: Pali Rohár S: Maintained F: drivers/platform/x86/dell-rbtn.* +DELL LAPTOP SMM DRIVER +M: Pali Rohár +S: Maintained +F: drivers/hwmon/dell-smm-hwmon.c +F: include/uapi/linux/i8k.h + DELL REMOTE BIOS UPDATE DRIVER M: Stuart Hayes L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/dell_rbu.c -DELL LAPTOP SMM DRIVER +DELL SMBIOS DRIVER M: Pali Rohár +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org S: Maintained -F: drivers/hwmon/dell-smm-hwmon.c -F: include/uapi/linux/i8k.h +F: drivers/platform/x86/dell-smbios.* + +DELL SMBIOS SMM DRIVER +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/dell-smbios-smm.c + +DELL SMBIOS WMI DRIVER +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/dell-smbios-wmi.c +F: tools/wmi/dell-smbios-example.c DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas) M: Stuart Hayes @@ -4806,17 +4806,17 @@ S: Maintained F: Documentation/driver-api/dcdbas.rst F: drivers/platform/x86/dcdbas.* +DELL WMI DESCRIPTOR DRIVER +M: Mario Limonciello +S: Maintained +F: drivers/platform/x86/dell-wmi-descriptor.c + DELL WMI NOTIFICATIONS DRIVER M: Matthew Garrett M: Pali Rohár S: Maintained F: drivers/platform/x86/dell-wmi.c -DELL WMI DESCRIPTOR DRIVER -M: Mario Limonciello -S: Maintained -F: drivers/platform/x86/dell-wmi-descriptor.c - DELTA ST MEDIA DRIVER M: Hugues Fruchet L: linux-media@vger.kernel.org @@ -7375,8 +7375,8 @@ F: drivers/media/usb/hackrf/ HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER M: Frank Seidel L: platform-driver-x86@vger.kernel.org -W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/ S: Maintained +W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/ F: drivers/platform/x86/hdaps.c HARDWARE MONITORING @@ -8119,15 +8119,15 @@ F: drivers/ide/ide-cd* IDEAPAD LAPTOP EXTRAS DRIVER M: Ike Panhc L: platform-driver-x86@vger.kernel.org -W: http://launchpad.net/ideapad-laptop S: Maintained +W: http://launchpad.net/ideapad-laptop F: drivers/platform/x86/ideapad-laptop.c IDEAPAD LAPTOP SLIDEBAR DRIVER M: Andrey Moiseev L: linux-input@vger.kernel.org -W: https://github.com/o2genum/ideapad-slidebar S: Maintained +W: https://github.com/o2genum/ideapad-slidebar F: drivers/input/misc/ideapad_slidebar.c IDT VersaClock 5 CLOCK DRIVER @@ -8593,8 +8593,8 @@ F: samples/mei/* INTEL MENLOW THERMAL DRIVER M: Sujith Thomas L: platform-driver-x86@vger.kernel.org -W: https://01.org/linux-acpi S: Supported +W: https://01.org/linux-acpi F: drivers/platform/x86/intel_menlow.c INTEL MIC DRIVERS (mic) @@ -8624,10 +8624,10 @@ INTEL PMC/P-Unit IPC DRIVER M: Zha Qipeng L: platform-driver-x86@vger.kernel.org S: Maintained -F: drivers/platform/x86/intel_pmc_ipc.c -F: drivers/platform/x86/intel_punit_ipc.c F: arch/x86/include/asm/intel_pmc_ipc.h F: arch/x86/include/asm/intel_punit_ipc.h +F: drivers/platform/x86/intel_pmc_ipc.c +F: drivers/platform/x86/intel_punit_ipc.c INTEL PMIC GPIO DRIVERS M: Andy Shevchenko @@ -8672,8 +8672,8 @@ M: Srinivas Pandruvada L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/intel_speed_select_if/ -F: tools/power/x86/intel-speed-select/ F: include/uapi/linux/isst_if.h +F: tools/power/x86/intel-speed-select/ INTEL STRATIX10 FIRMWARE DRIVERS M: Richard Gong @@ -15626,8 +15626,8 @@ F: include/linux/memstick.h SONY VAIO CONTROL DEVICE DRIVER M: Mattia Dongili L: platform-driver-x86@vger.kernel.org -W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers S: Maintained +W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers F: Documentation/admin-guide/laptops/sony-laptop.rst F: drivers/char/sonypi.c F: drivers/platform/x86/sony-laptop.c @@ -16602,10 +16602,10 @@ THINKPAD ACPI EXTRAS DRIVER M: Henrique de Moraes Holschuh L: ibm-acpi-devel@lists.sourceforge.net L: platform-driver-x86@vger.kernel.org +S: Maintained W: http://ibm-acpi.sourceforge.net W: http://thinkwiki.org/wiki/Ibm-acpi T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git -S: Maintained F: drivers/platform/x86/thinkpad_acpi.c THUNDERBOLT DRIVER @@ -18250,10 +18250,10 @@ X86 PLATFORM DRIVERS M: Darren Hart M: Andy Shevchenko L: platform-driver-x86@vger.kernel.org -T: git git://git.infradead.org/linux-platform-drivers-x86.git S: Odd Fixes -F: drivers/platform/x86/ +T: git git://git.infradead.org/linux-platform-drivers-x86.git F: drivers/platform/olpc/ +F: drivers/platform/x86/ X86 PLATFORM DRIVERS - ARCH R: Darren Hart diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index cd9e2758c479..0ad7ad8cf8e1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -16,40 +16,103 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES -config ACER_WMI - tristate "Acer WMI Laptop Extras" +config ACPI_WMI + tristate "WMI" depends on ACPI - select LEDS_CLASS - select NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE - depends on SERIO_I8042 - depends on INPUT - depends on RFKILL || RFKILL = n + help + This driver adds support for the ACPI-WMI (Windows Management + Instrumentation) mapper device (PNP0C14) found on some systems. + + ACPI-WMI is a proprietary extension to ACPI to expose parts of the + ACPI firmware to userspace - this is done through various vendor + defined methods and data blocks in a PNP0C14 device, which are then + made available for userspace to call. + + The implementation of this in Linux currently only exposes this to + other kernel space drivers. + + This driver is a required dependency to build the firmware specific + drivers needed on many machines, including Acer and HP laptops. + + It is safe to enable this driver even if your DSDT doesn't define + any ACPI-WMI devices. + +config WMI_BMOF + tristate "WMI embedded Binary MOF driver" depends on ACPI_WMI - select INPUT_SPARSEKMAP - # Acer WMI depends on ACPI_VIDEO when ACPI is enabled - select ACPI_VIDEO if ACPI + default ACPI_WMI ---help--- - This is a driver for newer Acer (and Wistron) laptops. It adds - wireless radio and bluetooth control, and on some laptops, - exposes the mail LED and LCD backlight. + Say Y here if you want to be able to read a firmware-embedded + WMI Binary MOF data. Using this requires userspace tools and may be + rather tedious. - If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M - here. + To compile this driver as a module, choose M here: the module will + be called wmi-bmof. -config ACER_WIRELESS - tristate "Acer Wireless Radio Control Driver" - depends on ACPI - depends on INPUT - ---help--- - The Acer Wireless Radio Control handles the airplane mode hotkey - present on new Acer laptops. +config ALIENWARE_WMI + tristate "Alienware Special feature control" + depends on ACPI + depends on LEDS_CLASS + depends on NEW_LEDS + depends on ACPI_WMI + ---help--- + This is a driver for controlling Alienware BIOS driven + features. It exposes an interface for controlling the AlienFX + zones on Alienware machines that don't contain a dedicated AlienFX + USB MCU such as the X51 and X51-R2. - Say Y or M here if you have an Acer notebook with an airplane mode - hotkey. +config HUAWEI_WMI + tristate "Huawei WMI laptop extras driver" + depends on ACPI_BATTERY + depends on ACPI_WMI + depends on INPUT + select INPUT_SPARSEKMAP + select LEDS_CLASS + select LEDS_TRIGGERS + select LEDS_TRIGGER_AUDIO + select NEW_LEDS + help + This driver provides support for Huawei WMI hotkeys, battery charge + control, fn-lock, mic-mute LED, and other extra features. - If you choose to compile this driver as a module the module will be - called acer-wireless. + To compile this driver as a module, choose M here: the module + will be called huawei-wmi. + +config INTEL_WMI_THUNDERBOLT + tristate "Intel WMI thunderbolt force power driver" + depends on ACPI_WMI + ---help--- + Say Y here if you want to be able to use the WMI interface on select + systems to force the power control of Intel Thunderbolt controllers. + This is useful for updating the firmware when devices are not plugged + into the controller. + + To compile this driver as a module, choose M here: the module will + be called intel-wmi-thunderbolt. + +config MXM_WMI + tristate "WMI support for MXM Laptop Graphics" + depends on ACPI_WMI + ---help--- + MXM is a standard for laptop graphics cards, the WMI interface + is required for switchable nvidia graphics machines + +config PEAQ_WMI + tristate "PEAQ 2-in-1 WMI hotkey driver" + depends on ACPI_WMI + depends on INPUT + help + Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s. + +config XIAOMI_WMI + tristate "Xiaomi WMI key driver" + depends on ACPI_WMI + depends on INPUT + help + Say Y here if you want to support WMI-based keys on Xiaomi notebooks. + + To compile this driver as a module, choose M here: the module will + be called xiaomi-wmi. config ACERHDF tristate "Acer Aspire One temperature and fan driver" @@ -72,17 +135,53 @@ config ACERHDF If you have an Acer Aspire One netbook, say Y or M here. -config ALIENWARE_WMI - tristate "Alienware Special feature control" +config ACER_WIRELESS + tristate "Acer Wireless Radio Control Driver" + depends on ACPI + depends on INPUT + ---help--- + The Acer Wireless Radio Control handles the airplane mode hotkey + present on new Acer laptops. + + Say Y or M here if you have an Acer notebook with an airplane mode + hotkey. + + If you choose to compile this driver as a module the module will be + called acer-wireless. + +config ACER_WMI + tristate "Acer WMI Laptop Extras" depends on ACPI - depends on LEDS_CLASS - depends on NEW_LEDS + select LEDS_CLASS + select NEW_LEDS + depends on BACKLIGHT_CLASS_DEVICE + depends on SERIO_I8042 + depends on INPUT + depends on RFKILL || RFKILL = n depends on ACPI_WMI + select INPUT_SPARSEKMAP + # Acer WMI depends on ACPI_VIDEO when ACPI is enabled + select ACPI_VIDEO if ACPI ---help--- - This is a driver for controlling Alienware BIOS driven - features. It exposes an interface for controlling the AlienFX - zones on Alienware machines that don't contain a dedicated AlienFX - USB MCU such as the X51 and X51-R2. + This is a driver for newer Acer (and Wistron) laptops. It adds + wireless radio and bluetooth control, and on some laptops, + exposes the mail LED and LCD backlight. + + If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M + here. + +config APPLE_GMUX + tristate "Apple Gmux Driver" + depends on ACPI && PCI + depends on PNP + depends on BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE + depends on ACPI_VIDEO=n || ACPI_VIDEO + ---help--- + This driver provides support for the gmux device found on many + Apple laptops, which controls the display mux for the hybrid + graphics as well as the backlight. Currently only backlight + control is supported by the driver. config ASUS_LAPTOP tristate "Asus Laptop Extras" @@ -108,6 +207,91 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. +config ASUS_WIRELESS + tristate "Asus Wireless Radio Control Driver" + depends on ACPI + depends on INPUT + select NEW_LEDS + select LEDS_CLASS + ---help--- + The Asus Wireless Radio Control handles the airplane mode hotkey + present on some Asus laptops. + + Say Y or M here if you have an ASUS notebook with an airplane mode + hotkey. + + If you choose to compile this driver as a module the module will be + called asus-wireless. + +config ASUS_WMI + tristate "ASUS WMI Driver" + depends on ACPI_WMI + depends on ACPI_BATTERY + depends on INPUT + depends on HWMON + depends on BACKLIGHT_CLASS_DEVICE + depends on RFKILL || RFKILL = n + depends on HOTPLUG_PCI + depends on ACPI_VIDEO || ACPI_VIDEO = n + select INPUT_SPARSEKMAP + select LEDS_CLASS + select NEW_LEDS + ---help--- + Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new + Asus Notebooks). + + To compile this driver as a module, choose M here: the module will + be called asus-wmi. + +config ASUS_NB_WMI + tristate "Asus Notebook WMI Driver" + depends on ASUS_WMI + depends on SERIO_I8042 || SERIO_I8042 = n + ---help--- + This is a driver for newer Asus notebooks. It adds extra features + like wireless radio and bluetooth control, leds, hotkeys, backlight... + + For more information, see + + + If you have an ACPI-WMI compatible Asus Notebook, say Y or M + here. + +config EEEPC_LAPTOP + tristate "Eee PC Hotkey Driver" + depends on ACPI + depends on INPUT + depends on RFKILL || RFKILL = n + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on HOTPLUG_PCI + depends on BACKLIGHT_CLASS_DEVICE + select HWMON + select LEDS_CLASS + select NEW_LEDS + select INPUT_SPARSEKMAP + ---help--- + This driver supports the Fn-Fx keys on Eee PC laptops. + + It also gives access to some extra laptop functionalities like + Bluetooth, backlight and allows powering on/off some other + devices. + + If you have an Eee PC laptop, say Y or M here. If this driver + doesn't work on your Eee PC, try eeepc-wmi instead. + +config EEEPC_WMI + tristate "Eee PC WMI Driver" + depends on ASUS_WMI + ---help--- + This is a driver for newer Eee PC laptops. It adds extra features + like wireless radio and bluetooth control, leds, hotkeys, backlight... + + For more information, see + + + If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M + here. + config DCDBAS tristate "Dell Systems Management Base Driver" depends on X86 @@ -183,6 +367,44 @@ config DELL_LAPTOP This driver adds support for rfkill and backlight control to Dell laptops (except for some models covered by the Compal driver). +config DELL_RBTN + tristate "Dell Airplane Mode Switch driver" + depends on ACPI + depends on INPUT + depends on RFKILL + ---help--- + Say Y here if you want to support Dell Airplane Mode Switch ACPI + device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN. + This driver register rfkill device or input hotkey device depending + on hardware type (hw switch slider or keyboard toggle button). For + rfkill devices it receive HW switch events and set correct hard + rfkill state. + + To compile this driver as a module, choose M here: the module will + be called dell-rbtn. + +config DELL_RBU + tristate "BIOS update support for DELL systems via sysfs" + depends on X86 + select FW_LOADER + select FW_LOADER_USER_HELPER + help + Say m if you want to have the option of updating the BIOS for your + DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) + supporting application to communicate with the BIOS regarding the new + image for the image update to take effect. + See for more details on the driver. + +config DELL_SMO8800 + tristate "Dell Latitude freefall driver (ACPI SMO88XX)" + depends on ACPI + ---help--- + Say Y here if you want to support SMO88XX freefall devices + on Dell Latitude laptops. + + To compile this driver as a module, choose M here: the module will + be called dell-smo8800. + config DELL_WMI tristate "Dell WMI notifications" depends on ACPI_WMI @@ -222,44 +444,13 @@ config DELL_WMI_LED This adds support for the Latitude 2100 and similar notebooks that have an external LED. -config DELL_SMO8800 - tristate "Dell Latitude freefall driver (ACPI SMO88XX)" - depends on ACPI - ---help--- - Say Y here if you want to support SMO88XX freefall devices - on Dell Latitude laptops. - - To compile this driver as a module, choose M here: the module will - be called dell-smo8800. - -config DELL_RBTN - tristate "Dell Airplane Mode Switch driver" - depends on ACPI - depends on INPUT +config AMILO_RFKILL + tristate "Fujitsu-Siemens Amilo rfkill support" depends on RFKILL + depends on SERIO_I8042 ---help--- - Say Y here if you want to support Dell Airplane Mode Switch ACPI - device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN. - This driver register rfkill device or input hotkey device depending - on hardware type (hw switch slider or keyboard toggle button). For - rfkill devices it receive HW switch events and set correct hard - rfkill state. - - To compile this driver as a module, choose M here: the module will - be called dell-rbtn. - -config DELL_RBU - tristate "BIOS update support for DELL systems via sysfs" - depends on X86 - select FW_LOADER - select FW_LOADER_USER_HELPER - help - Say m if you want to have the option of updating the BIOS for your - DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) - supporting application to communicate with the BIOS regarding the new - image for the image update to take effect. - See for more details on the driver. - + This is a driver for enabling wifi on some Fujitsu-Siemens Amilo + laptops. config FUJITSU_LAPTOP tristate "Fujitsu Laptop Extras" @@ -297,14 +488,6 @@ config FUJITSU_TABLET If you have a Fujitsu convertible or slate, say Y or M here. -config AMILO_RFKILL - tristate "Fujitsu-Siemens Amilo rfkill support" - depends on RFKILL - depends on SERIO_I8042 - ---help--- - This is a driver for enabling wifi on some Fujitsu-Siemens Amilo - laptops. - config GPD_POCKET_FAN tristate "GPD Pocket Fan Controller support" depends on ACPI @@ -317,15 +500,6 @@ config GPD_POCKET_FAN of the CPU temperature. Say Y or M if the kernel may be used on a GPD pocket. -config TC1100_WMI - tristate "HP Compaq TC1100 Tablet WMI Extras" - depends on !X86_64 - depends on ACPI - depends on ACPI_WMI - ---help--- - This is a driver for the WMI extensions (wireless and bluetooth power - control) of the HP Compaq TC1100 tablet. - config HP_ACCEL tristate "HP laptop accelerometer" depends on INPUT && ACPI @@ -369,91 +543,30 @@ config HP_WMI To compile this driver as a module, choose M here: the module will be called hp-wmi. -config LG_LAPTOP - tristate "LG Laptop Extras" +config TC1100_WMI + tristate "HP Compaq TC1100 Tablet WMI Extras" + depends on !X86_64 depends on ACPI depends on ACPI_WMI - depends on INPUT - select INPUT_SPARSEKMAP - select LEDS_CLASS - help - This driver adds support for hotkeys as well as control of keyboard - backlight, battery maximum charge level and various other ACPI - features. - - If you have an LG Gram laptop, say Y or M here. - -config MSI_LAPTOP - tristate "MSI Laptop Extras" - depends on ACPI - depends on BACKLIGHT_CLASS_DEVICE - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL - depends on INPUT && SERIO_I8042 - select INPUT_SPARSEKMAP ---help--- - This is a driver for laptops built by MSI (MICRO-STAR - INTERNATIONAL): + This is a driver for the WMI extensions (wireless and bluetooth power + control) of the HP Compaq TC1100 tablet. - MSI MegaBook S270 (MS-1013) - Cytron/TCM/Medion/Tchibo MD96100/SAM2000 - - It adds support for Bluetooth, WLAN and LCD brightness control. - - More information about this driver is available at - . - - If you have an MSI S270 laptop, say Y or M here. - -config PANASONIC_LAPTOP - tristate "Panasonic Laptop Extras" - depends on INPUT && ACPI - depends on BACKLIGHT_CLASS_DEVICE - select INPUT_SPARSEKMAP +config IBM_RTL + tristate "Device driver to enable PRTL support" + depends on PCI ---help--- - This driver adds support for access to backlight control and hotkeys - on Panasonic Let's Note laptops. + Enable support for IBM Premium Real Time Mode (PRTM). + This module will allow you the enter and exit PRTM in the BIOS via + sysfs on platforms that support this feature. System in PRTM will + not receive CPU-generated SMIs for recoverable errors. Use of this + feature without proper support may void your hardware warranty. - If you have a Panasonic Let's note laptop (such as the R1(N variant), - R2, R3, R5, T2, W2 and Y2 series), say Y. - -config COMPAL_LAPTOP - tristate "Compal (and others) Laptop Extras" - depends on ACPI - depends on BACKLIGHT_CLASS_DEVICE - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL - depends on HWMON - depends on POWER_SUPPLY - ---help--- - This is a driver for laptops built by Compal, and some models by - other brands (e.g. Dell, Toshiba). - - It adds support for rfkill, Bluetooth, WLAN, LCD brightness, hwmon - and battery charging level control. - -config SONY_LAPTOP - tristate "Sony Laptop Extras" - depends on ACPI - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on BACKLIGHT_CLASS_DEVICE - depends on INPUT - depends on RFKILL - ---help--- - This mini-driver drives the SNC and SPIC devices present in the ACPI - BIOS of the Sony Vaio laptops. - - It gives access to some extra laptop functionalities like Bluetooth, - screen brightness control, Fn keys and allows powering on/off some - devices. - - Read for more information. - -config SONYPI_COMPAT - bool "Sonypi compatibility" - depends on SONY_LAPTOP - ---help--- - Build the sonypi driver compatibility code into the sony-laptop driver. + If the proper BIOS support is found the driver will load and create + /sys/devices/system/ibm_rtl/. The "state" variable will indicate + whether or not the BIOS is in PRTM. + state = 0 (BIOS SMIs on) + state = 1 (BIOS SMIs off) config IDEAPAD_LAPTOP tristate "Lenovo IdeaPad Laptop Extras" @@ -468,17 +581,23 @@ config IDEAPAD_LAPTOP This is a driver for Lenovo IdeaPad netbooks contains drivers for rfkill switch, hotkey, fan control and backlight control. -config SURFACE3_WMI - tristate "Surface 3 WMI Driver" - depends on ACPI_WMI - depends on DMI +config SENSORS_HDAPS + tristate "Thinkpad Hard Drive Active Protection System (hdaps)" depends on INPUT - depends on SPI - ---help--- - Say Y here if you have a Surface 3. + help + This driver provides support for the IBM Hard Drive Active Protection + System (hdaps), which provides an accelerometer and other misc. data. + ThinkPads starting with the R50, T41, and X40 are supported. The + accelerometer data is readable via sysfs. - To compile this driver as a module, choose M here: the module will - be called surface3-wmi. + This driver also provides an absolute input class device, allowing + the laptop to act as a pinball machine-esque joystick. + + If your ThinkPad is not recognized by the driver, please update to latest + BIOS. This is especially the case for some R52 ThinkPads. + + Say Y here if you have an applicable laptop and want to experience + the awesome power of hdaps. config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" @@ -619,23 +738,72 @@ config THINKPAD_ACPI_HOTKEY_POLL If you are not sure, say Y here. The driver enables polling only if it is strictly necessary to do so. -config SENSORS_HDAPS - tristate "Thinkpad Hard Drive Active Protection System (hdaps)" - depends on INPUT +config INTEL_ATOMISP2_PM + tristate "Intel AtomISP2 dummy / power-management driver" + depends on PCI && IOSF_MBI && PM help - This driver provides support for the IBM Hard Drive Active Protection - System (hdaps), which provides an accelerometer and other misc. data. - ThinkPads starting with the R50, T41, and X40 are supported. The - accelerometer data is readable via sysfs. + Power-management driver for Intel's Image Signal Processor found on + Bay Trail and Cherry Trail devices. This dummy driver's sole purpose + is to turn the ISP off (put it in D3) to save power and to allow + entering of S0ix modes. - This driver also provides an absolute input class device, allowing - the laptop to act as a pinball machine-esque joystick. + To compile this driver as a module, choose M here: the module + will be called intel_atomisp2_pm. - If your ThinkPad is not recognized by the driver, please update to latest - BIOS. This is especially the case for some R52 ThinkPads. +config INTEL_CHT_INT33FE + tristate "Intel Cherry Trail ACPI INT33FE Driver" + depends on X86 && ACPI && I2C && REGULATOR + depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m) + depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m) + depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m) + ---help--- + This driver add support for the INT33FE ACPI device found on + some Intel Cherry Trail devices. - Say Y here if you have an applicable laptop and want to experience - the awesome power of hdaps. + There are two kinds of INT33FE ACPI device possible: for hardware + with USB Type-C and Micro-B connectors. This driver supports both. + + The INT33FE ACPI device has a CRS table with I2cSerialBusV2 + resources for Fuel Gauge Controller and (in the Type-C variant) + FUSB302 USB Type-C Controller and PI3USB30532 USB switch. + This driver instantiates i2c-clients for these, so that standard + i2c drivers for these chips can bind to the them. + + If you enable this driver it is advised to also select + CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B + device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m + for Type-C device. + +config INTEL_HID_EVENT + tristate "INTEL HID Event" + depends on ACPI + depends on INPUT + select INPUT_SPARSEKMAP + help + This driver provides support for the Intel HID Event hotkey interface. + Some laptops require this driver for hotkey support. + + To compile this driver as a module, choose M here: the module will + be called intel_hid. + +config INTEL_INT0002_VGPIO + tristate "Intel ACPI INT0002 Virtual GPIO driver" + depends on GPIOLIB && ACPI + select GPIOLIB_IRQCHIP + ---help--- + Some peripherals on Bay Trail and Cherry Trail platforms signal a + Power Management Event (PME) to the Power Management Controller (PMC) + to wakeup the system. When this happens software needs to explicitly + clear the PME bus 0 status bit in the GPE0a_STS register to avoid an + IRQ storm on IRQ 9. + + This is modelled in ACPI through the INT0002 ACPI device, which is + called a "Virtual GPIO controller" in ACPI because it defines the + event handler to call when the PME triggers through _AEI and _L02 + methods as would be done for a real GPIO interrupt in ACPI. + + To compile this driver as a module, choose M here: the module will + be called intel_int0002_vgpio. config INTEL_MENLOW tristate "Thermal Management driver for Intel menlow platform" @@ -647,145 +815,80 @@ config INTEL_MENLOW If unsure, say N. -config EEEPC_LAPTOP - tristate "Eee PC Hotkey Driver" +config INTEL_OAKTRAIL + tristate "Intel Oaktrail Platform Extras" depends on ACPI - depends on INPUT - depends on RFKILL || RFKILL = n depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on HOTPLUG_PCI - depends on BACKLIGHT_CLASS_DEVICE - select HWMON - select LEDS_CLASS - select NEW_LEDS - select INPUT_SPARSEKMAP + depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI ---help--- - This driver supports the Fn-Fx keys on Eee PC laptops. + Intel Oaktrail platform need this driver to provide interfaces to + enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y + here; it will only load on supported platforms. - It also gives access to some extra laptop functionalities like - Bluetooth, backlight and allows powering on/off some other - devices. - - If you have an Eee PC laptop, say Y or M here. If this driver - doesn't work on your Eee PC, try eeepc-wmi instead. - -config ASUS_WMI - tristate "ASUS WMI Driver" - depends on ACPI_WMI - depends on ACPI_BATTERY - depends on INPUT - depends on HWMON - depends on BACKLIGHT_CLASS_DEVICE - depends on RFKILL || RFKILL = n - depends on HOTPLUG_PCI - depends on ACPI_VIDEO || ACPI_VIDEO = n - select INPUT_SPARSEKMAP - select LEDS_CLASS - select NEW_LEDS - ---help--- - Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new - Asus Notebooks). - - To compile this driver as a module, choose M here: the module will - be called asus-wmi. - -config ASUS_NB_WMI - tristate "Asus Notebook WMI Driver" - depends on ASUS_WMI - depends on SERIO_I8042 || SERIO_I8042 = n - ---help--- - This is a driver for newer Asus notebooks. It adds extra features - like wireless radio and bluetooth control, leds, hotkeys, backlight... - - For more information, see - - - If you have an ACPI-WMI compatible Asus Notebook, say Y or M - here. - -config EEEPC_WMI - tristate "Eee PC WMI Driver" - depends on ASUS_WMI - ---help--- - This is a driver for newer Eee PC laptops. It adds extra features - like wireless radio and bluetooth control, leds, hotkeys, backlight... - - For more information, see - - - If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M - here. - -config ASUS_WIRELESS - tristate "Asus Wireless Radio Control Driver" +config INTEL_VBTN + tristate "INTEL VIRTUAL BUTTON" depends on ACPI depends on INPUT - select NEW_LEDS - select LEDS_CLASS - ---help--- - The Asus Wireless Radio Control handles the airplane mode hotkey - present on some Asus laptops. - - Say Y or M here if you have an ASUS notebook with an airplane mode - hotkey. - - If you choose to compile this driver as a module the module will be - called asus-wireless. - -config ACPI_WMI - tristate "WMI" - depends on ACPI + select INPUT_SPARSEKMAP help - This driver adds support for the ACPI-WMI (Windows Management - Instrumentation) mapper device (PNP0C14) found on some systems. + This driver provides support for the Intel Virtual Button interface. + Some laptops require this driver for power button support. - ACPI-WMI is a proprietary extension to ACPI to expose parts of the - ACPI firmware to userspace - this is done through various vendor - defined methods and data blocks in a PNP0C14 device, which are then - made available for userspace to call. + To compile this driver as a module, choose M here: the module will + be called intel_vbtn. - The implementation of this in Linux currently only exposes this to - other kernel space drivers. - - This driver is a required dependency to build the firmware specific - drivers needed on many machines, including Acer and HP laptops. - - It is safe to enable this driver even if your DSDT doesn't define - any ACPI-WMI devices. - -config WMI_BMOF - tristate "WMI embedded Binary MOF driver" +config SURFACE3_WMI + tristate "Surface 3 WMI Driver" depends on ACPI_WMI - default ACPI_WMI + depends on DMI + depends on INPUT + depends on SPI ---help--- - Say Y here if you want to be able to read a firmware-embedded - WMI Binary MOF data. Using this requires userspace tools and may be - rather tedious. + Say Y here if you have a Surface 3. To compile this driver as a module, choose M here: the module will - be called wmi-bmof. + be called surface3-wmi. -config INTEL_WMI_THUNDERBOLT - tristate "Intel WMI thunderbolt force power driver" - depends on ACPI_WMI +config SURFACE_3_BUTTON + tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet" + depends on ACPI && KEYBOARD_GPIO && I2C ---help--- - Say Y here if you want to be able to use the WMI interface on select - systems to force the power control of Intel Thunderbolt controllers. - This is useful for updating the firmware when devices are not plugged - into the controller. + This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet. - To compile this driver as a module, choose M here: the module will - be called intel-wmi-thunderbolt. +config SURFACE_3_POWER_OPREGION + tristate "Surface 3 battery platform operation region support" + depends on ACPI && I2C + help + This driver provides support for ACPI operation + region of the Surface 3 battery platform driver. -config XIAOMI_WMI - tristate "Xiaomi WMI key driver" - depends on ACPI_WMI - depends on INPUT - help - Say Y here if you want to support WMI-based keys on Xiaomi notebooks. +config SURFACE_PRO3_BUTTON + tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet" + depends on ACPI && INPUT + ---help--- + This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet. - To compile this driver as a module, choose M here: the module will - be called xiaomi-wmi. +config MSI_LAPTOP + tristate "MSI Laptop Extras" + depends on ACPI + depends on BACKLIGHT_CLASS_DEVICE + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on RFKILL + depends on INPUT && SERIO_I8042 + select INPUT_SPARSEKMAP + ---help--- + This is a driver for laptops built by MSI (MICRO-STAR + INTERNATIONAL): + + MSI MegaBook S270 (MS-1013) + Cytron/TCM/Medion/Tchibo MD96100/SAM2000 + + It adds support for Bluetooth, WLAN and LCD brightness control. + + More information about this driver is available at + . + + If you have an MSI S270 laptop, say Y or M here. config MSI_WMI tristate "MSI WMI extras" @@ -800,24 +903,63 @@ config MSI_WMI To compile this driver as a module, choose M here: the module will be called msi-wmi. -config PEAQ_WMI - tristate "PEAQ 2-in-1 WMI hotkey driver" - depends on ACPI_WMI - depends on INPUT - help - Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s. +config XO15_EBOOK + tristate "OLPC XO-1.5 ebook switch" + depends on OLPC || COMPILE_TEST + depends on ACPI && INPUT + ---help--- + Support for the ebook switch on the OLPC XO-1.5 laptop. -config TOPSTAR_LAPTOP - tristate "Topstar Laptop Extras" - depends on ACPI - depends on INPUT - select INPUT_SPARSEKMAP + This switch is triggered as the screen is rotated and folded down to + convert the device into ebook form. + +config XO1_RFKILL + tristate "OLPC XO-1 software RF kill switch" + depends on OLPC || COMPILE_TEST + depends on RFKILL + ---help--- + Support for enabling/disabling the WLAN interface on the OLPC XO-1 + laptop. + +config PCENGINES_APU2 + tristate "PC Engines APUv2/3 front button and LEDs driver" + depends on INPUT && INPUT_KEYBOARD && GPIOLIB + depends on LEDS_CLASS + select GPIO_AMD_FCH + select KEYBOARD_GPIO_POLLED + select LEDS_GPIO + help + This driver provides support for the front button and LEDs on + PC Engines APUv2/APUv3 board. + + To compile this driver as a module, choose M here: the module + will be called pcengines-apuv2. + +config SAMSUNG_LAPTOP + tristate "Samsung Laptop driver" + depends on RFKILL || RFKILL = n + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on BACKLIGHT_CLASS_DEVICE select LEDS_CLASS select NEW_LEDS ---help--- - This driver adds support for hotkeys found on Topstar laptops. + This module implements a driver for a wide range of different + Samsung laptops. It offers control over the different + function keys, wireless LED, LCD backlight level. - If you have a Topstar laptop, say Y or M here. + It may also provide some sysfs files described in + + + To compile this driver as a module, choose M here: the module + will be called samsung-laptop. + +config SAMSUNG_Q10 + tristate "Samsung Q10 Extras" + depends on ACPI + select BACKLIGHT_CLASS_DEVICE + ---help--- + This driver provides support for backlight control on Samsung Q10 + and related laptops, including Dell Latitude X200. config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" @@ -917,115 +1059,129 @@ config ACPI_CMPC keys as input device, backlight device, tablet and accelerometer devices. -config INTEL_CHT_INT33FE - tristate "Intel Cherry Trail ACPI INT33FE Driver" - depends on X86 && ACPI && I2C && REGULATOR - depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m) - depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m) - depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m) +config COMPAL_LAPTOP + tristate "Compal (and others) Laptop Extras" + depends on ACPI + depends on BACKLIGHT_CLASS_DEVICE + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on RFKILL + depends on HWMON + depends on POWER_SUPPLY ---help--- - This driver add support for the INT33FE ACPI device found on - some Intel Cherry Trail devices. + This is a driver for laptops built by Compal, and some models by + other brands (e.g. Dell, Toshiba). - There are two kinds of INT33FE ACPI device possible: for hardware - with USB Type-C and Micro-B connectors. This driver supports both. + It adds support for rfkill, Bluetooth, WLAN, LCD brightness, hwmon + and battery charging level control. - The INT33FE ACPI device has a CRS table with I2cSerialBusV2 - resources for Fuel Gauge Controller and (in the Type-C variant) - FUSB302 USB Type-C Controller and PI3USB30532 USB switch. - This driver instantiates i2c-clients for these, so that standard - i2c drivers for these chips can bind to the them. +config LG_LAPTOP + tristate "LG Laptop Extras" + depends on ACPI + depends on ACPI_WMI + depends on INPUT + select INPUT_SPARSEKMAP + select LEDS_CLASS + help + This driver adds support for hotkeys as well as control of keyboard + backlight, battery maximum charge level and various other ACPI + features. - If you enable this driver it is advised to also select - CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B - device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m - for Type-C device. + If you have an LG Gram laptop, say Y or M here. - -config INTEL_INT0002_VGPIO - tristate "Intel ACPI INT0002 Virtual GPIO driver" - depends on GPIOLIB && ACPI - select GPIOLIB_IRQCHIP +config PANASONIC_LAPTOP + tristate "Panasonic Laptop Extras" + depends on INPUT && ACPI + depends on BACKLIGHT_CLASS_DEVICE + select INPUT_SPARSEKMAP ---help--- - Some peripherals on Bay Trail and Cherry Trail platforms signal a - Power Management Event (PME) to the Power Management Controller (PMC) - to wakeup the system. When this happens software needs to explicitly - clear the PME bus 0 status bit in the GPE0a_STS register to avoid an - IRQ storm on IRQ 9. + This driver adds support for access to backlight control and hotkeys + on Panasonic Let's Note laptops. - This is modelled in ACPI through the INT0002 ACPI device, which is - called a "Virtual GPIO controller" in ACPI because it defines the - event handler to call when the PME triggers through _AEI and _L02 - methods as would be done for a real GPIO interrupt in ACPI. + If you have a Panasonic Let's note laptop (such as the R1(N variant), + R2, R3, R5, T2, W2 and Y2 series), say Y. - To compile this driver as a module, choose M here: the module will - be called intel_int0002_vgpio. +config SONY_LAPTOP + tristate "Sony Laptop Extras" + depends on ACPI + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on BACKLIGHT_CLASS_DEVICE + depends on INPUT + depends on RFKILL + ---help--- + This mini-driver drives the SNC and SPIC devices present in the ACPI + BIOS of the Sony Vaio laptops. -config INTEL_HID_EVENT - tristate "INTEL HID Event" + It gives access to some extra laptop functionalities like Bluetooth, + screen brightness control, Fn keys and allows powering on/off some + devices. + + Read for more information. + +config SONYPI_COMPAT + bool "Sonypi compatibility" + depends on SONY_LAPTOP + ---help--- + Build the sonypi driver compatibility code into the sony-laptop driver. + +config SYSTEM76_ACPI + tristate "System76 ACPI Driver" + depends on ACPI + select NEW_LEDS + select LEDS_CLASS + select LEDS_TRIGGERS + help + This is a driver for System76 laptops running open firmware. It adds + support for Fn-Fx key combinations, keyboard backlight, and airplane mode + LEDs. + + If you have a System76 laptop running open firmware, say Y or M here. + +config TOPSTAR_LAPTOP + tristate "Topstar Laptop Extras" depends on ACPI depends on INPUT select INPUT_SPARSEKMAP - help - This driver provides support for the Intel HID Event hotkey interface. - Some laptops require this driver for hotkey support. - - To compile this driver as a module, choose M here: the module will - be called intel_hid. - -config INTEL_VBTN - tristate "INTEL VIRTUAL BUTTON" - depends on ACPI - depends on INPUT - select INPUT_SPARSEKMAP - help - This driver provides support for the Intel Virtual Button interface. - Some laptops require this driver for power button support. - - To compile this driver as a module, choose M here: the module will - be called intel_vbtn. - -config INTEL_SCU_IPC - bool "Intel SCU IPC Support" - depends on X86_INTEL_MID - default y + select LEDS_CLASS + select NEW_LEDS ---help--- - IPC is used to bridge the communications between kernel and SCU on - some embedded Intel x86 platforms. This is not needed for PC-type - machines. + This driver adds support for hotkeys found on Topstar laptops. -config INTEL_SCU_IPC_UTIL - tristate "Intel SCU IPC utility driver" - depends on INTEL_SCU_IPC - ---help--- - The IPC Util driver provides an interface with the SCU enabling - low level access for debug work and updating the firmware. Say - N unless you will be doing this on an Intel MID platform. + If you have a Topstar laptop, say Y or M here. -config INTEL_MID_POWER_BUTTON - tristate "power button driver for Intel MID platforms" - depends on INTEL_SCU_IPC && INPUT +config I2C_MULTI_INSTANTIATE + tristate "I2C multi instantiate pseudo device driver" + depends on I2C && ACPI help - This driver handles the power button on the Intel MID platforms. + Some ACPI-based systems list multiple i2c-devices in a single ACPI + firmware-node. This driver will instantiate separate i2c-clients + for each device in the firmware-node. - If unsure, say N. + To compile this driver as a module, choose M here: the module + will be called i2c-multi-instantiate. -config INTEL_MFLD_THERMAL - tristate "Thermal driver for Intel Medfield platform" - depends on MFD_INTEL_MSIC && THERMAL - help - Say Y here to enable thermal driver support for the Intel Medfield - platform. - -config INTEL_IPS - tristate "Intel Intelligent Power Sharing" - depends on ACPI && PCI +config MLX_PLATFORM + tristate "Mellanox Technologies platform support" + depends on I2C && REGMAP ---help--- - Intel Calpella platforms support dynamic power sharing between the - CPU and GPU, maximizing performance in a given TDP. This driver, - along with the CPU frequency and i915 drivers, provides that - functionality. If in doubt, say Y here; it will only load on - supported platforms. + This option enables system support for the Mellanox Technologies + platform. The Mellanox systems provide data center networking + solutions based on Virtual Protocol Interconnect (VPI) technology + enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE + connection. + + If you have a Mellanox system, say Y or M here. + +config TOUCHSCREEN_DMI + bool "DMI based touchscreen configuration info" + depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD + select EFI_EMBEDDED_FIRMWARE if EFI + ---help--- + Certain ACPI based tablets with e.g. Silead or Chipone touchscreens + do not have enough data in ACPI tables for the touchscreen driver to + handle the touchscreen properly, as OEMs expect the data to be baked + into the tablet model specific version of the driver shipped with the + the OS-image for the device. This option supplies the missing info. + Enable this for x86 tablets with Silead or Chipone touchscreens. config INTEL_IMR bool "Intel Isolated Memory Region support" @@ -1051,116 +1207,21 @@ config INTEL_IMR If you are running on a Galileo/Quark say Y here. -config INTEL_PMC_CORE - tristate "Intel PMC Core driver" - depends on PCI - ---help--- - The Intel Platform Controller Hub for Intel Core SoCs provides access - to Power Management Controller registers via a PCI interface. This - driver can utilize debugging capabilities and supported features as - exposed by the Power Management Controller. - - Supported features: - - SLP_S0_RESIDENCY counter - - PCH IP Power Gating status - - LTR Ignore - - MPHY/PLL gating status (Sunrisepoint PCH only) - -config IBM_RTL - tristate "Device driver to enable PRTL support" - depends on PCI - ---help--- - Enable support for IBM Premium Real Time Mode (PRTM). - This module will allow you the enter and exit PRTM in the BIOS via - sysfs on platforms that support this feature. System in PRTM will - not receive CPU-generated SMIs for recoverable errors. Use of this - feature without proper support may void your hardware warranty. - - If the proper BIOS support is found the driver will load and create - /sys/devices/system/ibm_rtl/. The "state" variable will indicate - whether or not the BIOS is in PRTM. - state = 0 (BIOS SMIs on) - state = 1 (BIOS SMIs off) - -config XO1_RFKILL - tristate "OLPC XO-1 software RF kill switch" - depends on OLPC || COMPILE_TEST - depends on RFKILL - ---help--- - Support for enabling/disabling the WLAN interface on the OLPC XO-1 - laptop. - -config XO15_EBOOK - tristate "OLPC XO-1.5 ebook switch" - depends on OLPC || COMPILE_TEST - depends on ACPI && INPUT - ---help--- - Support for the ebook switch on the OLPC XO-1.5 laptop. - - This switch is triggered as the screen is rotated and folded down to - convert the device into ebook form. - -config SAMSUNG_LAPTOP - tristate "Samsung Laptop driver" - depends on RFKILL || RFKILL = n - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on BACKLIGHT_CLASS_DEVICE - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module implements a driver for a wide range of different - Samsung laptops. It offers control over the different - function keys, wireless LED, LCD backlight level. - - It may also provide some sysfs files described in - - - To compile this driver as a module, choose M here: the module - will be called samsung-laptop. - -config MXM_WMI - tristate "WMI support for MXM Laptop Graphics" - depends on ACPI_WMI - ---help--- - MXM is a standard for laptop graphics cards, the WMI interface - is required for switchable nvidia graphics machines - -config INTEL_OAKTRAIL - tristate "Intel Oaktrail Platform Extras" - depends on ACPI - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI - ---help--- - Intel Oaktrail platform need this driver to provide interfaces to - enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y - here; it will only load on supported platforms. - -config SAMSUNG_Q10 - tristate "Samsung Q10 Extras" - depends on ACPI - select BACKLIGHT_CLASS_DEVICE - ---help--- - This driver provides support for backlight control on Samsung Q10 - and related laptops, including Dell Latitude X200. - -config APPLE_GMUX - tristate "Apple Gmux Driver" +config INTEL_IPS + tristate "Intel Intelligent Power Sharing" depends on ACPI && PCI - depends on PNP - depends on BACKLIGHT_CLASS_DEVICE - depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE - depends on ACPI_VIDEO=n || ACPI_VIDEO ---help--- - This driver provides support for the gmux device found on many - Apple laptops, which controls the display mux for the hybrid - graphics as well as the backlight. Currently only backlight - control is supported by the driver. + Intel Calpella platforms support dynamic power sharing between the + CPU and GPU, maximizing performance in a given TDP. This driver, + along with the CPU frequency and i915 drivers, provides that + functionality. If in doubt, say Y here; it will only load on + supported platforms. config INTEL_RST tristate "Intel Rapid Start Technology Driver" depends on ACPI ---help--- - This driver provides support for modifying paramaters on systems + This driver provides support for modifying parameters on systems equipped with Intel's Rapid Start Technology. When put in an ACPI sleep state, these devices will wake after either a configured timeout or when the system battery reaches a critical state, @@ -1182,62 +1243,7 @@ config INTEL_SMARTCONNECT This driver checks to determine whether the device has Intel Smart Connect enabled, and if so disables it. -config INTEL_PMC_IPC - tristate "Intel PMC IPC Driver" - depends on ACPI && PCI - ---help--- - This driver provides support for PMC control on some Intel platforms. - The PMC is an ARC processor which defines IPC commands for communication - with other entities in the CPU. - -config INTEL_BXTWC_PMIC_TMU - tristate "Intel BXT Whiskey Cove TMU Driver" - depends on REGMAP - depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC - ---help--- - Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature. - This driver enables the alarm wakeup functionality in the TMU unit - of Whiskey Cove PMIC. - -config SURFACE_PRO3_BUTTON - tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet" - depends on ACPI && INPUT - ---help--- - This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet. - -config SURFACE_3_BUTTON - tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet" - depends on ACPI && KEYBOARD_GPIO && I2C - ---help--- - This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet. - -config INTEL_PUNIT_IPC - tristate "Intel P-Unit IPC Driver" - ---help--- - This driver provides support for Intel P-Unit Mailbox IPC mechanism, - which is used to bridge the communications between kernel and P-Unit. - -config INTEL_TELEMETRY - tristate "Intel SoC Telemetry Driver" - depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 - ---help--- - This driver provides interfaces to configure and use - telemetry for INTEL SoC from APL onwards. It is also - used to get various SoC events and parameters - directly via debugfs files. Various tools may use - this interface for SoC state monitoring. - -config MLX_PLATFORM - tristate "Mellanox Technologies platform support" - depends on I2C && REGMAP - ---help--- - This option enables system support for the Mellanox Technologies - platform. The Mellanox systems provide data center networking - solutions based on Virtual Protocol Interconnect (VPI) technology - enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE - connection. - - If you have a Mellanox system, say Y or M here. +source "drivers/platform/x86/intel_speed_select_if/Kconfig" config INTEL_TURBO_MAX_3 bool "Intel Turbo Boost Max Technology 3.0 enumeration driver" @@ -1249,94 +1255,6 @@ config INTEL_TURBO_MAX_3 This driver is only required when the system is not using Hardware P-States (HWP). In HWP mode, priority can be read from ACPI tables. -config TOUCHSCREEN_DMI - bool "DMI based touchscreen configuration info" - depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD - select EFI_EMBEDDED_FIRMWARE if EFI - ---help--- - Certain ACPI based tablets with e.g. Silead or Chipone touchscreens - do not have enough data in ACPI tables for the touchscreen driver to - handle the touchscreen properly, as OEMs expect the data to be baked - into the tablet model specific version of the driver shipped with the - the OS-image for the device. This option supplies the missing info. - Enable this for x86 tablets with Silead or Chipone touchscreens. - -config INTEL_CHTDC_TI_PWRBTN - tristate "Intel Cherry Trail Dollar Cove TI power button driver" - depends on INTEL_SOC_PMIC_CHTDC_TI - depends on INPUT - ---help--- - This option adds a power button driver driver for Dollar Cove TI - PMIC on Intel Cherry Trail devices. - - To compile this driver as a module, choose M here: the module - will be called intel_chtdc_ti_pwrbtn. - -config INTEL_MRFLD_PWRBTN - tristate "Intel Merrifield Basin Cove power button driver" - depends on INTEL_SOC_PMIC_MRFLD - depends on INPUT - ---help--- - This option adds a power button driver for Basin Cove PMIC - on Intel Merrifield devices. - - To compile this driver as a module, choose M here: the module - will be called intel_mrfld_pwrbtn. - -config I2C_MULTI_INSTANTIATE - tristate "I2C multi instantiate pseudo device driver" - depends on I2C && ACPI - help - Some ACPI-based systems list multiple i2c-devices in a single ACPI - firmware-node. This driver will instantiate separate i2c-clients - for each device in the firmware-node. - - To compile this driver as a module, choose M here: the module - will be called i2c-multi-instantiate. - -config INTEL_ATOMISP2_PM - tristate "Intel AtomISP2 dummy / power-management driver" - depends on PCI && IOSF_MBI && PM - help - Power-management driver for Intel's Image Signal Processor found on - Bay Trail and Cherry Trail devices. This dummy driver's sole purpose - is to turn the ISP off (put it in D3) to save power and to allow - entering of S0ix modes. - - To compile this driver as a module, choose M here: the module - will be called intel_atomisp2_pm. - -config HUAWEI_WMI - tristate "Huawei WMI laptop extras driver" - depends on ACPI_BATTERY - depends on ACPI_WMI - depends on INPUT - select INPUT_SPARSEKMAP - select LEDS_CLASS - select LEDS_TRIGGERS - select LEDS_TRIGGER_AUDIO - select NEW_LEDS - help - This driver provides support for Huawei WMI hotkeys, battery charge - control, fn-lock, mic-mute LED, and other extra features. - - To compile this driver as a module, choose M here: the module - will be called huawei-wmi. - -config PCENGINES_APU2 - tristate "PC Engines APUv2/3 front button and LEDs driver" - depends on INPUT && INPUT_KEYBOARD && GPIOLIB - depends on LEDS_CLASS - select GPIO_AMD_FCH - select KEYBOARD_GPIO_POLLED - select LEDS_GPIO - help - This driver provides support for the front button and LEDs on - PC Engines APUv2/APUv3 board. - - To compile this driver as a module, choose M here: the module - will be called pcengines-apuv2. - config INTEL_UNCORE_FREQ_CONTROL tristate "Intel Uncore frequency control driver" depends on X86_64 @@ -1348,20 +1266,107 @@ config INTEL_UNCORE_FREQ_CONTROL To compile this driver as a module, choose M here: the module will be called intel-uncore-frequency. -source "drivers/platform/x86/intel_speed_select_if/Kconfig" +config INTEL_BXTWC_PMIC_TMU + tristate "Intel BXT Whiskey Cove TMU Driver" + depends on REGMAP + depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC + ---help--- + Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature. + This driver enables the alarm wakeup functionality in the TMU unit + of Whiskey Cove PMIC. -config SYSTEM76_ACPI - tristate "System76 ACPI Driver" - depends on ACPI - select NEW_LEDS - select LEDS_CLASS - select LEDS_TRIGGERS +config INTEL_CHTDC_TI_PWRBTN + tristate "Intel Cherry Trail Dollar Cove TI power button driver" + depends on INTEL_SOC_PMIC_CHTDC_TI + depends on INPUT + ---help--- + This option adds a power button driver driver for Dollar Cove TI + PMIC on Intel Cherry Trail devices. + + To compile this driver as a module, choose M here: the module + will be called intel_chtdc_ti_pwrbtn. + +config INTEL_MFLD_THERMAL + tristate "Thermal driver for Intel Medfield platform" + depends on MFD_INTEL_MSIC && THERMAL + help + Say Y here to enable thermal driver support for the Intel Medfield + platform. + +config INTEL_MID_POWER_BUTTON + tristate "power button driver for Intel MID platforms" + depends on INTEL_SCU_IPC && INPUT help - This is a driver for System76 laptops running open firmware. It adds - support for Fn-Fx key combinations, keyboard backlight, and airplane mode - LEDs. + This driver handles the power button on the Intel MID platforms. - If you have a System76 laptop running open firmware, say Y or M here. + If unsure, say N. + +config INTEL_MRFLD_PWRBTN + tristate "Intel Merrifield Basin Cove power button driver" + depends on INTEL_SOC_PMIC_MRFLD + depends on INPUT + ---help--- + This option adds a power button driver for Basin Cove PMIC + on Intel Merrifield devices. + + To compile this driver as a module, choose M here: the module + will be called intel_mrfld_pwrbtn. + +config INTEL_PMC_CORE + tristate "Intel PMC Core driver" + depends on PCI + ---help--- + The Intel Platform Controller Hub for Intel Core SoCs provides access + to Power Management Controller registers via a PCI interface. This + driver can utilize debugging capabilities and supported features as + exposed by the Power Management Controller. + + Supported features: + - SLP_S0_RESIDENCY counter + - PCH IP Power Gating status + - LTR Ignore + - MPHY/PLL gating status (Sunrisepoint PCH only) + +config INTEL_PMC_IPC + tristate "Intel PMC IPC Driver" + depends on ACPI && PCI + ---help--- + This driver provides support for PMC control on some Intel platforms. + The PMC is an ARC processor which defines IPC commands for communication + with other entities in the CPU. + +config INTEL_PUNIT_IPC + tristate "Intel P-Unit IPC Driver" + ---help--- + This driver provides support for Intel P-Unit Mailbox IPC mechanism, + which is used to bridge the communications between kernel and P-Unit. + +config INTEL_SCU_IPC + bool "Intel SCU IPC Support" + depends on X86_INTEL_MID + default y + ---help--- + IPC is used to bridge the communications between kernel and SCU on + some embedded Intel x86 platforms. This is not needed for PC-type + machines. + +config INTEL_SCU_IPC_UTIL + tristate "Intel SCU IPC utility driver" + depends on INTEL_SCU_IPC + ---help--- + The IPC Util driver provides an interface with the SCU enabling + low level access for debug work and updating the firmware. Say + N unless you will be doing this on an Intel MID platform. + +config INTEL_TELEMETRY + tristate "Intel SoC Telemetry Driver" + depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 + ---help--- + This driver provides interfaces to configure and use + telemetry for INTEL SoC from APL onwards. It is also + used to get various SoC events and parameters + directly via debugfs files. Various tools may use + this interface for SoC state monitoring. endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 3747b1f07cf1..53408d965874 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -3,106 +3,146 @@ # Makefile for linux/drivers/platform/x86 # x86 Platform-Specific Drivers # + +# Windows Management Interface +obj-$(CONFIG_ACPI_WMI) += wmi.o +obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o + +# WMI drivers +obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o +obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o +obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o +obj-$(CONFIG_MXM_WMI) += mxm-wmi.o +obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o +obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o + +# Acer +obj-$(CONFIG_ACERHDF) += acerhdf.o +obj-$(CONFIG_ACER_WIRELESS) += acer-wireless.o +obj-$(CONFIG_ACER_WMI) += acer-wmi.o + +# Apple +obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o + +# ASUS obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o +obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o obj-$(CONFIG_ASUS_WMI) += asus-wmi.o obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o -obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o -obj-$(CONFIG_LG_LAPTOP) += lg-laptop.o -obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o -obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o -obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o -obj-$(CONFIG_DCDBAS) += dcdbas.o -obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o -dell-smbios-objs := dell-smbios-base.o + +# Dell +obj-$(CONFIG_DCDBAS) += dcdbas.o +obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +dell-smbios-objs := dell-smbios-base.o dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o -obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o -obj-$(CONFIG_DELL_WMI) += dell-wmi.o +obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o +obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o +obj-$(CONFIG_DELL_RBU) += dell_rbu.o +obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o +obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o -obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o -obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o -obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o -obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o -obj-$(CONFIG_DELL_RBU) += dell_rbu.o -obj-$(CONFIG_ACER_WMI) += acer-wmi.o -obj-$(CONFIG_ACER_WIRELESS) += acer-wireless.o -obj-$(CONFIG_ACERHDF) += acerhdf.o +obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o +obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o + +# Fujitsu +obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o +obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o +obj-$(CONFIG_FUJITSU_TABLET) += fujitsu-tablet.o + +# GPD +obj-$(CONFIG_GPD_POCKET_FAN) += gpd-pocket-fan.o + +# Hewlett Packard obj-$(CONFIG_HP_ACCEL) += hp_accel.o obj-$(CONFIG_HP_WIRELESS) += hp-wireless.o obj-$(CONFIG_HP_WMI) += hp-wmi.o -obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o -obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o -obj-$(CONFIG_GPD_POCKET_FAN) += gpd-pocket-fan.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o -obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o + +# IBM Thinkpad and Lenovo +obj-$(CONFIG_IBM_RTL) += ibm_rtl.o obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o -obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o -obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o -obj-$(CONFIG_FUJITSU_TABLET) += fujitsu-tablet.o -obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o -obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o -obj-$(CONFIG_ACPI_WMI) += wmi.o +obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o + +# Intel +obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o +obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o +intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ + intel_cht_int33fe_typec.o \ + intel_cht_int33fe_microb.o +obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o +obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o +obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o +obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o +obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o + +# Microsoft +obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o +obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o +obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o +obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o + +# MSI +obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_MSI_WMI) += msi-wmi.o -obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o -obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o -obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o -obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o -obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o -obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o + +# OLPC +obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o +obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o + +# PC Engines +obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o + +# Samsung +obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o +obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o + +# Toshiba +obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o +obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o +obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o # toshiba_acpi must link after wmi to ensure that wmi devices are found # before toshiba_acpi initializes obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o -obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o -obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o -obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o -obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o -intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ - intel_cht_int33fe_typec.o \ - intel_cht_int33fe_microb.o - -obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o -obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o -obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o -obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o -obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o -obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o -obj-$(CONFIG_INTEL_IPS) += intel_ips.o -obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o -obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o -obj-$(CONFIG_IBM_RTL) += ibm_rtl.o -obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o -obj-$(CONFIG_MXM_WMI) += mxm-wmi.o -obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o -obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o -obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o -obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o -obj-$(CONFIG_INTEL_RST) += intel-rst.o -obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o - -obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o -obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o -obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o -obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o -obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o -obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o -obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o -obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ - intel_telemetry_pltdrv.o \ - intel_telemetry_debugfs.o -obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o -obj-$(CONFIG_PMC_ATOM) += pmc_atom.o -obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o -obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o -obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o -obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o -obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o -obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o -obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o -obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/ +# Laptop drivers +obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o +obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o +obj-$(CONFIG_LG_LAPTOP) += lg-laptop.o +obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o +obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o -obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o +obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o + +# Platform drivers +obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o +obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o +obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o + +# Intel uncore drivers +obj-$(CONFIG_INTEL_IPS) += intel_ips.o +obj-$(CONFIG_INTEL_RST) += intel-rst.o +obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o +obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/ +obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o +obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o + +# Intel PMIC / PMC / P-Unit devices +obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o +obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o +obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o +obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o +obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o +obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o +obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o +obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o +obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o +obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o +obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ + intel_telemetry_pltdrv.o \ + intel_telemetry_debugfs.o +obj-$(CONFIG_PMC_ATOM) += pmc_atom.o diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 612ef5526226..bb7c529d7d16 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -426,8 +426,11 @@ static int asus_wmi_battery_add(struct power_supply *battery) { /* The WMI method does not provide a way to specific a battery, so we * just assume it is the first battery. + * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first + * battery is named BATT. */ - if (strcmp(battery->desc->name, "BAT0") != 0) + if (strcmp(battery->desc->name, "BAT0") != 0 && + strcmp(battery->desc->name, "BATT") != 0) return -ENODEV; if (device_create_file(&battery->dev, @@ -1719,7 +1722,7 @@ static ssize_t fan_boost_mode_store(struct device *dev, asus->fan_boost_mode = new_mode; fan_boost_mode_write(asus); - return result; + return count; } // Fan boost mode: 0 - normal, 1 - overboost, 2 - silent diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c index 7d5453326b43..03c3ff34bcf5 100644 --- a/drivers/platform/x86/dell_rbu.c +++ b/drivers/platform/x86/dell_rbu.c @@ -26,6 +26,9 @@ * * See Documentation/admin-guide/dell_rbu.rst for more info. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -61,13 +64,11 @@ static struct _rbu_data { static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; module_param_string(image_type, image_type, sizeof (image_type), 0); -MODULE_PARM_DESC(image_type, - "BIOS image type. choose- mono or packet or init"); +MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet or init"); static unsigned long allocation_floor = 0x100000; module_param(allocation_floor, ulong, 0644); -MODULE_PARM_DESC(allocation_floor, - "Minimum address for allocations when using Packet mode"); +MODULE_PARM_DESC(allocation_floor, "Minimum address for allocations when using Packet mode"); struct packet_data { struct list_head list; @@ -100,10 +101,10 @@ static int create_packet(void *data, size_t length) void *packet_data_temp_buf = NULL; unsigned int idx = 0; - pr_debug("create_packet: entry \n"); + pr_debug("entry\n"); if (!rbu_data.packetsize) { - pr_debug("create_packet: packetsize not specified\n"); + pr_debug("packetsize not specified\n"); retval = -EINVAL; goto out_noalloc; } @@ -113,9 +114,7 @@ static int create_packet(void *data, size_t length) newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL); if (!newpacket) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __func__); + pr_warn("failed to allocate new packet\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_noalloc; @@ -134,17 +133,12 @@ static int create_packet(void *data, size_t length) * due to BIOS errata. This shouldn't be used for higher floors * or you will run out of mem trying to allocate the array. */ - packet_array_size = max( - (unsigned int)(allocation_floor / rbu_data.packetsize), - (unsigned int)1); + packet_array_size = max_t(unsigned int, allocation_floor / rbu_data.packetsize, 1); invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *), GFP_KERNEL); if (!invalid_addr_packet_array) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate " - "invalid_addr_packet_array \n", - __func__); + pr_warn("failed to allocate invalid_addr_packet_array\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_alloc_packet; @@ -154,9 +148,7 @@ static int create_packet(void *data, size_t length) packet_data_temp_buf = (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); if (!packet_data_temp_buf) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __func__); + pr_warn("failed to allocate new packet\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_alloc_packet_array; @@ -164,7 +156,7 @@ static int create_packet(void *data, size_t length) if ((unsigned long)virt_to_phys(packet_data_temp_buf) < allocation_floor) { - pr_debug("packet 0x%lx below floor at 0x%lx.\n", + pr_debug("packet 0x%lx below floor at 0x%lx\n", (unsigned long)virt_to_phys( packet_data_temp_buf), allocation_floor); @@ -181,7 +173,7 @@ static int create_packet(void *data, size_t length) newpacket->data = packet_data_temp_buf; - pr_debug("create_packet: newpacket at physical addr %lx\n", + pr_debug("newpacket at physical addr %lx\n", (unsigned long)virt_to_phys(newpacket->data)); /* packets may not have fixed size */ @@ -195,16 +187,14 @@ static int create_packet(void *data, size_t length) memcpy(newpacket->data, data, length); - pr_debug("create_packet: exit \n"); + pr_debug("exit\n"); out_alloc_packet_array: /* always free packet array */ - for (;idx>0;idx--) { - pr_debug("freeing unused packet below floor 0x%lx.\n", - (unsigned long)virt_to_phys( - invalid_addr_packet_array[idx-1])); - free_pages((unsigned long)invalid_addr_packet_array[idx-1], - ordernum); + while (idx--) { + pr_debug("freeing unused packet below floor 0x%lx\n", + (unsigned long)virt_to_phys(invalid_addr_packet_array[idx])); + free_pages((unsigned long)invalid_addr_packet_array[idx], ordernum); } kfree(invalid_addr_packet_array); @@ -224,10 +214,9 @@ static int packetize_data(const u8 *data, size_t length) int packet_length; u8 *temp; u8 *end = (u8 *) data + length; - pr_debug("packetize_data: data length %zd\n", length); + pr_debug("data length %zd\n", length); if (!rbu_data.packetsize) { - printk(KERN_WARNING - "dell_rbu: packetsize not specified\n"); + pr_warn("packetsize not specified\n"); return -EIO; } @@ -255,15 +244,13 @@ static int packetize_data(const u8 *data, size_t length) return rc; } -static int do_packet_read(char *data, struct list_head *ptemp_list, +static int do_packet_read(char *data, struct packet_data *newpacket, int length, int bytes_read, int *list_read_count) { void *ptemp_buf; - struct packet_data *newpacket = NULL; int bytes_copied = 0; int j = 0; - newpacket = list_entry(ptemp_list, struct packet_data, list); *list_read_count += newpacket->length; if (*list_read_count > bytes_read) { @@ -291,7 +278,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list, static int packet_read_list(char *data, size_t * pread_length) { - struct list_head *ptemp_list; + struct packet_data *newpacket; int temp_count = 0; int bytes_copied = 0; int bytes_read = 0; @@ -305,9 +292,8 @@ static int packet_read_list(char *data, size_t * pread_length) remaining_bytes = *pread_length; bytes_read = rbu_data.packet_read_count; - ptemp_list = (&packet_data_head.list)->next; - while (!list_empty(ptemp_list)) { - bytes_copied = do_packet_read(pdest, ptemp_list, + list_for_each_entry(newpacket, (&packet_data_head.list)->next, list) { + bytes_copied = do_packet_read(pdest, newpacket, remaining_bytes, bytes_read, &temp_count); remaining_bytes -= bytes_copied; bytes_read += bytes_copied; @@ -318,8 +304,6 @@ static int packet_read_list(char *data, size_t * pread_length) */ if (remaining_bytes == 0) break; - - ptemp_list = ptemp_list->next; } /*finally set the bytes read */ *pread_length = bytes_read - rbu_data.packet_read_count; @@ -329,17 +313,11 @@ static int packet_read_list(char *data, size_t * pread_length) static void packet_empty_list(void) { - struct list_head *ptemp_list; - struct list_head *pnext_list; - struct packet_data *newpacket; + struct packet_data *newpacket, *tmp; + + list_for_each_entry_safe(newpacket, tmp, (&packet_data_head.list)->next, list) { + list_del(&newpacket->list); - ptemp_list = (&packet_data_head.list)->next; - while (!list_empty(ptemp_list)) { - newpacket = - list_entry(ptemp_list, struct packet_data, list); - pnext_list = ptemp_list->next; - list_del(ptemp_list); - ptemp_list = pnext_list; /* * zero out the RBU packet memory before freeing * to make sure there are no stale RBU packets left in memory @@ -407,8 +385,7 @@ static int img_update_realloc(unsigned long size) * check for corruption */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { - printk(KERN_ERR "dell_rbu:%s: corruption " - "check failed\n", __func__); + pr_err("corruption check failed\n"); return -EINVAL; } /* @@ -430,8 +407,7 @@ static int img_update_realloc(unsigned long size) (unsigned char *)__get_free_pages(GFP_DMA32, ordernum); spin_lock(&rbu_data.lock); if (!image_update_buffer) { - pr_debug("Not enough memory for image update:" - "size = %ld\n", size); + pr_debug("Not enough memory for image update: size = %ld\n", size); return -ENOMEM; } @@ -455,15 +431,14 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if (rbu_data.num_packets == 0) { - pr_debug("read_packet_data: no packets written\n"); + pr_debug("no packets written\n"); retval = -ENOMEM; goto read_rbu_data_exit; } if (pos > rbu_data.imagesize) { retval = 0; - printk(KERN_WARNING "dell_rbu:read_packet_data: " - "data underrun\n"); + pr_warn("data underrun\n"); goto read_rbu_data_exit; } @@ -489,8 +464,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if ((rbu_data.image_update_buffer == NULL) || (rbu_data.bios_image_size == 0)) { - pr_debug("read_rbu_data_mono: image_update_buffer %p ," - "bios_image_size %lu\n", + pr_debug("image_update_buffer %p, bios_image_size %lu\n", rbu_data.image_update_buffer, rbu_data.bios_image_size); return -ENOMEM; @@ -500,9 +474,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) rbu_data.image_update_buffer, rbu_data.bios_image_size); } -static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -513,11 +487,12 @@ static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj, else if (!strcmp(image_type, "packet")) ret_count = read_packet_data(buffer, pos, count); else - pr_debug("read_rbu_data: invalid image type specified\n"); + pr_debug("invalid image type specified\n"); spin_unlock(&rbu_data.lock); return ret_count; } +static BIN_ATTR_RO(data, 0); static void callbackfn_rbu(const struct firmware *fw, void *context) { @@ -548,15 +523,15 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) */ packet_empty_list(); } else - pr_debug("invalid image type specified.\n"); + pr_debug("invalid image type specified\n"); spin_unlock(&rbu_data.lock); out: release_firmware(fw); } -static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t image_type_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) @@ -564,9 +539,9 @@ static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj, return size; } -static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t image_type_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; @@ -602,9 +577,7 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, &rbu_device->dev, GFP_KERNEL, &context, callbackfn_rbu); if (req_firm_rc) { - printk(KERN_ERR - "dell_rbu:%s request_firmware_nowait" - " failed %d\n", __func__, rc); + pr_err("request_firmware_nowait failed %d\n", rc); rc = -EIO; } else rbu_data.entry_created = 1; @@ -612,7 +585,7 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, spin_lock(&rbu_data.lock); } } else { - printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); + pr_warn("image_type is invalid\n"); spin_unlock(&rbu_data.lock); return -EINVAL; } @@ -624,10 +597,11 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, return rc; } +static BIN_ATTR_RW(image_type, 0); -static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t packet_size_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) { @@ -638,9 +612,9 @@ static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj, return size; } -static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t packet_size_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { unsigned long temp; spin_lock(&rbu_data.lock); @@ -652,22 +626,17 @@ static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj, spin_unlock(&rbu_data.lock); return count; } +static BIN_ATTR_RW(packet_size, 0); -static struct bin_attribute rbu_data_attr = { - .attr = {.name = "data", .mode = 0444}, - .read = read_rbu_data, +static struct bin_attribute *rbu_bin_attrs[] = { + &bin_attr_data, + &bin_attr_image_type, + &bin_attr_packet_size, + NULL }; -static struct bin_attribute rbu_image_type_attr = { - .attr = {.name = "image_type", .mode = 0644}, - .read = read_rbu_image_type, - .write = write_rbu_image_type, -}; - -static struct bin_attribute rbu_packet_size_attr = { - .attr = {.name = "packet_size", .mode = 0644}, - .read = read_rbu_packet_size, - .write = write_rbu_packet_size, +static const struct attribute_group rbu_group = { + .bin_attrs = rbu_bin_attrs, }; static int __init dcdrbu_init(void) @@ -678,30 +647,17 @@ static int __init dcdrbu_init(void) init_packet_head(); rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0); if (IS_ERR(rbu_device)) { - printk(KERN_ERR - "dell_rbu:%s:platform_device_register_simple " - "failed\n", __func__); + pr_err("platform_device_register_simple failed\n"); return PTR_ERR(rbu_device); } - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); + rc = sysfs_create_group(&rbu_device->dev.kobj, &rbu_group); if (rc) goto out_devreg; - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); - if (rc) - goto out_data; - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, - &rbu_packet_size_attr); - if (rc) - goto out_imtype; rbu_data.entry_created = 0; return 0; -out_imtype: - sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); -out_data: - sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); out_devreg: platform_device_unregister(rbu_device); return rc; @@ -713,6 +669,7 @@ static __exit void dcdrbu_exit(void) packet_empty_list(); img_update_free(); spin_unlock(&rbu_data.lock); + sysfs_remove_group(&rbu_device->dev.kobj, &rbu_group); platform_device_unregister(rbu_device); } diff --git a/drivers/platform/x86/gpd-pocket-fan.c b/drivers/platform/x86/gpd-pocket-fan.c index b471b86c28fe..5b516e4c2bfb 100644 --- a/drivers/platform/x86/gpd-pocket-fan.c +++ b/drivers/platform/x86/gpd-pocket-fan.c @@ -128,7 +128,7 @@ static int gpd_pocket_fan_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(temp_limits); i++) { if (temp_limits[i] < 20000 || temp_limits[i] > 90000) { - dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 40000 and 70000)\n", + dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 20000 and 90000)\n", temp_limits[i]); temp_limits[0] = TEMP_LIMIT0_DEFAULT; temp_limits[1] = TEMP_LIMIT1_DEFAULT; diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index ffb8d5d1eb5f..6acc8457866e 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -28,7 +28,7 @@ struct i2c_inst_data { struct i2c_multi_inst_data { int num_clients; - struct i2c_client *clients[0]; + struct i2c_client *clients[]; }; static int i2c_multi_inst_count(struct acpi_resource *ares, void *data) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 43d590250228..5f4f5716c893 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -23,6 +23,7 @@ static const struct acpi_device_id intel_hid_ids[] = { {"INT33D5", 0}, {"", 0}, }; +MODULE_DEVICE_TABLE(acpi, intel_hid_ids); /* In theory, these are HID usages. */ static const struct key_entry intel_hid_keymap[] = { @@ -541,7 +542,6 @@ static struct platform_driver intel_hid_pl_driver = { .probe = intel_hid_probe, .remove = intel_hid_remove, }; -MODULE_DEVICE_TABLE(acpi, intel_hid_ids); /* * Unfortunately, some laptops provide a _HID="INT33D5" device with diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 859272075a8f..b96d172eb2c1 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -38,6 +38,7 @@ */ struct uncore_data { struct kobject kobj; + struct completion kobj_unregister; u64 stored_uncore_data; u32 initial_min_freq_khz; u32 initial_max_freq_khz; @@ -52,7 +53,7 @@ static int uncore_max_entries __read_mostly; /* Storage for uncore data for all instances */ static struct uncore_data *uncore_instances; /* Root of the all uncore sysfs kobjs */ -struct kobject uncore_root_kobj; +struct kobject *uncore_root_kobj; /* Stores the CPU mask of the target CPUs to use during uncore read/write */ static cpumask_t uncore_cpu_mask; /* CPU online callback register instance */ @@ -97,6 +98,9 @@ static int uncore_read_ratio(struct uncore_data *data, unsigned int *min, u64 cap; int ret; + if (data->control_cpu < 0) + return -ENXIO; + ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap); if (ret) return ret; @@ -116,6 +120,11 @@ static int uncore_write_ratio(struct uncore_data *data, unsigned int input, mutex_lock(&uncore_lock); + if (data->control_cpu < 0) { + ret = -ENXIO; + goto finish_write; + } + input /= UNCORE_FREQ_KHZ_MULTIPLIER; if (!input || input > 0x7F) { ret = -EINVAL; @@ -217,15 +226,19 @@ static struct attribute *uncore_attrs[] = { NULL }; +static void uncore_sysfs_entry_release(struct kobject *kobj) +{ + struct uncore_data *data = to_uncore_data(kobj); + + complete(&data->kobj_unregister); +} + static struct kobj_type uncore_ktype = { + .release = uncore_sysfs_entry_release, .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uncore_attrs, }; -static struct kobj_type uncore_root_ktype = { - .sysfs_ops = &kobj_sysfs_ops, -}; - /* Caller provides protection */ static struct uncore_data *uncore_get_instance(unsigned int cpu) { @@ -263,8 +276,10 @@ static void uncore_add_die_entry(int cpu) uncore_read_ratio(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); + init_completion(&data->kobj_unregister); + ret = kobject_init_and_add(&data->kobj, &uncore_ktype, - &uncore_root_kobj, str); + uncore_root_kobj, str); if (!ret) { data->control_cpu = cpu; data->valid = true; @@ -273,18 +288,15 @@ static void uncore_add_die_entry(int cpu) mutex_unlock(&uncore_lock); } -/* Last CPU in this die is offline, so remove sysfs entries */ +/* Last CPU in this die is offline, make control cpu invalid */ static void uncore_remove_die_entry(int cpu) { struct uncore_data *data; mutex_lock(&uncore_lock); data = uncore_get_instance(cpu); - if (data) { - kobject_put(&data->kobj); + if (data) data->control_cpu = -1; - data->valid = false; - } mutex_unlock(&uncore_lock); } @@ -384,11 +396,12 @@ static int __init intel_uncore_init(void) if (!uncore_instances) return -ENOMEM; - ret = kobject_init_and_add(&uncore_root_kobj, &uncore_root_ktype, - &cpu_subsys.dev_root->kobj, - "intel_uncore_frequency"); - if (ret) + uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", + &cpu_subsys.dev_root->kobj); + if (!uncore_root_kobj) { + ret = -ENOMEM; goto err_free; + } ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "platform/x86/uncore-freq:online", @@ -408,7 +421,7 @@ static int __init intel_uncore_init(void) err_rem_state: cpuhp_remove_state(uncore_hp_state); err_rem_kobj: - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); err_free: kfree(uncore_instances); @@ -423,10 +436,12 @@ static void __exit intel_uncore_exit(void) unregister_pm_notifier(&uncore_pm_nb); cpuhp_remove_state(uncore_hp_state); for (i = 0; i < uncore_max_entries; ++i) { - if (uncore_instances[i].valid) + if (uncore_instances[i].valid) { kobject_put(&uncore_instances[i].kobj); + wait_for_completion(&uncore_instances[i].kobj_unregister); + } } - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); kfree(uncore_instances); } module_exit(intel_uncore_exit) diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index b74932307d69..b5880936d785 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -26,6 +26,7 @@ static const struct acpi_device_id intel_vbtn_ids[] = { {"INT33D6", 0}, {"", 0}, }; +MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); /* In theory, these are HID usages. */ static const struct key_entry intel_vbtn_keymap[] = { @@ -239,7 +240,6 @@ static struct platform_driver intel_vbtn_pl_driver = { .probe = intel_vbtn_probe, .remove = intel_vbtn_remove, }; -MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); static acpi_status __init check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 3df33ff50faa..d2a5d4c36715 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -193,7 +194,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"Fuse", BIT(6)}, /* * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, - * Tiger Lake and Elkhart Lake. + * Tiger Lake, Elkhart Lake and Jasper Lake. */ {"SBR8", BIT(7)}, @@ -240,7 +241,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"HDA_PGD6", BIT(4)}, /* * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, - * Tiger Lake and ELkhart Lake. + * Tiger Lake, ELkhart Lake and Jasper Lake. */ {"PSF6", BIT(5)}, {"PSF7", BIT(6)}, @@ -273,7 +274,7 @@ static const struct pmc_bit_map *ext_icl_pfear_map[] = { }; static const struct pmc_bit_map tgl_pfear_map[] = { - /* Tiger Lake and Elkhart Lake generation onwards only */ + /* Tiger Lake, Elkhart Lake and Jasper Lake generation onwards only */ {"PSF9", BIT(0)}, {"RES_66", BIT(1)}, {"RES_67", BIT(2)}, @@ -408,13 +409,157 @@ static const struct pmc_reg_map icl_reg_map = { .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, }; +static const struct pmc_bit_map tgl_lpm0_map[] = { + {"USB2PLL_OFF_STS", BIT(18)}, + {"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)}, + {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, + {"OPIOPLL_OFF_STS", BIT(21)}, + {"OCPLL_OFF_STS", BIT(22)}, + {"AudioPLL_OFF_STS", BIT(23)}, + {"MIPIPLL_OFF_STS", BIT(24)}, + {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, + {"AC_Ring_Osc_OFF_STS", BIT(26)}, + {"MC_Ring_Osc_OFF_STS", BIT(27)}, + {"SATAPLL_OFF_STS", BIT(29)}, + {"XTAL_USB2PLL_OFF_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm1_map[] = { + {"SPI_PG_STS", BIT(2)}, + {"xHCI_PG_STS", BIT(3)}, + {"PCIe_Ctrller_A_PG_STS", BIT(4)}, + {"PCIe_Ctrller_B_PG_STS", BIT(5)}, + {"PCIe_Ctrller_C_PG_STS", BIT(6)}, + {"GBE_PG_STS", BIT(7)}, + {"SATA_PG_STS", BIT(8)}, + {"HDA0_PG_STS", BIT(9)}, + {"HDA1_PG_STS", BIT(10)}, + {"HDA2_PG_STS", BIT(11)}, + {"HDA3_PG_STS", BIT(12)}, + {"PCIe_Ctrller_D_PG_STS", BIT(13)}, + {"ISIO_PG_STS", BIT(14)}, + {"SMB_PG_STS", BIT(16)}, + {"ISH_PG_STS", BIT(17)}, + {"ITH_PG_STS", BIT(19)}, + {"SDX_PG_STS", BIT(20)}, + {"xDCI_PG_STS", BIT(25)}, + {"DCI_PG_STS", BIT(26)}, + {"CSME0_PG_STS", BIT(27)}, + {"CSME_KVM_PG_STS", BIT(28)}, + {"CSME1_PG_STS", BIT(29)}, + {"CSME_CLINK_PG_STS", BIT(30)}, + {"CSME2_PG_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm2_map[] = { + {"ADSP_D3_STS", BIT(0)}, + {"SATA_D3_STS", BIT(1)}, + {"xHCI0_D3_STS", BIT(2)}, + {"xDCI1_D3_STS", BIT(5)}, + {"SDX_D3_STS", BIT(6)}, + {"EMMC_D3_STS", BIT(7)}, + {"IS_D3_STS", BIT(8)}, + {"THC0_D3_STS", BIT(9)}, + {"THC1_D3_STS", BIT(10)}, + {"GBE_D3_STS", BIT(11)}, + {"GBE_TSN_D3_STS", BIT(12)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm3_map[] = { + {"GPIO_COM0_VNN_REQ_STS", BIT(1)}, + {"GPIO_COM1_VNN_REQ_STS", BIT(2)}, + {"GPIO_COM2_VNN_REQ_STS", BIT(3)}, + {"GPIO_COM3_VNN_REQ_STS", BIT(4)}, + {"GPIO_COM4_VNN_REQ_STS", BIT(5)}, + {"GPIO_COM5_VNN_REQ_STS", BIT(6)}, + {"Audio_VNN_REQ_STS", BIT(7)}, + {"ISH_VNN_REQ_STS", BIT(8)}, + {"CNVI_VNN_REQ_STS", BIT(9)}, + {"eSPI_VNN_REQ_STS", BIT(10)}, + {"Display_VNN_REQ_STS", BIT(11)}, + {"DTS_VNN_REQ_STS", BIT(12)}, + {"SMBUS_VNN_REQ_STS", BIT(14)}, + {"CSME_VNN_REQ_STS", BIT(15)}, + {"SMLINK0_VNN_REQ_STS", BIT(16)}, + {"SMLINK1_VNN_REQ_STS", BIT(17)}, + {"CLINK_VNN_REQ_STS", BIT(20)}, + {"DCI_VNN_REQ_STS", BIT(21)}, + {"ITH_VNN_REQ_STS", BIT(22)}, + {"CSME_VNN_REQ_STS", BIT(24)}, + {"GBE_VNN_REQ_STS", BIT(25)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm4_map[] = { + {"CPU_C10_REQ_STS_0", BIT(0)}, + {"PCIe_LPM_En_REQ_STS_3", BIT(3)}, + {"ITH_REQ_STS_5", BIT(5)}, + {"CNVI_REQ_STS_6", BIT(6)}, + {"ISH_REQ_STS_7", BIT(7)}, + {"USB2_SUS_PG_Sys_REQ_STS_10", BIT(10)}, + {"PCIe_Clk_REQ_STS_12", BIT(12)}, + {"MPHY_Core_DL_REQ_STS_16", BIT(16)}, + {"Break-even_En_REQ_STS_17", BIT(17)}, + {"Auto-demo_En_REQ_STS_18", BIT(18)}, + {"MPHY_SUS_REQ_STS_22", BIT(22)}, + {"xDCI_attached_REQ_STS_24", BIT(24)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm5_map[] = { + {"LSX_Wake0_En_STS", BIT(0)}, + {"LSX_Wake0_Pol_STS", BIT(1)}, + {"LSX_Wake1_En_STS", BIT(2)}, + {"LSX_Wake1_Pol_STS", BIT(3)}, + {"LSX_Wake2_En_STS", BIT(4)}, + {"LSX_Wake2_Pol_STS", BIT(5)}, + {"LSX_Wake3_En_STS", BIT(6)}, + {"LSX_Wake3_Pol_STS", BIT(7)}, + {"LSX_Wake4_En_STS", BIT(8)}, + {"LSX_Wake4_Pol_STS", BIT(9)}, + {"LSX_Wake5_En_STS", BIT(10)}, + {"LSX_Wake5_Pol_STS", BIT(11)}, + {"LSX_Wake6_En_STS", BIT(12)}, + {"LSX_Wake6_Pol_STS", BIT(13)}, + {"LSX_Wake7_En_STS", BIT(14)}, + {"LSX_Wake7_Pol_STS", BIT(15)}, + {"Intel_Se_IO_Wake0_En_STS", BIT(16)}, + {"Intel_Se_IO_Wake0_Pol_STS", BIT(17)}, + {"Intel_Se_IO_Wake1_En_STS", BIT(18)}, + {"Intel_Se_IO_Wake1_Pol_STS", BIT(19)}, + {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, + {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, + {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, + {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, + {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, + {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, + {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, + {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, + {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, + {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, + {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, + {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map *tgl_lpm_maps[] = { + tgl_lpm0_map, + tgl_lpm1_map, + tgl_lpm2_map, + tgl_lpm3_map, + tgl_lpm4_map, + tgl_lpm5_map, + NULL +}; + static const struct pmc_reg_map tgl_reg_map = { .pfear_sts = ext_tgl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slps0_dbg_maps = cnp_slps0_dbg_maps, .ltr_show_sts = cnp_ltr_show_map, .msr_sts = msr_map, - .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, .regmap_length = CNP_PMC_MMIO_REG_LEN, .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, @@ -422,6 +567,12 @@ static const struct pmc_reg_map tgl_reg_map = { .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, + .lpm_modes = tgl_lpm_modes, + .lpm_en_offset = TGL_LPM_EN_OFFSET, + .lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET, + .lpm_sts = tgl_lpm_maps, + .lpm_status_offset = TGL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET, }; static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) @@ -463,6 +614,84 @@ static int pmc_core_check_read_lock_bit(void) return value & BIT(pmcdev->map->pm_read_disable_bit); } +static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev, + struct seq_file *s) +{ + const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; + const struct pmc_bit_map *map; + int offset = pmcdev->map->slps0_dbg_offset; + u32 data; + + while (*maps) { + map = *maps; + data = pmc_core_reg_read(pmcdev, offset); + offset += 4; + while (map->name) { + if (dev) + dev_dbg(dev, "SLP_S0_DBG: %-32s\tState: %s\n", + map->name, + data & map->bit_mask ? "Yes" : "No"); + if (s) + seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", + map->name, + data & map->bit_mask ? "Yes" : "No"); + ++map; + } + ++maps; + } +} + +static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps) +{ + int idx; + + for (idx = 0; maps[idx]; idx++) + ;/* Nothing */ + + return idx; +} + +static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, + struct seq_file *s, u32 offset, + const char *str, + const struct pmc_bit_map **maps) +{ + int index, idx, len = 32, bit_mask, arr_size; + u32 *lpm_regs; + + arr_size = pmc_core_lpm_get_arr_size(maps); + lpm_regs = kmalloc_array(arr_size, sizeof(*lpm_regs), GFP_KERNEL); + if (!lpm_regs) + return; + + for (index = 0; index < arr_size; index++) { + lpm_regs[index] = pmc_core_reg_read(pmcdev, offset); + offset += 4; + } + + for (idx = 0; idx < arr_size; idx++) { + if (dev) + dev_dbg(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx, + lpm_regs[idx]); + if (s) + seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx, + lpm_regs[idx]); + for (index = 0; maps[idx][index].name && index < len; index++) { + bit_mask = maps[idx][index].bit_mask; + if (dev) + dev_dbg(dev, "%-30s %-30d\n", + maps[idx][index].name, + lpm_regs[idx] & bit_mask ? 1 : 0); + if (s) + seq_printf(s, "%-30s %-30d\n", + maps[idx][index].name, + lpm_regs[idx] & bit_mask ? 1 : 0); + } + } + + kfree(lpm_regs); +} + #if IS_ENABLED(CONFIG_DEBUG_FS) static bool slps0_dbg_latch; @@ -698,27 +927,11 @@ out_unlock: static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; - const struct pmc_bit_map *map; - int offset; - u32 data; pmc_core_slps0_dbg_latch(pmcdev, false); - offset = pmcdev->map->slps0_dbg_offset; - while (*maps) { - map = *maps; - data = pmc_core_reg_read(pmcdev, offset); - offset += 4; - while (map->name) { - seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", - map->name, - data & map->bit_mask ? - "Yes" : "No"); - ++map; - } - ++maps; - } + pmc_core_slps0_display(pmcdev, NULL, s); pmc_core_slps0_dbg_latch(pmcdev, true); + return 0; } DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); @@ -794,6 +1007,51 @@ static int pmc_core_ltr_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); +static int pmc_core_substate_res_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const char **lpm_modes = pmcdev->map->lpm_modes; + u32 offset = pmcdev->map->lpm_residency_offset; + u32 lpm_en; + int index; + + lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); + seq_printf(s, "status substate residency\n"); + for (index = 0; lpm_modes[index]; index++) { + seq_printf(s, "%7s %7s %-15u\n", + BIT(index) & lpm_en ? "Enabled" : " ", + lpm_modes[index], pmc_core_reg_read(pmcdev, offset)); + offset += 4; + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res); + +static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + u32 offset = pmcdev->map->lpm_status_offset; + + pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs); + +static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + u32 offset = pmcdev->map->lpm_live_status_offset; + + pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_l_sts_regs); + static int pmc_core_pkgc_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; @@ -859,6 +1117,21 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_bool("slp_s0_dbg_latch", 0644, dir, &slps0_dbg_latch); } + + if (pmcdev->map->lpm_en_offset) { + debugfs_create_file("substate_residencies", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_res_fops); + } + + if (pmcdev->map->lpm_status_offset) { + debugfs_create_file("substate_status_registers", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_sts_regs_fops); + debugfs_create_file("substate_live_status_registers", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_l_sts_regs_fops); + } } #else static inline void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) @@ -883,6 +1156,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &tgl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &tgl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &tgl_reg_map), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &tgl_reg_map), {} }; @@ -1047,10 +1321,8 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) static int pmc_core_resume(struct device *dev) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; - int offset = pmcdev->map->slps0_dbg_offset; - const struct pmc_bit_map *map; - u32 data; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + int offset = pmcdev->map->lpm_status_offset; if (!pmcdev->check_counters) return 0; @@ -1068,18 +1340,11 @@ static int pmc_core_resume(struct device *dev) /* The real interesting case - S0ix failed - lets ask PMC why. */ dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n", pmcdev->s0ix_counter); - while (*maps) { - map = *maps; - data = pmc_core_reg_read(pmcdev, offset); - offset += 4; - while (map->name) { - dev_dbg(dev, "SLP_S0_DBG: %-32s\tState: %s\n", - map->name, - data & map->bit_mask ? "Yes" : "No"); - map++; - } - maps++; - } + if (pmcdev->map->slps0_dbg_maps) + pmc_core_slps0_display(pmcdev, dev, NULL); + if (pmcdev->map->lpm_sts) + pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps); + return 0; } diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index f1a0792b3f91..0d50b2402abe 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -188,6 +188,28 @@ enum ppfear_regs { #define TGL_NUM_IP_IGN_ALLOWED 22 +/* + * Tigerlake Power Management Controller register offsets + */ +#define TGL_LPM_EN_OFFSET 0x1C78 +#define TGL_LPM_RESIDENCY_OFFSET 0x1C80 + +/* Tigerlake Low Power Mode debug registers */ +#define TGL_LPM_STATUS_OFFSET 0x1C3C +#define TGL_LPM_LIVE_STATUS_OFFSET 0x1C5C + +const char *tgl_lpm_modes[] = { + "S0i2.0", + "S0i2.1", + "S0i2.2", + "S0i3.0", + "S0i3.1", + "S0i3.2", + "S0i3.3", + "S0i3.4", + NULL +}; + struct pmc_bit_map { const char *name; u32 bit_mask; @@ -221,6 +243,7 @@ struct pmc_reg_map { const struct pmc_bit_map **slps0_dbg_maps; const struct pmc_bit_map *ltr_show_sts; const struct pmc_bit_map *msr_sts; + const struct pmc_bit_map **lpm_sts; const u32 slp_s0_offset; const u32 ltr_ignore_offset; const int regmap_length; @@ -231,6 +254,12 @@ struct pmc_reg_map { const u32 slps0_dbg_offset; const u32 ltr_ignore_max; const u32 pm_vric1_offset; + /* Low Power Mode registers */ + const char **lpm_modes; + const u32 lpm_en_offset; + const u32 lpm_residency_offset; + const u32 lpm_status_offset; + const u32 lpm_live_status_offset; }; /** diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c index ad8c7c0df4d9..3584859fcc42 100644 --- a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c +++ b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c @@ -126,7 +126,7 @@ static void isst_if_remove(struct pci_dev *pdev) struct isst_if_device *punit_dev; punit_dev = pci_get_drvdata(pdev); - isst_if_cdev_unregister(ISST_IF_DEV_MBOX); + isst_if_cdev_unregister(ISST_IF_DEV_MMIO); mutex_destroy(&punit_dev->mutex); } diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index 3e3c66dfec2e..ca684ed760d1 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -383,6 +383,14 @@ static const struct dmi_system_id critclk_systems[] = { DMI_MATCH(DMI_PRODUCT_NAME, "3I380D"), }, }, + { + /* pmc_plt_clk* - are used for ethernet controllers */ + .ident = "Lex 2I385SW", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"), + DMI_MATCH(DMI_PRODUCT_NAME, "2I385SW"), + }, + }, { /* pmc_plt_clk* - are used for ethernet controllers */ .ident = "Beckhoff CB3163", diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fb088dd8529e..51309f7ceede 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -827,10 +827,10 @@ static ssize_t sony_nc_handles_show(struct device *dev, int i; for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", + len += scnprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", handles->cap[i]); } - len += snprintf(buffer + len, PAGE_SIZE - len, "\n"); + len += scnprintf(buffer + len, PAGE_SIZE - len, "\n"); return len; } @@ -2187,10 +2187,10 @@ static ssize_t sony_nc_thermal_profiles_show(struct device *dev, for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) { if (!cnt || (th_handle->profiles & cnt)) - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ", + idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "%s ", snc_thermal_profiles[cnt]); } - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n"); + idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "\n"); return idx; } diff --git a/drivers/platform/x86/surface3_power.c b/drivers/platform/x86/surface3_power.c new file mode 100644 index 000000000000..946ac2dc08ae --- /dev/null +++ b/drivers/platform/x86/surface3_power.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Supports for the power IC on the Surface 3 tablet. + * + * (C) Copyright 2016-2018 Red Hat, Inc + * (C) Copyright 2016-2018 Benjamin Tissoires + * (C) Copyright 2016 Stephen Just + * + * This driver has been reverse-engineered by parsing the DSDT of the Surface 3 + * and looking at the registers of the chips. + * + * The DSDT allowed to find out that: + * - the driver is required for the ACPI BAT0 device to communicate to the chip + * through an operation region. + * - the various defines for the operation region functions to communicate with + * this driver + * - the DSM 3f99e367-6220-4955-8b0f-06ef2ae79412 allows to trigger ACPI + * events to BAT0 (the code is all available in the DSDT). + * + * Further findings regarding the 2 chips declared in the MSHW0011 are: + * - there are 2 chips declared: + * . 0x22 seems to control the ADP1 line status (and probably the charger) + * . 0x55 controls the battery directly + * - the battery chip uses a SMBus protocol (using plain SMBus allows non + * destructive commands): + * . the commands/registers used are in the range 0x00..0x7F + * . if bit 8 (0x80) is set in the SMBus command, the returned value is the + * same as when it is not set. There is a high chance this bit is the + * read/write + * . the various registers semantic as been deduced by observing the register + * dumps. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SURFACE_3_POLL_INTERVAL (2 * HZ) +#define SURFACE_3_STRLEN 10 + +struct mshw0011_data { + struct i2c_client *adp1; + struct i2c_client *bat0; + unsigned short notify_mask; + struct task_struct *poll_task; + bool kthread_running; + + bool charging; + bool bat_charging; + u8 trip_point; + s32 full_capacity; +}; + +struct mshw0011_handler_data { + struct acpi_connection_info info; + struct i2c_client *client; +}; + +struct bix { + u32 revision; + u32 power_unit; + u32 design_capacity; + u32 last_full_charg_capacity; + u32 battery_technology; + u32 design_voltage; + u32 design_capacity_of_warning; + u32 design_capacity_of_low; + u32 cycle_count; + u32 measurement_accuracy; + u32 max_sampling_time; + u32 min_sampling_time; + u32 max_average_interval; + u32 min_average_interval; + u32 battery_capacity_granularity_1; + u32 battery_capacity_granularity_2; + char model[SURFACE_3_STRLEN]; + char serial[SURFACE_3_STRLEN]; + char type[SURFACE_3_STRLEN]; + char OEM[SURFACE_3_STRLEN]; +} __packed; + +struct bst { + u32 battery_state; + s32 battery_present_rate; + u32 battery_remaining_capacity; + u32 battery_present_voltage; +} __packed; + +struct gsb_command { + u8 arg0; + u8 arg1; + u8 arg2; +} __packed; + +struct gsb_buffer { + u8 status; + u8 len; + u8 ret; + union { + struct gsb_command cmd; + struct bst bst; + struct bix bix; + } __packed; +} __packed; + +#define ACPI_BATTERY_STATE_DISCHARGING BIT(0) +#define ACPI_BATTERY_STATE_CHARGING BIT(1) +#define ACPI_BATTERY_STATE_CRITICAL BIT(2) + +#define MSHW0011_CMD_DEST_BAT0 0x01 +#define MSHW0011_CMD_DEST_ADP1 0x03 + +#define MSHW0011_CMD_BAT0_STA 0x01 +#define MSHW0011_CMD_BAT0_BIX 0x02 +#define MSHW0011_CMD_BAT0_BCT 0x03 +#define MSHW0011_CMD_BAT0_BTM 0x04 +#define MSHW0011_CMD_BAT0_BST 0x05 +#define MSHW0011_CMD_BAT0_BTP 0x06 +#define MSHW0011_CMD_ADP1_PSR 0x07 +#define MSHW0011_CMD_BAT0_PSOC 0x09 +#define MSHW0011_CMD_BAT0_PMAX 0x0a +#define MSHW0011_CMD_BAT0_PSRC 0x0b +#define MSHW0011_CMD_BAT0_CHGI 0x0c +#define MSHW0011_CMD_BAT0_ARTG 0x0d + +#define MSHW0011_NOTIFY_GET_VERSION 0x00 +#define MSHW0011_NOTIFY_ADP1 0x01 +#define MSHW0011_NOTIFY_BAT0_BST 0x02 +#define MSHW0011_NOTIFY_BAT0_BIX 0x05 + +#define MSHW0011_ADP1_REG_PSR 0x04 + +#define MSHW0011_BAT0_REG_CAPACITY 0x0c +#define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY 0x0e +#define MSHW0011_BAT0_REG_DESIGN_CAPACITY 0x40 +#define MSHW0011_BAT0_REG_VOLTAGE 0x08 +#define MSHW0011_BAT0_REG_RATE 0x14 +#define MSHW0011_BAT0_REG_OEM 0x45 +#define MSHW0011_BAT0_REG_TYPE 0x4e +#define MSHW0011_BAT0_REG_SERIAL_NO 0x56 +#define MSHW0011_BAT0_REG_CYCLE_CNT 0x6e + +#define MSHW0011_EV_2_5_MASK GENMASK(8, 0) + +/* 3f99e367-6220-4955-8b0f-06ef2ae79412 */ +static const guid_t mshw0011_guid = + GUID_INIT(0x3F99E367, 0x6220, 0x4955, 0x8B, 0x0F, 0x06, 0xEF, + 0x2A, 0xE7, 0x94, 0x12); + +static int +mshw0011_notify(struct mshw0011_data *cdata, u8 arg1, u8 arg2, + unsigned int *ret_value) +{ + union acpi_object *obj; + struct acpi_device *adev; + acpi_handle handle; + unsigned int i; + + handle = ACPI_HANDLE(&cdata->adp1->dev); + if (!handle || acpi_bus_get_device(handle, &adev)) + return -ENODEV; + + obj = acpi_evaluate_dsm_typed(handle, &mshw0011_guid, arg1, arg2, NULL, + ACPI_TYPE_BUFFER); + if (!obj) { + dev_err(&cdata->adp1->dev, "device _DSM execution failed\n"); + return -ENODEV; + } + + *ret_value = 0; + for (i = 0; i < obj->buffer.length; i++) + *ret_value |= obj->buffer.pointer[i] << (i * 8); + + ACPI_FREE(obj); + return 0; +} + +static const struct bix default_bix = { + .revision = 0x00, + .power_unit = 0x01, + .design_capacity = 0x1dca, + .last_full_charg_capacity = 0x1dca, + .battery_technology = 0x01, + .design_voltage = 0x10df, + .design_capacity_of_warning = 0x8f, + .design_capacity_of_low = 0x47, + .cycle_count = 0xffffffff, + .measurement_accuracy = 0x00015f90, + .max_sampling_time = 0x03e8, + .min_sampling_time = 0x03e8, + .max_average_interval = 0x03e8, + .min_average_interval = 0x03e8, + .battery_capacity_granularity_1 = 0x45, + .battery_capacity_granularity_2 = 0x11, + .model = "P11G8M", + .serial = "", + .type = "LION", + .OEM = "", +}; + +static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix) +{ + struct i2c_client *client = cdata->bat0; + char buf[SURFACE_3_STRLEN]; + int ret; + + *bix = default_bix; + + /* get design capacity */ + ret = i2c_smbus_read_word_data(client, + MSHW0011_BAT0_REG_DESIGN_CAPACITY); + if (ret < 0) { + dev_err(&client->dev, "Error reading design capacity: %d\n", + ret); + return ret; + } + bix->design_capacity = ret; + + /* get last full charge capacity */ + ret = i2c_smbus_read_word_data(client, + MSHW0011_BAT0_REG_FULL_CHG_CAPACITY); + if (ret < 0) { + dev_err(&client->dev, + "Error reading last full charge capacity: %d\n", ret); + return ret; + } + bix->last_full_charg_capacity = ret; + + /* get serial number */ + ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO, + sizeof(buf), buf); + if (ret != sizeof(buf)) { + dev_err(&client->dev, "Error reading serial no: %d\n", ret); + return ret; + } + snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf); + + /* get cycle count */ + ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT); + if (ret < 0) { + dev_err(&client->dev, "Error reading cycle count: %d\n", ret); + return ret; + } + bix->cycle_count = ret; + + /* get OEM name */ + ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_OEM, + 4, buf); + if (ret != 4) { + dev_err(&client->dev, "Error reading cycle count: %d\n", ret); + return ret; + } + snprintf(bix->OEM, ARRAY_SIZE(bix->OEM), "%3pE", buf); + + return 0; +} + +static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst) +{ + struct i2c_client *client = cdata->bat0; + int rate, capacity, voltage, state; + s16 tmp; + + rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE); + if (rate < 0) + return rate; + + capacity = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CAPACITY); + if (capacity < 0) + return capacity; + + voltage = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_VOLTAGE); + if (voltage < 0) + return voltage; + + tmp = rate; + bst->battery_present_rate = abs((s32)tmp); + + state = 0; + if ((s32) tmp > 0) + state |= ACPI_BATTERY_STATE_CHARGING; + else if ((s32) tmp < 0) + state |= ACPI_BATTERY_STATE_DISCHARGING; + bst->battery_state = state; + + bst->battery_remaining_capacity = capacity; + bst->battery_present_voltage = voltage; + + return 0; +} + +static int mshw0011_adp_psr(struct mshw0011_data *cdata) +{ + return i2c_smbus_read_byte_data(cdata->adp1, MSHW0011_ADP1_REG_PSR); +} + +static int mshw0011_isr(struct mshw0011_data *cdata) +{ + struct bst bst; + struct bix bix; + int ret; + bool status, bat_status; + + ret = mshw0011_adp_psr(cdata); + if (ret < 0) + return ret; + + status = ret; + if (status != cdata->charging) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_ADP1, &ret); + + cdata->charging = status; + + ret = mshw0011_bst(cdata, &bst); + if (ret < 0) + return ret; + + bat_status = bst.battery_state; + if (bat_status != cdata->bat_charging) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_BAT0_BST, &ret); + + cdata->bat_charging = bat_status; + + ret = mshw0011_bix(cdata, &bix); + if (ret < 0) + return ret; + + if (bix.last_full_charg_capacity != cdata->full_capacity) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_BAT0_BIX, &ret); + + cdata->full_capacity = bix.last_full_charg_capacity; + + return 0; +} + +static int mshw0011_poll_task(void *data) +{ + struct mshw0011_data *cdata = data; + int ret = 0; + + cdata->kthread_running = true; + + set_freezable(); + + while (!kthread_should_stop()) { + schedule_timeout_interruptible(SURFACE_3_POLL_INTERVAL); + try_to_freeze(); + ret = mshw0011_isr(data); + if (ret) + break; + } + + cdata->kthread_running = false; + return ret; +} + +static acpi_status +mshw0011_space_handler(u32 function, acpi_physical_address command, + u32 bits, u64 *value64, + void *handler_context, void *region_context) +{ + struct gsb_buffer *gsb = (struct gsb_buffer *)value64; + struct mshw0011_handler_data *data = handler_context; + struct acpi_connection_info *info = &data->info; + struct acpi_resource_i2c_serialbus *sb; + struct i2c_client *client = data->client; + struct mshw0011_data *cdata = i2c_get_clientdata(client); + struct acpi_resource *ares; + u32 accessor_type = function >> 16; + acpi_status ret; + int status = 1; + + ret = acpi_buffer_to_resource(info->connection, info->length, &ares); + if (ACPI_FAILURE(ret)) + return ret; + + if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { + ret = AE_BAD_PARAMETER; + goto err; + } + + sb = &ares->data.i2c_serial_bus; + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { + ret = AE_BAD_PARAMETER; + goto err; + } + + if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) { + ret = AE_BAD_PARAMETER; + goto err; + } + + if (gsb->cmd.arg0 == MSHW0011_CMD_DEST_ADP1 && + gsb->cmd.arg1 == MSHW0011_CMD_ADP1_PSR) { + status = mshw0011_adp_psr(cdata); + if (status >= 0) { + ret = AE_OK; + goto out; + } else { + ret = AE_ERROR; + goto err; + } + } + + if (gsb->cmd.arg0 != MSHW0011_CMD_DEST_BAT0) { + ret = AE_BAD_PARAMETER; + goto err; + } + + switch (gsb->cmd.arg1) { + case MSHW0011_CMD_BAT0_STA: + break; + case MSHW0011_CMD_BAT0_BIX: + ret = mshw0011_bix(cdata, &gsb->bix); + break; + case MSHW0011_CMD_BAT0_BTP: + cdata->trip_point = gsb->cmd.arg2; + break; + case MSHW0011_CMD_BAT0_BST: + ret = mshw0011_bst(cdata, &gsb->bst); + break; + default: + dev_info(&cdata->bat0->dev, "command(0x%02x) is not supported.\n", gsb->cmd.arg1); + ret = AE_BAD_PARAMETER; + goto err; + } + + out: + gsb->ret = status; + gsb->status = 0; + + err: + ACPI_FREE(ares); + return ret; +} + +static int mshw0011_install_space_handler(struct i2c_client *client) +{ + acpi_handle handle; + struct mshw0011_handler_data *data; + acpi_status status; + + handle = ACPI_HANDLE(&client->dev); + if (!handle) + return -ENODEV; + + data = kzalloc(sizeof(struct mshw0011_handler_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + status = acpi_bus_attach_private_data(handle, (void *)data); + if (ACPI_FAILURE(status)) { + kfree(data); + return -ENOMEM; + } + + status = acpi_install_address_space_handler(handle, + ACPI_ADR_SPACE_GSBUS, + &mshw0011_space_handler, + NULL, + data); + if (ACPI_FAILURE(status)) { + dev_err(&client->dev, "Error installing i2c space handler\n"); + acpi_bus_detach_private_data(handle); + kfree(data); + return -ENOMEM; + } + + acpi_walk_dep_device_list(handle); + return 0; +} + +static void mshw0011_remove_space_handler(struct i2c_client *client) +{ + struct mshw0011_handler_data *data; + acpi_handle handle; + acpi_status status; + + handle = ACPI_HANDLE(&client->dev); + if (!handle) + return; + + acpi_remove_address_space_handler(handle, + ACPI_ADR_SPACE_GSBUS, + &mshw0011_space_handler); + + status = acpi_bus_get_private_data(handle, (void **)&data); + if (ACPI_SUCCESS(status)) + kfree(data); + + acpi_bus_detach_private_data(handle); +} + +static int mshw0011_probe(struct i2c_client *client) +{ + struct i2c_board_info board_info; + struct device *dev = &client->dev; + struct i2c_client *bat0; + struct mshw0011_data *data; + int error, mask; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->adp1 = client; + i2c_set_clientdata(client, data); + + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE); + + bat0 = i2c_acpi_new_device(dev, 1, &board_info); + if (!bat0) + return -ENOMEM; + + data->bat0 = bat0; + i2c_set_clientdata(bat0, data); + + error = mshw0011_notify(data, 1, MSHW0011_NOTIFY_GET_VERSION, &mask); + if (error) + goto out_err; + + data->notify_mask = mask == MSHW0011_EV_2_5_MASK; + + data->poll_task = kthread_run(mshw0011_poll_task, data, "mshw0011_adp"); + if (IS_ERR(data->poll_task)) { + error = PTR_ERR(data->poll_task); + dev_err(&client->dev, "Unable to run kthread err %d\n", error); + goto out_err; + } + + error = mshw0011_install_space_handler(client); + if (error) + goto out_err; + + return 0; + +out_err: + if (data->kthread_running) + kthread_stop(data->poll_task); + i2c_unregister_device(data->bat0); + return error; +} + +static int mshw0011_remove(struct i2c_client *client) +{ + struct mshw0011_data *cdata = i2c_get_clientdata(client); + + mshw0011_remove_space_handler(client); + + if (cdata->kthread_running) + kthread_stop(cdata->poll_task); + + i2c_unregister_device(cdata->bat0); + + return 0; +} + +static const struct acpi_device_id mshw0011_acpi_match[] = { + { "MSHW0011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match); + +static struct i2c_driver mshw0011_driver = { + .probe_new = mshw0011_probe, + .remove = mshw0011_remove, + .driver = { + .name = "mshw0011", + .acpi_match_table = mshw0011_acpi_match, + }, +}; +module_i2c_driver(mshw0011_driver); + +MODULE_AUTHOR("Benjamin Tissoires "); +MODULE_DESCRIPTION("mshw0011 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c index 2b2b8167c65b..b73763489410 100644 --- a/tools/power/x86/intel-speed-select/isst-config.c +++ b/tools/power/x86/intel-speed-select/isst-config.c @@ -15,7 +15,7 @@ struct process_cmd_struct { int arg; }; -static const char *version_str = "v1.2"; +static const char *version_str = "v1.3"; static const int supported_api_ver = 1; static struct isst_if_platform_info isst_platform_info; static char *progname; @@ -42,6 +42,7 @@ static int out_format_json; static int cmd_help; static int force_online_offline; static int auto_mode; +static int fact_enable_fail; /* clos related */ static int current_clos = -1; @@ -61,6 +62,18 @@ struct _cpu_map { }; struct _cpu_map *cpu_map; +struct cpu_topology { + short cpu; + short core_id; + short pkg_id; + short die_id; +}; + +FILE *get_output_file(void) +{ + return outf; +} + void debug_printf(const char *format, ...) { va_list args; @@ -82,6 +95,14 @@ int is_clx_n_platform(void) return 0; } +int is_skx_based_platform(void) +{ + if (cpu_model == 0x55) + return 1; + + return 0; +} + static int update_cpu_model(void) { unsigned int ebx, ecx, edx; @@ -175,25 +196,137 @@ int out_format_is_json(void) return out_format_json; } +static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id) +{ + const char *pathname = "/tmp/isst_cpu_topology.dat"; + struct cpu_topology cpu_top; + FILE *fp; + int ret; + + fp = fopen(pathname, "rb"); + if (!fp) + return -1; + + ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET); + if (ret) + goto err_ret; + + ret = fread(&cpu_top, sizeof(cpu_top), 1, fp); + if (ret != 1) { + ret = -1; + goto err_ret; + } + + *pkg_id = cpu_top.pkg_id; + *core_id = cpu_top.core_id; + *die_id = cpu_top.die_id; + ret = 0; + +err_ret: + fclose(fp); + + return ret; +} + +static void store_cpu_topology(void) +{ + const char *pathname = "/tmp/isst_cpu_topology.dat"; + FILE *fp; + int i; + + fp = fopen(pathname, "rb"); + if (fp) { + /* Mapping already exists */ + fclose(fp); + return; + } + + fp = fopen(pathname, "wb"); + if (!fp) { + fprintf(stderr, "Can't create file:%s\n", pathname); + return; + } + + for (i = 0; i < topo_max_cpus; ++i) { + struct cpu_topology cpu_top; + + cpu_top.core_id = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/core_id", i); + if (cpu_top.core_id < 0) + cpu_top.core_id = -1; + + cpu_top.pkg_id = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i); + if (cpu_top.pkg_id < 0) + cpu_top.pkg_id = -1; + + cpu_top.die_id = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/die_id", i); + if (cpu_top.die_id < 0) + cpu_top.die_id = -1; + + cpu_top.cpu = i; + + if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) { + fprintf(stderr, "Can't write to:%s\n", pathname); + break; + } + } + + fclose(fp); +} + int get_physical_package_id(int cpu) { - return parse_int_file( - 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", - cpu); + int ret; + + ret = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", + cpu); + if (ret < 0) { + int core_id, pkg_id, die_id; + + ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); + if (!ret) + return pkg_id; + } + + return ret; } int get_physical_core_id(int cpu) { - return parse_int_file( - 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); + int ret; + + ret = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/core_id", + cpu); + if (ret < 0) { + int core_id, pkg_id, die_id; + + ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); + if (!ret) + return core_id; + } + + return ret; } int get_physical_die_id(int cpu) { int ret; - ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id", - cpu); + ret = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/die_id", + cpu); + if (ret < 0) { + int core_id, pkg_id, die_id; + + ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); + if (!ret) + return die_id; + } + if (ret < 0) ret = 0; @@ -219,8 +352,14 @@ static void set_cpu_online_offline(int cpu, int state) "/sys/devices/system/cpu/cpu%d/online", cpu); fd = open(buffer, O_WRONLY); - if (fd < 0) + if (fd < 0) { + if (!cpu && state) { + fprintf(stderr, "This system is not configured for CPU 0 online/offline\n"); + fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n"); + return; + } err(-1, "%s open failed", buffer); + } if (state) ret = write(fd, "1\n", 2); @@ -259,7 +398,12 @@ static void for_each_online_package_in_set(void (*callback)(int, void *, void *, die_id = get_physical_die_id(i); if (die_id < 0) die_id = 0; - pkg_id = get_physical_package_id(i); + + pkg_id = parse_int_file(0, + "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i); + if (pkg_id < 0) + continue; + /* Create an unique id for package, die combination to store */ pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id); @@ -281,7 +425,7 @@ static void for_each_online_target_cpu_in_set( void (*callback)(int, void *, void *, void *, void *), void *arg1, void *arg2, void *arg3, void *arg4) { - int i; + int i, found = 0; for (i = 0; i < topo_max_cpus; ++i) { int online; @@ -295,9 +439,14 @@ static void for_each_online_target_cpu_in_set( online = 1; /* online entry for CPU 0 needs some special configs */ - if (online && callback) + if (online && callback) { callback(i, arg1, arg2, arg3, arg4); + found = 1; + } } + + if (!found) + fprintf(stderr, "No valid CPU in the list\n"); } #define BITMASK_SIZE 32 @@ -305,14 +454,27 @@ static void set_max_cpu_num(void) { FILE *filep; unsigned long dummy; + int i; topo_max_cpus = 0; - filep = fopen_or_exit( - "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r"); + for (i = 0; i < 256; ++i) { + char path[256]; + + snprintf(path, sizeof(path), + "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); + filep = fopen(path, "r"); + if (filep) + break; + } + + if (!filep) { + fprintf(stderr, "Can't get max cpu number\n"); + exit(0); + } + while (fscanf(filep, "%lx,", &dummy) == 1) topo_max_cpus += BITMASK_SIZE; fclose(filep); - topo_max_cpus--; /* 0 based */ debug_printf("max cpus %d\n", topo_max_cpus); } @@ -362,6 +524,10 @@ static void set_cpu_present_cpu_mask(void) die_id = 0; pkg_id = get_physical_package_id(i); + if (pkg_id < 0) { + fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i); + continue; + } if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) { int core_id = get_physical_core_id(i); @@ -542,7 +708,11 @@ static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write, } if (ioctl(fd, cmd, &io_regs) == -1) { - perror("ISST_IF_IO_CMD"); + if (errno == ENOTTY) { + perror("ISST_IF_IO_COMMAND\n"); + fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n"); + exit(0); + } fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n", cpu, reg, write); } else { @@ -571,7 +741,8 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n", cpu, command, sub_command, parameter, req_data); - if (isst_platform_info.mmio_supported && command == CONFIG_CLOS) { + if (!is_skx_based_platform() && command == CONFIG_CLOS && + sub_command != CLOS_PM_QOS_CONFIG) { unsigned int value; int write = 0; int clos_id, core_id, ret = 0; @@ -620,10 +791,14 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, err(-1, "%s open failed", pathname); if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) { - perror("ISST_IF_MBOX_COMMAND"); - fprintf(outf, - "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n", - cpu, command, sub_command, parameter, req_data); + if (errno == ENOTTY) { + perror("ISST_IF_MBOX_COMMAND\n"); + fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n"); + exit(0); + } + debug_printf( + "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n", + cpu, command, sub_command, parameter, req_data, errno); return -1; } else { *resp = mbox_cmds.mbox_cmd[0].resp_data; @@ -656,7 +831,7 @@ int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write, msr_cmds.msr_cmd[0].data = *req_resp; if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) { - perror("ISST_IF_MSR_COMMAD"); + perror("ISST_IF_MSR_COMMAND"); fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n", cpu, msr, write); } else { @@ -697,12 +872,85 @@ static int isst_fill_platform_info(void) return 0; } +static void isst_print_extended_platform_info(void) +{ + int cp_state, cp_cap, fact_support = 0, pbf_support = 0; + struct isst_pkg_ctdp_level_info ctdp_level; + struct isst_pkg_ctdp pkg_dev; + int ret, i, j; + FILE *filep; + + for (i = 0; i < 256; ++i) { + char path[256]; + + snprintf(path, sizeof(path), + "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); + filep = fopen(path, "r"); + if (filep) + break; + } + + if (!filep) + return; + + fclose(filep); + + ret = isst_get_ctdp_levels(i, &pkg_dev); + if (ret) + return; + + if (pkg_dev.enabled) { + fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n"); + } else { + fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n"); + fprintf(outf, "Only performance level 0 (base level) is present\n"); + } + + if (pkg_dev.locked) + fprintf(outf, "TDP level change control is locked\n"); + else + fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels); + + for (j = 0; j <= pkg_dev.levels; ++j) { + ret = isst_get_ctdp_control(i, j, &ctdp_level); + if (ret) + continue; + + if (!fact_support && ctdp_level.fact_support) + fact_support = 1; + + if (!pbf_support && ctdp_level.pbf_support) + pbf_support = 1; + } + + if (fact_support) + fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n"); + else + fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n"); + + if (pbf_support) + fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n"); + else + fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n"); + + ret = isst_read_pm_config(i, &cp_state, &cp_cap); + if (cp_cap) + fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n"); + else + fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n"); +} + static void isst_print_platform_information(void) { struct isst_if_platform_info platform_info; const char *pathname = "/dev/isst_interface"; int fd; + if (is_clx_n_platform()) { + fprintf(stderr, "\nThis option in not supported on this platform\n"); + exit(0); + } + fd = open(pathname, O_RDWR); if (fd < 0) err(-1, "%s open failed", pathname); @@ -718,6 +966,7 @@ static void isst_print_platform_information(void) platform_info.mbox_supported); fprintf(outf, "Platform: mmio supported : %d\n", platform_info.mmio_supported); + isst_print_extended_platform_info(); } close(fd); @@ -725,6 +974,7 @@ static void isst_print_platform_information(void) exit(0); } +static char *local_str0, *local_str1; static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, void *arg4) { @@ -734,13 +984,14 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, fn_ptr = arg1; ret = fn_ptr(cpu, arg2); if (ret) - perror("get_tdp_*"); + isst_display_error_info_message(1, "get_tdp_* failed", 0, 0); else isst_ctdp_display_core_info(cpu, outf, arg3, - *(unsigned int *)arg4); + *(unsigned int *)arg4, + local_str0, local_str1); } -#define _get_tdp_level(desc, suffix, object, help) \ +#define _get_tdp_level(desc, suffix, object, help, str0, str1) \ static void get_tdp_##object(int arg) \ { \ struct isst_pkg_ctdp ctdp; \ @@ -751,6 +1002,8 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, help); \ exit(0); \ } \ + local_str0 = str0; \ + local_str1 = str1; \ isst_ctdp_display_information_start(outf); \ if (max_target_cpus) \ for_each_online_target_cpu_in_set( \ @@ -764,12 +1017,12 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, isst_ctdp_display_information_end(outf); \ } -_get_tdp_level("get-config-levels", levels, levels, "TDP levels"); -_get_tdp_level("get-config-version", levels, version, "TDP version"); -_get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status"); +_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL); +_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL); +_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled"); _get_tdp_level("get-config-current_level", levels, current_level, - "Current TDP Level"); -_get_tdp_level("get-lock-status", levels, locked, "TDP lock status"); + "Current TDP Level", NULL, NULL); +_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked"); struct isst_pkg_ctdp clx_n_pkg_dev; @@ -902,9 +1155,14 @@ static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2, { int ret; + if (tdp_level != 0xff && tdp_level != 0) { + isst_display_error_info_message(1, "Invalid level", 1, tdp_level); + exit(0); + } + ret = clx_n_config(cpu); if (ret) { - perror("isst_get_process_ctdp"); + debug_printf("clx_n_config failed"); } else { struct isst_pkg_ctdp_level_info *ctdp_level; struct isst_pbf_info *pbf_info; @@ -926,7 +1184,9 @@ static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2, memset(&pkg_dev, 0, sizeof(pkg_dev)); ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev); if (ret) { - perror("isst_get_process_ctdp"); + isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu); + isst_ctdp_display_information_end(outf); + exit(1); } else { isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev); isst_get_process_ctdp_complete(cpu, &pkg_dev); @@ -969,9 +1229,11 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, int ret; ret = isst_set_tdp_level(cpu, tdp_level); - if (ret) - perror("set_tdp_level_for_cpu"); - else { + if (ret) { + isst_display_error_info_message(1, "Set TDP level failed", 0, 0); + isst_ctdp_display_information_end(outf); + exit(1); + } else { isst_display_result(cpu, outf, "perf-profile", "set_tdp_level", ret); if (force_online_offline) { @@ -1009,11 +1271,13 @@ static void set_tdp_level(int arg) "\t Arguments: -l|--level : Specify tdp level\n"); fprintf(stderr, "\t Optional Arguments: -o | online : online/offline for the tdp level\n"); + fprintf(stderr, + "\t online/offline operation has limitations, refer to Linux hotplug documentation\n"); exit(0); } if (tdp_level == 0xff) { - fprintf(outf, "Invalid command: specify tdp_level\n"); + isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); exit(1); } isst_ctdp_display_information_start(outf); @@ -1033,7 +1297,7 @@ static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, ret = clx_n_config(cpu); if (ret) { - perror("isst_get_process_ctdp"); + isst_display_error_info_message(1, "clx_n_config failed", 0, 0); } else { struct isst_pkg_ctdp_level_info *ctdp_level; struct isst_pbf_info *pbf_info; @@ -1054,7 +1318,9 @@ static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info); if (ret) { - perror("isst_get_pbf_info"); + isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level); + isst_ctdp_display_information_end(outf); + exit(1); } else { isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info); isst_get_pbf_info_complete(&pbf_info); @@ -1074,7 +1340,7 @@ static void dump_pbf_config(int arg) } if (tdp_level == 0xff) { - fprintf(outf, "Invalid command: specify tdp_level\n"); + isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); exit(1); } @@ -1100,7 +1366,7 @@ static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max) ret = isst_pm_get_clos(cpu, clos, &clos_config); if (ret) { - perror("isst_pm_get_clos"); + isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); return ret; } clos_config.clos_min = min; @@ -1109,7 +1375,7 @@ static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max) clos_config.clos_prop_prio = wt; ret = isst_set_clos(cpu, clos, &clos_config); if (ret) { - perror("isst_pm_set_clos"); + isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); return ret; } @@ -1153,7 +1419,7 @@ static int set_clx_pbf_cpufreq_scaling_min_max(int cpu) ret = clx_n_config(cpu); if (ret) { - perror("set_clx_pbf_cpufreq_scaling_min_max"); + debug_printf("cpufreq_scaling_min_max failed for CLX"); return ret; } @@ -1316,7 +1582,7 @@ static int set_core_priority_and_min(int cpu, int mask_size, debug_printf("Associate cpu: %d clos: %d\n", i, clos); ret = isst_clos_associate(i, clos); if (ret) { - perror("isst_clos_associate"); + isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0); return ret; } } @@ -1332,14 +1598,14 @@ static int set_pbf_core_power(int cpu) ret = isst_get_ctdp_levels(cpu, &pkg_dev); if (ret) { - perror("isst_get_ctdp_levels"); + debug_printf("isst_get_ctdp_levels failed"); return ret; } debug_printf("Current_level: %d\n", pkg_dev.current_level); ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info); if (ret) { - perror("isst_get_pbf_info"); + debug_printf("isst_get_pbf_info failed"); return ret; } debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high, @@ -1349,13 +1615,13 @@ static int set_pbf_core_power(int cpu) pbf_info.core_cpumask, pbf_info.p1_high, pbf_info.p1_low); if (ret) { - perror("set_core_priority_and_min"); + debug_printf("set_core_priority_and_min failed"); return ret; } ret = isst_pm_qos_config(cpu, 1, 1); if (ret) { - perror("isst_pm_qos_config"); + debug_printf("isst_pm_qos_config failed"); return ret; } @@ -1369,17 +1635,13 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, int status = *(int *)arg4; if (is_clx_n_platform()) { + ret = 0; if (status) { - ret = 0; - if (auto_mode) - set_clx_pbf_cpufreq_scaling_min_max(cpu); + set_clx_pbf_cpufreq_scaling_min_max(cpu); } else { - ret = -1; - if (auto_mode) { - set_scaling_max_to_cpuinfo_max(cpu); - set_scaling_min_to_cpuinfo_min(cpu); - } + set_scaling_max_to_cpuinfo_max(cpu); + set_scaling_min_to_cpuinfo_min(cpu); } goto disp_result; } @@ -1392,7 +1654,7 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_set_pbf_fact_status(cpu, 1, status); if (ret) { - perror("isst_set_pbf"); + debug_printf("isst_set_pbf_fact_status failed"); if (auto_mode) isst_pm_qos_config(cpu, 0, 0); } else { @@ -1405,7 +1667,7 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, } if (auto_mode && !status) - isst_pm_qos_config(cpu, 0, 0); + isst_pm_qos_config(cpu, 0, 1); disp_result: if (status) @@ -1424,10 +1686,25 @@ static void set_pbf_enable(int arg) if (enable) { fprintf(stderr, "Enable Intel Speed Select Technology base frequency feature\n"); + if (is_clx_n_platform()) { + fprintf(stderr, + "\tOn this platform this command doesn't enable feature in the hardware.\n"); + fprintf(stderr, + "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n"); + exit(0); + + } fprintf(stderr, "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n"); } else { + if (is_clx_n_platform()) { + fprintf(stderr, + "\tOn this platform this command doesn't disable feature in the hardware.\n"); + fprintf(stderr, + "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n"); + exit(0); + } fprintf(stderr, "Disable Intel Speed Select Technology base frequency feature\n"); fprintf(stderr, @@ -1452,12 +1729,15 @@ static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2, struct isst_fact_info fact_info; int ret; - ret = isst_get_fact_info(cpu, tdp_level, &fact_info); - if (ret) - perror("isst_get_fact_bucket_info"); - else + ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info); + if (ret) { + isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level); + isst_ctdp_display_information_end(outf); + exit(1); + } else { isst_fact_display_information(cpu, outf, tdp_level, fact_bucket, fact_avx, &fact_info); + } } static void dump_fact_config(int arg) @@ -1475,7 +1755,7 @@ static void dump_fact_config(int arg) } if (tdp_level == 0xff) { - fprintf(outf, "Invalid command: specify tdp_level\n"); + isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0); exit(1); } @@ -1503,7 +1783,7 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_set_pbf_fact_status(cpu, 0, status); if (ret) { - perror("isst_set_fact"); + debug_printf("isst_set_pbf_fact_status failed"); if (auto_mode) isst_pm_qos_config(cpu, 0, 0); @@ -1527,6 +1807,8 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, disp_results: if (status) { isst_display_result(cpu, outf, "turbo-freq", "enable", ret); + if (ret) + fact_enable_fail = ret; } else { /* Since we modified TRL during Fact enable, restore it */ isst_set_trl_from_current_tdp(cpu, fact_trl); @@ -1568,7 +1850,7 @@ static void set_fact_enable(int arg) NULL, &enable); isst_ctdp_display_information_end(outf); - if (enable && auto_mode) { + if (!fact_enable_fail && enable && auto_mode) { /* * When we adjust CLOS param, we have to set for siblings also. * So for the each user specified CPU, also add the sibling @@ -1652,9 +1934,12 @@ static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3, int ret; int status = *(int *)arg4; + if (is_skx_based_platform()) + clos_priority_type = 1; + ret = isst_pm_qos_config(cpu, status, clos_priority_type); if (ret) - perror("isst_pm_qos_config"); + isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0); if (status) isst_display_result(cpu, outf, "core-power", "enable", @@ -1672,9 +1957,11 @@ static void set_clos_enable(int arg) if (enable) { fprintf(stderr, "Enable core-power for a package/die\n"); - fprintf(stderr, - "\tClos Enable: Specify priority type with [--priority|-p]\n"); - fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n"); + if (!is_skx_based_platform()) { + fprintf(stderr, + "\tClos Enable: Specify priority type with [--priority|-p]\n"); + fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n"); + } } else { fprintf(stderr, "Disable core-power: [No command arguments are required]\n"); @@ -1705,7 +1992,7 @@ static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2, ret = isst_pm_get_clos(cpu, current_clos, &clos_config); if (ret) - perror("isst_pm_get_clos"); + isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); else isst_clos_display_information(cpu, outf, current_clos, &clos_config); @@ -1721,7 +2008,8 @@ static void dump_clos_config(int arg) exit(0); } if (current_clos < 0 || current_clos > 3) { - fprintf(stderr, "Invalid clos id\n"); + isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); + isst_ctdp_display_information_end(outf); exit(0); } @@ -1742,9 +2030,14 @@ static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_clos_get_clos_information(cpu, &enable, &prio_type); if (ret) - perror("isst_clos_get_info"); - else - isst_clos_display_clos_information(cpu, outf, enable, prio_type); + isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0); + else { + int cp_state, cp_cap; + + isst_read_pm_config(cpu, &cp_state, &cp_cap); + isst_clos_display_clos_information(cpu, outf, enable, prio_type, + cp_state, cp_cap); + } } static void dump_clos_info(int arg) @@ -1752,19 +2045,17 @@ static void dump_clos_info(int arg) if (cmd_help) { fprintf(stderr, "Print Intel Speed Select Technology core power information\n"); - fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n"); - exit(0); - } - - if (!max_target_cpus) { - fprintf(stderr, - "Invalid target cpu. Specify with [-c|--cpu]\n"); + fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n"); exit(0); } isst_ctdp_display_information_start(outf); - for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, - NULL, NULL, NULL); + if (max_target_cpus) + for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, + NULL, NULL, NULL); + else + for_each_online_package_in_set(get_clos_info_for_cpu, NULL, + NULL, NULL, NULL); isst_ctdp_display_information_end(outf); } @@ -1785,7 +2076,7 @@ static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, clos_config.clos_desired = clos_desired; ret = isst_set_clos(cpu, current_clos, &clos_config); if (ret) - perror("isst_set_clos"); + isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); else isst_display_result(cpu, outf, "core-power", "config", ret); } @@ -1797,26 +2088,27 @@ static void set_clos_config(int arg) "Set core-power configuration for one of the four clos ids\n"); fprintf(stderr, "\tSpecify targeted clos id with [--clos|-c]\n"); - fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n"); - fprintf(stderr, - "\tSpecify clos Proportional Priority [--weight|-w]\n"); + if (!is_skx_based_platform()) { + fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n"); + fprintf(stderr, + "\tSpecify clos Proportional Priority [--weight|-w]\n"); + } fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n"); fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n"); - fprintf(stderr, "\tSpecify clos desired in MHz with [--desired|-d]\n"); exit(0); } if (current_clos < 0 || current_clos > 3) { - fprintf(stderr, "Invalid clos id\n"); + isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); exit(0); } - if (clos_epp < 0 || clos_epp > 0x0F) { - fprintf(stderr, "clos epp is not specified, default: 0\n"); + if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) { + fprintf(stderr, "clos epp is not specified or invalid, default: 0\n"); clos_epp = 0; } - if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) { + if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) { fprintf(stderr, - "clos frequency weight is not specified, default: 0\n"); + "clos frequency weight is not specified or invalid, default: 0\n"); clos_prop_prio = 0; } if (clos_min < 0) { @@ -1824,11 +2116,11 @@ static void set_clos_config(int arg) clos_min = 0; } if (clos_max < 0) { - fprintf(stderr, "clos max is not specified, default: 25500 MHz\n"); + fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n"); clos_max = 0xff; } - if (clos_desired < 0) { - fprintf(stderr, "clos desired is not specified, default: 0\n"); + if (clos_desired) { + fprintf(stderr, "clos desired is not supported on this platform\n"); clos_desired = 0x00; } @@ -1849,7 +2141,7 @@ static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_clos_associate(cpu, current_clos); if (ret) - perror("isst_clos_associate"); + debug_printf("isst_clos_associate failed"); else isst_display_result(cpu, outf, "core-power", "assoc", ret); } @@ -1860,19 +2152,22 @@ static void set_clos_assoc(int arg) fprintf(stderr, "Associate a clos id to a CPU\n"); fprintf(stderr, "\tSpecify targeted clos id with [--clos|-c]\n"); + fprintf(stderr, + "\tFor example to associate clos 1 to CPU 0: issue\n"); + fprintf(stderr, + "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n"); exit(0); } if (current_clos < 0 || current_clos > 3) { - fprintf(stderr, "Invalid clos id\n"); + isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); exit(0); } if (max_target_cpus) for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL, NULL, NULL, NULL); else { - fprintf(stderr, - "Invalid target cpu. Specify with [-c|--cpu]\n"); + isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); } } @@ -1883,7 +2178,7 @@ static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_clos_get_assoc_status(cpu, &clos); if (ret) - perror("isst_clos_get_assoc_status"); + isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0); else isst_clos_display_assoc_information(cpu, outf, clos); } @@ -1897,8 +2192,7 @@ static void get_clos_assoc(int arg) } if (!max_target_cpus) { - fprintf(stderr, - "Invalid target cpu. Specify with [-c|--cpu]\n"); + isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); exit(0); } @@ -2035,7 +2329,7 @@ static void parse_cmd_args(int argc, int start, char **argv) option_index = start; optind = start + 1; - while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:hoa", + while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa", long_options, &option_index)) != -1) { switch (opt) { case 'a': @@ -2061,7 +2355,7 @@ static void parse_cmd_args(int argc, int start, char **argv) fact_avx = 0x01; } else if (!strncmp(optarg, "avx2", 4)) { fact_avx = 0x02; - } else if (!strncmp(optarg, "avx512", 4)) { + } else if (!strncmp(optarg, "avx512", 6)) { fact_avx = 0x04; } else { fprintf(outf, "Invalid sse,avx options\n"); @@ -2078,6 +2372,10 @@ static void parse_cmd_args(int argc, int start, char **argv) break; case 'e': clos_epp = atoi(optarg); + if (is_skx_based_platform()) { + isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0); + exit(0); + } break; case 'n': clos_min = atoi(optarg); @@ -2089,14 +2387,25 @@ static void parse_cmd_args(int argc, int start, char **argv) break; case 'p': clos_priority_type = atoi(optarg); + if (is_skx_based_platform() && !clos_priority_type) { + isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0); + exit(0); + } break; case 'w': clos_prop_prio = atoi(optarg); + if (is_skx_based_platform()) { + isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0); + exit(0); + } break; default: - printf("no match\n"); + printf("Unknown option: ignore\n"); } } + + if (argv[optind]) + printf("Garbage at the end of command: ignore\n"); } static void isst_help(void) @@ -2214,11 +2523,18 @@ void process_command(int argc, char **argv, static void usage(void) { - printf("Intel(R) Speed Select Technology\n"); + if (is_clx_n_platform()) { + fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n"); + fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n"); + } + printf("\nUsage:\n"); printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n"); - printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n"); - printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n"); + printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n"); + if (is_clx_n_platform()) + printf("\nFEATURE : [perf-profile|base-freq]\n"); + else + printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n"); printf("\nFor help on each feature, use -h|--help\n"); printf("\tFor example: intel-speed-select perf-profile -h\n"); @@ -2231,17 +2547,29 @@ static void usage(void) printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n"); printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n"); printf("\t[-d|--debug] : Debug mode\n"); + printf("\t[-f|--format] : output format [json|text]. Default: text\n"); printf("\t[-h|--help] : Print help\n"); printf("\t[-i|--info] : Print platform information\n"); printf("\t[-o|--out] : Output file\n"); printf("\t\t\tDefault : stderr\n"); - printf("\t[-f|--format] : output format [json|text]. Default: text\n"); printf("\t[-v|--version] : Print version\n"); printf("\nResult format\n"); printf("\tResult display uses a common format for each command:\n"); printf("\tResults are formatted in text/JSON with\n"); printf("\t\tPackage, Die, CPU, and command specific results.\n"); + + printf("\nExamples\n"); + printf("\tTo get platform information:\n"); + printf("\t\tintel-speed-select --info\n"); + printf("\tTo get full perf-profile information dump:\n"); + printf("\t\tintel-speed-select perf-profile info\n"); + printf("\tTo get full base-freq information dump:\n"); + printf("\t\tintel-speed-select base-freq info -l 0\n"); + if (!is_clx_n_platform()) { + printf("\tTo get full turbo-freq information dump:\n"); + printf("\t\tintel-speed-select turbo-freq info -l 0\n"); + } exit(1); } @@ -2254,6 +2582,8 @@ static void print_version(void) static void cmdline(int argc, char **argv) { + const char *pathname = "/dev/isst_interface"; + FILE *fp; int opt; int option_index = 0; int ret; @@ -2269,6 +2599,28 @@ static void cmdline(int argc, char **argv) { 0, 0, 0, 0 } }; + if (geteuid() != 0) { + fprintf(stderr, "Must run as root\n"); + exit(0); + } + + ret = update_cpu_model(); + if (ret) + err(-1, "Invalid CPU model (%d)\n", cpu_model); + printf("Intel(R) Speed Select Technology\n"); + printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); + + if (!is_clx_n_platform()) { + fp = fopen(pathname, "rb"); + if (!fp) { + fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n"); + fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n"); + fprintf(stderr, "If the config is included then this is not a supported platform.\n"); + exit(0); + } + fclose(fp); + } + progname = argv[0]; while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options, &option_index)) != -1) { @@ -2303,21 +2655,12 @@ static void cmdline(int argc, char **argv) } } - if (geteuid() != 0) { - fprintf(stderr, "Must run as root\n"); - exit(0); - } - if (optind > (argc - 2)) { - fprintf(stderr, "Feature name and|or command not specified\n"); + usage(); exit(0); } - ret = update_cpu_model(); - if (ret) - err(-1, "Invalid CPU model (%d)\n", cpu_model); - printf("Intel(R) Speed Select Technology\n"); - printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); set_max_cpu_num(); + store_cpu_topology(); set_cpu_present_cpu_mask(); set_cpu_target_cpu_mask(); diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c index 81a119f688a3..67c9b1139631 100644 --- a/tools/power/x86/intel-speed-select/isst-core.c +++ b/tools/power/x86/intel-speed-select/isst-core.c @@ -114,8 +114,10 @@ int isst_get_tdp_info(int cpu, int config_index, ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO, 0, config_index, &resp); - if (ret) + if (ret) { + isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index); return ret; + } ctdp_level->pkg_tdp = resp & GENMASK(14, 0); ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16; @@ -352,7 +354,7 @@ int isst_set_tdp_level_msr(int cpu, int tdp_level) debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level); if (isst_get_config_tdp_lock_status(cpu)) { - debug_printf("cpu: tdp_locked %d\n", cpu); + isst_display_error_info_message(1, "tdp_locked", 0, 0); return -1; } @@ -373,19 +375,50 @@ int isst_set_tdp_level(int cpu, int tdp_level) unsigned int resp; int ret; + + if (isst_get_config_tdp_lock_status(cpu)) { + isst_display_error_info_message(1, "TDP is locked", 0, 0); + return -1; + + } + ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0, tdp_level, &resp); - if (ret) - return isst_set_tdp_level_msr(cpu, tdp_level); + if (ret) { + isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level); + return ret; + } return 0; } int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info) { + struct isst_pkg_ctdp_level_info ctdp_level; + struct isst_pkg_ctdp pkg_dev; int i, ret, core_cnt, max; unsigned int req, resp; + ret = isst_get_ctdp_levels(cpu, &pkg_dev); + if (ret) { + isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); + return ret; + } + + if (level > pkg_dev.levels) { + isst_display_error_info_message(1, "Invalid level", 1, level); + return -1; + } + + ret = isst_get_ctdp_control(cpu, level, &ctdp_level); + if (ret) + return ret; + + if (!ctdp_level.pbf_support) { + isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level); + return -1; + } + pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask); core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu)); @@ -481,6 +514,10 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable) else req &= ~BIT(17); } else { + + if (enable && !ctdp_level.sst_cp_enabled) + isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0); + if (ctdp_level.pbf_enabled) req = BIT(17); @@ -566,10 +603,32 @@ int isst_get_fact_bucket_info(int cpu, int level, return 0; } -int isst_get_fact_info(int cpu, int level, struct isst_fact_info *fact_info) +int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info) { + struct isst_pkg_ctdp_level_info ctdp_level; + struct isst_pkg_ctdp pkg_dev; unsigned int resp; - int ret; + int j, ret, print; + + ret = isst_get_ctdp_levels(cpu, &pkg_dev); + if (ret) { + isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); + return ret; + } + + if (level > pkg_dev.levels) { + isst_display_error_info_message(1, "Invalid level", 1, level); + return -1; + } + + ret = isst_get_ctdp_control(cpu, level, &ctdp_level); + if (ret) + return ret; + + if (!ctdp_level.fact_support) { + isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level); + return -1; + } ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0, @@ -585,8 +644,25 @@ int isst_get_fact_info(int cpu, int level, struct isst_fact_info *fact_info) fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff; ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info); + if (ret) + return ret; - return ret; + print = 0; + for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { + if (fact_bucket != 0xff && fact_bucket != j) + continue; + + if (!fact_info->bucket_info[j].high_priority_cores_count) + break; + + print = 1; + } + if (!print) { + isst_display_error_info_message(1, "Invalid bucket", 0, 0); + return -1; + } + + return 0; } int isst_set_trl(int cpu, unsigned long long trl) @@ -671,7 +747,7 @@ void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev) int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) { - int i, ret; + int i, ret, valid = 0; if (pkg_dev->processed) return 0; @@ -684,6 +760,14 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) cpu, pkg_dev->enabled, pkg_dev->current_level, pkg_dev->levels); + if (tdp_level != 0xff && tdp_level > pkg_dev->levels) { + isst_display_error_info_message(1, "Invalid level", 0, 0); + return -1; + } + + if (!pkg_dev->enabled) + isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0); + for (i = 0; i <= pkg_dev->levels; ++i) { struct isst_pkg_ctdp_level_info *ctdp_level; @@ -703,6 +787,7 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) if (ret) continue; + valid = 1; pkg_dev->processed = 1; ctdp_level->processed = 1; @@ -713,7 +798,7 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) } if (ctdp_level->fact_support) { - ret = isst_get_fact_info(cpu, i, + ret = isst_get_fact_info(cpu, i, 0xff, &ctdp_level->fact_info); if (ret) return ret; @@ -775,6 +860,9 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) isst_get_uncore_mem_freq(cpu, i, ctdp_level); } + if (!valid) + isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu); + return 0; } @@ -829,17 +917,19 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type) } ret = isst_write_pm_config(cpu, 0); if (ret) - perror("isst_write_pm_config\n"); + isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error\n", 0, 0); } else { ret = isst_write_pm_config(cpu, 1); if (ret) - perror("isst_write_pm_config\n"); + isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error\n", 0, 0); } ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, &resp); - if (ret) + if (ret) { + isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0); return ret; + } debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp); @@ -850,6 +940,9 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type) else req = req & ~BIT(1); + if (priority_type > 1) + isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0); + if (priority_type) req = req | BIT(2); else diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c index 4fb0c1d49d64..51dbaa5f02ec 100644 --- a/tools/power/x86/intel-speed-select/isst-display.c +++ b/tools/power/x86/intel-speed-select/isst-display.c @@ -158,10 +158,17 @@ static void format_and_print(FILE *outf, int level, char *header, char *value) last_level = level; } -static void print_package_info(int cpu, FILE *outf) +static int print_package_info(int cpu, FILE *outf) { char header[256]; + if (out_format_is_json()) { + snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d", + get_physical_package_id(cpu), get_physical_die_id(cpu), + cpu); + format_and_print(outf, 1, header, NULL); + return 1; + } snprintf(header, sizeof(header), "package-%d", get_physical_package_id(cpu)); format_and_print(outf, 1, header, NULL); @@ -169,6 +176,8 @@ static void print_package_info(int cpu, FILE *outf) format_and_print(outf, 2, header, NULL); snprintf(header, sizeof(header), "cpu-%d", cpu); format_and_print(outf, 3, header, NULL); + + return 3; } static void _isst_pbf_display_information(int cpu, FILE *outf, int level, @@ -178,7 +187,7 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level, char header[256]; char value[256]; - snprintf(header, sizeof(header), "speed-select-base-freq"); + snprintf(header, sizeof(header), "speed-select-base-freq-properties"); format_and_print(outf, disp_level, header, NULL); snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)"); @@ -222,9 +231,23 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info; char header[256]; char value[256]; - int j; + int print = 0, j; - snprintf(header, sizeof(header), "speed-select-turbo-freq"); + for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { + if (fact_bucket != 0xff && fact_bucket != j) + continue; + + if (!bucket_info[j].high_priority_cores_count) + break; + + print = 1; + } + if (!print) { + fprintf(stderr, "Invalid bucket\n"); + return; + } + + snprintf(header, sizeof(header), "speed-select-turbo-freq-properties"); format_and_print(outf, base_level, header, NULL); for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { if (fact_bucket != 0xff && fact_bucket != j) @@ -289,7 +312,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, } void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix, - unsigned int val) + unsigned int val, char *str0, char *str1) { char header[256]; char value[256]; @@ -301,8 +324,12 @@ void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix, format_and_print(outf, 2, header, NULL); snprintf(header, sizeof(header), "cpu-%d", cpu); format_and_print(outf, 3, header, NULL); - - snprintf(value, sizeof(value), "%u", val); + if (str0 && !val) + snprintf(value, sizeof(value), "%s", str0); + else if (str1 && val) + snprintf(value, sizeof(value), "%s", str1); + else + snprintf(value, sizeof(value), "%u", val); format_and_print(outf, 4, prefix, value); format_and_print(outf, 1, NULL, NULL); @@ -313,10 +340,11 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, { char header[256]; char value[256]; - int i, base_level = 1; + static int level; + int i; if (pkg_dev->processed) - print_package_info(cpu, outf); + level = print_package_info(cpu, outf); for (i = 0; i <= pkg_dev->levels; ++i) { struct isst_pkg_ctdp_level_info *ctdp_level; @@ -328,72 +356,80 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, snprintf(header, sizeof(header), "perf-profile-level-%d", ctdp_level->level); - format_and_print(outf, base_level + 3, header, NULL); + format_and_print(outf, level + 1, header, NULL); snprintf(header, sizeof(header), "cpu-count"); j = get_cpu_count(get_physical_die_id(cpu), get_physical_die_id(cpu)); snprintf(value, sizeof(value), "%d", j); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); + + j = CPU_COUNT_S(ctdp_level->core_cpumask_size, + ctdp_level->core_cpumask); + if (j) { + snprintf(header, sizeof(header), "enable-cpu-count"); + snprintf(value, sizeof(value), "%d", j); + format_and_print(outf, level + 2, header, value); + } if (ctdp_level->core_cpumask_size) { snprintf(header, sizeof(header), "enable-cpu-mask"); printcpumask(sizeof(value), value, ctdp_level->core_cpumask_size, ctdp_level->core_cpumask); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "enable-cpu-list"); printcpulist(sizeof(value), value, ctdp_level->core_cpumask_size, ctdp_level->core_cpumask); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } snprintf(header, sizeof(header), "thermal-design-power-ratio"); snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "base-frequency(MHz)"); if (!ctdp_level->sse_p1) ctdp_level->sse_p1 = ctdp_level->tdp_ratio; snprintf(value, sizeof(value), "%d", ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); if (ctdp_level->avx2_p1) { snprintf(header, sizeof(header), "base-frequency-avx2(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->avx2_p1 * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } if (ctdp_level->avx512_p1) { snprintf(header, sizeof(header), "base-frequency-avx512(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->avx512_p1 * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } if (ctdp_level->uncore_p1) { snprintf(header, sizeof(header), "uncore-frequency-min(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } if (ctdp_level->uncore_p0) { snprintf(header, sizeof(header), "uncore-frequency-max(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->uncore_p0 * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } if (ctdp_level->mem_freq) { snprintf(header, sizeof(header), "mem-frequency(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->mem_freq * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } snprintf(header, sizeof(header), @@ -405,7 +441,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, snprintf(value, sizeof(value), "disabled"); } else snprintf(value, sizeof(value), "unsupported"); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "speed-select-base-freq"); @@ -416,7 +452,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, snprintf(value, sizeof(value), "disabled"); } else snprintf(value, sizeof(value), "unsupported"); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "speed-select-core-power"); @@ -427,110 +463,115 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, snprintf(value, sizeof(value), "disabled"); } else snprintf(value, sizeof(value), "unsupported"); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); if (is_clx_n_platform()) { if (ctdp_level->pbf_support) _isst_pbf_display_information(cpu, outf, tdp_level, &ctdp_level->pbf_info, - base_level + 4); + level + 1); continue; } if (ctdp_level->pkg_tdp) { snprintf(header, sizeof(header), "thermal-design-power(W)"); snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } if (ctdp_level->t_proc_hot) { snprintf(header, sizeof(header), "tjunction-max(C)"); snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot); - format_and_print(outf, base_level + 4, header, value); + format_and_print(outf, level + 2, header, value); } snprintf(header, sizeof(header), "turbo-ratio-limits-sse"); - format_and_print(outf, base_level + 4, header, NULL); + format_and_print(outf, level + 2, header, NULL); for (j = 0; j < 8; ++j) { snprintf(header, sizeof(header), "bucket-%d", j); - format_and_print(outf, base_level + 5, header, NULL); + format_and_print(outf, level + 3, header, NULL); snprintf(header, sizeof(header), "core-count"); snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); snprintf(header, sizeof(header), "max-turbo-frequency(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->trl_sse_active_cores[j] * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); } if (ctdp_level->trl_avx_active_cores[0]) { snprintf(header, sizeof(header), "turbo-ratio-limits-avx2"); - format_and_print(outf, base_level + 4, header, NULL); + format_and_print(outf, level + 2, header, NULL); for (j = 0; j < 8; ++j) { snprintf(header, sizeof(header), "bucket-%d", j); - format_and_print(outf, base_level + 5, header, NULL); + format_and_print(outf, level + 3, header, NULL); snprintf(header, sizeof(header), "core-count"); snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); snprintf(header, sizeof(header), "max-turbo-frequency(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_active_cores[j] * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); } } if (ctdp_level->trl_avx_512_active_cores[0]) { snprintf(header, sizeof(header), "turbo-ratio-limits-avx512"); - format_and_print(outf, base_level + 4, header, NULL); + format_and_print(outf, level + 2, header, NULL); for (j = 0; j < 8; ++j) { snprintf(header, sizeof(header), "bucket-%d", j); - format_and_print(outf, base_level + 5, header, NULL); + format_and_print(outf, level + 3, header, NULL); snprintf(header, sizeof(header), "core-count"); snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); snprintf(header, sizeof(header), "max-turbo-frequency(MHz)"); snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_512_active_cores[j] * DISP_FREQ_MULTIPLIER); - format_and_print(outf, base_level + 6, header, value); + format_and_print(outf, level + 4, header, value); } } if (ctdp_level->pbf_support) _isst_pbf_display_information(cpu, outf, i, &ctdp_level->pbf_info, - base_level + 4); + level + 2); if (ctdp_level->fact_support) _isst_fact_display_information(cpu, outf, i, 0xff, 0xff, &ctdp_level->fact_info, - base_level + 4); + level + 2); } format_and_print(outf, 1, NULL, NULL); } +static int start; void isst_ctdp_display_information_start(FILE *outf) { last_level = 0; format_and_print(outf, 0, "start", NULL); + start = 1; } void isst_ctdp_display_information_end(FILE *outf) { format_and_print(outf, 0, NULL, NULL); + start = 0; } void isst_pbf_display_information(int cpu, FILE *outf, int level, struct isst_pbf_info *pbf_info) { - print_package_info(cpu, outf); - _isst_pbf_display_information(cpu, outf, level, pbf_info, 4); + int _level; + + _level = print_package_info(cpu, outf); + _isst_pbf_display_information(cpu, outf, level, pbf_info, _level + 1); format_and_print(outf, 1, NULL, NULL); } @@ -538,9 +579,11 @@ void isst_fact_display_information(int cpu, FILE *outf, int level, int fact_bucket, int fact_avx, struct isst_fact_info *fact_info) { - print_package_info(cpu, outf); + int _level; + + _level = print_package_info(cpu, outf); _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx, - fact_info, 4); + fact_info, _level + 1); format_and_print(outf, 1, NULL, NULL); } @@ -549,94 +592,103 @@ void isst_clos_display_information(int cpu, FILE *outf, int clos, { char header[256]; char value[256]; + int level; - snprintf(header, sizeof(header), "package-%d", - get_physical_package_id(cpu)); - format_and_print(outf, 1, header, NULL); - snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu)); - format_and_print(outf, 2, header, NULL); - snprintf(header, sizeof(header), "cpu-%d", cpu); - format_and_print(outf, 3, header, NULL); + level = print_package_info(cpu, outf); snprintf(header, sizeof(header), "core-power"); - format_and_print(outf, 4, header, NULL); + format_and_print(outf, level + 1, header, NULL); snprintf(header, sizeof(header), "clos"); snprintf(value, sizeof(value), "%d", clos); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "epp"); snprintf(value, sizeof(value), "%d", clos_config->epp); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "clos-proportional-priority"); snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "clos-min"); snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "clos-max"); - snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER); - format_and_print(outf, 5, header, value); + if (clos_config->clos_max == 0xff) + snprintf(value, sizeof(value), "Max Turbo frequency"); + else + snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "clos-desired"); snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); - format_and_print(outf, 1, NULL, NULL); + format_and_print(outf, level, NULL, NULL); } void isst_clos_display_clos_information(int cpu, FILE *outf, - int clos_enable, int type) + int clos_enable, int type, + int state, int cap) { char header[256]; char value[256]; + int level; - snprintf(header, sizeof(header), "package-%d", - get_physical_package_id(cpu)); - format_and_print(outf, 1, header, NULL); - snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu)); - format_and_print(outf, 2, header, NULL); - snprintf(header, sizeof(header), "cpu-%d", cpu); - format_and_print(outf, 3, header, NULL); + level = print_package_info(cpu, outf); snprintf(header, sizeof(header), "core-power"); - format_and_print(outf, 4, header, NULL); + format_and_print(outf, level + 1, header, NULL); + + snprintf(header, sizeof(header), "support-status"); + if (cap) + snprintf(value, sizeof(value), "supported"); + else + snprintf(value, sizeof(value), "unsupported"); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "enable-status"); - snprintf(value, sizeof(value), "%d", clos_enable); - format_and_print(outf, 5, header, value); + if (state) + snprintf(value, sizeof(value), "enabled"); + else + snprintf(value, sizeof(value), "disabled"); + format_and_print(outf, level + 2, header, value); + + snprintf(header, sizeof(header), "clos-enable-status"); + if (clos_enable) + snprintf(value, sizeof(value), "enabled"); + else + snprintf(value, sizeof(value), "disabled"); + format_and_print(outf, level + 2, header, value); snprintf(header, sizeof(header), "priority-type"); - snprintf(value, sizeof(value), "%d", type); - format_and_print(outf, 5, header, value); + if (type) + snprintf(value, sizeof(value), "ordered"); + else + snprintf(value, sizeof(value), "proportional"); + format_and_print(outf, level + 2, header, value); - format_and_print(outf, 1, NULL, NULL); + format_and_print(outf, level, NULL, NULL); } void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos) { char header[256]; char value[256]; + int level; - snprintf(header, sizeof(header), "package-%d", - get_physical_package_id(cpu)); - format_and_print(outf, 1, header, NULL); - snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu)); - format_and_print(outf, 2, header, NULL); - snprintf(header, sizeof(header), "cpu-%d", cpu); - format_and_print(outf, 3, header, NULL); + level = print_package_info(cpu, outf); snprintf(header, sizeof(header), "get-assoc"); - format_and_print(outf, 4, header, NULL); + format_and_print(outf, level + 1, header, NULL); snprintf(header, sizeof(header), "clos"); snprintf(value, sizeof(value), "%d", clos); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); - format_and_print(outf, 1, NULL, NULL); + format_and_print(outf, level, NULL, NULL); } void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, @@ -644,24 +696,60 @@ void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, { char header[256]; char value[256]; + int level = 3; + + if (cpu >= 0) + level = print_package_info(cpu, outf); - if (cpu >= 0) { - snprintf(header, sizeof(header), "package-%d", - get_physical_package_id(cpu)); - format_and_print(outf, 1, header, NULL); - snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu)); - format_and_print(outf, 2, header, NULL); - snprintf(header, sizeof(header), "cpu-%d", cpu); - format_and_print(outf, 3, header, NULL); - } snprintf(header, sizeof(header), "%s", feature); - format_and_print(outf, 4, header, NULL); + format_and_print(outf, level + 1, header, NULL); snprintf(header, sizeof(header), "%s", cmd); if (!result) snprintf(value, sizeof(value), "success"); else snprintf(value, sizeof(value), "failed(error %d)", result); - format_and_print(outf, 5, header, value); + format_and_print(outf, level + 2, header, value); - format_and_print(outf, 1, NULL, NULL); + format_and_print(outf, level, NULL, NULL); +} + +void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg) +{ + FILE *outf = get_output_file(); + static int error_index; + char header[256]; + char value[256]; + + if (!out_format_is_json()) { + if (arg_valid) + snprintf(value, sizeof(value), "%s %d", msg, arg); + else + snprintf(value, sizeof(value), "%s", msg); + + if (error) + fprintf(outf, "Error: %s\n", value); + else + fprintf(outf, "Information: %s\n", value); + return; + } + + if (!start) + format_and_print(outf, 0, "start", NULL); + + if (error) + snprintf(header, sizeof(header), "Error%d", error_index++); + else + snprintf(header, sizeof(header), "Information:%d", error_index++); + format_and_print(outf, 1, header, NULL); + + snprintf(header, sizeof(header), "message"); + if (arg_valid) + snprintf(value, sizeof(value), "%s %d", msg, arg); + else + snprintf(value, sizeof(value), "%s", msg); + + format_and_print(outf, 2, header, value); + format_and_print(outf, 1, NULL, NULL); + if (!start) + format_and_print(outf, 0, NULL, NULL); } diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h index ad5aa6341d0f..2e1afd856a78 100644 --- a/tools/power/x86/intel-speed-select/isst.h +++ b/tools/power/x86/intel-speed-select/isst.h @@ -172,6 +172,7 @@ extern int get_cpu_count(int pkg_id, int die_id); extern int get_core_count(int pkg_id, int die_id); /* Common interfaces */ +FILE *get_output_file(void); extern void debug_printf(const char *format, ...); extern int out_format_is_json(void); extern int get_physical_package_id(int cpu); @@ -196,6 +197,8 @@ extern int isst_send_msr_command(unsigned int cpu, unsigned int command, int write, unsigned long long *req_resp); extern int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev); +extern int isst_get_ctdp_control(int cpu, int config_index, + struct isst_pkg_ctdp_level_info *ctdp_level); extern int isst_get_coremask_info(int cpu, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level); extern int isst_get_process_ctdp(int cpu, int tdp_level, @@ -205,7 +208,7 @@ extern void isst_get_process_ctdp_complete(int cpu, extern void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, struct isst_pkg_ctdp *pkg_dev); extern void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix, - unsigned int val); + unsigned int val, char *str0, char *str1); extern void isst_ctdp_display_information_start(FILE *outf); extern void isst_ctdp_display_information_end(FILE *outf); extern void isst_pbf_display_information(int cpu, FILE *outf, int level, @@ -216,7 +219,7 @@ extern int isst_set_pbf_fact_status(int cpu, int pbf, int enable); extern int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info); extern void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info); -extern int isst_get_fact_info(int cpu, int level, +extern int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info); extern int isst_get_fact_bucket_info(int cpu, int level, struct isst_fact_bucket_info *bucket_info); @@ -245,7 +248,10 @@ extern void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, extern int isst_clos_get_clos_information(int cpu, int *enable, int *type); extern void isst_clos_display_clos_information(int cpu, FILE *outf, - int clos_enable, int type); + int clos_enable, int type, + int state, int cap); extern int is_clx_n_platform(void); extern int get_cpufreq_base_freq(int cpu); +extern int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap); +extern void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg); #endif