platform-drivers-x86 for v6.16-4

Fixes and New HW Support
 
 - alienware-wmi-wmax:
 
   - Add AWCC support for Alienware Area-51m and m15 R5.
 
   - Fix `dmi_system_id` array termination
 
 - arm64: huawei-gaokun-ec: fix OF node leak
 
 - dell-ddv: Fix taking psy->extensions_sem twice
 
 - dell-lis3lv02d: Add Precision 3551 accelerometer support
 
 - firmware_attributes_class: Fix initialization order
 
 - ideapad-laptop: Retain FnLock and kbd backlight across boots
 
 - lenovo-wmi-hotkey: Avoid triggering error -5 due to missing mute LED
 
 - mellanox: mlxbf-pmc: Validate event names and bool input
 
 - power: supply: Add get/set property direct to allow avoiding taking
                  psy->extensions_sem twice from power supply extensions
 
 The following is an automated shortlog grouped by driver:
 
 alieneware-wmi-wmax:
  -  Add AWCC support to more laptops
 
 alienware-wmi-wmax:
  -  Fix `dmi_system_id` array
 
 arm64: huawei-gaokun-ec:
  -  fix OF node leak
 
 dell-ddv:
  -  Fix taking the psy->extensions_sem lock twice
 
 dell-lis3lv02d:
  -  Add Precision 3551
 
 Fix initialization order for firmware_attributes_class:
  - Fix initialization order for firmware_attributes_class
 
 ideapad-laptop:
  -  Fix FnLock not remembered among boots
  -  Fix kbd backlight not remembered among boots
 
 lenovo-wmi-hotkey:
  -  Avoid triggering error -5 due to missing mute LED
 
 MAINTAINERS:
  -  Update entries for IFS and SBL drivers
 
 mlxbf-pmc:
  -  Remove newline char from event name input
  -  Use kstrtobool() to check 0/1 input
  -  Validate event/enable input
 
 power: supply: core:
  -  Add power_supply_get/set_property_direct()
 
 power: supply: test-power:
  -  Test access to extended power supply
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCaH40yAAKCRBZrE9hU+XO
 MbSEAP4tNEOahKx4ER4Awg7BvJKY6lfifKvu1yt5K3/aWde9VQD8CRv99ryV3kAy
 EX3Ut1otWsB7UY7+tfV8WeYmXutf/Qs=
 =wHun
 -----END PGP SIGNATURE-----

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

Pull x86 platform drivers fixes from Ilpo Järvinen:

 - power supply code:
    - Add get/set property direct to allow avoiding taking
      psy->extensions_sem twice from power supply extensions

 - alienware-wmi-wmax:
    - Add AWCC support for Alienware Area-51m and m15 R5
    - Fix `dmi_system_id` array termination

 - arm64: huawei-gaokun-ec: fix OF node leak

 - dell-ddv: Fix taking psy->extensions_sem twice

 - dell-lis3lv02d: Add Precision 3551 accelerometer support

 - firmware_attributes_class: Fix initialization order

 - ideapad-laptop: Retain FnLock and kbd backlight across boots

 - lenovo-wmi-hotkey: Avoid triggering error -5 due to missing mute LED

 - mellanox: mlxbf-pmc: Validate event names and bool input

* tag 'platform-drivers-x86-v6.16-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
  MAINTAINERS: Update entries for IFS and SBL drivers
  platform/x86: dell-lis3lv02d: Add Precision 3551
  platform/x86: alieneware-wmi-wmax: Add AWCC support to more laptops
  platform/x86: Fix initialization order for firmware_attributes_class
  platform: arm64: huawei-gaokun-ec: fix OF node leak
  lenovo-wmi-hotkey: Avoid triggering error -5 due to missing mute LED
  platform/x86: ideapad-laptop: Fix kbd backlight not remembered among boots
  platform/x86: ideapad-laptop: Fix FnLock not remembered among boots
  platform/mellanox: mlxbf-pmc: Use kstrtobool() to check 0/1 input
  platform/mellanox: mlxbf-pmc: Validate event/enable input
  platform/mellanox: mlxbf-pmc: Remove newline char from event name input
  platform/x86: dell-ddv: Fix taking the psy->extensions_sem lock twice
  power: supply: test-power: Test access to extended power supply
  power: supply: core: Add power_supply_get/set_property_direct()
  platform/x86: alienware-wmi-wmax: Fix `dmi_system_id` array
This commit is contained in:
Linus Torvalds 2025-07-21 08:32:36 -07:00
commit 964ebc07c5
12 changed files with 153 additions and 39 deletions

View File

@ -12188,9 +12188,8 @@ F: drivers/dma/idxd/*
F: include/uapi/linux/idxd.h
INTEL IN FIELD SCAN (IFS) DEVICE
M: Jithu Joseph <jithu.joseph@intel.com>
M: Tony Luck <tony.luck@intel.com>
R: Ashok Raj <ashok.raj.linux@gmail.com>
R: Tony Luck <tony.luck@intel.com>
S: Maintained
F: drivers/platform/x86/intel/ifs
F: include/trace/events/intel_ifs.h
@ -12530,8 +12529,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
F: drivers/net/wireless/intel/iwlwifi/
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
M: Jithu Joseph <jithu.joseph@intel.com>
S: Maintained
S: Orphan
W: https://slimbootloader.github.io/security/firmware-update.html
F: drivers/platform/x86/intel/wmi/sbl-fw-update.c

View File

@ -662,6 +662,7 @@ static void gaokun_aux_release(struct device *dev)
{
struct auxiliary_device *adev = to_auxiliary_dev(dev);
of_node_put(dev->of_node);
kfree(adev);
}
@ -693,6 +694,7 @@ static int gaokun_aux_init(struct device *parent, const char *name,
ret = auxiliary_device_init(adev);
if (ret) {
of_node_put(adev->dev.of_node);
kfree(adev);
return ret;
}

View File

@ -15,6 +15,7 @@
#include <linux/hwmon.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
#include <uapi/linux/psci.h>
#define MLXBF_PMC_WRITE_REG_32 0x82000009
@ -1222,7 +1223,7 @@ static int mlxbf_pmc_get_event_num(const char *blk, const char *evt)
return -ENODEV;
}
/* Get the event number given the name */
/* Get the event name given the number */
static char *mlxbf_pmc_get_event_name(const char *blk, u32 evt)
{
const struct mlxbf_pmc_events *events;
@ -1784,6 +1785,7 @@ static ssize_t mlxbf_pmc_event_store(struct device *dev,
attr, struct mlxbf_pmc_attribute, dev_attr);
unsigned int blk_num, cnt_num;
bool is_l3 = false;
char *evt_name;
int evt_num;
int err;
@ -1791,14 +1793,23 @@ static ssize_t mlxbf_pmc_event_store(struct device *dev,
cnt_num = attr_event->index;
if (isalpha(buf[0])) {
/* Remove the trailing newline character if present */
evt_name = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!evt_name)
return -ENOMEM;
evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num],
buf);
evt_name);
kfree(evt_name);
if (evt_num < 0)
return -EINVAL;
} else {
err = kstrtouint(buf, 0, &evt_num);
if (err < 0)
return err;
if (!mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num))
return -EINVAL;
}
if (strstr(pmc->block_name[blk_num], "l3cache"))
@ -1879,13 +1890,14 @@ static ssize_t mlxbf_pmc_enable_store(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_enable = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
unsigned int en, blk_num;
unsigned int blk_num;
u32 word;
int err;
bool en;
blk_num = attr_enable->nr;
err = kstrtouint(buf, 0, &en);
err = kstrtobool(buf, &en);
if (err < 0)
return err;
@ -1905,14 +1917,11 @@ static ssize_t mlxbf_pmc_enable_store(struct device *dev,
MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
MLXBF_PMC_WRITE_REG_32, word);
} else {
if (en && en != 1)
return -EINVAL;
err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en);
if (err)
return err;
if (en == 1) {
if (en) {
err = mlxbf_pmc_config_l3_counters(blk_num, true, false);
if (err)
return err;

View File

@ -58,6 +58,8 @@ obj-$(CONFIG_X86_PLATFORM_DRIVERS_HP) += hp/
# Hewlett Packard Enterprise
obj-$(CONFIG_UV_SYSFS) += uv_sysfs.o
obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o
# IBM Thinkpad and Lenovo
obj-$(CONFIG_IBM_RTL) += ibm_rtl.o
obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o
@ -128,7 +130,6 @@ obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o
obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
# Platform drivers
obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o
obj-$(CONFIG_SERIAL_MULTI_INSTANTIATE) += serial-multi-instantiate.o
obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o
obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o

View File

@ -89,6 +89,14 @@ static struct awcc_quirks generic_quirks = {
static struct awcc_quirks empty_quirks;
static const struct dmi_system_id awcc_dmi_table[] __initconst = {
{
.ident = "Alienware Area-51m",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m"),
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware Area-51m R2",
.matches = {
@ -97,6 +105,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware m15 R5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R5"),
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware m15 R7",
.matches = {
@ -233,6 +249,7 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
},
.driver_data = &g_series_quirks,
},
{}
};
enum AWCC_GET_FAN_SENSORS_OPERATIONS {

View File

@ -49,6 +49,7 @@ static const struct dmi_system_id lis3lv02d_devices[] __initconst = {
DELL_LIS3LV02D_DMI_ENTRY("Latitude E6330", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude E6430", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Precision 3540", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Precision 3551", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Precision M6800", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Vostro V131", 0x1d),
DELL_LIS3LV02D_DMI_ENTRY("Vostro 5568", 0x29),

View File

@ -689,9 +689,13 @@ static int dell_wmi_ddv_battery_translate(struct dell_wmi_ddv_data *data,
dev_dbg(&data->wdev->dev, "Translation cache miss\n");
/* Perform a translation between a ACPI battery and a battery index */
ret = power_supply_get_property(battery, POWER_SUPPLY_PROP_SERIAL_NUMBER, &val);
/*
* Perform a translation between a ACPI battery and a battery index.
* We have to use power_supply_get_property_direct() here because this
* function will also get called from the callbacks of the power supply
* extension.
*/
ret = power_supply_get_property_direct(battery, POWER_SUPPLY_PROP_SERIAL_NUMBER, &val);
if (ret < 0)
return ret;

View File

@ -1669,7 +1669,7 @@ static int ideapad_kbd_bl_init(struct ideapad_private *priv)
priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get;
priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED;
priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED | LED_RETAIN_AT_SHUTDOWN;
err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led);
if (err)
@ -1728,7 +1728,7 @@ static int ideapad_fn_lock_led_init(struct ideapad_private *priv)
priv->fn_lock.led.name = "platform::" LED_FUNCTION_FNLOCK;
priv->fn_lock.led.brightness_get = ideapad_fn_lock_led_cdev_get;
priv->fn_lock.led.brightness_set_blocking = ideapad_fn_lock_led_cdev_set;
priv->fn_lock.led.flags = LED_BRIGHT_HW_CHANGED;
priv->fn_lock.led.flags = LED_BRIGHT_HW_CHANGED | LED_RETAIN_AT_SHUTDOWN;
err = led_classdev_register(&priv->platform_device->dev, &priv->fn_lock.led);
if (err)

View File

@ -122,26 +122,35 @@ static int lenovo_super_hotkey_wmi_led_init(enum mute_led_type led_type, struct
return -EIO;
union acpi_object *obj __free(kfree) = output.pointer;
if (obj && obj->type == ACPI_TYPE_INTEGER)
led_version = obj->integer.value;
else
if (!obj || obj->type != ACPI_TYPE_INTEGER)
return -EIO;
wpriv->cdev[led_type].max_brightness = LED_ON;
wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME;
led_version = obj->integer.value;
/*
* Output parameters define: 0 means mute LED is not supported, Non-zero means
* mute LED can be supported.
*/
if (led_version == 0)
return 0;
switch (led_type) {
case MIC_MUTE:
if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER)
return -EIO;
if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER) {
pr_warn("The MIC_MUTE LED of this device isn't supported.\n");
return 0;
}
wpriv->cdev[led_type].name = "platform::micmute";
wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_micmute_led_set;
wpriv->cdev[led_type].default_trigger = "audio-micmute";
break;
case AUDIO_MUTE:
if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER)
return -EIO;
if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER) {
pr_warn("The AUDIO_MUTE LED of this device isn't supported.\n");
return 0;
}
wpriv->cdev[led_type].name = "platform::mute";
wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_audiomute_led_set;
@ -152,6 +161,9 @@ static int lenovo_super_hotkey_wmi_led_init(enum mute_led_type led_type, struct
return -EINVAL;
}
wpriv->cdev[led_type].max_brightness = LED_ON;
wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME;
err = devm_led_classdev_register(dev, &wpriv->cdev[led_type]);
if (err < 0) {
dev_err(dev, "Could not register mute LED %d : %d\n", led_type, err);

View File

@ -1235,9 +1235,8 @@ bool power_supply_has_property(struct power_supply *psy,
return false;
}
int power_supply_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
static int __power_supply_get_property(struct power_supply *psy, enum power_supply_property psp,
union power_supply_propval *val, bool use_extensions)
{
struct power_supply_ext_registration *reg;
@ -1247,10 +1246,14 @@ int power_supply_get_property(struct power_supply *psy,
return -ENODEV;
}
scoped_guard(rwsem_read, &psy->extensions_sem) {
power_supply_for_each_extension(reg, psy) {
if (power_supply_ext_has_property(reg->ext, psp))
if (use_extensions) {
scoped_guard(rwsem_read, &psy->extensions_sem) {
power_supply_for_each_extension(reg, psy) {
if (!power_supply_ext_has_property(reg->ext, psp))
continue;
return reg->ext->get_property(psy, reg->ext, reg->data, psp, val);
}
}
}
@ -1261,20 +1264,49 @@ int power_supply_get_property(struct power_supply *psy,
else
return -EINVAL;
}
int power_supply_get_property(struct power_supply *psy, enum power_supply_property psp,
union power_supply_propval *val)
{
return __power_supply_get_property(psy, psp, val, true);
}
EXPORT_SYMBOL_GPL(power_supply_get_property);
int power_supply_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
/**
* power_supply_get_property_direct - Read a power supply property without checking for extensions
* @psy: The power supply
* @psp: The power supply property to read
* @val: The resulting value of the power supply property
*
* Read a power supply property without taking into account any power supply extensions registered
* on the given power supply. This is mostly useful for power supply extensions that want to access
* their own power supply as using power_supply_get_property() directly will result in a potential
* deadlock.
*
* Return: 0 on success or negative error code on failure.
*/
int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp,
union power_supply_propval *val)
{
return __power_supply_get_property(psy, psp, val, false);
}
EXPORT_SYMBOL_GPL(power_supply_get_property_direct);
static int __power_supply_set_property(struct power_supply *psy, enum power_supply_property psp,
const union power_supply_propval *val, bool use_extensions)
{
struct power_supply_ext_registration *reg;
if (atomic_read(&psy->use_cnt) <= 0)
return -ENODEV;
scoped_guard(rwsem_read, &psy->extensions_sem) {
power_supply_for_each_extension(reg, psy) {
if (power_supply_ext_has_property(reg->ext, psp)) {
if (use_extensions) {
scoped_guard(rwsem_read, &psy->extensions_sem) {
power_supply_for_each_extension(reg, psy) {
if (!power_supply_ext_has_property(reg->ext, psp))
continue;
if (reg->ext->set_property)
return reg->ext->set_property(psy, reg->ext, reg->data,
psp, val);
@ -1289,8 +1321,34 @@ int power_supply_set_property(struct power_supply *psy,
return psy->desc->set_property(psy, psp, val);
}
int power_supply_set_property(struct power_supply *psy, enum power_supply_property psp,
const union power_supply_propval *val)
{
return __power_supply_set_property(psy, psp, val, true);
}
EXPORT_SYMBOL_GPL(power_supply_set_property);
/**
* power_supply_set_property_direct - Write a power supply property without checking for extensions
* @psy: The power supply
* @psp: The power supply property to write
* @val: The value to write to the power supply property
*
* Write a power supply property without taking into account any power supply extensions registered
* on the given power supply. This is mostly useful for power supply extensions that want to access
* their own power supply as using power_supply_set_property() directly will result in a potential
* deadlock.
*
* Return: 0 on success or negative error code on failure.
*/
int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp,
const union power_supply_propval *val)
{
return __power_supply_set_property(psy, psp, val, false);
}
EXPORT_SYMBOL_GPL(power_supply_set_property_direct);
int power_supply_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{

View File

@ -259,6 +259,7 @@ static const struct power_supply_config test_power_configs[] = {
static int test_power_battery_extmanufacture_year = 1234;
static int test_power_battery_exttemp_max = 1000;
static const enum power_supply_property test_power_battery_extprops[] = {
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_MANUFACTURE_YEAR,
POWER_SUPPLY_PROP_TEMP_MAX,
};
@ -270,6 +271,9 @@ static int test_power_battery_extget_property(struct power_supply *psy,
union power_supply_propval *val)
{
switch (psp) {
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
return power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
val);
case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
val->intval = test_power_battery_extmanufacture_year;
break;

View File

@ -888,15 +888,23 @@ static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
extern int power_supply_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val);
int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp,
union power_supply_propval *val);
#if IS_ENABLED(CONFIG_POWER_SUPPLY)
extern int power_supply_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val);
int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp,
const union power_supply_propval *val);
#else
static inline int power_supply_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{ return 0; }
static inline int power_supply_set_property_direct(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{ return 0; }
#endif
extern void power_supply_external_power_changed(struct power_supply *psy);