Merge branches 'acpi-pci', 'acpi-battery', 'acpi-ec' and 'acpi-apei'

Merge an ACPI PCI root driver update, ACPI battery driver updates, an
ACPI EC driver update and APEI updates for 6.16-rc1:

 - Turn the acpi_pci_root_remap_iospace() fwnode_handle parameter into a
   const pointer (Pei Xiao).

 - Round battery capacity percengate in the ACPI battery driver to the
   closest integer to avoid user confusion (shitao).

 - Make the ACPI battery driver report the current as a negative number
   to the power supply framework when the battery is discharging as
   documented (Peter Marheine).

 - Add TUXEDO InfinityBook Pro AMD Gen9 to the acpi_ec_no_wakeup[] list
   to prevent spurious wakeups from suspend-to-idle (Werner Sembach).

 - Convert the APEI EINJ driver to a faux device one (Sudeep Holla, Jon
   Hunter).

 - Remove redundant calls to einj_get_available_error_type() from the
   APEI EINJ driver (Zaid Alali).

* acpi-pci:
  ACPI: PCI: Constify fwnode_handle in acpi_pci_root_remap_iospace()

* acpi-battery:
  ACPI: battery: negate current when discharging
  ACPI: battery: Round capacity percengate to closest integer

* acpi-ec:
  ACPI: EC: Add device to acpi_ec_no_wakeup[] qurik list

* acpi-apei:
  ACPI: APEI: EINJ: Remove redundant calls to einj_get_available_error_type()
  ACPI: APEI: EINJ: Fix probe error message
  ACPI: APEI: EINJ: Transition to the faux device interface
This commit is contained in:
Rafael J. Wysocki 2025-05-26 19:31:50 +02:00
4 changed files with 49 additions and 44 deletions

View File

@ -21,7 +21,7 @@
#include <linux/nmi.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/device/faux.h>
#include <linux/unaligned.h>
#include "apei-internal.h"
@ -83,6 +83,8 @@ static struct debugfs_blob_wrapper vendor_blob;
static struct debugfs_blob_wrapper vendor_errors;
static char vendor_dev[64];
static u32 available_error_type;
/*
* Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
* EINJ table through an unpublished extension. Use with caution as
@ -648,14 +650,9 @@ static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
static int available_error_type_show(struct seq_file *m, void *v)
{
int rc;
u32 error_type = 0;
rc = einj_get_available_error_type(&error_type);
if (rc)
return rc;
for (int pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++)
if (error_type & einj_error_type_string[pos].mask)
if (available_error_type & einj_error_type_string[pos].mask)
seq_printf(m, "0x%08x\t%s\n", einj_error_type_string[pos].mask,
einj_error_type_string[pos].str);
@ -678,8 +675,7 @@ bool einj_is_cxl_error_type(u64 type)
int einj_validate_error_type(u64 type)
{
u32 tval, vendor, available_error_type = 0;
int rc;
u32 tval, vendor;
/* Only low 32 bits for error type are valid */
if (type & GENMASK_ULL(63, 32))
@ -695,13 +691,9 @@ int einj_validate_error_type(u64 type)
/* Only one error type can be specified */
if (tval & (tval - 1))
return -EINVAL;
if (!vendor) {
rc = einj_get_available_error_type(&available_error_type);
if (rc)
return rc;
if (!vendor)
if (!(type & available_error_type))
return -EINVAL;
}
return 0;
}
@ -749,17 +741,12 @@ static int einj_check_table(struct acpi_table_einj *einj_tab)
return 0;
}
static int __init einj_probe(struct platform_device *pdev)
static int __init einj_probe(struct faux_device *fdev)
{
int rc;
acpi_status status;
struct apei_exec_context ctx;
if (acpi_disabled) {
pr_debug("ACPI disabled.\n");
return -ENODEV;
}
status = acpi_get_table(ACPI_SIG_EINJ, 0,
(struct acpi_table_header **)&einj_tab);
if (status == AE_NOT_FOUND) {
@ -777,6 +764,10 @@ static int __init einj_probe(struct platform_device *pdev)
goto err_put_table;
}
rc = einj_get_available_error_type(&available_error_type);
if (rc)
return rc;
rc = -ENOMEM;
einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir());
@ -851,7 +842,7 @@ static int __init einj_probe(struct platform_device *pdev)
return rc;
}
static void __exit einj_remove(struct platform_device *pdev)
static void __exit einj_remove(struct faux_device *fdev)
{
struct apei_exec_context ctx;
@ -872,34 +863,30 @@ static void __exit einj_remove(struct platform_device *pdev)
acpi_put_table((struct acpi_table_header *)einj_tab);
}
static struct platform_device *einj_dev;
static struct faux_device *einj_dev;
/*
* einj_remove() lives in .exit.text. For drivers registered via
* platform_driver_probe() this is ok because they cannot get unbound at
* runtime. So mark the driver struct with __refdata to prevent modpost
* triggering a section mismatch warning.
*/
static struct platform_driver einj_driver __refdata = {
static struct faux_device_ops einj_device_ops __refdata = {
.probe = einj_probe,
.remove = __exit_p(einj_remove),
.driver = {
.name = "acpi-einj",
},
};
static int __init einj_init(void)
{
struct platform_device_info einj_dev_info = {
.name = "acpi-einj",
.id = -1,
};
int rc;
if (acpi_disabled) {
pr_debug("ACPI disabled.\n");
return -ENODEV;
}
einj_dev = platform_device_register_full(&einj_dev_info);
if (IS_ERR(einj_dev))
return PTR_ERR(einj_dev);
einj_dev = faux_device_create("acpi-einj", NULL, &einj_device_ops);
if (!einj_dev)
return -ENODEV;
rc = platform_driver_probe(&einj_driver, einj_probe);
einj_initialized = rc == 0;
einj_initialized = true;
return 0;
}
@ -907,9 +894,8 @@ static int __init einj_init(void)
static void __exit einj_exit(void)
{
if (einj_initialized)
platform_driver_unregister(&einj_driver);
faux_device_destroy(einj_dev);
platform_device_unregister(einj_dev);
}
module_init(einj_init);

View File

@ -243,10 +243,23 @@ static int acpi_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_POWER_NOW:
if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) {
ret = -ENODEV;
else
val->intval = battery->rate_now * 1000;
break;
}
val->intval = battery->rate_now * 1000;
/*
* When discharging, the current should be reported as a
* negative number as per the power supply class interface
* definition.
*/
if (psp == POWER_SUPPLY_PROP_CURRENT_NOW &&
(battery->state & ACPI_BATTERY_STATE_DISCHARGING) &&
acpi_battery_handle_discharging(battery)
== POWER_SUPPLY_STATUS_DISCHARGING)
val->intval = -val->intval;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
@ -279,8 +292,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->capacity_now * 100/
full_capacity;
val->intval = DIV_ROUND_CLOSEST_ULL(battery->capacity_now * 100ULL,
full_capacity);
break;
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
if (battery->state & ACPI_BATTERY_STATE_CRITICAL)

View File

@ -2329,6 +2329,12 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"),
}
},
{
// TUXEDO InfinityBook Pro AMD Gen9
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
},
},
{ },
};

View File

@ -858,7 +858,7 @@ static void acpi_pci_root_validate_resources(struct device *dev,
}
}
static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
static void acpi_pci_root_remap_iospace(const struct fwnode_handle *fwnode,
struct resource_entry *entry)
{
#ifdef PCI_IOBASE