Merge tag 'acpi-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki: "These update the ACPICA code in the kernel to the 20180508 upstream revision and make it support the RT patch, add CPPC v3 support to the ACPI CPPC library, add a WDAT-based watchdog quirk to prevent clashes with the RTC, add quirks to the ACPI AC and battery drivers, and update the ACPI SoC drivers. Specifics: - Update the ACPICA code in the kernel to the 20180508 upstream revision including: * iASL -tc option enhancement (Bob Moore). * Debugger improvements (Bob Moore). * Support for tables larger than 1 MB in acpidump/acpixtract (Bob Moore). * Minor fixes and cleanups (Colin Ian King, Toomas Soome). - Make the ACPICA code in the kernel support the RT patch (Sebastian Andrzej Siewior, Steven Rostedt). - Add a kmemleak annotation to the ACPICA code (Larry Finger). - Add CPPC v3 support to the ACPI CPPC library and fix two issues related to CPPC (Prashanth Prakash, Al Stone). - Add an ACPI WDAT-based watchdog quirk to prefer iTCO_wdt on systems where WDAT clashes with the RTC SRAM (Mika Westerberg). - Add some quirks to the ACPI AC and battery drivers (Carlo Caione, Hans de Goede). - Update the ACPI SoC drivers for Intel (LPSS) and AMD (APD) platforms (Akshu Agrawal, Hans de Goede). - Fix up some assorted minor issues (Al Stone, Laszlo Toth, Mathieu Malaterre)" * tag 'acpi-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (32 commits) ACPICA: Mark acpi_ut_create_internal_object_dbg() memory allocations as non-leaks ACPI / watchdog: Prefer iTCO_wdt always when WDAT table uses RTC SRAM mailbox: PCC: erroneous error message when parsing ACPI PCCT ACPICA: Update version to 20180508 ACPICA: acpidump/acpixtract: Support for tables larger than 1MB ACPI: APD: Add AMD misc clock handler support clk: x86: Add ST oscout platform clock ACPICA: Update version to 20180427 ACPICA: Debugger: Removed direct support for EC address space in "Test Objects" ACPICA: Debugger: Add Package support for "test objects" command ACPICA: Improve error messages for the namespace root node ACPICA: Fix potential infinite loop in acpi_rs_dump_byte_list ACPICA: vsnprintf: this statement may fall through ACPICA: Tables: Fix spelling mistake in comment ACPICA: iASL: Enhance the -tc option (create AML hex file in C) ACPI: Add missing prototype_for arch_post_acpi_subsys_init() ACPI / tables: improve comments regarding acpi_parse_entries_array() ACPICA: Convert acpi_gbl_hardware lock back to an acpi_raw_spinlock ACPICA: provide abstraction for raw_spinlock_t ACPI / CPPC: Fix invalid PCC channel status errors ...
Esse commit está contido em:
@@ -86,6 +86,7 @@ extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
|
||||
|
||||
|
||||
static int ac_sleep_before_get_state_ms;
|
||||
static int ac_check_pmic = 1;
|
||||
|
||||
static struct acpi_driver acpi_ac_driver = {
|
||||
.name = "ac",
|
||||
@@ -293,21 +294,43 @@ static int acpi_ac_battery_notify(struct notifier_block *nb,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int thinkpad_e530_quirk(const struct dmi_system_id *d)
|
||||
static int __init thinkpad_e530_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
ac_sleep_before_get_state_ms = 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id ac_dmi_table[] = {
|
||||
static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
ac_check_pmic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id ac_dmi_table[] __initconst = {
|
||||
{
|
||||
/* Thinkpad e530 */
|
||||
.callback = thinkpad_e530_quirk,
|
||||
.ident = "thinkpad e530",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* ECS EF20EA */
|
||||
.callback = ac_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Ideapad Miix 320 */
|
||||
.callback = ac_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -367,7 +390,6 @@ end:
|
||||
kfree(ac);
|
||||
}
|
||||
|
||||
dmi_check_system(ac_dmi_table);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -425,13 +447,17 @@ static int __init acpi_ac_init(void)
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
|
||||
acpi_ac_blacklist[i].hrv)) {
|
||||
pr_info(PREFIX "AC: found native %s PMIC, not loading\n",
|
||||
acpi_ac_blacklist[i].hid);
|
||||
return -ENODEV;
|
||||
}
|
||||
dmi_check_system(ac_dmi_table);
|
||||
|
||||
if (ac_check_pmic) {
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
|
||||
acpi_ac_blacklist[i].hrv)) {
|
||||
pr_info(PREFIX "AC: found native %s PMIC, not loading\n",
|
||||
acpi_ac_blacklist[i].hid);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||
acpi_ac_dir = acpi_lock_ac_dir();
|
||||
|
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_data/clk-st.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/clkdev.h>
|
||||
@@ -72,6 +73,47 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
|
||||
|
||||
static int misc_check_res(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct resource res;
|
||||
|
||||
return !acpi_dev_resource_memory(ares, &res);
|
||||
}
|
||||
|
||||
static int st_misc_setup(struct apd_private_data *pdata)
|
||||
{
|
||||
struct acpi_device *adev = pdata->adev;
|
||||
struct platform_device *clkdev;
|
||||
struct st_clk_data *clk_data;
|
||||
struct resource_entry *rentry;
|
||||
struct list_head resource_list;
|
||||
int ret;
|
||||
|
||||
clk_data = devm_kzalloc(&adev->dev, sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
ret = acpi_dev_get_resources(adev, &resource_list, misc_check_res,
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
return -ENOENT;
|
||||
|
||||
list_for_each_entry(rentry, &resource_list, node) {
|
||||
clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,
|
||||
resource_size(rentry->res));
|
||||
break;
|
||||
}
|
||||
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
clkdev = platform_device_register_data(&adev->dev, "clk-st",
|
||||
PLATFORM_DEVID_NONE, clk_data,
|
||||
sizeof(*clk_data));
|
||||
return PTR_ERR_OR_ZERO(clkdev);
|
||||
}
|
||||
|
||||
static const struct apd_device_desc cz_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 133000000,
|
||||
@@ -94,6 +136,10 @@ static const struct apd_device_desc cz_uart_desc = {
|
||||
.fixed_clk_rate = 48000000,
|
||||
.properties = uart_properties,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc st_misc_desc = {
|
||||
.setup = st_misc_setup,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
@@ -179,6 +225,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
|
||||
{ "AMD0020", APD_ADDR(cz_uart_desc) },
|
||||
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
|
||||
{ "AMD0030", },
|
||||
{ "AMD0040", APD_ADDR(st_misc_desc)},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64
|
||||
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
|
||||
|
@@ -69,6 +69,10 @@ ACPI_MODULE_NAME("acpi_lpss");
|
||||
#define LPSS_SAVE_CTX BIT(4)
|
||||
#define LPSS_NO_D3_DELAY BIT(5)
|
||||
|
||||
/* Crystal Cove PMIC shares same ACPI ID between different platforms */
|
||||
#define BYT_CRC_HRV 2
|
||||
#define CHT_CRC_HRV 3
|
||||
|
||||
struct lpss_private_data;
|
||||
|
||||
struct lpss_device_desc {
|
||||
@@ -162,7 +166,7 @@ static void byt_pwm_setup(struct lpss_private_data *pdata)
|
||||
if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1"))
|
||||
return;
|
||||
|
||||
if (!acpi_dev_present("INT33FD", NULL, -1))
|
||||
if (!acpi_dev_present("INT33FD", NULL, BYT_CRC_HRV))
|
||||
pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
|
||||
}
|
||||
|
||||
|
@@ -12,35 +12,51 @@
|
||||
#define pr_fmt(fmt) "ACPI: watchdog: " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static const struct dmi_system_id acpi_watchdog_skip[] = {
|
||||
{
|
||||
/*
|
||||
* On Lenovo Z50-70 there are two issues with the WDAT
|
||||
* table. First some of the instructions use RTC SRAM
|
||||
* to store persistent information. This does not work well
|
||||
* with Linux RTC driver. Second, more important thing is
|
||||
* that the instructions do not actually reset the system.
|
||||
*
|
||||
* On this particular system iTCO_wdt seems to work just
|
||||
* fine so we prefer that over WDAT for now.
|
||||
*
|
||||
* See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
|
||||
*/
|
||||
.ident = "Lenovo Z50-70",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20354"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
#ifdef CONFIG_RTC_MC146818_LIB
|
||||
#include <linux/mc146818rtc.h>
|
||||
|
||||
/*
|
||||
* There are several systems where the WDAT table is accessing RTC SRAM to
|
||||
* store persistent information. This does not work well with the Linux RTC
|
||||
* driver so on those systems we skip WDAT driver and prefer iTCO_wdt
|
||||
* instead.
|
||||
*
|
||||
* See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
|
||||
*/
|
||||
static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
|
||||
{
|
||||
const struct acpi_wdat_entry *entries;
|
||||
int i;
|
||||
|
||||
entries = (struct acpi_wdat_entry *)(wdat + 1);
|
||||
for (i = 0; i < wdat->entries; i++) {
|
||||
const struct acpi_generic_address *gas;
|
||||
|
||||
gas = &entries[i].register_region;
|
||||
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
switch (gas->address) {
|
||||
case RTC_PORT(0):
|
||||
case RTC_PORT(1):
|
||||
case RTC_PORT(2):
|
||||
case RTC_PORT(3):
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
|
||||
{
|
||||
@@ -50,9 +66,6 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
|
||||
if (acpi_disabled)
|
||||
return NULL;
|
||||
|
||||
if (dmi_check_system(acpi_watchdog_skip))
|
||||
return NULL;
|
||||
|
||||
status = acpi_get_table(ACPI_SIG_WDAT, 0,
|
||||
(struct acpi_table_header **)&wdat);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -60,6 +73,11 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (acpi_watchdog_uses_rtc(wdat)) {
|
||||
pr_info("Skipping WDAT on this system because it uses RTC SRAM\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wdat;
|
||||
}
|
||||
|
||||
|
@@ -143,6 +143,8 @@ acpi_status
|
||||
fl_split_input_pathname(char *input_path,
|
||||
char **out_directory_path, char **out_filename);
|
||||
|
||||
char *fl_get_file_basename(char *file_pathname);
|
||||
|
||||
char *ad_generate_filename(char *prefix, char *table_id);
|
||||
|
||||
void
|
||||
|
@@ -82,7 +82,7 @@ ACPI_GLOBAL(u8, acpi_gbl_global_lock_pending);
|
||||
* interrupt level
|
||||
*/
|
||||
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */
|
||||
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||||
ACPI_GLOBAL(acpi_raw_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||||
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock);
|
||||
|
||||
/* Mutex for _OSI support */
|
||||
|
@@ -189,9 +189,15 @@ void acpi_db_dump_namespace(char *start_arg, char *depth_arg)
|
||||
}
|
||||
|
||||
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
|
||||
acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n",
|
||||
((struct acpi_namespace_node *)subtree_entry)->name.
|
||||
ascii, subtree_entry);
|
||||
|
||||
if (((struct acpi_namespace_node *)subtree_entry)->parent) {
|
||||
acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n",
|
||||
((struct acpi_namespace_node *)subtree_entry)->
|
||||
name.ascii, subtree_entry);
|
||||
} else {
|
||||
acpi_os_printf("ACPI Namespace (from %s):\n",
|
||||
ACPI_NAMESPACE_ROOT);
|
||||
}
|
||||
|
||||
/* Display the subtree */
|
||||
|
||||
|
@@ -30,6 +30,8 @@ acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length);
|
||||
static acpi_status
|
||||
acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length);
|
||||
|
||||
static acpi_status acpi_db_test_package_type(struct acpi_namespace_node *node);
|
||||
|
||||
static acpi_status
|
||||
acpi_db_read_from_object(struct acpi_namespace_node *node,
|
||||
acpi_object_type expected_type,
|
||||
@@ -273,6 +275,11 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
bit_length = byte_length * 8;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
local_type = ACPI_TYPE_PACKAGE;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_FIELD_UNIT:
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
@@ -305,6 +312,7 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
|
||||
acpi_os_printf("%14s: %4.4s",
|
||||
acpi_ut_get_type_name(node->type), node->name.ascii);
|
||||
|
||||
if (!obj_desc) {
|
||||
acpi_os_printf(" Ignoring, no attached object\n");
|
||||
return (AE_OK);
|
||||
@@ -322,14 +330,13 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||
case ACPI_ADR_SPACE_PCI_CONFIG:
|
||||
case ACPI_ADR_SPACE_EC:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
acpi_os_printf
|
||||
(" %s space is not supported [%4.4s]\n",
|
||||
(" %s space is not supported in this command [%4.4s]\n",
|
||||
acpi_ut_get_region_name(region_obj->region.
|
||||
space_id),
|
||||
region_obj->region.node->name.ascii);
|
||||
@@ -359,6 +366,11 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
status = acpi_db_test_buffer_type(node, bit_length);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
status = acpi_db_test_package_type(node);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
acpi_os_printf(" Ignoring, type not implemented (%2.2X)",
|
||||
@@ -366,6 +378,13 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Exit on error, but don't abort the namespace walk */
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = AE_OK;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (node->type) {
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
|
||||
@@ -373,12 +392,14 @@ acpi_db_test_one_object(acpi_handle obj_handle,
|
||||
acpi_os_printf(" (%s)",
|
||||
acpi_ut_get_region_name(region_obj->region.
|
||||
space_id));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
acpi_os_printf("\n");
|
||||
return (status);
|
||||
}
|
||||
@@ -431,7 +452,6 @@ acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length)
|
||||
if (temp1->integer.value == value_to_write) {
|
||||
value_to_write = 0;
|
||||
}
|
||||
|
||||
/* Write a new value */
|
||||
|
||||
write_value.type = ACPI_TYPE_INTEGER;
|
||||
@@ -706,6 +726,35 @@ exit:
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_db_test_package_type
|
||||
*
|
||||
* PARAMETERS: node - Parent NS node for the object
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Test read for a Package object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status acpi_db_test_package_type(struct acpi_namespace_node *node)
|
||||
{
|
||||
union acpi_object *temp1 = NULL;
|
||||
acpi_status status;
|
||||
|
||||
/* Read the original value */
|
||||
|
||||
status = acpi_db_read_from_object(node, ACPI_TYPE_PACKAGE, &temp1);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
acpi_os_printf(" %8.8X Elements", temp1->package.count);
|
||||
acpi_os_free(temp1);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_db_read_from_object
|
||||
@@ -746,8 +795,8 @@ acpi_db_read_from_object(struct acpi_namespace_node *node,
|
||||
acpi_gbl_method_executing = TRUE;
|
||||
status = acpi_evaluate_object(read_handle, NULL,
|
||||
¶m_objects, &return_obj);
|
||||
acpi_gbl_method_executing = FALSE;
|
||||
|
||||
acpi_gbl_method_executing = FALSE;
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_os_printf("Could not read from object, %s",
|
||||
acpi_format_exception(status));
|
||||
@@ -760,6 +809,7 @@ acpi_db_read_from_object(struct acpi_namespace_node *node,
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/*
|
||||
* Did we receive the type we wanted? Most important for the
|
||||
* Integer/Buffer case (when a field is larger than an Integer,
|
||||
@@ -771,6 +821,7 @@ acpi_db_read_from_object(struct acpi_namespace_node *node,
|
||||
acpi_ut_get_type_name(expected_type),
|
||||
acpi_ut_get_type_name(ret_value->type));
|
||||
|
||||
acpi_os_free(return_obj.pointer);
|
||||
return (AE_TYPE);
|
||||
}
|
||||
|
||||
|
@@ -115,7 +115,7 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
|
||||
acpi_ut_get_type_name(old_scope_info->
|
||||
common.value)));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT"));
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, ACPI_NAMESPACE_ROOT));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
|
||||
@@ -166,14 +166,14 @@ acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state)
|
||||
|
||||
new_scope_info = walk_state->scope_info;
|
||||
if (new_scope_info) {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
|
||||
"[%4.4s] (%s)\n",
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[%4.4s] (%s)\n",
|
||||
acpi_ut_get_node_name(new_scope_info->
|
||||
scope.node),
|
||||
acpi_ut_get_type_name(new_scope_info->
|
||||
common.value)));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n"));
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "%s\n",
|
||||
ACPI_NAMESPACE_ROOT));
|
||||
}
|
||||
|
||||
acpi_ut_delete_generic_state(scope_info);
|
||||
|
@@ -390,14 +390,14 @@ acpi_status acpi_hw_clear_acpi_status(void)
|
||||
ACPI_BITMASK_ALL_FIXED_STATUS,
|
||||
ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
|
||||
|
||||
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||||
lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock);
|
||||
|
||||
/* Clear the fixed events in PM1 A/B */
|
||||
|
||||
status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
|
||||
ACPI_BITMASK_ALL_FIXED_STATUS);
|
||||
|
||||
acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
acpi_os_release_raw_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
|
@@ -227,7 +227,7 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value)
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||||
lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock);
|
||||
|
||||
/*
|
||||
* At this point, we know that the parent register is one of the
|
||||
@@ -288,7 +288,7 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value)
|
||||
|
||||
unlock_and_exit:
|
||||
|
||||
acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
acpi_os_release_raw_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
|
@@ -539,7 +539,7 @@ static void acpi_rs_out_title(const char *title)
|
||||
|
||||
static void acpi_rs_dump_byte_list(u16 length, u8 * data)
|
||||
{
|
||||
u8 i;
|
||||
u16 i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]);
|
||||
|
@@ -88,7 +88,7 @@ acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
* DESCRIPTION: This function is called to verify and install an ACPI table.
|
||||
* When this function is called by "Load" or "LoadTable" opcodes,
|
||||
* or by acpi_load_table() API, the "Reload" parameter is set.
|
||||
* After sucessfully returning from this function, table is
|
||||
* After successfully returning from this function, table is
|
||||
* "INSTALLED" but not "VALIDATED".
|
||||
*
|
||||
******************************************************************************/
|
||||
|
@@ -53,7 +53,7 @@ void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset)
|
||||
|
||||
/* Print current offset */
|
||||
|
||||
acpi_os_printf("%6.4X: ", (base_offset + i));
|
||||
acpi_os_printf("%8.4X: ", (base_offset + i));
|
||||
|
||||
/* Print 16 hex chars */
|
||||
|
||||
@@ -219,7 +219,7 @@ acpi_ut_dump_buffer_to_file(ACPI_FILE file,
|
||||
|
||||
/* Print current offset */
|
||||
|
||||
fprintf(file, "%6.4X: ", (base_offset + i));
|
||||
fprintf(file, "%8.4X: ", (base_offset + i));
|
||||
|
||||
/* Print 16 hex chars */
|
||||
|
||||
|
@@ -52,7 +52,7 @@ acpi_status acpi_ut_mutex_initialize(void)
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
status = acpi_os_create_lock (&acpi_gbl_hardware_lock);
|
||||
status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
@@ -109,7 +109,7 @@ void acpi_ut_mutex_terminate(void)
|
||||
/* Delete the spinlocks */
|
||||
|
||||
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
||||
acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
||||
acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
|
||||
acpi_os_delete_lock(acpi_gbl_reference_count_lock);
|
||||
|
||||
/* Delete the reader/writer lock */
|
||||
|
@@ -8,6 +8,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <linux/kmemleak.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
|
||||
@@ -70,6 +71,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
|
||||
if (!object) {
|
||||
return_PTR(NULL);
|
||||
}
|
||||
kmemleak_not_leak(object);
|
||||
|
||||
switch (type) {
|
||||
case ACPI_TYPE_REGION:
|
||||
|
@@ -470,6 +470,7 @@ int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
|
||||
case 'X':
|
||||
|
||||
type |= ACPI_FORMAT_UPPER;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 'x':
|
||||
|
||||
|
@@ -141,7 +141,7 @@ void acpi_ut_repair_name(char *name)
|
||||
* Special case for the root node. This can happen if we get an
|
||||
* error during the execution of module-level code.
|
||||
*/
|
||||
if (ACPI_COMPARE_NAME(name, "\\___")) {
|
||||
if (ACPI_COMPARE_NAME(name, ACPI_ROOT_PATHNAME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -74,6 +74,8 @@ static async_cookie_t async_cookie;
|
||||
static bool battery_driver_registered;
|
||||
static int battery_bix_broken_package;
|
||||
static int battery_notification_delay_ms;
|
||||
static int battery_ac_is_broken;
|
||||
static int battery_check_pmic = 1;
|
||||
static unsigned int cache_time = 1000;
|
||||
module_param(cache_time, uint, 0644);
|
||||
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
||||
@@ -207,6 +209,20 @@ 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)
|
||||
@@ -222,7 +238,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
val->intval = acpi_battery_handle_discharging(battery);
|
||||
else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else if (acpi_battery_is_charged(battery))
|
||||
@@ -1263,23 +1279,64 @@ battery_notification_delay_quirk(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
battery_ac_is_broken_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
battery_ac_is_broken = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
battery_check_pmic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
||||
{
|
||||
/* NEC LZ750/LS */
|
||||
.callback = battery_bix_broken_package_quirk,
|
||||
.ident = "NEC LZ750/LS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Acer Aspire V5-573G */
|
||||
.callback = battery_notification_delay_quirk,
|
||||
.ident = "Acer Aspire V5-573G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Point of View mobii wintab p800w */
|
||||
.callback = battery_ac_is_broken_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
|
||||
/* Above matches are too generic, add bios-date match */
|
||||
DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* ECS EF20EA */
|
||||
.callback = battery_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Ideapad Miix 320 */
|
||||
.callback = battery_do_not_check_pmic_quirk,
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -1419,16 +1476,18 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||
unsigned int i;
|
||||
int result;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
|
||||
pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
|
||||
": found native %s PMIC, not loading\n",
|
||||
acpi_battery_blacklist[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
dmi_check_system(bat_dmi_table);
|
||||
|
||||
if (battery_check_pmic) {
|
||||
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
|
||||
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
|
||||
pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
|
||||
": found native %s PMIC, not loading\n",
|
||||
acpi_battery_blacklist[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||
acpi_battery_dir = acpi_lock_battery_dir();
|
||||
if (!acpi_battery_dir)
|
||||
|
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/wait.h>
|
||||
@@ -49,7 +50,7 @@ struct cppc_pcc_data {
|
||||
struct mbox_chan *pcc_channel;
|
||||
void __iomem *pcc_comm_addr;
|
||||
bool pcc_channel_acquired;
|
||||
ktime_t deadline;
|
||||
unsigned int deadline_us;
|
||||
unsigned int pcc_mpar, pcc_mrtt, pcc_nominal;
|
||||
|
||||
bool pending_pcc_write_cmd; /* Any pending/batched PCC write cmds? */
|
||||
@@ -156,6 +157,9 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, highest_perf);
|
||||
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, lowest_perf);
|
||||
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_perf);
|
||||
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, lowest_nonlinear_perf);
|
||||
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, lowest_freq);
|
||||
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_freq);
|
||||
|
||||
show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, reference_perf);
|
||||
show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
|
||||
|
||||
@@ -183,6 +187,8 @@ static struct attribute *cppc_attrs[] = {
|
||||
&lowest_perf.attr,
|
||||
&lowest_nonlinear_perf.attr,
|
||||
&nominal_perf.attr,
|
||||
&nominal_freq.attr,
|
||||
&lowest_freq.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -193,42 +199,31 @@ static struct kobj_type cppc_ktype = {
|
||||
|
||||
static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit)
|
||||
{
|
||||
int ret = -EIO, status = 0;
|
||||
int ret, status;
|
||||
struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
struct acpi_pcct_shared_memory __iomem *generic_comm_base =
|
||||
pcc_ss_data->pcc_comm_addr;
|
||||
ktime_t next_deadline = ktime_add(ktime_get(),
|
||||
pcc_ss_data->deadline);
|
||||
|
||||
if (!pcc_ss_data->platform_owns_pcc)
|
||||
return 0;
|
||||
|
||||
/* Retry in case the remote processor was too slow to catch up. */
|
||||
while (!ktime_after(ktime_get(), next_deadline)) {
|
||||
/*
|
||||
* Per spec, prior to boot the PCC space wil be initialized by
|
||||
* platform and should have set the command completion bit when
|
||||
* PCC can be used by OSPM
|
||||
*/
|
||||
status = readw_relaxed(&generic_comm_base->status);
|
||||
if (status & PCC_CMD_COMPLETE_MASK) {
|
||||
ret = 0;
|
||||
if (chk_err_bit && (status & PCC_ERROR_MASK))
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Reducing the bus traffic in case this loop takes longer than
|
||||
* a few retries.
|
||||
*/
|
||||
udelay(3);
|
||||
/*
|
||||
* Poll PCC status register every 3us(delay_us) for maximum of
|
||||
* deadline_us(timeout_us) until PCC command complete bit is set(cond)
|
||||
*/
|
||||
ret = readw_relaxed_poll_timeout(&generic_comm_base->status, status,
|
||||
status & PCC_CMD_COMPLETE_MASK, 3,
|
||||
pcc_ss_data->deadline_us);
|
||||
|
||||
if (likely(!ret)) {
|
||||
pcc_ss_data->platform_owns_pcc = false;
|
||||
if (chk_err_bit && (status & PCC_ERROR_MASK))
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (likely(!ret))
|
||||
pcc_ss_data->platform_owns_pcc = false;
|
||||
else
|
||||
pr_err("PCC check channel failed for ss: %d. Status=%x\n",
|
||||
pcc_ss_id, status);
|
||||
if (unlikely(ret))
|
||||
pr_err("PCC check channel failed for ss: %d. ret=%d\n",
|
||||
pcc_ss_id, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -580,7 +575,7 @@ static int register_pcc_channel(int pcc_ss_idx)
|
||||
* So add an arbitrary amount of wait on top of Nominal.
|
||||
*/
|
||||
usecs_lat = NUM_RETRIES * cppc_ss->latency;
|
||||
pcc_data[pcc_ss_idx]->deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
|
||||
pcc_data[pcc_ss_idx]->deadline_us = usecs_lat;
|
||||
pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time;
|
||||
pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate;
|
||||
pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency;
|
||||
@@ -613,7 +608,6 @@ bool __weak cpc_ffh_supported(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace
|
||||
*
|
||||
@@ -641,6 +635,34 @@ int pcc_data_alloc(int pcc_ss_id)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if CPPC revision + num_ent combination is supported */
|
||||
static bool is_cppc_supported(int revision, int num_ent)
|
||||
{
|
||||
int expected_num_ent;
|
||||
|
||||
switch (revision) {
|
||||
case CPPC_V2_REV:
|
||||
expected_num_ent = CPPC_V2_NUM_ENT;
|
||||
break;
|
||||
case CPPC_V3_REV:
|
||||
expected_num_ent = CPPC_V3_NUM_ENT;
|
||||
break;
|
||||
default:
|
||||
pr_debug("Firmware exports unsupported CPPC revision: %d\n",
|
||||
revision);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected_num_ent != num_ent) {
|
||||
pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n",
|
||||
num_ent, expected_num_ent, revision);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* An example CPC table looks like the following.
|
||||
*
|
||||
@@ -731,14 +753,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
|
||||
cpc_obj->type);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Only support CPPCv2. Bail otherwise. */
|
||||
if (num_ent != CPPC_NUM_ENT) {
|
||||
pr_debug("Firmware exports %d entries. Expected: %d\n",
|
||||
num_ent, CPPC_NUM_ENT);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
cpc_ptr->num_entries = num_ent;
|
||||
|
||||
/* Second entry should be revision. */
|
||||
@@ -750,12 +764,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
|
||||
cpc_obj->type);
|
||||
goto out_free;
|
||||
}
|
||||
cpc_ptr->version = cpc_rev;
|
||||
|
||||
if (cpc_rev != CPPC_REV) {
|
||||
pr_debug("Firmware exports revision:%d. Expected:%d\n",
|
||||
cpc_rev, CPPC_REV);
|
||||
if (!is_cppc_supported(cpc_rev, num_ent))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Iterate through remaining entries in _CPC */
|
||||
for (i = 2; i < num_ent; i++) {
|
||||
@@ -808,6 +820,18 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
|
||||
}
|
||||
}
|
||||
per_cpu(cpu_pcc_subspace_idx, pr->id) = pcc_subspace_id;
|
||||
|
||||
/*
|
||||
* Initialize the remaining cpc_regs as unsupported.
|
||||
* Example: In case FW exposes CPPC v2, the below loop will initialize
|
||||
* LOWEST_FREQ and NOMINAL_FREQ regs as unsupported
|
||||
*/
|
||||
for (i = num_ent - 2; i < MAX_CPC_REG_ENT; i++) {
|
||||
cpc_ptr->cpc_regs[i].type = ACPI_TYPE_INTEGER;
|
||||
cpc_ptr->cpc_regs[i].cpc_entry.int_value = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Store CPU Logical ID */
|
||||
cpc_ptr->cpu_id = pr->id;
|
||||
|
||||
@@ -1037,26 +1061,34 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
|
||||
struct cpc_register_resource *highest_reg, *lowest_reg,
|
||||
*lowest_non_linear_reg, *nominal_reg;
|
||||
u64 high, low, nom, min_nonlinear;
|
||||
*lowest_non_linear_reg, *nominal_reg,
|
||||
*low_freq_reg = NULL, *nom_freq_reg = NULL;
|
||||
u64 high, low, nom, min_nonlinear, low_f = 0, nom_f = 0;
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
|
||||
struct cppc_pcc_data *pcc_ss_data;
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
int ret = 0, regs_in_pcc = 0;
|
||||
|
||||
if (!cpc_desc || pcc_ss_id < 0) {
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
highest_reg = &cpc_desc->cpc_regs[HIGHEST_PERF];
|
||||
lowest_reg = &cpc_desc->cpc_regs[LOWEST_PERF];
|
||||
lowest_non_linear_reg = &cpc_desc->cpc_regs[LOW_NON_LINEAR_PERF];
|
||||
nominal_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
|
||||
low_freq_reg = &cpc_desc->cpc_regs[LOWEST_FREQ];
|
||||
nom_freq_reg = &cpc_desc->cpc_regs[NOMINAL_FREQ];
|
||||
|
||||
/* Are any of the regs PCC ?*/
|
||||
if (CPC_IN_PCC(highest_reg) || CPC_IN_PCC(lowest_reg) ||
|
||||
CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg)) {
|
||||
CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) ||
|
||||
CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg)) {
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
regs_in_pcc = 1;
|
||||
down_write(&pcc_ss_data->pcc_lock);
|
||||
/* Ring doorbell once to update PCC subspace */
|
||||
@@ -1081,6 +1113,17 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
if (!high || !low || !nom || !min_nonlinear)
|
||||
ret = -EFAULT;
|
||||
|
||||
/* Read optional lowest and nominal frequencies if present */
|
||||
if (CPC_SUPPORTED(low_freq_reg))
|
||||
cpc_read(cpunum, low_freq_reg, &low_f);
|
||||
|
||||
if (CPC_SUPPORTED(nom_freq_reg))
|
||||
cpc_read(cpunum, nom_freq_reg, &nom_f);
|
||||
|
||||
perf_caps->lowest_freq = low_f;
|
||||
perf_caps->nominal_freq = nom_f;
|
||||
|
||||
|
||||
out_err:
|
||||
if (regs_in_pcc)
|
||||
up_write(&pcc_ss_data->pcc_lock);
|
||||
@@ -1101,16 +1144,15 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
|
||||
struct cpc_register_resource *delivered_reg, *reference_reg,
|
||||
*ref_perf_reg, *ctr_wrap_reg;
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
|
||||
struct cppc_pcc_data *pcc_ss_data;
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
u64 delivered, reference, ref_perf, ctr_wrap_time;
|
||||
int ret = 0, regs_in_pcc = 0;
|
||||
|
||||
if (!cpc_desc || pcc_ss_id < 0) {
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
delivered_reg = &cpc_desc->cpc_regs[DELIVERED_CTR];
|
||||
reference_reg = &cpc_desc->cpc_regs[REFERENCE_CTR];
|
||||
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
|
||||
@@ -1126,6 +1168,11 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
|
||||
/* Are any of the regs PCC ?*/
|
||||
if (CPC_IN_PCC(delivered_reg) || CPC_IN_PCC(reference_reg) ||
|
||||
CPC_IN_PCC(ctr_wrap_reg) || CPC_IN_PCC(ref_perf_reg)) {
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
down_write(&pcc_ss_data->pcc_lock);
|
||||
regs_in_pcc = 1;
|
||||
/* Ring doorbell once to update PCC subspace */
|
||||
@@ -1176,15 +1223,14 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
|
||||
struct cpc_register_resource *desired_reg;
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
struct cppc_pcc_data *pcc_ss_data;
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!cpc_desc || pcc_ss_id < 0) {
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
|
||||
|
||||
/*
|
||||
@@ -1195,6 +1241,11 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
|
||||
* achieve that goal here
|
||||
*/
|
||||
if (CPC_IN_PCC(desired_reg)) {
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
down_read(&pcc_ss_data->pcc_lock); /* BEGIN Phase-I */
|
||||
if (pcc_ss_data->platform_owns_pcc) {
|
||||
ret = check_pcc_chan(pcc_ss_id, false);
|
||||
|
@@ -8,8 +8,8 @@ void acpi_reboot(void)
|
||||
{
|
||||
struct acpi_generic_address *rr;
|
||||
struct pci_bus *bus0;
|
||||
u8 reset_value;
|
||||
unsigned int devfn;
|
||||
u8 reset_value;
|
||||
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
@@ -40,7 +40,7 @@ void acpi_reboot(void)
|
||||
/* Form PCI device/function pair. */
|
||||
devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
|
||||
(rr->address >> 16) & 0xffff);
|
||||
printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.");
|
||||
printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.\n");
|
||||
/* Write the value that resets us. */
|
||||
pci_bus_write_config_byte(bus0, devfn,
|
||||
(rr->address & 0xffff), reset_value);
|
||||
|
@@ -222,7 +222,7 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
|
||||
* acpi_parse_entries_array - for each proc_num find a suitable subtable
|
||||
*
|
||||
* @id: table id (for debugging purposes)
|
||||
* @table_size: single entry size
|
||||
* @table_size: size of the root table
|
||||
* @table_header: where does the table start?
|
||||
* @proc: array of acpi_subtable_proc struct containing entry id
|
||||
* and associated handler with it
|
||||
@@ -233,6 +233,11 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
|
||||
* on it. Assumption is that there's only single handler for particular
|
||||
* entry id.
|
||||
*
|
||||
* The table_size is not the size of the complete ACPI table (the length
|
||||
* field in the header struct), but only the size of the root table; i.e.,
|
||||
* the offset from the very first byte of the complete ACPI table, to the
|
||||
* first byte of the very first subtable.
|
||||
*
|
||||
* On success returns sum of all matching entries for all proc handlers.
|
||||
* Otherwise, -ENODEV or -EINVAL is returned.
|
||||
*/
|
||||
@@ -400,7 +405,7 @@ int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* The BIOS is supposed to supply a single APIC/MADT,
|
||||
* but some report two. Provide a knob to use either.
|
||||
* (don't you wish instance 0 and 1 were not the same?)
|
||||
|
Referência em uma nova issue
Block a user