Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4fe74cc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 3c89adb0 2448d139
Loading
Loading
Loading
Loading
+69 −0
Original line number Original line Diff line number Diff line

	Collaborative Processor Performance Control (CPPC)

CPPC defined in the ACPI spec describes a mechanism for the OS to manage the
performance of a logical processor on a contigious and abstract performance
scale. CPPC exposes a set of registers to describe abstract performance scale,
to request performance levels and to measure per-cpu delivered performance.

For more details on CPPC please refer to the ACPI specification at:

http://uefi.org/specifications

Some of the CPPC registers are exposed via sysfs under:

/sys/devices/system/cpu/cpuX/acpi_cppc/

for each cpu X

--------------------------------------------------------------------------------

$ ls -lR  /sys/devices/system/cpu/cpu0/acpi_cppc/
/sys/devices/system/cpu/cpu0/acpi_cppc/:
total 0
-r--r--r-- 1 root root 65536 Mar  5 19:38 feedback_ctrs
-r--r--r-- 1 root root 65536 Mar  5 19:38 highest_perf
-r--r--r-- 1 root root 65536 Mar  5 19:38 lowest_freq
-r--r--r-- 1 root root 65536 Mar  5 19:38 lowest_nonlinear_perf
-r--r--r-- 1 root root 65536 Mar  5 19:38 lowest_perf
-r--r--r-- 1 root root 65536 Mar  5 19:38 nominal_freq
-r--r--r-- 1 root root 65536 Mar  5 19:38 nominal_perf
-r--r--r-- 1 root root 65536 Mar  5 19:38 reference_perf
-r--r--r-- 1 root root 65536 Mar  5 19:38 wraparound_time

--------------------------------------------------------------------------------

* highest_perf : Highest performance of this processor (abstract scale).
* nominal_perf : Highest sustained performance of this processor (abstract scale).
* lowest_nonlinear_perf : Lowest performance of this processor with nonlinear
  power savings (abstract scale).
* lowest_perf : Lowest performance of this processor (abstract scale).

* lowest_freq : CPU frequency corresponding to lowest_perf (in MHz).
* nominal_freq : CPU frequency corresponding to nominal_perf (in MHz).
  The above frequencies should only be used to report processor performance in
  freqency instead of abstract scale. These values should not be used for any
  functional decisions.

* feedback_ctrs : Includes both Reference and delivered performance counter.
  Reference counter ticks up proportional to processor's reference performance.
  Delivered counter ticks up proportional to processor's delivered performance.
* wraparound_time: Minimum time for the feedback counters to wraparound (seconds).
* reference_perf : Performance level at which reference performance counter
  accumulates (abstract scale).

--------------------------------------------------------------------------------

		Computing Average Delivered Performance

Below describes the steps to compute the average performance delivered by taking
two different snapshots of feedback counters at time T1 and T2.

T1: Read feedback_ctrs as fbc_t1
    Wait or run some workload
T2: Read feedback_ctrs as fbc_t2

delivered_counter_delta = fbc_t2[del] - fbc_t1[del]
reference_counter_delta = fbc_t2[ref] - fbc_t1[ref]

delivered_perf = (refernce_perf x delivered_counter_delta) / reference_counter_delta
+37 −11
Original line number Original line Diff line number Diff line
@@ -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_sleep_before_get_state_ms;
static int ac_check_pmic = 1;


static struct acpi_driver acpi_ac_driver = {
static struct acpi_driver acpi_ac_driver = {
	.name = "ac",
	.name = "ac",
@@ -293,21 +294,43 @@ static int acpi_ac_battery_notify(struct notifier_block *nb,
	return NOTIFY_OK;
	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;
	ac_sleep_before_get_state_ms = 1000;
	return 0;
	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,
	.callback = thinkpad_e530_quirk,
	.ident = "thinkpad e530",
	.matches = {
	.matches = {
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
		DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"),
		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 @@ static int acpi_ac_add(struct acpi_device *device)
		kfree(ac);
		kfree(ac);
	}
	}


	dmi_check_system(ac_dmi_table);
	return result;
	return result;
}
}


@@ -425,6 +447,9 @@ static int __init acpi_ac_init(void)
	if (acpi_disabled)
	if (acpi_disabled)
		return -ENODEV;
		return -ENODEV;


	dmi_check_system(ac_dmi_table);

	if (ac_check_pmic) {
		for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
		for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
			if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
			if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
					     acpi_ac_blacklist[i].hrv)) {
					     acpi_ac_blacklist[i].hrv)) {
@@ -432,6 +457,7 @@ static int __init acpi_ac_init(void)
					acpi_ac_blacklist[i].hid);
					acpi_ac_blacklist[i].hid);
				return -ENODEV;
				return -ENODEV;
			}
			}
	}


#ifdef CONFIG_ACPI_PROCFS_POWER
#ifdef CONFIG_ACPI_PROCFS_POWER
	acpi_ac_dir = acpi_lock_ac_dir();
	acpi_ac_dir = acpi_lock_ac_dir();
+47 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@
 */
 */


#include <linux/clk-provider.h>
#include <linux/clk-provider.h>
#include <linux/platform_data/clk-st.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_domain.h>
#include <linux/clkdev.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
#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 = {
static const struct apd_device_desc cz_i2c_desc = {
	.setup = acpi_apd_setup,
	.setup = acpi_apd_setup,
	.fixed_clk_rate = 133000000,
	.fixed_clk_rate = 133000000,
@@ -94,6 +136,10 @@ static const struct apd_device_desc cz_uart_desc = {
	.fixed_clk_rate = 48000000,
	.fixed_clk_rate = 48000000,
	.properties = uart_properties,
	.properties = uart_properties,
};
};

static const struct apd_device_desc st_misc_desc = {
	.setup = st_misc_setup,
};
#endif
#endif


#ifdef CONFIG_ARM64
#ifdef CONFIG_ARM64
@@ -179,6 +225,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
	{ "AMD0020", APD_ADDR(cz_uart_desc) },
	{ "AMD0020", APD_ADDR(cz_uart_desc) },
	{ "AMDI0020", APD_ADDR(cz_uart_desc) },
	{ "AMDI0020", APD_ADDR(cz_uart_desc) },
	{ "AMD0030", },
	{ "AMD0030", },
	{ "AMD0040", APD_ADDR(st_misc_desc)},
#endif
#endif
#ifdef CONFIG_ARM64
#ifdef CONFIG_ARM64
	{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
	{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
+5 −1
Original line number Original line Diff line number Diff line
@@ -69,6 +69,10 @@ ACPI_MODULE_NAME("acpi_lpss");
#define LPSS_SAVE_CTX			BIT(4)
#define LPSS_SAVE_CTX			BIT(4)
#define LPSS_NO_D3_DELAY		BIT(5)
#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_private_data;


struct lpss_device_desc {
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"))
	if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1"))
		return;
		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));
		pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
}
}


+45 −27
Original line number Original line Diff line number Diff line
@@ -12,35 +12,51 @@
#define pr_fmt(fmt) "ACPI: watchdog: " fmt
#define pr_fmt(fmt) "ACPI: watchdog: " fmt


#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>


#include "internal.h"
#include "internal.h"


static const struct dmi_system_id acpi_watchdog_skip[] = {
#ifdef CONFIG_RTC_MC146818_LIB
	{
#include <linux/mc146818rtc.h>

/*
/*
		 * On Lenovo Z50-70 there are two issues with the WDAT
 * There are several systems where the WDAT table is accessing RTC SRAM to
		 * table. First some of the instructions use RTC SRAM
 * store persistent information. This does not work well with the Linux RTC
		 * to store persistent information. This does not work well
 * driver so on those systems we skip WDAT driver and prefer iTCO_wdt
		 * with Linux RTC driver. Second, more important thing is
 * instead.
		 * 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.
 * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033.
 */
 */
		.ident = "Lenovo Z50-70",
static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
		.matches = {
{
			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
	const struct acpi_wdat_entry *entries;
			DMI_MATCH(DMI_PRODUCT_NAME, "20354"),
	int i;
			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"),

		},
	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)
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)
	if (acpi_disabled)
		return NULL;
		return NULL;


	if (dmi_check_system(acpi_watchdog_skip))
		return NULL;

	status = acpi_get_table(ACPI_SIG_WDAT, 0,
	status = acpi_get_table(ACPI_SIG_WDAT, 0,
				(struct acpi_table_header **)&wdat);
				(struct acpi_table_header **)&wdat);
	if (ACPI_FAILURE(status)) {
	if (ACPI_FAILURE(status)) {
@@ -60,6 +73,11 @@ static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
		return NULL;
		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;
	return wdat;
}
}


Loading