Skip to content

Commit

Permalink
ACPI: TAD: Install SystemCMOS address space handler for ACPI000E
Browse files Browse the repository at this point in the history
Currently, the SystemCMOS address space handler is installed for the
ACPI RTC devices (PNP0B00/PNP0B01/PNP0B02) only. But there are platforms
with SystemCMOS Operetion Region defined under the ACPI Time and Alarm
Device (ACPI000E), which is used by the ACPI pre-defined control methods
like _GRT (Get the Real time) and _SRT (Set the Real time).

When accessing these control methods via the acpi_tad sysfs interface,
missing SystemCMOS address space handler causes errors like below
[  478.255453] ACPI Error: No handler for Region [RTCM] (00000000a8d2dd39) [SystemCMOS] (20230331/evregion-130)
[  478.255458] ACPI Error: Region SystemCMOS (ID=5) has no handler (20230331/exfldio-261)
[  478.255461] Initialized Local Variables for Method [_GRT]:
[  478.255461]   Local1: 00000000f182542c <Obj>           Integer 0000000000000000
[  478.255464] No Arguments are initialized for method [_GRT]
[  478.255465] ACPI Error: Aborting method \_SB.AWAC._GRT due to previous error (AE_NOT_EXIST) (20230331/psparse-529)

Export two APIs for SystemCMOS address space handler from acpi_cmos_rtc
scan handler and install the handler for the ACPI Time and Alarm Device
from the ACPI TAD driver.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=217714
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
[ rjw: Subject and changelog edits, whitespace adjustment ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Zhang Rui authored and Rafael J. Wysocki committed Aug 17, 2023
1 parent 2ccdd1b commit 596ca52
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
25 changes: 18 additions & 7 deletions drivers/acpi/acpi_cmos_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
return AE_OK;
}

static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
const struct acpi_device_id *id)
int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
{
acpi_status status;

status = acpi_install_address_space_handler(adev->handle,
status = acpi_install_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS,
&acpi_cmos_rtc_space_handler,
NULL, NULL);
Expand All @@ -67,18 +66,30 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,

return 1;
}
EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);

static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev)
void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{
if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle,
if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
pr_err("Error removing CMOS-RTC region handler\n");
}
EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);

static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
{
return acpi_install_cmos_rtc_space_handler(adev->handle);
}

static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
{
acpi_remove_cmos_rtc_space_handler(adev->handle);
}

static struct acpi_scan_handler cmos_rtc_handler = {
.ids = acpi_cmos_rtc_ids,
.attach = acpi_install_cmos_rtc_space_handler,
.detach = acpi_remove_cmos_rtc_space_handler,
.attach = acpi_cmos_rtc_attach_handler,
.detach = acpi_cmos_rtc_detach_handler,
};

void __init acpi_cmos_rtc_init(void)
Expand Down
27 changes: 22 additions & 5 deletions drivers/acpi/acpi_tad.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
static int acpi_tad_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);

device_init_wakeup(dev, false);
Expand All @@ -577,6 +578,7 @@ static int acpi_tad_remove(struct platform_device *pdev)

pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
acpi_remove_cmos_rtc_space_handler(handle);
return 0;
}

Expand All @@ -589,29 +591,39 @@ static int acpi_tad_probe(struct platform_device *pdev)
unsigned long long caps;
int ret;

ret = acpi_install_cmos_rtc_space_handler(handle);
if (ret < 0) {
dev_info(dev, "Unable to install space handler\n");
return -ENODEV;
}
/*
* Initialization failure messages are mostly about firmware issues, so
* print them at the "info" level.
*/
status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
if (ACPI_FAILURE(status)) {
dev_info(dev, "Unable to get capabilities\n");
return -ENODEV;
ret = -ENODEV;
goto remove_handler;
}

if (!(caps & ACPI_TAD_AC_WAKE)) {
dev_info(dev, "Unsupported capabilities\n");
return -ENODEV;
ret = -ENODEV;
goto remove_handler;
}

if (!acpi_has_method(handle, "_PRW")) {
dev_info(dev, "Missing _PRW\n");
return -ENODEV;
ret = -ENODEV;
goto remove_handler;
}

dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
if (!dd)
return -ENOMEM;
if (!dd) {
ret = -ENOMEM;
goto remove_handler;
}

dd->capabilities = caps;
dev_set_drvdata(dev, dd);
Expand Down Expand Up @@ -653,6 +665,11 @@ static int acpi_tad_probe(struct platform_device *pdev)

fail:
acpi_tad_remove(pdev);
/* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
return ret;

remove_handler:
acpi_remove_cmos_rtc_space_handler(handle);
return ret;
}

Expand Down
9 changes: 9 additions & 0 deletions include/acpi/acpi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev);
#ifdef CONFIG_X86
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
bool acpi_quirk_skip_acpi_ac_and_battery(void);
int acpi_install_cmos_rtc_space_handler(acpi_handle handle);
void acpi_remove_cmos_rtc_space_handler(acpi_handle handle);
#else
static inline bool acpi_device_override_status(struct acpi_device *adev,
unsigned long long *status)
Expand All @@ -655,6 +657,13 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
{
return false;
}
static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
{
return 1;
}
static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{
}
#endif

#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
Expand Down

0 comments on commit 596ca52

Please sign in to comment.