diff options
author | Linus Torvalds | 2020-08-03 18:02:53 -0700 |
---|---|---|
committer | Linus Torvalds | 2020-08-03 18:02:53 -0700 |
commit | 09a0bd07764359650d41dbcb723f81321e523217 (patch) | |
tree | afcba7e534e48d7790f8acaa01993d03dee8cf43 | |
parent | e53bc3ff99b413083bfef80d0fdbf7da3a09fc0c (diff) | |
parent | 67186653c90360922e3965d0376a61dbf6c42711 (diff) |
Merge tag 'platform-drivers-x86-v5.9-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform driver updates from Andy Shevchenko:
- ASUS WMI driver honors BAT1 name of the battery (quite a few new
laptops are using it)
- Dell WMI driver supports new key codes and backlight events
- ThinkPad ACPI driver now may use standard charge threshold interface,
it also has been updated to provide Laptop or Desktop mode to the
user
- Intel Speed Select Technology gained support on Sapphire Rapids
platform
- Regular update of Speed Select Technology tools
- Mellanox has been updated to support complex attributes
- PMC core driver has been fixed to show correct names for LPM0
register
- HTTP links were replaced by HTTPS ones where it applies
- Miscellaneous fixes and cleanups here and there
* tag 'platform-drivers-x86-v5.9-1' of git://git.infradead.org/linux-platform-drivers-x86: (42 commits)
platform/x86: asus-nb-wmi: Drop duplicate DMI quirk structures
platform/x86: thinkpad_acpi: Make some symbols static
platform/x86: thinkpad_acpi: add documentation for battery charge control
platform/x86: thinkpad_acpi: use standard charge control attribute names
platform/x86: thinkpad_acpi: remove unused defines
platform/x86: ISST: drop a duplicated word in isst_if.h
tools/power/x86/intel-speed-select: Update version for v5.9
tools/power/x86/intel-speed-select: Add retries for mail box commands
tools/power/x86/intel-speed-select: Add option to delay mbox commands
tools/power/x86/intel-speed-select: Ignore -o option processing on error
tools/power/x86/intel-speed-select: Change path for caching topology info
platform/x86: acerhdf: Replace HTTP links with HTTPS ones
platform/x86: apple-gmux: Replace HTTP links with HTTPS ones
platform/x86: pcengines-apuv2: revert wiring up simswitch GPIO as LED
platform/x86: mlx-platform: Extend FAN platform data description
platform_data/mlxreg: Add presence register field for FAN devices
Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces
platform/mellanox: mlxreg-io: Add support for complex attributes
platform/x86: mlx-platform: Add more definitions for system attributes
platform_data/mlxreg: Add support for complex attributes
...
25 files changed, 846 insertions, 135 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io index b0d90cc696a8..fd9a8045bb0c 100644 --- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io +++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io @@ -206,3 +206,20 @@ Description: This file exposes the firmware version of burnable voltage regulator devices. The file is read only. + +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_pn +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_pn +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_pn +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_pn +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_version_min +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_version_min +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version_min +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_version_min +Date: July 2020 +KernelVersion: 5.9 +Contact: Vadim Pasternak <vadimpmellanox.com> +Description: These files show with which CPLD part numbers and minor + versions have been burned CPLD devices equipped on a + system. + + The files are read only. diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst index 822907dcc845..fb0d346bf31a 100644 --- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst +++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst @@ -50,6 +50,7 @@ detailed description): - WAN enable and disable - UWB enable and disable - LCD Shadow (PrivacyGuard) enable and disable + - Lap mode sensor A compatibility table by model and feature is maintained on the web site, http://ibm-acpi.sf.net/. I appreciate any success or failure @@ -1432,6 +1433,20 @@ The first command ensures the best viewing angle and the latter one turns on the feature, restricting the viewing angles. +DYTC Lapmode sensor +------------------ + +sysfs: dytc_lapmode + +Newer thinkpads and mobile workstations have the ability to determine if +the device is in deskmode or lapmode. This feature is used by user space +to decide if WWAN transmission can be increased to maximum power and is +also useful for understanding the different thermal modes available as +they differ between desk and lap mode. + +The property is read-only. If the platform doesn't have support the sysfs +class is not created. + EXPERIMENTAL: UWB ----------------- @@ -1470,6 +1485,23 @@ For more details about which buttons will appear depending on the mode, please review the laptop's user guide: http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf +Battery charge control +---------------------- + +sysfs attributes: +/sys/class/power_supply/BAT*/charge_control_{start,end}_threshold + +These two attributes are created for those batteries that are supported by the +driver. They enable the user to control the battery charge thresholds of the +given battery. Both values may be read and set. `charge_control_start_threshold` +accepts an integer between 0 and 99 (inclusive); this value represents a battery +percentage level, below which charging will begin. `charge_control_end_threshold` +accepts an integer between 1 and 100 (inclusive); this value represents a battery +percentage level, above which charging will stop. + +The exact semantics of the attributes may be found in +Documentation/ABI/testing/sysfs-class-power. + Multiple Commands, Module Parameters ------------------------------------ diff --git a/MAINTAINERS b/MAINTAINERS index 13e323b46f68..9e4e81f124b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8610,6 +8610,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/intel_atomisp2_pm.c +INTEL ATOMISP2 LED DRIVER +M: Hans de Goede <hdegoede@redhat.com> +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/intel_atomisp2_led.c + INTEL BROXTON PMC DRIVER M: Mika Westerberg <mika.westerberg@linux.intel.com> M: Zha Qipeng <qipeng.zha@intel.com> diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index ed48917af162..b013445147dd 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -1,34 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016-2018 Vadim Pasternak <vadimp@mellanox.com> + * Mellanox hotplug driver * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016-2020 Mellanox Technologies */ #include <linux/bitops.h> @@ -42,6 +16,7 @@ #include <linux/platform_data/mlxreg.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/string_helpers.h> #include <linux/regmap.h> #include <linux/workqueue.h> @@ -97,6 +72,23 @@ struct mlxreg_hotplug_priv_data { u8 not_asserted; }; +/* Environment variables array for udev. */ +static char *mlxreg_hotplug_udev_envp[] = { NULL, NULL }; + +static int +mlxreg_hotplug_udev_event_send(struct kobject *kobj, + struct mlxreg_core_data *data, bool action) +{ + char event_str[MLXREG_CORE_LABEL_MAX_SIZE + 2]; + char label[MLXREG_CORE_LABEL_MAX_SIZE] = { 0 }; + + mlxreg_hotplug_udev_envp[0] = event_str; + string_upper(label, data->label); + snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=%d", label, !!action); + + return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp); +} + static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { @@ -104,7 +96,7 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct i2c_client *client; /* Notify user by sending hwmon uevent. */ - kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); + mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, true); /* * Return if adapter number is negative. It could be in case hotplug @@ -144,7 +136,7 @@ mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { /* Notify user by sending hwmon uevent. */ - kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); + mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false); if (data->hpdev.client) { i2c_unregister_device(data->hpdev.client); @@ -199,17 +191,49 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) struct mlxreg_core_hotplug_platform_data *pdata; struct mlxreg_core_item *item; struct mlxreg_core_data *data; - int num_attrs = 0, id = 0, i, j; + unsigned long mask; + u32 regval; + int num_attrs = 0, id = 0, i, j, k, ret; pdata = dev_get_platdata(&priv->pdev->dev); item = pdata->items; /* Go over all kinds of items - psu, pwr, fan. */ for (i = 0; i < pdata->counter; i++, item++) { - num_attrs += item->count; + if (item->capability) { + /* + * Read group capability register to get actual number + * of interrupt capable components and set group mask + * accordingly. + */ + ret = regmap_read(priv->regmap, item->capability, + ®val); + if (ret) + return ret; + + item->mask = GENMASK((regval & item->mask) - 1, 0); + } + data = item->data; - /* Go over all units within the item. */ - for (j = 0; j < item->count; j++, data++, id++) { + + /* Go over all unmasked units within item. */ + mask = item->mask; + k = 0; + for_each_set_bit(j, &mask, item->count) { + if (data->capability) { + /* + * Read capability register and skip non + * relevant attributes. + */ + ret = regmap_read(priv->regmap, + data->capability, ®val); + if (ret) + return ret; + if (!(regval & data->bit)) { + data++; + continue; + } + } PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr; PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, @@ -227,9 +251,13 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) PRIV_DEV_ATTR(id).dev_attr.show = mlxreg_hotplug_attr_show; PRIV_DEV_ATTR(id).nr = i; - PRIV_DEV_ATTR(id).index = j; + PRIV_DEV_ATTR(id).index = k; sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr); + data++; + id++; + k++; } + num_attrs += k; } priv->group.attrs = devm_kcalloc(&priv->pdev->dev, @@ -507,20 +535,6 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) item = pdata->items; for (i = 0; i < pdata->counter; i++, item++) { - if (item->capability) { - /* - * Read group capability register to get actual number - * of interrupt capable components and set group mask - * accordingly. - */ - ret = regmap_read(priv->regmap, item->capability, - ®val); - if (ret) - goto out; - - item->mask = GENMASK((regval & item->mask) - 1, 0); - } - /* Clear group presense event. */ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF, 0); diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c index acfaf64ffde6..7646708d57e4 100644 --- a/drivers/platform/mellanox/mlxreg-io.c +++ b/drivers/platform/mellanox/mlxreg-io.c @@ -30,6 +30,7 @@ * @mlxreg_io_dev_attr: sysfs sensor device attribute array; * @group: sysfs attribute group; * @groups: list of sysfs attribute group for hwmon registration; + * @regsize: size of a register value; */ struct mlxreg_io_priv_data { struct platform_device *pdev; @@ -39,27 +40,30 @@ struct mlxreg_io_priv_data { struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM]; struct attribute_group group; const struct attribute_group *groups[2]; + int regsize; }; static int mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, - bool rw_flag, u32 *regval) + bool rw_flag, int regsize, u32 *regval) { - int ret; + int i, val, ret; ret = regmap_read(regmap, data->reg, regval); if (ret) goto access_error; /* - * There are three kinds of attributes: single bit, full register's - * bits and bit sequence. For the first kind field mask indicates which - * bits are not related and field bit is set zero. For the second kind - * field mask is set to zero and field bit is set with all bits one. - * No special handling for such kind of attributes - pass value as is. - * For the third kind, field mask indicates which bits are related and - * field bit is set to the first bit number (from 1 to 32) is the bit - * sequence. + * There are four kinds of attributes: single bit, full register's + * bits, bit sequence, bits in few registers For the first kind field + * mask indicates which bits are not related and field bit is set zero. + * For the second kind field mask is set to zero and field bit is set + * with all bits one. No special handling for such kind of attributes - + * pass value as is. For the third kind, the field mask indicates which + * bits are related and the field bit is set to the first bit number + * (from 1 to 32) is the bit sequence. For the fourth kind - the number + * of registers which should be read for getting an attribute are + * specified through 'data->regnum' field. */ if (!data->bit) { /* Single bit. */ @@ -83,6 +87,19 @@ mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, /* Clear relevant bits and set them to new value. */ *regval = (*regval & ~data->mask) | in_val; } + } else { + /* + * Some attributes could occupied few registers in case regmap + * bit size is 8 or 16. Compose such attributes from 'regnum' + * registers. Such attributes contain read-only data. + */ + for (i = 1; i < data->regnum; i++) { + ret = regmap_read(regmap, data->reg + i, &val); + if (ret) + goto access_error; + + *regval |= rol32(val, regsize * i); + } } access_error: @@ -99,7 +116,8 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr, u32 regval = 0; int ret; - ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val); + ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, + priv->regsize, ®val); if (ret) goto access_error; @@ -128,7 +146,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, return ret; ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false, - ®val); + priv->regsize, ®val); if (ret) goto access_error; @@ -207,6 +225,9 @@ static int mlxreg_io_probe(struct platform_device *pdev) } priv->pdev = pdev; + priv->regsize = regmap_get_val_bytes(priv->pdata->regmap); + if (priv->regsize < 0) + return priv->regsize; err = mlxreg_io_attr_init(priv); if (err) { diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 0581a54cf562..40219bba6801 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -140,7 +140,7 @@ config ACERHDF in the same node directory will tell you if it is "acerhdf". For more information about this driver see - <http://piie.net/files/acerhdf_README.txt> + <https://piie.net/files/acerhdf_README.txt> If you have an Acer Aspire One netbook, say Y or M here. @@ -748,6 +748,27 @@ 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 INTEL_ATOMISP2_LED + tristate "Intel AtomISP2 camera LED driver" + depends on GPIOLIB && LEDS_GPIO + help + Many Bay Trail and Cherry Trail devices come with a camera attached + to Intel's Image Signal Processor. Linux currently does not have a + driver for these, so they do not work as a camera. Some of these + camera's have a LED which is controlled through a GPIO. + + Some of these devices have a firmware issue where the LED gets turned + on at boot. This driver will turn the LED off at boot and also allows + controlling the LED (repurposing it) through the sysfs LED interface. + + Which GPIO is attached to the LED is usually not described in the + ACPI tables, so this driver contains per-system info about the GPIO + inside the driver, this means that this driver only works on systems + the driver knows about. + + To compile this driver as a module, choose M here: the module + will be called intel_atomisp2_led. + config INTEL_ATOMISP2_PM tristate "Intel AtomISP2 dummy / power-management driver" depends on PCI && IOSF_MBI && PM diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2b85852a1a87..5f823f7eff45 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o # Intel +obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o 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 \ diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 4df7609b4aa9..a7a0b2e0ceb9 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -5,7 +5,7 @@ * as soon as the upper/lower threshold is reached. * * (C) 2009 - Peter Kaestle peter (a) piie.net - * http://piie.net + * https://piie.net * 2009 Borislav Petkov bp (a) alien8.de * * Inspired by and many thanks to: diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 7e3083deb1c5..9aae45a45200 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -277,8 +277,8 @@ static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) * MBP5 2008/09 uses a `TI LP8543`_ backlight driver. All newer models * use a `TI LP8545`_. * - * .. _TI LP8543: http://www.ti.com/lit/ds/symlink/lp8543.pdf - * .. _TI LP8545: http://www.ti.com/lit/ds/symlink/lp8545.pdf + * .. _TI LP8543: https://www.ti.com/lit/ds/symlink/lp8543.pdf + * .. _TI LP8545: https://www.ti.com/lit/ds/symlink/lp8545.pdf */ static int gmux_get_brightness(struct backlight_device *bd) @@ -373,14 +373,14 @@ static const struct backlight_ops gmux_bl_ops = { * switch the panel and the external DP connector and allocates a framebuffer * for the selected GPU. * - * .. _US 8,687,007 B2: http://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf - * .. _NXP CBTL06141: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf - * .. _NXP CBTL06142: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf - * .. _TI HD3SS212: http://www.ti.com/lit/ds/symlink/hd3ss212.pdf + * .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf + * .. _NXP CBTL06141: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf + * .. _NXP CBTL06142: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf + * .. _TI HD3SS212: https://www.ti.com/lit/ds/symlink/hd3ss212.pdf * .. _Pericom PI3VDP12412: https://www.pericom.com/assets/Datasheets/PI3VDP12412.pdf - * .. _TI SN74LV4066A: http://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf + * .. _TI SN74LV4066A: https://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf * .. _NXP CBTL03062: http://pdf.datasheetarchive.com/indexerfiles/Datasheets-SW16/DSASW00308511.pdf - * .. _TI TS3DS10224: http://www.ti.com/lit/ds/symlink/ts3ds10224.pdf + * .. _TI TS3DS10224: https://www.ti.com/lit/ds/symlink/ts3ds10224.pdf */ static void gmux_read_switch_state(struct apple_gmux_data *gmux_data) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 8c4d00482ef0..b2e3d1e3b3e9 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -110,6 +110,11 @@ static struct quirk_entry quirk_asus_forceals = { .wmi_force_als_set = true, }; +static struct quirk_entry quirk_asus_vendor_backlight = { + .wmi_backlight_power = true, + .wmi_backlight_set_devstate = true, +}; + static int dmi_matched(const struct dmi_system_id *dmi) { pr_info("Identified laptop model '%s'\n", dmi->ident); @@ -411,6 +416,78 @@ static const struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_forceals, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA401IH", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401IH"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA401II", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401II"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA401IU", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401IU"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA401IV", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401IV"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA401IVC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401IVC"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA502II", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA502II"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA502IU", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA502IU"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. GA502IV", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA502IV"), + }, + .driver_data = &quirk_asus_vendor_backlight, + }, {}, }; diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index c25a4286d766..bbdb3e860892 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -255,6 +255,10 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { /* Keyboard backlight change notification */ { KE_IGNORE, 0x3f, { KEY_RESERVED } }, + /* Backlight brightness level */ + { KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, 0x58, { KEY_BRIGHTNESSUP } }, + /* Mic mute */ { KE_KEY, 0x150, { KEY_MICMUTE } }, @@ -330,6 +334,15 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = { { KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } }, }; +/* + * Keymap for WMI events of type 0x0012 + * They are events with extended data + */ +static const struct key_entry dell_wmi_keymap_type_0012[] = { + /* Fn-lock button pressed */ + { KE_IGNORE, 0xe035, { KEY_RESERVED } }, +}; + static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code) { struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev); @@ -414,10 +427,11 @@ static void dell_wmi_notify(struct wmi_device *wdev, switch (buffer_entry[1]) { case 0x0000: /* One key pressed or event occurred */ + case 0x0012: /* Event with extended data occurred */ if (len > 2) - dell_wmi_process_key(wdev, 0x0000, + dell_wmi_process_key(wdev, buffer_entry[1], buffer_entry[2]); - /* Other entries could contain additional information */ + /* Extended data is currently ignored */ break; case 0x0010: /* Sequence of keys pressed */ case 0x0011: /* Sequence of events occurred */ @@ -492,7 +506,7 @@ static void handle_dmi_entry(const struct dmi_header *dm, void *opaque) u16 keycode = (bios_entry->keycode < ARRAY_SIZE(bios_to_linux_keycode)) ? bios_to_linux_keycode[bios_entry->keycode] : - KEY_RESERVED; + (bios_entry->keycode == 0xffff ? KEY_UNKNOWN : KEY_RESERVED); /* * Log if we find an entry in the DMI table that we don't @@ -552,6 +566,7 @@ static int dell_wmi_input_setup(struct wmi_device *wdev) ARRAY_SIZE(dell_wmi_keymap_type_0000) + ARRAY_SIZE(dell_wmi_keymap_type_0010) + ARRAY_SIZE(dell_wmi_keymap_type_0011) + + ARRAY_SIZE(dell_wmi_keymap_type_0012) + 1, sizeof(struct key_entry), GFP_KERNEL); if (!keymap) { @@ -596,6 +611,13 @@ static int dell_wmi_input_setup(struct wmi_device *wdev) pos++; } + /* Append table with events of type 0x0012 */ + for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) { + keymap[pos] = dell_wmi_keymap_type_0012[i]; + keymap[pos].code |= (0x0012 << 16); + pos++; + } + /* * Now append also table with "legacy" events of type 0x0000. Some of * them are reported also on laptops which have scancodes in DMI. diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 9ee79b74311c..86261970bd8f 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -571,7 +571,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; if (acpi_match_device_ids(dev, ids) == 0) - if (acpi_create_platform_device(dev, NULL)) + if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) dev_info(&dev->dev, "intel-hid: created platform device\n"); diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 0487b606a274..e85d8e58320c 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -299,7 +299,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; if (acpi_match_device_ids(dev, ids) == 0) - if (acpi_create_platform_device(dev, NULL)) + if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) dev_info(&dev->dev, "intel-vbtn: created platform device\n"); diff --git a/drivers/platform/x86/intel_atomisp2_led.c b/drivers/platform/x86/intel_atomisp2_led.c new file mode 100644 index 000000000000..5935dfca166f --- /dev/null +++ b/drivers/platform/x86/intel_atomisp2_led.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for controlling LEDs for cameras connected to the Intel atomisp2 + * The main purpose of this driver is to turn off LEDs which are on at boot. + * + * Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com> + */ + +#include <linux/dmi.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> + +/* This must be leds-gpio as the leds-gpio driver binds to the name */ +#define DEV_NAME "leds-gpio" + +static const struct gpio_led atomisp2_leds[] = { + { + .name = "atomisp2::camera", + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, +}; + +static const struct gpio_led_platform_data atomisp2_leds_pdata = { + .num_leds = ARRAY_SIZE(atomisp2_leds), + .leds = atomisp2_leds, +}; + +static struct gpiod_lookup_table asus_t100ta_lookup = { + .dev_id = DEV_NAME, + .table = { + GPIO_LOOKUP_IDX("INT33FC:02", 8, NULL, 0, GPIO_ACTIVE_HIGH), + { } + } +}; + +static struct gpiod_lookup_table asus_t100chi_lookup = { + .dev_id = DEV_NAME, + .table = { + GPIO_LOOKUP_IDX("INT33FC:01", 24, NULL, 0, GPIO_ACTIVE_HIGH), + { } + } +}; + +static const struct dmi_system_id atomisp2_led_systems[] __initconst = { + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), + }, + .driver_data = &asus_t100ta_lookup, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"), + }, + .driver_data = &asus_t100ta_lookup, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"), + }, + .driver_data = &asus_t100chi_lookup, + }, + {} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(dmi, atomisp2_led_systems); + +static struct gpiod_lookup_table *gpio_lookup; +static struct platform_device *pdev; + +static int __init atomisp2_led_init(void) +{ + const struct dmi_system_id *system; + + system = dmi_first_match(atomisp2_led_systems); + if (!system) + return -ENODEV; + + gpio_lookup = system->driver_data; + gpiod_add_lookup_table(gpio_lookup); + + pdev = platform_device_register_resndata(NULL, + DEV_NAME, PLATFORM_DEVID_NONE, + NULL, 0, &atomisp2_leds_pdata, + sizeof(atomisp2_leds_pdata)); + if (IS_ERR(pdev)) + gpiod_remove_lookup_table(gpio_lookup); + + return PTR_ERR_OR_ZERO(pdev); +} + +static void __exit atomisp2_led_cleanup(void) +{ + platform_device_unregister(pdev); + gpiod_remove_lookup_table(gpio_lookup); +} + +module_init(atomisp2_led_init); +module_exit(atomisp2_led_cleanup); + +/* + * The ACPI INIT method from Asus WMI's code on the T100TA and T200TA turns the + * LED on (without the WMI interface allowing further control over the LED). + * Ensure we are loaded after asus-nb-wmi so that we turn the LED off again. + */ +MODULE_SOFTDEP("pre: asus_nb_wmi"); +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com"); +MODULE_DESCRIPTION("Intel atomisp2 camera LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel_cht_int33fe_common.c b/drivers/platform/x86/intel_cht_int33fe_common.c index 42dd11623f56..251ed9bac789 100644 --- a/drivers/platform/x86/intel_cht_int33fe_common.c +++ b/drivers/platform/x86/intel_cht_int33fe_common.c @@ -29,18 +29,16 @@ static int cht_int33fe_i2c_res_filter(struct acpi_resource *ares, void *data) static int cht_int33fe_count_i2c_clients(struct device *dev) { - struct acpi_device *adev; + struct acpi_device *adev = ACPI_COMPANION(dev); LIST_HEAD(resource_list); int count = 0; + int ret; - adev = ACPI_COMPANION(dev); - if (!adev) - return -EINVAL; - - acpi_dev_get_resources(adev, &resource_list, - cht_int33fe_i2c_res_filter, &count); - + ret = acpi_dev_get_resources(adev, &resource_list, + cht_int33fe_i2c_res_filter, &count); acpi_dev_free_resource_list(&resource_list); + if (ret < 0) + return ret; return count; } diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 7c8bdab078cf..338ea5222555 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -415,7 +415,7 @@ static const struct pmc_bit_map tgl_lpm0_map[] = { {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, {"OPIOPLL_OFF_STS", BIT(21)}, {"OCPLL_OFF_STS", BIT(22)}, - {"AudioPLL_OFF_STS", BIT(23)}, + {"MainPLL_OFF_STS", BIT(23)}, {"MIPIPLL_OFF_STS", BIT(24)}, {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, {"AC_Ring_Osc_OFF_STS", BIT(26)}, @@ -795,7 +795,7 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) msleep(10); val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); - for (index = 0; map[index].name && index < 8; index++) { + for (index = 0; index < 8 && map[index].name; index++) { seq_printf(s, "%-32s\tState: %s\n", map[index].name, map[index].bit_mask & val_low ? "Not power gated" : diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index c27548fd386a..90bc7969b199 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -26,6 +26,10 @@ #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 #define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 #define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03 +#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET 0x04 +#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET 0x06 +#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET 0x08 +#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f @@ -72,6 +76,10 @@ #define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1 #define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2 #define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3 +#define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde +#define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf +#define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0 +#define MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET 0xe1 #define MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET 0xe2 #define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 #define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 @@ -1304,6 +1312,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { .mode = 0444, }, { + .label = "cpld1_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld2_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld1_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld2_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { .label = "reset_long_pb", .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, .mask = GENMASK(7, 0) & ~BIT(0), @@ -1410,6 +1444,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { .mode = 0444, }, { + .label = "cpld1_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld2_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld1_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld2_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { .label = "reset_long_pb", .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, .mask = GENMASK(7, 0) & ~BIT(0), @@ -1528,6 +1588,58 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { .mode = 0444, }, { + .label = "cpld1_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld2_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld3_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld4_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET, + .bit = GENMASK(15, 0), + .mode = 0444, + .regnum = 2, + }, + { + .label = "cpld1_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld2_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld3_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld4_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { .label = "reset_long_pb", .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, .mask = GENMASK(7, 0) & ~BIT(0), @@ -1728,6 +1840,8 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(0), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + }, { .label = "tacho2", @@ -1735,6 +1849,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(1), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho3", @@ -1742,6 +1857,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(2), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho4", @@ -1749,6 +1865,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(3), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho5", @@ -1756,6 +1873,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(4), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho6", @@ -1763,6 +1881,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(5), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho7", @@ -1770,6 +1889,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(6), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho8", @@ -1777,6 +1897,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, .bit = BIT(7), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho9", @@ -1784,6 +1905,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, .bit = BIT(0), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho10", @@ -1791,6 +1913,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, .bit = BIT(1), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho11", @@ -1798,6 +1921,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, .bit = BIT(2), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "tacho12", @@ -1805,6 +1929,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { .mask = GENMASK(7, 0), .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, .bit = BIT(3), + .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, }, { .label = "conf", @@ -2006,6 +2131,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: @@ -2051,6 +2180,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: @@ -2085,6 +2218,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: @@ -2122,6 +2259,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c index 9b11ef1a401f..6aff6cf41414 100644 --- a/drivers/platform/x86/pcengines-apuv2.c +++ b/drivers/platform/x86/pcengines-apuv2.c @@ -78,7 +78,6 @@ static const struct gpio_led apu2_leds[] = { { .name = "apu:green:1" }, { .name = "apu:green:2" }, { .name = "apu:green:3" }, - { .name = "apu:simswap" }, }; static const struct gpio_led_platform_data apu2_leds_pdata = { @@ -95,8 +94,6 @@ static struct gpiod_lookup_table gpios_led_table = { NULL, 1, GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3, NULL, 2, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_SIMSWAP, - NULL, 3, GPIO_ACTIVE_LOW), } }; diff --git a/drivers/platform/x86/system76_acpi.c b/drivers/platform/x86/system76_acpi.c index 4f6e4c342382..c14fd22ba196 100644 --- a/drivers/platform/x86/system76_acpi.c +++ b/drivers/platform/x86/system76_acpi.c @@ -103,12 +103,12 @@ static enum led_brightness ap_led_get(struct led_classdev *led) } // Set the airplane mode LED brightness -static void ap_led_set(struct led_classdev *led, enum led_brightness value) +static int ap_led_set(struct led_classdev *led, enum led_brightness value) { struct system76_data *data; data = container_of(led, struct system76_data, ap_led); - system76_set(data, "SAPL", value == LED_OFF ? 0 : 1); + return system76_set(data, "SAPL", value == LED_OFF ? 0 : 1); } // Get the last set keyboard LED brightness @@ -121,13 +121,13 @@ static enum led_brightness kb_led_get(struct led_classdev *led) } // Set the keyboard LED brightness -static void kb_led_set(struct led_classdev *led, enum led_brightness value) +static int kb_led_set(struct led_classdev *led, enum led_brightness value) { struct system76_data *data; data = container_of(led, struct system76_data, kb_led); data->kb_brightness = value; - system76_set(data, "SKBL", (int)data->kb_brightness); + return system76_set(data, "SKBL", (int)data->kb_brightness); } // Get the last set keyboard LED color @@ -313,7 +313,7 @@ static int system76_add(struct acpi_device *acpi_dev) data->ap_led.name = "system76_acpi::airplane"; data->ap_led.flags = LED_CORE_SUSPENDRESUME; data->ap_led.brightness_get = ap_led_get; - data->ap_led.brightness_set = ap_led_set; + data->ap_led.brightness_set_blocking = ap_led_set; data->ap_led.max_brightness = 1; data->ap_led.default_trigger = "rfkill-none"; err = devm_led_classdev_register(&acpi_dev->dev, &data->ap_led); @@ -323,7 +323,7 @@ static int system76_add(struct acpi_device *acpi_dev) data->kb_led.name = "system76_acpi::kbd_backlight"; data->kb_led.flags = LED_BRIGHT_HW_CHANGED | LED_CORE_SUSPENDRESUME; data->kb_led.brightness_get = kb_led_get; - data->kb_led.brightness_set = kb_led_set; + data->kb_led.brightness_set_blocking = kb_led_set; if (acpi_has_method(acpi_device_handle(data->acpi_dev), "SKBC")) { data->kb_led.max_brightness = 255; data->kb_toggle_brightness = 72; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0f6fceda5fc0..4864a5c189d4 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -4030,8 +4030,8 @@ static bool hotkey_notify_6xxx(const u32 hkey, return true; case TP_HKEY_EV_THM_CSM_COMPLETED: pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n"); - /* recommended action: do nothing, we don't have - * Lenovo ATM information */ + /* Thermal event - pass on to event handler */ + tpacpi_driver_event(hkey); return true; case TP_HKEY_EV_THM_TRANSFM_CHANGED: pr_debug("EC reports: Thermal Transformation changed (GMTS)\n"); @@ -6963,10 +6963,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm) pr_warn("Cannot enable backlight brightness support, ACPI is already handling it. Refer to the acpi_backlight kernel parameter.\n"); return 1; } - } else if (tp_features.bright_acpimode && brightness_enable > 1) { - pr_notice("Standard ACPI backlight interface not available, thinkpad_acpi native brightness control enabled\n"); + } else if (!tp_features.bright_acpimode) { + pr_notice("ACPI backlight interface not available\n"); + return 1; } + pr_notice("ACPI native brightness control enabled\n"); + /* * Check for module parameter bogosity, note that we * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be @@ -7965,7 +7968,7 @@ static struct ibm_struct volume_driver_data = { * does so, its initial value is meaningless (0x07). * * For firmware bugs, refer to: - * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues + * https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues * * ---- * @@ -7990,7 +7993,7 @@ static struct ibm_struct volume_driver_data = { * mode. * * For firmware bugs, refer to: - * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues + * https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues * * ---- * @@ -9315,9 +9318,6 @@ static struct ibm_struct mute_led_driver_data = { #define GET_STOP "BCSG" #define SET_STOP "BCSS" -#define START_ATTR "charge_start_threshold" -#define STOP_ATTR "charge_stop_threshold" - enum { BAT_ANY = 0, BAT_PRIMARY = 1, @@ -9603,38 +9603,52 @@ static ssize_t tpacpi_battery_show(int what, return sprintf(buf, "%d\n", ret); } -static ssize_t charge_start_threshold_show(struct device *device, +static ssize_t charge_control_start_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { return tpacpi_battery_show(THRESHOLD_START, device, buf); } -static ssize_t charge_stop_threshold_show(struct device *device, +static ssize_t charge_control_end_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { return tpacpi_battery_show(THRESHOLD_STOP, device, buf); } -static ssize_t charge_start_threshold_store(struct device *dev, +static ssize_t charge_control_start_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { return tpacpi_battery_store(THRESHOLD_START, dev, buf, count); } -static ssize_t charge_stop_threshold_store(struct device *dev, +static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count); } -static DEVICE_ATTR_RW(charge_start_threshold); -static DEVICE_ATTR_RW(charge_stop_threshold); +static DEVICE_ATTR_RW(charge_control_start_threshold); +static DEVICE_ATTR_RW(charge_control_end_threshold); +static struct device_attribute dev_attr_charge_start_threshold = __ATTR( + charge_start_threshold, + 0644, + charge_control_start_threshold_show, + charge_control_start_threshold_store +); +static struct device_attribute dev_attr_charge_stop_threshold = __ATTR( + charge_stop_threshold, + 0644, + charge_control_end_threshold_show, + charge_control_end_threshold_store +); static struct attribute *tpacpi_battery_attrs[] = { + &dev_attr_charge_control_start_threshold.attr, + &dev_attr_charge_control_end_threshold.attr, &dev_attr_charge_start_threshold.attr, &dev_attr_charge_stop_threshold.attr, NULL, @@ -9803,6 +9817,105 @@ static struct ibm_struct lcdshadow_driver_data = { .write = lcdshadow_write, }; +/************************************************************************* + * DYTC subdriver, for the Lenovo lapmode feature + */ + +#define DYTC_CMD_GET 2 /* To get current IC function and mode */ +#define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */ + +static bool dytc_lapmode; + +static void dytc_lapmode_notify_change(void) +{ + sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode"); +} + +static int dytc_command(int command, int *output) +{ + acpi_handle dytc_handle; + + if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) { + /* Platform doesn't support DYTC */ + return -ENODEV; + } + if (!acpi_evalf(dytc_handle, output, NULL, "dd", command)) + return -EIO; + return 0; +} + +static int dytc_lapmode_get(bool *state) +{ + int output, err; + + err = dytc_command(DYTC_CMD_GET, &output); + if (err) + return err; + *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false; + return 0; +} + +static void dytc_lapmode_refresh(void) +{ + bool new_state; + int err; + + err = dytc_lapmode_get(&new_state); + if (err || (new_state == dytc_lapmode)) + return; + + dytc_lapmode = new_state; + dytc_lapmode_notify_change(); +} + +/* sysfs lapmode entry */ +static ssize_t dytc_lapmode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", dytc_lapmode); +} + +static DEVICE_ATTR_RO(dytc_lapmode); + +static struct attribute *dytc_attributes[] = { + &dev_attr_dytc_lapmode.attr, + NULL, +}; + +static const struct attribute_group dytc_attr_group = { + .attrs = dytc_attributes, +}; + +static int tpacpi_dytc_init(struct ibm_init_struct *iibm) +{ + int err; + + err = dytc_lapmode_get(&dytc_lapmode); + /* If support isn't available (ENODEV) then don't return an error + * but just don't create the sysfs group + */ + if (err == -ENODEV) + return 0; + /* For all other errors we can flag the failure */ + if (err) + return err; + + /* Platform supports this feature - create the group */ + err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group); + return err; +} + +static void dytc_exit(void) +{ + sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group); +} + +static struct ibm_struct dytc_driver_data = { + .name = "dytc", + .exit = dytc_exit, +}; + /**************************************************************************** **************************************************************************** * @@ -9850,6 +9963,10 @@ static void tpacpi_driver_event(const unsigned int hkey_event) mutex_unlock(&kbdlight_mutex); } + + if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED) + dytc_lapmode_refresh(); + } static void hotkey_driver_event(const unsigned int scancode) @@ -10102,7 +10219,7 @@ static int __must_check __init get_thinkpad_model_data( * X32 or newer, all Z series; Some models must have an * up-to-date BIOS or they will not be detected. * - * See http://thinkwiki.org/wiki/List_of_DMI_IDs + * See https://thinkwiki.org/wiki/List_of_DMI_IDs */ while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { if (sscanf(dev->name, @@ -10288,6 +10405,10 @@ static struct ibm_init_struct ibms_init[] __initdata = { .init = tpacpi_lcdshadow_init, .data = &lcdshadow_driver_data, }, + { + .init = tpacpi_dytc_init, + .data = &dytc_driver_data, + }, }; static int __init set_ibm_param(const char *val, const struct kernel_param *kp) @@ -10621,8 +10742,8 @@ MODULE_DEVICE_TABLE(acpi, ibm_htk_device_ids); /* * DMI matching for module autoloading * - * See http://thinkwiki.org/wiki/List_of_DMI_IDs - * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads + * See https://thinkwiki.org/wiki/List_of_DMI_IDs + * See https://thinkwiki.org/wiki/BIOS_Upgrade_Downloads * * Only models listed in thinkwiki will be supported, so add yours * if it is not there yet. diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h index b8da8aef2446..9cffa9a64ab3 100644 --- a/include/linux/platform_data/mlxreg.h +++ b/include/linux/platform_data/mlxreg.h @@ -75,11 +75,13 @@ struct mlxreg_hotplug_device { * @mask: attribute access mask; * @bit: attribute effective bit; * @capability: attribute capability register; + * @reg_prsnt: attribute presence register; * @mode: access mode; * @np - pointer to node platform associated with attribute; * @hpdev - hotplug device data; * @health_cntr: dynamic device health indication counter; * @attached: true if device has been attached after good health indication; + * @regnum: number of registers occupied by multi-register attribute; */ struct mlxreg_core_data { char label[MLXREG_CORE_LABEL_MAX_SIZE]; @@ -87,11 +89,13 @@ struct mlxreg_core_data { u32 mask; u32 bit; u32 capability; + u32 reg_prsnt; umode_t mode; struct device_node *np; struct mlxreg_hotplug_device hpdev; u8 health_cntr; bool attached; + u8 regnum; }; /** diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index c28955132234..86f150c2a6b6 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -2,6 +2,7 @@ #ifndef _LINUX_STRING_HELPERS_H_ #define _LINUX_STRING_HELPERS_H_ +#include <linux/ctype.h> #include <linux/types.h> struct file; @@ -75,6 +76,20 @@ static inline int string_escape_str_any_np(const char *src, char *dst, return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, only); } +static inline void string_upper(char *dst, const char *src) +{ + do { + *dst++ = toupper(*src); + } while (*src++); +} + +static inline void string_lower(char *dst, const char *src) +{ + do { + *dst++ = tolower(*src); + } while (*src++); +} + char *kstrdup_quotable(const char *src, gfp_t gfp); char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp); char *kstrdup_quotable_file(struct file *file, gfp_t gfp); diff --git a/include/uapi/linux/isst_if.h b/include/uapi/linux/isst_if.h index 0a52b7b093d3..ba078f8e9add 100644 --- a/include/uapi/linux/isst_if.h +++ b/include/uapi/linux/isst_if.h @@ -69,7 +69,7 @@ struct isst_if_cpu_maps { * @logical_cpu: Logical CPU number to get target PCI device. * @reg: PUNIT register offset * @value: For write operation value to write and for - * for read placeholder read value + * read placeholder read value * * Structure to specify read/write data to PUNIT registers. */ diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c index 25b5cbfb7615..10360d4ea273 100644 --- a/lib/test-string_helpers.c +++ b/lib/test-string_helpers.c @@ -238,6 +238,28 @@ static const struct test_string_2 escape1[] __initconst = {{ /* terminator */ }}; +static const struct test_string strings_upper[] __initconst = { + { + .in = "abcdefgh1234567890test", + .out = "ABCDEFGH1234567890TEST", + }, + { + .in = "abCdeFgH1234567890TesT", + .out = "ABCDEFGH1234567890TEST", + }, +}; + +static const struct test_string strings_lower[] __initconst = { + { + .in = "ABCDEFGH1234567890TEST", + .out = "abcdefgh1234567890test", + }, + { + .in = "abCdeFgH1234567890TesT", + .out = "abcdefgh1234567890test", + }, +}; + static __init const char *test_string_find_match(const struct test_string_2 *s2, unsigned int flags) { @@ -390,6 +412,48 @@ static __init void test_string_get_size(void) test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB"); } +static void __init test_string_upper_lower(void) +{ + char *dst; + int i; + + for (i = 0; i < ARRAY_SIZE(strings_upper); i++) { + const char *s = strings_upper[i].in; + int len = strlen(strings_upper[i].in) + 1; + + dst = kmalloc(len, GFP_KERNEL); + if (!dst) + return; + + string_upper(dst, s); + if (memcmp(dst, strings_upper[i].out, len)) { + pr_warn("Test 'string_upper' failed : expected %s, got %s!\n", + strings_upper[i].out, dst); + kfree(dst); + return; + } + kfree(dst); + } + + for (i = 0; i < ARRAY_SIZE(strings_lower); i++) { + const char *s = strings_lower[i].in; + int len = strlen(strings_lower[i].in) + 1; + + dst = kmalloc(len, GFP_KERNEL); + if (!dst) + return; + + string_lower(dst, s); + if (memcmp(dst, strings_lower[i].out, len)) { + pr_warn("Test 'string_lower failed : : expected %s, got %s!\n", + strings_lower[i].out, dst); + kfree(dst); + return; + } + kfree(dst); + } +} + static int __init test_string_helpers_init(void) { unsigned int i; @@ -411,6 +475,9 @@ static int __init test_string_helpers_init(void) /* Test string_get_size() */ test_string_get_size(); + /* Test string upper(), string_lower() */ + test_string_upper_lower(); + return -EINVAL; } module_init(test_string_helpers_init); diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c index 9f68f51ca652..9f4b190f1d74 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.4"; +static const char *version_str = "v1.5"; static const int supported_api_ver = 1; static struct isst_if_platform_info isst_platform_info; static char *progname; @@ -44,6 +44,9 @@ static int force_online_offline; static int auto_mode; static int fact_enable_fail; +static int mbox_delay; +static int mbox_retries = 3; + /* clos related */ static int current_clos = -1; static int clos_epp = -1; @@ -198,7 +201,7 @@ int out_format_is_json(void) 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"; + const char *pathname = "/var/run/isst_cpu_topology.dat"; struct cpu_topology cpu_top; FILE *fp; int ret; @@ -230,7 +233,7 @@ err_ret: static void store_cpu_topology(void) { - const char *pathname = "/tmp/isst_cpu_topology.dat"; + const char *pathname = "/var/run/isst_cpu_topology.dat"; FILE *fp; int i; @@ -247,6 +250,8 @@ static void store_cpu_topology(void) return; } + fprintf(stderr, "Caching topology information\n"); + for (i = 0; i < topo_max_cpus; ++i) { struct cpu_topology cpu_top; @@ -734,7 +739,7 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, unsigned int req_data, unsigned int *resp) { const char *pathname = "/dev/isst_interface"; - int fd; + int fd, retry; struct isst_if_mbox_cmds mbox_cmds = { 0 }; debug_printf( @@ -786,29 +791,42 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, mbox_cmds.mbox_cmd[0].parameter = parameter; mbox_cmds.mbox_cmd[0].req_data = req_data; + if (mbox_delay) + usleep(mbox_delay * 1000); + fd = open(pathname, O_RDWR); if (fd < 0) err(-1, "%s open failed", pathname); - if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) { - 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); + retry = mbox_retries; + + do { + if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) { + 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); + --retry; + } else { + *resp = mbox_cmds.mbox_cmd[0].resp_data; + debug_printf( + "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n", + cpu, command, sub_command, parameter, req_data, *resp); + break; } - 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; - debug_printf( - "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n", - cpu, command, sub_command, parameter, req_data, *resp); - } + } while (retry); close(fd); + if (!retry) { + debug_printf("Failed mbox command even after retries\n"); + return -1; + + } return 0; } @@ -1245,7 +1263,11 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, fprintf(stderr, "Option is set to online/offline\n"); ctdp_level.core_cpumask_size = alloc_cpu_set(&ctdp_level.core_cpumask); - isst_get_coremask_info(cpu, tdp_level, &ctdp_level); + ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level); + if (ret) { + isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0); + return; + } if (ctdp_level.cpu_count) { int i, max_cpus = get_topo_max_cpus(); for (i = 0; i < max_cpus; ++i) { @@ -2593,6 +2615,8 @@ static void usage(void) printf("\t[-i|--info] : Print platform information\n"); printf("\t[-o|--out] : Output file\n"); printf("\t\t\tDefault : stderr\n"); + printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n"); + printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n"); printf("\t[-v|--version] : Print version\n"); printf("\nResult format\n"); @@ -2624,6 +2648,7 @@ static void print_version(void) static void cmdline(int argc, char **argv) { const char *pathname = "/dev/isst_interface"; + char *ptr; FILE *fp; int opt; int option_index = 0; @@ -2635,7 +2660,9 @@ static void cmdline(int argc, char **argv) { "format", required_argument, 0, 'f' }, { "help", no_argument, 0, 'h' }, { "info", no_argument, 0, 'i' }, + { "pause", required_argument, 0, 'p' }, { "out", required_argument, 0, 'o' }, + { "retry", required_argument, 0, 'r' }, { "version", no_argument, 0, 'v' }, { 0, 0, 0, 0 } }; @@ -2688,6 +2715,20 @@ static void cmdline(int argc, char **argv) fclose(outf); outf = fopen_or_exit(optarg, "w"); break; + case 'p': + ret = strtol(optarg, &ptr, 10); + if (!ret) + fprintf(stderr, "Invalid pause interval, ignore\n"); + else + mbox_delay = ret; + break; + case 'r': + ret = strtol(optarg, &ptr, 10); + if (!ret) + fprintf(stderr, "Invalid retry count, ignore\n"); + else + mbox_retries = ret; + break; case 'v': print_version(); break; |