Merge tag 'acpi-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Jun 2018 17:08:27 +0000 (10:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Jun 2018 17:08:27 +0000 (10:08 -0700)
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
  ...

36 files changed:
Documentation/acpi/cppc_sysfs.txt [new file with mode: 0644]
drivers/acpi/ac.c
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_watchdog.c
drivers/acpi/acpica/acapps.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/dbnames.c
drivers/acpi/acpica/dbtest.c
drivers/acpi/acpica/dswscope.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/rsdump.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/utbuffer.c
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utobject.c
drivers/acpi/acpica/utprint.c
drivers/acpi/acpica/utstring.c
drivers/acpi/battery.c
drivers/acpi/cppc_acpi.c
drivers/acpi/reboot.c
drivers/acpi/tables.c
drivers/clk/x86/Makefile
drivers/clk/x86/clk-st.c [new file with mode: 0644]
drivers/cpufreq/cppc_cpufreq.c
drivers/mailbox/pcc.c
include/acpi/acnames.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/cppc_acpi.h
include/acpi/platform/aclinux.h
include/acpi/platform/aclinuxex.h
include/linux/acpi.h
include/linux/platform_data/clk-st.h [new file with mode: 0644]

diff --git a/Documentation/acpi/cppc_sysfs.txt b/Documentation/acpi/cppc_sysfs.txt
new file mode 100644 (file)
index 0000000..f20fb44
--- /dev/null
@@ -0,0 +1,69 @@
+
+       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
index 84fdfa70920a2ce6cc7e0896750405e8ff2d589e..cdd3136829f15182464b865be099c141a8dd4f67 100644 (file)
@@ -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();
index d553b00879470f4a3705bca4d9df5635bdbe6412..2664452fa112630d254106099bc8e3026a2ecb7b 100644 (file)
@@ -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) },
index 2bcffec8dbf0d612b41e17590b503b75bcab622e..cb6ac5c65c2e4c97f4cc9432d8d701b9e3b3f0da 100644 (file)
@@ -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));
 }
 
index 4bde16fb97d8818f59e893adf9bb642fed5f9d5c..95600309ce420a21d32f50f6b8095a6fe335fb78 100644 (file)
 #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;
 }
 
index a2a85122fafeeb1bf6ec3813fa845cfa8da63a24..5a9c2febc0fb9df68e034137af4c05255a87da61 100644 (file)
@@ -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
index 0bc550072a21426815ba17dcb5ea9622b9a392b8..1e6204518496cffb6f02953d1ee1b3a12561f22a 100644 (file)
@@ -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 */
index 170802c62179b58da5a960ec62f126fb2def9249..dc94de91033e653c004c9dc499f4bc52cae94773 100644 (file)
@@ -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 */
 
index 3892680a5258ab06ee13f1de3c5508de119a65a9..8a5462439a97058358f3912b7fbc2d88b70b2b42 100644 (file)
@@ -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,
                                      &param_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);
                }
 
index d1422f984f6e3db23cd9114f650ba38b001e43d0..7592176a8fa2eba4f3a288575a379c63cae088ef 100644 (file)
@@ -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);
index 27a86ad55b58617cc6393910f54dbc3f75a6ff6e..3de794bcf8fa8c1bf906ca5ac6f4d422ec5e0faa 100644 (file)
@@ -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;
index 5d1396870bd0b421d42b21bb8b425f62b6d20250..6e39a771a56efb7021bd9f07654b3ca5dbdd8d9c 100644 (file)
@@ -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);
 }
 
index b12a0b1cd9ceda6717eddf6c1e00c1f426ef831e..6601e71b45e332aa0591218353de7bab43292637 100644 (file)
@@ -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]);
index c5085b7ae8c962b4b24e2cf90e0fbe84c69fbbcf..5f8e7b561c90b3532757fc653a7660ec4faba570 100644 (file)
@@ -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".
  *
  ******************************************************************************/
index 148aeb84e561067e5a89b19215a75bc66b203309..fffa6f5ae59e8152e898a61b2e28daca8f0f88d3 100644 (file)
@@ -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 */
 
index d2d93e388f40873bb573d7737b2551f6c7d8e31a..2e465e6a0ab65a30f462a8aedff78a54d9e6df99 100644 (file)
@@ -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 */
index 5b78fe08d7d70223da937fb22ac201e8125a8969..ae6d8cc18cec790c0112f4e311c0e45c67445428 100644 (file)
@@ -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:
index 35ffd8d51c6541a3034764d2015ec1c4d538a4a3..a98c334c3bb7585f80851d7b61aba2fada13ae54 100644 (file)
@@ -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':
 
index bd57a77bbcb2ef87698f874e9286a47efa3dca6f..5bef0b0594062fc76195e96dfd9aa09f58bc99a5 100644 (file)
@@ -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;
        }
 
index 76550689ce10ff1cbd7eadc17dc1a5ce8038cb0f..b0113a5802a3c073f5787de456bc601f0f8c11cd 100644 (file)
@@ -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)
index 735c74a4cbdb30250a26a17bfa8258b276613869..d9ce4b162e2ce0533039cbe2d5ef4704ecb24642 100644 (file)
@@ -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))
+       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 (chk_err_bit && (status & PCC_ERROR_MASK))
+                       ret = -EIO;
+       }
+
+       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);
index 71769fd687b202b385cdcd67de20143d138ec8a7..6fa9c2a4cfe9d31f31ee129128995733a1b7a3be 100644 (file)
@@ -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);
index 849c4fb19b033f54a93db411d150e5fce9b6efc6..4a3410aa65408f3597799580e8c3e5db0b59c0cb 100644 (file)
@@ -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?)
index 1367afb03858b843e26d265495282237c4887dab..00303bc05415ac0a5b91e1dd059984b0ea9a96b6 100644 (file)
@@ -1,3 +1,4 @@
+obj-$(CONFIG_PMC_ATOM)         += clk-pmc-atom.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
 clk-x86-lpss-objs              := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
-obj-$(CONFIG_PMC_ATOM)         += clk-pmc-atom.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
new file mode 100644 (file)
index 0000000..fb62f39
--- /dev/null
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT
+/*
+ * clock framework for AMD Stoney based clocks
+ *
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_data/clk-st.h>
+#include <linux/platform_device.h>
+
+/* Clock Driving Strength 2 register */
+#define CLKDRVSTR2     0x28
+/* Clock Control 1 register */
+#define MISCCLKCNTL1   0x40
+/* Auxiliary clock1 enable bit */
+#define OSCCLKENB      2
+/* 25Mhz auxiliary output clock freq bit */
+#define OSCOUT1CLK25MHZ        16
+
+#define ST_CLK_48M     0
+#define ST_CLK_25M     1
+#define ST_CLK_MUX     2
+#define ST_CLK_GATE    3
+#define ST_MAX_CLKS    4
+
+static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
+static struct clk_hw *hws[ST_MAX_CLKS];
+
+static int st_clk_probe(struct platform_device *pdev)
+{
+       struct st_clk_data *st_data;
+
+       st_data = dev_get_platdata(&pdev->dev);
+       if (!st_data || !st_data->base)
+               return -EINVAL;
+
+       hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
+                                                    48000000);
+       hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
+                                                    25000000);
+
+       hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+               clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+               0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+
+       clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
+
+       hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
+               0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+               CLK_GATE_SET_TO_DISABLE, NULL);
+
+       clk_hw_register_clkdev(hws[ST_CLK_GATE], "oscout1", NULL);
+
+       return 0;
+}
+
+static int st_clk_remove(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 0; i < ST_MAX_CLKS; i++)
+               clk_hw_unregister(hws[i]);
+       return 0;
+}
+
+static struct platform_driver st_clk_driver = {
+       .driver = {
+               .name = "clk-st",
+               .suppress_bind_attrs = true,
+       },
+       .probe = st_clk_probe,
+       .remove = st_clk_remove,
+};
+builtin_platform_driver(st_clk_driver);
index b15115a48775cb9c6b18cc94b1aa5decd67667c9..3464580ac3ca4d4284c704c81676a3fad9da93fb 100644 (file)
@@ -42,9 +42,6 @@
  */
 static struct cppc_cpudata **all_cpu_data;
 
-/* Capture the max KHz from DMI */
-static u64 cppc_dmi_max_khz;
-
 /* Callback function used to retrieve the max frequency from DMI */
 static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
 {
@@ -75,6 +72,64 @@ static u64 cppc_get_dmi_max_khz(void)
        return (1000 * mhz);
 }
 
+/*
+ * If CPPC lowest_freq and nominal_freq registers are exposed then we can
+ * use them to convert perf to freq and vice versa
+ *
+ * If the perf/freq point lies between Nominal and Lowest, we can treat
+ * (Low perf, Low freq) and (Nom Perf, Nom freq) as 2D co-ordinates of a line
+ * and extrapolate the rest
+ * For perf/freq > Nominal, we use the ratio perf:freq at Nominal for conversion
+ */
+static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu,
+                                       unsigned int perf)
+{
+       static u64 max_khz;
+       struct cppc_perf_caps *caps = &cpu->perf_caps;
+       u64 mul, div;
+
+       if (caps->lowest_freq && caps->nominal_freq) {
+               if (perf >= caps->nominal_perf) {
+                       mul = caps->nominal_freq;
+                       div = caps->nominal_perf;
+               } else {
+                       mul = caps->nominal_freq - caps->lowest_freq;
+                       div = caps->nominal_perf - caps->lowest_perf;
+               }
+       } else {
+               if (!max_khz)
+                       max_khz = cppc_get_dmi_max_khz();
+               mul = max_khz;
+               div = cpu->perf_caps.highest_perf;
+       }
+       return (u64)perf * mul / div;
+}
+
+static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu,
+                                       unsigned int freq)
+{
+       static u64 max_khz;
+       struct cppc_perf_caps *caps = &cpu->perf_caps;
+       u64  mul, div;
+
+       if (caps->lowest_freq && caps->nominal_freq) {
+               if (freq >= caps->nominal_freq) {
+                       mul = caps->nominal_perf;
+                       div = caps->nominal_freq;
+               } else {
+                       mul = caps->lowest_perf;
+                       div = caps->lowest_freq;
+               }
+       } else {
+               if (!max_khz)
+                       max_khz = cppc_get_dmi_max_khz();
+               mul = cpu->perf_caps.highest_perf;
+               div = max_khz;
+       }
+
+       return (u64)freq * mul / div;
+}
+
 static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
                unsigned int target_freq,
                unsigned int relation)
@@ -86,7 +141,7 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
 
        cpu = all_cpu_data[policy->cpu];
 
-       desired_perf = (u64)target_freq * cpu->perf_caps.highest_perf / cppc_dmi_max_khz;
+       desired_perf = cppc_cpufreq_khz_to_perf(cpu, target_freq);
        /* Return if it is exactly the same perf */
        if (desired_perf == cpu->perf_ctrls.desired_perf)
                return ret;
@@ -186,24 +241,24 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return ret;
        }
 
-       cppc_dmi_max_khz = cppc_get_dmi_max_khz();
+       /* Convert the lowest and nominal freq from MHz to KHz */
+       cpu->perf_caps.lowest_freq *= 1000;
+       cpu->perf_caps.nominal_freq *= 1000;
 
        /*
         * Set min to lowest nonlinear perf to avoid any efficiency penalty (see
         * Section 8.4.7.1.1.5 of ACPI 6.1 spec)
         */
-       policy->min = cpu->perf_caps.lowest_nonlinear_perf * cppc_dmi_max_khz /
-               cpu->perf_caps.highest_perf;
-       policy->max = cppc_dmi_max_khz;
+       policy->min = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_nonlinear_perf);
+       policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
 
        /*
         * Set cpuinfo.min_freq to Lowest to make the full range of performance
         * available if userspace wants to use any perf between lowest & lowest
         * nonlinear perf
         */
-       policy->cpuinfo.min_freq = cpu->perf_caps.lowest_perf * cppc_dmi_max_khz /
-               cpu->perf_caps.highest_perf;
-       policy->cpuinfo.max_freq = cppc_dmi_max_khz;
+       policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_perf);
+       policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
 
        policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num);
        policy->shared_type = cpu->shared_type;
@@ -229,7 +284,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
        cpu->cur_policy = policy;
 
        /* Set policy->cur to max now. The governors will adjust later. */
-       policy->cur = cppc_dmi_max_khz;
+       policy->cur = cppc_cpufreq_perf_to_khz(cpu,
+                                       cpu->perf_caps.highest_perf);
        cpu->perf_ctrls.desired_perf = cpu->perf_caps.highest_perf;
 
        ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls);
index 3ef7f036ceeaac1eafb5a3b0592c79bfeb37ea7e..fc3c237daef24ec6e96ec30319361a9385a4a891 100644 (file)
@@ -373,33 +373,24 @@ static const struct mbox_chan_ops pcc_chan_ops = {
 };
 
 /**
- * parse_pcc_subspace - Parse the PCC table and verify PCC subspace
- *             entries. There should be one entry per PCC client.
+ * parse_pcc_subspaces -- Count PCC subspaces defined
  * @header: Pointer to the ACPI subtable header under the PCCT.
  * @end: End of subtable entry.
  *
- * Return: 0 for Success, else errno.
+ * Return: If we find a PCC subspace entry of a valid type, return 0.
+ *     Otherwise, return -EINVAL.
  *
  * This gets called for each entry in the PCC table.
  */
 static int parse_pcc_subspace(struct acpi_subtable_header *header,
                const unsigned long end)
 {
-       struct acpi_pcct_hw_reduced *pcct_ss;
-
-       if (pcc_mbox_ctrl.num_chans <= MAX_PCC_SUBSPACES) {
-               pcct_ss = (struct acpi_pcct_hw_reduced *) header;
+       struct acpi_pcct_subspace *ss = (struct acpi_pcct_subspace *) header;
 
-               if ((pcct_ss->header.type !=
-                               ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE)
-                   && (pcct_ss->header.type !=
-                               ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2)) {
-                       pr_err("Incorrect PCC Subspace type detected\n");
-                       return -EINVAL;
-               }
-       }
+       if (ss->header.type < ACPI_PCCT_TYPE_RESERVED)
+               return 0;
 
-       return 0;
+       return -EINVAL;
 }
 
 /**
@@ -449,8 +440,8 @@ static int __init acpi_pcc_probe(void)
        struct acpi_table_header *pcct_tbl;
        struct acpi_subtable_header *pcct_entry;
        struct acpi_table_pcct *acpi_pcct_tbl;
+       struct acpi_subtable_proc proc[ACPI_PCCT_TYPE_RESERVED];
        int count, i, rc;
-       int sum = 0;
        acpi_status status = AE_OK;
 
        /* Search for PCCT */
@@ -459,43 +450,41 @@ static int __init acpi_pcc_probe(void)
        if (ACPI_FAILURE(status) || !pcct_tbl)
                return -ENODEV;
 
-       count = acpi_table_parse_entries(ACPI_SIG_PCCT,
-                       sizeof(struct acpi_table_pcct),
-                       ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
-                       parse_pcc_subspace, MAX_PCC_SUBSPACES);
-       sum += (count > 0) ? count : 0;
-
-       count = acpi_table_parse_entries(ACPI_SIG_PCCT,
-                       sizeof(struct acpi_table_pcct),
-                       ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2,
-                       parse_pcc_subspace, MAX_PCC_SUBSPACES);
-       sum += (count > 0) ? count : 0;
+       /* Set up the subtable handlers */
+       for (i = ACPI_PCCT_TYPE_GENERIC_SUBSPACE;
+            i < ACPI_PCCT_TYPE_RESERVED; i++) {
+               proc[i].id = i;
+               proc[i].count = 0;
+               proc[i].handler = parse_pcc_subspace;
+       }
 
-       if (sum == 0 || sum >= MAX_PCC_SUBSPACES) {
-               pr_err("Error parsing PCC subspaces from PCCT\n");
+       count = acpi_table_parse_entries_array(ACPI_SIG_PCCT,
+                       sizeof(struct acpi_table_pcct), proc,
+                       ACPI_PCCT_TYPE_RESERVED, MAX_PCC_SUBSPACES);
+       if (count == 0 || count > MAX_PCC_SUBSPACES) {
+               pr_warn("Invalid PCCT: %d PCC subspaces\n", count);
                return -EINVAL;
        }
 
-       pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
-                       sum, GFP_KERNEL);
+       pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * count, GFP_KERNEL);
        if (!pcc_mbox_channels) {
                pr_err("Could not allocate space for PCC mbox channels\n");
                return -ENOMEM;
        }
 
-       pcc_doorbell_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
+       pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
        if (!pcc_doorbell_vaddr) {
                rc = -ENOMEM;
                goto err_free_mbox;
        }
 
-       pcc_doorbell_ack_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
+       pcc_doorbell_ack_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
        if (!pcc_doorbell_ack_vaddr) {
                rc = -ENOMEM;
                goto err_free_db_vaddr;
        }
 
-       pcc_doorbell_irq = kcalloc(sum, sizeof(int), GFP_KERNEL);
+       pcc_doorbell_irq = kcalloc(count, sizeof(int), GFP_KERNEL);
        if (!pcc_doorbell_irq) {
                rc = -ENOMEM;
                goto err_free_db_ack_vaddr;
@@ -509,18 +498,24 @@ static int __init acpi_pcc_probe(void)
        if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
                pcc_mbox_ctrl.txdone_irq = true;
 
-       for (i = 0; i < sum; i++) {
+       for (i = 0; i < count; i++) {
                struct acpi_generic_address *db_reg;
-               struct acpi_pcct_hw_reduced *pcct_ss;
+               struct acpi_pcct_subspace *pcct_ss;
                pcc_mbox_channels[i].con_priv = pcct_entry;
 
-               pcct_ss = (struct acpi_pcct_hw_reduced *) pcct_entry;
+               if (pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
+                   pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
+                       struct acpi_pcct_hw_reduced *pcct_hrss;
+
+                       pcct_hrss = (struct acpi_pcct_hw_reduced *) pcct_entry;
 
-               if (pcc_mbox_ctrl.txdone_irq) {
-                       rc = pcc_parse_subspace_irq(i, pcct_ss);
-                       if (rc < 0)
-                               goto err;
+                       if (pcc_mbox_ctrl.txdone_irq) {
+                               rc = pcc_parse_subspace_irq(i, pcct_hrss);
+                               if (rc < 0)
+                                       goto err;
+                       }
                }
+               pcct_ss = (struct acpi_pcct_subspace *) pcct_entry;
 
                /* If doorbell is in system memory cache the virt address */
                db_reg = &pcct_ss->doorbell_register;
@@ -531,7 +526,7 @@ static int __init acpi_pcc_probe(void)
                        ((unsigned long) pcct_entry + pcct_entry->length);
        }
 
-       pcc_mbox_ctrl.num_chans = sum;
+       pcc_mbox_ctrl.num_chans = count;
 
        pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);
 
index 7b289dd00a30f4ab72001d3dd37b5f67e4c2a2e4..6f69a4f638f8f8130fe0feab4025290f46a113fc 100644 (file)
 /* Definitions of the predefined namespace names  */
 
 #define ACPI_UNKNOWN_NAME       (u32) 0x3F3F3F3F       /* Unknown name is "????" */
-#define ACPI_ROOT_NAME          (u32) 0x5F5F5F5C       /* Root name is    "\___" */
-
 #define ACPI_PREFIX_MIXED       (u32) 0x69706341       /* "Acpi" */
 #define ACPI_PREFIX_LOWER       (u32) 0x69706361       /* "acpi" */
 
+/* Root name stuff */
+
+#define ACPI_ROOT_NAME          (u32) 0x5F5F5F5C       /* Root name is    "\___" */
+#define ACPI_ROOT_PATHNAME      "\\___"
+#define ACPI_NAMESPACE_ROOT     "Namespace Root"
 #define ACPI_NS_ROOT_PATH       "\\"
 
 #endif                         /* __ACNAMES_H__  */
index 540d35f06ad6eb0b743db06b44a1c5a36ccfe2dd..eb1f21af75563b855835fdc0b3f1aaa8e011ad50 100644 (file)
@@ -97,6 +97,27 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle);
 void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags);
 #endif
 
+/*
+ * RAW spinlock primitives. If the OS does not provide them, fallback to
+ * spinlock primitives
+ */
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_raw_lock
+# define acpi_os_create_raw_lock(out_handle)   acpi_os_create_lock(out_handle)
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock
+# define acpi_os_delete_raw_lock(handle)       acpi_os_delete_lock(handle)
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock
+# define acpi_os_acquire_raw_lock(handle)      acpi_os_acquire_lock(handle)
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock
+# define acpi_os_release_raw_lock(handle, flags)       \
+       acpi_os_release_lock(handle, flags)
+#endif
+
 /*
  * Semaphore primitives
  */
index c01d790c17c2e4d218d2b6e5d2ff7af8622d9b5f..77d71bd1be39abcc4e1d4528f26158b130fd1615 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20180313
+#define ACPI_CA_VERSION                 0x20180508
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index 1c530f95dc3476394a02feb610a6066e574b7716..2b1bafa197c0d68bc094949818695c2b29ae6c64 100644 (file)
@@ -245,6 +245,10 @@ typedef u64 acpi_physical_address;
 #define acpi_spinlock                   void *
 #endif
 
+#ifndef acpi_raw_spinlock
+#define acpi_raw_spinlock              acpi_spinlock
+#endif
+
 #ifndef acpi_semaphore
 #define acpi_semaphore                  void *
 #endif
index 2010c0516f273f05185d8131b363996c37d68903..8e0b8250a139975ffd49cea4e2ce724ba464bd9d 100644 (file)
 #include <acpi/pcc.h>
 #include <acpi/processor.h>
 
-/* Only support CPPCv2 for now. */
-#define CPPC_NUM_ENT   21
-#define CPPC_REV       2
+/* Support CPPCv2 and CPPCv3  */
+#define CPPC_V2_REV    2
+#define CPPC_V3_REV    3
+#define CPPC_V2_NUM_ENT        21
+#define CPPC_V3_NUM_ENT        23
 
 #define PCC_CMD_COMPLETE_MASK  (1 << 0)
 #define PCC_ERROR_MASK         (1 << 2)
 
-#define MAX_CPC_REG_ENT 19
+#define MAX_CPC_REG_ENT 21
 
 /* CPPC specific PCC commands. */
 #define        CMD_READ 0
@@ -91,6 +93,8 @@ enum cppc_regs {
        AUTO_ACT_WINDOW,
        ENERGY_PERF,
        REFERENCE_PERF,
+       LOWEST_FREQ,
+       NOMINAL_FREQ,
 };
 
 /*
@@ -104,6 +108,8 @@ struct cppc_perf_caps {
        u32 nominal_perf;
        u32 lowest_perf;
        u32 lowest_nonlinear_perf;
+       u32 lowest_freq;
+       u32 nominal_freq;
 };
 
 struct cppc_perf_ctrls {
index a0b232703302dae86f535ef942c770ecd85516bf..7451b3bca83a842bf9d632f1f4cd0898882daafe 100644 (file)
 
 #define acpi_cache_t                        struct kmem_cache
 #define acpi_spinlock                       spinlock_t *
+#define acpi_raw_spinlock                   raw_spinlock_t *
 #define acpi_cpu_flags                      unsigned long
 
 /* Use native linux version of acpi_os_allocate_zeroed */
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_raw_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock
 
 /*
  * OSL interfaces used by debugger/disassembler
index 7e81475fe03486374502c0f396dd8cf87286cb8e..d754a1b1272122db181641c66510ffa70aea55a7 100644 (file)
@@ -90,6 +90,36 @@ static inline acpi_thread_id acpi_os_get_thread_id(void)
                lock ? AE_OK : AE_NO_MEMORY; \
        })
 
+
+#define acpi_os_create_raw_lock(__handle) \
+       ({ \
+               raw_spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
+               if (lock) { \
+                       *(__handle) = lock; \
+                       raw_spin_lock_init(*(__handle)); \
+               } \
+               lock ? AE_OK : AE_NO_MEMORY; \
+       })
+
+static inline acpi_cpu_flags acpi_os_acquire_raw_lock(acpi_raw_spinlock lockp)
+{
+       acpi_cpu_flags flags;
+
+       raw_spin_lock_irqsave(lockp, flags);
+       return flags;
+}
+
+static inline void acpi_os_release_raw_lock(acpi_raw_spinlock lockp,
+                                           acpi_cpu_flags flags)
+{
+       raw_spin_unlock_irqrestore(lockp, flags);
+}
+
+static inline void acpi_os_delete_raw_lock(acpi_raw_spinlock handle)
+{
+       ACPI_FREE(handle);
+}
+
 static inline u8 acpi_os_readable(void *pointer, acpi_size length)
 {
        return TRUE;
index c01675b3d93f45726ee1deec60836fbc7e19a658..fd0ea6af9e36c47ab2eee9cf3f44c4759da258f3 100644 (file)
@@ -578,6 +578,7 @@ int acpi_match_platform_list(const struct acpi_platform_list *plat);
 
 extern void acpi_early_init(void);
 extern void acpi_subsystem_init(void);
+extern void arch_post_acpi_subsys_init(void);
 
 extern int acpi_nvs_register(__u64 start, __u64 size);
 
diff --git a/include/linux/platform_data/clk-st.h b/include/linux/platform_data/clk-st.h
new file mode 100644 (file)
index 0000000..7cdb6a4
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * clock framework for AMD Stoney based clock
+ *
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ */
+
+#ifndef __CLK_ST_H
+#define __CLK_ST_H
+
+#include <linux/compiler.h>
+
+struct st_clk_data {
+       void __iomem *base;
+};
+
+#endif /* __CLK_ST_H */