From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============3955309640872037530==" MIME-Version: 1.0 From: Ross Zwisler Subject: [Devel] [PATCH v3 2/3] hmat: add heterogeneous memory sysfs support Date: Wed, 13 Dec 2017 19:10:18 -0700 Message-ID: <20171214021019.13579-3-ross.zwisler@linux.intel.com> In-Reply-To: 20171214021019.13579-1-ross.zwisler@linux.intel.com List-ID: To: devel@acpica.org --===============3955309640872037530== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Add a new sysfs subsystem, /sys/devices/system/hmat, which surfaces information about memory initiators and memory targets to the user. These initiators and targets are described by the ACPI SRAT and HMAT tables. A "memory initiator" in this case is a NUMA node containing one or more devices such as CPU or separate memory I/O devices that can initiate memory requests. A "memory target" is NUMA node containing at least one CPU-accessible physical address range. The key piece of information surfaced by this patch is the mapping between the ACPI table "proximity domain" numbers, held in the "firmware_id" attribute, and Linux NUMA node numbers. Every ACPI proximity domain will end up being a unique NUMA node in Linux, but the numbers may get reordered and Linux can create extra NUMA nodes that don't map back to ACPI proximity domains. The firmware_id value is needed if anyone ever wants to look at the ACPI HMAT and SRAT tables directly and make sense of how they map to NUMA nodes in Linux. Initiators are found at /sys/devices/system/hmat/mem_initX, and the attributes for a given initiator look like this: # tree mem_init0 mem_init0 =E2=94=9C=E2=94=80=E2=94=80 firmware_id =E2=94=9C=E2=94=80=E2=94=80 node0 -> ../../node/node0 =E2=94=9C=E2=94=80=E2=94=80 power =E2=94=82=C2=A0=C2=A0 =E2=94=9C=E2=94=80=E2=94=80 async =E2=94=82=C2=A0=C2=A0 ... =E2=94=9C=E2=94=80=E2=94=80 subsystem -> ../../../../bus/hmat =E2=94=94=E2=94=80=E2=94=80 uevent Where "mem_init0" on my system represents the CPU acting as a memory initiator at NUMA node 0. Users can discover which CPUs are part of this memory initiator by following the node0 symlink and looking at cpumap, cpulist and the cpu* symlinks. Targets are found at /sys/devices/system/hmat/mem_tgtX, and the attributes for a given target look like this: # tree mem_tgt2 mem_tgt2 =E2=94=9C=E2=94=80=E2=94=80 firmware_id =E2=94=9C=E2=94=80=E2=94=80 is_cached =E2=94=9C=E2=94=80=E2=94=80 node2 -> ../../node/node2 =E2=94=9C=E2=94=80=E2=94=80 power =E2=94=82=C2=A0=C2=A0 =E2=94=9C=E2=94=80=E2=94=80 async =E2=94=82=C2=A0=C2=A0 ... =E2=94=9C=E2=94=80=E2=94=80 subsystem -> ../../../../bus/hmat =E2=94=94=E2=94=80=E2=94=80 uevent Users can discover information about the memory owned by this memory target by following the node2 symlink and looking at meminfo, vmstat and at the memory* memory section symlinks. Signed-off-by: Ross Zwisler --- MAINTAINERS | 6 + drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 7 + drivers/acpi/hmat/Makefile | 2 + drivers/acpi/hmat/core.c | 536 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/acpi/hmat/hmat.h | 47 ++++ drivers/acpi/hmat/initiator.c | 43 ++++ drivers/acpi/hmat/target.c | 55 +++++ 9 files changed, 698 insertions(+) create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/core.c create mode 100644 drivers/acpi/hmat/hmat.h create mode 100644 drivers/acpi/hmat/initiator.c create mode 100644 drivers/acpi/hmat/target.c diff --git a/MAINTAINERS b/MAINTAINERS index 82ad0eabce4f..64ebec0708de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6366,6 +6366,12 @@ S: Supported F: drivers/scsi/hisi_sas/ F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt = +HMAT - ACPI Heterogeneous Memory Attribute Table Support +M: Ross Zwisler +L: linux-mm(a)kvack.org +S: Supported +F: drivers/acpi/hmat/ + HMM - Heterogeneous Memory Management M: J=C3=A9r=C3=B4me Glisse L: linux-mm(a)kvack.org diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 46505396869e..21cdd1288430 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -466,6 +466,7 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. = source "drivers/acpi/nfit/Kconfig" +source "drivers/acpi/hmat/Kconfig" = source "drivers/acpi/apei/Kconfig" source "drivers/acpi/dptf/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 41954a601989..ed5eab6b0412 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) +=3D processor.o obj-$(CONFIG_ACPI) +=3D container.o obj-$(CONFIG_ACPI_THERMAL) +=3D thermal.o obj-$(CONFIG_ACPI_NFIT) +=3D nfit/ +obj-$(CONFIG_ACPI_HMAT) +=3D hmat/ obj-$(CONFIG_ACPI) +=3D acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) +=3D ioapic.o obj-$(CONFIG_ACPI_BATTERY) +=3D battery.o diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig new file mode 100644 index 000000000000..954ad4701005 --- /dev/null +++ b/drivers/acpi/hmat/Kconfig @@ -0,0 +1,7 @@ +config ACPI_HMAT + bool "ACPI Heterogeneous Memory Attribute Table Support" + depends on ACPI_NUMA + depends on SYSFS + help + Exports a sysfs representation of the ACPI Heterogeneous Memory + Attributes Table (HMAT). diff --git a/drivers/acpi/hmat/Makefile b/drivers/acpi/hmat/Makefile new file mode 100644 index 000000000000..edf4bcb1c97d --- /dev/null +++ b/drivers/acpi/hmat/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ACPI_HMAT) :=3D hmat.o +hmat-y :=3D core.o initiator.o target.o diff --git a/drivers/acpi/hmat/core.c b/drivers/acpi/hmat/core.c new file mode 100644 index 000000000000..61b90dadf84b --- /dev/null +++ b/drivers/acpi/hmat/core.c @@ -0,0 +1,536 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmat.h" + +static LIST_HEAD(target_list); +static LIST_HEAD(initiator_list); + +static bool bad_hmat; + +static int link_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + return sysfs_create_link(kobj, &node_devices[node]->dev.kobj, + kobject_name(&node_devices[node]->dev.kobj)); + return 0; +} + +static void remove_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + sysfs_remove_link(kobj, + kobject_name(&node_devices[node]->dev.kobj)); +} + +#define HMAT_CLASS_NAME "hmat" + +static struct bus_type hmat_subsys =3D { + /* + * .dev_name is set before device_register() based on the type of + * device we are registering. + */ + .name =3D HMAT_CLASS_NAME, +}; + +/* memory initiators */ +static void release_memory_initiator(struct device *dev) +{ + struct memory_initiator *init =3D to_memory_initiator(dev); + + list_del(&init->list); + kfree(init); +} + +static void __init remove_memory_initiator(struct memory_initiator *init) +{ + if (init->is_registered) { + remove_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); + device_unregister(&init->dev); + } else + release_memory_initiator(&init->dev); +} + +static int __init register_memory_initiator(struct memory_initiator *init) +{ + int ret; + + hmat_subsys.dev_name =3D "mem_init"; + init->dev.bus =3D &hmat_subsys; + init->dev.id =3D pxm_to_node(init->pxm); + init->dev.release =3D release_memory_initiator; + init->dev.groups =3D memory_initiator_attribute_groups; + + ret =3D device_register(&init->dev); + if (ret < 0) + return ret; + + init->is_registered =3D true; + return link_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); +} + +static struct memory_initiator * __init add_memory_initiator(int pxm) +{ + struct memory_initiator *init; + + if (pxm_to_node(pxm) =3D=3D NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", pxm); + bad_hmat =3D true; + return ERR_PTR(-EINVAL); + } + + /* + * Make sure we haven't already added an initiator for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (apic_id, etc), so we just use the data from the first table + * we see for a given proximity domain. + */ + list_for_each_entry(init, &initiator_list, list) + if (init->pxm =3D=3D pxm) + return 0; + + init =3D kzalloc(sizeof(*init), GFP_KERNEL); + if (!init) { + bad_hmat =3D true; + return ERR_PTR(-ENOMEM); + } + + init->pxm =3D pxm; + + list_add_tail(&init->list, &initiator_list); + return init; +} + +/* memory targets */ +static void release_memory_target(struct device *dev) +{ + struct memory_target *tgt =3D to_memory_target(dev); + + list_del(&tgt->list); + kfree(tgt); +} + +static void __init remove_memory_target(struct memory_target *tgt) +{ + if (tgt->is_registered) { + remove_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); + device_unregister(&tgt->dev); + } else + release_memory_target(&tgt->dev); +} + +static int __init register_memory_target(struct memory_target *tgt) +{ + int ret; + + if (!tgt->ma || !tgt->spa) { + pr_err("HMAT: Incomplete memory target found\n"); + return -EINVAL; + } + + hmat_subsys.dev_name =3D "mem_tgt"; + tgt->dev.bus =3D &hmat_subsys; + tgt->dev.id =3D pxm_to_node(tgt->ma->proximity_domain); + tgt->dev.release =3D release_memory_target; + tgt->dev.groups =3D memory_target_attribute_groups; + + ret =3D device_register(&tgt->dev); + if (ret < 0) + return ret; + + tgt->is_registered =3D true; + + return link_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); +} + +static int __init add_memory_target(struct acpi_srat_mem_affinity *ma) +{ + struct memory_target *tgt; + + if (pxm_to_node(ma->proximity_domain) =3D=3D NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", ma->proximity_domain); + bad_hmat =3D true; + return -EINVAL; + } + + /* + * Make sure we haven't already added a target for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (base_address, length), so we just use the data from the + * first table we see for a given proximity domain. + */ + list_for_each_entry(tgt, &target_list, list) + if (tgt->ma->proximity_domain =3D=3D ma->proximity_domain) + return 0; + + tgt =3D kzalloc(sizeof(*tgt), GFP_KERNEL); + if (!tgt) { + bad_hmat =3D true; + return -ENOMEM; + } + + tgt->ma =3D ma; + + list_add_tail(&tgt->list, &target_list); + return 0; +} + +/* ACPI parsing code, starting with the HMAT */ +static int __init hmat_noop_parse(struct acpi_table_header *table) +{ + /* real work done by the hmat_parse_* and srat_parse_* routines */ + return 0; +} + +static bool __init hmat_spa_matches_srat(struct acpi_hmat_address_range *s= pa, + struct acpi_srat_mem_affinity *ma) +{ + if (spa->physical_address_base !=3D ma->base_address || + spa->physical_address_length !=3D ma->length) + return false; + + return true; +} + +static void find_local_initiator(struct memory_target *tgt) +{ + struct memory_initiator *init; + + if (!(tgt->spa->flags & ACPI_HMAT_PROCESSOR_PD_VALID) || + pxm_to_node(tgt->spa->processor_PD) =3D=3D NUMA_NO_NODE) + return; + + list_for_each_entry(init, &initiator_list, list) { + if (init->pxm =3D=3D tgt->spa->processor_PD) { + tgt->local_init =3D init; + return; + } + } +} + +/* ACPI HMAT parsing routines */ +static int __init +hmat_parse_address_range(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_address_range *spa; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + spa =3D (struct acpi_hmat_address_range *)header; + if (!spa) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (spa->header.length !=3D sizeof(*spa)) { + pr_err("HMAT: Unexpected header length: %d\n", + spa->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if ((spa->flags & ACPI_HMAT_MEMORY_PD_VALID) && + spa->memory_PD =3D=3D tgt->ma->proximity_domain) { + /* + * We only add a single HMAT target per proximity + * domain so we wait for the one that matches the + * single SRAT memory affinity structure per PXM we + * saved in add_memory_target(). + */ + if (hmat_spa_matches_srat(spa, tgt->ma)) { + tgt->spa =3D spa; + find_local_initiator(tgt); + } + return 0; + } + } + + return 0; +err: + bad_hmat =3D true; + return -EINVAL; +} + +static int __init hmat_parse_cache(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_cache *cache; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + cache =3D (struct acpi_hmat_cache *)header; + if (!cache) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (cache->header.length < sizeof(*cache)) { + pr_err("HMAT: Unexpected header length: %d\n", + cache->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if (cache->memory_PD =3D=3D tgt->ma->proximity_domain) { + tgt->is_cached =3D true; + return 0; + } + } + + pr_err("HMAT: Couldn't find cached target PXM %d\n", cache->memory_PD); +err: + bad_hmat =3D true; + return -EINVAL; +} + +/* + * SRAT parsing. We use srat_disabled() and pxm_to_node() so we don't redo + * any of the SRAT sanity checking done in drivers/acpi/numa.c. + */ +static int __init +srat_parse_processor_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_cpu_affinity *cpu; + struct memory_initiator *init; + u32 pxm; + + if (bad_hmat) + return 0; + + cpu =3D (struct acpi_srat_cpu_affinity *)header; + if (!cpu) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat =3D true; + return -EINVAL; + } + + pxm =3D cpu->proximity_domain_lo; + if (acpi_srat_revision >=3D 2) + pxm |=3D *((unsigned int *)cpu->proximity_domain_hi) << 8; + + if (!(cpu->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init =3D add_memory_initiator(pxm); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->cpu =3D cpu; + return 0; +} + +static int __init +srat_parse_x2apic_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + x2apic =3D (struct acpi_srat_x2apic_cpu_affinity *)header; + if (!x2apic) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat =3D true; + return -EINVAL; + } + + if (!(x2apic->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init =3D add_memory_initiator(x2apic->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->x2apic =3D x2apic; + return 0; +} + +static int __init +srat_parse_gicc_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_gicc_affinity *gicc; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + gicc =3D (struct acpi_srat_gicc_affinity *)header; + if (!gicc) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat =3D true; + return -EINVAL; + } + + if (!(gicc->flags & ACPI_SRAT_GICC_ENABLED)) + return 0; + + init =3D add_memory_initiator(gicc->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->gicc =3D gicc; + return 0; +} + +static int __init +srat_parse_memory_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_mem_affinity *ma; + + if (bad_hmat) + return 0; + + ma =3D (struct acpi_srat_mem_affinity *)header; + if (!ma) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat =3D true; + return -EINVAL; + } + + if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) + return 0; + + return add_memory_target(ma); +} + +/* + * Remove our sysfs entries, unregister our devices and free allocated mem= ory. + */ +static void hmat_cleanup(void) +{ + struct memory_initiator *init, *init_iter; + struct memory_target *tgt, *tgt_iter; + + list_for_each_entry_safe(tgt, tgt_iter, &target_list, list) + remove_memory_target(tgt); + + list_for_each_entry_safe(init, init_iter, &initiator_list, list) + remove_memory_initiator(init); +} + +static int __init hmat_init(void) +{ + struct acpi_table_header *tbl; + struct memory_initiator *init; + struct memory_target *tgt; + acpi_status status =3D AE_OK; + int ret; + + if (srat_disabled()) + return 0; + + /* + * We take a permanent reference to both the HMAT and SRAT in ACPI + * memory so we can keep pointers to their subtables. These tables + * already had references on them which would never be released, taken + * by acpi_sysfs_init(), so this shouldn't negatively impact anything. + */ + status =3D acpi_get_table(ACPI_SIG_SRAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + status =3D acpi_get_table(ACPI_SIG_HMAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + ret =3D subsys_system_register(&hmat_subsys, NULL); + if (ret) + return ret; + + if (!acpi_table_parse(ACPI_SIG_SRAT, hmat_noop_parse)) { + struct acpi_subtable_proc srat_proc[4]; + + memset(srat_proc, 0, sizeof(srat_proc)); + srat_proc[0].id =3D ACPI_SRAT_TYPE_CPU_AFFINITY; + srat_proc[0].handler =3D srat_parse_processor_affinity; + srat_proc[1].id =3D ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; + srat_proc[1].handler =3D srat_parse_x2apic_affinity; + srat_proc[2].id =3D ACPI_SRAT_TYPE_GICC_AFFINITY; + srat_proc[2].handler =3D srat_parse_gicc_affinity; + srat_proc[3].id =3D ACPI_SRAT_TYPE_MEMORY_AFFINITY; + srat_proc[3].handler =3D srat_parse_memory_affinity; + + acpi_table_parse_entries_array(ACPI_SIG_SRAT, + sizeof(struct acpi_table_srat), + srat_proc, ARRAY_SIZE(srat_proc), 0); + } + + if (!acpi_table_parse(ACPI_SIG_HMAT, hmat_noop_parse)) { + struct acpi_subtable_proc hmat_proc[2]; + + memset(hmat_proc, 0, sizeof(hmat_proc)); + hmat_proc[0].id =3D ACPI_HMAT_TYPE_ADDRESS_RANGE; + hmat_proc[0].handler =3D hmat_parse_address_range; + hmat_proc[1].id =3D ACPI_HMAT_TYPE_CACHE; + hmat_proc[1].handler =3D hmat_parse_cache; + + acpi_table_parse_entries_array(ACPI_SIG_HMAT, + sizeof(struct acpi_table_hmat), + hmat_proc, ARRAY_SIZE(hmat_proc), 0); + } + + if (bad_hmat) { + ret =3D -EINVAL; + goto err; + } + + list_for_each_entry(init, &initiator_list, list) { + ret =3D register_memory_initiator(init); + if (ret) + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + ret =3D register_memory_target(tgt); + if (ret) + goto err; + } + + return 0; +err: + pr_err("HMAT: Error during initialization\n"); + hmat_cleanup(); + return ret; +} + +static __exit void hmat_exit(void) +{ + hmat_cleanup(); +} + +module_init(hmat_init); +module_exit(hmat_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/acpi/hmat/hmat.h b/drivers/acpi/hmat/hmat.h new file mode 100644 index 000000000000..108aad1f8ad7 --- /dev/null +++ b/drivers/acpi/hmat/hmat.h @@ -0,0 +1,47 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + */ + +#ifndef _ACPI_HMAT_H_ +#define _ACPI_HMAT_H_ + +struct memory_initiator { + struct list_head list; + struct device dev; + + /* only one of the following three will be set */ + struct acpi_srat_cpu_affinity *cpu; + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct acpi_srat_gicc_affinity *gicc; + + int pxm; + bool is_registered; +}; +#define to_memory_initiator(d) container_of((d), struct memory_initiator, = dev) + +struct memory_target { + struct list_head list; + struct device dev; + struct acpi_srat_mem_affinity *ma; + struct acpi_hmat_address_range *spa; + struct memory_initiator *local_init; + + bool is_cached; + bool is_registered; +}; +#define to_memory_target(d) container_of((d), struct memory_target, dev) + +extern const struct attribute_group *memory_initiator_attribute_groups[]; +extern const struct attribute_group *memory_target_attribute_groups[]; +#endif /* _ACPI_HMAT_H_ */ diff --git a/drivers/acpi/hmat/initiator.c b/drivers/acpi/hmat/initiator.c new file mode 100644 index 000000000000..be2bf2b58940 --- /dev/null +++ b/drivers/acpi/hmat/initiator.c @@ -0,0 +1,43 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs initiator representa= tion + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_initiator *init =3D to_memory_initiator(dev); + + return sprintf(buf, "%d\n", init->pxm); +} +static DEVICE_ATTR_RO(firmware_id); + +static struct attribute *memory_initiator_attributes[] =3D { + &dev_attr_firmware_id.attr, + NULL, +}; + +static struct attribute_group memory_initiator_attribute_group =3D { + .attrs =3D memory_initiator_attributes, +}; + +const struct attribute_group *memory_initiator_attribute_groups[] =3D { + &memory_initiator_attribute_group, + NULL, +}; diff --git a/drivers/acpi/hmat/target.c b/drivers/acpi/hmat/target.c new file mode 100644 index 000000000000..2a9b44d5f44c --- /dev/null +++ b/drivers/acpi/hmat/target.c @@ -0,0 +1,55 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs target representation + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +/* attributes for memory targets */ +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt =3D to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->ma->proximity_domain); +} +static DEVICE_ATTR_RO(firmware_id); + +static ssize_t is_cached_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt =3D to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->is_cached); +} +static DEVICE_ATTR_RO(is_cached); + +static struct attribute *memory_target_attributes[] =3D { + &dev_attr_firmware_id.attr, + &dev_attr_is_cached.attr, + NULL +}; + +/* attributes which are present for all memory targets */ +static struct attribute_group memory_target_attribute_group =3D { + .attrs =3D memory_target_attributes, +}; + +const struct attribute_group *memory_target_attribute_groups[] =3D { + &memory_target_attribute_group, + NULL, +}; -- = 2.14.3 --===============3955309640872037530==-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ross Zwisler Subject: [PATCH v3 2/3] hmat: add heterogeneous memory sysfs support Date: Wed, 13 Dec 2017 19:10:18 -0700 Message-ID: <20171214021019.13579-3-ross.zwisler@linux.intel.com> References: <20171214021019.13579-1-ross.zwisler@linux.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20171214021019.13579-1-ross.zwisler-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org Sender: "Linux-nvdimm" To: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: "Box, David E" , Dave Hansen , "Zheng, Lv" , linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org, "Rafael J. Wysocki" , "Anaczkowski, Lukasz" , "Moore, Robert" , linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, "Odzioba, Lukasz" , "Schmauss, Erik" , Len Brown , John Hubbard , Jerome Glisse , devel-E0kO6a4B6psdnm+yROfE0A@public.gmane.org, "Kogut, Jaroslaw" , linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, "Koss, Marcin" , Brice Goglin , "Nachimuthu, Murugasamy" , "Rafael J. Wysocki" , "Koziej, Artur" , "Lahtinen, Joonas" , Andrew Morton List-Id: linux-acpi@vger.kernel.org QWRkIGEgbmV3IHN5c2ZzIHN1YnN5c3RlbSwgL3N5cy9kZXZpY2VzL3N5c3RlbS9obWF0LCB3aGlj aCBzdXJmYWNlcwppbmZvcm1hdGlvbiBhYm91dCBtZW1vcnkgaW5pdGlhdG9ycyBhbmQgbWVtb3J5 IHRhcmdldHMgdG8gdGhlIHVzZXIuICBUaGVzZQppbml0aWF0b3JzIGFuZCB0YXJnZXRzIGFyZSBk ZXNjcmliZWQgYnkgdGhlIEFDUEkgU1JBVCBhbmQgSE1BVCB0YWJsZXMuCgpBICJtZW1vcnkgaW5p dGlhdG9yIiBpbiB0aGlzIGNhc2UgaXMgYSBOVU1BIG5vZGUgY29udGFpbmluZyBvbmUgb3IgbW9y ZQpkZXZpY2VzIHN1Y2ggYXMgQ1BVIG9yIHNlcGFyYXRlIG1lbW9yeSBJL08gZGV2aWNlcyB0aGF0 IGNhbiBpbml0aWF0ZQptZW1vcnkgcmVxdWVzdHMuICBBICJtZW1vcnkgdGFyZ2V0IiBpcyBOVU1B IG5vZGUgY29udGFpbmluZyBhdCBsZWFzdCBvbmUKQ1BVLWFjY2Vzc2libGUgcGh5c2ljYWwgYWRk cmVzcyByYW5nZS4KClRoZSBrZXkgcGllY2Ugb2YgaW5mb3JtYXRpb24gc3VyZmFjZWQgYnkgdGhp cyBwYXRjaCBpcyB0aGUgbWFwcGluZyBiZXR3ZWVuCnRoZSBBQ1BJIHRhYmxlICJwcm94aW1pdHkg ZG9tYWluIiBudW1iZXJzLCBoZWxkIGluIHRoZSAiZmlybXdhcmVfaWQiCmF0dHJpYnV0ZSwgYW5k IExpbnV4IE5VTUEgbm9kZSBudW1iZXJzLiAgRXZlcnkgQUNQSSBwcm94aW1pdHkgZG9tYWluIHdp bGwKZW5kIHVwIGJlaW5nIGEgdW5pcXVlIE5VTUEgbm9kZSBpbiBMaW51eCwgYnV0IHRoZSBudW1i ZXJzIG1heSBnZXQgcmVvcmRlcmVkCmFuZCBMaW51eCBjYW4gY3JlYXRlIGV4dHJhIE5VTUEgbm9k ZXMgdGhhdCBkb24ndCBtYXAgYmFjayB0byBBQ1BJIHByb3hpbWl0eQpkb21haW5zLiAgVGhlIGZp cm13YXJlX2lkIHZhbHVlIGlzIG5lZWRlZCBpZiBhbnlvbmUgZXZlciB3YW50cyB0byBsb29rIGF0 CnRoZSBBQ1BJIEhNQVQgYW5kIFNSQVQgdGFibGVzIGRpcmVjdGx5IGFuZCBtYWtlIHNlbnNlIG9m IGhvdyB0aGV5IG1hcCB0bwpOVU1BIG5vZGVzIGluIExpbnV4LgoKSW5pdGlhdG9ycyBhcmUgZm91 bmQgYXQgL3N5cy9kZXZpY2VzL3N5c3RlbS9obWF0L21lbV9pbml0WCwgYW5kIHRoZQphdHRyaWJ1 dGVzIGZvciBhIGdpdmVuIGluaXRpYXRvciBsb29rIGxpa2UgdGhpczoKCiAgIyB0cmVlIG1lbV9p bml0MAogIG1lbV9pbml0MAogIOKUnOKUgOKUgCBmaXJtd2FyZV9pZAogIOKUnOKUgOKUgCBub2Rl MCAtPiAuLi8uLi9ub2RlL25vZGUwCiAg4pSc4pSA4pSAIHBvd2VyCiAg4pSCwqDCoCDilJzilIDi lIAgYXN5bmMKICDilILCoMKgIC4uLgogIOKUnOKUgOKUgCBzdWJzeXN0ZW0gLT4gLi4vLi4vLi4v Li4vYnVzL2htYXQKICDilJTilIDilIAgdWV2ZW50CgpXaGVyZSAibWVtX2luaXQwIiBvbiBteSBz eXN0ZW0gcmVwcmVzZW50cyB0aGUgQ1BVIGFjdGluZyBhcyBhIG1lbW9yeQppbml0aWF0b3IgYXQg TlVNQSBub2RlIDAuICBVc2VycyBjYW4gZGlzY292ZXIgd2hpY2ggQ1BVcyBhcmUgcGFydCBvZiB0 aGlzCm1lbW9yeSBpbml0aWF0b3IgYnkgZm9sbG93aW5nIHRoZSBub2RlMCBzeW1saW5rIGFuZCBs b29raW5nIGF0IGNwdW1hcCwKY3B1bGlzdCBhbmQgdGhlIGNwdSogc3ltbGlua3MuCgpUYXJnZXRz IGFyZSBmb3VuZCBhdCAvc3lzL2RldmljZXMvc3lzdGVtL2htYXQvbWVtX3RndFgsIGFuZCB0aGUg YXR0cmlidXRlcwpmb3IgYSBnaXZlbiB0YXJnZXQgbG9vayBsaWtlIHRoaXM6CgogICMgdHJlZSBt ZW1fdGd0MgogIG1lbV90Z3QyCiAg4pSc4pSA4pSAIGZpcm13YXJlX2lkCiAg4pSc4pSA4pSAIGlz X2NhY2hlZAogIOKUnOKUgOKUgCBub2RlMiAtPiAuLi8uLi9ub2RlL25vZGUyCiAg4pSc4pSA4pSA IHBvd2VyCiAg4pSCwqDCoCDilJzilIDilIAgYXN5bmMKICDilILCoMKgIC4uLgogIOKUnOKUgOKU gCBzdWJzeXN0ZW0gLT4gLi4vLi4vLi4vLi4vYnVzL2htYXQKICDilJTilIDilIAgdWV2ZW50CgpV c2VycyBjYW4gZGlzY292ZXIgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1lbW9yeSBvd25lZCBieSB0 aGlzIG1lbW9yeSB0YXJnZXQKYnkgZm9sbG93aW5nIHRoZSBub2RlMiBzeW1saW5rIGFuZCBsb29r aW5nIGF0IG1lbWluZm8sIHZtc3RhdCBhbmQgYXQgdGhlCm1lbW9yeSogbWVtb3J5IHNlY3Rpb24g c3ltbGlua3MuCgpTaWduZWQtb2ZmLWJ5OiBSb3NzIFp3aXNsZXIgPHJvc3Muendpc2xlckBsaW51 eC5pbnRlbC5jb20+Ci0tLQogTUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgICAgfCAgIDYgKwog ZHJpdmVycy9hY3BpL0tjb25maWcgICAgICAgICAgfCAgIDEgKwogZHJpdmVycy9hY3BpL01ha2Vm aWxlICAgICAgICAgfCAgIDEgKwogZHJpdmVycy9hY3BpL2htYXQvS2NvbmZpZyAgICAgfCAgIDcg KwogZHJpdmVycy9hY3BpL2htYXQvTWFrZWZpbGUgICAgfCAgIDIgKwogZHJpdmVycy9hY3BpL2ht YXQvY29yZS5jICAgICAgfCA1MzYgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrCiBkcml2ZXJzL2FjcGkvaG1hdC9obWF0LmggICAgICB8ICA0NyArKysrCiBkcml2ZXJz L2FjcGkvaG1hdC9pbml0aWF0b3IuYyB8ICA0MyArKysrCiBkcml2ZXJzL2FjcGkvaG1hdC90YXJn ZXQuYyAgICB8ICA1NSArKysrKwogOSBmaWxlcyBjaGFuZ2VkLCA2OTggaW5zZXJ0aW9ucygrKQog Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9obWF0L0tjb25maWcKIGNyZWF0ZSBtb2Rl IDEwMDY0NCBkcml2ZXJzL2FjcGkvaG1hdC9NYWtlZmlsZQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvYWNwaS9obWF0L2NvcmUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9o bWF0L2htYXQuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9obWF0L2luaXRpYXRv ci5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9hY3BpL2htYXQvdGFyZ2V0LmMKCmRpZmYg LS1naXQgYS9NQUlOVEFJTkVSUyBiL01BSU5UQUlORVJTCmluZGV4IDgyYWQwZWFiY2U0Zi4uNjRl YmVjMDcwOGRlIDEwMDY0NAotLS0gYS9NQUlOVEFJTkVSUworKysgYi9NQUlOVEFJTkVSUwpAQCAt NjM2Niw2ICs2MzY2LDEyIEBAIFM6CVN1cHBvcnRlZAogRjoJZHJpdmVycy9zY3NpL2hpc2lfc2Fz LwogRjoJRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3Njc2kvaGlzaWxpY29uLXNh cy50eHQKIAorSE1BVCAtIEFDUEkgSGV0ZXJvZ2VuZW91cyBNZW1vcnkgQXR0cmlidXRlIFRhYmxl IFN1cHBvcnQKK006CVJvc3MgWndpc2xlciA8cm9zcy56d2lzbGVyQGxpbnV4LmludGVsLmNvbT4K K0w6CWxpbnV4LW1tQGt2YWNrLm9yZworUzoJU3VwcG9ydGVkCitGOglkcml2ZXJzL2FjcGkvaG1h dC8KKwogSE1NIC0gSGV0ZXJvZ2VuZW91cyBNZW1vcnkgTWFuYWdlbWVudAogTToJSsOpcsO0bWUg R2xpc3NlIDxqZ2xpc3NlQHJlZGhhdC5jb20+CiBMOglsaW51eC1tbUBrdmFjay5vcmcKZGlmZiAt LWdpdCBhL2RyaXZlcnMvYWNwaS9LY29uZmlnIGIvZHJpdmVycy9hY3BpL0tjb25maWcKaW5kZXgg NDY1MDUzOTY4NjllLi4yMWNkZDEyODg0MzAgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvYWNwaS9LY29u ZmlnCisrKyBiL2RyaXZlcnMvYWNwaS9LY29uZmlnCkBAIC00NjYsNiArNDY2LDcgQEAgY29uZmln IEFDUElfUkVEVUNFRF9IQVJEV0FSRV9PTkxZCiAJICBJZiB5b3UgYXJlIHVuc3VyZSB3aGF0IHRv IGRvLCBkbyBub3QgZW5hYmxlIHRoaXMgb3B0aW9uLgogCiBzb3VyY2UgImRyaXZlcnMvYWNwaS9u Zml0L0tjb25maWciCitzb3VyY2UgImRyaXZlcnMvYWNwaS9obWF0L0tjb25maWciCiAKIHNvdXJj ZSAiZHJpdmVycy9hY3BpL2FwZWkvS2NvbmZpZyIKIHNvdXJjZSAiZHJpdmVycy9hY3BpL2RwdGYv S2NvbmZpZyIKZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9NYWtlZmlsZSBiL2RyaXZlcnMvYWNw aS9NYWtlZmlsZQppbmRleCA0MTk1NGE2MDE5ODkuLmVkNWVhYjZiMDQxMiAxMDA2NDQKLS0tIGEv ZHJpdmVycy9hY3BpL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvYWNwaS9NYWtlZmlsZQpAQCAtNzUs NiArNzUsNyBAQCBvYmotJChDT05GSUdfQUNQSV9QUk9DRVNTT1IpCSs9IHByb2Nlc3Nvci5vCiBv YmotJChDT05GSUdfQUNQSSkJCSs9IGNvbnRhaW5lci5vCiBvYmotJChDT05GSUdfQUNQSV9USEVS TUFMKQkrPSB0aGVybWFsLm8KIG9iai0kKENPTkZJR19BQ1BJX05GSVQpCQkrPSBuZml0Lworb2Jq LSQoQ09ORklHX0FDUElfSE1BVCkJCSs9IGhtYXQvCiBvYmotJChDT05GSUdfQUNQSSkJCSs9IGFj cGlfbWVtaG90cGx1Zy5vCiBvYmotJChDT05GSUdfQUNQSV9IT1RQTFVHX0lPQVBJQykgKz0gaW9h cGljLm8KIG9iai0kKENPTkZJR19BQ1BJX0JBVFRFUlkpCSs9IGJhdHRlcnkubwpkaWZmIC0tZ2l0 IGEvZHJpdmVycy9hY3BpL2htYXQvS2NvbmZpZyBiL2RyaXZlcnMvYWNwaS9obWF0L0tjb25maWcK bmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi45NTRhZDQ3MDEwMDUKLS0t IC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9LY29uZmlnCkBAIC0wLDAgKzEsNyBA QAorY29uZmlnIEFDUElfSE1BVAorCWJvb2wgIkFDUEkgSGV0ZXJvZ2VuZW91cyBNZW1vcnkgQXR0 cmlidXRlIFRhYmxlIFN1cHBvcnQiCisJZGVwZW5kcyBvbiBBQ1BJX05VTUEKKwlkZXBlbmRzIG9u IFNZU0ZTCisJaGVscAorCSAgRXhwb3J0cyBhIHN5c2ZzIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBB Q1BJIEhldGVyb2dlbmVvdXMgTWVtb3J5CisJICBBdHRyaWJ1dGVzIFRhYmxlIChITUFUKS4KZGlm ZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9obWF0L01ha2VmaWxlIGIvZHJpdmVycy9hY3BpL2htYXQv TWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5lZGY0YmNi MWM5N2QKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9NYWtlZmlsZQpAQCAt MCwwICsxLDIgQEAKK29iai0kKENPTkZJR19BQ1BJX0hNQVQpIDo9IGhtYXQubworaG1hdC15IDo9 IGNvcmUubyBpbml0aWF0b3IubyB0YXJnZXQubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9hY3BpL2ht YXQvY29yZS5jIGIvZHJpdmVycy9hY3BpL2htYXQvY29yZS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0 CmluZGV4IDAwMDAwMDAwMDAwMC4uNjFiOTBkYWRmODRiCi0tLSAvZGV2L251bGwKKysrIGIvZHJp dmVycy9hY3BpL2htYXQvY29yZS5jCkBAIC0wLDAgKzEsNTM2IEBACisvKgorICogSGV0ZXJvZ2Vu ZW91cyBNZW1vcnkgQXR0cmlidXRlcyBUYWJsZSAoSE1BVCkgcmVwcmVzZW50YXRpb24gaW4gc3lz ZnMKKyAqCisgKiBDb3B5cmlnaHQgKGMpIDIwMTcsIEludGVsIENvcnBvcmF0aW9uLgorICoKKyAq IFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBh bmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdGhl IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLAorICogdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQg YnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMg ZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUCisg KiBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJD SEFOVEFCSUxJVFkgb3IKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2Vl IHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IKKyAqIG1vcmUgZGV0YWlscy4KKyAq LworCisjaW5jbHVkZSA8YWNwaS9hY3BpX251bWEuaD4KKyNpbmNsdWRlIDxsaW51eC9hY3BpLmg+ CisjaW5jbHVkZSA8bGludXgvY3B1Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5j bHVkZSA8bGludXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KKyNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSAiaG1hdC5o IgorCitzdGF0aWMgTElTVF9IRUFEKHRhcmdldF9saXN0KTsKK3N0YXRpYyBMSVNUX0hFQUQoaW5p dGlhdG9yX2xpc3QpOworCitzdGF0aWMgYm9vbCBiYWRfaG1hdDsKKworc3RhdGljIGludCBsaW5r X25vZGVfZm9yX2tvYmoodW5zaWduZWQgaW50IG5vZGUsIHN0cnVjdCBrb2JqZWN0ICprb2JqKQor eworCWlmIChub2RlX2RldmljZXNbbm9kZV0pCisJCXJldHVybiBzeXNmc19jcmVhdGVfbGluayhr b2JqLCAmbm9kZV9kZXZpY2VzW25vZGVdLT5kZXYua29iaiwKKwkJCQlrb2JqZWN0X25hbWUoJm5v ZGVfZGV2aWNlc1tub2RlXS0+ZGV2LmtvYmopKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZv aWQgcmVtb3ZlX25vZGVfZm9yX2tvYmoodW5zaWduZWQgaW50IG5vZGUsIHN0cnVjdCBrb2JqZWN0 ICprb2JqKQoreworCWlmIChub2RlX2RldmljZXNbbm9kZV0pCisJCXN5c2ZzX3JlbW92ZV9saW5r KGtvYmosCisJCQkJa29iamVjdF9uYW1lKCZub2RlX2RldmljZXNbbm9kZV0tPmRldi5rb2JqKSk7 Cit9CisKKyNkZWZpbmUgSE1BVF9DTEFTU19OQU1FCSJobWF0IgorCitzdGF0aWMgc3RydWN0IGJ1 c190eXBlIGhtYXRfc3Vic3lzID0geworCS8qCisJICogLmRldl9uYW1lIGlzIHNldCBiZWZvcmUg ZGV2aWNlX3JlZ2lzdGVyKCkgYmFzZWQgb24gdGhlIHR5cGUgb2YKKwkgKiBkZXZpY2Ugd2UgYXJl IHJlZ2lzdGVyaW5nLgorCSAqLworCS5uYW1lID0gSE1BVF9DTEFTU19OQU1FLAorfTsKKworLyog bWVtb3J5IGluaXRpYXRvcnMgKi8KK3N0YXRpYyB2b2lkIHJlbGVhc2VfbWVtb3J5X2luaXRpYXRv cihzdHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQg PSB0b19tZW1vcnlfaW5pdGlhdG9yKGRldik7CisKKwlsaXN0X2RlbCgmaW5pdC0+bGlzdCk7CisJ a2ZyZWUoaW5pdCk7Cit9CisKK3N0YXRpYyB2b2lkIF9faW5pdCByZW1vdmVfbWVtb3J5X2luaXRp YXRvcihzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5pdCkKK3sKKwlpZiAoaW5pdC0+aXNfcmVn aXN0ZXJlZCkgeworCQlyZW1vdmVfbm9kZV9mb3Jfa29iaihweG1fdG9fbm9kZShpbml0LT5weG0p LCAmaW5pdC0+ZGV2LmtvYmopOworCQlkZXZpY2VfdW5yZWdpc3RlcigmaW5pdC0+ZGV2KTsKKwl9 IGVsc2UKKwkJcmVsZWFzZV9tZW1vcnlfaW5pdGlhdG9yKCZpbml0LT5kZXYpOworfQorCitzdGF0 aWMgaW50IF9faW5pdCByZWdpc3Rlcl9tZW1vcnlfaW5pdGlhdG9yKHN0cnVjdCBtZW1vcnlfaW5p dGlhdG9yICppbml0KQoreworCWludCByZXQ7CisKKwlobWF0X3N1YnN5cy5kZXZfbmFtZSA9ICJt ZW1faW5pdCI7CisJaW5pdC0+ZGV2LmJ1cyA9ICZobWF0X3N1YnN5czsKKwlpbml0LT5kZXYuaWQg PSBweG1fdG9fbm9kZShpbml0LT5weG0pOworCWluaXQtPmRldi5yZWxlYXNlID0gcmVsZWFzZV9t ZW1vcnlfaW5pdGlhdG9yOworCWluaXQtPmRldi5ncm91cHMgPSBtZW1vcnlfaW5pdGlhdG9yX2F0 dHJpYnV0ZV9ncm91cHM7CisKKwlyZXQgPSBkZXZpY2VfcmVnaXN0ZXIoJmluaXQtPmRldik7CisJ aWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisKKwlpbml0LT5pc19yZWdpc3RlcmVkID0gdHJ1 ZTsKKwlyZXR1cm4gbGlua19ub2RlX2Zvcl9rb2JqKHB4bV90b19ub2RlKGluaXQtPnB4bSksICZp bml0LT5kZXYua29iaik7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqIF9f aW5pdCBhZGRfbWVtb3J5X2luaXRpYXRvcihpbnQgcHhtKQoreworCXN0cnVjdCBtZW1vcnlfaW5p dGlhdG9yICppbml0OworCisJaWYgKHB4bV90b19ub2RlKHB4bSkgPT0gTlVNQV9OT19OT0RFKSB7 CisJCXByX2VycigiSE1BVDogTm8gTlVNQSBub2RlIGZvciBQWE0gJWRcbiIsIHB4bSk7CisJCWJh ZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7CisJfQorCisJLyoKKwkg KiBNYWtlIHN1cmUgd2UgaGF2ZW4ndCBhbHJlYWR5IGFkZGVkIGFuIGluaXRpYXRvciBmb3IgdGhp cyBwcm94aW1pdHkKKwkgKiBkb21haW4uICBXZSBkb24ndCBjYXJlIGFib3V0IGFueSBvdGhlciBk aWZmZXJlbmNlcyBpbiB0aGUgU1JBVAorCSAqIHRhYmxlcyAoYXBpY19pZCwgZXRjKSwgc28gd2Ug anVzdCB1c2UgdGhlIGRhdGEgZnJvbSB0aGUgZmlyc3QgdGFibGUKKwkgKiB3ZSBzZWUgZm9yIGEg Z2l2ZW4gcHJveGltaXR5IGRvbWFpbi4KKwkgKi8KKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGluaXQs ICZpbml0aWF0b3JfbGlzdCwgbGlzdCkKKwkJaWYgKGluaXQtPnB4bSA9PSBweG0pCisJCQlyZXR1 cm4gMDsKKworCWluaXQgPSBremFsbG9jKHNpemVvZigqaW5pdCksIEdGUF9LRVJORUwpOworCWlm ICghaW5pdCkgeworCQliYWRfaG1hdCA9IHRydWU7CisJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0p OworCX0KKworCWluaXQtPnB4bSA9IHB4bTsKKworCWxpc3RfYWRkX3RhaWwoJmluaXQtPmxpc3Qs ICZpbml0aWF0b3JfbGlzdCk7CisJcmV0dXJuIGluaXQ7Cit9CisKKy8qIG1lbW9yeSB0YXJnZXRz ICovCitzdGF0aWMgdm9pZCByZWxlYXNlX21lbW9yeV90YXJnZXQoc3RydWN0IGRldmljZSAqZGV2 KQoreworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3QgPSB0b19tZW1vcnlfdGFyZ2V0KGRldik7 CisKKwlsaXN0X2RlbCgmdGd0LT5saXN0KTsKKwlrZnJlZSh0Z3QpOworfQorCitzdGF0aWMgdm9p ZCBfX2luaXQgcmVtb3ZlX21lbW9yeV90YXJnZXQoc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCkK K3sKKwlpZiAodGd0LT5pc19yZWdpc3RlcmVkKSB7CisJCXJlbW92ZV9ub2RlX2Zvcl9rb2JqKHB4 bV90b19ub2RlKHRndC0+bWEtPnByb3hpbWl0eV9kb21haW4pLAorCQkJCSZ0Z3QtPmRldi5rb2Jq KTsKKwkJZGV2aWNlX3VucmVnaXN0ZXIoJnRndC0+ZGV2KTsKKwl9IGVsc2UKKwkJcmVsZWFzZV9t ZW1vcnlfdGFyZ2V0KCZ0Z3QtPmRldik7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0IHJlZ2lzdGVy X21lbW9yeV90YXJnZXQoc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCkKK3sKKwlpbnQgcmV0Owor CisJaWYgKCF0Z3QtPm1hIHx8ICF0Z3QtPnNwYSkgeworCQlwcl9lcnIoIkhNQVQ6IEluY29tcGxl dGUgbWVtb3J5IHRhcmdldCBmb3VuZFxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWht YXRfc3Vic3lzLmRldl9uYW1lID0gIm1lbV90Z3QiOworCXRndC0+ZGV2LmJ1cyA9ICZobWF0X3N1 YnN5czsKKwl0Z3QtPmRldi5pZCA9IHB4bV90b19ub2RlKHRndC0+bWEtPnByb3hpbWl0eV9kb21h aW4pOworCXRndC0+ZGV2LnJlbGVhc2UgPSByZWxlYXNlX21lbW9yeV90YXJnZXQ7CisJdGd0LT5k ZXYuZ3JvdXBzID0gbWVtb3J5X3RhcmdldF9hdHRyaWJ1dGVfZ3JvdXBzOworCisJcmV0ID0gZGV2 aWNlX3JlZ2lzdGVyKCZ0Z3QtPmRldik7CisJaWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisK Kwl0Z3QtPmlzX3JlZ2lzdGVyZWQgPSB0cnVlOworCisJcmV0dXJuIGxpbmtfbm9kZV9mb3Jfa29i aihweG1fdG9fbm9kZSh0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWluKSwKKwkJCSZ0Z3QtPmRldi5r b2JqKTsKK30KKworc3RhdGljIGludCBfX2luaXQgYWRkX21lbW9yeV90YXJnZXQoc3RydWN0IGFj cGlfc3JhdF9tZW1fYWZmaW5pdHkgKm1hKQoreworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7 CisKKwlpZiAocHhtX3RvX25vZGUobWEtPnByb3hpbWl0eV9kb21haW4pID09IE5VTUFfTk9fTk9E RSkgeworCQlwcl9lcnIoIkhNQVQ6IE5vIE5VTUEgbm9kZSBmb3IgUFhNICVkXG4iLCBtYS0+cHJv eGltaXR5X2RvbWFpbik7CisJCWJhZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJ fQorCisJLyoKKwkgKiBNYWtlIHN1cmUgd2UgaGF2ZW4ndCBhbHJlYWR5IGFkZGVkIGEgdGFyZ2V0 IGZvciB0aGlzIHByb3hpbWl0eQorCSAqIGRvbWFpbi4gIFdlIGRvbid0IGNhcmUgYWJvdXQgYW55 IG90aGVyIGRpZmZlcmVuY2VzIGluIHRoZSBTUkFUCisJICogdGFibGVzIChiYXNlX2FkZHJlc3Ms IGxlbmd0aCksIHNvIHdlIGp1c3QgdXNlIHRoZSBkYXRhIGZyb20gdGhlCisJICogZmlyc3QgdGFi bGUgd2Ugc2VlIGZvciBhIGdpdmVuIHByb3hpbWl0eSBkb21haW4uCisJICovCisJbGlzdF9mb3Jf ZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkKKwkJaWYgKHRndC0+bWEtPnByb3hp bWl0eV9kb21haW4gPT0gbWEtPnByb3hpbWl0eV9kb21haW4pCisJCQlyZXR1cm4gMDsKKworCXRn dCA9IGt6YWxsb2Moc2l6ZW9mKCp0Z3QpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXRndCkgeworCQli YWRfaG1hdCA9IHRydWU7CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCXRndC0+bWEgPSBtYTsK KworCWxpc3RfYWRkX3RhaWwoJnRndC0+bGlzdCwgJnRhcmdldF9saXN0KTsKKwlyZXR1cm4gMDsK K30KKworLyogQUNQSSBwYXJzaW5nIGNvZGUsIHN0YXJ0aW5nIHdpdGggdGhlIEhNQVQgKi8KK3N0 YXRpYyBpbnQgX19pbml0IGhtYXRfbm9vcF9wYXJzZShzdHJ1Y3QgYWNwaV90YWJsZV9oZWFkZXIg KnRhYmxlKQoreworCS8qIHJlYWwgd29yayBkb25lIGJ5IHRoZSBobWF0X3BhcnNlXyogYW5kIHNy YXRfcGFyc2VfKiByb3V0aW5lcyAqLworCXJldHVybiAwOworfQorCitzdGF0aWMgYm9vbCBfX2lu aXQgaG1hdF9zcGFfbWF0Y2hlc19zcmF0KHN0cnVjdCBhY3BpX2htYXRfYWRkcmVzc19yYW5nZSAq c3BhLAorCQlzdHJ1Y3QgYWNwaV9zcmF0X21lbV9hZmZpbml0eSAqbWEpCit7CisJaWYgKHNwYS0+ cGh5c2ljYWxfYWRkcmVzc19iYXNlICE9IG1hLT5iYXNlX2FkZHJlc3MgfHwKKwkgICAgc3BhLT5w aHlzaWNhbF9hZGRyZXNzX2xlbmd0aCAhPSBtYS0+bGVuZ3RoKQorCQlyZXR1cm4gZmFsc2U7CisK KwlyZXR1cm4gdHJ1ZTsKK30KKworc3RhdGljIHZvaWQgZmluZF9sb2NhbF9pbml0aWF0b3Ioc3Ry dWN0IG1lbW9yeV90YXJnZXQgKnRndCkKK3sKKwlzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5p dDsKKworCWlmICghKHRndC0+c3BhLT5mbGFncyAmIEFDUElfSE1BVF9QUk9DRVNTT1JfUERfVkFM SUQpIHx8CisJCQlweG1fdG9fbm9kZSh0Z3QtPnNwYS0+cHJvY2Vzc29yX1BEKSA9PSBOVU1BX05P X05PREUpCisJCXJldHVybjsKKworCWxpc3RfZm9yX2VhY2hfZW50cnkoaW5pdCwgJmluaXRpYXRv cl9saXN0LCBsaXN0KSB7CisJCWlmIChpbml0LT5weG0gPT0gdGd0LT5zcGEtPnByb2Nlc3Nvcl9Q RCkgeworCQkJdGd0LT5sb2NhbF9pbml0ID0gaW5pdDsKKwkJCXJldHVybjsKKwkJfQorCX0KK30K KworLyogQUNQSSBITUFUIHBhcnNpbmcgcm91dGluZXMgKi8KK3N0YXRpYyBpbnQgX19pbml0Cito bWF0X3BhcnNlX2FkZHJlc3NfcmFuZ2Uoc3RydWN0IGFjcGlfc3VidGFibGVfaGVhZGVyICpoZWFk ZXIsCisJCWNvbnN0IHVuc2lnbmVkIGxvbmcgZW5kKQoreworCXN0cnVjdCBhY3BpX2htYXRfYWRk cmVzc19yYW5nZSAqc3BhOworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7CisKKwlpZiAoYmFk X2htYXQpCisJCXJldHVybiAwOworCisJc3BhID0gKHN0cnVjdCBhY3BpX2htYXRfYWRkcmVzc19y YW5nZSAqKWhlYWRlcjsKKwlpZiAoIXNwYSkgeworCQlwcl9lcnIoIkhNQVQ6IE5VTEwgdGFibGUg ZW50cnlcbiIpOworCQlnb3RvIGVycjsKKwl9CisKKwlpZiAoc3BhLT5oZWFkZXIubGVuZ3RoICE9 IHNpemVvZigqc3BhKSkgeworCQlwcl9lcnIoIkhNQVQ6IFVuZXhwZWN0ZWQgaGVhZGVyIGxlbmd0 aDogJWRcbiIsCisJCQkJc3BhLT5oZWFkZXIubGVuZ3RoKTsKKwkJZ290byBlcnI7CisJfQorCisJ bGlzdF9mb3JfZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlpZiAoKHNw YS0+ZmxhZ3MgJiBBQ1BJX0hNQVRfTUVNT1JZX1BEX1ZBTElEKSAmJgorCQkJCXNwYS0+bWVtb3J5 X1BEID09IHRndC0+bWEtPnByb3hpbWl0eV9kb21haW4pIHsKKwkJCS8qCisJCQkgKiBXZSBvbmx5 IGFkZCBhIHNpbmdsZSBITUFUIHRhcmdldCBwZXIgcHJveGltaXR5CisJCQkgKiBkb21haW4gc28g d2Ugd2FpdCBmb3IgdGhlIG9uZSB0aGF0IG1hdGNoZXMgdGhlCisJCQkgKiBzaW5nbGUgU1JBVCBt ZW1vcnkgYWZmaW5pdHkgc3RydWN0dXJlIHBlciBQWE0gd2UKKwkJCSAqIHNhdmVkIGluIGFkZF9t ZW1vcnlfdGFyZ2V0KCkuCisJCQkgKi8KKwkJCWlmIChobWF0X3NwYV9tYXRjaGVzX3NyYXQoc3Bh LCB0Z3QtPm1hKSkgeworCQkJCXRndC0+c3BhID0gc3BhOworCQkJCWZpbmRfbG9jYWxfaW5pdGlh dG9yKHRndCk7CisJCQl9CisJCQlyZXR1cm4gMDsKKwkJfQorCX0KKworCXJldHVybiAwOworZXJy OgorCWJhZF9obWF0ID0gdHJ1ZTsKKwlyZXR1cm4gLUVJTlZBTDsKK30KKworc3RhdGljIGludCBf X2luaXQgaG1hdF9wYXJzZV9jYWNoZShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRl ciwKKwkJY29uc3QgdW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfaG1hdF9jYWNo ZSAqY2FjaGU7CisJc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndDsKKworCWlmIChiYWRfaG1hdCkK KwkJcmV0dXJuIDA7CisKKwljYWNoZSA9IChzdHJ1Y3QgYWNwaV9obWF0X2NhY2hlICopaGVhZGVy OworCWlmICghY2FjaGUpIHsKKwkJcHJfZXJyKCJITUFUOiBOVUxMIHRhYmxlIGVudHJ5XG4iKTsK KwkJZ290byBlcnI7CisJfQorCisJaWYgKGNhY2hlLT5oZWFkZXIubGVuZ3RoIDwgc2l6ZW9mKCpj YWNoZSkpIHsKKwkJcHJfZXJyKCJITUFUOiBVbmV4cGVjdGVkIGhlYWRlciBsZW5ndGg6ICVkXG4i LAorCQkJCWNhY2hlLT5oZWFkZXIubGVuZ3RoKTsKKwkJZ290byBlcnI7CisJfQorCisJbGlzdF9m b3JfZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlpZiAoY2FjaGUtPm1l bW9yeV9QRCA9PSB0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWluKSB7CisJCQl0Z3QtPmlzX2NhY2hl ZCA9IHRydWU7CisJCQlyZXR1cm4gMDsKKwkJfQorCX0KKworCXByX2VycigiSE1BVDogQ291bGRu J3QgZmluZCBjYWNoZWQgdGFyZ2V0IFBYTSAlZFxuIiwgY2FjaGUtPm1lbW9yeV9QRCk7CitlcnI6 CisJYmFkX2htYXQgPSB0cnVlOworCXJldHVybiAtRUlOVkFMOworfQorCisvKgorICogU1JBVCBw YXJzaW5nLiAgV2UgdXNlIHNyYXRfZGlzYWJsZWQoKSBhbmQgcHhtX3RvX25vZGUoKSBzbyB3ZSBk b24ndCByZWRvCisgKiBhbnkgb2YgdGhlIFNSQVQgc2FuaXR5IGNoZWNraW5nIGRvbmUgaW4gZHJp dmVycy9hY3BpL251bWEuYy4KKyAqLworc3RhdGljIGludCBfX2luaXQKK3NyYXRfcGFyc2VfcHJv Y2Vzc29yX2FmZmluaXR5KHN0cnVjdCBhY3BpX3N1YnRhYmxlX2hlYWRlciAqaGVhZGVyLAorCQlj b25zdCB1bnNpZ25lZCBsb25nIGVuZCkKK3sKKwlzdHJ1Y3QgYWNwaV9zcmF0X2NwdV9hZmZpbml0 eSAqY3B1OworCXN0cnVjdCBtZW1vcnlfaW5pdGlhdG9yICppbml0OworCXUzMiBweG07CisKKwlp ZiAoYmFkX2htYXQpCisJCXJldHVybiAwOworCisJY3B1ID0gKHN0cnVjdCBhY3BpX3NyYXRfY3B1 X2FmZmluaXR5ICopaGVhZGVyOworCWlmICghY3B1KSB7CisJCXByX2VycigiSE1BVDogTlVMTCB0 YWJsZSBlbnRyeVxuIik7CisJCWJhZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJ fQorCisJcHhtID0gY3B1LT5wcm94aW1pdHlfZG9tYWluX2xvOworCWlmIChhY3BpX3NyYXRfcmV2 aXNpb24gPj0gMikKKwkJcHhtIHw9ICooKHVuc2lnbmVkIGludCAqKWNwdS0+cHJveGltaXR5X2Rv bWFpbl9oaSkgPDwgODsKKworCWlmICghKGNwdS0+ZmxhZ3MgJiBBQ1BJX1NSQVRfQ1BVX0VOQUJM RUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRfbWVtb3J5X2luaXRpYXRvcihweG0pOwor CWlmIChJU19FUlJfT1JfTlVMTChpbml0KSkKKwkJcmV0dXJuIFBUUl9FUlIoaW5pdCk7CisKKwlp bml0LT5jcHUgPSBjcHU7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0 X3BhcnNlX3gyYXBpY19hZmZpbml0eShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRl ciwKKwkJY29uc3QgdW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfc3JhdF94MmFw aWNfY3B1X2FmZmluaXR5ICp4MmFwaWM7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQ7 CisKKwlpZiAoYmFkX2htYXQpCisJCXJldHVybiAwOworCisJeDJhcGljID0gKHN0cnVjdCBhY3Bp X3NyYXRfeDJhcGljX2NwdV9hZmZpbml0eSAqKWhlYWRlcjsKKwlpZiAoIXgyYXBpYykgeworCQlw cl9lcnIoIkhNQVQ6IE5VTEwgdGFibGUgZW50cnlcbiIpOworCQliYWRfaG1hdCA9IHRydWU7CisJ CXJldHVybiAtRUlOVkFMOworCX0KKworCWlmICghKHgyYXBpYy0+ZmxhZ3MgJiBBQ1BJX1NSQVRf Q1BVX0VOQUJMRUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRfbWVtb3J5X2luaXRpYXRv cih4MmFwaWMtPnByb3hpbWl0eV9kb21haW4pOworCWlmIChJU19FUlJfT1JfTlVMTChpbml0KSkK KwkJcmV0dXJuIFBUUl9FUlIoaW5pdCk7CisKKwlpbml0LT54MmFwaWMgPSB4MmFwaWM7CisJcmV0 dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0X3BhcnNlX2dpY2NfYWZmaW5pdHko c3RydWN0IGFjcGlfc3VidGFibGVfaGVhZGVyICpoZWFkZXIsCisJCWNvbnN0IHVuc2lnbmVkIGxv bmcgZW5kKQoreworCXN0cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqZ2ljYzsKKwlzdHJ1 Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5pdDsKKworCWlmIChiYWRfaG1hdCkKKwkJcmV0dXJuIDA7 CisKKwlnaWNjID0gKHN0cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqKWhlYWRlcjsKKwlp ZiAoIWdpY2MpIHsKKwkJcHJfZXJyKCJITUFUOiBOVUxMIHRhYmxlIGVudHJ5XG4iKTsKKwkJYmFk X2htYXQgPSB0cnVlOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlpZiAoIShnaWNjLT5mbGFn cyAmIEFDUElfU1JBVF9HSUNDX0VOQUJMRUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRf bWVtb3J5X2luaXRpYXRvcihnaWNjLT5wcm94aW1pdHlfZG9tYWluKTsKKwlpZiAoSVNfRVJSX09S X05VTEwoaW5pdCkpCisJCXJldHVybiBQVFJfRVJSKGluaXQpOworCisJaW5pdC0+Z2ljYyA9IGdp Y2M7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0X3BhcnNlX21lbW9y eV9hZmZpbml0eShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRlciwKKwkJY29uc3Qg dW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfc3JhdF9tZW1fYWZmaW5pdHkgKm1h OworCisJaWYgKGJhZF9obWF0KQorCQlyZXR1cm4gMDsKKworCW1hID0gKHN0cnVjdCBhY3BpX3Ny YXRfbWVtX2FmZmluaXR5ICopaGVhZGVyOworCWlmICghbWEpIHsKKwkJcHJfZXJyKCJITUFUOiBO VUxMIHRhYmxlIGVudHJ5XG4iKTsKKwkJYmFkX2htYXQgPSB0cnVlOworCQlyZXR1cm4gLUVJTlZB TDsKKwl9CisKKwlpZiAoIShtYS0+ZmxhZ3MgJiBBQ1BJX1NSQVRfTUVNX0VOQUJMRUQpKQorCQly ZXR1cm4gMDsKKworCXJldHVybiBhZGRfbWVtb3J5X3RhcmdldChtYSk7Cit9CisKKy8qCisgKiBS ZW1vdmUgb3VyIHN5c2ZzIGVudHJpZXMsIHVucmVnaXN0ZXIgb3VyIGRldmljZXMgYW5kIGZyZWUg YWxsb2NhdGVkIG1lbW9yeS4KKyAqLworc3RhdGljIHZvaWQgaG1hdF9jbGVhbnVwKHZvaWQpCit7 CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQsICppbml0X2l0ZXI7CisJc3RydWN0IG1l bW9yeV90YXJnZXQgKnRndCwgKnRndF9pdGVyOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZl KHRndCwgdGd0X2l0ZXIsICZ0YXJnZXRfbGlzdCwgbGlzdCkKKwkJcmVtb3ZlX21lbW9yeV90YXJn ZXQodGd0KTsKKworCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShpbml0LCBpbml0X2l0ZXIsICZp bml0aWF0b3JfbGlzdCwgbGlzdCkKKwkJcmVtb3ZlX21lbW9yeV9pbml0aWF0b3IoaW5pdCk7Cit9 CisKK3N0YXRpYyBpbnQgX19pbml0IGhtYXRfaW5pdCh2b2lkKQoreworCXN0cnVjdCBhY3BpX3Rh YmxlX2hlYWRlciAqdGJsOworCXN0cnVjdCBtZW1vcnlfaW5pdGlhdG9yICppbml0OworCXN0cnVj dCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7CisJYWNwaV9zdGF0dXMgc3RhdHVzID0gQUVfT0s7CisJaW50 IHJldDsKKworCWlmIChzcmF0X2Rpc2FibGVkKCkpCisJCXJldHVybiAwOworCisJLyoKKwkgKiBX ZSB0YWtlIGEgcGVybWFuZW50IHJlZmVyZW5jZSB0byBib3RoIHRoZSBITUFUIGFuZCBTUkFUIGlu IEFDUEkKKwkgKiBtZW1vcnkgc28gd2UgY2FuIGtlZXAgcG9pbnRlcnMgdG8gdGhlaXIgc3VidGFi bGVzLiAgVGhlc2UgdGFibGVzCisJICogYWxyZWFkeSBoYWQgcmVmZXJlbmNlcyBvbiB0aGVtIHdo aWNoIHdvdWxkIG5ldmVyIGJlIHJlbGVhc2VkLCB0YWtlbgorCSAqIGJ5IGFjcGlfc3lzZnNfaW5p dCgpLCBzbyB0aGlzIHNob3VsZG4ndCBuZWdhdGl2ZWx5IGltcGFjdCBhbnl0aGluZy4KKwkgKi8K KwlzdGF0dXMgPSBhY3BpX2dldF90YWJsZShBQ1BJX1NJR19TUkFULCAwLCAmdGJsKTsKKwlpZiAo QUNQSV9GQUlMVVJFKHN0YXR1cykpCisJCXJldHVybiAwOworCisJc3RhdHVzID0gYWNwaV9nZXRf dGFibGUoQUNQSV9TSUdfSE1BVCwgMCwgJnRibCk7CisJaWYgKEFDUElfRkFJTFVSRShzdGF0dXMp KQorCQlyZXR1cm4gMDsKKworCXJldCA9IHN1YnN5c19zeXN0ZW1fcmVnaXN0ZXIoJmhtYXRfc3Vi c3lzLCBOVUxMKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJaWYgKCFhY3BpX3RhYmxl X3BhcnNlKEFDUElfU0lHX1NSQVQsIGhtYXRfbm9vcF9wYXJzZSkpIHsKKwkJc3RydWN0IGFjcGlf c3VidGFibGVfcHJvYyBzcmF0X3Byb2NbNF07CisKKwkJbWVtc2V0KHNyYXRfcHJvYywgMCwgc2l6 ZW9mKHNyYXRfcHJvYykpOworCQlzcmF0X3Byb2NbMF0uaWQgPSBBQ1BJX1NSQVRfVFlQRV9DUFVf QUZGSU5JVFk7CisJCXNyYXRfcHJvY1swXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9wcm9jZXNzb3Jf YWZmaW5pdHk7CisJCXNyYXRfcHJvY1sxXS5pZCA9IEFDUElfU1JBVF9UWVBFX1gyQVBJQ19DUFVf QUZGSU5JVFk7CisJCXNyYXRfcHJvY1sxXS5oYW5kbGVyID0gc3JhdF9wYXJzZV94MmFwaWNfYWZm aW5pdHk7CisJCXNyYXRfcHJvY1syXS5pZCA9IEFDUElfU1JBVF9UWVBFX0dJQ0NfQUZGSU5JVFk7 CisJCXNyYXRfcHJvY1syXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9naWNjX2FmZmluaXR5OworCQlz cmF0X3Byb2NbM10uaWQgPSBBQ1BJX1NSQVRfVFlQRV9NRU1PUllfQUZGSU5JVFk7CisJCXNyYXRf cHJvY1szXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9tZW1vcnlfYWZmaW5pdHk7CisKKwkJYWNwaV90 YWJsZV9wYXJzZV9lbnRyaWVzX2FycmF5KEFDUElfU0lHX1NSQVQsCisJCQkJCXNpemVvZihzdHJ1 Y3QgYWNwaV90YWJsZV9zcmF0KSwKKwkJCQkJc3JhdF9wcm9jLCBBUlJBWV9TSVpFKHNyYXRfcHJv YyksIDApOworCX0KKworCWlmICghYWNwaV90YWJsZV9wYXJzZShBQ1BJX1NJR19ITUFULCBobWF0 X25vb3BfcGFyc2UpKSB7CisJCXN0cnVjdCBhY3BpX3N1YnRhYmxlX3Byb2MgaG1hdF9wcm9jWzJd OworCisJCW1lbXNldChobWF0X3Byb2MsIDAsIHNpemVvZihobWF0X3Byb2MpKTsKKwkJaG1hdF9w cm9jWzBdLmlkID0gQUNQSV9ITUFUX1RZUEVfQUREUkVTU19SQU5HRTsKKwkJaG1hdF9wcm9jWzBd LmhhbmRsZXIgPSBobWF0X3BhcnNlX2FkZHJlc3NfcmFuZ2U7CisJCWhtYXRfcHJvY1sxXS5pZCA9 IEFDUElfSE1BVF9UWVBFX0NBQ0hFOworCQlobWF0X3Byb2NbMV0uaGFuZGxlciA9IGhtYXRfcGFy c2VfY2FjaGU7CisKKwkJYWNwaV90YWJsZV9wYXJzZV9lbnRyaWVzX2FycmF5KEFDUElfU0lHX0hN QVQsCisJCQkJCXNpemVvZihzdHJ1Y3QgYWNwaV90YWJsZV9obWF0KSwKKwkJCQkJaG1hdF9wcm9j LCBBUlJBWV9TSVpFKGhtYXRfcHJvYyksIDApOworCX0KKworCWlmIChiYWRfaG1hdCkgeworCQly ZXQgPSAtRUlOVkFMOworCQlnb3RvIGVycjsKKwl9CisKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGlu aXQsICZpbml0aWF0b3JfbGlzdCwgbGlzdCkgeworCQlyZXQgPSByZWdpc3Rlcl9tZW1vcnlfaW5p dGlhdG9yKGluaXQpOworCQlpZiAocmV0KQorCQkJZ290byBlcnI7CisJfQorCisJbGlzdF9mb3Jf ZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlyZXQgPSByZWdpc3Rlcl9t ZW1vcnlfdGFyZ2V0KHRndCk7CisJCWlmIChyZXQpCisJCQlnb3RvIGVycjsKKwl9CisKKwlyZXR1 cm4gMDsKK2VycjoKKwlwcl9lcnIoIkhNQVQ6IEVycm9yIGR1cmluZyBpbml0aWFsaXphdGlvblxu Iik7CisJaG1hdF9jbGVhbnVwKCk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIF9fZXhpdCB2 b2lkIGhtYXRfZXhpdCh2b2lkKQoreworCWhtYXRfY2xlYW51cCgpOworfQorCittb2R1bGVfaW5p dChobWF0X2luaXQpOworbW9kdWxlX2V4aXQoaG1hdF9leGl0KTsKK01PRFVMRV9MSUNFTlNFKCJH UEwgdjIiKTsKK01PRFVMRV9BVVRIT1IoIkludGVsIENvcnBvcmF0aW9uIik7CmRpZmYgLS1naXQg YS9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmggYi9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmgKbmV3 IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi4xMDhhYWQxZjhhZDcKLS0tIC9k ZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmgKQEAgLTAsMCArMSw0NyBAQAor LyoKKyAqIEhldGVyb2dlbmVvdXMgTWVtb3J5IEF0dHJpYnV0ZXMgVGFibGUgKEhNQVQpIHJlcHJl c2VudGF0aW9uIGluIHN5c2ZzCisgKgorICogQ29weXJpZ2h0IChjKSAyMDE3LCBJbnRlbCBDb3Jw b3JhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiBy ZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBj b25kaXRpb25zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwKKyAqIHZlcnNpb24g MiwgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICog VGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVs LCBidXQgV0lUSE9VVAorICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQg d2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM QVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yCisgKiBt b3JlIGRldGFpbHMuCisgKi8KKworI2lmbmRlZiBfQUNQSV9ITUFUX0hfCisjZGVmaW5lIF9BQ1BJ X0hNQVRfSF8KKworc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgeworCXN0cnVjdCBsaXN0X2hlYWQg bGlzdDsKKwlzdHJ1Y3QgZGV2aWNlIGRldjsKKworCS8qIG9ubHkgb25lIG9mIHRoZSBmb2xsb3dp bmcgdGhyZWUgd2lsbCBiZSBzZXQgKi8KKwlzdHJ1Y3QgYWNwaV9zcmF0X2NwdV9hZmZpbml0eSAq Y3B1OworCXN0cnVjdCBhY3BpX3NyYXRfeDJhcGljX2NwdV9hZmZpbml0eSAqeDJhcGljOworCXN0 cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqZ2ljYzsKKworCWludCBweG07CisJYm9vbCBp c19yZWdpc3RlcmVkOworfTsKKyNkZWZpbmUgdG9fbWVtb3J5X2luaXRpYXRvcihkKSBjb250YWlu ZXJfb2YoKGQpLCBzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciwgZGV2KQorCitzdHJ1Y3QgbWVtb3J5 X3RhcmdldCB7CisJc3RydWN0IGxpc3RfaGVhZCBsaXN0OworCXN0cnVjdCBkZXZpY2UgZGV2Owor CXN0cnVjdCBhY3BpX3NyYXRfbWVtX2FmZmluaXR5ICptYTsKKwlzdHJ1Y3QgYWNwaV9obWF0X2Fk ZHJlc3NfcmFuZ2UgKnNwYTsKKwlzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqbG9jYWxfaW5pdDsK KworCWJvb2wgaXNfY2FjaGVkOworCWJvb2wgaXNfcmVnaXN0ZXJlZDsKK307CisjZGVmaW5lIHRv X21lbW9yeV90YXJnZXQoZCkgY29udGFpbmVyX29mKChkKSwgc3RydWN0IG1lbW9yeV90YXJnZXQs IGRldikKKworZXh0ZXJuIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKm1lbW9yeV9pbml0 aWF0b3JfYXR0cmlidXRlX2dyb3Vwc1tdOworZXh0ZXJuIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVf Z3JvdXAgKm1lbW9yeV90YXJnZXRfYXR0cmlidXRlX2dyb3Vwc1tdOworI2VuZGlmIC8qIF9BQ1BJ X0hNQVRfSF8gKi8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9obWF0L2luaXRpYXRvci5jIGIv ZHJpdmVycy9hY3BpL2htYXQvaW5pdGlhdG9yLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXgg MDAwMDAwMDAwMDAwLi5iZTJiZjJiNTg5NDAKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2Fj cGkvaG1hdC9pbml0aWF0b3IuYwpAQCAtMCwwICsxLDQzIEBACisvKgorICogSGV0ZXJvZ2VuZW91 cyBNZW1vcnkgQXR0cmlidXRlcyBUYWJsZSAoSE1BVCkgc3lzZnMgaW5pdGlhdG9yIHJlcHJlc2Vu dGF0aW9uCisgKgorICogQ29weXJpZ2h0IChjKSAyMDE3LCBJbnRlbCBDb3Jwb3JhdGlvbi4KKyAq CisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUg aXQgYW5kL29yIG1vZGlmeSBpdAorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zIG9m IHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwKKyAqIHZlcnNpb24gMiwgYXMgcHVibGlz aGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICogVGhpcyBwcm9ncmFt IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9V VAorICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Yg TUVSQ0hBTlRBQklMSVRZIG9yCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4g IFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yCisgKiBtb3JlIGRldGFpbHMu CisgKi8KKworI2luY2x1ZGUgPGFjcGkvYWNwaV9udW1hLmg+CisjaW5jbHVkZSA8bGludXgvYWNw aS5oPgorI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4L3N5c2ZzLmg+ CisjaW5jbHVkZSAiaG1hdC5oIgorCitzdGF0aWMgc3NpemVfdCBmaXJtd2FyZV9pZF9zaG93KHN0 cnVjdCBkZXZpY2UgKmRldiwKKwkJCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLCBjaGFy ICpidWYpCit7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQgPSB0b19tZW1vcnlfaW5p dGlhdG9yKGRldik7CisKKwlyZXR1cm4gc3ByaW50ZihidWYsICIlZFxuIiwgaW5pdC0+cHhtKTsK K30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhmaXJtd2FyZV9pZCk7CisKK3N0YXRpYyBzdHJ1Y3Qg YXR0cmlidXRlICptZW1vcnlfaW5pdGlhdG9yX2F0dHJpYnV0ZXNbXSA9IHsKKwkmZGV2X2F0dHJf ZmlybXdhcmVfaWQuYXR0ciwKKwlOVUxMLAorfTsKKworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGVf Z3JvdXAgbWVtb3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVfZ3JvdXAgPSB7CisJLmF0dHJzID0gbWVt b3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVzLAorfTsKKworY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9n cm91cCAqbWVtb3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVfZ3JvdXBzW10gPSB7CisJJm1lbW9yeV9p bml0aWF0b3JfYXR0cmlidXRlX2dyb3VwLAorCU5VTEwsCit9OwpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9hY3BpL2htYXQvdGFyZ2V0LmMgYi9kcml2ZXJzL2FjcGkvaG1hdC90YXJnZXQuYwpuZXcgZmls ZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjJhOWI0NGQ1ZjQ0YwotLS0gL2Rldi9u dWxsCisrKyBiL2RyaXZlcnMvYWNwaS9obWF0L3RhcmdldC5jCkBAIC0wLDAgKzEsNTUgQEAKKy8q CisgKiBIZXRlcm9nZW5lb3VzIE1lbW9yeSBBdHRyaWJ1dGVzIFRhYmxlIChITUFUKSBzeXNmcyB0 YXJnZXQgcmVwcmVzZW50YXRpb24KKyAqCisgKiBDb3B5cmlnaHQgKGMpIDIwMTcsIEludGVsIENv cnBvcmF0aW9uLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2Fu IHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgYW5k IGNvbmRpdGlvbnMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLAorICogdmVyc2lv biAyLCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisg KiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgaXQgd2lsbCBiZSB1c2Vm dWwsIGJ1dCBXSVRIT1VUCisgKiBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGll ZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElD VUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IKKyAq IG1vcmUgZGV0YWlscy4KKyAqLworCisjaW5jbHVkZSA8YWNwaS9hY3BpX251bWEuaD4KKyNpbmNs dWRlIDxsaW51eC9hY3BpLmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8 bGludXgvc3lzZnMuaD4KKyNpbmNsdWRlICJobWF0LmgiCisKKy8qIGF0dHJpYnV0ZXMgZm9yIG1l bW9yeSB0YXJnZXRzICovCitzdGF0aWMgc3NpemVfdCBmaXJtd2FyZV9pZF9zaG93KHN0cnVjdCBk ZXZpY2UgKmRldiwKKwkJCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLCBjaGFyICpidWYp Cit7CisJc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCA9IHRvX21lbW9yeV90YXJnZXQoZGV2KTsK KworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLCB0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWlu KTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhmaXJtd2FyZV9pZCk7CisKK3N0YXRpYyBzc2l6 ZV90IGlzX2NhY2hlZF9zaG93KHN0cnVjdCBkZXZpY2UgKmRldiwKKwkJc3RydWN0IGRldmljZV9h dHRyaWJ1dGUgKmF0dHIsIGNoYXIgKmJ1ZikKK3sKKwlzdHJ1Y3QgbWVtb3J5X3RhcmdldCAqdGd0 ID0gdG9fbWVtb3J5X3RhcmdldChkZXYpOworCisJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs IHRndC0+aXNfY2FjaGVkKTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhpc19jYWNoZWQpOwor CitzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqbWVtb3J5X3RhcmdldF9hdHRyaWJ1dGVzW10gPSB7 CisJJmRldl9hdHRyX2Zpcm13YXJlX2lkLmF0dHIsCisJJmRldl9hdHRyX2lzX2NhY2hlZC5hdHRy LAorCU5VTEwKK307CisKKy8qIGF0dHJpYnV0ZXMgd2hpY2ggYXJlIHByZXNlbnQgZm9yIGFsbCBt ZW1vcnkgdGFyZ2V0cyAqLworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgbWVtb3J5X3Rh cmdldF9hdHRyaWJ1dGVfZ3JvdXAgPSB7CisJLmF0dHJzID0gbWVtb3J5X3RhcmdldF9hdHRyaWJ1 dGVzLAorfTsKKworY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqbWVtb3J5X3RhcmdldF9h dHRyaWJ1dGVfZ3JvdXBzW10gPSB7CisJJm1lbW9yeV90YXJnZXRfYXR0cmlidXRlX2dyb3VwLAor CU5VTEwsCit9OwotLSAKMi4xNC4zCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpMaW51eC1udmRpbW0gbWFpbGluZyBsaXN0CkxpbnV4LW52ZGltbUBsaXN0 cy4wMS5vcmcKaHR0cHM6Ly9saXN0cy4wMS5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udmRp bW0K From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 888FD2034B9F3 for ; Wed, 13 Dec 2017 18:05:52 -0800 (PST) From: Ross Zwisler Subject: [PATCH v3 2/3] hmat: add heterogeneous memory sysfs support Date: Wed, 13 Dec 2017 19:10:18 -0700 Message-Id: <20171214021019.13579-3-ross.zwisler@linux.intel.com> In-Reply-To: <20171214021019.13579-1-ross.zwisler@linux.intel.com> References: <20171214021019.13579-1-ross.zwisler@linux.intel.com> MIME-Version: 1.0 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" To: linux-kernel@vger.kernel.org Cc: "Box, David E" , Dave Hansen , "Zheng, Lv" , linux-nvdimm@lists.01.org, "Rafael J. Wysocki" , Anaczkowski,, Robert, Lukasz, "Erik , Len Brown" , John Hubbard , Jerome Glisse , devel@acpica.org, Kogut,, "Marcin , Brice Goglin , Nachimuthu, Murugasamy" , "Rafael J. Wysocki" , Koziej,, "Joonas , Andrew Morton , Tim Chen" List-ID: QWRkIGEgbmV3IHN5c2ZzIHN1YnN5c3RlbSwgL3N5cy9kZXZpY2VzL3N5c3RlbS9obWF0LCB3aGlj aCBzdXJmYWNlcwppbmZvcm1hdGlvbiBhYm91dCBtZW1vcnkgaW5pdGlhdG9ycyBhbmQgbWVtb3J5 IHRhcmdldHMgdG8gdGhlIHVzZXIuICBUaGVzZQppbml0aWF0b3JzIGFuZCB0YXJnZXRzIGFyZSBk ZXNjcmliZWQgYnkgdGhlIEFDUEkgU1JBVCBhbmQgSE1BVCB0YWJsZXMuCgpBICJtZW1vcnkgaW5p dGlhdG9yIiBpbiB0aGlzIGNhc2UgaXMgYSBOVU1BIG5vZGUgY29udGFpbmluZyBvbmUgb3IgbW9y ZQpkZXZpY2VzIHN1Y2ggYXMgQ1BVIG9yIHNlcGFyYXRlIG1lbW9yeSBJL08gZGV2aWNlcyB0aGF0 IGNhbiBpbml0aWF0ZQptZW1vcnkgcmVxdWVzdHMuICBBICJtZW1vcnkgdGFyZ2V0IiBpcyBOVU1B IG5vZGUgY29udGFpbmluZyBhdCBsZWFzdCBvbmUKQ1BVLWFjY2Vzc2libGUgcGh5c2ljYWwgYWRk cmVzcyByYW5nZS4KClRoZSBrZXkgcGllY2Ugb2YgaW5mb3JtYXRpb24gc3VyZmFjZWQgYnkgdGhp cyBwYXRjaCBpcyB0aGUgbWFwcGluZyBiZXR3ZWVuCnRoZSBBQ1BJIHRhYmxlICJwcm94aW1pdHkg ZG9tYWluIiBudW1iZXJzLCBoZWxkIGluIHRoZSAiZmlybXdhcmVfaWQiCmF0dHJpYnV0ZSwgYW5k IExpbnV4IE5VTUEgbm9kZSBudW1iZXJzLiAgRXZlcnkgQUNQSSBwcm94aW1pdHkgZG9tYWluIHdp bGwKZW5kIHVwIGJlaW5nIGEgdW5pcXVlIE5VTUEgbm9kZSBpbiBMaW51eCwgYnV0IHRoZSBudW1i ZXJzIG1heSBnZXQgcmVvcmRlcmVkCmFuZCBMaW51eCBjYW4gY3JlYXRlIGV4dHJhIE5VTUEgbm9k ZXMgdGhhdCBkb24ndCBtYXAgYmFjayB0byBBQ1BJIHByb3hpbWl0eQpkb21haW5zLiAgVGhlIGZp cm13YXJlX2lkIHZhbHVlIGlzIG5lZWRlZCBpZiBhbnlvbmUgZXZlciB3YW50cyB0byBsb29rIGF0 CnRoZSBBQ1BJIEhNQVQgYW5kIFNSQVQgdGFibGVzIGRpcmVjdGx5IGFuZCBtYWtlIHNlbnNlIG9m IGhvdyB0aGV5IG1hcCB0bwpOVU1BIG5vZGVzIGluIExpbnV4LgoKSW5pdGlhdG9ycyBhcmUgZm91 bmQgYXQgL3N5cy9kZXZpY2VzL3N5c3RlbS9obWF0L21lbV9pbml0WCwgYW5kIHRoZQphdHRyaWJ1 dGVzIGZvciBhIGdpdmVuIGluaXRpYXRvciBsb29rIGxpa2UgdGhpczoKCiAgIyB0cmVlIG1lbV9p bml0MAogIG1lbV9pbml0MAogIOKUnOKUgOKUgCBmaXJtd2FyZV9pZAogIOKUnOKUgOKUgCBub2Rl MCAtPiAuLi8uLi9ub2RlL25vZGUwCiAg4pSc4pSA4pSAIHBvd2VyCiAg4pSCwqDCoCDilJzilIDi lIAgYXN5bmMKICDilILCoMKgIC4uLgogIOKUnOKUgOKUgCBzdWJzeXN0ZW0gLT4gLi4vLi4vLi4v Li4vYnVzL2htYXQKICDilJTilIDilIAgdWV2ZW50CgpXaGVyZSAibWVtX2luaXQwIiBvbiBteSBz eXN0ZW0gcmVwcmVzZW50cyB0aGUgQ1BVIGFjdGluZyBhcyBhIG1lbW9yeQppbml0aWF0b3IgYXQg TlVNQSBub2RlIDAuICBVc2VycyBjYW4gZGlzY292ZXIgd2hpY2ggQ1BVcyBhcmUgcGFydCBvZiB0 aGlzCm1lbW9yeSBpbml0aWF0b3IgYnkgZm9sbG93aW5nIHRoZSBub2RlMCBzeW1saW5rIGFuZCBs b29raW5nIGF0IGNwdW1hcCwKY3B1bGlzdCBhbmQgdGhlIGNwdSogc3ltbGlua3MuCgpUYXJnZXRz IGFyZSBmb3VuZCBhdCAvc3lzL2RldmljZXMvc3lzdGVtL2htYXQvbWVtX3RndFgsIGFuZCB0aGUg YXR0cmlidXRlcwpmb3IgYSBnaXZlbiB0YXJnZXQgbG9vayBsaWtlIHRoaXM6CgogICMgdHJlZSBt ZW1fdGd0MgogIG1lbV90Z3QyCiAg4pSc4pSA4pSAIGZpcm13YXJlX2lkCiAg4pSc4pSA4pSAIGlz X2NhY2hlZAogIOKUnOKUgOKUgCBub2RlMiAtPiAuLi8uLi9ub2RlL25vZGUyCiAg4pSc4pSA4pSA IHBvd2VyCiAg4pSCwqDCoCDilJzilIDilIAgYXN5bmMKICDilILCoMKgIC4uLgogIOKUnOKUgOKU gCBzdWJzeXN0ZW0gLT4gLi4vLi4vLi4vLi4vYnVzL2htYXQKICDilJTilIDilIAgdWV2ZW50CgpV c2VycyBjYW4gZGlzY292ZXIgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1lbW9yeSBvd25lZCBieSB0 aGlzIG1lbW9yeSB0YXJnZXQKYnkgZm9sbG93aW5nIHRoZSBub2RlMiBzeW1saW5rIGFuZCBsb29r aW5nIGF0IG1lbWluZm8sIHZtc3RhdCBhbmQgYXQgdGhlCm1lbW9yeSogbWVtb3J5IHNlY3Rpb24g c3ltbGlua3MuCgpTaWduZWQtb2ZmLWJ5OiBSb3NzIFp3aXNsZXIgPHJvc3Muendpc2xlckBsaW51 eC5pbnRlbC5jb20+Ci0tLQogTUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgICAgfCAgIDYgKwog ZHJpdmVycy9hY3BpL0tjb25maWcgICAgICAgICAgfCAgIDEgKwogZHJpdmVycy9hY3BpL01ha2Vm aWxlICAgICAgICAgfCAgIDEgKwogZHJpdmVycy9hY3BpL2htYXQvS2NvbmZpZyAgICAgfCAgIDcg KwogZHJpdmVycy9hY3BpL2htYXQvTWFrZWZpbGUgICAgfCAgIDIgKwogZHJpdmVycy9hY3BpL2ht YXQvY29yZS5jICAgICAgfCA1MzYgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrCiBkcml2ZXJzL2FjcGkvaG1hdC9obWF0LmggICAgICB8ICA0NyArKysrCiBkcml2ZXJz L2FjcGkvaG1hdC9pbml0aWF0b3IuYyB8ICA0MyArKysrCiBkcml2ZXJzL2FjcGkvaG1hdC90YXJn ZXQuYyAgICB8ICA1NSArKysrKwogOSBmaWxlcyBjaGFuZ2VkLCA2OTggaW5zZXJ0aW9ucygrKQog Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9obWF0L0tjb25maWcKIGNyZWF0ZSBtb2Rl IDEwMDY0NCBkcml2ZXJzL2FjcGkvaG1hdC9NYWtlZmlsZQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvYWNwaS9obWF0L2NvcmUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9o bWF0L2htYXQuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvYWNwaS9obWF0L2luaXRpYXRv ci5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9hY3BpL2htYXQvdGFyZ2V0LmMKCmRpZmYg LS1naXQgYS9NQUlOVEFJTkVSUyBiL01BSU5UQUlORVJTCmluZGV4IDgyYWQwZWFiY2U0Zi4uNjRl YmVjMDcwOGRlIDEwMDY0NAotLS0gYS9NQUlOVEFJTkVSUworKysgYi9NQUlOVEFJTkVSUwpAQCAt NjM2Niw2ICs2MzY2LDEyIEBAIFM6CVN1cHBvcnRlZAogRjoJZHJpdmVycy9zY3NpL2hpc2lfc2Fz LwogRjoJRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3Njc2kvaGlzaWxpY29uLXNh cy50eHQKIAorSE1BVCAtIEFDUEkgSGV0ZXJvZ2VuZW91cyBNZW1vcnkgQXR0cmlidXRlIFRhYmxl IFN1cHBvcnQKK006CVJvc3MgWndpc2xlciA8cm9zcy56d2lzbGVyQGxpbnV4LmludGVsLmNvbT4K K0w6CWxpbnV4LW1tQGt2YWNrLm9yZworUzoJU3VwcG9ydGVkCitGOglkcml2ZXJzL2FjcGkvaG1h dC8KKwogSE1NIC0gSGV0ZXJvZ2VuZW91cyBNZW1vcnkgTWFuYWdlbWVudAogTToJSsOpcsO0bWUg R2xpc3NlIDxqZ2xpc3NlQHJlZGhhdC5jb20+CiBMOglsaW51eC1tbUBrdmFjay5vcmcKZGlmZiAt LWdpdCBhL2RyaXZlcnMvYWNwaS9LY29uZmlnIGIvZHJpdmVycy9hY3BpL0tjb25maWcKaW5kZXgg NDY1MDUzOTY4NjllLi4yMWNkZDEyODg0MzAgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvYWNwaS9LY29u ZmlnCisrKyBiL2RyaXZlcnMvYWNwaS9LY29uZmlnCkBAIC00NjYsNiArNDY2LDcgQEAgY29uZmln IEFDUElfUkVEVUNFRF9IQVJEV0FSRV9PTkxZCiAJICBJZiB5b3UgYXJlIHVuc3VyZSB3aGF0IHRv IGRvLCBkbyBub3QgZW5hYmxlIHRoaXMgb3B0aW9uLgogCiBzb3VyY2UgImRyaXZlcnMvYWNwaS9u Zml0L0tjb25maWciCitzb3VyY2UgImRyaXZlcnMvYWNwaS9obWF0L0tjb25maWciCiAKIHNvdXJj ZSAiZHJpdmVycy9hY3BpL2FwZWkvS2NvbmZpZyIKIHNvdXJjZSAiZHJpdmVycy9hY3BpL2RwdGYv S2NvbmZpZyIKZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9NYWtlZmlsZSBiL2RyaXZlcnMvYWNw aS9NYWtlZmlsZQppbmRleCA0MTk1NGE2MDE5ODkuLmVkNWVhYjZiMDQxMiAxMDA2NDQKLS0tIGEv ZHJpdmVycy9hY3BpL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvYWNwaS9NYWtlZmlsZQpAQCAtNzUs NiArNzUsNyBAQCBvYmotJChDT05GSUdfQUNQSV9QUk9DRVNTT1IpCSs9IHByb2Nlc3Nvci5vCiBv YmotJChDT05GSUdfQUNQSSkJCSs9IGNvbnRhaW5lci5vCiBvYmotJChDT05GSUdfQUNQSV9USEVS TUFMKQkrPSB0aGVybWFsLm8KIG9iai0kKENPTkZJR19BQ1BJX05GSVQpCQkrPSBuZml0Lworb2Jq LSQoQ09ORklHX0FDUElfSE1BVCkJCSs9IGhtYXQvCiBvYmotJChDT05GSUdfQUNQSSkJCSs9IGFj cGlfbWVtaG90cGx1Zy5vCiBvYmotJChDT05GSUdfQUNQSV9IT1RQTFVHX0lPQVBJQykgKz0gaW9h cGljLm8KIG9iai0kKENPTkZJR19BQ1BJX0JBVFRFUlkpCSs9IGJhdHRlcnkubwpkaWZmIC0tZ2l0 IGEvZHJpdmVycy9hY3BpL2htYXQvS2NvbmZpZyBiL2RyaXZlcnMvYWNwaS9obWF0L0tjb25maWcK bmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi45NTRhZDQ3MDEwMDUKLS0t IC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9LY29uZmlnCkBAIC0wLDAgKzEsNyBA QAorY29uZmlnIEFDUElfSE1BVAorCWJvb2wgIkFDUEkgSGV0ZXJvZ2VuZW91cyBNZW1vcnkgQXR0 cmlidXRlIFRhYmxlIFN1cHBvcnQiCisJZGVwZW5kcyBvbiBBQ1BJX05VTUEKKwlkZXBlbmRzIG9u IFNZU0ZTCisJaGVscAorCSAgRXhwb3J0cyBhIHN5c2ZzIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBB Q1BJIEhldGVyb2dlbmVvdXMgTWVtb3J5CisJICBBdHRyaWJ1dGVzIFRhYmxlIChITUFUKS4KZGlm ZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9obWF0L01ha2VmaWxlIGIvZHJpdmVycy9hY3BpL2htYXQv TWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5lZGY0YmNi MWM5N2QKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9NYWtlZmlsZQpAQCAt MCwwICsxLDIgQEAKK29iai0kKENPTkZJR19BQ1BJX0hNQVQpIDo9IGhtYXQubworaG1hdC15IDo9 IGNvcmUubyBpbml0aWF0b3IubyB0YXJnZXQubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9hY3BpL2ht YXQvY29yZS5jIGIvZHJpdmVycy9hY3BpL2htYXQvY29yZS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0 CmluZGV4IDAwMDAwMDAwMDAwMC4uNjFiOTBkYWRmODRiCi0tLSAvZGV2L251bGwKKysrIGIvZHJp dmVycy9hY3BpL2htYXQvY29yZS5jCkBAIC0wLDAgKzEsNTM2IEBACisvKgorICogSGV0ZXJvZ2Vu ZW91cyBNZW1vcnkgQXR0cmlidXRlcyBUYWJsZSAoSE1BVCkgcmVwcmVzZW50YXRpb24gaW4gc3lz ZnMKKyAqCisgKiBDb3B5cmlnaHQgKGMpIDIwMTcsIEludGVsIENvcnBvcmF0aW9uLgorICoKKyAq IFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBh bmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdGhl IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLAorICogdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQg YnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMg ZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUCisg KiBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJD SEFOVEFCSUxJVFkgb3IKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2Vl IHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IKKyAqIG1vcmUgZGV0YWlscy4KKyAq LworCisjaW5jbHVkZSA8YWNwaS9hY3BpX251bWEuaD4KKyNpbmNsdWRlIDxsaW51eC9hY3BpLmg+ CisjaW5jbHVkZSA8bGludXgvY3B1Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5j bHVkZSA8bGludXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KKyNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSAiaG1hdC5o IgorCitzdGF0aWMgTElTVF9IRUFEKHRhcmdldF9saXN0KTsKK3N0YXRpYyBMSVNUX0hFQUQoaW5p dGlhdG9yX2xpc3QpOworCitzdGF0aWMgYm9vbCBiYWRfaG1hdDsKKworc3RhdGljIGludCBsaW5r X25vZGVfZm9yX2tvYmoodW5zaWduZWQgaW50IG5vZGUsIHN0cnVjdCBrb2JqZWN0ICprb2JqKQor eworCWlmIChub2RlX2RldmljZXNbbm9kZV0pCisJCXJldHVybiBzeXNmc19jcmVhdGVfbGluayhr b2JqLCAmbm9kZV9kZXZpY2VzW25vZGVdLT5kZXYua29iaiwKKwkJCQlrb2JqZWN0X25hbWUoJm5v ZGVfZGV2aWNlc1tub2RlXS0+ZGV2LmtvYmopKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZv aWQgcmVtb3ZlX25vZGVfZm9yX2tvYmoodW5zaWduZWQgaW50IG5vZGUsIHN0cnVjdCBrb2JqZWN0 ICprb2JqKQoreworCWlmIChub2RlX2RldmljZXNbbm9kZV0pCisJCXN5c2ZzX3JlbW92ZV9saW5r KGtvYmosCisJCQkJa29iamVjdF9uYW1lKCZub2RlX2RldmljZXNbbm9kZV0tPmRldi5rb2JqKSk7 Cit9CisKKyNkZWZpbmUgSE1BVF9DTEFTU19OQU1FCSJobWF0IgorCitzdGF0aWMgc3RydWN0IGJ1 c190eXBlIGhtYXRfc3Vic3lzID0geworCS8qCisJICogLmRldl9uYW1lIGlzIHNldCBiZWZvcmUg ZGV2aWNlX3JlZ2lzdGVyKCkgYmFzZWQgb24gdGhlIHR5cGUgb2YKKwkgKiBkZXZpY2Ugd2UgYXJl IHJlZ2lzdGVyaW5nLgorCSAqLworCS5uYW1lID0gSE1BVF9DTEFTU19OQU1FLAorfTsKKworLyog bWVtb3J5IGluaXRpYXRvcnMgKi8KK3N0YXRpYyB2b2lkIHJlbGVhc2VfbWVtb3J5X2luaXRpYXRv cihzdHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQg PSB0b19tZW1vcnlfaW5pdGlhdG9yKGRldik7CisKKwlsaXN0X2RlbCgmaW5pdC0+bGlzdCk7CisJ a2ZyZWUoaW5pdCk7Cit9CisKK3N0YXRpYyB2b2lkIF9faW5pdCByZW1vdmVfbWVtb3J5X2luaXRp YXRvcihzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5pdCkKK3sKKwlpZiAoaW5pdC0+aXNfcmVn aXN0ZXJlZCkgeworCQlyZW1vdmVfbm9kZV9mb3Jfa29iaihweG1fdG9fbm9kZShpbml0LT5weG0p LCAmaW5pdC0+ZGV2LmtvYmopOworCQlkZXZpY2VfdW5yZWdpc3RlcigmaW5pdC0+ZGV2KTsKKwl9 IGVsc2UKKwkJcmVsZWFzZV9tZW1vcnlfaW5pdGlhdG9yKCZpbml0LT5kZXYpOworfQorCitzdGF0 aWMgaW50IF9faW5pdCByZWdpc3Rlcl9tZW1vcnlfaW5pdGlhdG9yKHN0cnVjdCBtZW1vcnlfaW5p dGlhdG9yICppbml0KQoreworCWludCByZXQ7CisKKwlobWF0X3N1YnN5cy5kZXZfbmFtZSA9ICJt ZW1faW5pdCI7CisJaW5pdC0+ZGV2LmJ1cyA9ICZobWF0X3N1YnN5czsKKwlpbml0LT5kZXYuaWQg PSBweG1fdG9fbm9kZShpbml0LT5weG0pOworCWluaXQtPmRldi5yZWxlYXNlID0gcmVsZWFzZV9t ZW1vcnlfaW5pdGlhdG9yOworCWluaXQtPmRldi5ncm91cHMgPSBtZW1vcnlfaW5pdGlhdG9yX2F0 dHJpYnV0ZV9ncm91cHM7CisKKwlyZXQgPSBkZXZpY2VfcmVnaXN0ZXIoJmluaXQtPmRldik7CisJ aWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisKKwlpbml0LT5pc19yZWdpc3RlcmVkID0gdHJ1 ZTsKKwlyZXR1cm4gbGlua19ub2RlX2Zvcl9rb2JqKHB4bV90b19ub2RlKGluaXQtPnB4bSksICZp bml0LT5kZXYua29iaik7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqIF9f aW5pdCBhZGRfbWVtb3J5X2luaXRpYXRvcihpbnQgcHhtKQoreworCXN0cnVjdCBtZW1vcnlfaW5p dGlhdG9yICppbml0OworCisJaWYgKHB4bV90b19ub2RlKHB4bSkgPT0gTlVNQV9OT19OT0RFKSB7 CisJCXByX2VycigiSE1BVDogTm8gTlVNQSBub2RlIGZvciBQWE0gJWRcbiIsIHB4bSk7CisJCWJh ZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7CisJfQorCisJLyoKKwkg KiBNYWtlIHN1cmUgd2UgaGF2ZW4ndCBhbHJlYWR5IGFkZGVkIGFuIGluaXRpYXRvciBmb3IgdGhp cyBwcm94aW1pdHkKKwkgKiBkb21haW4uICBXZSBkb24ndCBjYXJlIGFib3V0IGFueSBvdGhlciBk aWZmZXJlbmNlcyBpbiB0aGUgU1JBVAorCSAqIHRhYmxlcyAoYXBpY19pZCwgZXRjKSwgc28gd2Ug anVzdCB1c2UgdGhlIGRhdGEgZnJvbSB0aGUgZmlyc3QgdGFibGUKKwkgKiB3ZSBzZWUgZm9yIGEg Z2l2ZW4gcHJveGltaXR5IGRvbWFpbi4KKwkgKi8KKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGluaXQs ICZpbml0aWF0b3JfbGlzdCwgbGlzdCkKKwkJaWYgKGluaXQtPnB4bSA9PSBweG0pCisJCQlyZXR1 cm4gMDsKKworCWluaXQgPSBremFsbG9jKHNpemVvZigqaW5pdCksIEdGUF9LRVJORUwpOworCWlm ICghaW5pdCkgeworCQliYWRfaG1hdCA9IHRydWU7CisJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0p OworCX0KKworCWluaXQtPnB4bSA9IHB4bTsKKworCWxpc3RfYWRkX3RhaWwoJmluaXQtPmxpc3Qs ICZpbml0aWF0b3JfbGlzdCk7CisJcmV0dXJuIGluaXQ7Cit9CisKKy8qIG1lbW9yeSB0YXJnZXRz ICovCitzdGF0aWMgdm9pZCByZWxlYXNlX21lbW9yeV90YXJnZXQoc3RydWN0IGRldmljZSAqZGV2 KQoreworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3QgPSB0b19tZW1vcnlfdGFyZ2V0KGRldik7 CisKKwlsaXN0X2RlbCgmdGd0LT5saXN0KTsKKwlrZnJlZSh0Z3QpOworfQorCitzdGF0aWMgdm9p ZCBfX2luaXQgcmVtb3ZlX21lbW9yeV90YXJnZXQoc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCkK K3sKKwlpZiAodGd0LT5pc19yZWdpc3RlcmVkKSB7CisJCXJlbW92ZV9ub2RlX2Zvcl9rb2JqKHB4 bV90b19ub2RlKHRndC0+bWEtPnByb3hpbWl0eV9kb21haW4pLAorCQkJCSZ0Z3QtPmRldi5rb2Jq KTsKKwkJZGV2aWNlX3VucmVnaXN0ZXIoJnRndC0+ZGV2KTsKKwl9IGVsc2UKKwkJcmVsZWFzZV9t ZW1vcnlfdGFyZ2V0KCZ0Z3QtPmRldik7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0IHJlZ2lzdGVy X21lbW9yeV90YXJnZXQoc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCkKK3sKKwlpbnQgcmV0Owor CisJaWYgKCF0Z3QtPm1hIHx8ICF0Z3QtPnNwYSkgeworCQlwcl9lcnIoIkhNQVQ6IEluY29tcGxl dGUgbWVtb3J5IHRhcmdldCBmb3VuZFxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWht YXRfc3Vic3lzLmRldl9uYW1lID0gIm1lbV90Z3QiOworCXRndC0+ZGV2LmJ1cyA9ICZobWF0X3N1 YnN5czsKKwl0Z3QtPmRldi5pZCA9IHB4bV90b19ub2RlKHRndC0+bWEtPnByb3hpbWl0eV9kb21h aW4pOworCXRndC0+ZGV2LnJlbGVhc2UgPSByZWxlYXNlX21lbW9yeV90YXJnZXQ7CisJdGd0LT5k ZXYuZ3JvdXBzID0gbWVtb3J5X3RhcmdldF9hdHRyaWJ1dGVfZ3JvdXBzOworCisJcmV0ID0gZGV2 aWNlX3JlZ2lzdGVyKCZ0Z3QtPmRldik7CisJaWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisK Kwl0Z3QtPmlzX3JlZ2lzdGVyZWQgPSB0cnVlOworCisJcmV0dXJuIGxpbmtfbm9kZV9mb3Jfa29i aihweG1fdG9fbm9kZSh0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWluKSwKKwkJCSZ0Z3QtPmRldi5r b2JqKTsKK30KKworc3RhdGljIGludCBfX2luaXQgYWRkX21lbW9yeV90YXJnZXQoc3RydWN0IGFj cGlfc3JhdF9tZW1fYWZmaW5pdHkgKm1hKQoreworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7 CisKKwlpZiAocHhtX3RvX25vZGUobWEtPnByb3hpbWl0eV9kb21haW4pID09IE5VTUFfTk9fTk9E RSkgeworCQlwcl9lcnIoIkhNQVQ6IE5vIE5VTUEgbm9kZSBmb3IgUFhNICVkXG4iLCBtYS0+cHJv eGltaXR5X2RvbWFpbik7CisJCWJhZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJ fQorCisJLyoKKwkgKiBNYWtlIHN1cmUgd2UgaGF2ZW4ndCBhbHJlYWR5IGFkZGVkIGEgdGFyZ2V0 IGZvciB0aGlzIHByb3hpbWl0eQorCSAqIGRvbWFpbi4gIFdlIGRvbid0IGNhcmUgYWJvdXQgYW55 IG90aGVyIGRpZmZlcmVuY2VzIGluIHRoZSBTUkFUCisJICogdGFibGVzIChiYXNlX2FkZHJlc3Ms IGxlbmd0aCksIHNvIHdlIGp1c3QgdXNlIHRoZSBkYXRhIGZyb20gdGhlCisJICogZmlyc3QgdGFi bGUgd2Ugc2VlIGZvciBhIGdpdmVuIHByb3hpbWl0eSBkb21haW4uCisJICovCisJbGlzdF9mb3Jf ZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkKKwkJaWYgKHRndC0+bWEtPnByb3hp bWl0eV9kb21haW4gPT0gbWEtPnByb3hpbWl0eV9kb21haW4pCisJCQlyZXR1cm4gMDsKKworCXRn dCA9IGt6YWxsb2Moc2l6ZW9mKCp0Z3QpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXRndCkgeworCQli YWRfaG1hdCA9IHRydWU7CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCXRndC0+bWEgPSBtYTsK KworCWxpc3RfYWRkX3RhaWwoJnRndC0+bGlzdCwgJnRhcmdldF9saXN0KTsKKwlyZXR1cm4gMDsK K30KKworLyogQUNQSSBwYXJzaW5nIGNvZGUsIHN0YXJ0aW5nIHdpdGggdGhlIEhNQVQgKi8KK3N0 YXRpYyBpbnQgX19pbml0IGhtYXRfbm9vcF9wYXJzZShzdHJ1Y3QgYWNwaV90YWJsZV9oZWFkZXIg KnRhYmxlKQoreworCS8qIHJlYWwgd29yayBkb25lIGJ5IHRoZSBobWF0X3BhcnNlXyogYW5kIHNy YXRfcGFyc2VfKiByb3V0aW5lcyAqLworCXJldHVybiAwOworfQorCitzdGF0aWMgYm9vbCBfX2lu aXQgaG1hdF9zcGFfbWF0Y2hlc19zcmF0KHN0cnVjdCBhY3BpX2htYXRfYWRkcmVzc19yYW5nZSAq c3BhLAorCQlzdHJ1Y3QgYWNwaV9zcmF0X21lbV9hZmZpbml0eSAqbWEpCit7CisJaWYgKHNwYS0+ cGh5c2ljYWxfYWRkcmVzc19iYXNlICE9IG1hLT5iYXNlX2FkZHJlc3MgfHwKKwkgICAgc3BhLT5w aHlzaWNhbF9hZGRyZXNzX2xlbmd0aCAhPSBtYS0+bGVuZ3RoKQorCQlyZXR1cm4gZmFsc2U7CisK KwlyZXR1cm4gdHJ1ZTsKK30KKworc3RhdGljIHZvaWQgZmluZF9sb2NhbF9pbml0aWF0b3Ioc3Ry dWN0IG1lbW9yeV90YXJnZXQgKnRndCkKK3sKKwlzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5p dDsKKworCWlmICghKHRndC0+c3BhLT5mbGFncyAmIEFDUElfSE1BVF9QUk9DRVNTT1JfUERfVkFM SUQpIHx8CisJCQlweG1fdG9fbm9kZSh0Z3QtPnNwYS0+cHJvY2Vzc29yX1BEKSA9PSBOVU1BX05P X05PREUpCisJCXJldHVybjsKKworCWxpc3RfZm9yX2VhY2hfZW50cnkoaW5pdCwgJmluaXRpYXRv cl9saXN0LCBsaXN0KSB7CisJCWlmIChpbml0LT5weG0gPT0gdGd0LT5zcGEtPnByb2Nlc3Nvcl9Q RCkgeworCQkJdGd0LT5sb2NhbF9pbml0ID0gaW5pdDsKKwkJCXJldHVybjsKKwkJfQorCX0KK30K KworLyogQUNQSSBITUFUIHBhcnNpbmcgcm91dGluZXMgKi8KK3N0YXRpYyBpbnQgX19pbml0Cito bWF0X3BhcnNlX2FkZHJlc3NfcmFuZ2Uoc3RydWN0IGFjcGlfc3VidGFibGVfaGVhZGVyICpoZWFk ZXIsCisJCWNvbnN0IHVuc2lnbmVkIGxvbmcgZW5kKQoreworCXN0cnVjdCBhY3BpX2htYXRfYWRk cmVzc19yYW5nZSAqc3BhOworCXN0cnVjdCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7CisKKwlpZiAoYmFk X2htYXQpCisJCXJldHVybiAwOworCisJc3BhID0gKHN0cnVjdCBhY3BpX2htYXRfYWRkcmVzc19y YW5nZSAqKWhlYWRlcjsKKwlpZiAoIXNwYSkgeworCQlwcl9lcnIoIkhNQVQ6IE5VTEwgdGFibGUg ZW50cnlcbiIpOworCQlnb3RvIGVycjsKKwl9CisKKwlpZiAoc3BhLT5oZWFkZXIubGVuZ3RoICE9 IHNpemVvZigqc3BhKSkgeworCQlwcl9lcnIoIkhNQVQ6IFVuZXhwZWN0ZWQgaGVhZGVyIGxlbmd0 aDogJWRcbiIsCisJCQkJc3BhLT5oZWFkZXIubGVuZ3RoKTsKKwkJZ290byBlcnI7CisJfQorCisJ bGlzdF9mb3JfZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlpZiAoKHNw YS0+ZmxhZ3MgJiBBQ1BJX0hNQVRfTUVNT1JZX1BEX1ZBTElEKSAmJgorCQkJCXNwYS0+bWVtb3J5 X1BEID09IHRndC0+bWEtPnByb3hpbWl0eV9kb21haW4pIHsKKwkJCS8qCisJCQkgKiBXZSBvbmx5 IGFkZCBhIHNpbmdsZSBITUFUIHRhcmdldCBwZXIgcHJveGltaXR5CisJCQkgKiBkb21haW4gc28g d2Ugd2FpdCBmb3IgdGhlIG9uZSB0aGF0IG1hdGNoZXMgdGhlCisJCQkgKiBzaW5nbGUgU1JBVCBt ZW1vcnkgYWZmaW5pdHkgc3RydWN0dXJlIHBlciBQWE0gd2UKKwkJCSAqIHNhdmVkIGluIGFkZF9t ZW1vcnlfdGFyZ2V0KCkuCisJCQkgKi8KKwkJCWlmIChobWF0X3NwYV9tYXRjaGVzX3NyYXQoc3Bh LCB0Z3QtPm1hKSkgeworCQkJCXRndC0+c3BhID0gc3BhOworCQkJCWZpbmRfbG9jYWxfaW5pdGlh dG9yKHRndCk7CisJCQl9CisJCQlyZXR1cm4gMDsKKwkJfQorCX0KKworCXJldHVybiAwOworZXJy OgorCWJhZF9obWF0ID0gdHJ1ZTsKKwlyZXR1cm4gLUVJTlZBTDsKK30KKworc3RhdGljIGludCBf X2luaXQgaG1hdF9wYXJzZV9jYWNoZShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRl ciwKKwkJY29uc3QgdW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfaG1hdF9jYWNo ZSAqY2FjaGU7CisJc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndDsKKworCWlmIChiYWRfaG1hdCkK KwkJcmV0dXJuIDA7CisKKwljYWNoZSA9IChzdHJ1Y3QgYWNwaV9obWF0X2NhY2hlICopaGVhZGVy OworCWlmICghY2FjaGUpIHsKKwkJcHJfZXJyKCJITUFUOiBOVUxMIHRhYmxlIGVudHJ5XG4iKTsK KwkJZ290byBlcnI7CisJfQorCisJaWYgKGNhY2hlLT5oZWFkZXIubGVuZ3RoIDwgc2l6ZW9mKCpj YWNoZSkpIHsKKwkJcHJfZXJyKCJITUFUOiBVbmV4cGVjdGVkIGhlYWRlciBsZW5ndGg6ICVkXG4i LAorCQkJCWNhY2hlLT5oZWFkZXIubGVuZ3RoKTsKKwkJZ290byBlcnI7CisJfQorCisJbGlzdF9m b3JfZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlpZiAoY2FjaGUtPm1l bW9yeV9QRCA9PSB0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWluKSB7CisJCQl0Z3QtPmlzX2NhY2hl ZCA9IHRydWU7CisJCQlyZXR1cm4gMDsKKwkJfQorCX0KKworCXByX2VycigiSE1BVDogQ291bGRu J3QgZmluZCBjYWNoZWQgdGFyZ2V0IFBYTSAlZFxuIiwgY2FjaGUtPm1lbW9yeV9QRCk7CitlcnI6 CisJYmFkX2htYXQgPSB0cnVlOworCXJldHVybiAtRUlOVkFMOworfQorCisvKgorICogU1JBVCBw YXJzaW5nLiAgV2UgdXNlIHNyYXRfZGlzYWJsZWQoKSBhbmQgcHhtX3RvX25vZGUoKSBzbyB3ZSBk b24ndCByZWRvCisgKiBhbnkgb2YgdGhlIFNSQVQgc2FuaXR5IGNoZWNraW5nIGRvbmUgaW4gZHJp dmVycy9hY3BpL251bWEuYy4KKyAqLworc3RhdGljIGludCBfX2luaXQKK3NyYXRfcGFyc2VfcHJv Y2Vzc29yX2FmZmluaXR5KHN0cnVjdCBhY3BpX3N1YnRhYmxlX2hlYWRlciAqaGVhZGVyLAorCQlj b25zdCB1bnNpZ25lZCBsb25nIGVuZCkKK3sKKwlzdHJ1Y3QgYWNwaV9zcmF0X2NwdV9hZmZpbml0 eSAqY3B1OworCXN0cnVjdCBtZW1vcnlfaW5pdGlhdG9yICppbml0OworCXUzMiBweG07CisKKwlp ZiAoYmFkX2htYXQpCisJCXJldHVybiAwOworCisJY3B1ID0gKHN0cnVjdCBhY3BpX3NyYXRfY3B1 X2FmZmluaXR5ICopaGVhZGVyOworCWlmICghY3B1KSB7CisJCXByX2VycigiSE1BVDogTlVMTCB0 YWJsZSBlbnRyeVxuIik7CisJCWJhZF9obWF0ID0gdHJ1ZTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJ fQorCisJcHhtID0gY3B1LT5wcm94aW1pdHlfZG9tYWluX2xvOworCWlmIChhY3BpX3NyYXRfcmV2 aXNpb24gPj0gMikKKwkJcHhtIHw9ICooKHVuc2lnbmVkIGludCAqKWNwdS0+cHJveGltaXR5X2Rv bWFpbl9oaSkgPDwgODsKKworCWlmICghKGNwdS0+ZmxhZ3MgJiBBQ1BJX1NSQVRfQ1BVX0VOQUJM RUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRfbWVtb3J5X2luaXRpYXRvcihweG0pOwor CWlmIChJU19FUlJfT1JfTlVMTChpbml0KSkKKwkJcmV0dXJuIFBUUl9FUlIoaW5pdCk7CisKKwlp bml0LT5jcHUgPSBjcHU7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0 X3BhcnNlX3gyYXBpY19hZmZpbml0eShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRl ciwKKwkJY29uc3QgdW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfc3JhdF94MmFw aWNfY3B1X2FmZmluaXR5ICp4MmFwaWM7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQ7 CisKKwlpZiAoYmFkX2htYXQpCisJCXJldHVybiAwOworCisJeDJhcGljID0gKHN0cnVjdCBhY3Bp X3NyYXRfeDJhcGljX2NwdV9hZmZpbml0eSAqKWhlYWRlcjsKKwlpZiAoIXgyYXBpYykgeworCQlw cl9lcnIoIkhNQVQ6IE5VTEwgdGFibGUgZW50cnlcbiIpOworCQliYWRfaG1hdCA9IHRydWU7CisJ CXJldHVybiAtRUlOVkFMOworCX0KKworCWlmICghKHgyYXBpYy0+ZmxhZ3MgJiBBQ1BJX1NSQVRf Q1BVX0VOQUJMRUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRfbWVtb3J5X2luaXRpYXRv cih4MmFwaWMtPnByb3hpbWl0eV9kb21haW4pOworCWlmIChJU19FUlJfT1JfTlVMTChpbml0KSkK KwkJcmV0dXJuIFBUUl9FUlIoaW5pdCk7CisKKwlpbml0LT54MmFwaWMgPSB4MmFwaWM7CisJcmV0 dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0X3BhcnNlX2dpY2NfYWZmaW5pdHko c3RydWN0IGFjcGlfc3VidGFibGVfaGVhZGVyICpoZWFkZXIsCisJCWNvbnN0IHVuc2lnbmVkIGxv bmcgZW5kKQoreworCXN0cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqZ2ljYzsKKwlzdHJ1 Y3QgbWVtb3J5X2luaXRpYXRvciAqaW5pdDsKKworCWlmIChiYWRfaG1hdCkKKwkJcmV0dXJuIDA7 CisKKwlnaWNjID0gKHN0cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqKWhlYWRlcjsKKwlp ZiAoIWdpY2MpIHsKKwkJcHJfZXJyKCJITUFUOiBOVUxMIHRhYmxlIGVudHJ5XG4iKTsKKwkJYmFk X2htYXQgPSB0cnVlOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlpZiAoIShnaWNjLT5mbGFn cyAmIEFDUElfU1JBVF9HSUNDX0VOQUJMRUQpKQorCQlyZXR1cm4gMDsKKworCWluaXQgPSBhZGRf bWVtb3J5X2luaXRpYXRvcihnaWNjLT5wcm94aW1pdHlfZG9tYWluKTsKKwlpZiAoSVNfRVJSX09S X05VTEwoaW5pdCkpCisJCXJldHVybiBQVFJfRVJSKGluaXQpOworCisJaW5pdC0+Z2ljYyA9IGdp Y2M7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0CitzcmF0X3BhcnNlX21lbW9y eV9hZmZpbml0eShzdHJ1Y3QgYWNwaV9zdWJ0YWJsZV9oZWFkZXIgKmhlYWRlciwKKwkJY29uc3Qg dW5zaWduZWQgbG9uZyBlbmQpCit7CisJc3RydWN0IGFjcGlfc3JhdF9tZW1fYWZmaW5pdHkgKm1h OworCisJaWYgKGJhZF9obWF0KQorCQlyZXR1cm4gMDsKKworCW1hID0gKHN0cnVjdCBhY3BpX3Ny YXRfbWVtX2FmZmluaXR5ICopaGVhZGVyOworCWlmICghbWEpIHsKKwkJcHJfZXJyKCJITUFUOiBO VUxMIHRhYmxlIGVudHJ5XG4iKTsKKwkJYmFkX2htYXQgPSB0cnVlOworCQlyZXR1cm4gLUVJTlZB TDsKKwl9CisKKwlpZiAoIShtYS0+ZmxhZ3MgJiBBQ1BJX1NSQVRfTUVNX0VOQUJMRUQpKQorCQly ZXR1cm4gMDsKKworCXJldHVybiBhZGRfbWVtb3J5X3RhcmdldChtYSk7Cit9CisKKy8qCisgKiBS ZW1vdmUgb3VyIHN5c2ZzIGVudHJpZXMsIHVucmVnaXN0ZXIgb3VyIGRldmljZXMgYW5kIGZyZWUg YWxsb2NhdGVkIG1lbW9yeS4KKyAqLworc3RhdGljIHZvaWQgaG1hdF9jbGVhbnVwKHZvaWQpCit7 CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQsICppbml0X2l0ZXI7CisJc3RydWN0IG1l bW9yeV90YXJnZXQgKnRndCwgKnRndF9pdGVyOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZl KHRndCwgdGd0X2l0ZXIsICZ0YXJnZXRfbGlzdCwgbGlzdCkKKwkJcmVtb3ZlX21lbW9yeV90YXJn ZXQodGd0KTsKKworCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShpbml0LCBpbml0X2l0ZXIsICZp bml0aWF0b3JfbGlzdCwgbGlzdCkKKwkJcmVtb3ZlX21lbW9yeV9pbml0aWF0b3IoaW5pdCk7Cit9 CisKK3N0YXRpYyBpbnQgX19pbml0IGhtYXRfaW5pdCh2b2lkKQoreworCXN0cnVjdCBhY3BpX3Rh YmxlX2hlYWRlciAqdGJsOworCXN0cnVjdCBtZW1vcnlfaW5pdGlhdG9yICppbml0OworCXN0cnVj dCBtZW1vcnlfdGFyZ2V0ICp0Z3Q7CisJYWNwaV9zdGF0dXMgc3RhdHVzID0gQUVfT0s7CisJaW50 IHJldDsKKworCWlmIChzcmF0X2Rpc2FibGVkKCkpCisJCXJldHVybiAwOworCisJLyoKKwkgKiBX ZSB0YWtlIGEgcGVybWFuZW50IHJlZmVyZW5jZSB0byBib3RoIHRoZSBITUFUIGFuZCBTUkFUIGlu IEFDUEkKKwkgKiBtZW1vcnkgc28gd2UgY2FuIGtlZXAgcG9pbnRlcnMgdG8gdGhlaXIgc3VidGFi bGVzLiAgVGhlc2UgdGFibGVzCisJICogYWxyZWFkeSBoYWQgcmVmZXJlbmNlcyBvbiB0aGVtIHdo aWNoIHdvdWxkIG5ldmVyIGJlIHJlbGVhc2VkLCB0YWtlbgorCSAqIGJ5IGFjcGlfc3lzZnNfaW5p dCgpLCBzbyB0aGlzIHNob3VsZG4ndCBuZWdhdGl2ZWx5IGltcGFjdCBhbnl0aGluZy4KKwkgKi8K KwlzdGF0dXMgPSBhY3BpX2dldF90YWJsZShBQ1BJX1NJR19TUkFULCAwLCAmdGJsKTsKKwlpZiAo QUNQSV9GQUlMVVJFKHN0YXR1cykpCisJCXJldHVybiAwOworCisJc3RhdHVzID0gYWNwaV9nZXRf dGFibGUoQUNQSV9TSUdfSE1BVCwgMCwgJnRibCk7CisJaWYgKEFDUElfRkFJTFVSRShzdGF0dXMp KQorCQlyZXR1cm4gMDsKKworCXJldCA9IHN1YnN5c19zeXN0ZW1fcmVnaXN0ZXIoJmhtYXRfc3Vi c3lzLCBOVUxMKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJaWYgKCFhY3BpX3RhYmxl X3BhcnNlKEFDUElfU0lHX1NSQVQsIGhtYXRfbm9vcF9wYXJzZSkpIHsKKwkJc3RydWN0IGFjcGlf c3VidGFibGVfcHJvYyBzcmF0X3Byb2NbNF07CisKKwkJbWVtc2V0KHNyYXRfcHJvYywgMCwgc2l6 ZW9mKHNyYXRfcHJvYykpOworCQlzcmF0X3Byb2NbMF0uaWQgPSBBQ1BJX1NSQVRfVFlQRV9DUFVf QUZGSU5JVFk7CisJCXNyYXRfcHJvY1swXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9wcm9jZXNzb3Jf YWZmaW5pdHk7CisJCXNyYXRfcHJvY1sxXS5pZCA9IEFDUElfU1JBVF9UWVBFX1gyQVBJQ19DUFVf QUZGSU5JVFk7CisJCXNyYXRfcHJvY1sxXS5oYW5kbGVyID0gc3JhdF9wYXJzZV94MmFwaWNfYWZm aW5pdHk7CisJCXNyYXRfcHJvY1syXS5pZCA9IEFDUElfU1JBVF9UWVBFX0dJQ0NfQUZGSU5JVFk7 CisJCXNyYXRfcHJvY1syXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9naWNjX2FmZmluaXR5OworCQlz cmF0X3Byb2NbM10uaWQgPSBBQ1BJX1NSQVRfVFlQRV9NRU1PUllfQUZGSU5JVFk7CisJCXNyYXRf cHJvY1szXS5oYW5kbGVyID0gc3JhdF9wYXJzZV9tZW1vcnlfYWZmaW5pdHk7CisKKwkJYWNwaV90 YWJsZV9wYXJzZV9lbnRyaWVzX2FycmF5KEFDUElfU0lHX1NSQVQsCisJCQkJCXNpemVvZihzdHJ1 Y3QgYWNwaV90YWJsZV9zcmF0KSwKKwkJCQkJc3JhdF9wcm9jLCBBUlJBWV9TSVpFKHNyYXRfcHJv YyksIDApOworCX0KKworCWlmICghYWNwaV90YWJsZV9wYXJzZShBQ1BJX1NJR19ITUFULCBobWF0 X25vb3BfcGFyc2UpKSB7CisJCXN0cnVjdCBhY3BpX3N1YnRhYmxlX3Byb2MgaG1hdF9wcm9jWzJd OworCisJCW1lbXNldChobWF0X3Byb2MsIDAsIHNpemVvZihobWF0X3Byb2MpKTsKKwkJaG1hdF9w cm9jWzBdLmlkID0gQUNQSV9ITUFUX1RZUEVfQUREUkVTU19SQU5HRTsKKwkJaG1hdF9wcm9jWzBd LmhhbmRsZXIgPSBobWF0X3BhcnNlX2FkZHJlc3NfcmFuZ2U7CisJCWhtYXRfcHJvY1sxXS5pZCA9 IEFDUElfSE1BVF9UWVBFX0NBQ0hFOworCQlobWF0X3Byb2NbMV0uaGFuZGxlciA9IGhtYXRfcGFy c2VfY2FjaGU7CisKKwkJYWNwaV90YWJsZV9wYXJzZV9lbnRyaWVzX2FycmF5KEFDUElfU0lHX0hN QVQsCisJCQkJCXNpemVvZihzdHJ1Y3QgYWNwaV90YWJsZV9obWF0KSwKKwkJCQkJaG1hdF9wcm9j LCBBUlJBWV9TSVpFKGhtYXRfcHJvYyksIDApOworCX0KKworCWlmIChiYWRfaG1hdCkgeworCQly ZXQgPSAtRUlOVkFMOworCQlnb3RvIGVycjsKKwl9CisKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGlu aXQsICZpbml0aWF0b3JfbGlzdCwgbGlzdCkgeworCQlyZXQgPSByZWdpc3Rlcl9tZW1vcnlfaW5p dGlhdG9yKGluaXQpOworCQlpZiAocmV0KQorCQkJZ290byBlcnI7CisJfQorCisJbGlzdF9mb3Jf ZWFjaF9lbnRyeSh0Z3QsICZ0YXJnZXRfbGlzdCwgbGlzdCkgeworCQlyZXQgPSByZWdpc3Rlcl9t ZW1vcnlfdGFyZ2V0KHRndCk7CisJCWlmIChyZXQpCisJCQlnb3RvIGVycjsKKwl9CisKKwlyZXR1 cm4gMDsKK2VycjoKKwlwcl9lcnIoIkhNQVQ6IEVycm9yIGR1cmluZyBpbml0aWFsaXphdGlvblxu Iik7CisJaG1hdF9jbGVhbnVwKCk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIF9fZXhpdCB2 b2lkIGhtYXRfZXhpdCh2b2lkKQoreworCWhtYXRfY2xlYW51cCgpOworfQorCittb2R1bGVfaW5p dChobWF0X2luaXQpOworbW9kdWxlX2V4aXQoaG1hdF9leGl0KTsKK01PRFVMRV9MSUNFTlNFKCJH UEwgdjIiKTsKK01PRFVMRV9BVVRIT1IoIkludGVsIENvcnBvcmF0aW9uIik7CmRpZmYgLS1naXQg YS9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmggYi9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmgKbmV3 IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi4xMDhhYWQxZjhhZDcKLS0tIC9k ZXYvbnVsbAorKysgYi9kcml2ZXJzL2FjcGkvaG1hdC9obWF0LmgKQEAgLTAsMCArMSw0NyBAQAor LyoKKyAqIEhldGVyb2dlbmVvdXMgTWVtb3J5IEF0dHJpYnV0ZXMgVGFibGUgKEhNQVQpIHJlcHJl c2VudGF0aW9uIGluIHN5c2ZzCisgKgorICogQ29weXJpZ2h0IChjKSAyMDE3LCBJbnRlbCBDb3Jw b3JhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiBy ZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBj b25kaXRpb25zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwKKyAqIHZlcnNpb24g MiwgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICog VGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVs LCBidXQgV0lUSE9VVAorICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQg d2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM QVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yCisgKiBt b3JlIGRldGFpbHMuCisgKi8KKworI2lmbmRlZiBfQUNQSV9ITUFUX0hfCisjZGVmaW5lIF9BQ1BJ X0hNQVRfSF8KKworc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgeworCXN0cnVjdCBsaXN0X2hlYWQg bGlzdDsKKwlzdHJ1Y3QgZGV2aWNlIGRldjsKKworCS8qIG9ubHkgb25lIG9mIHRoZSBmb2xsb3dp bmcgdGhyZWUgd2lsbCBiZSBzZXQgKi8KKwlzdHJ1Y3QgYWNwaV9zcmF0X2NwdV9hZmZpbml0eSAq Y3B1OworCXN0cnVjdCBhY3BpX3NyYXRfeDJhcGljX2NwdV9hZmZpbml0eSAqeDJhcGljOworCXN0 cnVjdCBhY3BpX3NyYXRfZ2ljY19hZmZpbml0eSAqZ2ljYzsKKworCWludCBweG07CisJYm9vbCBp c19yZWdpc3RlcmVkOworfTsKKyNkZWZpbmUgdG9fbWVtb3J5X2luaXRpYXRvcihkKSBjb250YWlu ZXJfb2YoKGQpLCBzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciwgZGV2KQorCitzdHJ1Y3QgbWVtb3J5 X3RhcmdldCB7CisJc3RydWN0IGxpc3RfaGVhZCBsaXN0OworCXN0cnVjdCBkZXZpY2UgZGV2Owor CXN0cnVjdCBhY3BpX3NyYXRfbWVtX2FmZmluaXR5ICptYTsKKwlzdHJ1Y3QgYWNwaV9obWF0X2Fk ZHJlc3NfcmFuZ2UgKnNwYTsKKwlzdHJ1Y3QgbWVtb3J5X2luaXRpYXRvciAqbG9jYWxfaW5pdDsK KworCWJvb2wgaXNfY2FjaGVkOworCWJvb2wgaXNfcmVnaXN0ZXJlZDsKK307CisjZGVmaW5lIHRv X21lbW9yeV90YXJnZXQoZCkgY29udGFpbmVyX29mKChkKSwgc3RydWN0IG1lbW9yeV90YXJnZXQs IGRldikKKworZXh0ZXJuIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKm1lbW9yeV9pbml0 aWF0b3JfYXR0cmlidXRlX2dyb3Vwc1tdOworZXh0ZXJuIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVf Z3JvdXAgKm1lbW9yeV90YXJnZXRfYXR0cmlidXRlX2dyb3Vwc1tdOworI2VuZGlmIC8qIF9BQ1BJ X0hNQVRfSF8gKi8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9obWF0L2luaXRpYXRvci5jIGIv ZHJpdmVycy9hY3BpL2htYXQvaW5pdGlhdG9yLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXgg MDAwMDAwMDAwMDAwLi5iZTJiZjJiNTg5NDAKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2Fj cGkvaG1hdC9pbml0aWF0b3IuYwpAQCAtMCwwICsxLDQzIEBACisvKgorICogSGV0ZXJvZ2VuZW91 cyBNZW1vcnkgQXR0cmlidXRlcyBUYWJsZSAoSE1BVCkgc3lzZnMgaW5pdGlhdG9yIHJlcHJlc2Vu dGF0aW9uCisgKgorICogQ29weXJpZ2h0IChjKSAyMDE3LCBJbnRlbCBDb3Jwb3JhdGlvbi4KKyAq CisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUg aXQgYW5kL29yIG1vZGlmeSBpdAorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zIG9m IHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwKKyAqIHZlcnNpb24gMiwgYXMgcHVibGlz aGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICogVGhpcyBwcm9ncmFt IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9V VAorICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Yg TUVSQ0hBTlRBQklMSVRZIG9yCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4g IFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yCisgKiBtb3JlIGRldGFpbHMu CisgKi8KKworI2luY2x1ZGUgPGFjcGkvYWNwaV9udW1hLmg+CisjaW5jbHVkZSA8bGludXgvYWNw aS5oPgorI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4L3N5c2ZzLmg+ CisjaW5jbHVkZSAiaG1hdC5oIgorCitzdGF0aWMgc3NpemVfdCBmaXJtd2FyZV9pZF9zaG93KHN0 cnVjdCBkZXZpY2UgKmRldiwKKwkJCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLCBjaGFy ICpidWYpCit7CisJc3RydWN0IG1lbW9yeV9pbml0aWF0b3IgKmluaXQgPSB0b19tZW1vcnlfaW5p dGlhdG9yKGRldik7CisKKwlyZXR1cm4gc3ByaW50ZihidWYsICIlZFxuIiwgaW5pdC0+cHhtKTsK K30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhmaXJtd2FyZV9pZCk7CisKK3N0YXRpYyBzdHJ1Y3Qg YXR0cmlidXRlICptZW1vcnlfaW5pdGlhdG9yX2F0dHJpYnV0ZXNbXSA9IHsKKwkmZGV2X2F0dHJf ZmlybXdhcmVfaWQuYXR0ciwKKwlOVUxMLAorfTsKKworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGVf Z3JvdXAgbWVtb3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVfZ3JvdXAgPSB7CisJLmF0dHJzID0gbWVt b3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVzLAorfTsKKworY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9n cm91cCAqbWVtb3J5X2luaXRpYXRvcl9hdHRyaWJ1dGVfZ3JvdXBzW10gPSB7CisJJm1lbW9yeV9p bml0aWF0b3JfYXR0cmlidXRlX2dyb3VwLAorCU5VTEwsCit9OwpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9hY3BpL2htYXQvdGFyZ2V0LmMgYi9kcml2ZXJzL2FjcGkvaG1hdC90YXJnZXQuYwpuZXcgZmls ZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjJhOWI0NGQ1ZjQ0YwotLS0gL2Rldi9u dWxsCisrKyBiL2RyaXZlcnMvYWNwaS9obWF0L3RhcmdldC5jCkBAIC0wLDAgKzEsNTUgQEAKKy8q CisgKiBIZXRlcm9nZW5lb3VzIE1lbW9yeSBBdHRyaWJ1dGVzIFRhYmxlIChITUFUKSBzeXNmcyB0 YXJnZXQgcmVwcmVzZW50YXRpb24KKyAqCisgKiBDb3B5cmlnaHQgKGMpIDIwMTcsIEludGVsIENv cnBvcmF0aW9uLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2Fu IHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgYW5k IGNvbmRpdGlvbnMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLAorICogdmVyc2lv biAyLCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisg KiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgaXQgd2lsbCBiZSB1c2Vm dWwsIGJ1dCBXSVRIT1VUCisgKiBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGll ZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElD VUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IKKyAq IG1vcmUgZGV0YWlscy4KKyAqLworCisjaW5jbHVkZSA8YWNwaS9hY3BpX251bWEuaD4KKyNpbmNs dWRlIDxsaW51eC9hY3BpLmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8 bGludXgvc3lzZnMuaD4KKyNpbmNsdWRlICJobWF0LmgiCisKKy8qIGF0dHJpYnV0ZXMgZm9yIG1l bW9yeSB0YXJnZXRzICovCitzdGF0aWMgc3NpemVfdCBmaXJtd2FyZV9pZF9zaG93KHN0cnVjdCBk ZXZpY2UgKmRldiwKKwkJCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLCBjaGFyICpidWYp Cit7CisJc3RydWN0IG1lbW9yeV90YXJnZXQgKnRndCA9IHRvX21lbW9yeV90YXJnZXQoZGV2KTsK KworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLCB0Z3QtPm1hLT5wcm94aW1pdHlfZG9tYWlu KTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhmaXJtd2FyZV9pZCk7CisKK3N0YXRpYyBzc2l6 ZV90IGlzX2NhY2hlZF9zaG93KHN0cnVjdCBkZXZpY2UgKmRldiwKKwkJc3RydWN0IGRldmljZV9h dHRyaWJ1dGUgKmF0dHIsIGNoYXIgKmJ1ZikKK3sKKwlzdHJ1Y3QgbWVtb3J5X3RhcmdldCAqdGd0 ID0gdG9fbWVtb3J5X3RhcmdldChkZXYpOworCisJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs IHRndC0+aXNfY2FjaGVkKTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhpc19jYWNoZWQpOwor CitzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqbWVtb3J5X3RhcmdldF9hdHRyaWJ1dGVzW10gPSB7 CisJJmRldl9hdHRyX2Zpcm13YXJlX2lkLmF0dHIsCisJJmRldl9hdHRyX2lzX2NhY2hlZC5hdHRy LAorCU5VTEwKK307CisKKy8qIGF0dHJpYnV0ZXMgd2hpY2ggYXJlIHByZXNlbnQgZm9yIGFsbCBt ZW1vcnkgdGFyZ2V0cyAqLworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgbWVtb3J5X3Rh cmdldF9hdHRyaWJ1dGVfZ3JvdXAgPSB7CisJLmF0dHJzID0gbWVtb3J5X3RhcmdldF9hdHRyaWJ1 dGVzLAorfTsKKworY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqbWVtb3J5X3RhcmdldF9h dHRyaWJ1dGVfZ3JvdXBzW10gPSB7CisJJm1lbW9yeV90YXJnZXRfYXR0cmlidXRlX2dyb3VwLAor CU5VTEwsCit9OwotLSAKMi4xNC4zCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpMaW51eC1udmRpbW0gbWFpbGluZyBsaXN0CkxpbnV4LW52ZGltbUBsaXN0 cy4wMS5vcmcKaHR0cHM6Ly9saXN0cy4wMS5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udmRp bW0K From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf0-f200.google.com (mail-pf0-f200.google.com [209.85.192.200]) by kanga.kvack.org (Postfix) with ESMTP id CF6CF6B025F for ; Wed, 13 Dec 2017 21:10:35 -0500 (EST) Received: by mail-pf0-f200.google.com with SMTP id j3so3205786pfh.16 for ; Wed, 13 Dec 2017 18:10:35 -0800 (PST) Received: from mga11.intel.com (mga11.intel.com. [192.55.52.93]) by mx.google.com with ESMTPS id e69si2358748pfc.337.2017.12.13.18.10.33 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Dec 2017 18:10:33 -0800 (PST) From: Ross Zwisler Subject: [PATCH v3 2/3] hmat: add heterogeneous memory sysfs support Date: Wed, 13 Dec 2017 19:10:18 -0700 Message-Id: <20171214021019.13579-3-ross.zwisler@linux.intel.com> In-Reply-To: <20171214021019.13579-1-ross.zwisler@linux.intel.com> References: <20171214021019.13579-1-ross.zwisler@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: owner-linux-mm@kvack.org List-ID: To: linux-kernel@vger.kernel.org Cc: Ross Zwisler , "Anaczkowski, Lukasz" , "Box, David E" , "Kogut, Jaroslaw" , "Koss, Marcin" , "Koziej, Artur" , "Lahtinen, Joonas" , "Moore, Robert" , "Nachimuthu, Murugasamy" , "Odzioba, Lukasz" , "Rafael J. Wysocki" , "Rafael J. Wysocki" , "Schmauss, Erik" , "Verma, Vishal L" , "Zheng, Lv" , Andrew Morton , Balbir Singh , Brice Goglin , Dan Williams , Dave Hansen , Jerome Glisse , John Hubbard , Len Brown , Tim Chen , devel@acpica.org, linux-acpi@vger.kernel.org, linux-mm@kvack.org, linux-nvdimm@lists.01.org Add a new sysfs subsystem, /sys/devices/system/hmat, which surfaces information about memory initiators and memory targets to the user. These initiators and targets are described by the ACPI SRAT and HMAT tables. A "memory initiator" in this case is a NUMA node containing one or more devices such as CPU or separate memory I/O devices that can initiate memory requests. A "memory target" is NUMA node containing at least one CPU-accessible physical address range. The key piece of information surfaced by this patch is the mapping between the ACPI table "proximity domain" numbers, held in the "firmware_id" attribute, and Linux NUMA node numbers. Every ACPI proximity domain will end up being a unique NUMA node in Linux, but the numbers may get reordered and Linux can create extra NUMA nodes that don't map back to ACPI proximity domains. The firmware_id value is needed if anyone ever wants to look at the ACPI HMAT and SRAT tables directly and make sense of how they map to NUMA nodes in Linux. Initiators are found at /sys/devices/system/hmat/mem_initX, and the attributes for a given initiator look like this: # tree mem_init0 mem_init0 a??a??a?? firmware_id a??a??a?? node0 -> ../../node/node0 a??a??a?? power a??A A a??a??a?? async a??A A ... a??a??a?? subsystem -> ../../../../bus/hmat a??a??a?? uevent Where "mem_init0" on my system represents the CPU acting as a memory initiator at NUMA node 0. Users can discover which CPUs are part of this memory initiator by following the node0 symlink and looking at cpumap, cpulist and the cpu* symlinks. Targets are found at /sys/devices/system/hmat/mem_tgtX, and the attributes for a given target look like this: # tree mem_tgt2 mem_tgt2 a??a??a?? firmware_id a??a??a?? is_cached a??a??a?? node2 -> ../../node/node2 a??a??a?? power a??A A a??a??a?? async a??A A ... a??a??a?? subsystem -> ../../../../bus/hmat a??a??a?? uevent Users can discover information about the memory owned by this memory target by following the node2 symlink and looking at meminfo, vmstat and at the memory* memory section symlinks. Signed-off-by: Ross Zwisler --- MAINTAINERS | 6 + drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 7 + drivers/acpi/hmat/Makefile | 2 + drivers/acpi/hmat/core.c | 536 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/hmat/hmat.h | 47 ++++ drivers/acpi/hmat/initiator.c | 43 ++++ drivers/acpi/hmat/target.c | 55 +++++ 9 files changed, 698 insertions(+) create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/core.c create mode 100644 drivers/acpi/hmat/hmat.h create mode 100644 drivers/acpi/hmat/initiator.c create mode 100644 drivers/acpi/hmat/target.c diff --git a/MAINTAINERS b/MAINTAINERS index 82ad0eabce4f..64ebec0708de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6366,6 +6366,12 @@ S: Supported F: drivers/scsi/hisi_sas/ F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +HMAT - ACPI Heterogeneous Memory Attribute Table Support +M: Ross Zwisler +L: linux-mm@kvack.org +S: Supported +F: drivers/acpi/hmat/ + HMM - Heterogeneous Memory Management M: JA(C)rA'me Glisse L: linux-mm@kvack.org diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 46505396869e..21cdd1288430 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -466,6 +466,7 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. source "drivers/acpi/nfit/Kconfig" +source "drivers/acpi/hmat/Kconfig" source "drivers/acpi/apei/Kconfig" source "drivers/acpi/dptf/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 41954a601989..ed5eab6b0412 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_NFIT) += nfit/ +obj-$(CONFIG_ACPI_HMAT) += hmat/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o obj-$(CONFIG_ACPI_BATTERY) += battery.o diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig new file mode 100644 index 000000000000..954ad4701005 --- /dev/null +++ b/drivers/acpi/hmat/Kconfig @@ -0,0 +1,7 @@ +config ACPI_HMAT + bool "ACPI Heterogeneous Memory Attribute Table Support" + depends on ACPI_NUMA + depends on SYSFS + help + Exports a sysfs representation of the ACPI Heterogeneous Memory + Attributes Table (HMAT). diff --git a/drivers/acpi/hmat/Makefile b/drivers/acpi/hmat/Makefile new file mode 100644 index 000000000000..edf4bcb1c97d --- /dev/null +++ b/drivers/acpi/hmat/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ACPI_HMAT) := hmat.o +hmat-y := core.o initiator.o target.o diff --git a/drivers/acpi/hmat/core.c b/drivers/acpi/hmat/core.c new file mode 100644 index 000000000000..61b90dadf84b --- /dev/null +++ b/drivers/acpi/hmat/core.c @@ -0,0 +1,536 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmat.h" + +static LIST_HEAD(target_list); +static LIST_HEAD(initiator_list); + +static bool bad_hmat; + +static int link_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + return sysfs_create_link(kobj, &node_devices[node]->dev.kobj, + kobject_name(&node_devices[node]->dev.kobj)); + return 0; +} + +static void remove_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + sysfs_remove_link(kobj, + kobject_name(&node_devices[node]->dev.kobj)); +} + +#define HMAT_CLASS_NAME "hmat" + +static struct bus_type hmat_subsys = { + /* + * .dev_name is set before device_register() based on the type of + * device we are registering. + */ + .name = HMAT_CLASS_NAME, +}; + +/* memory initiators */ +static void release_memory_initiator(struct device *dev) +{ + struct memory_initiator *init = to_memory_initiator(dev); + + list_del(&init->list); + kfree(init); +} + +static void __init remove_memory_initiator(struct memory_initiator *init) +{ + if (init->is_registered) { + remove_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); + device_unregister(&init->dev); + } else + release_memory_initiator(&init->dev); +} + +static int __init register_memory_initiator(struct memory_initiator *init) +{ + int ret; + + hmat_subsys.dev_name = "mem_init"; + init->dev.bus = &hmat_subsys; + init->dev.id = pxm_to_node(init->pxm); + init->dev.release = release_memory_initiator; + init->dev.groups = memory_initiator_attribute_groups; + + ret = device_register(&init->dev); + if (ret < 0) + return ret; + + init->is_registered = true; + return link_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); +} + +static struct memory_initiator * __init add_memory_initiator(int pxm) +{ + struct memory_initiator *init; + + if (pxm_to_node(pxm) == NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", pxm); + bad_hmat = true; + return ERR_PTR(-EINVAL); + } + + /* + * Make sure we haven't already added an initiator for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (apic_id, etc), so we just use the data from the first table + * we see for a given proximity domain. + */ + list_for_each_entry(init, &initiator_list, list) + if (init->pxm == pxm) + return 0; + + init = kzalloc(sizeof(*init), GFP_KERNEL); + if (!init) { + bad_hmat = true; + return ERR_PTR(-ENOMEM); + } + + init->pxm = pxm; + + list_add_tail(&init->list, &initiator_list); + return init; +} + +/* memory targets */ +static void release_memory_target(struct device *dev) +{ + struct memory_target *tgt = to_memory_target(dev); + + list_del(&tgt->list); + kfree(tgt); +} + +static void __init remove_memory_target(struct memory_target *tgt) +{ + if (tgt->is_registered) { + remove_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); + device_unregister(&tgt->dev); + } else + release_memory_target(&tgt->dev); +} + +static int __init register_memory_target(struct memory_target *tgt) +{ + int ret; + + if (!tgt->ma || !tgt->spa) { + pr_err("HMAT: Incomplete memory target found\n"); + return -EINVAL; + } + + hmat_subsys.dev_name = "mem_tgt"; + tgt->dev.bus = &hmat_subsys; + tgt->dev.id = pxm_to_node(tgt->ma->proximity_domain); + tgt->dev.release = release_memory_target; + tgt->dev.groups = memory_target_attribute_groups; + + ret = device_register(&tgt->dev); + if (ret < 0) + return ret; + + tgt->is_registered = true; + + return link_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); +} + +static int __init add_memory_target(struct acpi_srat_mem_affinity *ma) +{ + struct memory_target *tgt; + + if (pxm_to_node(ma->proximity_domain) == NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", ma->proximity_domain); + bad_hmat = true; + return -EINVAL; + } + + /* + * Make sure we haven't already added a target for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (base_address, length), so we just use the data from the + * first table we see for a given proximity domain. + */ + list_for_each_entry(tgt, &target_list, list) + if (tgt->ma->proximity_domain == ma->proximity_domain) + return 0; + + tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); + if (!tgt) { + bad_hmat = true; + return -ENOMEM; + } + + tgt->ma = ma; + + list_add_tail(&tgt->list, &target_list); + return 0; +} + +/* ACPI parsing code, starting with the HMAT */ +static int __init hmat_noop_parse(struct acpi_table_header *table) +{ + /* real work done by the hmat_parse_* and srat_parse_* routines */ + return 0; +} + +static bool __init hmat_spa_matches_srat(struct acpi_hmat_address_range *spa, + struct acpi_srat_mem_affinity *ma) +{ + if (spa->physical_address_base != ma->base_address || + spa->physical_address_length != ma->length) + return false; + + return true; +} + +static void find_local_initiator(struct memory_target *tgt) +{ + struct memory_initiator *init; + + if (!(tgt->spa->flags & ACPI_HMAT_PROCESSOR_PD_VALID) || + pxm_to_node(tgt->spa->processor_PD) == NUMA_NO_NODE) + return; + + list_for_each_entry(init, &initiator_list, list) { + if (init->pxm == tgt->spa->processor_PD) { + tgt->local_init = init; + return; + } + } +} + +/* ACPI HMAT parsing routines */ +static int __init +hmat_parse_address_range(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_address_range *spa; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + spa = (struct acpi_hmat_address_range *)header; + if (!spa) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (spa->header.length != sizeof(*spa)) { + pr_err("HMAT: Unexpected header length: %d\n", + spa->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if ((spa->flags & ACPI_HMAT_MEMORY_PD_VALID) && + spa->memory_PD == tgt->ma->proximity_domain) { + /* + * We only add a single HMAT target per proximity + * domain so we wait for the one that matches the + * single SRAT memory affinity structure per PXM we + * saved in add_memory_target(). + */ + if (hmat_spa_matches_srat(spa, tgt->ma)) { + tgt->spa = spa; + find_local_initiator(tgt); + } + return 0; + } + } + + return 0; +err: + bad_hmat = true; + return -EINVAL; +} + +static int __init hmat_parse_cache(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_cache *cache; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + cache = (struct acpi_hmat_cache *)header; + if (!cache) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (cache->header.length < sizeof(*cache)) { + pr_err("HMAT: Unexpected header length: %d\n", + cache->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if (cache->memory_PD == tgt->ma->proximity_domain) { + tgt->is_cached = true; + return 0; + } + } + + pr_err("HMAT: Couldn't find cached target PXM %d\n", cache->memory_PD); +err: + bad_hmat = true; + return -EINVAL; +} + +/* + * SRAT parsing. We use srat_disabled() and pxm_to_node() so we don't redo + * any of the SRAT sanity checking done in drivers/acpi/numa.c. + */ +static int __init +srat_parse_processor_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_cpu_affinity *cpu; + struct memory_initiator *init; + u32 pxm; + + if (bad_hmat) + return 0; + + cpu = (struct acpi_srat_cpu_affinity *)header; + if (!cpu) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + pxm = cpu->proximity_domain_lo; + if (acpi_srat_revision >= 2) + pxm |= *((unsigned int *)cpu->proximity_domain_hi) << 8; + + if (!(cpu->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init = add_memory_initiator(pxm); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->cpu = cpu; + return 0; +} + +static int __init +srat_parse_x2apic_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + x2apic = (struct acpi_srat_x2apic_cpu_affinity *)header; + if (!x2apic) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(x2apic->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init = add_memory_initiator(x2apic->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->x2apic = x2apic; + return 0; +} + +static int __init +srat_parse_gicc_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_gicc_affinity *gicc; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + gicc = (struct acpi_srat_gicc_affinity *)header; + if (!gicc) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(gicc->flags & ACPI_SRAT_GICC_ENABLED)) + return 0; + + init = add_memory_initiator(gicc->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->gicc = gicc; + return 0; +} + +static int __init +srat_parse_memory_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_mem_affinity *ma; + + if (bad_hmat) + return 0; + + ma = (struct acpi_srat_mem_affinity *)header; + if (!ma) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) + return 0; + + return add_memory_target(ma); +} + +/* + * Remove our sysfs entries, unregister our devices and free allocated memory. + */ +static void hmat_cleanup(void) +{ + struct memory_initiator *init, *init_iter; + struct memory_target *tgt, *tgt_iter; + + list_for_each_entry_safe(tgt, tgt_iter, &target_list, list) + remove_memory_target(tgt); + + list_for_each_entry_safe(init, init_iter, &initiator_list, list) + remove_memory_initiator(init); +} + +static int __init hmat_init(void) +{ + struct acpi_table_header *tbl; + struct memory_initiator *init; + struct memory_target *tgt; + acpi_status status = AE_OK; + int ret; + + if (srat_disabled()) + return 0; + + /* + * We take a permanent reference to both the HMAT and SRAT in ACPI + * memory so we can keep pointers to their subtables. These tables + * already had references on them which would never be released, taken + * by acpi_sysfs_init(), so this shouldn't negatively impact anything. + */ + status = acpi_get_table(ACPI_SIG_SRAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + ret = subsys_system_register(&hmat_subsys, NULL); + if (ret) + return ret; + + if (!acpi_table_parse(ACPI_SIG_SRAT, hmat_noop_parse)) { + struct acpi_subtable_proc srat_proc[4]; + + memset(srat_proc, 0, sizeof(srat_proc)); + srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; + srat_proc[0].handler = srat_parse_processor_affinity; + srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; + srat_proc[1].handler = srat_parse_x2apic_affinity; + srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY; + srat_proc[2].handler = srat_parse_gicc_affinity; + srat_proc[3].id = ACPI_SRAT_TYPE_MEMORY_AFFINITY; + srat_proc[3].handler = srat_parse_memory_affinity; + + acpi_table_parse_entries_array(ACPI_SIG_SRAT, + sizeof(struct acpi_table_srat), + srat_proc, ARRAY_SIZE(srat_proc), 0); + } + + if (!acpi_table_parse(ACPI_SIG_HMAT, hmat_noop_parse)) { + struct acpi_subtable_proc hmat_proc[2]; + + memset(hmat_proc, 0, sizeof(hmat_proc)); + hmat_proc[0].id = ACPI_HMAT_TYPE_ADDRESS_RANGE; + hmat_proc[0].handler = hmat_parse_address_range; + hmat_proc[1].id = ACPI_HMAT_TYPE_CACHE; + hmat_proc[1].handler = hmat_parse_cache; + + acpi_table_parse_entries_array(ACPI_SIG_HMAT, + sizeof(struct acpi_table_hmat), + hmat_proc, ARRAY_SIZE(hmat_proc), 0); + } + + if (bad_hmat) { + ret = -EINVAL; + goto err; + } + + list_for_each_entry(init, &initiator_list, list) { + ret = register_memory_initiator(init); + if (ret) + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + ret = register_memory_target(tgt); + if (ret) + goto err; + } + + return 0; +err: + pr_err("HMAT: Error during initialization\n"); + hmat_cleanup(); + return ret; +} + +static __exit void hmat_exit(void) +{ + hmat_cleanup(); +} + +module_init(hmat_init); +module_exit(hmat_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/acpi/hmat/hmat.h b/drivers/acpi/hmat/hmat.h new file mode 100644 index 000000000000..108aad1f8ad7 --- /dev/null +++ b/drivers/acpi/hmat/hmat.h @@ -0,0 +1,47 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _ACPI_HMAT_H_ +#define _ACPI_HMAT_H_ + +struct memory_initiator { + struct list_head list; + struct device dev; + + /* only one of the following three will be set */ + struct acpi_srat_cpu_affinity *cpu; + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct acpi_srat_gicc_affinity *gicc; + + int pxm; + bool is_registered; +}; +#define to_memory_initiator(d) container_of((d), struct memory_initiator, dev) + +struct memory_target { + struct list_head list; + struct device dev; + struct acpi_srat_mem_affinity *ma; + struct acpi_hmat_address_range *spa; + struct memory_initiator *local_init; + + bool is_cached; + bool is_registered; +}; +#define to_memory_target(d) container_of((d), struct memory_target, dev) + +extern const struct attribute_group *memory_initiator_attribute_groups[]; +extern const struct attribute_group *memory_target_attribute_groups[]; +#endif /* _ACPI_HMAT_H_ */ diff --git a/drivers/acpi/hmat/initiator.c b/drivers/acpi/hmat/initiator.c new file mode 100644 index 000000000000..be2bf2b58940 --- /dev/null +++ b/drivers/acpi/hmat/initiator.c @@ -0,0 +1,43 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs initiator representation + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_initiator *init = to_memory_initiator(dev); + + return sprintf(buf, "%d\n", init->pxm); +} +static DEVICE_ATTR_RO(firmware_id); + +static struct attribute *memory_initiator_attributes[] = { + &dev_attr_firmware_id.attr, + NULL, +}; + +static struct attribute_group memory_initiator_attribute_group = { + .attrs = memory_initiator_attributes, +}; + +const struct attribute_group *memory_initiator_attribute_groups[] = { + &memory_initiator_attribute_group, + NULL, +}; diff --git a/drivers/acpi/hmat/target.c b/drivers/acpi/hmat/target.c new file mode 100644 index 000000000000..2a9b44d5f44c --- /dev/null +++ b/drivers/acpi/hmat/target.c @@ -0,0 +1,55 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs target representation + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +/* attributes for memory targets */ +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt = to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->ma->proximity_domain); +} +static DEVICE_ATTR_RO(firmware_id); + +static ssize_t is_cached_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt = to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->is_cached); +} +static DEVICE_ATTR_RO(is_cached); + +static struct attribute *memory_target_attributes[] = { + &dev_attr_firmware_id.attr, + &dev_attr_is_cached.attr, + NULL +}; + +/* attributes which are present for all memory targets */ +static struct attribute_group memory_target_attribute_group = { + .attrs = memory_target_attributes, +}; + +const struct attribute_group *memory_target_attribute_groups[] = { + &memory_target_attribute_group, + NULL, +}; -- 2.14.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752247AbdLNCKy (ORCPT ); Wed, 13 Dec 2017 21:10:54 -0500 Received: from mga01.intel.com ([192.55.52.88]:64707 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751917AbdLNCKd (ORCPT ); Wed, 13 Dec 2017 21:10:33 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,399,1508828400"; d="scan'208";a="2623240" From: Ross Zwisler To: linux-kernel@vger.kernel.org Cc: Ross Zwisler , "Anaczkowski, Lukasz" , "Box, David E" , "Kogut, Jaroslaw" , "Koss, Marcin" , "Koziej, Artur" , "Lahtinen, Joonas" , "Moore, Robert" , "Nachimuthu, Murugasamy" , "Odzioba, Lukasz" , "Rafael J. Wysocki" , "Rafael J. Wysocki" , "Schmauss, Erik" , "Verma, Vishal L" , "Zheng, Lv" , Andrew Morton , Balbir Singh , Brice Goglin , Dan Williams , Dave Hansen , Jerome Glisse , John Hubbard , Len Brown , Tim Chen , devel@acpica.org, linux-acpi@vger.kernel.org, linux-mm@kvack.org, linux-nvdimm@lists.01.org Subject: [PATCH v3 2/3] hmat: add heterogeneous memory sysfs support Date: Wed, 13 Dec 2017 19:10:18 -0700 Message-Id: <20171214021019.13579-3-ross.zwisler@linux.intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171214021019.13579-1-ross.zwisler@linux.intel.com> References: <20171214021019.13579-1-ross.zwisler@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a new sysfs subsystem, /sys/devices/system/hmat, which surfaces information about memory initiators and memory targets to the user. These initiators and targets are described by the ACPI SRAT and HMAT tables. A "memory initiator" in this case is a NUMA node containing one or more devices such as CPU or separate memory I/O devices that can initiate memory requests. A "memory target" is NUMA node containing at least one CPU-accessible physical address range. The key piece of information surfaced by this patch is the mapping between the ACPI table "proximity domain" numbers, held in the "firmware_id" attribute, and Linux NUMA node numbers. Every ACPI proximity domain will end up being a unique NUMA node in Linux, but the numbers may get reordered and Linux can create extra NUMA nodes that don't map back to ACPI proximity domains. The firmware_id value is needed if anyone ever wants to look at the ACPI HMAT and SRAT tables directly and make sense of how they map to NUMA nodes in Linux. Initiators are found at /sys/devices/system/hmat/mem_initX, and the attributes for a given initiator look like this: # tree mem_init0 mem_init0 ├── firmware_id ├── node0 -> ../../node/node0 ├── power │   ├── async │   ... ├── subsystem -> ../../../../bus/hmat └── uevent Where "mem_init0" on my system represents the CPU acting as a memory initiator at NUMA node 0. Users can discover which CPUs are part of this memory initiator by following the node0 symlink and looking at cpumap, cpulist and the cpu* symlinks. Targets are found at /sys/devices/system/hmat/mem_tgtX, and the attributes for a given target look like this: # tree mem_tgt2 mem_tgt2 ├── firmware_id ├── is_cached ├── node2 -> ../../node/node2 ├── power │   ├── async │   ... ├── subsystem -> ../../../../bus/hmat └── uevent Users can discover information about the memory owned by this memory target by following the node2 symlink and looking at meminfo, vmstat and at the memory* memory section symlinks. Signed-off-by: Ross Zwisler --- MAINTAINERS | 6 + drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 7 + drivers/acpi/hmat/Makefile | 2 + drivers/acpi/hmat/core.c | 536 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/hmat/hmat.h | 47 ++++ drivers/acpi/hmat/initiator.c | 43 ++++ drivers/acpi/hmat/target.c | 55 +++++ 9 files changed, 698 insertions(+) create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/core.c create mode 100644 drivers/acpi/hmat/hmat.h create mode 100644 drivers/acpi/hmat/initiator.c create mode 100644 drivers/acpi/hmat/target.c diff --git a/MAINTAINERS b/MAINTAINERS index 82ad0eabce4f..64ebec0708de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6366,6 +6366,12 @@ S: Supported F: drivers/scsi/hisi_sas/ F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +HMAT - ACPI Heterogeneous Memory Attribute Table Support +M: Ross Zwisler +L: linux-mm@kvack.org +S: Supported +F: drivers/acpi/hmat/ + HMM - Heterogeneous Memory Management M: Jérôme Glisse L: linux-mm@kvack.org diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 46505396869e..21cdd1288430 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -466,6 +466,7 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. source "drivers/acpi/nfit/Kconfig" +source "drivers/acpi/hmat/Kconfig" source "drivers/acpi/apei/Kconfig" source "drivers/acpi/dptf/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 41954a601989..ed5eab6b0412 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_NFIT) += nfit/ +obj-$(CONFIG_ACPI_HMAT) += hmat/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o obj-$(CONFIG_ACPI_BATTERY) += battery.o diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig new file mode 100644 index 000000000000..954ad4701005 --- /dev/null +++ b/drivers/acpi/hmat/Kconfig @@ -0,0 +1,7 @@ +config ACPI_HMAT + bool "ACPI Heterogeneous Memory Attribute Table Support" + depends on ACPI_NUMA + depends on SYSFS + help + Exports a sysfs representation of the ACPI Heterogeneous Memory + Attributes Table (HMAT). diff --git a/drivers/acpi/hmat/Makefile b/drivers/acpi/hmat/Makefile new file mode 100644 index 000000000000..edf4bcb1c97d --- /dev/null +++ b/drivers/acpi/hmat/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ACPI_HMAT) := hmat.o +hmat-y := core.o initiator.o target.o diff --git a/drivers/acpi/hmat/core.c b/drivers/acpi/hmat/core.c new file mode 100644 index 000000000000..61b90dadf84b --- /dev/null +++ b/drivers/acpi/hmat/core.c @@ -0,0 +1,536 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmat.h" + +static LIST_HEAD(target_list); +static LIST_HEAD(initiator_list); + +static bool bad_hmat; + +static int link_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + return sysfs_create_link(kobj, &node_devices[node]->dev.kobj, + kobject_name(&node_devices[node]->dev.kobj)); + return 0; +} + +static void remove_node_for_kobj(unsigned int node, struct kobject *kobj) +{ + if (node_devices[node]) + sysfs_remove_link(kobj, + kobject_name(&node_devices[node]->dev.kobj)); +} + +#define HMAT_CLASS_NAME "hmat" + +static struct bus_type hmat_subsys = { + /* + * .dev_name is set before device_register() based on the type of + * device we are registering. + */ + .name = HMAT_CLASS_NAME, +}; + +/* memory initiators */ +static void release_memory_initiator(struct device *dev) +{ + struct memory_initiator *init = to_memory_initiator(dev); + + list_del(&init->list); + kfree(init); +} + +static void __init remove_memory_initiator(struct memory_initiator *init) +{ + if (init->is_registered) { + remove_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); + device_unregister(&init->dev); + } else + release_memory_initiator(&init->dev); +} + +static int __init register_memory_initiator(struct memory_initiator *init) +{ + int ret; + + hmat_subsys.dev_name = "mem_init"; + init->dev.bus = &hmat_subsys; + init->dev.id = pxm_to_node(init->pxm); + init->dev.release = release_memory_initiator; + init->dev.groups = memory_initiator_attribute_groups; + + ret = device_register(&init->dev); + if (ret < 0) + return ret; + + init->is_registered = true; + return link_node_for_kobj(pxm_to_node(init->pxm), &init->dev.kobj); +} + +static struct memory_initiator * __init add_memory_initiator(int pxm) +{ + struct memory_initiator *init; + + if (pxm_to_node(pxm) == NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", pxm); + bad_hmat = true; + return ERR_PTR(-EINVAL); + } + + /* + * Make sure we haven't already added an initiator for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (apic_id, etc), so we just use the data from the first table + * we see for a given proximity domain. + */ + list_for_each_entry(init, &initiator_list, list) + if (init->pxm == pxm) + return 0; + + init = kzalloc(sizeof(*init), GFP_KERNEL); + if (!init) { + bad_hmat = true; + return ERR_PTR(-ENOMEM); + } + + init->pxm = pxm; + + list_add_tail(&init->list, &initiator_list); + return init; +} + +/* memory targets */ +static void release_memory_target(struct device *dev) +{ + struct memory_target *tgt = to_memory_target(dev); + + list_del(&tgt->list); + kfree(tgt); +} + +static void __init remove_memory_target(struct memory_target *tgt) +{ + if (tgt->is_registered) { + remove_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); + device_unregister(&tgt->dev); + } else + release_memory_target(&tgt->dev); +} + +static int __init register_memory_target(struct memory_target *tgt) +{ + int ret; + + if (!tgt->ma || !tgt->spa) { + pr_err("HMAT: Incomplete memory target found\n"); + return -EINVAL; + } + + hmat_subsys.dev_name = "mem_tgt"; + tgt->dev.bus = &hmat_subsys; + tgt->dev.id = pxm_to_node(tgt->ma->proximity_domain); + tgt->dev.release = release_memory_target; + tgt->dev.groups = memory_target_attribute_groups; + + ret = device_register(&tgt->dev); + if (ret < 0) + return ret; + + tgt->is_registered = true; + + return link_node_for_kobj(pxm_to_node(tgt->ma->proximity_domain), + &tgt->dev.kobj); +} + +static int __init add_memory_target(struct acpi_srat_mem_affinity *ma) +{ + struct memory_target *tgt; + + if (pxm_to_node(ma->proximity_domain) == NUMA_NO_NODE) { + pr_err("HMAT: No NUMA node for PXM %d\n", ma->proximity_domain); + bad_hmat = true; + return -EINVAL; + } + + /* + * Make sure we haven't already added a target for this proximity + * domain. We don't care about any other differences in the SRAT + * tables (base_address, length), so we just use the data from the + * first table we see for a given proximity domain. + */ + list_for_each_entry(tgt, &target_list, list) + if (tgt->ma->proximity_domain == ma->proximity_domain) + return 0; + + tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); + if (!tgt) { + bad_hmat = true; + return -ENOMEM; + } + + tgt->ma = ma; + + list_add_tail(&tgt->list, &target_list); + return 0; +} + +/* ACPI parsing code, starting with the HMAT */ +static int __init hmat_noop_parse(struct acpi_table_header *table) +{ + /* real work done by the hmat_parse_* and srat_parse_* routines */ + return 0; +} + +static bool __init hmat_spa_matches_srat(struct acpi_hmat_address_range *spa, + struct acpi_srat_mem_affinity *ma) +{ + if (spa->physical_address_base != ma->base_address || + spa->physical_address_length != ma->length) + return false; + + return true; +} + +static void find_local_initiator(struct memory_target *tgt) +{ + struct memory_initiator *init; + + if (!(tgt->spa->flags & ACPI_HMAT_PROCESSOR_PD_VALID) || + pxm_to_node(tgt->spa->processor_PD) == NUMA_NO_NODE) + return; + + list_for_each_entry(init, &initiator_list, list) { + if (init->pxm == tgt->spa->processor_PD) { + tgt->local_init = init; + return; + } + } +} + +/* ACPI HMAT parsing routines */ +static int __init +hmat_parse_address_range(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_address_range *spa; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + spa = (struct acpi_hmat_address_range *)header; + if (!spa) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (spa->header.length != sizeof(*spa)) { + pr_err("HMAT: Unexpected header length: %d\n", + spa->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if ((spa->flags & ACPI_HMAT_MEMORY_PD_VALID) && + spa->memory_PD == tgt->ma->proximity_domain) { + /* + * We only add a single HMAT target per proximity + * domain so we wait for the one that matches the + * single SRAT memory affinity structure per PXM we + * saved in add_memory_target(). + */ + if (hmat_spa_matches_srat(spa, tgt->ma)) { + tgt->spa = spa; + find_local_initiator(tgt); + } + return 0; + } + } + + return 0; +err: + bad_hmat = true; + return -EINVAL; +} + +static int __init hmat_parse_cache(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_hmat_cache *cache; + struct memory_target *tgt; + + if (bad_hmat) + return 0; + + cache = (struct acpi_hmat_cache *)header; + if (!cache) { + pr_err("HMAT: NULL table entry\n"); + goto err; + } + + if (cache->header.length < sizeof(*cache)) { + pr_err("HMAT: Unexpected header length: %d\n", + cache->header.length); + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + if (cache->memory_PD == tgt->ma->proximity_domain) { + tgt->is_cached = true; + return 0; + } + } + + pr_err("HMAT: Couldn't find cached target PXM %d\n", cache->memory_PD); +err: + bad_hmat = true; + return -EINVAL; +} + +/* + * SRAT parsing. We use srat_disabled() and pxm_to_node() so we don't redo + * any of the SRAT sanity checking done in drivers/acpi/numa.c. + */ +static int __init +srat_parse_processor_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_cpu_affinity *cpu; + struct memory_initiator *init; + u32 pxm; + + if (bad_hmat) + return 0; + + cpu = (struct acpi_srat_cpu_affinity *)header; + if (!cpu) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + pxm = cpu->proximity_domain_lo; + if (acpi_srat_revision >= 2) + pxm |= *((unsigned int *)cpu->proximity_domain_hi) << 8; + + if (!(cpu->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init = add_memory_initiator(pxm); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->cpu = cpu; + return 0; +} + +static int __init +srat_parse_x2apic_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + x2apic = (struct acpi_srat_x2apic_cpu_affinity *)header; + if (!x2apic) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(x2apic->flags & ACPI_SRAT_CPU_ENABLED)) + return 0; + + init = add_memory_initiator(x2apic->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->x2apic = x2apic; + return 0; +} + +static int __init +srat_parse_gicc_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_gicc_affinity *gicc; + struct memory_initiator *init; + + if (bad_hmat) + return 0; + + gicc = (struct acpi_srat_gicc_affinity *)header; + if (!gicc) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(gicc->flags & ACPI_SRAT_GICC_ENABLED)) + return 0; + + init = add_memory_initiator(gicc->proximity_domain); + if (IS_ERR_OR_NULL(init)) + return PTR_ERR(init); + + init->gicc = gicc; + return 0; +} + +static int __init +srat_parse_memory_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_mem_affinity *ma; + + if (bad_hmat) + return 0; + + ma = (struct acpi_srat_mem_affinity *)header; + if (!ma) { + pr_err("HMAT: NULL table entry\n"); + bad_hmat = true; + return -EINVAL; + } + + if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) + return 0; + + return add_memory_target(ma); +} + +/* + * Remove our sysfs entries, unregister our devices and free allocated memory. + */ +static void hmat_cleanup(void) +{ + struct memory_initiator *init, *init_iter; + struct memory_target *tgt, *tgt_iter; + + list_for_each_entry_safe(tgt, tgt_iter, &target_list, list) + remove_memory_target(tgt); + + list_for_each_entry_safe(init, init_iter, &initiator_list, list) + remove_memory_initiator(init); +} + +static int __init hmat_init(void) +{ + struct acpi_table_header *tbl; + struct memory_initiator *init; + struct memory_target *tgt; + acpi_status status = AE_OK; + int ret; + + if (srat_disabled()) + return 0; + + /* + * We take a permanent reference to both the HMAT and SRAT in ACPI + * memory so we can keep pointers to their subtables. These tables + * already had references on them which would never be released, taken + * by acpi_sysfs_init(), so this shouldn't negatively impact anything. + */ + status = acpi_get_table(ACPI_SIG_SRAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl); + if (ACPI_FAILURE(status)) + return 0; + + ret = subsys_system_register(&hmat_subsys, NULL); + if (ret) + return ret; + + if (!acpi_table_parse(ACPI_SIG_SRAT, hmat_noop_parse)) { + struct acpi_subtable_proc srat_proc[4]; + + memset(srat_proc, 0, sizeof(srat_proc)); + srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; + srat_proc[0].handler = srat_parse_processor_affinity; + srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; + srat_proc[1].handler = srat_parse_x2apic_affinity; + srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY; + srat_proc[2].handler = srat_parse_gicc_affinity; + srat_proc[3].id = ACPI_SRAT_TYPE_MEMORY_AFFINITY; + srat_proc[3].handler = srat_parse_memory_affinity; + + acpi_table_parse_entries_array(ACPI_SIG_SRAT, + sizeof(struct acpi_table_srat), + srat_proc, ARRAY_SIZE(srat_proc), 0); + } + + if (!acpi_table_parse(ACPI_SIG_HMAT, hmat_noop_parse)) { + struct acpi_subtable_proc hmat_proc[2]; + + memset(hmat_proc, 0, sizeof(hmat_proc)); + hmat_proc[0].id = ACPI_HMAT_TYPE_ADDRESS_RANGE; + hmat_proc[0].handler = hmat_parse_address_range; + hmat_proc[1].id = ACPI_HMAT_TYPE_CACHE; + hmat_proc[1].handler = hmat_parse_cache; + + acpi_table_parse_entries_array(ACPI_SIG_HMAT, + sizeof(struct acpi_table_hmat), + hmat_proc, ARRAY_SIZE(hmat_proc), 0); + } + + if (bad_hmat) { + ret = -EINVAL; + goto err; + } + + list_for_each_entry(init, &initiator_list, list) { + ret = register_memory_initiator(init); + if (ret) + goto err; + } + + list_for_each_entry(tgt, &target_list, list) { + ret = register_memory_target(tgt); + if (ret) + goto err; + } + + return 0; +err: + pr_err("HMAT: Error during initialization\n"); + hmat_cleanup(); + return ret; +} + +static __exit void hmat_exit(void) +{ + hmat_cleanup(); +} + +module_init(hmat_init); +module_exit(hmat_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/acpi/hmat/hmat.h b/drivers/acpi/hmat/hmat.h new file mode 100644 index 000000000000..108aad1f8ad7 --- /dev/null +++ b/drivers/acpi/hmat/hmat.h @@ -0,0 +1,47 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) representation in sysfs + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _ACPI_HMAT_H_ +#define _ACPI_HMAT_H_ + +struct memory_initiator { + struct list_head list; + struct device dev; + + /* only one of the following three will be set */ + struct acpi_srat_cpu_affinity *cpu; + struct acpi_srat_x2apic_cpu_affinity *x2apic; + struct acpi_srat_gicc_affinity *gicc; + + int pxm; + bool is_registered; +}; +#define to_memory_initiator(d) container_of((d), struct memory_initiator, dev) + +struct memory_target { + struct list_head list; + struct device dev; + struct acpi_srat_mem_affinity *ma; + struct acpi_hmat_address_range *spa; + struct memory_initiator *local_init; + + bool is_cached; + bool is_registered; +}; +#define to_memory_target(d) container_of((d), struct memory_target, dev) + +extern const struct attribute_group *memory_initiator_attribute_groups[]; +extern const struct attribute_group *memory_target_attribute_groups[]; +#endif /* _ACPI_HMAT_H_ */ diff --git a/drivers/acpi/hmat/initiator.c b/drivers/acpi/hmat/initiator.c new file mode 100644 index 000000000000..be2bf2b58940 --- /dev/null +++ b/drivers/acpi/hmat/initiator.c @@ -0,0 +1,43 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs initiator representation + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_initiator *init = to_memory_initiator(dev); + + return sprintf(buf, "%d\n", init->pxm); +} +static DEVICE_ATTR_RO(firmware_id); + +static struct attribute *memory_initiator_attributes[] = { + &dev_attr_firmware_id.attr, + NULL, +}; + +static struct attribute_group memory_initiator_attribute_group = { + .attrs = memory_initiator_attributes, +}; + +const struct attribute_group *memory_initiator_attribute_groups[] = { + &memory_initiator_attribute_group, + NULL, +}; diff --git a/drivers/acpi/hmat/target.c b/drivers/acpi/hmat/target.c new file mode 100644 index 000000000000..2a9b44d5f44c --- /dev/null +++ b/drivers/acpi/hmat/target.c @@ -0,0 +1,55 @@ +/* + * Heterogeneous Memory Attributes Table (HMAT) sysfs target representation + * + * Copyright (c) 2017, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include "hmat.h" + +/* attributes for memory targets */ +static ssize_t firmware_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt = to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->ma->proximity_domain); +} +static DEVICE_ATTR_RO(firmware_id); + +static ssize_t is_cached_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct memory_target *tgt = to_memory_target(dev); + + return sprintf(buf, "%d\n", tgt->is_cached); +} +static DEVICE_ATTR_RO(is_cached); + +static struct attribute *memory_target_attributes[] = { + &dev_attr_firmware_id.attr, + &dev_attr_is_cached.attr, + NULL +}; + +/* attributes which are present for all memory targets */ +static struct attribute_group memory_target_attribute_group = { + .attrs = memory_target_attributes, +}; + +const struct attribute_group *memory_target_attribute_groups[] = { + &memory_target_attribute_group, + NULL, +}; -- 2.14.3