mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-28 06:23:42 -04:00
Merge tag 'acpi-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more ACPI support updates from Rafael Wysocki:
"These update documentation to reflect recent changes in the upstream
ACPICA project, fix issues in the core ACPI device enumeration code
(one of which has been introduced recently), improve the primary
"physical" device lookup for ACPI device objects in that code, and
update ACPI device drivers:
- Update MAINTAINERS, CREDITS and ACPI subsystem documentation to
reflect recent changes in the upstream ACPICA project (Rafael
Wysocki)
- Prevent the core ACPI enumeration code from combining device
resources that overlap completely in order to avoid resource
conflicts during platform device registration because there are
drivers that expect such resources to be present (Rafael Wysocki)
- Defer device power initialization during ACPI-based device
enumeration to the point when the given device is known to be
present and functional and all of its dependencies have been met
(Peixin Xie)
- Fix bus ID cleanup on device_add() failures during ACPI device
object registration (Hongyan Xu)
- Introduce a new helper function for looking up the primary
"physical" device for a given ACPI device object and update the
core ACPI device enumeration code to use that function (Rafael
Wysocki)
- Protect all battery properties with a separated mutex in the ACPI
battery driver to prevent race conditions from occurring and avoid
evaluating the _BST ACPI control method multiple times in parallel
for the same battery device (Rong Zhang)
- Add DMI quirk for the Razer Blade Pro 17 early 2020 lid switch to
the ACPI button driver (Robin Everaars)
- Convert fixed clock rates in the ACPI driver for AMD SoCs (APD) to
use HZ_PER_MHZ and add a clock frequency for the HJMC01 I2C
controller to it (Hongnan Li and Xiangyang Yu)
- Fix a stack buffer overflow in query_capability() in the ACPI
platform firmware runtime update driver (Anirudh Prasad)"
* tag 'acpi-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI: button: Add DMI quirk for Razer Blade Pro 17 early 2020 lid switch
ACPI: scan: Do not combine resources that overlap completely
ACPI: Update upstream ACPICA repository URL in documentation
ACPI: Update MAINTAINERS entry for ACPICA
ACPI: Add Bob Moore to CREDITS
ACPI: pfr_update: fix stack buffer overflow in query_capability()
ACPI: scan: Defer device power initialization
ACPI: APD: Add clock frequency for HJMC01 I2C controller
ACPI: APD: Convert fixed clock rates to use HZ_PER_MHZ
ACPI: scan: Use acpi_bus_get_primary_device()
ACPI: platform: Use acpi_bus_get_primary_device()
ACPI: bus: Introduce acpi_bus_get_primary_device()
ACPI: scan: fix bus ID cleanup on device_add() failures
ACPI: battery: Protect all properties with a separated mutex
This commit is contained in:
4
CREDITS
4
CREDITS
@@ -2919,6 +2919,10 @@ N: Thomas Molina
|
||||
E: tmolina@cablespeed.com
|
||||
D: bug fixes, documentation, minor hackery
|
||||
|
||||
N: Bob Moore
|
||||
E: robert.moore@intel.com
|
||||
D: ACPI Component Architecture (ACPICA)
|
||||
|
||||
N: Paul Moore
|
||||
E: paul@paul-moore.com
|
||||
W: https://www.paul-moore.com
|
||||
|
||||
@@ -117,7 +117,7 @@ ACPICA Release
|
||||
==============
|
||||
|
||||
The ACPICA project maintains its code base at the following repository URL:
|
||||
https://github.com/acpica/acpica.git. As a rule, a release is made every
|
||||
https://github.com/open-acpica/acpica.git. As a rule, a release is made every
|
||||
month.
|
||||
|
||||
As the coding style adopted by the ACPICA project is not acceptable by
|
||||
@@ -173,7 +173,7 @@ illustrated in the following figure::
|
||||
utility located in source/tools/acpisrc folder and a number of
|
||||
scripts located in generate/linux folder.
|
||||
B. acpica / master - "master" branch of the git repository at
|
||||
<https://github.com/acpica/acpica.git>.
|
||||
<https://github.com/open-acpica/acpica.git>.
|
||||
C. linux-pm / linux-next - "linux-next" branch of the git repository at
|
||||
<https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git>.
|
||||
D. linux / master - "master" branch of the git repository at
|
||||
@@ -244,7 +244,7 @@ before they become available from the ACPICA release process.
|
||||
Then the gen-patch.sh command can help to cherry-pick an ACPICA commit
|
||||
from the ACPICA local repository::
|
||||
|
||||
$ git clone https://github.com/acpica/acpica
|
||||
$ git clone https://github.com/open-acpica/acpica
|
||||
$ cd acpica
|
||||
$ generate/linux/gen-patch.sh -u [commit ID]
|
||||
|
||||
@@ -259,7 +259,7 @@ before they become available from the ACPICA release process.
|
||||
You can generate the ACPICA release series yourself and rebase your code on
|
||||
top of the generated ACPICA release patches::
|
||||
|
||||
$ git clone https://github.com/acpica/acpica
|
||||
$ git clone https://github.com/open-acpica/acpica
|
||||
$ cd acpica
|
||||
$ generate/linux/make-patches.sh -u [commit ID]
|
||||
|
||||
@@ -273,7 +273,7 @@ before they become available from the ACPICA release process.
|
||||
If you have local copies of both Linux and upstream ACPICA, you can generate
|
||||
a diff file indicating the state of the current divergences::
|
||||
|
||||
# git clone https://github.com/acpica/acpica
|
||||
# git clone https://github.com/open-acpica/acpica
|
||||
# git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
# cd acpica
|
||||
# generate/linux/divergence.sh -s ../linux
|
||||
|
||||
@@ -313,15 +313,15 @@ F: drivers/firmware/efi/cper*
|
||||
|
||||
ACPI COMPONENT ARCHITECTURE (ACPICA)
|
||||
M: "Rafael J. Wysocki" <rafael@kernel.org>
|
||||
M: Saket Dumbre <saket.dumbre@intel.com>
|
||||
M: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
|
||||
M: Pawel Chmielewski <pawel.chmielewski@intel.com>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
L: acpica-devel@lists.linux.dev
|
||||
S: Supported
|
||||
W: https://acpica.org/
|
||||
W: https://github.com/acpica/acpica/
|
||||
W: https://github.com/open-acpica/acpica/
|
||||
Q: https://patchwork.kernel.org/project/linux-acpi/list/
|
||||
B: https://bugzilla.kernel.org
|
||||
B: https://bugs.acpica.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
|
||||
F: drivers/acpi/acpica/
|
||||
F: include/acpi/
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_data/clk-fch.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -110,17 +111,17 @@ static int fch_misc_setup(struct apd_private_data *pdata)
|
||||
|
||||
static const struct apd_device_desc cz_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 133000000,
|
||||
.fixed_clk_rate = 133 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc wt_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 150000000,
|
||||
.fixed_clk_rate = 150 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc wt_i3c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 125000000,
|
||||
.fixed_clk_rate = 125 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static struct property_entry uart_properties[] = {
|
||||
@@ -132,7 +133,7 @@ static struct property_entry uart_properties[] = {
|
||||
|
||||
static const struct apd_device_desc cz_uart_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 48000000,
|
||||
.fixed_clk_rate = 48 * HZ_PER_MHZ,
|
||||
.properties = uart_properties,
|
||||
};
|
||||
|
||||
@@ -144,52 +145,57 @@ static const struct apd_device_desc fch_misc_desc = {
|
||||
#ifdef CONFIG_ARM64
|
||||
static const struct apd_device_desc xgene_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 100000000,
|
||||
.fixed_clk_rate = 100 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc vulcan_spi_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 133000000,
|
||||
.fixed_clk_rate = 133 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc hip07_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 200000000,
|
||||
.fixed_clk_rate = 200 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc hip08_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 250000000,
|
||||
.fixed_clk_rate = 250 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc hip08_lite_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 125000000,
|
||||
.fixed_clk_rate = 125 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc thunderx2_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 125000000,
|
||||
.fixed_clk_rate = 125 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc nxp_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 350000000,
|
||||
.fixed_clk_rate = 350 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc hip08_spi_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 250000000,
|
||||
.fixed_clk_rate = 250 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc leca_spi_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 400000000,
|
||||
.fixed_clk_rate = 400 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc leca_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 250000000,
|
||||
.fixed_clk_rate = 250 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc hjmc_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 200 * HZ_PER_MHZ,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_ARM64 */
|
||||
@@ -262,6 +268,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
|
||||
{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },
|
||||
{ "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },
|
||||
{ "HISI0173", APD_ADDR(hip08_spi_desc) },
|
||||
{ "HJMC3001", APD_ADDR(hjmc_i2c_desc) },
|
||||
{ "LECA0002", APD_ADDR(leca_spi_desc) },
|
||||
{ "LECA0003", APD_ADDR(leca_i2c_desc) },
|
||||
{ "NXP0001", APD_ADDR(nxp_i2c_desc) },
|
||||
|
||||
@@ -85,7 +85,13 @@ static unsigned int acpi_platform_adjust_resources(struct acpi_device *adev,
|
||||
for (i = 0; i < count; ) {
|
||||
struct resource *res = &resources[i];
|
||||
|
||||
if (resource_type(new_res) != resource_type(res) ||
|
||||
/*
|
||||
* Look for overlaps of resources of the same type that would
|
||||
* cause resource insertion to fail down the road.
|
||||
*/
|
||||
if (__resource_contains_unbound(res, new_res) ||
|
||||
__resource_contains_unbound(new_res, res) ||
|
||||
resource_type(new_res) != resource_type(res) ||
|
||||
!resource_union(new_res, res, new_res)) {
|
||||
i++;
|
||||
continue;
|
||||
@@ -102,18 +108,15 @@ static unsigned int acpi_platform_adjust_resources(struct acpi_device *adev,
|
||||
return count;
|
||||
}
|
||||
|
||||
static void acpi_platform_fill_resource(struct acpi_device *adev,
|
||||
const struct resource *src, struct resource *dest)
|
||||
static void acpi_platform_fill_resource(struct device *parent,
|
||||
const struct resource *src,
|
||||
struct resource *dest)
|
||||
{
|
||||
struct device *parent;
|
||||
|
||||
*dest = *src;
|
||||
|
||||
/*
|
||||
* If the device has parent we need to take its resources into
|
||||
* account as well because this device might consume part of those.
|
||||
*/
|
||||
parent = acpi_get_first_physical_node(acpi_dev_parent(adev));
|
||||
if (parent && dev_is_pci(parent))
|
||||
dest->parent = pci_find_resource(to_pci_dev(parent), dest);
|
||||
}
|
||||
@@ -141,7 +144,8 @@ static unsigned int acpi_platform_resource_count(struct acpi_resource *ares, voi
|
||||
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct property_entry *properties)
|
||||
{
|
||||
struct acpi_device *parent = acpi_dev_parent(adev);
|
||||
struct acpi_device *p = acpi_dev_parent(adev);
|
||||
struct device *parent __free(put_device) = acpi_bus_get_primary_device(p);
|
||||
struct platform_device *pdev = NULL;
|
||||
struct platform_device_info pdevinfo;
|
||||
const struct acpi_device_id *match;
|
||||
@@ -187,7 +191,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
rentry->res,
|
||||
resources,
|
||||
count);
|
||||
acpi_platform_fill_resource(adev, rentry->res,
|
||||
acpi_platform_fill_resource(parent, rentry->res,
|
||||
&resources[count++]);
|
||||
}
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
@@ -200,7 +204,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
* attached to it, that physical device should be the parent of the
|
||||
* platform device we are about to create.
|
||||
*/
|
||||
pdevinfo.parent = parent ? acpi_get_first_physical_node(parent) : NULL;
|
||||
pdevinfo.parent = parent;
|
||||
pdevinfo.name = dev_name(&adev->dev);
|
||||
pdevinfo.id = PLATFORM_DEVID_NONE;
|
||||
pdevinfo.res = resources;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -105,6 +106,9 @@ struct acpi_battery {
|
||||
struct delayed_work acpi_notif_dwork;
|
||||
struct notifier_block pm_nb;
|
||||
struct list_head list;
|
||||
unsigned long flags;
|
||||
|
||||
struct mutex property_lock; /* Protects properties below. */
|
||||
unsigned long update_time;
|
||||
int revision;
|
||||
int rate_now;
|
||||
@@ -131,7 +135,6 @@ struct acpi_battery {
|
||||
char oem_info[MAX_STRING_LENGTH];
|
||||
int state;
|
||||
int power_unit;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
#define to_acpi_battery(x) power_supply_get_drvdata(x)
|
||||
@@ -189,20 +192,6 @@ static bool acpi_battery_is_degraded(struct acpi_battery *battery)
|
||||
battery->full_charge_capacity < battery->design_capacity;
|
||||
}
|
||||
|
||||
static int acpi_battery_handle_discharging(struct acpi_battery *battery)
|
||||
{
|
||||
/*
|
||||
* Some devices wrongly report discharging if the battery's charge level
|
||||
* was above the device's start charging threshold atm the AC adapter
|
||||
* was plugged in and the device thus did not start a new charge cycle.
|
||||
*/
|
||||
if ((battery_ac_is_broken || power_supply_is_system_supplied()) &&
|
||||
battery->rate_now == 0)
|
||||
return POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
|
||||
return POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
}
|
||||
|
||||
static int acpi_battery_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
@@ -210,15 +199,41 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||
int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
|
||||
struct acpi_battery *battery = to_acpi_battery(psy);
|
||||
|
||||
if (acpi_battery_present(battery)) {
|
||||
/* run battery update only if it is present */
|
||||
acpi_battery_get_state(battery);
|
||||
} else if (psp != POWER_SUPPLY_PROP_PRESENT)
|
||||
return -ENODEV;
|
||||
/* run battery update only if it is present */
|
||||
if (!acpi_battery_present(battery)) {
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = 0;
|
||||
return 0;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&battery->property_lock);
|
||||
|
||||
acpi_battery_get_state(battery);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
/*
|
||||
* Some devices wrongly report discharging if the battery's charge level
|
||||
* was above the device's start charging threshold atm the AC adapter
|
||||
* was plugged in and the device thus did not start a new charge cycle.
|
||||
*/
|
||||
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
|
||||
val->intval = acpi_battery_handle_discharging(battery);
|
||||
if (battery->rate_now != 0) {
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
} else if (battery_ac_is_broken) {
|
||||
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
} else {
|
||||
mutex_unlock(&battery->property_lock);
|
||||
|
||||
val->intval = power_supply_is_system_supplied()
|
||||
? POWER_SUPPLY_STATUS_NOT_CHARGING
|
||||
: POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
return 0;
|
||||
}
|
||||
else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
|
||||
/* Check the rate and capacity to validate the status. */
|
||||
if (!acpi_battery_is_full(battery) ||
|
||||
@@ -321,6 +336,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&battery->property_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -556,6 +573,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
|
||||
int use_bix;
|
||||
int result = -ENODEV;
|
||||
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
if (!acpi_battery_present(battery))
|
||||
return 0;
|
||||
|
||||
@@ -595,6 +614,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
|
||||
acpi_status status = 0;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
if (!acpi_battery_present(battery))
|
||||
return 0;
|
||||
|
||||
@@ -648,6 +669,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
if (!acpi_battery_present(battery) ||
|
||||
!test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
|
||||
return -ENODEV;
|
||||
@@ -665,6 +688,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
|
||||
|
||||
static int acpi_battery_init_alarm(struct acpi_battery *battery)
|
||||
{
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
/* See if alarms are supported, and if so, set default */
|
||||
if (!acpi_has_method(battery->device->handle, "_BTP")) {
|
||||
clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
|
||||
@@ -682,6 +707,8 @@ static ssize_t acpi_battery_alarm_show(struct device *dev,
|
||||
{
|
||||
struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
|
||||
|
||||
guard(mutex)(&battery->property_lock);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", battery->alarm * 1000);
|
||||
}
|
||||
|
||||
@@ -697,6 +724,8 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
guard(mutex)(&battery->property_lock);
|
||||
|
||||
battery->alarm = x / 1000;
|
||||
if (acpi_battery_present(battery))
|
||||
acpi_battery_set_alarm(battery);
|
||||
@@ -881,12 +910,17 @@ static int sysfs_add_battery(struct acpi_battery *battery)
|
||||
.no_wakeup_source = true,
|
||||
};
|
||||
bool full_cap_broken = false;
|
||||
int power_unit;
|
||||
|
||||
if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
|
||||
!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
|
||||
full_cap_broken = true;
|
||||
scoped_guard(mutex, &battery->property_lock) {
|
||||
power_unit = battery->power_unit;
|
||||
|
||||
if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
|
||||
if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
|
||||
!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
|
||||
full_cap_broken = true;
|
||||
}
|
||||
|
||||
if (power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
|
||||
if (full_cap_broken) {
|
||||
battery->bat_desc.properties =
|
||||
charge_battery_full_cap_broken_props;
|
||||
@@ -940,6 +974,9 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
|
||||
static void find_battery(const struct dmi_header *dm, void *private)
|
||||
{
|
||||
struct acpi_battery *battery = (struct acpi_battery *)private;
|
||||
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
/* Note: the hardcoded offsets below have been extracted from
|
||||
* the source code of dmidecode.
|
||||
*/
|
||||
@@ -971,6 +1008,8 @@ static void find_battery(const struct dmi_header *dm, void *private)
|
||||
*/
|
||||
static void acpi_battery_quirks(struct acpi_battery *battery)
|
||||
{
|
||||
lockdep_assert_held(&battery->property_lock);
|
||||
|
||||
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
|
||||
return;
|
||||
|
||||
@@ -1023,30 +1062,38 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
|
||||
static int acpi_battery_update(struct acpi_battery *battery, bool resume)
|
||||
{
|
||||
int result = acpi_battery_get_status(battery);
|
||||
bool wakeup;
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (!acpi_battery_present(battery)) {
|
||||
sysfs_remove_battery(battery);
|
||||
battery->update_time = 0;
|
||||
scoped_guard(mutex, &battery->property_lock)
|
||||
battery->update_time = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resume)
|
||||
return 0;
|
||||
|
||||
if (!battery->update_time) {
|
||||
result = acpi_battery_get_info(battery);
|
||||
scoped_guard(mutex, &battery->property_lock) {
|
||||
if (!battery->update_time) {
|
||||
result = acpi_battery_get_info(battery);
|
||||
if (result)
|
||||
return result;
|
||||
acpi_battery_init_alarm(battery);
|
||||
}
|
||||
|
||||
result = acpi_battery_get_state(battery);
|
||||
if (result)
|
||||
return result;
|
||||
acpi_battery_init_alarm(battery);
|
||||
}
|
||||
acpi_battery_quirks(battery);
|
||||
|
||||
result = acpi_battery_get_state(battery);
|
||||
if (result)
|
||||
return result;
|
||||
acpi_battery_quirks(battery);
|
||||
wakeup = ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
|
||||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
|
||||
(battery->capacity_now <= battery->alarm)));
|
||||
}
|
||||
|
||||
if (!battery->bat) {
|
||||
result = sysfs_add_battery(battery);
|
||||
@@ -1058,9 +1105,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
|
||||
* Wakeup the system if battery is critical low
|
||||
* or lower than the alarm level
|
||||
*/
|
||||
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
|
||||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
|
||||
(battery->capacity_now <= battery->alarm)))
|
||||
if (wakeup)
|
||||
acpi_pm_wakeup_event(battery->phys_dev);
|
||||
|
||||
return result;
|
||||
@@ -1073,12 +1118,14 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
|
||||
if (!battery->bat)
|
||||
return;
|
||||
|
||||
power_unit = battery->power_unit;
|
||||
scoped_guard(mutex, &battery->property_lock) {
|
||||
power_unit = battery->power_unit;
|
||||
|
||||
acpi_battery_get_info(battery);
|
||||
acpi_battery_get_info(battery);
|
||||
|
||||
if (power_unit == battery->power_unit)
|
||||
return;
|
||||
if (power_unit == battery->power_unit)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The battery has changed its reporting units. */
|
||||
sysfs_remove_battery(battery);
|
||||
@@ -1170,17 +1217,21 @@ static int battery_notify(struct notifier_block *nb,
|
||||
} else {
|
||||
int result;
|
||||
|
||||
result = acpi_battery_get_info(battery);
|
||||
if (result)
|
||||
return result;
|
||||
scoped_guard(mutex, &battery->property_lock) {
|
||||
result = acpi_battery_get_info(battery);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = sysfs_add_battery(battery);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
acpi_battery_init_alarm(battery);
|
||||
acpi_battery_get_state(battery);
|
||||
scoped_guard(mutex, &battery->property_lock) {
|
||||
acpi_battery_init_alarm(battery);
|
||||
acpi_battery_get_state(battery);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1345,6 +1396,10 @@ static int acpi_battery_probe(struct platform_device *pdev)
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = devm_mutex_init(&pdev->dev, &battery->property_lock);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (acpi_has_method(battery->device->handle, "_BIX"))
|
||||
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
||||
|
||||
|
||||
@@ -774,30 +774,52 @@ static int __init acpi_setup_sb_notify_handler(void)
|
||||
Device Matching
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static struct device *primary_physical_device(struct acpi_device *adev)
|
||||
{
|
||||
struct acpi_device_physical_node *pn;
|
||||
|
||||
pn = list_first_entry_or_null(&adev->physical_node_list,
|
||||
struct acpi_device_physical_node, node);
|
||||
if (pn)
|
||||
return pn->dev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_get_first_physical_node - Get first physical node of an ACPI device
|
||||
* acpi_bus_get_primary_device - Get first physical device for a given ACPI one
|
||||
* @adev: ACPI device to get the first physical device for.
|
||||
*
|
||||
* Find the first physical device for which @adev is the ACPI companion and
|
||||
* reference count it if present.
|
||||
*
|
||||
* Return: Pointer to the first physical counterpart of @adev or NULL if there
|
||||
* are none. Callers are responsible for invoking put_device() on the returned
|
||||
* device.
|
||||
*/
|
||||
struct device *acpi_bus_get_primary_device(struct acpi_device *adev)
|
||||
{
|
||||
if (!adev)
|
||||
return NULL;
|
||||
|
||||
guard(mutex)(&adev->physical_node_lock);
|
||||
|
||||
return get_device(primary_physical_device(adev));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_bus_get_primary_device);
|
||||
|
||||
/**
|
||||
* acpi_get_first_physical_node - Find first physical node of an ACPI device
|
||||
* @adev: ACPI device in question
|
||||
*
|
||||
* Return: First physical node of ACPI device @adev
|
||||
*/
|
||||
struct device *acpi_get_first_physical_node(struct acpi_device *adev)
|
||||
{
|
||||
struct mutex *physical_node_lock = &adev->physical_node_lock;
|
||||
struct device *phys_dev;
|
||||
guard(mutex)(&adev->physical_node_lock);
|
||||
|
||||
mutex_lock(physical_node_lock);
|
||||
if (list_empty(&adev->physical_node_list)) {
|
||||
phys_dev = NULL;
|
||||
} else {
|
||||
const struct acpi_device_physical_node *node;
|
||||
|
||||
node = list_first_entry(&adev->physical_node_list,
|
||||
struct acpi_device_physical_node, node);
|
||||
|
||||
phys_dev = node->dev;
|
||||
}
|
||||
mutex_unlock(physical_node_lock);
|
||||
return phys_dev;
|
||||
return primary_physical_device(adev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_get_first_physical_node);
|
||||
|
||||
|
||||
@@ -133,6 +133,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Razer Blade Pro 17 early 2020, notification of the LID device
|
||||
* only happens on close, not on open and _LID keeps returning closed.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Blade Pro 17 (Early 2020) - RZ09-0329"),
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Samsung galaxybook2 ,initial _LID device notification returns
|
||||
|
||||
@@ -120,7 +120,7 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr,
|
||||
struct pfru_device *pfru_dev)
|
||||
{
|
||||
acpi_handle handle = ACPI_HANDLE(pfru_dev->parent_dev);
|
||||
union acpi_object *out_obj;
|
||||
union acpi_object *out_obj, *elem;
|
||||
int ret = -EINVAL;
|
||||
|
||||
out_obj = acpi_evaluate_dsm_typed(handle, &pfru_guid,
|
||||
@@ -150,7 +150,9 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr,
|
||||
goto free_acpi_buffer;
|
||||
}
|
||||
|
||||
cap_hdr->status = out_obj->package.elements[CAP_STATUS_IDX].integer.value;
|
||||
elem = out_obj->package.elements;
|
||||
|
||||
cap_hdr->status = elem[CAP_STATUS_IDX].integer.value;
|
||||
if (cap_hdr->status != DSM_SUCCEED) {
|
||||
ret = -EBUSY;
|
||||
dev_dbg(pfru_dev->parent_dev, "Query cap Error Status:%d\n",
|
||||
@@ -158,29 +160,30 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr,
|
||||
goto free_acpi_buffer;
|
||||
}
|
||||
|
||||
cap_hdr->update_cap = out_obj->package.elements[CAP_UPDATE_IDX].integer.value;
|
||||
if (elem[CAP_CODE_TYPE_IDX].buffer.length > sizeof(cap_hdr->code_type) ||
|
||||
elem[CAP_DRV_TYPE_IDX].buffer.length > sizeof(cap_hdr->drv_type) ||
|
||||
elem[CAP_PLAT_ID_IDX].buffer.length > sizeof(cap_hdr->platform_id) ||
|
||||
elem[CAP_OEM_ID_IDX].buffer.length > sizeof(cap_hdr->oem_id))
|
||||
goto free_acpi_buffer;
|
||||
|
||||
cap_hdr->update_cap = elem[CAP_UPDATE_IDX].integer.value;
|
||||
memcpy(&cap_hdr->code_type,
|
||||
out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.pointer,
|
||||
out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.length);
|
||||
cap_hdr->fw_version =
|
||||
out_obj->package.elements[CAP_FW_VER_IDX].integer.value;
|
||||
cap_hdr->code_rt_version =
|
||||
out_obj->package.elements[CAP_CODE_RT_VER_IDX].integer.value;
|
||||
elem[CAP_CODE_TYPE_IDX].buffer.pointer,
|
||||
elem[CAP_CODE_TYPE_IDX].buffer.length);
|
||||
cap_hdr->fw_version = elem[CAP_FW_VER_IDX].integer.value;
|
||||
cap_hdr->code_rt_version = elem[CAP_CODE_RT_VER_IDX].integer.value;
|
||||
memcpy(&cap_hdr->drv_type,
|
||||
out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.pointer,
|
||||
out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.length);
|
||||
cap_hdr->drv_rt_version =
|
||||
out_obj->package.elements[CAP_DRV_RT_VER_IDX].integer.value;
|
||||
cap_hdr->drv_svn =
|
||||
out_obj->package.elements[CAP_DRV_SVN_IDX].integer.value;
|
||||
elem[CAP_DRV_TYPE_IDX].buffer.pointer,
|
||||
elem[CAP_DRV_TYPE_IDX].buffer.length);
|
||||
cap_hdr->drv_rt_version = elem[CAP_DRV_RT_VER_IDX].integer.value;
|
||||
cap_hdr->drv_svn = elem[CAP_DRV_SVN_IDX].integer.value;
|
||||
memcpy(&cap_hdr->platform_id,
|
||||
out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.pointer,
|
||||
out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.length);
|
||||
elem[CAP_PLAT_ID_IDX].buffer.pointer,
|
||||
elem[CAP_PLAT_ID_IDX].buffer.length);
|
||||
memcpy(&cap_hdr->oem_id,
|
||||
out_obj->package.elements[CAP_OEM_ID_IDX].buffer.pointer,
|
||||
out_obj->package.elements[CAP_OEM_ID_IDX].buffer.length);
|
||||
cap_hdr->oem_info_len =
|
||||
out_obj->package.elements[CAP_OEM_INFO_IDX].buffer.length;
|
||||
elem[CAP_OEM_ID_IDX].buffer.pointer,
|
||||
elem[CAP_OEM_ID_IDX].buffer.length);
|
||||
cap_hdr->oem_info_len = elem[CAP_OEM_INFO_IDX].buffer.length;
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
@@ -954,6 +954,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
|
||||
INIT_LIST_HEAD(&resource->list_node);
|
||||
INIT_LIST_HEAD(&resource->dependents);
|
||||
device->power.state = ACPI_STATE_UNKNOWN;
|
||||
device->flags.initialized = true;
|
||||
|
||||
/* Evaluate the object to get the system level and resource order. */
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
|
||||
|
||||
@@ -520,12 +520,10 @@ static void acpi_device_release(struct device *dev)
|
||||
kfree(acpi_dev);
|
||||
}
|
||||
|
||||
static void acpi_device_del(struct acpi_device *device)
|
||||
static void acpi_device_cleanup(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_device_bus_id *acpi_device_bus_id;
|
||||
|
||||
mutex_lock(&acpi_device_lock);
|
||||
|
||||
list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
|
||||
if (!strcmp(acpi_device_bus_id->bus_id,
|
||||
acpi_device_hid(device))) {
|
||||
@@ -540,6 +538,13 @@ static void acpi_device_del(struct acpi_device *device)
|
||||
}
|
||||
|
||||
list_del(&device->wakeup_list);
|
||||
}
|
||||
|
||||
static void acpi_device_del(struct acpi_device *device)
|
||||
{
|
||||
mutex_lock(&acpi_device_lock);
|
||||
|
||||
acpi_device_cleanup(device);
|
||||
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
|
||||
@@ -799,7 +804,7 @@ int acpi_device_add(struct acpi_device *device)
|
||||
err:
|
||||
mutex_lock(&acpi_device_lock);
|
||||
|
||||
list_del(&device->wakeup_list);
|
||||
acpi_device_cleanup(device);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
@@ -1139,9 +1144,6 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
|
||||
if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
|
||||
device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
|
||||
}
|
||||
|
||||
if (acpi_bus_init_power(device))
|
||||
device->flags.power_manageable = 0;
|
||||
}
|
||||
|
||||
static void acpi_bus_get_flags(struct acpi_device *device)
|
||||
@@ -1823,7 +1825,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
acpi_set_pnp_ids(handle, &device->pnp, type);
|
||||
acpi_init_properties(device);
|
||||
acpi_bus_get_flags(device);
|
||||
device->flags.initialized = true;
|
||||
device->flags.enumeration_by_parent =
|
||||
acpi_device_enumeration_by_parent(device);
|
||||
acpi_device_clear_enumerated(device);
|
||||
@@ -2209,29 +2210,27 @@ static void acpi_create_video_bus_device(struct acpi_device *adev,
|
||||
struct auxiliary_device *aux_dev;
|
||||
static unsigned int aux_dev_id;
|
||||
|
||||
struct device *phys_parent __free(put_device) = acpi_bus_get_primary_device(parent);
|
||||
if (!phys_parent)
|
||||
return;
|
||||
|
||||
aux_dev = kzalloc_obj(*aux_dev);
|
||||
if (!aux_dev)
|
||||
return;
|
||||
|
||||
aux_dev->id = aux_dev_id++;
|
||||
aux_dev->name = "video_bus";
|
||||
aux_dev->dev.parent = acpi_get_first_physical_node(parent);
|
||||
if (!aux_dev->dev.parent)
|
||||
goto err;
|
||||
|
||||
aux_dev->dev.parent = phys_parent;
|
||||
aux_dev->dev.release = acpi_video_bus_device_release;
|
||||
|
||||
if (auxiliary_device_init(aux_dev))
|
||||
goto err;
|
||||
if (auxiliary_device_init(aux_dev)) {
|
||||
kfree(aux_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
ACPI_COMPANION_SET(&aux_dev->dev, adev);
|
||||
if (__auxiliary_device_add(aux_dev, "acpi"))
|
||||
auxiliary_device_uninit(aux_dev);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
kfree(aux_dev);
|
||||
}
|
||||
|
||||
struct acpi_scan_system_dev {
|
||||
|
||||
@@ -646,6 +646,7 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler);
|
||||
int acpi_bus_scan(acpi_handle handle);
|
||||
void acpi_bus_trim(struct acpi_device *start);
|
||||
acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
|
||||
struct device *acpi_bus_get_primary_device(struct acpi_device *adev);
|
||||
int acpi_match_device_ids(struct acpi_device *device,
|
||||
const struct acpi_device_id *ids);
|
||||
void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
|
||||
@@ -948,6 +949,11 @@ int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices);
|
||||
u32 arch_acpi_add_auto_dep(acpi_handle handle);
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
static inline struct device *acpi_bus_get_primary_device(struct acpi_device *adev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int register_acpi_bus_type(void *bus) { return 0; }
|
||||
static inline int unregister_acpi_bus_type(void *bus) { return 0; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user