From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56870C433F5 for ; Tue, 30 Nov 2021 12:08:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241390AbhK3MLq (ORCPT ); Tue, 30 Nov 2021 07:11:46 -0500 Received: from szxga02-in.huawei.com ([45.249.212.188]:16325 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236174AbhK3MLN (ORCPT ); Tue, 30 Nov 2021 07:11:13 -0500 Received: from dggemv711-chm.china.huawei.com (unknown [172.30.72.54]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4J3LZ10d3rz91RC; Tue, 30 Nov 2021 20:07:21 +0800 (CST) Received: from kwepemm600003.china.huawei.com (7.193.23.202) by dggemv711-chm.china.huawei.com (10.1.198.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 30 Nov 2021 20:07:52 +0800 Received: from localhost.localdomain (10.67.165.103) by kwepemm600003.china.huawei.com (7.193.23.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 30 Nov 2021 20:07:52 +0800 From: Qi Liu To: , , CC: , , , , Subject: [PATCH v12 2/2] drivers/perf: hisi: Add driver for HiSilicon PCIe PMU Date: Tue, 30 Nov 2021 20:04:50 +0800 Message-ID: <20211130120450.2747-3-liuqi115@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211130120450.2747-1-liuqi115@huawei.com> References: <20211130120450.2747-1-liuqi115@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-Originating-IP: [10.67.165.103] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To kwepemm600003.china.huawei.com (7.193.23.202) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org PCIe PMU Root Complex Integrated End Point(RCiEP) device is supported to sample bandwidth, latency, buffer occupation etc. Each PMU RCiEP device monitors multiple Root Ports, and each RCiEP is registered as a PMU in /sys/bus/event_source/devices, so users can select target PMU, and use filter to do further sets. Filtering options contains: event - select the event. port - select target Root Ports. Information of Root Ports are shown under sysfs. bdf - select requester_id of target EP device. trig_len - set trigger condition for starting event statistics. trig_mode - set trigger mode. 0 means starting to statistic when bigger than trigger condition, and 1 means smaller. thr_len - set threshold for statistics. thr_mode - set threshold mode. 0 means count when bigger than threshold, and 1 means smaller. Acked-by: Krzysztof WilczyƄski Reviewed-by: John Garry Signed-off-by: Qi Liu --- MAINTAINERS | 2 + drivers/perf/hisilicon/Kconfig | 9 + drivers/perf/hisilicon/Makefile | 2 + drivers/perf/hisilicon/hisi_pcie_pmu.c | 948 +++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 5 files changed, 962 insertions(+) create mode 100644 drivers/perf/hisilicon/hisi_pcie_pmu.c diff --git a/MAINTAINERS b/MAINTAINERS index 5b33791bb8e9..94e71ab69870 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8453,8 +8453,10 @@ F: Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.yaml HISILICON PMU DRIVER M: Shaokun Zhang +M: Qi Liu S: Supported W: http://www.hisilicon.com +F: Documentation/admin-guide/perf/hisi-pcie-pmu.rst F: Documentation/admin-guide/perf/hisi-pmu.rst F: drivers/perf/hisilicon diff --git a/drivers/perf/hisilicon/Kconfig b/drivers/perf/hisilicon/Kconfig index c5d1b7019fff..5546218b5598 100644 --- a/drivers/perf/hisilicon/Kconfig +++ b/drivers/perf/hisilicon/Kconfig @@ -5,3 +5,12 @@ config HISI_PMU help Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home Agent performance monitor and DDR Controller performance monitor. + +config HISI_PCIE_PMU + tristate "HiSilicon PCIE PERF PMU" + depends on PCI && ARM64 + help + Provide support for HiSilicon PCIe performance monitoring unit (PMU) + RCiEP devices. + Adds the PCIe PMU into perf events system for monitoring latency, + bandwidth etc. diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile index 7643c9f93e36..506ed39e3266 100644 --- a/drivers/perf/hisilicon/Makefile +++ b/drivers/perf/hisilicon/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ hisi_uncore_pa_pmu.o + +obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c new file mode 100644 index 000000000000..aca5954e288d --- /dev/null +++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c @@ -0,0 +1,948 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * This driver adds support for PCIe PMU RCiEP device. Related + * perf events are bandwidth, latency etc. + * + * Copyright (C) 2021 HiSilicon Limited + * Author: Qi Liu + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "hisi_pcie_pmu" +/* Define registers */ +#define HISI_PCIE_GLOBAL_CTRL 0x00 +#define HISI_PCIE_EVENT_CTRL 0x010 +#define HISI_PCIE_CNT 0x090 +#define HISI_PCIE_EXT_CNT 0x110 +#define HISI_PCIE_INT_STAT 0x150 +#define HISI_PCIE_INT_MASK 0x154 +#define HISI_PCIE_REG_BDF 0xfe0 +#define HISI_PCIE_REG_VERSION 0xfe4 +#define HISI_PCIE_REG_INFO 0xfe8 + +/* Define command in HISI_PCIE_GLOBAL_CTRL */ +#define HISI_PCIE_GLOBAL_EN 0x01 +#define HISI_PCIE_GLOBAL_NONE 0 + +/* Define command in HISI_PCIE_EVENT_CTRL */ +#define HISI_PCIE_EVENT_EN BIT_ULL(20) +#define HISI_PCIE_RESET_CNT BIT_ULL(22) +#define HISI_PCIE_INIT_SET BIT_ULL(34) +#define HISI_PCIE_THR_EN BIT_ULL(26) +#define HISI_PCIE_TARGET_EN BIT_ULL(32) +#define HISI_PCIE_TRIG_EN BIT_ULL(52) + +/* Define offsets in HISI_PCIE_EVENT_CTRL */ +#define HISI_PCIE_EVENT_M GENMASK_ULL(15, 0) +#define HISI_PCIE_THR_MODE_M GENMASK_ULL(27, 27) +#define HISI_PCIE_THR_M GENMASK_ULL(31, 28) +#define HISI_PCIE_TARGET_M GENMASK_ULL(52, 36) +#define HISI_PCIE_TRIG_MODE_M GENMASK_ULL(53, 53) +#define HISI_PCIE_TRIG_M GENMASK_ULL(59, 56) + +#define HISI_PCIE_MAX_COUNTERS 8 +#define HISI_PCIE_REG_STEP 8 +#define HISI_PCIE_THR_MAX_VAL 10 +#define HISI_PCIE_TRIG_MAX_VAL 10 +#define HISI_PCIE_MAX_PERIOD (GENMASK_ULL(63, 0)) +#define HISI_PCIE_INIT_VAL BIT_ULL(63) + +struct hisi_pcie_pmu { + struct perf_event *hw_events[HISI_PCIE_MAX_COUNTERS]; + struct hlist_node node; + struct pci_dev *pdev; + struct pmu pmu; + void __iomem *base; + int irq; + u32 identifier; + /* Minimum and maximum BDF of root ports monitored by PMU */ + u16 bdf_min; + u16 bdf_max; + int on_cpu; +}; + +struct hisi_pcie_reg_pair { + u16 lo; + u16 hi; +}; + +#define to_pcie_pmu(p) (container_of((p), struct hisi_pcie_pmu, pmu)) +#define GET_PCI_DEVFN(bdf) ((bdf) & 0xff) + +#define HISI_PCIE_PMU_FILTER_ATTR(_name, _config, _hi, _lo) \ + static u64 hisi_pcie_get_##_name(struct perf_event *event) \ + { \ + return FIELD_GET(GENMASK(_hi, _lo), event->attr._config); \ + } \ + +HISI_PCIE_PMU_FILTER_ATTR(event, config, 16, 0); +HISI_PCIE_PMU_FILTER_ATTR(thr_len, config1, 3, 0); +HISI_PCIE_PMU_FILTER_ATTR(thr_mode, config1, 4, 4); +HISI_PCIE_PMU_FILTER_ATTR(trig_len, config1, 8, 5); +HISI_PCIE_PMU_FILTER_ATTR(trig_mode, config1, 9, 9); +HISI_PCIE_PMU_FILTER_ATTR(port, config2, 15, 0); +HISI_PCIE_PMU_FILTER_ATTR(bdf, config2, 31, 16); + +static ssize_t hisi_pcie_format_sysfs_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + + return sysfs_emit(buf, "%s\n", (char *)eattr->var); +} + +static ssize_t hisi_pcie_event_sysfs_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct perf_pmu_events_attr *pmu_attr = + container_of(attr, struct perf_pmu_events_attr, attr); + + return sysfs_emit(buf, "config=0x%llx\n", pmu_attr->id); +} + +#define HISI_PCIE_PMU_FORMAT_ATTR(_name, _format) \ + (&((struct dev_ext_attribute[]){ \ + { .attr = __ATTR(_name, 0444, hisi_pcie_format_sysfs_show, \ + NULL), \ + .var = (void *)_format } \ + })[0].attr.attr) + +#define HISI_PCIE_PMU_EVENT_ATTR(_name, _id) \ + PMU_EVENT_ATTR_ID(_name, hisi_pcie_event_sysfs_show, _id) + +static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); + + return cpumap_print_to_pagebuf(true, buf, cpumask_of(pcie_pmu->on_cpu)); +} +static DEVICE_ATTR_RO(cpumask); + +static ssize_t identifier_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); + + return sysfs_emit(buf, "%#x\n", pcie_pmu->identifier); +} +static DEVICE_ATTR_RO(identifier); + +static ssize_t bus_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); + + return sysfs_emit(buf, "%#04x\n", PCI_BUS_NUM(pcie_pmu->bdf_min)); +} +static DEVICE_ATTR_RO(bus); + +static struct hisi_pcie_reg_pair +hisi_pcie_parse_reg_value(struct hisi_pcie_pmu *pcie_pmu, u32 reg_off) +{ + u32 val = readl_relaxed(pcie_pmu->base + reg_off); + struct hisi_pcie_reg_pair regs = { + .lo = val, + .hi = val >> 16, + }; + + return regs; +} + +/* + * Hardware counter and ext_counter work together for bandwidth, latency, bus + * utilization and buffer occupancy events. For example, RX memory write latency + * events(index = 0x0010), counter counts total delay cycles and ext_counter + * counts RX memory write PCIe packets number. + * + * As we don't want PMU driver to process these two data, "delay cycles" can + * be treated as an independent event(index = 0x0010), "RX memory write packets + * number" as another(index = 0x10010). BIT 16 is used to distinguish and 0-15 + * bits are "real" event index, which can be used to set HISI_PCIE_EVENT_CTRL. + */ +#define EXT_COUNTER_IS_USED(idx) ((idx) & BIT(16)) + +static u32 hisi_pcie_get_real_event(struct perf_event *event) +{ + return hisi_pcie_get_event(event) & GENMASK(15, 0); +} + +static u32 hisi_pcie_pmu_get_offset(u32 offset, u32 idx) +{ + return offset + HISI_PCIE_REG_STEP * idx; +} + +static u32 hisi_pcie_pmu_readl(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, + u32 idx) +{ + u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); + + return readl_relaxed(pcie_pmu->base + offset); +} + +static void hisi_pcie_pmu_writel(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx, u32 val) +{ + u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); + + writel_relaxed(val, pcie_pmu->base + offset); +} + +static u64 hisi_pcie_pmu_readq(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx) +{ + u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); + + return readq_relaxed(pcie_pmu->base + offset); +} + +static void hisi_pcie_pmu_writeq(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx, u64 val) +{ + u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); + + writeq_relaxed(val, pcie_pmu->base + offset); +} + +static void hisi_pcie_pmu_config_filter(struct perf_event *event) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 reg = HISI_PCIE_INIT_SET; + u64 port, trig_len, thr_len; + + /* Config HISI_PCIE_EVENT_CTRL according to event. */ + reg |= FIELD_PREP(HISI_PCIE_EVENT_M, hisi_pcie_get_real_event(event)); + + /* Config HISI_PCIE_EVENT_CTRL according to root port or EP device. */ + port = hisi_pcie_get_port(event); + if (port) + reg |= FIELD_PREP(HISI_PCIE_TARGET_M, port); + else + reg |= HISI_PCIE_TARGET_EN | + FIELD_PREP(HISI_PCIE_TARGET_M, hisi_pcie_get_bdf(event)); + + /* Config HISI_PCIE_EVENT_CTRL according to trigger condition. */ + trig_len = hisi_pcie_get_trig_len(event); + if (trig_len) { + reg |= FIELD_PREP(HISI_PCIE_TRIG_M, trig_len); + reg |= FIELD_PREP(HISI_PCIE_TRIG_MODE_M, hisi_pcie_get_trig_mode(event)); + reg |= HISI_PCIE_TRIG_EN; + } + + /* Config HISI_PCIE_EVENT_CTRL according to threshold condition. */ + thr_len = hisi_pcie_get_thr_len(event); + if (thr_len) { + reg |= FIELD_PREP(HISI_PCIE_THR_M, thr_len); + reg |= FIELD_PREP(HISI_PCIE_THR_MODE_M, hisi_pcie_get_thr_mode(event)); + reg |= HISI_PCIE_THR_EN; + } + + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, reg); +} + +static void hisi_pcie_pmu_clear_filter(struct perf_event *event) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, HISI_PCIE_INIT_SET); +} + +static bool hisi_pcie_pmu_valid_requester_id(struct hisi_pcie_pmu *pcie_pmu, u32 bdf) +{ + struct pci_dev *root_port, *pdev; + u16 rp_bdf; + + pdev = pci_get_domain_bus_and_slot(pci_domain_nr(pcie_pmu->pdev->bus), PCI_BUS_NUM(bdf), + GET_PCI_DEVFN(bdf)); + if (!pdev) + return false; + + root_port = pcie_find_root_port(pdev); + if (!root_port) { + pci_dev_put(pdev); + return false; + } + + pci_dev_put(pdev); + rp_bdf = pci_dev_id(root_port); + return rp_bdf >= pcie_pmu->bdf_min && rp_bdf <= pcie_pmu->bdf_max; +} + +static bool hisi_pcie_pmu_valid_filter(struct perf_event *event, + struct hisi_pcie_pmu *pcie_pmu) +{ + u32 requester_id = hisi_pcie_get_bdf(event); + + if (hisi_pcie_get_thr_len(event) > HISI_PCIE_THR_MAX_VAL) + return false; + + if (hisi_pcie_get_trig_len(event) > HISI_PCIE_TRIG_MAX_VAL) + return false; + + if (requester_id) { + if (!hisi_pcie_pmu_valid_requester_id(pcie_pmu, requester_id)) + return false; + } + + return true; +} + +static bool hisi_pcie_pmu_cmp_event(struct perf_event *target, + struct perf_event *event) +{ + return hisi_pcie_get_real_event(target) == hisi_pcie_get_real_event(event); +} + +static bool hisi_pcie_pmu_validate_event_group(struct perf_event *event) +{ + struct perf_event *sibling, *leader = event->group_leader; + struct perf_event *event_group[HISI_PCIE_MAX_COUNTERS]; + int counters = 1; + int num; + + event_group[0] = leader; + if (!is_software_event(leader)) { + if (leader->pmu != event->pmu) + return false; + + if (leader != event && !hisi_pcie_pmu_cmp_event(leader, event)) + event_group[counters++] = event; + } + + for_each_sibling_event(sibling, event->group_leader) { + if (is_software_event(sibling)) + continue; + + if (sibling->pmu != event->pmu) + return false; + + for (num = 0; num < counters; num++) { + if (hisi_pcie_pmu_cmp_event(event_group[num], sibling)) + break; + } + + if (num == counters) + event_group[counters++] = sibling; + } + + return counters <= HISI_PCIE_MAX_COUNTERS; +} + +static int hisi_pcie_pmu_event_init(struct perf_event *event) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + event->cpu = pcie_pmu->on_cpu; + + if (EXT_COUNTER_IS_USED(hisi_pcie_get_event(event))) + hwc->event_base = HISI_PCIE_EXT_CNT; + else + hwc->event_base = HISI_PCIE_CNT; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + /* Sampling is not supported. */ + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + + if (!hisi_pcie_pmu_valid_filter(event, pcie_pmu)) + return -EINVAL; + + if (!hisi_pcie_pmu_validate_event_group(event)) + return -EINVAL; + + return 0; +} + +static u64 hisi_pcie_pmu_read_counter(struct perf_event *event) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + u32 idx = event->hw.idx; + + return hisi_pcie_pmu_readq(pcie_pmu, event->hw.event_base, idx); +} + +static int hisi_pcie_pmu_find_related_event(struct hisi_pcie_pmu *pcie_pmu, + struct perf_event *event) +{ + struct perf_event *sibling; + int idx; + + for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { + sibling = pcie_pmu->hw_events[idx]; + if (!sibling) + continue; + + if (!hisi_pcie_pmu_cmp_event(sibling, event)) + continue; + + /* Related events must be used in group */ + if (sibling->group_leader == event->group_leader) + return idx; + else + return -EINVAL; + } + + return idx; +} + +static int hisi_pcie_pmu_get_event_idx(struct hisi_pcie_pmu *pcie_pmu) +{ + int idx; + + for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { + if (!pcie_pmu->hw_events[idx]) + return idx; + } + + return -EINVAL; +} + +static void hisi_pcie_pmu_event_update(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 new_cnt, prev_cnt, delta; + + do { + prev_cnt = local64_read(&hwc->prev_count); + new_cnt = hisi_pcie_pmu_read_counter(event); + } while (local64_cmpxchg(&hwc->prev_count, prev_cnt, + new_cnt) != prev_cnt); + + delta = (new_cnt - prev_cnt) & HISI_PCIE_MAX_PERIOD; + local64_add(delta, &event->count); +} + +static void hisi_pcie_pmu_read(struct perf_event *event) +{ + hisi_pcie_pmu_event_update(event); +} + +static void hisi_pcie_pmu_set_period(struct perf_event *event) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + local64_set(&hwc->prev_count, HISI_PCIE_INIT_VAL); + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_CNT, idx, HISI_PCIE_INIT_VAL); + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EXT_CNT, idx, HISI_PCIE_INIT_VAL); +} + +static void hisi_pcie_pmu_enable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) +{ + u32 idx = hwc->idx; + u64 val; + + val = hisi_pcie_pmu_readq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx); + val |= HISI_PCIE_EVENT_EN; + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, val); +} + +static void hisi_pcie_pmu_disable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) +{ + u32 idx = hwc->idx; + u64 val; + + val = hisi_pcie_pmu_readq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx); + val &= ~HISI_PCIE_EVENT_EN; + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, val); +} + +static void hisi_pcie_pmu_enable_int(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) +{ + u32 idx = hwc->idx; + + hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_MASK, idx, 0); +} + +static void hisi_pcie_pmu_disable_int(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) +{ + u32 idx = hwc->idx; + + hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_MASK, idx, 1); +} + +static void hisi_pcie_pmu_reset_counter(struct hisi_pcie_pmu *pcie_pmu, int idx) +{ + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, HISI_PCIE_RESET_CNT); + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, HISI_PCIE_INIT_SET); +} + +static void hisi_pcie_pmu_start(struct perf_event *event, int flags) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + u64 prev_cnt; + + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); + hwc->state = 0; + + hisi_pcie_pmu_config_filter(event); + hisi_pcie_pmu_enable_counter(pcie_pmu, hwc); + hisi_pcie_pmu_enable_int(pcie_pmu, hwc); + hisi_pcie_pmu_set_period(event); + + if (flags & PERF_EF_RELOAD) { + prev_cnt = local64_read(&hwc->prev_count); + hisi_pcie_pmu_writeq(pcie_pmu, hwc->event_base, idx, prev_cnt); + } + + perf_event_update_userpage(event); +} + +static void hisi_pcie_pmu_stop(struct perf_event *event, int flags) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + hisi_pcie_pmu_event_update(event); + hisi_pcie_pmu_disable_int(pcie_pmu, hwc); + hisi_pcie_pmu_disable_counter(pcie_pmu, hwc); + hisi_pcie_pmu_clear_filter(event); + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); + hwc->state |= PERF_HES_STOPPED; + + if (hwc->state & PERF_HES_UPTODATE) + return; + + hwc->state |= PERF_HES_UPTODATE; +} + +static int hisi_pcie_pmu_add(struct perf_event *event, int flags) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx; + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + /* Check all working events to find a related event. */ + idx = hisi_pcie_pmu_find_related_event(pcie_pmu, event); + if (idx < 0) + return idx; + + /* Current event shares an enabled counter with the related event */ + if (idx < HISI_PCIE_MAX_COUNTERS) { + hwc->idx = idx; + goto start_count; + } + + idx = hisi_pcie_pmu_get_event_idx(pcie_pmu); + if (idx < 0) + return idx; + + hwc->idx = idx; + pcie_pmu->hw_events[idx] = event; + /* Reset Counter to avoid previous statistic interference. */ + hisi_pcie_pmu_reset_counter(pcie_pmu, idx); + +start_count: + if (flags & PERF_EF_START) + hisi_pcie_pmu_start(event, PERF_EF_RELOAD); + + return 0; +} + +static void hisi_pcie_pmu_del(struct perf_event *event, int flags) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + hisi_pcie_pmu_stop(event, PERF_EF_UPDATE); + pcie_pmu->hw_events[hwc->idx] = NULL; + perf_event_update_userpage(event); +} + +static void hisi_pcie_pmu_enable(struct pmu *pmu) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(pmu); + int num; + + for (num = 0; num < HISI_PCIE_MAX_COUNTERS; num++) { + if (pcie_pmu->hw_events[num]) + break; + } + + if (num == HISI_PCIE_MAX_COUNTERS) + return; + + writel(HISI_PCIE_GLOBAL_EN, pcie_pmu->base + HISI_PCIE_GLOBAL_CTRL); +} + +static void hisi_pcie_pmu_disable(struct pmu *pmu) +{ + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(pmu); + + writel(HISI_PCIE_GLOBAL_NONE, pcie_pmu->base + HISI_PCIE_GLOBAL_CTRL); +} + +static irqreturn_t hisi_pcie_pmu_irq(int irq, void *data) +{ + struct hisi_pcie_pmu *pcie_pmu = data; + irqreturn_t ret = IRQ_NONE; + struct perf_event *event; + u32 overflown; + int idx; + + for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { + overflown = hisi_pcie_pmu_readl(pcie_pmu, HISI_PCIE_INT_STAT, idx); + if (!overflown) + continue; + + /* Clear status of interrupt. */ + hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_STAT, idx, 1); + event = pcie_pmu->hw_events[idx]; + if (!event) + continue; + + hisi_pcie_pmu_event_update(event); + hisi_pcie_pmu_set_period(event); + ret = IRQ_HANDLED; + } + + return ret; +} + +static int hisi_pcie_pmu_irq_register(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) +{ + int irq, ret; + + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); + if (ret < 0) { + pci_err(pdev, "Failed to enable MSI vectors: %d\n", ret); + return ret; + } + + irq = pci_irq_vector(pdev, 0); + ret = request_irq(irq, hisi_pcie_pmu_irq, IRQF_NOBALANCING | IRQF_NO_THREAD, DRV_NAME, + pcie_pmu); + if (ret) { + pci_err(pdev, "Failed to register IRQ: %d\n", ret); + pci_free_irq_vectors(pdev); + return ret; + } + + pcie_pmu->irq = irq; + + return 0; +} + +static void hisi_pcie_pmu_irq_unregister(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) +{ + free_irq(pcie_pmu->irq, pcie_pmu); + pci_free_irq_vectors(pdev); +} + +static int hisi_pcie_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); + + if (pcie_pmu->on_cpu == -1) { + pcie_pmu->on_cpu = cpu; + WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(cpu))); + } + + return 0; +} + +static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); + unsigned int target; + + /* Nothing to do if this CPU doesn't own the PMU */ + if (pcie_pmu->on_cpu != cpu) + return 0; + + pcie_pmu->on_cpu = -1; + /* Choose a new CPU from all online cpus. */ + target = cpumask_first(cpu_online_mask); + if (target >= nr_cpu_ids) { + pci_err(pcie_pmu->pdev, "There is no CPU to set\n"); + return 0; + } + + perf_pmu_migrate_context(&pcie_pmu->pmu, cpu, target); + /* Use this CPU for event counting */ + pcie_pmu->on_cpu = target; + WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(target))); + + return 0; +} + +static struct attribute *hisi_pcie_pmu_events_attr[] = { + HISI_PCIE_PMU_EVENT_ATTR(rx_mwr_latency, 0x0010), + HISI_PCIE_PMU_EVENT_ATTR(rx_mwr_cnt, 0x10010), + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_latency, 0x0210), + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_cnt, 0x10210), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_latency, 0x0011), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_cnt, 0x10011), + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x1005), + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x11005), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x2004), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x12004), + NULL +}; + +static struct attribute_group hisi_pcie_pmu_events_group = { + .name = "events", + .attrs = hisi_pcie_pmu_events_attr, +}; + +static struct attribute *hisi_pcie_pmu_format_attr[] = { + HISI_PCIE_PMU_FORMAT_ATTR(event, "config:0-16"), + HISI_PCIE_PMU_FORMAT_ATTR(thr_len, "config1:0-3"), + HISI_PCIE_PMU_FORMAT_ATTR(thr_mode, "config1:4"), + HISI_PCIE_PMU_FORMAT_ATTR(trig_len, "config1:5-8"), + HISI_PCIE_PMU_FORMAT_ATTR(trig_mode, "config1:9"), + HISI_PCIE_PMU_FORMAT_ATTR(port, "config2:0-15"), + HISI_PCIE_PMU_FORMAT_ATTR(bdf, "config2:16-31"), + NULL +}; + +static const struct attribute_group hisi_pcie_pmu_format_group = { + .name = "format", + .attrs = hisi_pcie_pmu_format_attr, +}; + +static struct attribute *hisi_pcie_pmu_bus_attrs[] = { + &dev_attr_bus.attr, + NULL +}; + +static const struct attribute_group hisi_pcie_pmu_bus_attr_group = { + .attrs = hisi_pcie_pmu_bus_attrs, +}; + +static struct attribute *hisi_pcie_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL +}; + +static const struct attribute_group hisi_pcie_pmu_cpumask_attr_group = { + .attrs = hisi_pcie_pmu_cpumask_attrs, +}; + +static struct attribute *hisi_pcie_pmu_identifier_attrs[] = { + &dev_attr_identifier.attr, + NULL +}; + +static const struct attribute_group hisi_pcie_pmu_identifier_attr_group = { + .attrs = hisi_pcie_pmu_identifier_attrs, +}; + +static const struct attribute_group *hisi_pcie_pmu_attr_groups[] = { + &hisi_pcie_pmu_events_group, + &hisi_pcie_pmu_format_group, + &hisi_pcie_pmu_bus_attr_group, + &hisi_pcie_pmu_cpumask_attr_group, + &hisi_pcie_pmu_identifier_attr_group, + NULL +}; + +static int hisi_pcie_alloc_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) +{ + struct hisi_pcie_reg_pair regs; + u16 sicl_id, core_id; + char *name; + + regs = hisi_pcie_parse_reg_value(pcie_pmu, HISI_PCIE_REG_BDF); + pcie_pmu->bdf_min = regs.lo; + pcie_pmu->bdf_max = regs.hi; + + regs = hisi_pcie_parse_reg_value(pcie_pmu, HISI_PCIE_REG_INFO); + sicl_id = regs.hi; + core_id = regs.lo; + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_pcie%u_core%u", sicl_id, core_id); + if (!name) + return -ENOMEM; + + pcie_pmu->pdev = pdev; + pcie_pmu->on_cpu = -1; + pcie_pmu->identifier = readl(pcie_pmu->base + HISI_PCIE_REG_VERSION); + pcie_pmu->pmu = (struct pmu) { + .name = name, + .module = THIS_MODULE, + .event_init = hisi_pcie_pmu_event_init, + .pmu_enable = hisi_pcie_pmu_enable, + .pmu_disable = hisi_pcie_pmu_disable, + .add = hisi_pcie_pmu_add, + .del = hisi_pcie_pmu_del, + .start = hisi_pcie_pmu_start, + .stop = hisi_pcie_pmu_stop, + .read = hisi_pcie_pmu_read, + .task_ctx_nr = perf_invalid_context, + .attr_groups = hisi_pcie_pmu_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + return 0; +} + +static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) +{ + int ret; + + pcie_pmu->base = pci_ioremap_bar(pdev, 2); + if (!pcie_pmu->base) { + pci_err(pdev, "Ioremap failed for pcie_pmu resource\n"); + return -ENOMEM; + } + + ret = hisi_pcie_alloc_pmu(pdev, pcie_pmu); + if (ret) + goto err_iounmap; + + ret = hisi_pcie_pmu_irq_register(pdev, pcie_pmu); + if (ret) + goto err_iounmap; + + ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); + if (ret) { + pci_err(pdev, "Failed to register hotplug: %d\n", ret); + goto err_irq_unregister; + } + + ret = perf_pmu_register(&pcie_pmu->pmu, pcie_pmu->pmu.name, -1); + if (ret) { + pci_err(pdev, "Failed to register PCIe PMU: %d\n", ret); + goto err_hotplug_unregister; + } + + return ret; + +err_hotplug_unregister: + cpuhp_state_remove_instance_nocalls( + CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); + +err_irq_unregister: + hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); + +err_iounmap: + iounmap(pcie_pmu->base); + + return ret; +} + +static void hisi_pcie_uninit_pmu(struct pci_dev *pdev) +{ + struct hisi_pcie_pmu *pcie_pmu = pci_get_drvdata(pdev); + + perf_pmu_unregister(&pcie_pmu->pmu); + cpuhp_state_remove_instance_nocalls( + CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); + hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); + iounmap(pcie_pmu->base); +} + +static int hisi_pcie_init_dev(struct pci_dev *pdev) +{ + int ret; + + ret = pcim_enable_device(pdev); + if (ret) { + pci_err(pdev, "Failed to enable PCI device: %d\n", ret); + return ret; + } + + ret = pcim_iomap_regions(pdev, BIT(2), DRV_NAME); + if (ret < 0) { + pci_err(pdev, "Failed to request PCI mem regions: %d\n", ret); + return ret; + } + + pci_set_master(pdev); + + return 0; +} + +static int hisi_pcie_pmu_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct hisi_pcie_pmu *pcie_pmu; + int ret; + + pcie_pmu = devm_kzalloc(&pdev->dev, sizeof(*pcie_pmu), GFP_KERNEL); + if (!pcie_pmu) + return -ENOMEM; + + ret = hisi_pcie_init_dev(pdev); + if (ret) + return ret; + + ret = hisi_pcie_init_pmu(pdev, pcie_pmu); + if (ret) + return ret; + + pci_set_drvdata(pdev, pcie_pmu); + + return ret; +} + +static void hisi_pcie_pmu_remove(struct pci_dev *pdev) +{ + hisi_pcie_uninit_pmu(pdev); + pci_set_drvdata(pdev, NULL); +} + +static const struct pci_device_id hisi_pcie_pmu_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, 0xa12d) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, hisi_pcie_pmu_ids); + +static struct pci_driver hisi_pcie_pmu_driver = { + .name = DRV_NAME, + .id_table = hisi_pcie_pmu_ids, + .probe = hisi_pcie_pmu_probe, + .remove = hisi_pcie_pmu_remove, +}; + +static int __init hisi_pcie_module_init(void) +{ + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, + "AP_PERF_ARM_HISI_PCIE_PMU_ONLINE", + hisi_pcie_pmu_online_cpu, + hisi_pcie_pmu_offline_cpu); + if (ret) { + pr_err("Failed to setup PCIe PMU hotplug, ret = %d\n", ret); + return ret; + } + + ret = pci_register_driver(&hisi_pcie_pmu_driver); + if (ret) + cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); + + return ret; +} +module_init(hisi_pcie_module_init); + +static void __exit hisi_pcie_module_exit(void) +{ + pci_unregister_driver(&hisi_pcie_pmu_driver); + cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); +} +module_exit(hisi_pcie_module_exit); + +MODULE_DESCRIPTION("HiSilicon PCIe PMU driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Qi Liu "); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 832d8a74fa59..02ed483b79bf 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -222,6 +222,7 @@ enum cpuhp_state { CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, CPUHP_AP_PERF_ARM_L2X0_ONLINE, CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, -- 2.33.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CA794C433EF for ; Tue, 30 Nov 2021 12:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=S5ytc+k1Mlr/xHF8OHjYAAsE6OY2i7b4i3mpqvjGlro=; b=x3Ubpbq66izYev jidd+FRUdqz0H8ZB31QSziBqJJ6u+cpmTLXsBrsMujGZoC/ZK19EJCuvpfXkebQ0uZt9ohKOa3BzL YgzPcUBe0QhgTb7XdnBSHI3TvJSI74iGotcvHAjINrV8Brtj35vy2LaagmIkddzlLVfVH+lnm8s27 xJrX+7z29DBJu/D+iB6rRUq5u2A+DsSFu47T57pRwyRhJKbqOpcRwbYY14qP2RIC0EKQmx4zX5LDc /d8grhsu74a2AACMfN8h7eL0uD00+S6MJiQHfJndyrAZpX8uA8ib2ofnuCsTTJQwRKPntFMdoznNg zK4aF3UCWv98NJITpHyQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ms1vx-0051Po-NC; Tue, 30 Nov 2021 12:08:29 +0000 Received: from szxga02-in.huawei.com ([45.249.212.188]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ms1vQ-0051D4-8x for linux-arm-kernel@lists.infradead.org; Tue, 30 Nov 2021 12:08:01 +0000 Received: from dggemv711-chm.china.huawei.com (unknown [172.30.72.54]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4J3LZ10d3rz91RC; Tue, 30 Nov 2021 20:07:21 +0800 (CST) Received: from kwepemm600003.china.huawei.com (7.193.23.202) by dggemv711-chm.china.huawei.com (10.1.198.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 30 Nov 2021 20:07:52 +0800 Received: from localhost.localdomain (10.67.165.103) by kwepemm600003.china.huawei.com (7.193.23.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 30 Nov 2021 20:07:52 +0800 From: Qi Liu To: , , CC: , , , , Subject: [PATCH v12 2/2] drivers/perf: hisi: Add driver for HiSilicon PCIe PMU Date: Tue, 30 Nov 2021 20:04:50 +0800 Message-ID: <20211130120450.2747-3-liuqi115@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211130120450.2747-1-liuqi115@huawei.com> References: <20211130120450.2747-1-liuqi115@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.103] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To kwepemm600003.china.huawei.com (7.193.23.202) X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211130_040756_744349_8FD3BF6E X-CRM114-Status: GOOD ( 24.20 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org UENJZSBQTVUgUm9vdCBDb21wbGV4IEludGVncmF0ZWQgRW5kIFBvaW50KFJDaUVQKSBkZXZpY2Ug aXMgc3VwcG9ydGVkCnRvIHNhbXBsZSBiYW5kd2lkdGgsIGxhdGVuY3ksIGJ1ZmZlciBvY2N1cGF0 aW9uIGV0Yy4KCkVhY2ggUE1VIFJDaUVQIGRldmljZSBtb25pdG9ycyBtdWx0aXBsZSBSb290IFBv cnRzLCBhbmQgZWFjaCBSQ2lFUCBpcwpyZWdpc3RlcmVkIGFzIGEgUE1VIGluIC9zeXMvYnVzL2V2 ZW50X3NvdXJjZS9kZXZpY2VzLCBzbyB1c2VycyBjYW4Kc2VsZWN0IHRhcmdldCBQTVUsIGFuZCB1 c2UgZmlsdGVyIHRvIGRvIGZ1cnRoZXIgc2V0cy4KCkZpbHRlcmluZyBvcHRpb25zIGNvbnRhaW5z OgpldmVudCAgICAgLSBzZWxlY3QgdGhlIGV2ZW50Lgpwb3J0ICAgICAgLSBzZWxlY3QgdGFyZ2V0 IFJvb3QgUG9ydHMuIEluZm9ybWF0aW9uIG9mIFJvb3QgUG9ydHMgYXJlCiAgICAgICAgICAgIHNo b3duIHVuZGVyIHN5c2ZzLgpiZGYgICAgICAgLSBzZWxlY3QgcmVxdWVzdGVyX2lkIG9mIHRhcmdl dCBFUCBkZXZpY2UuCnRyaWdfbGVuICAtIHNldCB0cmlnZ2VyIGNvbmRpdGlvbiBmb3Igc3RhcnRp bmcgZXZlbnQgc3RhdGlzdGljcy4KdHJpZ19tb2RlIC0gc2V0IHRyaWdnZXIgbW9kZS4gMCBtZWFu cyBzdGFydGluZyB0byBzdGF0aXN0aWMgd2hlbiBiaWdnZXIKICAgICAgICAgICAgdGhhbiB0cmln Z2VyIGNvbmRpdGlvbiwgYW5kIDEgbWVhbnMgc21hbGxlci4KdGhyX2xlbiAgIC0gc2V0IHRocmVz aG9sZCBmb3Igc3RhdGlzdGljcy4KdGhyX21vZGUgIC0gc2V0IHRocmVzaG9sZCBtb2RlLiAwIG1l YW5zIGNvdW50IHdoZW4gYmlnZ2VyIHRoYW4gdGhyZXNob2xkLAogICAgICAgICAgICBhbmQgMSBt ZWFucyBzbWFsbGVyLgoKQWNrZWQtYnk6IEtyenlzenRvZiBXaWxjennFhHNraSA8a3dAbGludXgu Y29tPgpSZXZpZXdlZC1ieTogSm9obiBHYXJyeSA8am9obi5nYXJyeUBodWF3ZWkuY29tPgpTaWdu ZWQtb2ZmLWJ5OiBRaSBMaXUgPGxpdXFpMTE1QGh1YXdlaS5jb20+Ci0tLQogTUFJTlRBSU5FUlMg ICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDIgKwogZHJpdmVycy9wZXJmL2hpc2lsaWNv bi9LY29uZmlnICAgICAgICAgfCAgIDkgKwogZHJpdmVycy9wZXJmL2hpc2lsaWNvbi9NYWtlZmls ZSAgICAgICAgfCAgIDIgKwogZHJpdmVycy9wZXJmL2hpc2lsaWNvbi9oaXNpX3BjaWVfcG11LmMg fCA5NDggKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS9saW51eC9jcHVob3RwbHVn LmggICAgICAgICAgICAgfCAgIDEgKwogNSBmaWxlcyBjaGFuZ2VkLCA5NjIgaW5zZXJ0aW9ucygr KQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvcGVyZi9oaXNpbGljb24vaGlzaV9wY2llX3Bt dS5jCgpkaWZmIC0tZ2l0IGEvTUFJTlRBSU5FUlMgYi9NQUlOVEFJTkVSUwppbmRleCA1YjMzNzkx YmI4ZTkuLjk0ZTcxYWI2OTg3MCAxMDA2NDQKLS0tIGEvTUFJTlRBSU5FUlMKKysrIGIvTUFJTlRB SU5FUlMKQEAgLTg0NTMsOCArODQ1MywxMCBAQCBGOglEb2N1bWVudGF0aW9uL2RldmljZXRyZWUv YmluZGluZ3MvbWlzYy9oaXNpbGljb24taGlrZXktdXNiLnlhbWwKIAogSElTSUxJQ09OIFBNVSBE UklWRVIKIE06CVNoYW9rdW4gWmhhbmcgPHpoYW5nc2hhb2t1bkBoaXNpbGljb24uY29tPgorTToJ UWkgTGl1IDxsaXVxaTExNUBodWF3ZWkuY29tPgogUzoJU3VwcG9ydGVkCiBXOglodHRwOi8vd3d3 Lmhpc2lsaWNvbi5jb20KK0Y6CURvY3VtZW50YXRpb24vYWRtaW4tZ3VpZGUvcGVyZi9oaXNpLXBj aWUtcG11LnJzdAogRjoJRG9jdW1lbnRhdGlvbi9hZG1pbi1ndWlkZS9wZXJmL2hpc2ktcG11LnJz dAogRjoJZHJpdmVycy9wZXJmL2hpc2lsaWNvbgogCmRpZmYgLS1naXQgYS9kcml2ZXJzL3BlcmYv aGlzaWxpY29uL0tjb25maWcgYi9kcml2ZXJzL3BlcmYvaGlzaWxpY29uL0tjb25maWcKaW5kZXgg YzVkMWI3MDE5ZmZmLi41NTQ2MjE4YjU1OTggMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvcGVyZi9oaXNp bGljb24vS2NvbmZpZworKysgYi9kcml2ZXJzL3BlcmYvaGlzaWxpY29uL0tjb25maWcKQEAgLTUs MyArNSwxMiBAQCBjb25maWcgSElTSV9QTVUKIAkgIGhlbHAKIAkgIFN1cHBvcnQgZm9yIEhpU2ls aWNvbiBTb0MgTDMgQ2FjaGUgcGVyZm9ybWFuY2UgbW9uaXRvciwgSHlkcmEgSG9tZQogCSAgQWdl bnQgcGVyZm9ybWFuY2UgbW9uaXRvciBhbmQgRERSIENvbnRyb2xsZXIgcGVyZm9ybWFuY2UgbW9u aXRvci4KKworY29uZmlnIEhJU0lfUENJRV9QTVUKKwl0cmlzdGF0ZSAiSGlTaWxpY29uIFBDSUUg UEVSRiBQTVUiCisJZGVwZW5kcyBvbiBQQ0kgJiYgQVJNNjQKKwloZWxwCisJICBQcm92aWRlIHN1 cHBvcnQgZm9yIEhpU2lsaWNvbiBQQ0llIHBlcmZvcm1hbmNlIG1vbml0b3JpbmcgdW5pdCAoUE1V KQorCSAgUkNpRVAgZGV2aWNlcy4KKwkgIEFkZHMgdGhlIFBDSWUgUE1VIGludG8gcGVyZiBldmVu dHMgc3lzdGVtIGZvciBtb25pdG9yaW5nIGxhdGVuY3ksCisJICBiYW5kd2lkdGggZXRjLgpkaWZm IC0tZ2l0IGEvZHJpdmVycy9wZXJmL2hpc2lsaWNvbi9NYWtlZmlsZSBiL2RyaXZlcnMvcGVyZi9o aXNpbGljb24vTWFrZWZpbGUKaW5kZXggNzY0M2M5ZjkzZTM2Li41MDZlZDM5ZTMyNjYgMTAwNjQ0 Ci0tLSBhL2RyaXZlcnMvcGVyZi9oaXNpbGljb24vTWFrZWZpbGUKKysrIGIvZHJpdmVycy9wZXJm L2hpc2lsaWNvbi9NYWtlZmlsZQpAQCAtMiwzICsyLDUgQEAKIG9iai0kKENPTkZJR19ISVNJX1BN VSkgKz0gaGlzaV91bmNvcmVfcG11Lm8gaGlzaV91bmNvcmVfbDNjX3BtdS5vIFwKIAkJCSAgaGlz aV91bmNvcmVfaGhhX3BtdS5vIGhpc2lfdW5jb3JlX2RkcmNfcG11Lm8gaGlzaV91bmNvcmVfc2xs Y19wbXUubyBcCiAJCQkgIGhpc2lfdW5jb3JlX3BhX3BtdS5vCisKK29iai0kKENPTkZJR19ISVNJ X1BDSUVfUE1VKSArPSBoaXNpX3BjaWVfcG11Lm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGVyZi9o aXNpbGljb24vaGlzaV9wY2llX3BtdS5jIGIvZHJpdmVycy9wZXJmL2hpc2lsaWNvbi9oaXNpX3Bj aWVfcG11LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5hY2E1OTU0 ZTI4OGQKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3BlcmYvaGlzaWxpY29uL2hpc2lfcGNp ZV9wbXUuYwpAQCAtMCwwICsxLDk0OCBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjAtb25seQorLyoKKyAqIFRoaXMgZHJpdmVyIGFkZHMgc3VwcG9ydCBmb3IgUENJZSBQTVUg UkNpRVAgZGV2aWNlLiBSZWxhdGVkCisgKiBwZXJmIGV2ZW50cyBhcmUgYmFuZHdpZHRoLCBsYXRl bmN5IGV0Yy4KKyAqCisgKiBDb3B5cmlnaHQgKEMpIDIwMjEgSGlTaWxpY29uIExpbWl0ZWQKKyAq IEF1dGhvcjogUWkgTGl1IDxsaXVxaTExNUBodWF3ZWkuY29tPgorICovCisjaW5jbHVkZSA8bGlu dXgvYml0ZmllbGQuaD4KKyNpbmNsdWRlIDxsaW51eC9iaXRtYXAuaD4KKyNpbmNsdWRlIDxsaW51 eC9idWcuaD4KKyNpbmNsdWRlIDxsaW51eC9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIu aD4KKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KKyNpbmNsdWRlIDxsaW51eC9pcnEuaD4K KyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+CisjaW5j bHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgvcGNpLmg+CisjaW5jbHVkZSA8 bGludXgvcGVyZl9ldmVudC5oPgorCisjZGVmaW5lIERSVl9OQU1FICJoaXNpX3BjaWVfcG11Igor LyogRGVmaW5lIHJlZ2lzdGVycyAqLworI2RlZmluZSBISVNJX1BDSUVfR0xPQkFMX0NUUkwJCTB4 MDAKKyNkZWZpbmUgSElTSV9QQ0lFX0VWRU5UX0NUUkwJCTB4MDEwCisjZGVmaW5lIEhJU0lfUENJ RV9DTlQJCQkweDA5MAorI2RlZmluZSBISVNJX1BDSUVfRVhUX0NOVAkJMHgxMTAKKyNkZWZpbmUg SElTSV9QQ0lFX0lOVF9TVEFUCQkweDE1MAorI2RlZmluZSBISVNJX1BDSUVfSU5UX01BU0sJCTB4 MTU0CisjZGVmaW5lIEhJU0lfUENJRV9SRUdfQkRGCQkweGZlMAorI2RlZmluZSBISVNJX1BDSUVf UkVHX1ZFUlNJT04JCTB4ZmU0CisjZGVmaW5lIEhJU0lfUENJRV9SRUdfSU5GTwkJMHhmZTgKKwor LyogRGVmaW5lIGNvbW1hbmQgaW4gSElTSV9QQ0lFX0dMT0JBTF9DVFJMICovCisjZGVmaW5lIEhJ U0lfUENJRV9HTE9CQUxfRU4JCTB4MDEKKyNkZWZpbmUgSElTSV9QQ0lFX0dMT0JBTF9OT05FCQkw CisKKy8qIERlZmluZSBjb21tYW5kIGluIEhJU0lfUENJRV9FVkVOVF9DVFJMICovCisjZGVmaW5l IEhJU0lfUENJRV9FVkVOVF9FTgkJQklUX1VMTCgyMCkKKyNkZWZpbmUgSElTSV9QQ0lFX1JFU0VU X0NOVAkJQklUX1VMTCgyMikKKyNkZWZpbmUgSElTSV9QQ0lFX0lOSVRfU0VUCQlCSVRfVUxMKDM0 KQorI2RlZmluZSBISVNJX1BDSUVfVEhSX0VOCQlCSVRfVUxMKDI2KQorI2RlZmluZSBISVNJX1BD SUVfVEFSR0VUX0VOCQlCSVRfVUxMKDMyKQorI2RlZmluZSBISVNJX1BDSUVfVFJJR19FTgkJQklU X1VMTCg1MikKKworLyogRGVmaW5lIG9mZnNldHMgaW4gSElTSV9QQ0lFX0VWRU5UX0NUUkwgKi8K KyNkZWZpbmUgSElTSV9QQ0lFX0VWRU5UX00JCUdFTk1BU0tfVUxMKDE1LCAwKQorI2RlZmluZSBI SVNJX1BDSUVfVEhSX01PREVfTQkJR0VOTUFTS19VTEwoMjcsIDI3KQorI2RlZmluZSBISVNJX1BD SUVfVEhSX00JCQlHRU5NQVNLX1VMTCgzMSwgMjgpCisjZGVmaW5lIEhJU0lfUENJRV9UQVJHRVRf TQkJR0VOTUFTS19VTEwoNTIsIDM2KQorI2RlZmluZSBISVNJX1BDSUVfVFJJR19NT0RFX00JCUdF Tk1BU0tfVUxMKDUzLCA1MykKKyNkZWZpbmUgSElTSV9QQ0lFX1RSSUdfTQkJR0VOTUFTS19VTEwo NTksIDU2KQorCisjZGVmaW5lIEhJU0lfUENJRV9NQVhfQ09VTlRFUlMJCTgKKyNkZWZpbmUgSElT SV9QQ0lFX1JFR19TVEVQCQk4CisjZGVmaW5lIEhJU0lfUENJRV9USFJfTUFYX1ZBTAkJMTAKKyNk ZWZpbmUgSElTSV9QQ0lFX1RSSUdfTUFYX1ZBTAkJMTAKKyNkZWZpbmUgSElTSV9QQ0lFX01BWF9Q RVJJT0QJCShHRU5NQVNLX1VMTCg2MywgMCkpCisjZGVmaW5lIEhJU0lfUENJRV9JTklUX1ZBTAkJ QklUX1VMTCg2MykKKworc3RydWN0IGhpc2lfcGNpZV9wbXUgeworCXN0cnVjdCBwZXJmX2V2ZW50 ICpod19ldmVudHNbSElTSV9QQ0lFX01BWF9DT1VOVEVSU107CisJc3RydWN0IGhsaXN0X25vZGUg bm9kZTsKKwlzdHJ1Y3QgcGNpX2RldiAqcGRldjsKKwlzdHJ1Y3QgcG11IHBtdTsKKwl2b2lkIF9f aW9tZW0gKmJhc2U7CisJaW50IGlycTsKKwl1MzIgaWRlbnRpZmllcjsKKwkvKiBNaW5pbXVtIGFu ZCBtYXhpbXVtIEJERiBvZiByb290IHBvcnRzIG1vbml0b3JlZCBieSBQTVUgKi8KKwl1MTYgYmRm X21pbjsKKwl1MTYgYmRmX21heDsKKwlpbnQgb25fY3B1OworfTsKKworc3RydWN0IGhpc2lfcGNp ZV9yZWdfcGFpciB7CisJdTE2IGxvOworCXUxNiBoaTsKK307CisKKyNkZWZpbmUgdG9fcGNpZV9w bXUocCkgIChjb250YWluZXJfb2YoKHApLCBzdHJ1Y3QgaGlzaV9wY2llX3BtdSwgcG11KSkKKyNk ZWZpbmUgR0VUX1BDSV9ERVZGTihiZGYpICAoKGJkZikgJiAweGZmKQorCisjZGVmaW5lIEhJU0lf UENJRV9QTVVfRklMVEVSX0FUVFIoX25hbWUsIF9jb25maWcsIF9oaSwgX2xvKQkJICBcCisJc3Rh dGljIHU2NCBoaXNpX3BjaWVfZ2V0XyMjX25hbWUoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50KQkg IFwKKwl7CQkJCQkJCQkgIFwKKwkJcmV0dXJuIEZJRUxEX0dFVChHRU5NQVNLKF9oaSwgX2xvKSwg ZXZlbnQtPmF0dHIuX2NvbmZpZyk7IFwKKwl9CQkJCQkJCQkgIFwKKworSElTSV9QQ0lFX1BNVV9G SUxURVJfQVRUUihldmVudCwgY29uZmlnLCAxNiwgMCk7CitISVNJX1BDSUVfUE1VX0ZJTFRFUl9B VFRSKHRocl9sZW4sIGNvbmZpZzEsIDMsIDApOworSElTSV9QQ0lFX1BNVV9GSUxURVJfQVRUUih0 aHJfbW9kZSwgY29uZmlnMSwgNCwgNCk7CitISVNJX1BDSUVfUE1VX0ZJTFRFUl9BVFRSKHRyaWdf bGVuLCBjb25maWcxLCA4LCA1KTsKK0hJU0lfUENJRV9QTVVfRklMVEVSX0FUVFIodHJpZ19tb2Rl LCBjb25maWcxLCA5LCA5KTsKK0hJU0lfUENJRV9QTVVfRklMVEVSX0FUVFIocG9ydCwgY29uZmln MiwgMTUsIDApOworSElTSV9QQ0lFX1BNVV9GSUxURVJfQVRUUihiZGYsIGNvbmZpZzIsIDMxLCAx Nik7CisKK3N0YXRpYyBzc2l6ZV90IGhpc2lfcGNpZV9mb3JtYXRfc3lzZnNfc2hvdyhzdHJ1Y3Qg ZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAorCQkJCQkgICBjaGFy ICpidWYpCit7CisJc3RydWN0IGRldl9leHRfYXR0cmlidXRlICplYXR0cjsKKworCWVhdHRyID0g Y29udGFpbmVyX29mKGF0dHIsIHN0cnVjdCBkZXZfZXh0X2F0dHJpYnV0ZSwgYXR0cik7CisKKwly ZXR1cm4gc3lzZnNfZW1pdChidWYsICIlc1xuIiwgKGNoYXIgKillYXR0ci0+dmFyKTsKK30KKwor c3RhdGljIHNzaXplX3QgaGlzaV9wY2llX2V2ZW50X3N5c2ZzX3Nob3coc3RydWN0IGRldmljZSAq ZGV2LCBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqYXR0ciwKKwkJCQkJICBjaGFyICpidWYpCit7 CisJc3RydWN0IHBlcmZfcG11X2V2ZW50c19hdHRyICpwbXVfYXR0ciA9CisJCWNvbnRhaW5lcl9v ZihhdHRyLCBzdHJ1Y3QgcGVyZl9wbXVfZXZlbnRzX2F0dHIsIGF0dHIpOworCisJcmV0dXJuIHN5 c2ZzX2VtaXQoYnVmLCAiY29uZmlnPTB4JWxseFxuIiwgcG11X2F0dHItPmlkKTsKK30KKworI2Rl ZmluZSBISVNJX1BDSUVfUE1VX0ZPUk1BVF9BVFRSKF9uYW1lLCBfZm9ybWF0KSAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIFwKKwkoJigoc3RydWN0IGRldl9leHRfYXR0cmlidXRlW10peyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKKwkJeyAuYXR0ciA9IF9fQVRU UihfbmFtZSwgMDQ0NCwgaGlzaV9wY2llX2Zvcm1hdF9zeXNmc19zaG93LCAgICAgXAorCQkJCSBO VUxMKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAorCQkgIC52YXIg PSAodm9pZCAqKV9mb3JtYXQgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBc CisJfSlbMF0uYXR0ci5hdHRyKQorCisjZGVmaW5lIEhJU0lfUENJRV9QTVVfRVZFTlRfQVRUUihf bmFtZSwgX2lkKQkJCVwKKwlQTVVfRVZFTlRfQVRUUl9JRChfbmFtZSwgaGlzaV9wY2llX2V2ZW50 X3N5c2ZzX3Nob3csIF9pZCkKKworc3RhdGljIHNzaXplX3QgY3B1bWFza19zaG93KHN0cnVjdCBk ZXZpY2UgKmRldiwgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmF0dHIsIGNoYXIgKmJ1ZikKK3sK KwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2llX3BtdShkZXZfZ2V0X2Ry dmRhdGEoZGV2KSk7CisKKwlyZXR1cm4gY3B1bWFwX3ByaW50X3RvX3BhZ2VidWYodHJ1ZSwgYnVm LCBjcHVtYXNrX29mKHBjaWVfcG11LT5vbl9jcHUpKTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9S TyhjcHVtYXNrKTsKKworc3RhdGljIHNzaXplX3QgaWRlbnRpZmllcl9zaG93KHN0cnVjdCBkZXZp Y2UgKmRldiwgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmF0dHIsIGNoYXIgKmJ1ZikKK3sKKwlz dHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2llX3BtdShkZXZfZ2V0X2RydmRh dGEoZGV2KSk7CisKKwlyZXR1cm4gc3lzZnNfZW1pdChidWYsICIlI3hcbiIsIHBjaWVfcG11LT5p ZGVudGlmaWVyKTsKK30KK3N0YXRpYyBERVZJQ0VfQVRUUl9STyhpZGVudGlmaWVyKTsKKworc3Rh dGljIHNzaXplX3QgYnVzX3Nob3coc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNlX2F0 dHJpYnV0ZSAqYXR0ciwgY2hhciAqYnVmKQoreworCXN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2ll X3BtdSA9IHRvX3BjaWVfcG11KGRldl9nZXRfZHJ2ZGF0YShkZXYpKTsKKworCXJldHVybiBzeXNm c19lbWl0KGJ1ZiwgIiUjMDR4XG4iLCBQQ0lfQlVTX05VTShwY2llX3BtdS0+YmRmX21pbikpOwor fQorc3RhdGljIERFVklDRV9BVFRSX1JPKGJ1cyk7CisKK3N0YXRpYyBzdHJ1Y3QgaGlzaV9wY2ll X3JlZ19wYWlyCitoaXNpX3BjaWVfcGFyc2VfcmVnX3ZhbHVlKHN0cnVjdCBoaXNpX3BjaWVfcG11 ICpwY2llX3BtdSwgdTMyIHJlZ19vZmYpCit7CisJdTMyIHZhbCA9IHJlYWRsX3JlbGF4ZWQocGNp ZV9wbXUtPmJhc2UgKyByZWdfb2ZmKTsKKwlzdHJ1Y3QgaGlzaV9wY2llX3JlZ19wYWlyIHJlZ3Mg PSB7CisJCS5sbyA9IHZhbCwKKwkJLmhpID0gdmFsID4+IDE2LAorCX07CisKKwlyZXR1cm4gcmVn czsKK30KKworLyoKKyAqIEhhcmR3YXJlIGNvdW50ZXIgYW5kIGV4dF9jb3VudGVyIHdvcmsgdG9n ZXRoZXIgZm9yIGJhbmR3aWR0aCwgbGF0ZW5jeSwgYnVzCisgKiB1dGlsaXphdGlvbiBhbmQgYnVm ZmVyIG9jY3VwYW5jeSBldmVudHMuIEZvciBleGFtcGxlLCBSWCBtZW1vcnkgd3JpdGUgbGF0ZW5j eQorICogZXZlbnRzKGluZGV4ID0gMHgwMDEwKSwgY291bnRlciBjb3VudHMgdG90YWwgZGVsYXkg Y3ljbGVzIGFuZCBleHRfY291bnRlcgorICogY291bnRzIFJYIG1lbW9yeSB3cml0ZSBQQ0llIHBh Y2tldHMgbnVtYmVyLgorICoKKyAqIEFzIHdlIGRvbid0IHdhbnQgUE1VIGRyaXZlciB0byBwcm9j ZXNzIHRoZXNlIHR3byBkYXRhLCAiZGVsYXkgY3ljbGVzIiBjYW4KKyAqIGJlIHRyZWF0ZWQgYXMg YW4gaW5kZXBlbmRlbnQgZXZlbnQoaW5kZXggPSAweDAwMTApLCAiUlggbWVtb3J5IHdyaXRlIHBh Y2tldHMKKyAqIG51bWJlciIgYXMgYW5vdGhlcihpbmRleCA9IDB4MTAwMTApLiBCSVQgMTYgaXMg dXNlZCB0byBkaXN0aW5ndWlzaCBhbmQgMC0xNQorICogYml0cyBhcmUgInJlYWwiIGV2ZW50IGlu ZGV4LCB3aGljaCBjYW4gYmUgdXNlZCB0byBzZXQgSElTSV9QQ0lFX0VWRU5UX0NUUkwuCisgKi8K KyNkZWZpbmUgRVhUX0NPVU5URVJfSVNfVVNFRChpZHgpCQkoKGlkeCkgJiBCSVQoMTYpKQorCitz dGF0aWMgdTMyIGhpc2lfcGNpZV9nZXRfcmVhbF9ldmVudChzdHJ1Y3QgcGVyZl9ldmVudCAqZXZl bnQpCit7CisJcmV0dXJuIGhpc2lfcGNpZV9nZXRfZXZlbnQoZXZlbnQpICYgR0VOTUFTSygxNSwg MCk7Cit9CisKK3N0YXRpYyB1MzIgaGlzaV9wY2llX3BtdV9nZXRfb2Zmc2V0KHUzMiBvZmZzZXQs IHUzMiBpZHgpCit7CisJcmV0dXJuIG9mZnNldCArIEhJU0lfUENJRV9SRUdfU1RFUCAqIGlkeDsK K30KKworc3RhdGljIHUzMiBoaXNpX3BjaWVfcG11X3JlYWRsKHN0cnVjdCBoaXNpX3BjaWVfcG11 ICpwY2llX3BtdSwgdTMyIHJlZ19vZmZzZXQsCisJCQkgICAgICAgdTMyIGlkeCkKK3sKKwl1MzIg b2Zmc2V0ID0gaGlzaV9wY2llX3BtdV9nZXRfb2Zmc2V0KHJlZ19vZmZzZXQsIGlkeCk7CisKKwly ZXR1cm4gcmVhZGxfcmVsYXhlZChwY2llX3BtdS0+YmFzZSArIG9mZnNldCk7Cit9CisKK3N0YXRp YyB2b2lkIGhpc2lfcGNpZV9wbXVfd3JpdGVsKHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3Bt dSwgdTMyIHJlZ19vZmZzZXQsIHUzMiBpZHgsIHUzMiB2YWwpCit7CisJdTMyIG9mZnNldCA9IGhp c2lfcGNpZV9wbXVfZ2V0X29mZnNldChyZWdfb2Zmc2V0LCBpZHgpOworCisJd3JpdGVsX3JlbGF4 ZWQodmFsLCBwY2llX3BtdS0+YmFzZSArIG9mZnNldCk7Cit9CisKK3N0YXRpYyB1NjQgaGlzaV9w Y2llX3BtdV9yZWFkcShzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUsIHUzMiByZWdfb2Zm c2V0LCB1MzIgaWR4KQoreworCXUzMiBvZmZzZXQgPSBoaXNpX3BjaWVfcG11X2dldF9vZmZzZXQo cmVnX29mZnNldCwgaWR4KTsKKworCXJldHVybiByZWFkcV9yZWxheGVkKHBjaWVfcG11LT5iYXNl ICsgb2Zmc2V0KTsKK30KKworc3RhdGljIHZvaWQgaGlzaV9wY2llX3BtdV93cml0ZXEoc3RydWN0 IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11LCB1MzIgcmVnX29mZnNldCwgdTMyIGlkeCwgdTY0IHZh bCkKK3sKKwl1MzIgb2Zmc2V0ID0gaGlzaV9wY2llX3BtdV9nZXRfb2Zmc2V0KHJlZ19vZmZzZXQs IGlkeCk7CisKKwl3cml0ZXFfcmVsYXhlZCh2YWwsIHBjaWVfcG11LT5iYXNlICsgb2Zmc2V0KTsK K30KKworc3RhdGljIHZvaWQgaGlzaV9wY2llX3BtdV9jb25maWdfZmlsdGVyKHN0cnVjdCBwZXJm X2V2ZW50ICpldmVudCkKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19w Y2llX3BtdShldmVudC0+cG11KTsKKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50 LT5odzsKKwl1NjQgcmVnID0gSElTSV9QQ0lFX0lOSVRfU0VUOworCXU2NCBwb3J0LCB0cmlnX2xl biwgdGhyX2xlbjsKKworCS8qIENvbmZpZyBISVNJX1BDSUVfRVZFTlRfQ1RSTCBhY2NvcmRpbmcg dG8gZXZlbnQuICovCisJcmVnIHw9IEZJRUxEX1BSRVAoSElTSV9QQ0lFX0VWRU5UX00sIGhpc2lf cGNpZV9nZXRfcmVhbF9ldmVudChldmVudCkpOworCisJLyogQ29uZmlnIEhJU0lfUENJRV9FVkVO VF9DVFJMIGFjY29yZGluZyB0byByb290IHBvcnQgb3IgRVAgZGV2aWNlLiAqLworCXBvcnQgPSBo aXNpX3BjaWVfZ2V0X3BvcnQoZXZlbnQpOworCWlmIChwb3J0KQorCQlyZWcgfD0gRklFTERfUFJF UChISVNJX1BDSUVfVEFSR0VUX00sIHBvcnQpOworCWVsc2UKKwkJcmVnIHw9IEhJU0lfUENJRV9U QVJHRVRfRU4gfAorCQkgICAgICAgRklFTERfUFJFUChISVNJX1BDSUVfVEFSR0VUX00sIGhpc2lf cGNpZV9nZXRfYmRmKGV2ZW50KSk7CisKKwkvKiBDb25maWcgSElTSV9QQ0lFX0VWRU5UX0NUUkwg YWNjb3JkaW5nIHRvIHRyaWdnZXIgY29uZGl0aW9uLiAqLworCXRyaWdfbGVuID0gaGlzaV9wY2ll X2dldF90cmlnX2xlbihldmVudCk7CisJaWYgKHRyaWdfbGVuKSB7CisJCXJlZyB8PSBGSUVMRF9Q UkVQKEhJU0lfUENJRV9UUklHX00sIHRyaWdfbGVuKTsKKwkJcmVnIHw9IEZJRUxEX1BSRVAoSElT SV9QQ0lFX1RSSUdfTU9ERV9NLCBoaXNpX3BjaWVfZ2V0X3RyaWdfbW9kZShldmVudCkpOworCQly ZWcgfD0gSElTSV9QQ0lFX1RSSUdfRU47CisJfQorCisJLyogQ29uZmlnIEhJU0lfUENJRV9FVkVO VF9DVFJMIGFjY29yZGluZyB0byB0aHJlc2hvbGQgY29uZGl0aW9uLiAqLworCXRocl9sZW4gPSBo aXNpX3BjaWVfZ2V0X3Rocl9sZW4oZXZlbnQpOworCWlmICh0aHJfbGVuKSB7CisJCXJlZyB8PSBG SUVMRF9QUkVQKEhJU0lfUENJRV9USFJfTSwgdGhyX2xlbik7CisJCXJlZyB8PSBGSUVMRF9QUkVQ KEhJU0lfUENJRV9USFJfTU9ERV9NLCBoaXNpX3BjaWVfZ2V0X3Rocl9tb2RlKGV2ZW50KSk7CisJ CXJlZyB8PSBISVNJX1BDSUVfVEhSX0VOOworCX0KKworCWhpc2lfcGNpZV9wbXVfd3JpdGVxKHBj aWVfcG11LCBISVNJX1BDSUVfRVZFTlRfQ1RSTCwgaHdjLT5pZHgsIHJlZyk7Cit9CisKK3N0YXRp YyB2b2lkIGhpc2lfcGNpZV9wbXVfY2xlYXJfZmlsdGVyKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVu dCkKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2llX3BtdShldmVu dC0+cG11KTsKKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsKKworCWhp c2lfcGNpZV9wbXVfd3JpdGVxKHBjaWVfcG11LCBISVNJX1BDSUVfRVZFTlRfQ1RSTCwgaHdjLT5p ZHgsIEhJU0lfUENJRV9JTklUX1NFVCk7Cit9CisKK3N0YXRpYyBib29sIGhpc2lfcGNpZV9wbXVf dmFsaWRfcmVxdWVzdGVyX2lkKHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdSwgdTMyIGJk ZikKK3sKKwlzdHJ1Y3QgcGNpX2RldiAqcm9vdF9wb3J0LCAqcGRldjsKKwl1MTYgcnBfYmRmOwor CisJcGRldiA9IHBjaV9nZXRfZG9tYWluX2J1c19hbmRfc2xvdChwY2lfZG9tYWluX25yKHBjaWVf cG11LT5wZGV2LT5idXMpLCBQQ0lfQlVTX05VTShiZGYpLAorCQkJCQkgICBHRVRfUENJX0RFVkZO KGJkZikpOworCWlmICghcGRldikKKwkJcmV0dXJuIGZhbHNlOworCisJcm9vdF9wb3J0ID0gcGNp ZV9maW5kX3Jvb3RfcG9ydChwZGV2KTsKKwlpZiAoIXJvb3RfcG9ydCkgeworCQlwY2lfZGV2X3B1 dChwZGV2KTsKKwkJcmV0dXJuIGZhbHNlOworCX0KKworCXBjaV9kZXZfcHV0KHBkZXYpOworCXJw X2JkZiA9IHBjaV9kZXZfaWQocm9vdF9wb3J0KTsKKwlyZXR1cm4gcnBfYmRmID49IHBjaWVfcG11 LT5iZGZfbWluICYmIHJwX2JkZiA8PSBwY2llX3BtdS0+YmRmX21heDsKK30KKworc3RhdGljIGJv b2wgaGlzaV9wY2llX3BtdV92YWxpZF9maWx0ZXIoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50LAor CQkJCSAgICAgICBzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUpCit7CisJdTMyIHJlcXVl c3Rlcl9pZCA9IGhpc2lfcGNpZV9nZXRfYmRmKGV2ZW50KTsKKworCWlmIChoaXNpX3BjaWVfZ2V0 X3Rocl9sZW4oZXZlbnQpID4gSElTSV9QQ0lFX1RIUl9NQVhfVkFMKQorCQlyZXR1cm4gZmFsc2U7 CisKKwlpZiAoaGlzaV9wY2llX2dldF90cmlnX2xlbihldmVudCkgPiBISVNJX1BDSUVfVFJJR19N QVhfVkFMKQorCQlyZXR1cm4gZmFsc2U7CisKKwlpZiAocmVxdWVzdGVyX2lkKSB7CisJCWlmICgh aGlzaV9wY2llX3BtdV92YWxpZF9yZXF1ZXN0ZXJfaWQocGNpZV9wbXUsIHJlcXVlc3Rlcl9pZCkp CisJCQlyZXR1cm4gZmFsc2U7CisJfQorCisJcmV0dXJuIHRydWU7Cit9CisKK3N0YXRpYyBib29s IGhpc2lfcGNpZV9wbXVfY21wX2V2ZW50KHN0cnVjdCBwZXJmX2V2ZW50ICp0YXJnZXQsCisJCQkJ CXN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCkKK3sKKwlyZXR1cm4gaGlzaV9wY2llX2dldF9yZWFs X2V2ZW50KHRhcmdldCkgPT0gaGlzaV9wY2llX2dldF9yZWFsX2V2ZW50KGV2ZW50KTsKK30KKwor c3RhdGljIGJvb2wgaGlzaV9wY2llX3BtdV92YWxpZGF0ZV9ldmVudF9ncm91cChzdHJ1Y3QgcGVy Zl9ldmVudCAqZXZlbnQpCit7CisJc3RydWN0IHBlcmZfZXZlbnQgKnNpYmxpbmcsICpsZWFkZXIg PSBldmVudC0+Z3JvdXBfbGVhZGVyOworCXN0cnVjdCBwZXJmX2V2ZW50ICpldmVudF9ncm91cFtI SVNJX1BDSUVfTUFYX0NPVU5URVJTXTsKKwlpbnQgY291bnRlcnMgPSAxOworCWludCBudW07CisK KwlldmVudF9ncm91cFswXSA9IGxlYWRlcjsKKwlpZiAoIWlzX3NvZnR3YXJlX2V2ZW50KGxlYWRl cikpIHsKKwkJaWYgKGxlYWRlci0+cG11ICE9IGV2ZW50LT5wbXUpCisJCQlyZXR1cm4gZmFsc2U7 CisKKwkJaWYgKGxlYWRlciAhPSBldmVudCAmJiAhaGlzaV9wY2llX3BtdV9jbXBfZXZlbnQobGVh ZGVyLCBldmVudCkpCisJCQlldmVudF9ncm91cFtjb3VudGVycysrXSA9IGV2ZW50OworCX0KKwor CWZvcl9lYWNoX3NpYmxpbmdfZXZlbnQoc2libGluZywgZXZlbnQtPmdyb3VwX2xlYWRlcikgewor CQlpZiAoaXNfc29mdHdhcmVfZXZlbnQoc2libGluZykpCisJCQljb250aW51ZTsKKworCQlpZiAo c2libGluZy0+cG11ICE9IGV2ZW50LT5wbXUpCisJCQlyZXR1cm4gZmFsc2U7CisKKwkJZm9yIChu dW0gPSAwOyBudW0gPCBjb3VudGVyczsgbnVtKyspIHsKKwkJCWlmIChoaXNpX3BjaWVfcG11X2Nt cF9ldmVudChldmVudF9ncm91cFtudW1dLCBzaWJsaW5nKSkKKwkJCQlicmVhazsKKwkJfQorCisJ CWlmIChudW0gPT0gY291bnRlcnMpCisJCQlldmVudF9ncm91cFtjb3VudGVycysrXSA9IHNpYmxp bmc7CisJfQorCisJcmV0dXJuIGNvdW50ZXJzIDw9IEhJU0lfUENJRV9NQVhfQ09VTlRFUlM7Cit9 CisKK3N0YXRpYyBpbnQgaGlzaV9wY2llX3BtdV9ldmVudF9pbml0KHN0cnVjdCBwZXJmX2V2ZW50 ICpldmVudCkKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2llX3Bt dShldmVudC0+cG11KTsKKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsK KworCWV2ZW50LT5jcHUgPSBwY2llX3BtdS0+b25fY3B1OworCisJaWYgKEVYVF9DT1VOVEVSX0lT X1VTRUQoaGlzaV9wY2llX2dldF9ldmVudChldmVudCkpKQorCQlod2MtPmV2ZW50X2Jhc2UgPSBI SVNJX1BDSUVfRVhUX0NOVDsKKwllbHNlCisJCWh3Yy0+ZXZlbnRfYmFzZSA9IEhJU0lfUENJRV9D TlQ7CisKKwlpZiAoZXZlbnQtPmF0dHIudHlwZSAhPSBldmVudC0+cG11LT50eXBlKQorCQlyZXR1 cm4gLUVOT0VOVDsKKworCS8qIFNhbXBsaW5nIGlzIG5vdCBzdXBwb3J0ZWQuICovCisJaWYgKGlz X3NhbXBsaW5nX2V2ZW50KGV2ZW50KSB8fCBldmVudC0+YXR0YWNoX3N0YXRlICYgUEVSRl9BVFRB Q0hfVEFTSykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJaWYgKCFoaXNpX3BjaWVfcG11X3Zh bGlkX2ZpbHRlcihldmVudCwgcGNpZV9wbXUpKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWlmICgh aGlzaV9wY2llX3BtdV92YWxpZGF0ZV9ldmVudF9ncm91cChldmVudCkpCisJCXJldHVybiAtRUlO VkFMOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB1NjQgaGlzaV9wY2llX3BtdV9yZWFkX2Nv dW50ZXIoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50KQoreworCXN0cnVjdCBoaXNpX3BjaWVfcG11 ICpwY2llX3BtdSA9IHRvX3BjaWVfcG11KGV2ZW50LT5wbXUpOworCXUzMiBpZHggPSBldmVudC0+ aHcuaWR4OworCisJcmV0dXJuIGhpc2lfcGNpZV9wbXVfcmVhZHEocGNpZV9wbXUsIGV2ZW50LT5o dy5ldmVudF9iYXNlLCBpZHgpOworfQorCitzdGF0aWMgaW50IGhpc2lfcGNpZV9wbXVfZmluZF9y ZWxhdGVkX2V2ZW50KHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdSwKKwkJCQkJICAgIHN0 cnVjdCBwZXJmX2V2ZW50ICpldmVudCkKK3sKKwlzdHJ1Y3QgcGVyZl9ldmVudCAqc2libGluZzsK KwlpbnQgaWR4OworCisJZm9yIChpZHggPSAwOyBpZHggPCBISVNJX1BDSUVfTUFYX0NPVU5URVJT OyBpZHgrKykgeworCQlzaWJsaW5nID0gcGNpZV9wbXUtPmh3X2V2ZW50c1tpZHhdOworCQlpZiAo IXNpYmxpbmcpCisJCQljb250aW51ZTsKKworCQlpZiAoIWhpc2lfcGNpZV9wbXVfY21wX2V2ZW50 KHNpYmxpbmcsIGV2ZW50KSkKKwkJCWNvbnRpbnVlOworCisJCS8qIFJlbGF0ZWQgZXZlbnRzIG11 c3QgYmUgdXNlZCBpbiBncm91cCAqLworCQlpZiAoc2libGluZy0+Z3JvdXBfbGVhZGVyID09IGV2 ZW50LT5ncm91cF9sZWFkZXIpCisJCQlyZXR1cm4gaWR4OworCQllbHNlCisJCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlyZXR1cm4gaWR4OworfQorCitzdGF0aWMgaW50IGhpc2lfcGNpZV9wbXVf Z2V0X2V2ZW50X2lkeChzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUpCit7CisJaW50IGlk eDsKKworCWZvciAoaWR4ID0gMDsgaWR4IDwgSElTSV9QQ0lFX01BWF9DT1VOVEVSUzsgaWR4Kysp IHsKKwkJaWYgKCFwY2llX3BtdS0+aHdfZXZlbnRzW2lkeF0pCisJCQlyZXR1cm4gaWR4OworCX0K KworCXJldHVybiAtRUlOVkFMOworfQorCitzdGF0aWMgdm9pZCBoaXNpX3BjaWVfcG11X2V2ZW50 X3VwZGF0ZShzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQpCit7CisJc3RydWN0IGh3X3BlcmZfZXZl bnQgKmh3YyA9ICZldmVudC0+aHc7CisJdTY0IG5ld19jbnQsIHByZXZfY250LCBkZWx0YTsKKwor CWRvIHsKKwkJcHJldl9jbnQgPSBsb2NhbDY0X3JlYWQoJmh3Yy0+cHJldl9jb3VudCk7CisJCW5l d19jbnQgPSBoaXNpX3BjaWVfcG11X3JlYWRfY291bnRlcihldmVudCk7CisJfSB3aGlsZSAobG9j YWw2NF9jbXB4Y2hnKCZod2MtPnByZXZfY291bnQsIHByZXZfY250LAorCQkJCSBuZXdfY250KSAh PSBwcmV2X2NudCk7CisKKwlkZWx0YSA9IChuZXdfY250IC0gcHJldl9jbnQpICYgSElTSV9QQ0lF X01BWF9QRVJJT0Q7CisJbG9jYWw2NF9hZGQoZGVsdGEsICZldmVudC0+Y291bnQpOworfQorCitz dGF0aWMgdm9pZCBoaXNpX3BjaWVfcG11X3JlYWQoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50KQor eworCWhpc2lfcGNpZV9wbXVfZXZlbnRfdXBkYXRlKGV2ZW50KTsKK30KKworc3RhdGljIHZvaWQg aGlzaV9wY2llX3BtdV9zZXRfcGVyaW9kKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCkKK3sKKwlz dHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2llX3BtdShldmVudC0+cG11KTsK KwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsKKwlpbnQgaWR4ID0gaHdj LT5pZHg7CisKKwlsb2NhbDY0X3NldCgmaHdjLT5wcmV2X2NvdW50LCBISVNJX1BDSUVfSU5JVF9W QUwpOworCWhpc2lfcGNpZV9wbXVfd3JpdGVxKHBjaWVfcG11LCBISVNJX1BDSUVfQ05ULCBpZHgs IEhJU0lfUENJRV9JTklUX1ZBTCk7CisJaGlzaV9wY2llX3BtdV93cml0ZXEocGNpZV9wbXUsIEhJ U0lfUENJRV9FWFRfQ05ULCBpZHgsIEhJU0lfUENJRV9JTklUX1ZBTCk7Cit9CisKK3N0YXRpYyB2 b2lkIGhpc2lfcGNpZV9wbXVfZW5hYmxlX2NvdW50ZXIoc3RydWN0IGhpc2lfcGNpZV9wbXUgKnBj aWVfcG11LCBzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjKQoreworCXUzMiBpZHggPSBod2MtPmlk eDsKKwl1NjQgdmFsOworCisJdmFsID0gaGlzaV9wY2llX3BtdV9yZWFkcShwY2llX3BtdSwgSElT SV9QQ0lFX0VWRU5UX0NUUkwsIGlkeCk7CisJdmFsIHw9IEhJU0lfUENJRV9FVkVOVF9FTjsKKwlo aXNpX3BjaWVfcG11X3dyaXRlcShwY2llX3BtdSwgSElTSV9QQ0lFX0VWRU5UX0NUUkwsIGlkeCwg dmFsKTsKK30KKworc3RhdGljIHZvaWQgaGlzaV9wY2llX3BtdV9kaXNhYmxlX2NvdW50ZXIoc3Ry dWN0IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11LCBzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjKQor eworCXUzMiBpZHggPSBod2MtPmlkeDsKKwl1NjQgdmFsOworCisJdmFsID0gaGlzaV9wY2llX3Bt dV9yZWFkcShwY2llX3BtdSwgSElTSV9QQ0lFX0VWRU5UX0NUUkwsIGlkeCk7CisJdmFsICY9IH5I SVNJX1BDSUVfRVZFTlRfRU47CisJaGlzaV9wY2llX3BtdV93cml0ZXEocGNpZV9wbXUsIEhJU0lf UENJRV9FVkVOVF9DVFJMLCBpZHgsIHZhbCk7Cit9CisKK3N0YXRpYyB2b2lkIGhpc2lfcGNpZV9w bXVfZW5hYmxlX2ludChzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUsIHN0cnVjdCBod19w ZXJmX2V2ZW50ICpod2MpCit7CisJdTMyIGlkeCA9IGh3Yy0+aWR4OworCisJaGlzaV9wY2llX3Bt dV93cml0ZWwocGNpZV9wbXUsIEhJU0lfUENJRV9JTlRfTUFTSywgaWR4LCAwKTsKK30KKworc3Rh dGljIHZvaWQgaGlzaV9wY2llX3BtdV9kaXNhYmxlX2ludChzdHJ1Y3QgaGlzaV9wY2llX3BtdSAq cGNpZV9wbXUsIHN0cnVjdCBod19wZXJmX2V2ZW50ICpod2MpCit7CisJdTMyIGlkeCA9IGh3Yy0+ aWR4OworCisJaGlzaV9wY2llX3BtdV93cml0ZWwocGNpZV9wbXUsIEhJU0lfUENJRV9JTlRfTUFT SywgaWR4LCAxKTsKK30KKworc3RhdGljIHZvaWQgaGlzaV9wY2llX3BtdV9yZXNldF9jb3VudGVy KHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdSwgaW50IGlkeCkKK3sKKwloaXNpX3BjaWVf cG11X3dyaXRlcShwY2llX3BtdSwgSElTSV9QQ0lFX0VWRU5UX0NUUkwsIGlkeCwgSElTSV9QQ0lF X1JFU0VUX0NOVCk7CisJaGlzaV9wY2llX3BtdV93cml0ZXEocGNpZV9wbXUsIEhJU0lfUENJRV9F VkVOVF9DVFJMLCBpZHgsIEhJU0lfUENJRV9JTklUX1NFVCk7Cit9CisKK3N0YXRpYyB2b2lkIGhp c2lfcGNpZV9wbXVfc3RhcnQoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50LCBpbnQgZmxhZ3MpCit7 CisJc3RydWN0IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11ID0gdG9fcGNpZV9wbXUoZXZlbnQtPnBt dSk7CisJc3RydWN0IGh3X3BlcmZfZXZlbnQgKmh3YyA9ICZldmVudC0+aHc7CisJaW50IGlkeCA9 IGh3Yy0+aWR4OworCXU2NCBwcmV2X2NudDsKKworCWlmIChXQVJOX09OX09OQ0UoIShod2MtPnN0 YXRlICYgUEVSRl9IRVNfU1RPUFBFRCkpKQorCQlyZXR1cm47CisKKwlXQVJOX09OX09OQ0UoISho d2MtPnN0YXRlICYgUEVSRl9IRVNfVVBUT0RBVEUpKTsKKwlod2MtPnN0YXRlID0gMDsKKworCWhp c2lfcGNpZV9wbXVfY29uZmlnX2ZpbHRlcihldmVudCk7CisJaGlzaV9wY2llX3BtdV9lbmFibGVf Y291bnRlcihwY2llX3BtdSwgaHdjKTsKKwloaXNpX3BjaWVfcG11X2VuYWJsZV9pbnQocGNpZV9w bXUsIGh3Yyk7CisJaGlzaV9wY2llX3BtdV9zZXRfcGVyaW9kKGV2ZW50KTsKKworCWlmIChmbGFn cyAmIFBFUkZfRUZfUkVMT0FEKSB7CisJCXByZXZfY250ID0gbG9jYWw2NF9yZWFkKCZod2MtPnBy ZXZfY291bnQpOworCQloaXNpX3BjaWVfcG11X3dyaXRlcShwY2llX3BtdSwgaHdjLT5ldmVudF9i YXNlLCBpZHgsIHByZXZfY250KTsKKwl9CisKKwlwZXJmX2V2ZW50X3VwZGF0ZV91c2VycGFnZShl dmVudCk7Cit9CisKK3N0YXRpYyB2b2lkIGhpc2lfcGNpZV9wbXVfc3RvcChzdHJ1Y3QgcGVyZl9l dmVudCAqZXZlbnQsIGludCBmbGFncykKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9w bXUgPSB0b19wY2llX3BtdShldmVudC0+cG11KTsKKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdj ID0gJmV2ZW50LT5odzsKKworCWhpc2lfcGNpZV9wbXVfZXZlbnRfdXBkYXRlKGV2ZW50KTsKKwlo aXNpX3BjaWVfcG11X2Rpc2FibGVfaW50KHBjaWVfcG11LCBod2MpOworCWhpc2lfcGNpZV9wbXVf ZGlzYWJsZV9jb3VudGVyKHBjaWVfcG11LCBod2MpOworCWhpc2lfcGNpZV9wbXVfY2xlYXJfZmls dGVyKGV2ZW50KTsKKwlXQVJOX09OX09OQ0UoaHdjLT5zdGF0ZSAmIFBFUkZfSEVTX1NUT1BQRUQp OworCWh3Yy0+c3RhdGUgfD0gUEVSRl9IRVNfU1RPUFBFRDsKKworCWlmIChod2MtPnN0YXRlICYg UEVSRl9IRVNfVVBUT0RBVEUpCisJCXJldHVybjsKKworCWh3Yy0+c3RhdGUgfD0gUEVSRl9IRVNf VVBUT0RBVEU7Cit9CisKK3N0YXRpYyBpbnQgaGlzaV9wY2llX3BtdV9hZGQoc3RydWN0IHBlcmZf ZXZlbnQgKmV2ZW50LCBpbnQgZmxhZ3MpCit7CisJc3RydWN0IGhpc2lfcGNpZV9wbXUgKnBjaWVf cG11ID0gdG9fcGNpZV9wbXUoZXZlbnQtPnBtdSk7CisJc3RydWN0IGh3X3BlcmZfZXZlbnQgKmh3 YyA9ICZldmVudC0+aHc7CisJaW50IGlkeDsKKworCWh3Yy0+c3RhdGUgPSBQRVJGX0hFU19TVE9Q UEVEIHwgUEVSRl9IRVNfVVBUT0RBVEU7CisKKwkvKiBDaGVjayBhbGwgd29ya2luZyBldmVudHMg dG8gZmluZCBhIHJlbGF0ZWQgZXZlbnQuICovCisJaWR4ID0gaGlzaV9wY2llX3BtdV9maW5kX3Jl bGF0ZWRfZXZlbnQocGNpZV9wbXUsIGV2ZW50KTsKKwlpZiAoaWR4IDwgMCkKKwkJcmV0dXJuIGlk eDsKKworCS8qIEN1cnJlbnQgZXZlbnQgc2hhcmVzIGFuIGVuYWJsZWQgY291bnRlciB3aXRoIHRo ZSByZWxhdGVkIGV2ZW50ICovCisJaWYgKGlkeCA8IEhJU0lfUENJRV9NQVhfQ09VTlRFUlMpIHsK KwkJaHdjLT5pZHggPSBpZHg7CisJCWdvdG8gc3RhcnRfY291bnQ7CisJfQorCisJaWR4ID0gaGlz aV9wY2llX3BtdV9nZXRfZXZlbnRfaWR4KHBjaWVfcG11KTsKKwlpZiAoaWR4IDwgMCkKKwkJcmV0 dXJuIGlkeDsKKworCWh3Yy0+aWR4ID0gaWR4OworCXBjaWVfcG11LT5od19ldmVudHNbaWR4XSA9 IGV2ZW50OworCS8qIFJlc2V0IENvdW50ZXIgdG8gYXZvaWQgcHJldmlvdXMgc3RhdGlzdGljIGlu dGVyZmVyZW5jZS4gKi8KKwloaXNpX3BjaWVfcG11X3Jlc2V0X2NvdW50ZXIocGNpZV9wbXUsIGlk eCk7CisKK3N0YXJ0X2NvdW50OgorCWlmIChmbGFncyAmIFBFUkZfRUZfU1RBUlQpCisJCWhpc2lf cGNpZV9wbXVfc3RhcnQoZXZlbnQsIFBFUkZfRUZfUkVMT0FEKTsKKworCXJldHVybiAwOworfQor CitzdGF0aWMgdm9pZCBoaXNpX3BjaWVfcG11X2RlbChzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQs IGludCBmbGFncykKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2ll X3BtdShldmVudC0+cG11KTsKKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5o dzsKKworCWhpc2lfcGNpZV9wbXVfc3RvcChldmVudCwgUEVSRl9FRl9VUERBVEUpOworCXBjaWVf cG11LT5od19ldmVudHNbaHdjLT5pZHhdID0gTlVMTDsKKwlwZXJmX2V2ZW50X3VwZGF0ZV91c2Vy cGFnZShldmVudCk7Cit9CisKK3N0YXRpYyB2b2lkIGhpc2lfcGNpZV9wbXVfZW5hYmxlKHN0cnVj dCBwbXUgKnBtdSkKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUgPSB0b19wY2ll X3BtdShwbXUpOworCWludCBudW07CisKKwlmb3IgKG51bSA9IDA7IG51bSA8IEhJU0lfUENJRV9N QVhfQ09VTlRFUlM7IG51bSsrKSB7CisJCWlmIChwY2llX3BtdS0+aHdfZXZlbnRzW251bV0pCisJ CQlicmVhazsKKwl9CisKKwlpZiAobnVtID09IEhJU0lfUENJRV9NQVhfQ09VTlRFUlMpCisJCXJl dHVybjsKKworCXdyaXRlbChISVNJX1BDSUVfR0xPQkFMX0VOLCBwY2llX3BtdS0+YmFzZSArIEhJ U0lfUENJRV9HTE9CQUxfQ1RSTCk7Cit9CisKK3N0YXRpYyB2b2lkIGhpc2lfcGNpZV9wbXVfZGlz YWJsZShzdHJ1Y3QgcG11ICpwbXUpCit7CisJc3RydWN0IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11 ID0gdG9fcGNpZV9wbXUocG11KTsKKworCXdyaXRlbChISVNJX1BDSUVfR0xPQkFMX05PTkUsIHBj aWVfcG11LT5iYXNlICsgSElTSV9QQ0lFX0dMT0JBTF9DVFJMKTsKK30KKworc3RhdGljIGlycXJl dHVybl90IGhpc2lfcGNpZV9wbXVfaXJxKGludCBpcnEsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0 IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11ID0gZGF0YTsKKwlpcnFyZXR1cm5fdCByZXQgPSBJUlFf Tk9ORTsKKwlzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQ7CisJdTMyIG92ZXJmbG93bjsKKwlpbnQg aWR4OworCisJZm9yIChpZHggPSAwOyBpZHggPCBISVNJX1BDSUVfTUFYX0NPVU5URVJTOyBpZHgr KykgeworCQlvdmVyZmxvd24gPSBoaXNpX3BjaWVfcG11X3JlYWRsKHBjaWVfcG11LCBISVNJX1BD SUVfSU5UX1NUQVQsIGlkeCk7CisJCWlmICghb3ZlcmZsb3duKQorCQkJY29udGludWU7CisKKwkJ LyogQ2xlYXIgc3RhdHVzIG9mIGludGVycnVwdC4gKi8KKwkJaGlzaV9wY2llX3BtdV93cml0ZWwo cGNpZV9wbXUsIEhJU0lfUENJRV9JTlRfU1RBVCwgaWR4LCAxKTsKKwkJZXZlbnQgPSBwY2llX3Bt dS0+aHdfZXZlbnRzW2lkeF07CisJCWlmICghZXZlbnQpCisJCQljb250aW51ZTsKKworCQloaXNp X3BjaWVfcG11X2V2ZW50X3VwZGF0ZShldmVudCk7CisJCWhpc2lfcGNpZV9wbXVfc2V0X3Blcmlv ZChldmVudCk7CisJCXJldCA9IElSUV9IQU5ETEVEOworCX0KKworCXJldHVybiByZXQ7Cit9CisK K3N0YXRpYyBpbnQgaGlzaV9wY2llX3BtdV9pcnFfcmVnaXN0ZXIoc3RydWN0IHBjaV9kZXYgKnBk ZXYsIHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdSkKK3sKKwlpbnQgaXJxLCByZXQ7CisK KwlyZXQgPSBwY2lfYWxsb2NfaXJxX3ZlY3RvcnMocGRldiwgMSwgMSwgUENJX0lSUV9NU0kpOwor CWlmIChyZXQgPCAwKSB7CisJCXBjaV9lcnIocGRldiwgIkZhaWxlZCB0byBlbmFibGUgTVNJIHZl Y3RvcnM6ICVkXG4iLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCWlycSA9IHBjaV9pcnFf dmVjdG9yKHBkZXYsIDApOworCXJldCA9IHJlcXVlc3RfaXJxKGlycSwgaGlzaV9wY2llX3BtdV9p cnEsIElSUUZfTk9CQUxBTkNJTkcgfCBJUlFGX05PX1RIUkVBRCwgRFJWX05BTUUsCisJCQkgIHBj aWVfcG11KTsKKwlpZiAocmV0KSB7CisJCXBjaV9lcnIocGRldiwgIkZhaWxlZCB0byByZWdpc3Rl ciBJUlE6ICVkXG4iLCByZXQpOworCQlwY2lfZnJlZV9pcnFfdmVjdG9ycyhwZGV2KTsKKwkJcmV0 dXJuIHJldDsKKwl9CisKKwlwY2llX3BtdS0+aXJxID0gaXJxOworCisJcmV0dXJuIDA7Cit9CisK K3N0YXRpYyB2b2lkIGhpc2lfcGNpZV9wbXVfaXJxX3VucmVnaXN0ZXIoc3RydWN0IHBjaV9kZXYg KnBkZXYsIHN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdSkKK3sKKwlmcmVlX2lycShwY2ll X3BtdS0+aXJxLCBwY2llX3BtdSk7CisJcGNpX2ZyZWVfaXJxX3ZlY3RvcnMocGRldik7Cit9CisK K3N0YXRpYyBpbnQgaGlzaV9wY2llX3BtdV9vbmxpbmVfY3B1KHVuc2lnbmVkIGludCBjcHUsIHN0 cnVjdCBobGlzdF9ub2RlICpub2RlKQoreworCXN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3Bt dSA9IGhsaXN0X2VudHJ5X3NhZmUobm9kZSwgc3RydWN0IGhpc2lfcGNpZV9wbXUsIG5vZGUpOwor CisJaWYgKHBjaWVfcG11LT5vbl9jcHUgPT0gLTEpIHsKKwkJcGNpZV9wbXUtPm9uX2NwdSA9IGNw dTsKKwkJV0FSTl9PTihpcnFfc2V0X2FmZmluaXR5KHBjaWVfcG11LT5pcnEsIGNwdW1hc2tfb2Yo Y3B1KSkpOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGhpc2lfcGNpZV9wbXVf b2ZmbGluZV9jcHUodW5zaWduZWQgaW50IGNwdSwgc3RydWN0IGhsaXN0X25vZGUgKm5vZGUpCit7 CisJc3RydWN0IGhpc2lfcGNpZV9wbXUgKnBjaWVfcG11ID0gaGxpc3RfZW50cnlfc2FmZShub2Rl LCBzdHJ1Y3QgaGlzaV9wY2llX3BtdSwgbm9kZSk7CisJdW5zaWduZWQgaW50IHRhcmdldDsKKwor CS8qIE5vdGhpbmcgdG8gZG8gaWYgdGhpcyBDUFUgZG9lc24ndCBvd24gdGhlIFBNVSAqLworCWlm IChwY2llX3BtdS0+b25fY3B1ICE9IGNwdSkKKwkJcmV0dXJuIDA7CisKKwlwY2llX3BtdS0+b25f Y3B1ID0gLTE7CisJLyogQ2hvb3NlIGEgbmV3IENQVSBmcm9tIGFsbCBvbmxpbmUgY3B1cy4gKi8K Kwl0YXJnZXQgPSBjcHVtYXNrX2ZpcnN0KGNwdV9vbmxpbmVfbWFzayk7CisJaWYgKHRhcmdldCA+ PSBucl9jcHVfaWRzKSB7CisJCXBjaV9lcnIocGNpZV9wbXUtPnBkZXYsICJUaGVyZSBpcyBubyBD UFUgdG8gc2V0XG4iKTsKKwkJcmV0dXJuIDA7CisJfQorCisJcGVyZl9wbXVfbWlncmF0ZV9jb250 ZXh0KCZwY2llX3BtdS0+cG11LCBjcHUsIHRhcmdldCk7CisJLyogVXNlIHRoaXMgQ1BVIGZvciBl dmVudCBjb3VudGluZyAqLworCXBjaWVfcG11LT5vbl9jcHUgPSB0YXJnZXQ7CisJV0FSTl9PTihp cnFfc2V0X2FmZmluaXR5KHBjaWVfcG11LT5pcnEsIGNwdW1hc2tfb2YodGFyZ2V0KSkpOworCisJ cmV0dXJuIDA7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpoaXNpX3BjaWVfcG11X2V2 ZW50c19hdHRyW10gPSB7CisJSElTSV9QQ0lFX1BNVV9FVkVOVF9BVFRSKHJ4X213cl9sYXRlbmN5 LCAweDAwMTApLAorCUhJU0lfUENJRV9QTVVfRVZFTlRfQVRUUihyeF9td3JfY250LCAweDEwMDEw KSwKKwlISVNJX1BDSUVfUE1VX0VWRU5UX0FUVFIocnhfbXJkX2xhdGVuY3ksIDB4MDIxMCksCisJ SElTSV9QQ0lFX1BNVV9FVkVOVF9BVFRSKHJ4X21yZF9jbnQsIDB4MTAyMTApLAorCUhJU0lfUENJ RV9QTVVfRVZFTlRfQVRUUih0eF9tcmRfbGF0ZW5jeSwgMHgwMDExKSwKKwlISVNJX1BDSUVfUE1V X0VWRU5UX0FUVFIodHhfbXJkX2NudCwgMHgxMDAxMSksCisJSElTSV9QQ0lFX1BNVV9FVkVOVF9B VFRSKHJ4X21yZF9mbHV4LCAweDEwMDUpLAorCUhJU0lfUENJRV9QTVVfRVZFTlRfQVRUUihyeF9t cmRfdGltZSwgMHgxMTAwNSksCisJSElTSV9QQ0lFX1BNVV9FVkVOVF9BVFRSKHR4X21yZF9mbHV4 LCAweDIwMDQpLAorCUhJU0lfUENJRV9QTVVfRVZFTlRfQVRUUih0eF9tcmRfdGltZSwgMHgxMjAw NCksCisJTlVMTAorfTsKKworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgaGlzaV9wY2ll X3BtdV9ldmVudHNfZ3JvdXAgPSB7CisJLm5hbWUgPSAiZXZlbnRzIiwKKwkuYXR0cnMgPSBoaXNp X3BjaWVfcG11X2V2ZW50c19hdHRyLAorfTsKKworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmhp c2lfcGNpZV9wbXVfZm9ybWF0X2F0dHJbXSA9IHsKKwlISVNJX1BDSUVfUE1VX0ZPUk1BVF9BVFRS KGV2ZW50LCAiY29uZmlnOjAtMTYiKSwKKwlISVNJX1BDSUVfUE1VX0ZPUk1BVF9BVFRSKHRocl9s ZW4sICJjb25maWcxOjAtMyIpLAorCUhJU0lfUENJRV9QTVVfRk9STUFUX0FUVFIodGhyX21vZGUs ICJjb25maWcxOjQiKSwKKwlISVNJX1BDSUVfUE1VX0ZPUk1BVF9BVFRSKHRyaWdfbGVuLCAiY29u ZmlnMTo1LTgiKSwKKwlISVNJX1BDSUVfUE1VX0ZPUk1BVF9BVFRSKHRyaWdfbW9kZSwgImNvbmZp ZzE6OSIpLAorCUhJU0lfUENJRV9QTVVfRk9STUFUX0FUVFIocG9ydCwgImNvbmZpZzI6MC0xNSIp LAorCUhJU0lfUENJRV9QTVVfRk9STUFUX0FUVFIoYmRmLCAiY29uZmlnMjoxNi0zMSIpLAorCU5V TEwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGhpc2lfcGNpZV9w bXVfZm9ybWF0X2dyb3VwID0geworCS5uYW1lID0gImZvcm1hdCIsCisJLmF0dHJzID0gaGlzaV9w Y2llX3BtdV9mb3JtYXRfYXR0ciwKK307CisKK3N0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpoaXNp X3BjaWVfcG11X2J1c19hdHRyc1tdID0geworCSZkZXZfYXR0cl9idXMuYXR0ciwKKwlOVUxMCit9 OworCitzdGF0aWMgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBoaXNpX3BjaWVfcG11X2J1 c19hdHRyX2dyb3VwID0geworCS5hdHRycyA9IGhpc2lfcGNpZV9wbXVfYnVzX2F0dHJzLAorfTsK Kworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmhpc2lfcGNpZV9wbXVfY3B1bWFza19hdHRyc1td ID0geworCSZkZXZfYXR0cl9jcHVtYXNrLmF0dHIsCisJTlVMTAorfTsKKworc3RhdGljIGNvbnN0 IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgaGlzaV9wY2llX3BtdV9jcHVtYXNrX2F0dHJfZ3JvdXAg PSB7CisJLmF0dHJzID0gaGlzaV9wY2llX3BtdV9jcHVtYXNrX2F0dHJzLAorfTsKKworc3RhdGlj IHN0cnVjdCBhdHRyaWJ1dGUgKmhpc2lfcGNpZV9wbXVfaWRlbnRpZmllcl9hdHRyc1tdID0gewor CSZkZXZfYXR0cl9pZGVudGlmaWVyLmF0dHIsCisJTlVMTAorfTsKKworc3RhdGljIGNvbnN0IHN0 cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgaGlzaV9wY2llX3BtdV9pZGVudGlmaWVyX2F0dHJfZ3JvdXAg PSB7CisJLmF0dHJzID0gaGlzaV9wY2llX3BtdV9pZGVudGlmaWVyX2F0dHJzLAorfTsKKworc3Rh dGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKmhpc2lfcGNpZV9wbXVfYXR0cl9ncm91 cHNbXSA9IHsKKwkmaGlzaV9wY2llX3BtdV9ldmVudHNfZ3JvdXAsCisJJmhpc2lfcGNpZV9wbXVf Zm9ybWF0X2dyb3VwLAorCSZoaXNpX3BjaWVfcG11X2J1c19hdHRyX2dyb3VwLAorCSZoaXNpX3Bj aWVfcG11X2NwdW1hc2tfYXR0cl9ncm91cCwKKwkmaGlzaV9wY2llX3BtdV9pZGVudGlmaWVyX2F0 dHJfZ3JvdXAsCisJTlVMTAorfTsKKworc3RhdGljIGludCBoaXNpX3BjaWVfYWxsb2NfcG11KHN0 cnVjdCBwY2lfZGV2ICpwZGV2LCBzdHJ1Y3QgaGlzaV9wY2llX3BtdSAqcGNpZV9wbXUpCit7CisJ c3RydWN0IGhpc2lfcGNpZV9yZWdfcGFpciByZWdzOworCXUxNiBzaWNsX2lkLCBjb3JlX2lkOwor CWNoYXIgKm5hbWU7CisKKwlyZWdzID0gaGlzaV9wY2llX3BhcnNlX3JlZ192YWx1ZShwY2llX3Bt dSwgSElTSV9QQ0lFX1JFR19CREYpOworCXBjaWVfcG11LT5iZGZfbWluID0gcmVncy5sbzsKKwlw Y2llX3BtdS0+YmRmX21heCA9IHJlZ3MuaGk7CisKKwlyZWdzID0gaGlzaV9wY2llX3BhcnNlX3Jl Z192YWx1ZShwY2llX3BtdSwgSElTSV9QQ0lFX1JFR19JTkZPKTsKKwlzaWNsX2lkID0gcmVncy5o aTsKKwljb3JlX2lkID0gcmVncy5sbzsKKworCW5hbWUgPSBkZXZtX2thc3ByaW50ZigmcGRldi0+ ZGV2LCBHRlBfS0VSTkVMLCAiaGlzaV9wY2llJXVfY29yZSV1Iiwgc2ljbF9pZCwgY29yZV9pZCk7 CisJaWYgKCFuYW1lKQorCQlyZXR1cm4gLUVOT01FTTsKKworCXBjaWVfcG11LT5wZGV2ID0gcGRl djsKKwlwY2llX3BtdS0+b25fY3B1ID0gLTE7CisJcGNpZV9wbXUtPmlkZW50aWZpZXIgPSByZWFk bChwY2llX3BtdS0+YmFzZSArIEhJU0lfUENJRV9SRUdfVkVSU0lPTik7CisJcGNpZV9wbXUtPnBt dSA9IChzdHJ1Y3QgcG11KSB7CisJCS5uYW1lCQk9IG5hbWUsCisJCS5tb2R1bGUJCT0gVEhJU19N T0RVTEUsCisJCS5ldmVudF9pbml0CT0gaGlzaV9wY2llX3BtdV9ldmVudF9pbml0LAorCQkucG11 X2VuYWJsZQk9IGhpc2lfcGNpZV9wbXVfZW5hYmxlLAorCQkucG11X2Rpc2FibGUJPSBoaXNpX3Bj aWVfcG11X2Rpc2FibGUsCisJCS5hZGQJCT0gaGlzaV9wY2llX3BtdV9hZGQsCisJCS5kZWwJCT0g aGlzaV9wY2llX3BtdV9kZWwsCisJCS5zdGFydAkJPSBoaXNpX3BjaWVfcG11X3N0YXJ0LAorCQku c3RvcAkJPSBoaXNpX3BjaWVfcG11X3N0b3AsCisJCS5yZWFkCQk9IGhpc2lfcGNpZV9wbXVfcmVh ZCwKKwkJLnRhc2tfY3R4X25yCT0gcGVyZl9pbnZhbGlkX2NvbnRleHQsCisJCS5hdHRyX2dyb3Vw cwk9IGhpc2lfcGNpZV9wbXVfYXR0cl9ncm91cHMsCisJCS5jYXBhYmlsaXRpZXMJPSBQRVJGX1BN VV9DQVBfTk9fRVhDTFVERSwKKwl9OworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgaGlz aV9wY2llX2luaXRfcG11KHN0cnVjdCBwY2lfZGV2ICpwZGV2LCBzdHJ1Y3QgaGlzaV9wY2llX3Bt dSAqcGNpZV9wbXUpCit7CisJaW50IHJldDsKKworCXBjaWVfcG11LT5iYXNlID0gcGNpX2lvcmVt YXBfYmFyKHBkZXYsIDIpOworCWlmICghcGNpZV9wbXUtPmJhc2UpIHsKKwkJcGNpX2VycihwZGV2 LCAiSW9yZW1hcCBmYWlsZWQgZm9yIHBjaWVfcG11IHJlc291cmNlXG4iKTsKKwkJcmV0dXJuIC1F Tk9NRU07CisJfQorCisJcmV0ID0gaGlzaV9wY2llX2FsbG9jX3BtdShwZGV2LCBwY2llX3BtdSk7 CisJaWYgKHJldCkKKwkJZ290byBlcnJfaW91bm1hcDsKKworCXJldCA9IGhpc2lfcGNpZV9wbXVf aXJxX3JlZ2lzdGVyKHBkZXYsIHBjaWVfcG11KTsKKwlpZiAocmV0KQorCQlnb3RvIGVycl9pb3Vu bWFwOworCisJcmV0ID0gY3B1aHBfc3RhdGVfYWRkX2luc3RhbmNlKENQVUhQX0FQX1BFUkZfQVJN X0hJU0lfUENJRV9QTVVfT05MSU5FLCAmcGNpZV9wbXUtPm5vZGUpOworCWlmIChyZXQpIHsKKwkJ cGNpX2VycihwZGV2LCAiRmFpbGVkIHRvIHJlZ2lzdGVyIGhvdHBsdWc6ICVkXG4iLCByZXQpOwor CQlnb3RvIGVycl9pcnFfdW5yZWdpc3RlcjsKKwl9CisKKwlyZXQgPSBwZXJmX3BtdV9yZWdpc3Rl cigmcGNpZV9wbXUtPnBtdSwgcGNpZV9wbXUtPnBtdS5uYW1lLCAtMSk7CisJaWYgKHJldCkgewor CQlwY2lfZXJyKHBkZXYsICJGYWlsZWQgdG8gcmVnaXN0ZXIgUENJZSBQTVU6ICVkXG4iLCByZXQp OworCQlnb3RvIGVycl9ob3RwbHVnX3VucmVnaXN0ZXI7CisJfQorCisJcmV0dXJuIHJldDsKKwor ZXJyX2hvdHBsdWdfdW5yZWdpc3RlcjoKKwljcHVocF9zdGF0ZV9yZW1vdmVfaW5zdGFuY2Vfbm9j YWxscygKKwkJQ1BVSFBfQVBfUEVSRl9BUk1fSElTSV9QQ0lFX1BNVV9PTkxJTkUsICZwY2llX3Bt dS0+bm9kZSk7CisKK2Vycl9pcnFfdW5yZWdpc3RlcjoKKwloaXNpX3BjaWVfcG11X2lycV91bnJl Z2lzdGVyKHBkZXYsIHBjaWVfcG11KTsKKworZXJyX2lvdW5tYXA6CisJaW91bm1hcChwY2llX3Bt dS0+YmFzZSk7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBoaXNpX3BjaWVfdW5p bml0X3BtdShzdHJ1Y3QgcGNpX2RldiAqcGRldikKK3sKKwlzdHJ1Y3QgaGlzaV9wY2llX3BtdSAq cGNpZV9wbXUgPSBwY2lfZ2V0X2RydmRhdGEocGRldik7CisKKwlwZXJmX3BtdV91bnJlZ2lzdGVy KCZwY2llX3BtdS0+cG11KTsKKwljcHVocF9zdGF0ZV9yZW1vdmVfaW5zdGFuY2Vfbm9jYWxscygK KwkJQ1BVSFBfQVBfUEVSRl9BUk1fSElTSV9QQ0lFX1BNVV9PTkxJTkUsICZwY2llX3BtdS0+bm9k ZSk7CisJaGlzaV9wY2llX3BtdV9pcnFfdW5yZWdpc3RlcihwZGV2LCBwY2llX3BtdSk7CisJaW91 bm1hcChwY2llX3BtdS0+YmFzZSk7Cit9CisKK3N0YXRpYyBpbnQgaGlzaV9wY2llX2luaXRfZGV2 KHN0cnVjdCBwY2lfZGV2ICpwZGV2KQoreworCWludCByZXQ7CisKKwlyZXQgPSBwY2ltX2VuYWJs ZV9kZXZpY2UocGRldik7CisJaWYgKHJldCkgeworCQlwY2lfZXJyKHBkZXYsICJGYWlsZWQgdG8g ZW5hYmxlIFBDSSBkZXZpY2U6ICVkXG4iLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJl dCA9IHBjaW1faW9tYXBfcmVnaW9ucyhwZGV2LCBCSVQoMiksIERSVl9OQU1FKTsKKwlpZiAocmV0 IDwgMCkgeworCQlwY2lfZXJyKHBkZXYsICJGYWlsZWQgdG8gcmVxdWVzdCBQQ0kgbWVtIHJlZ2lv bnM6ICVkXG4iLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXBjaV9zZXRfbWFzdGVyKHBk ZXYpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgaGlzaV9wY2llX3BtdV9wcm9iZShz dHJ1Y3QgcGNpX2RldiAqcGRldiwgY29uc3Qgc3RydWN0IHBjaV9kZXZpY2VfaWQgKmlkKQorewor CXN0cnVjdCBoaXNpX3BjaWVfcG11ICpwY2llX3BtdTsKKwlpbnQgcmV0OworCisJcGNpZV9wbXUg PSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCpwY2llX3BtdSksIEdGUF9LRVJORUwp OworCWlmICghcGNpZV9wbXUpCisJCXJldHVybiAtRU5PTUVNOworCisJcmV0ID0gaGlzaV9wY2ll X2luaXRfZGV2KHBkZXYpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlyZXQgPSBoaXNp X3BjaWVfaW5pdF9wbXUocGRldiwgcGNpZV9wbXUpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7 CisKKwlwY2lfc2V0X2RydmRhdGEocGRldiwgcGNpZV9wbXUpOworCisJcmV0dXJuIHJldDsKK30K Kworc3RhdGljIHZvaWQgaGlzaV9wY2llX3BtdV9yZW1vdmUoc3RydWN0IHBjaV9kZXYgKnBkZXYp Cit7CisJaGlzaV9wY2llX3VuaW5pdF9wbXUocGRldik7CisJcGNpX3NldF9kcnZkYXRhKHBkZXYs IE5VTEwpOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IHBjaV9kZXZpY2VfaWQgaGlzaV9wY2ll X3BtdV9pZHNbXSA9IHsKKwl7IFBDSV9ERVZJQ0UoUENJX1ZFTkRPUl9JRF9IVUFXRUksIDB4YTEy ZCkgfSwKKwl7IDAsIH0KK307CitNT0RVTEVfREVWSUNFX1RBQkxFKHBjaSwgaGlzaV9wY2llX3Bt dV9pZHMpOworCitzdGF0aWMgc3RydWN0IHBjaV9kcml2ZXIgaGlzaV9wY2llX3BtdV9kcml2ZXIg PSB7CisJLm5hbWUgPSBEUlZfTkFNRSwKKwkuaWRfdGFibGUgPSBoaXNpX3BjaWVfcG11X2lkcywK KwkucHJvYmUgPSBoaXNpX3BjaWVfcG11X3Byb2JlLAorCS5yZW1vdmUgPSBoaXNpX3BjaWVfcG11 X3JlbW92ZSwKK307CisKK3N0YXRpYyBpbnQgX19pbml0IGhpc2lfcGNpZV9tb2R1bGVfaW5pdCh2 b2lkKQoreworCWludCByZXQ7CisKKwlyZXQgPSBjcHVocF9zZXR1cF9zdGF0ZV9tdWx0aShDUFVI UF9BUF9QRVJGX0FSTV9ISVNJX1BDSUVfUE1VX09OTElORSwKKwkJCQkgICAgICAiQVBfUEVSRl9B Uk1fSElTSV9QQ0lFX1BNVV9PTkxJTkUiLAorCQkJCSAgICAgIGhpc2lfcGNpZV9wbXVfb25saW5l X2NwdSwKKwkJCQkgICAgICBoaXNpX3BjaWVfcG11X29mZmxpbmVfY3B1KTsKKwlpZiAocmV0KSB7 CisJCXByX2VycigiRmFpbGVkIHRvIHNldHVwIFBDSWUgUE1VIGhvdHBsdWcsIHJldCA9ICVkXG4i LCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldCA9IHBjaV9yZWdpc3Rlcl9kcml2ZXIo Jmhpc2lfcGNpZV9wbXVfZHJpdmVyKTsKKwlpZiAocmV0KQorCQljcHVocF9yZW1vdmVfbXVsdGlf c3RhdGUoQ1BVSFBfQVBfUEVSRl9BUk1fSElTSV9QQ0lFX1BNVV9PTkxJTkUpOworCisJcmV0dXJu IHJldDsKK30KK21vZHVsZV9pbml0KGhpc2lfcGNpZV9tb2R1bGVfaW5pdCk7CisKK3N0YXRpYyB2 b2lkIF9fZXhpdCBoaXNpX3BjaWVfbW9kdWxlX2V4aXQodm9pZCkKK3sKKwlwY2lfdW5yZWdpc3Rl cl9kcml2ZXIoJmhpc2lfcGNpZV9wbXVfZHJpdmVyKTsKKwljcHVocF9yZW1vdmVfbXVsdGlfc3Rh dGUoQ1BVSFBfQVBfUEVSRl9BUk1fSElTSV9QQ0lFX1BNVV9PTkxJTkUpOworfQorbW9kdWxlX2V4 aXQoaGlzaV9wY2llX21vZHVsZV9leGl0KTsKKworTU9EVUxFX0RFU0NSSVBUSU9OKCJIaVNpbGlj b24gUENJZSBQTVUgZHJpdmVyIik7CitNT0RVTEVfTElDRU5TRSgiR1BMIHYyIik7CitNT0RVTEVf QVVUSE9SKCJRaSBMaXUgPGxpdXFpMTE1QGh1YXdlaS5jb20+Iik7CmRpZmYgLS1naXQgYS9pbmNs dWRlL2xpbnV4L2NwdWhvdHBsdWcuaCBiL2luY2x1ZGUvbGludXgvY3B1aG90cGx1Zy5oCmluZGV4 IDgzMmQ4YTc0ZmE1OS4uMDJlZDQ4M2I3OWJmIDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2Nw dWhvdHBsdWcuaAorKysgYi9pbmNsdWRlL2xpbnV4L2NwdWhvdHBsdWcuaApAQCAtMjIyLDYgKzIy Miw3IEBAIGVudW0gY3B1aHBfc3RhdGUgewogCUNQVUhQX0FQX1BFUkZfQVJNX0hJU0lfTDNfT05M SU5FLAogCUNQVUhQX0FQX1BFUkZfQVJNX0hJU0lfUEFfT05MSU5FLAogCUNQVUhQX0FQX1BFUkZf QVJNX0hJU0lfU0xMQ19PTkxJTkUsCisJQ1BVSFBfQVBfUEVSRl9BUk1fSElTSV9QQ0lFX1BNVV9P TkxJTkUsCiAJQ1BVSFBfQVBfUEVSRl9BUk1fTDJYMF9PTkxJTkUsCiAJQ1BVSFBfQVBfUEVSRl9B Uk1fUUNPTV9MMl9PTkxJTkUsCiAJQ1BVSFBfQVBfUEVSRl9BUk1fUUNPTV9MM19PTkxJTkUsCi0t IAoyLjMzLjAKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f XwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmlu ZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9s aW51eC1hcm0ta2VybmVsCg==