From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964929AbeAJG72 (ORCPT + 1 other); Wed, 10 Jan 2018 01:59:28 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:34254 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964891AbeAJG7V (ORCPT ); Wed, 10 Jan 2018 01:59:21 -0500 X-Google-Smtp-Source: ACJfBotvHnp1uays4dLsF1J8Ej7PdHMWH5Phtt1y3WojSIojTstGW21L7G6KdndDXUx/hEi02aGXxg== From: ShuFanLee To: heikki.krogerus@linux.intel.com Cc: cy_huang@richtek.com, shufan_lee@richtek.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH] USB TYPEC: RT1711H Type-C Chip Driver Date: Wed, 10 Jan 2018 14:59:12 +0800 Message-Id: <1515567552-7692-1-git-send-email-leechu729@gmail.com> X-Mailer: git-send-email 1.9.1 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 Return-Path: From: ShuFanLee Richtek RT1711H Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB Type-C functionalities. Signed-off-by: ShuFanLee --- .../devicetree/bindings/usb/richtek,rt1711h.txt | 38 + arch/arm64/boot/dts/hisilicon/rt1711h.dtsi | 11 + drivers/usb/typec/Kconfig | 2 + drivers/usb/typec/Makefile | 1 + drivers/usb/typec/rt1711h/Kconfig | 7 + drivers/usb/typec/rt1711h/Makefile | 2 + drivers/usb/typec/rt1711h/rt1711h.c | 2241 ++++++++++++++++++++ drivers/usb/typec/rt1711h/rt1711h.h | 300 +++ 8 files changed, 2602 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/richtek,rt1711h.txt create mode 100644 arch/arm64/boot/dts/hisilicon/rt1711h.dtsi create mode 100644 drivers/usb/typec/rt1711h/Kconfig create mode 100644 drivers/usb/typec/rt1711h/Makefile create mode 100644 drivers/usb/typec/rt1711h/rt1711h.c create mode 100644 drivers/usb/typec/rt1711h/rt1711h.h diff --git a/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt b/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt new file mode 100644 index 0000000..c28299c --- /dev/null +++ b/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt @@ -0,0 +1,38 @@ +Richtek RT1711H Type-C Port Controller. + +Required properties: +- compatible : Must be "richtek,typec_rt1711h"; +- reg : Must be 0x4e, it's default slave address of RT1711H. +- rt,intr_gpio : IRQ GPIO pin that's connected to RT1711H interrupt. + +Optional node: +- rt,name : Name used for registering IRQ and creating kthread. + If this property is not specified, "default" will be applied. +- rt,def_role : Default port role (TYPEC_SINK(0) or TYPEC_SOURCE(1)). + Set to TYPEC_NO_PREFERRED_ROLE(-1) if no default role. + If this property is not specified, TYPEC_SINK will be applied. +- rt,port_type : Port type (TYPEC_PORT_DFP(0), TYPEC_PORT_UFP(1), + or TYPEC_PORT_DRP(2)). If this property is not specified, + TYPEC_PORT_DRP will be applied. +- rt,max_snk_mv : Maximum acceptable sink voltage in mV. + If this property is not specified, 5000mV will be applied. +- rt,max_snk_ma : Maximum sink current in mA. + If this property is not specified, 3000mA will be applied. +- rt,max_snk_mw : Maximum required sink power in mW. + If this property is not specified, 15000mW will be applied. +- rt,operating_snk_mw : Required operating sink power in mW. + If this property is not specified, + 2500mW will be applied. +- rt,try_role_hw : True if try.{Src,Snk} is implemented in hardware. + If this property is not specified, False will be applied. + +Example: +rt1711h@4e { + status = "ok"; + compatible = "richtek,typec_rt1711h"; + reg = <0x4e>; + rt,intr_gpio = <&gpio26 0 0x0>; + rt,name = "rt1711h"; + rt,port_type = <2>; /* 0: DFP, 1: UFP, 2: DRP */ + rt,def_role = <0>; /* 0: SNK, 1: SRC, -1: TYPEC_NO_PREFERRED_ROLE */ +}; diff --git a/arch/arm64/boot/dts/hisilicon/rt1711h.dtsi b/arch/arm64/boot/dts/hisilicon/rt1711h.dtsi new file mode 100644 index 0000000..4196cc0 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/rt1711h.dtsi @@ -0,0 +1,11 @@ +&i2c7 { + rt1711h@4e { + status = "ok"; + compatible = "richtek,typec_rt1711h"; + reg = <0x4e>; + rt,intr_gpio = <&gpio26 0 0x0>; + rt,name = "rt1711h"; + rt,port_type = <2>; /* 0: DFP, 1: UFP, 2: DRP */ + rt,def_role = <0>; /* 0: SNK, 1: SRC */ + }; +}; diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index bcb2744..7bede0b 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -56,6 +56,8 @@ if TYPEC_TCPM source "drivers/usb/typec/fusb302/Kconfig" +source "drivers/usb/typec/rt1711h/Kconfig" + config TYPEC_WCOVE tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver" depends on ACPI diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index bb3138a..e3aaf3c 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_TYPEC) += typec.o obj-$(CONFIG_TYPEC_TCPM) += tcpm.o obj-y += fusb302/ +obj-$(CONFIG_TYPEC_RT1711H) += rt1711h/ obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o obj-$(CONFIG_TYPEC_UCSI) += ucsi/ obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o diff --git a/drivers/usb/typec/rt1711h/Kconfig b/drivers/usb/typec/rt1711h/Kconfig new file mode 100644 index 0000000..2fbfff5 --- /dev/null +++ b/drivers/usb/typec/rt1711h/Kconfig @@ -0,0 +1,7 @@ +config TYPEC_RT1711H + tristate "Richtek RT1711H Type-C chip driver" + depends on I2C && POWER_SUPPLY + help + The Richtek RT1711H Type-C chip driver that works with + Type-C Port Controller Manager to provide USB PD and USB + Type-C functionalities. diff --git a/drivers/usb/typec/rt1711h/Makefile b/drivers/usb/typec/rt1711h/Makefile new file mode 100644 index 0000000..5fab8ae --- /dev/null +++ b/drivers/usb/typec/rt1711h/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_TYPEC_RT1711H) += rt1711h.o diff --git a/drivers/usb/typec/rt1711h/rt1711h.c b/drivers/usb/typec/rt1711h/rt1711h.c new file mode 100644 index 0000000..1aef3e8 --- /dev/null +++ b/drivers/usb/typec/rt1711h/rt1711h.c @@ -0,0 +1,2241 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 Richtek Technologh Corp. + * + * Richtek RT1711H Type-C Chip Driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt1711h.h" + +#define RT1711H_DRV_VERSION "1.0.3" + +#define LOG_BUFFER_ENTRIES 1024 +#define LOG_BUFFER_ENTRY_SIZE 128 /* 128 char per line */ + +enum { + RT1711H_DBG_LOG = 0, + RT1711H_DBG_REGS, + RT1711H_DBG_REG_ADDR, + RT1711H_DBG_DATA, + RT1711H_DBG_MAX, +}; + +struct rt1711h_dbg_info { + struct rt1711h_chip *chip; + int id; +}; + + +struct rt1711h_chip { + struct i2c_client *i2c; + struct device *dev; + uint16_t did; + int irq_gpio; + int irq; + char *name; + struct tcpc_dev tcpc_dev; + struct tcpc_config tcpc_cfg; + struct tcpm_port *tcpm_port; + struct regulator *vbus; + struct extcon_dev *extcon; + + /* IRQ */ + struct kthread_worker irq_worker; + struct kthread_work irq_work; + struct task_struct *irq_worker_task; + atomic_t poll_count; + struct delayed_work poll_work; + + /* LPM */ + struct delayed_work wakeup_work; + struct alarm wakeup_timer; + struct mutex wakeup_lock; + enum typec_cc_pull lpm_pull; + bool wakeup_once; + bool low_rp_duty_cntdown; + bool cable_only; + bool lpm; + + /* I2C */ + atomic_t i2c_busy; + atomic_t pm_suspend; + + /* psy + psy status */ + struct power_supply *psy; + u32 current_limit; + u32 supply_voltage; + + /* lock for sharing chip states */ + struct mutex lock; + + /* port status */ + bool vconn_on; + bool vbus_on; + bool charge_on; + bool vbus_present; + enum typec_cc_polarity polarity; + enum typec_cc_status cc1; + enum typec_cc_status cc2; + enum typec_role pwr_role; + bool drp_toggling; + +#ifdef CONFIG_DEBUG_FS + struct dentry *dbgdir; + struct rt1711h_dbg_info dbg_info[RT1711H_DBG_MAX]; + struct dentry *dbg_files[RT1711H_DBG_MAX]; + int dbg_regidx; + struct mutex dbgops_lock; + /* lock for log buffer access */ + struct mutex logbuffer_lock; + int logbuffer_head; + int logbuffer_tail; + u8 *logbuffer[LOG_BUFFER_ENTRIES]; +#endif /* CONFIG_DEBUG_FS */ +}; + +/* + * Logging & debugging + */ + +#ifdef CONFIG_DEBUG_FS + +static int rt1711h_reg_block_read(struct rt1711h_chip *chip, uint8_t reg, + int len, uint8_t *data); +static int rt1711h_reg_block_write(struct rt1711h_chip *chip, uint8_t reg, + int len, const uint8_t *data); + +struct reg_desc { + uint8_t addr; + uint8_t size; +}; +#define DECL_REG(_addr, _size) {.addr = _addr, .size = _size} + +static struct reg_desc rt1711h_reg_desc[] = { + DECL_REG(RT1711H_REG_VID, 2), + DECL_REG(RT1711H_REG_PID, 2), + DECL_REG(RT1711H_REG_DID, 2), + DECL_REG(RT1711H_REG_TYPEC_REV, 2), + DECL_REG(RT1711H_REG_PD_REV, 2), + DECL_REG(RT1711H_REG_PDIF_REV, 2), + DECL_REG(RT1711H_REG_ALERT, 2), + DECL_REG(RT1711H_REG_ALERT_MASK, 2), + DECL_REG(RT1711H_REG_POWER_STATUS_MASK, 1), + DECL_REG(RT1711H_REG_FAULT_STATUS_MASK, 1), + DECL_REG(RT1711H_REG_TCPC_CTRL, 1), + DECL_REG(RT1711H_REG_ROLE_CTRL, 1), + DECL_REG(RT1711H_REG_FAULT_CTRL, 1), + DECL_REG(RT1711H_REG_POWER_CTRL, 1), + DECL_REG(RT1711H_REG_CC_STATUS, 1), + DECL_REG(RT1711H_REG_POWER_STATUS, 1), + DECL_REG(RT1711H_REG_FAULT_STATUS, 1), + DECL_REG(RT1711H_REG_COMMAND, 1), + DECL_REG(RT1711H_REG_MSG_HDR_INFO, 1), + DECL_REG(RT1711H_REG_RX_DETECT, 1), + DECL_REG(RT1711H_REG_RX_BYTE_CNT, 1), + DECL_REG(RT1711H_REG_RX_BUF_FRAME_TYPE, 1), + DECL_REG(RT1711H_REG_RX_HDR, 2), + DECL_REG(RT1711H_REG_RX_DATA, 1), + DECL_REG(RT1711H_REG_TRANSMIT, 1), + DECL_REG(RT1711H_REG_TX_BYTE_CNT, 1), + DECL_REG(RT1711H_REG_TX_HDR, 2), + DECL_REG(RT1711H_REG_TX_DATA, 1), + DECL_REG(RT1711H_REG_CLK_CTRL2, 1), + DECL_REG(RT1711H_REG_CLK_CTRL3, 1), + DECL_REG(RT1711H_REG_BMC_CTRL, 1), + DECL_REG(RT1711H_REG_BMCIO_RXDZSEL, 1), + DECL_REG(RT1711H_REG_VCONN_CLIMITEN, 1), + DECL_REG(RT1711H_REG_RT_STATUS, 1), + DECL_REG(RT1711H_REG_RT_INT, 1), + DECL_REG(RT1711H_REG_RT_MASK, 1), + DECL_REG(RT1711H_REG_IDLE_CTRL, 1), + DECL_REG(RT1711H_REG_INTRST_CTRL, 1), + DECL_REG(RT1711H_REG_WATCHDOG_CTRL, 1), + DECL_REG(RT1711H_REG_I2CRST_CTRL, 1), + DECL_REG(RT1711H_REG_SWRESET, 1), + DECL_REG(RT1711H_REG_TTCPC_FILTER, 1), + DECL_REG(RT1711H_REG_DRP_TOGGLE_CYCLE, 1), + DECL_REG(RT1711H_REG_DRP_DUTY_CTRL, 1), + DECL_REG(RT1711H_REG_BMCIO_RXDZEN, 1), +}; + +static const char *rt1711h_dbg_filename[RT1711H_DBG_MAX] = { + "log", "regs", "reg_addr", "data", +}; + +static bool rt1711h_log_full(struct rt1711h_chip *chip) +{ + return chip->logbuffer_tail == + (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; +} + +static void _rt1711h_log(struct rt1711h_chip *chip, const char *fmt, + va_list args) +{ + char tmpbuffer[LOG_BUFFER_ENTRY_SIZE]; + u64 ts_nsec = local_clock(); + unsigned long rem_nsec; + + if (!chip->logbuffer[chip->logbuffer_head]) { + chip->logbuffer[chip->logbuffer_head] = + devm_kzalloc(chip->dev, LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL); + if (!chip->logbuffer[chip->logbuffer_head]) + return; + } + + vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args); + + mutex_lock(&chip->logbuffer_lock); + + if (rt1711h_log_full(chip)) { + chip->logbuffer_head = max(chip->logbuffer_head - 1, 0); + strlcpy(tmpbuffer, "overflow", sizeof(tmpbuffer)); + } + + if (chip->logbuffer_head < 0 || + chip->logbuffer_head >= LOG_BUFFER_ENTRIES) { + dev_warn(chip->dev, "%s bad log buffer index %d\n", __func__, + chip->logbuffer_head); + goto abort; + } + + if (!chip->logbuffer[chip->logbuffer_head]) { + dev_warn(chip->dev, "%s log buffer index %d is NULL\n", + __func__, chip->logbuffer_head); + goto abort; + } + + rem_nsec = do_div(ts_nsec, 1000000000); + scnprintf(chip->logbuffer[chip->logbuffer_head], LOG_BUFFER_ENTRY_SIZE, + "[%5lu.%06lu] %s", (unsigned long)ts_nsec, rem_nsec / 1000, + tmpbuffer); + chip->logbuffer_head = (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; + +abort: + mutex_unlock(&chip->logbuffer_lock); +} + +static void rt1711h_log(struct rt1711h_chip *chip, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _rt1711h_log(chip, fmt, args); + va_end(args); +} + +static int rt1711h_log_show(struct rt1711h_chip *chip, struct seq_file *s) +{ + int tail; + + mutex_lock(&chip->logbuffer_lock); + tail = chip->logbuffer_tail; + while (tail != chip->logbuffer_head) { + seq_printf(s, "%s", chip->logbuffer[tail]); + tail = (tail + 1) % LOG_BUFFER_ENTRIES; + } + if (!seq_has_overflowed(s)) + chip->logbuffer_tail = tail; + mutex_unlock(&chip->logbuffer_lock); + + return 0; +} + +static int rt1711h_regs_show(struct rt1711h_chip *chip, struct seq_file *s) +{ + int ret = 0; + int i = 0, j = 0; + struct reg_desc *desc = NULL; + uint8_t regval[2] = {0}; + + for (i = 0; i < ARRAY_SIZE(rt1711h_reg_desc); i++) { + desc = &rt1711h_reg_desc[i]; + ret = rt1711h_reg_block_read(chip, desc->addr, desc->size, + regval); + if (ret < 0) { + dev_err(chip->dev, "%s read reg0x%02X fail\n", + __func__, desc->addr); + continue; + } + + seq_printf(s, "reg0x%02x:0x", desc->addr); + for (j = 0; j < desc->size; j++) + seq_printf(s, "%02x,", regval[j]); + seq_puts(s, "\n"); + } + + return 0; +} + +static inline int rt1711h_reg_addr_show(struct rt1711h_chip *chip, + struct seq_file *s) +{ + struct reg_desc *desc = &rt1711h_reg_desc[chip->dbg_regidx]; + + seq_printf(s, "0x%02x\n", desc->addr); + return 0; +} + +static inline int rt1711h_data_show(struct rt1711h_chip *chip, + struct seq_file *s) +{ + int ret = 0, i = 0; + struct reg_desc *desc = &rt1711h_reg_desc[chip->dbg_regidx]; + uint8_t regval[2] = {0}; + + ret = rt1711h_reg_block_read(chip, desc->addr, desc->size, regval); + if (ret < 0) + return ret; + + seq_printf(s, "reg0x%02x=0x", desc->addr); + for (i = 0; i < desc->size; i++) + seq_printf(s, "%02x,", regval[i]); + seq_puts(s, "\n"); + return 0; +} + +static int rt1711h_dbg_show(struct seq_file *s, void *v) +{ + int ret = 0; + struct rt1711h_dbg_info *info = (struct rt1711h_dbg_info *)s->private; + struct rt1711h_chip *chip = info->chip; + + mutex_lock(&chip->dbgops_lock); + switch (info->id) { + case RT1711H_DBG_LOG: + ret = rt1711h_log_show(chip, s); + break; + case RT1711H_DBG_REGS: + ret = rt1711h_regs_show(chip, s); + break; + case RT1711H_DBG_REG_ADDR: + ret = rt1711h_reg_addr_show(chip, s); + break; + case RT1711H_DBG_DATA: + ret = rt1711h_data_show(chip, s); + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&chip->dbgops_lock); + return ret; +} + +static int rt1711h_dbg_open(struct inode *inode, struct file *file) +{ + if (file->f_mode & FMODE_READ) + return single_open(file, rt1711h_dbg_show, inode->i_private); + file->private_data = inode->i_private; + return 0; +} + +static int get_parameters(char *buf, long int *param1, int num_of_par) +{ + char *token; + int base, cnt; + + token = strsep(&buf, " "); + + for (cnt = 0; cnt < num_of_par; cnt++) { + if (token != NULL) { + if ((token[1] == 'x') || (token[1] == 'X')) + base = 16; + else + base = 10; + + if (kstrtoul(token, base, ¶m1[cnt]) != 0) + return -EINVAL; + + token = strsep(&buf, " "); + } else + return -EINVAL; + } + return 0; +} + +static int get_datas(const char *buf, const int length, + unsigned char *data_buffer, unsigned char data_length) +{ + int i, ptr; + long int value; + char token[5]; + + token[0] = '0'; + token[1] = 'x'; + token[4] = 0; + if (buf[0] != '0' || buf[1] != 'x') + return -EINVAL; + + ptr = 2; + for (i = 0; (i < data_length) && (ptr + 2 <= length); i++) { + token[2] = buf[ptr++]; + token[3] = buf[ptr++]; + ptr++; + if (kstrtoul(token, 16, &value) != 0) + return -EINVAL; + data_buffer[i] = value; + } + return 0; +} + +static int rt1711h_regaddr2idx(uint8_t reg_addr) +{ + int i = 0; + struct reg_desc *desc = NULL; + + for (i = 0; i < ARRAY_SIZE(rt1711h_reg_desc); i++) { + desc = &rt1711h_reg_desc[i]; + if (desc->addr == reg_addr) + return i; + } + return -EINVAL; +} + +static ssize_t rt1711h_dbg_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + int ret = 0; + struct rt1711h_dbg_info *info = + (struct rt1711h_dbg_info *)file->private_data; + struct rt1711h_chip *chip = info->chip; + struct reg_desc *desc = NULL; + char lbuf[128]; + long int param[5]; + unsigned char reg_data[2] = {0}; + + if (count > sizeof(lbuf) - 1) + return -EFAULT; + + ret = copy_from_user(lbuf, ubuf, count); + if (ret) + return -EFAULT; + lbuf[count] = '\0'; + + mutex_lock(&chip->dbgops_lock); + switch (info->id) { + case RT1711H_DBG_REG_ADDR: + ret = get_parameters(lbuf, param, 1); + if (ret < 0) { + dev_err(chip->dev, "%s get param fail\n", __func__); + ret = -EINVAL; + goto out; + } + ret = rt1711h_regaddr2idx(param[0]); + if (ret < 0) { + dev_err(chip->dev, "%s addr2idx fail\n", __func__); + ret = -EINVAL; + goto out; + } + chip->dbg_regidx = ret; + break; + case RT1711H_DBG_DATA: + desc = &rt1711h_reg_desc[chip->dbg_regidx]; + if ((desc->size - 1) * 3 + 5 != count) { + dev_err(chip->dev, "%s incorrect input length\n", + __func__); + ret = -EINVAL; + goto out; + } + ret = get_datas((char *)ubuf, count, reg_data, desc->size); + if (ret < 0) { + dev_err(chip->dev, "%s get data fail\n", __func__); + ret = -EINVAL; + goto out; + } + ret = rt1711h_reg_block_write(chip, desc->addr, desc->size, + reg_data); + break; + default: + ret = -EINVAL; + break; + } + +out: + mutex_unlock(&chip->dbgops_lock); + return ret < 0 ? ret : count; +} + +static int rt1711h_dbg_release(struct inode *inode, struct file *file) +{ + if (file->f_mode & FMODE_READ) + return single_release(inode, file); + return 0; +} + +static const struct file_operations rt1711h_dbg_ops = { + .open = rt1711h_dbg_open, + .llseek = seq_lseek, + .read = seq_read, + .write = rt1711h_dbg_write, + .release = rt1711h_dbg_release, +}; + + +static int rt1711h_debugfs_init(struct rt1711h_chip *chip) +{ + int ret = 0, i = 0; + struct rt1711h_dbg_info *info = NULL; + int len = 0; + char *dirname = NULL; + + mutex_init(&chip->logbuffer_lock); + mutex_init(&chip->dbgops_lock); + len = strlen(dev_name(chip->dev)); + dirname = devm_kzalloc(chip->dev, len + 9, GFP_KERNEL); + if (!dirname) + return -ENOMEM; + snprintf(dirname, len + 9, "rt1711h-%s", dev_name(chip->dev)); + if (!chip->dbgdir) { + chip->dbgdir = debugfs_create_dir(dirname, NULL); + if (!chip->dbgdir) + return -ENOMEM; + } + + for (i = 0; i < RT1711H_DBG_MAX; i++) { + info = &chip->dbg_info[i]; + info->chip = chip; + info->id = i; + chip->dbg_files[i] = debugfs_create_file( + rt1711h_dbg_filename[i], S_IFREG | 0444, + chip->dbgdir, info, &rt1711h_dbg_ops); + if (!chip->dbg_files[i]) { + ret = -EINVAL; + goto err; + } + } + + return 0; +err: + debugfs_remove_recursive(chip->dbgdir); + return ret; +} + +static void rt1711h_debugfs_exit(struct rt1711h_chip *chip) +{ + debugfs_remove_recursive(chip->dbgdir); +} + +#else + +static void rt1711h_log(const struct rt1711h_chip *chip, const char *fmt, ...) +{ +} + +static int rt1711h_debugfs_init(const struct rt1711h_chip *chip) +{ + return 0; +} + +static void rt1711h_debugfs_exit(const struct rt1711h_chip *chip) +{ +} + +#endif /* CONFIG_DEBUG_FS */ + +static const char * const typec_cc_status_name[] = { + [TYPEC_CC_OPEN] = "Open", + [TYPEC_CC_RA] = "Ra", + [TYPEC_CC_RD] = "Rd", + [TYPEC_CC_RP_DEF] = "Rp-def", + [TYPEC_CC_RP_1_5] = "Rp-1.5", + [TYPEC_CC_RP_3_0] = "Rp-3.0", +}; + +static const char * const cc_polarity_name[] = { + [TYPEC_POLARITY_CC1] = "Polarity_CC1", + [TYPEC_POLARITY_CC2] = "Polarity_CC2", +}; + +static const char * const transmit_type_name[] = { + [TCPC_TX_SOP] = "SOP", + [TCPC_TX_SOP_PRIME] = "SOP'", + [TCPC_TX_SOP_PRIME_PRIME] = "SOP''", + [TCPC_TX_SOP_DEBUG_PRIME] = "DEBUG'", + [TCPC_TX_SOP_DEBUG_PRIME_PRIME] = "DEBUG''", + [TCPC_TX_HARD_RESET] = "HARD_RESET", + [TCPC_TX_CABLE_RESET] = "CABLE_RESET", + [TCPC_TX_BIST_MODE_2] = "BIST_MODE_2", +}; + +static const char * const typec_role_name[] = { + [TYPEC_SINK] = "Sink", + [TYPEC_SOURCE] = "Source", +}; + +static const char * const typec_data_role_name[] = { + [TYPEC_DEVICE] = "Device", + [TYPEC_HOST] = "Host", +}; + +static const enum typec_cc_pull typec_cc_status_pull_mapping[] = { + [TYPEC_CC_OPEN] = TYPEC_CC_PULL_OPEN, + [TYPEC_CC_RA] = TYPEC_CC_PULL_RA, + [TYPEC_CC_RD] = TYPEC_CC_PULL_RD, + [TYPEC_CC_RP_DEF] = TYPEC_CC_PULL_RP_DEF, + [TYPEC_CC_RP_1_5] = TYPEC_CC_PULL_RP_1_5, + [TYPEC_CC_RP_3_0] = TYPEC_CC_PULL_RP_3_0, +}; + +static inline enum typec_cc_pull rt1711h_cc_status2pull(enum typec_cc_status cc) +{ + return typec_cc_status_pull_mapping[cc]; +} + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) + +static const u32 src_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), +}; + +static const u32 snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), +}; + +static const struct tcpc_config rt1711h_tcpc_config = { + .src_pdo = src_pdo, + .nr_src_pdo = ARRAY_SIZE(src_pdo), + .snk_pdo = snk_pdo, + .nr_snk_pdo = ARRAY_SIZE(snk_pdo), + .max_snk_mv = 5000, + .max_snk_ma = 3000, + .max_snk_mw = 15000, + .operating_snk_mw = 2500, + .type = TYPEC_PORT_DRP, + .default_role = TYPEC_SINK, + .alt_modes = NULL, +}; + +#define RT1711H_RESUME_RETRY 10 +#define RT1711H_RESUME_RETRY_SLEEP 50 + +static inline bool rt1711h_is_suspended(struct rt1711h_chip *chip) +{ + int retry_cnt = 0; + + for (retry_cnt = 0; retry_cnt < RT1711H_RESUME_RETRY; retry_cnt++) { + if (atomic_read(&chip->pm_suspend)) { + rt1711h_log(chip, "%s retry %d/%d\n", __func__, + retry_cnt + 1, RT1711H_RESUME_RETRY); + msleep(RT1711H_RESUME_RETRY_SLEEP); + } else + return false; + } + + return true; +} + +static int rt1711h_reg_read(struct rt1711h_chip *chip, uint8_t reg, + uint8_t *data) +{ + int ret = 0; + + atomic_set(&chip->i2c_busy, 1); + if (rt1711h_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; + } + + ret = i2c_smbus_read_i2c_block_data(chip->i2c, reg, 1, data); + if (ret < 0) + rt1711h_log(chip, "%s reg%02X fail(%d)\n", __func__, reg, ret); + atomic_set(&chip->i2c_busy, 0); + + return ret; +} + +static int rt1711h_reg_write(struct rt1711h_chip *chip, uint8_t reg, + uint8_t data) +{ + int ret = 0; + + atomic_set(&chip->i2c_busy, 1); + if (rt1711h_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; + } + + ret = i2c_smbus_write_i2c_block_data(chip->i2c, reg, 1, &data); + if (ret < 0) + rt1711h_log(chip, "%s reg%02X = %02X fail(%d)\n", __func__, reg, + data, ret); + atomic_set(&chip->i2c_busy, 0); + + return ret; +} + +static int rt1711h_reg_block_write(struct rt1711h_chip *chip, uint8_t reg, + int len, const uint8_t *data) +{ + int ret = 0; + + atomic_set(&chip->i2c_busy, 1); + if (rt1711h_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; + } + + ret = i2c_smbus_write_i2c_block_data(chip->i2c, reg, len, data); + if (ret < 0) + rt1711h_log(chip, "%s reg%02X, len = %d fail(%d)\n", __func__, + reg, len, ret); + atomic_set(&chip->i2c_busy, 0); + + return ret; +} + +static int rt1711h_reg_block_read(struct rt1711h_chip *chip, uint8_t reg, + int len, uint8_t *data) +{ + int ret = 0; + + atomic_set(&chip->i2c_busy, 1); + if (rt1711h_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; + } + + ret = i2c_smbus_read_i2c_block_data(chip->i2c, reg, len, data); + if (ret < 0) + rt1711h_log(chip, "%s reg%02X, len = %d fail(%d)\n", __func__, + reg, len, ret); + atomic_set(&chip->i2c_busy, 0); + + return ret; +} + +static inline int rt1711h_reg_write_word(struct rt1711h_chip *chip, uint8_t reg, + uint16_t data) +{ + data = cpu_to_le16(data); + return rt1711h_reg_block_write(chip, reg, 2, (uint8_t *)&data); +} + +static inline int rt1711h_reg_read_word(struct rt1711h_chip *chip, uint8_t reg, + uint16_t *data) +{ + int ret = 0; + + ret = rt1711h_reg_block_read(chip, reg, 2, (uint8_t *)data); + if (ret < 0) + return ret; + *data = le16_to_cpu(*data); + return 0; +} + +static int rt1711h_psy_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct rt1711h_chip *chip = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = chip->charge_on; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = chip->supply_voltage * 1000; /* mV -> µV */ + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = chip->current_limit * 1000; /* mA -> µA */ + break; + default: + return -ENODATA; + } + + return 0; +} + +static enum power_supply_property rt1711h_psy_properties[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, +}; + +static const struct power_supply_desc rt1711h_psy_desc = { + .name = "rt1711h-typec-source", + .type = POWER_SUPPLY_TYPE_USB_TYPE_C, + .properties = rt1711h_psy_properties, + .num_properties = ARRAY_SIZE(rt1711h_psy_properties), + .get_property = rt1711h_psy_get_property, +}; + +static inline int rt1711h_software_reset(struct rt1711h_chip *chip) +{ + int ret = 0; + + ret = rt1711h_reg_write(chip, RT1711H_REG_SWRESET, 0x01); + if (ret < 0) + return ret; + + usleep_range(1000, 2000); + return 0; +} + +static inline int rt1711h_command(struct rt1711h_chip *chip, uint8_t cmd) +{ + return rt1711h_reg_write(chip, RT1711H_REG_COMMAND, cmd); +} + +static inline int rt1711h_init_cc_params(struct rt1711h_chip *chip, + const enum typec_cc_status *cc) +{ + int ret = 0; + uint8_t en = 0, sel = 0; + + if (*cc == TYPEC_CC_RP_DEF) { /* 0.55 */ + en = 0; + sel = 0x81; + } else if (chip->did >= RT1711H_DID_D) { /* 0.35 & 0.75 */ + en = 1; + sel = 0x81; + } else { /* 0.4 & 0.7 */ + en = 1; + sel = 0x80; + } + + ret = rt1711h_reg_write(chip, RT1711H_REG_BMCIO_RXDZEN, en); + if (ret < 0) + return ret; + + return rt1711h_reg_write(chip, RT1711H_REG_BMCIO_RXDZSEL, sel); +} + +static int rt1711h_alert_status_clear(struct rt1711h_chip *chip, uint32_t mask) +{ + int ret = 0; + uint16_t mask_t1 = 0; + uint8_t mask_t2 = 0; + + /* Write 1 clear */ + mask_t1 = (uint16_t)mask; + ret = rt1711h_reg_write_word(chip, RT1711H_REG_ALERT, mask_t1); + if (ret < 0) + return ret; + + mask_t2 = mask >> 16; + if (mask_t2) { + ret = rt1711h_reg_write(chip, RT1711H_REG_RT_INT, mask_t2); + if (ret < 0) + return ret; + } + + return 0; +} + +static int rt1711h_init_alert_mask(struct rt1711h_chip *chip) +{ + uint16_t mask = 0; + + mask = RT1711H_REG_ALERT_CC_STATUS | RT1711H_REG_ALERT_POWER_STATUS; + + mask |= RT1711H_REG_ALERT_TX_SUCCESS | RT1711H_REG_ALERT_TX_DISCARDED + | RT1711H_REG_ALERT_TX_FAILED | RT1711H_REG_ALERT_RX_HARD_RST + | RT1711H_REG_ALERT_RX_STATUS | RT1711H_REG_ALERT_RX_BUF_OVF; + + mask |= RT1711H_REG_ALERT_FAULT; + + return rt1711h_reg_write_word(chip, RT1711H_REG_ALERT_MASK, mask); +} + +static int rt1711h_init_power_status_mask(struct rt1711h_chip *chip) +{ + uint8_t mask = RT1711H_REG_POWER_STATUS_VBUS_PRES; + + return rt1711h_reg_write(chip, RT1711H_REG_POWER_STATUS_MASK, mask); +} + +static int rt1711h_init_fault_mask(struct rt1711h_chip *chip) +{ + const uint8_t mask = RT1711H_REG_FAULT_STATUS_VCONN_OV + | RT1711H_REG_FAULT_STATUS_VCONN_OC; + + return rt1711h_reg_write(chip, RT1711H_REG_FAULT_STATUS_MASK, mask); +} + +static int rt1711h_init_rt_mask(struct rt1711h_chip *chip) +{ + uint8_t rt_mask = RT1711H_REG_M_VBUS_80; + + if (chip->did < RT1711H_DID_D) + rt_mask |= (RT1711H_REG_M_WAKEUP | RT1711H_REG_M_RA_DETACH); + + return rt1711h_reg_write(chip, RT1711H_REG_RT_MASK, rt_mask); +} + +#define RT1711H_WAKEUP_WORK_TIME (1000) +static enum alarmtimer_restart + rt1711h_alarm_wakeup_handler(struct alarm *alarm, ktime_t now) +{ + struct rt1711h_chip *chip = + container_of(alarm, struct rt1711h_chip, wakeup_timer); + + rt1711h_log(chip, "%s\n", __func__); + pm_wakeup_event(chip->dev, RT1711H_WAKEUP_WORK_TIME); + schedule_delayed_work(&chip->wakeup_work, 0); + return ALARMTIMER_NORESTART; +} + +static void rt1711h_enable_wakeup_timer(struct rt1711h_chip *chip, bool en) +{ + int tout = 300; /* s */ + + rt1711h_log(chip, "%s %d\n", __func__, en); + if (en) { + if (!chip->wakeup_once) + tout = (chip->low_rp_duty_cntdown) ? 5 : 20; + alarm_start_relative(&chip->wakeup_timer, ktime_set(tout, 0)); + } else + alarm_cancel(&chip->wakeup_timer); +} + +static inline bool rt1711h_is_cc_open(struct rt1711h_chip *chip) +{ + if (!chip->drp_toggling && chip->cc1 == TYPEC_CC_OPEN && + chip->cc2 == TYPEC_CC_OPEN) + return true; + return false; +} + +static int rt1711h_set_low_rp_duty(struct rt1711h_chip *chip, bool low_rp) +{ + uint16_t duty = low_rp ? RT1711H_LOW_RP_DUTY : RT1711H_NORMAL_RP_DUTY; + + return rt1711h_reg_write_word(chip, RT1711H_REG_DRP_DUTY_CTRL, duty); +} + +/* + * rt1711h_check_false_ra_detach + * + * Check single Ra resistance (eMark) exists or not when + * 1) ra detach int triggered + * 2) wakeup timer triggered + * + * If reentering low-power mode and eMark still exists, + * it may cause an infinite loop. + * + * If cc status is both open, return true; otherwise return false + */ +static int __tcpm_get_cc(struct rt1711h_chip *chip); +static int __tcpm_set_cc(struct rt1711h_chip *chip, enum typec_cc_status cc); +static inline int __tcpm_start_drp_toggling(struct rt1711h_chip *chip); +static inline bool rt1711h_check_false_ra_detach(struct rt1711h_chip *chip) +{ + bool drp = (chip->tcpc_cfg.type == TYPEC_PORT_DRP) ? true : false; + + rt1711h_log(chip, "%s\n", __func__); + + /* + * If the DUT is DRP and current CC status has stopped toggling, + * let cc_handler to handle it later. + * + * If CC is toggling, force CC to present Rp + */ + if (drp) { + __tcpm_get_cc(chip); + + if (!chip->drp_toggling) { + rt1711h_log(chip, "%s 1(%s, %s)\n", __func__, + typec_cc_status_name[chip->cc1], + typec_cc_status_name[chip->cc2]); + return true; + } + __tcpm_set_cc(chip, TYPEC_CC_RP_DEF); + usleep_range(1000, 2000); + } + + /* + * Check CC status + * Rd (device) -> let cc_handler to handle it later + * eMark only -> Reschedule wakeup timer + * Open -> (true condition) + * Read to reenter low-power mode. + * If we repeatedly enter this situation, + * it will trigger low rp duty protection + */ + __tcpm_get_cc(chip); + if (rt1711h_is_cc_open(chip)) + chip->cable_only = false; + else if ((chip->cc1 + chip->cc2) == TYPEC_CC_RA) { + chip->cable_only = true; + rt1711h_log(chip, "%s 2(emark)\n", __func__); + } else { + chip->cable_only = false; + rt1711h_log(chip, "%s 3(%s %s)\n", __func__, + typec_cc_status_name[chip->cc1], + typec_cc_status_name[chip->cc2]); + return true; + } + + if (chip->cable_only) + rt1711h_enable_wakeup_timer(chip, true); + else { + if (chip->low_rp_duty_cntdown) + rt1711h_set_low_rp_duty(chip, true); + else { + chip->wakeup_once = false; + chip->low_rp_duty_cntdown = true; + } + } + + /* If DUP is DRP, force CC to toggle again */ + if (drp) { + __tcpm_start_drp_toggling(chip); + rt1711h_alert_status_clear(chip, + RT1711H_REG_ALERT_EXT_RA_DETACH); + } + + return chip->cable_only; +} + +static int rt1711h_set_low_power_mode(struct rt1711h_chip *chip, bool en, + enum typec_cc_pull pull) +{ + uint8_t data = 0; + + rt1711h_log(chip, "%s %d\n", __func__, en); + + if (en) { + data = RT1711H_REG_BMCIO_LPEN; + + if (pull & TYPEC_CC_PULL_RP) + data |= RT1711H_REG_BMCIO_LPRPRD; + } else + data = RT1711H_REG_BMCIO_BG_EN | + RT1711H_REG_VBUS_DET_EN | RT1711H_REG_BMCIO_OSC_EN; + + return rt1711h_reg_write(chip, RT1711H_REG_BMC_CTRL, data); +} + +static int rt1711h_enter_lpm_again(struct rt1711h_chip *chip) +{ + bool check_ra = (chip->lpm) || (chip->cable_only); + + if (check_ra && rt1711h_check_false_ra_detach(chip)) + return 0; + + rt1711h_log(chip, "%s retry lpm\n", __func__); + chip->lpm = true; + + rt1711h_set_low_power_mode(chip, true, + (chip->pwr_role != TYPEC_SOURCE) ? + TYPEC_CC_PULL_DRP : TYPEC_CC_PULL_RP); + + return 0; +} + +static void rt1711h_wakeup_work(struct work_struct *work) +{ + struct rt1711h_chip *chip = + container_of(work, struct rt1711h_chip, wakeup_work.work); + + mutex_lock(&chip->wakeup_lock); + mutex_lock(&chip->lock); + rt1711h_log(chip, "%s\n", __func__); + chip->wakeup_once = true; + rt1711h_enter_lpm_again(chip); + mutex_unlock(&chip->lock); + mutex_unlock(&chip->wakeup_lock); + pm_relax(chip->dev); +} + +static inline int rt1711h_try_low_power_mode(struct rt1711h_chip *chip) +{ + return rt1711h_set_low_power_mode(chip, true, chip->lpm_pull); +} + +static inline int rt1711h_enter_low_power_mode(struct rt1711h_chip *chip) +{ + return rt1711h_try_low_power_mode(chip); +} + +static inline int rt1711h_enable_low_power_mode(struct rt1711h_chip *chip, + enum typec_cc_pull pull) +{ + if (chip->cable_only) { + rt1711h_log(chip, "%s ra only\n", __func__); + rt1711h_enable_wakeup_timer(chip, true); + return 0; + } + + if (chip->lpm != true) { + chip->lpm = true; + chip->lpm_pull = pull; + return rt1711h_enter_low_power_mode(chip); + } + + return 0; +} + +static inline int rt1711h_disable_low_power_mode(struct rt1711h_chip *chip) +{ + int ret = 0; + + if (chip->lpm != false) { + chip->lpm = false; + rt1711h_set_low_rp_duty(chip, false); + ret = rt1711h_set_low_power_mode(chip, false, + TYPEC_CC_PULL_DRP); + } + + chip->wakeup_once = false; + chip->low_rp_duty_cntdown = false; + return ret; +} + +static int tcpm_init(struct tcpc_dev *dev) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, + struct rt1711h_chip, tcpc_dev); + + rt1711h_log(chip, "%s\n", __func__); + + /* CK 300K from 320K, shipping off, auto_idle enable, tout = 32ms */ + ret = rt1711h_reg_write(chip, RT1711H_REG_IDLE_CTRL, + RT1711H_REG_IDLE_SET(0, 1, 1, 2)); + if (ret < 0) { + rt1711h_log(chip, "%s set idle ctrl fail(%d)\n", __func__, ret); + return ret; + } + + ret = rt1711h_reg_write(chip, RT1711H_REG_I2CRST_CTRL, + RT1711H_REG_I2CRST_SET(true, 0x0F)); + if (ret < 0) { + rt1711h_log(chip, "%s set i2crst fail(%d)\n", __func__, ret); + return ret; + } + + /* UFP Both RD setting */ + /* DRP = 0, RpVal = 0 (Default), Rd, Rd */ + ret = rt1711h_reg_write(chip, RT1711H_REG_ROLE_CTRL, + RT1711H_REG_ROLE_CTRL_RES_SET(0, 0, TYPEC_CC_PULL_RD, + TYPEC_CC_PULL_RD)); + if (ret < 0) { + rt1711h_log(chip, "%s set role ctrl fail(%d)\n", __func__, ret); + return ret; + } + + /* + * CC Detect Debounce : (26.7 * val) us + * Transition window count : spec 12~20us, based on 2.4MHz + */ + ret = rt1711h_reg_write(chip, RT1711H_REG_TTCPC_FILTER, 0x0F); + if (ret < 0) { + rt1711h_log(chip, "%s set cc deb fail(%d)\n", __func__, ret); + return ret; + } + + /* DRP Toggle Cycle : (51.2 + 6.4 * val) ms */ + rt1711h_reg_write(chip, RT1711H_REG_DRP_TOGGLE_CYCLE, 4); + if (ret < 0) { + rt1711h_log(chip, "%s set tog cyc fail(%d)\n", __func__, ret); + return ret; + } + + /* DRP Duty Ctrl: 33% */ + ret = rt1711h_reg_write_word(chip, RT1711H_REG_DRP_DUTY_CTRL, + RT1711H_NORMAL_RP_DUTY); + if (ret < 0) { + rt1711h_log(chip, "%s set drp duty fail(%d)\n", __func__, ret); + return ret; + } + + /* Vconn OC */ + ret = rt1711h_reg_write(chip, RT1711H_REG_VCONN_CLIMITEN, 1); + if (ret < 0) { + rt1711h_log(chip, "%s en vconn oc fail(%d)\n", __func__, ret); + return ret; + } + + /* Alert & Mask */ + ret = rt1711h_alert_status_clear(chip, 0xffffffff); + if (ret < 0) { + rt1711h_log(chip, "%s clear alert fail(%d)\n", __func__, ret); + return ret; + } + ret = rt1711h_init_power_status_mask(chip); + if (ret < 0) { + rt1711h_log(chip, "%s init pwr mask fail(%d)\n", __func__, ret); + return ret; + } + ret = rt1711h_init_alert_mask(chip); + if (ret < 0) { + rt1711h_log(chip, "%s init alert mask fail(%d)\n", __func__, + ret); + return ret; + } + ret = rt1711h_init_fault_mask(chip); + if (ret < 0) { + rt1711h_log(chip, "%s init fault mask fail(%d)\n", __func__, + ret); + return ret; + } + ret = rt1711h_init_rt_mask(chip); + if (ret < 0) { + rt1711h_log(chip, "%s init rt mask fail(%d)\n", __func__, ret); + return ret; + } + + return 0; +} + +static int tcpm_get_vbus(struct tcpc_dev *dev) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + rt1711h_log(chip, "%s\n", __func__); + mutex_lock(&chip->lock); + ret = chip->vbus_present ? 1 : 0; + mutex_unlock(&chip->lock); + + return ret; +} + +static int tcpm_get_current_limit(struct tcpc_dev *dev) +{ + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + int current_limit = 0; + unsigned long timeout; + + rt1711h_log(chip, "%s\n", __func__); + if (!chip->extcon) + return 0; + + /* + * USB2 Charger detection may still be in progress when we get here, + * this can take upto 600ms, wait 800ms max. + */ + timeout = jiffies + msecs_to_jiffies(800); + do { + if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_SDP) == 1) + current_limit = 500; + + if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_CDP) == 1 || + extcon_get_state(chip->extcon, EXTCON_CHG_USB_ACA) == 1) + current_limit = 1500; + + if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_DCP) == 1) + current_limit = 2000; + + msleep(50); + } while (current_limit == 0 && time_before(jiffies, timeout)); + + return current_limit; +} + +static int __tcpm_set_cc(struct rt1711h_chip *chip, enum typec_cc_status cc) +{ + uint8_t data = 0, pull = 0, rp_lvl = 0; + + rt1711h_log(chip, "%s %s\n", __func__, typec_cc_status_name[cc]); + switch (cc) { + case TYPEC_CC_OPEN: + case TYPEC_CC_RD: + case TYPEC_CC_RP_DEF: + case TYPEC_CC_RP_1_5: + case TYPEC_CC_RP_3_0: + pull = rt1711h_cc_status2pull(cc); + rp_lvl = RT1711H_TYPEC_CC_PULL_GET_RP_LVL(pull); + pull = RT1711H_TYPEC_CC_PULL_GET_RES(pull); + data = RT1711H_REG_ROLE_CTRL_RES_SET(0, rp_lvl, pull, pull); + break; + default: + rt1711h_log(chip, "%s unsupported cc value %s\n", __func__, + typec_cc_status_name[cc]); + return -EINVAL; + } + + return rt1711h_reg_write(chip, RT1711H_REG_ROLE_CTRL, data); +} + +static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + ret = __tcpm_set_cc(chip, cc); + mutex_unlock(&chip->lock); + + return ret; +} + +static inline enum typec_cc_status rt1711h_cc2enum(enum typec_cc_status cc, + bool act_as_sink) +{ + return act_as_sink ? cc + 2 : cc; +} + +static int __tcpm_get_cc(struct rt1711h_chip *chip) +{ + int ret = 0; + uint8_t status = 0, role_ctrl = 0, cc_role = 0; + bool act_as_sink, act_as_drp; + + ret = rt1711h_reg_read(chip, RT1711H_REG_CC_STATUS, &status); + if (ret < 0) + return ret; + + ret = rt1711h_reg_read(chip, RT1711H_REG_ROLE_CTRL, &role_ctrl); + if (ret < 0) + return ret; + + if (status & RT1711H_REG_CC_STATUS_DRP_TOGGLING) { + /* during toggling, consider cc as Open */ + chip->cc1 = TYPEC_CC_OPEN; + chip->cc2 = TYPEC_CC_OPEN; + rt1711h_log(chip, "%s drp toggling\n", __func__); + return 0; + } + chip->drp_toggling = false; + + act_as_drp = RT1711H_REG_ROLE_CTRL_DRP & role_ctrl; + + if (act_as_drp) + act_as_sink = RT1711H_REG_CC_STATUS_DRP_RESULT(status); + else { + cc_role = RT1711H_REG_ROLE_CTRL_CC1(role_ctrl); + act_as_sink = (cc_role == TYPEC_CC_PULL_RP) ? false : true; + } + + chip->cc1 = RT1711H_REG_CC_STATUS_CC1(status); + chip->cc2 = RT1711H_REG_CC_STATUS_CC2(status); + if (chip->cc1 != TYPEC_CC_OPEN) + chip->cc1 = rt1711h_cc2enum(chip->cc1, act_as_sink); + if (chip->cc2 != TYPEC_CC_OPEN) + chip->cc2 = rt1711h_cc2enum(chip->cc2, act_as_sink); + + ret = rt1711h_init_cc_params(chip, chip->polarity ? + &chip->cc2 : &chip->cc1); + if (ret < 0) + rt1711h_log(chip, "%s init cc param fail(%d)\n", __func__, ret); + + rt1711h_log(chip, "%s cc1 = %s, cc2 = %s\n", __func__, + typec_cc_status_name[chip->cc1], + typec_cc_status_name[chip->cc2]); + + return 0; +} + +static int tcpm_get_cc(struct tcpc_dev *dev, + enum typec_cc_status *cc1, enum typec_cc_status *cc2) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + ret = __tcpm_get_cc(chip); + if (ret < 0) + goto out; + *cc1 = chip->cc1; + *cc2 = chip->cc2; +out: + mutex_unlock(&chip->lock); + return ret; +} + +static int tcpm_set_polarity(struct tcpc_dev *dev, + enum typec_cc_polarity polarity) +{ + int ret = 0; + uint8_t data = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + rt1711h_log(chip, "%s %s\n", __func__, cc_polarity_name[polarity]); + ret = rt1711h_init_cc_params(chip, polarity ? &chip->cc2 : &chip->cc1); + if (ret < 0) + goto out; + + ret = rt1711h_reg_read(chip, RT1711H_REG_TCPC_CTRL, &data); + if (ret < 0) + goto out; + + data &= ~RT1711H_REG_TCPC_CTRL_PLUG_ORIENT; + data |= polarity ? RT1711H_REG_TCPC_CTRL_PLUG_ORIENT : 0; + + ret = rt1711h_reg_write(chip, RT1711H_REG_TCPC_CTRL, data); +out: + mutex_unlock(&chip->lock); + return ret; +} + +static int tcpm_set_vconn(struct tcpc_dev *dev, bool on) +{ + int ret = 0; + uint8_t data = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + if (chip->vconn_on == on) { + rt1711h_log(chip, "%s vconn is already %d\n", __func__, on); + goto out; + } + ret = rt1711h_reg_read(chip, RT1711H_REG_POWER_CTRL, &data); + if (ret < 0) + goto out; + + data &= ~RT1711H_REG_POWER_CTRL_VCONN; + data |= on ? RT1711H_REG_POWER_CTRL_VCONN : 0; + + ret = rt1711h_reg_write(chip, RT1711H_REG_POWER_CTRL, data); + if (ret < 0) + goto out; + + ret = rt1711h_reg_write(chip, RT1711H_REG_IDLE_CTRL, + RT1711H_REG_IDLE_SET(0, 1, on ? 0 : 1, 2)); + if (ret < 0) + goto out; + + chip->vconn_on = on; + rt1711h_log(chip, "%s vconn = %d\n", __func__, on); + +out: + mutex_unlock(&chip->lock); + return ret; +} + +static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + if (chip->vbus_on == on) + rt1711h_log(chip, "%s vbus is already %d\n", __func__, on); + else { + ret = (on ? regulator_enable : regulator_disable)(chip->vbus); + if (ret < 0) { + rt1711h_log(chip, "%s cannot %s vbus regulator(%d)\n", + __func__, on ? "enable" : "disable", ret); + goto out; + } + chip->vbus_on = on; + rt1711h_log(chip, "%s vbus = %d\n", __func__, on); + } + if (chip->charge_on == charge) + rt1711h_log(chip, "%s chg is already %d\n", __func__, charge); + else { + chip->charge_on = charge; + power_supply_changed(chip->psy); + } + +out: + mutex_unlock(&chip->lock); + return 0; +} + +static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, + u32 mv) +{ + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + rt1711h_log(chip, "%s %d ma, %d mv (not implemented)\n", __func__, + max_ma, mv); + + mutex_lock(&chip->lock); + chip->supply_voltage = mv; + chip->current_limit = max_ma; + mutex_unlock(&chip->lock); + + power_supply_changed(chip->psy); + return 0; +} + +static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) +{ + int ret = 0; + uint8_t rx_en = 0x00; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + rt1711h_log(chip, "%s %d\n", __func__, on); + if (on) + rx_en = BIT(TCPC_TX_SOP) | BIT(TCPC_TX_HARD_RESET); + + ret = rt1711h_reg_write(chip, RT1711H_REG_RX_DETECT, rx_en); + mutex_unlock(&chip->lock); + return ret; +} + +static int tcpm_set_roles(struct tcpc_dev *dev, bool attached, + enum typec_role pwr, enum typec_data_role data) +{ + int ret = 0; + uint8_t msg_hdr = RT1711H_REG_MSG_HDR_INFO_SET(data, pwr); + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + rt1711h_log(chip, "%s %s %s\n", __func__, typec_role_name[pwr], + typec_data_role_name[data]); + ret = rt1711h_reg_write(chip, RT1711H_REG_MSG_HDR_INFO, msg_hdr); + if (ret < 0) + goto out; + chip->pwr_role = pwr; +out: + mutex_unlock(&chip->lock); + return ret; +} + +static inline int __tcpm_start_drp_toggling(struct rt1711h_chip *chip) +{ + int ret = 0; + uint8_t data = 0; + uint8_t rp_def = RT1711H_TYPEC_CC_PULL_GET_RP_LVL(TYPEC_CC_PULL_RP_DEF); + uint8_t cc_role = TYPEC_CC_PULL_RD; + + data = RT1711H_REG_ROLE_CTRL_RES_SET(0, rp_def, cc_role, cc_role); + ret = rt1711h_reg_write(chip, RT1711H_REG_ROLE_CTRL, data); + if (ret < 0) + return ret; + mdelay(1); + data = RT1711H_REG_ROLE_CTRL_RES_SET(1, rp_def, cc_role, cc_role); + ret = rt1711h_reg_write(chip, RT1711H_REG_ROLE_CTRL, data); + if (ret < 0) + return ret; + ret = rt1711h_command(chip, RT1711H_CMD_LOOK_CONNECTION); + if (ret < 0) + return ret; + chip->drp_toggling = true; + + return 0; +} + +static int tcpm_start_drp_toggling(struct tcpc_dev *dev, + enum typec_cc_status cc) +{ + int ret = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + + mutex_lock(&chip->lock); + rt1711h_log(chip, "%s\n", __func__); + ret = __tcpm_start_drp_toggling(chip); + if (ret < 0) + goto out; + if (chip->did < RT1711H_DID_D) + ret = rt1711h_enable_low_power_mode(chip, TYPEC_CC_PULL_DRP); + +out: + mutex_unlock(&chip->lock); + return ret; +} + +#pragma pack(push, 1) +struct tcpc_transmit_packet { + uint8_t cnt; + uint16_t msg_header; + uint8_t data[sizeof(uint32_t) * PD_MAX_PAYLOAD]; +}; +#pragma pack(pop) + +static int tcpm_pd_transmit(struct tcpc_dev *dev, + enum tcpm_transmit_type type, const struct pd_message *msg) +{ + int ret = 0; + int data_cnt = 0; + struct rt1711h_chip *chip = container_of(dev, struct rt1711h_chip, + tcpc_dev); + struct tcpc_transmit_packet packet; + + rt1711h_log(chip, "%s %s\n", __func__, transmit_type_name[type]); + mutex_lock(&chip->lock); + switch (type) { + case TCPC_TX_SOP: + data_cnt = sizeof(uint32_t) * pd_header_cnt_le(msg->header); + packet.cnt = data_cnt + sizeof(uint16_t); + packet.msg_header = msg->header; + if (data_cnt > 0) + memcpy(packet.data, (uint8_t *)msg->payload, data_cnt); + + ret = rt1711h_reg_block_write(chip, RT1711H_REG_TX_BYTE_CNT, + packet.cnt + 1, (uint8_t *)&packet); + if (ret < 0) { + rt1711h_log(chip, "%s fail (%d)\n", __func__, ret); + goto out; + } + break; + case TCPC_TX_HARD_RESET: + break; + default: + rt1711h_log(chip, "type %s not supported\n", + transmit_type_name[type]); + ret = -EINVAL; + goto out; + } + + ret = rt1711h_reg_write(chip, RT1711H_REG_TRANSMIT, + RT1711H_REG_TRANSMIT_SET(3, type)); +out: + mutex_unlock(&chip->lock); + return ret; +} + +static int rt1711h_parse_dt(struct rt1711h_chip *chip) +{ + int ret = 0, len = 0; + uint32_t val = 0; + struct device_node *np = chip->dev->of_node; + struct tcpc_config *cfg = &chip->tcpc_cfg; + const char *name = "default"; + + if (!np) + return -EINVAL; + + dev_info(chip->dev, "%s\n", __func__); + + memcpy(cfg, &rt1711h_tcpc_config, sizeof(struct tcpc_config)); + + ret = of_get_named_gpio(np, "rt,intr_gpio", 0); + if (ret < 0) { + dev_err(chip->dev, "%s get int gpio fail(%d)\n", + __func__, ret); + return ret; + } + chip->irq_gpio = ret; + dev_info(chip->dev, "%s irq_gpio = %d\n", __func__, chip->irq_gpio); + + of_property_read_string(np, "rt,name", &name); + + len = strlen(name); + chip->name = devm_kzalloc(chip->dev, len + 1, GFP_KERNEL); + if (!chip->name) + return -ENOMEM; + strlcpy(chip->name, name, strlen(name) + 1); + + if (of_property_read_u32(np, "rt,def_role", &val) == 0) + cfg->default_role = val; + + if (of_property_read_u32(np, "rt,port_type", &val) == 0) + cfg->type = val; + + if (of_property_read_u32(np, "rt,max_snk_mv", &val) == 0) + cfg->max_snk_mv = val; + + if (of_property_read_u32(np, "rt,max_snk_ma", &val) == 0) + cfg->max_snk_ma = val; + + if (of_property_read_u32(np, "rt,max_snk_mw", &val) == 0) + cfg->max_snk_mw = val; + + if (of_property_read_u32(np, "rt,operating_snk_mw", &val) == 0) + cfg->operating_snk_mw = val; + + cfg->try_role_hw = of_property_read_bool(np, "rt,try_role_hw"); + + return 0; +} + +static void rt1711h_init_tcpc_dev(struct rt1711h_chip *chip) +{ + chip->tcpc_dev.config = &chip->tcpc_cfg; + chip->tcpc_dev.init = tcpm_init; + chip->tcpc_dev.get_vbus = tcpm_get_vbus; + chip->tcpc_dev.get_current_limit = tcpm_get_current_limit; + chip->tcpc_dev.set_cc = tcpm_set_cc; + chip->tcpc_dev.get_cc = tcpm_get_cc; + chip->tcpc_dev.set_polarity = tcpm_set_polarity; + chip->tcpc_dev.set_vconn = tcpm_set_vconn; + chip->tcpc_dev.set_vbus = tcpm_set_vbus; + chip->tcpc_dev.set_current_limit = tcpm_set_current_limit; + chip->tcpc_dev.set_pd_rx = tcpm_set_pd_rx; + chip->tcpc_dev.set_roles = tcpm_set_roles; + chip->tcpc_dev.start_drp_toggling = tcpm_start_drp_toggling; + chip->tcpc_dev.pd_transmit = tcpm_pd_transmit; + chip->tcpc_dev.mux = NULL; +} + +static int rt1711h_get_alert_status(struct rt1711h_chip *chip, + uint32_t *alert) +{ + int ret = 0; + uint16_t data = 0; + uint8_t rt_int = 0; + + ret = rt1711h_reg_read_word(chip, RT1711H_REG_ALERT, &data); + if (ret < 0) + return ret; + *alert = data; + + ret = rt1711h_reg_read(chip, RT1711H_REG_RT_INT, &rt_int); + if (ret < 0) + return ret; + *alert |= rt_int << 16; + + return 0; +} + +static int rt1711h_get_fault_status(struct rt1711h_chip *chip, uint8_t *status) +{ + return rt1711h_reg_read(chip, RT1711H_REG_FAULT_STATUS, status); +} + +static inline int rt1711h_fault_status_vconn_ov(struct rt1711h_chip *chip) +{ + int ret = 0; + uint8_t data = 0; + + ret = rt1711h_reg_read(chip, RT1711H_REG_BMC_CTRL, &data); + if (ret < 0) + return ret; + + data &= ~RT1711H_REG_DISCHARGE_EN; + return rt1711h_reg_write(chip, RT1711H_REG_BMC_CTRL, data); +} + +static int rt1711h_fault_status_clear(struct rt1711h_chip *chip, uint8_t status) +{ + if (status & RT1711H_REG_FAULT_STATUS_VCONN_OV) + rt1711h_fault_status_vconn_ov(chip); + + return rt1711h_reg_write(chip, RT1711H_REG_FAULT_STATUS, status); +} + +/* Alert handlers */ + +static int rt1711h_alert_cc_changed(struct rt1711h_chip *chip) +{ + int ret = 0; + + ret = __tcpm_get_cc(chip); + if (ret < 0) + return ret; + + if (chip->drp_toggling) { + rt1711h_log(chip, "%s DRP toggling\n", __func__); + if (chip->did < RT1711H_DID_D && chip->lpm && !chip->cable_only) + rt1711h_enter_low_power_mode(chip); + return 0; + } + if (chip->did < RT1711H_DID_D) + rt1711h_disable_low_power_mode(chip); + + tcpm_cc_change(chip->tcpm_port); + return 0; +} + +static int rt1711h_alert_power_status_changed(struct rt1711h_chip *chip) +{ + int ret = 0; + bool vbus_pres = false; + uint8_t data = 0; + + ret = rt1711h_reg_read(chip, RT1711H_REG_POWER_STATUS, &data); + if (ret < 0) + goto out; + + vbus_pres = (data & RT1711H_REG_POWER_STATUS_VBUS_PRES) ? true : false; + if (vbus_pres != chip->vbus_present) { + chip->vbus_present = vbus_pres; + rt1711h_log(chip, "%s vbus = %d\n", __func__, vbus_pres); + tcpm_vbus_change(chip->tcpm_port); + } + +out: + return ret; +} + +static int rt1711h_alert_recv_msg(struct rt1711h_chip *chip) +{ + int ret = 0, len = 0; + uint8_t buf[2]; + struct pd_message msg; + const uint32_t alert_rx = + RT1711H_REG_ALERT_RX_STATUS | RT1711H_REG_ALERT_RX_BUF_OVF; + + rt1711h_log(chip, "%s\n", __func__); + ret = rt1711h_reg_block_read(chip, RT1711H_REG_RX_HDR, 2, buf); + if (ret < 0) + return ret; + + memcpy(&(msg.header), buf, 2); + + len = pd_header_cnt_le(msg.header) * 4; + if (len > PD_MAX_PAYLOAD * 4) { + rt1711h_log(chip, "%s PD message too long %d\n", __func__, len); + return -EINVAL; + } + if (len > 0) + ret = rt1711h_reg_block_read(chip, RT1711H_REG_RX_DATA, len, + (uint8_t *)msg.payload); + + /* Read complete, clear RX status alert bit */ + rt1711h_alert_status_clear(chip, alert_rx); + + tcpm_pd_receive(chip->tcpm_port, &msg); + return ret; +} + +static int rt1711h_alert_recv_hard_reset(struct rt1711h_chip *chip) +{ + tcpm_pd_hard_reset(chip->tcpm_port); + return 0; +} + +static int rt1711h_alert_tx_failed(struct rt1711h_chip *chip) +{ + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_FAILED); + return 0; +} + +static int rt1711h_alert_tx_discard(struct rt1711h_chip *chip) +{ + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_DISCARDED); + return 0; +} + +static int rt1711h_alert_tx_success(struct rt1711h_chip *chip) +{ + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); + return 0; +} + +static int rt1711h_alert_fault(struct rt1711h_chip *chip) +{ + int ret = 0; + uint8_t status = 0; + + ret = rt1711h_get_fault_status(chip, &status); + if (ret < 0) + return ret; + + rt1711h_log(chip, "%s 0x%02X\n", __func__, status); + rt1711h_fault_status_clear(chip, status); + return 0; +} + +static int rt1711h_alert_rx_overflow(struct rt1711h_chip *chip) +{ + int ret = 0; + uint32_t alert_status = 0; + + rt1711h_log(chip, "%s\n", __func__); + + ret = rt1711h_get_alert_status(chip, &alert_status); + if (ret < 0) + return ret; + + if (alert_status & RT1711H_REG_ALERT_RX_STATUS) + return rt1711h_alert_recv_msg(chip); + + return 0; +} + +static int rt1711h_alert_wakeup(struct rt1711h_chip *chip) +{ + rt1711h_log(chip, "%s\n", __func__); + if (chip->drp_toggling) + rt1711h_enable_wakeup_timer(chip, true); + return 0; +} + +static int rt1711h_alert_ra_detach(struct rt1711h_chip *chip) +{ + rt1711h_log(chip, "%s\n", __func__); + if (chip->drp_toggling) + rt1711h_enter_lpm_again(chip); + + return 0; +} + +struct rt1711h_alert_handler { + uint32_t bit_mask; + int (*handler)(struct rt1711h_chip *chip); +}; + +#define RT1711H_DECL_ALERT_HANDLER(xbit, xhandler) { \ + .bit_mask = 1 << xbit, \ + .handler = xhandler, \ +} + +static const struct rt1711h_alert_handler rt1711h_alert_handlers[] = { + RT1711H_DECL_ALERT_HANDLER(4, rt1711h_alert_tx_failed), + RT1711H_DECL_ALERT_HANDLER(5, rt1711h_alert_tx_discard), + RT1711H_DECL_ALERT_HANDLER(6, rt1711h_alert_tx_success), + RT1711H_DECL_ALERT_HANDLER(2, rt1711h_alert_recv_msg), + RT1711H_DECL_ALERT_HANDLER(7, NULL), + RT1711H_DECL_ALERT_HANDLER(8, NULL), + RT1711H_DECL_ALERT_HANDLER(3, rt1711h_alert_recv_hard_reset), + RT1711H_DECL_ALERT_HANDLER(10, rt1711h_alert_rx_overflow), + RT1711H_DECL_ALERT_HANDLER(16, rt1711h_alert_wakeup), + RT1711H_DECL_ALERT_HANDLER(21, rt1711h_alert_ra_detach), + RT1711H_DECL_ALERT_HANDLER(9, rt1711h_alert_fault), + RT1711H_DECL_ALERT_HANDLER(0, rt1711h_alert_cc_changed), + RT1711H_DECL_ALERT_HANDLER(1, rt1711h_alert_power_status_changed), +}; + +static int __rt1711h_irq_handler(struct rt1711h_chip *chip) +{ + int i = 0, ret = 0; + uint32_t alert_status = 0; + + ret = rt1711h_get_alert_status(chip, &alert_status); + if (ret < 0) { + rt1711h_log(chip, "%s get alert status fail(%d)\n", + __func__, ret); + goto out; + } + + rt1711h_alert_status_clear(chip, + alert_status & (~RT1711H_REG_ALERT_RX_MASK)); + + if (alert_status) + rt1711h_log(chip, "%s 0x%04X\n", __func__, alert_status); + + if (alert_status & RT1711H_REG_ALERT_EXT_VBUS_80) + alert_status |= RT1711H_REG_ALERT_POWER_STATUS; + + for (i = 0; i < ARRAY_SIZE(rt1711h_alert_handlers); i++) { + if (rt1711h_alert_handlers[i].bit_mask & alert_status) { + if (rt1711h_alert_handlers[i].handler != 0) + rt1711h_alert_handlers[i].handler(chip); + } + } + +out: + return ret; +} + +static inline void rt1711h_poll_ctrl(struct rt1711h_chip *chip) +{ + cancel_delayed_work_sync(&chip->poll_work); + + if (atomic_read(&chip->poll_count) == 0) { + atomic_inc(&chip->poll_count); + cpu_idle_poll_ctrl(true); + } + + schedule_delayed_work(&chip->poll_work, msecs_to_jiffies(40)); +} + +static void rt1711h_irq_work_handler(struct kthread_work *work) +{ + struct rt1711h_chip *chip = + container_of(work, struct rt1711h_chip, irq_work); + int ret = 0, gpio_val = 0; + + rt1711h_poll_ctrl(chip); + mutex_lock(&chip->wakeup_lock); + mutex_lock(&chip->lock); + do { + ret = __rt1711h_irq_handler(chip); + if (ret < 0) + break; + gpio_val = gpio_get_value(chip->irq_gpio); + } while (gpio_val == 0); + mutex_unlock(&chip->lock); + mutex_unlock(&chip->wakeup_lock); +} + +static void rt1711h_poll_work(struct work_struct *work) +{ + struct rt1711h_chip *chip = container_of(work, struct rt1711h_chip, + poll_work.work); + + if (atomic_dec_and_test(&chip->poll_count)) + cpu_idle_poll_ctrl(false); +} +#define RT1711H_IRQ_WAKE_TIME (500) /* ms */ + +static irqreturn_t rt1711h_intr_handler(int irq, void *data) +{ + struct rt1711h_chip *chip = data; + + pm_wakeup_event(chip->dev, RT1711H_IRQ_WAKE_TIME); + kthread_queue_work(&chip->irq_worker, &chip->irq_work); + + return IRQ_HANDLED; +} + +static int rt1711h_init_alert(struct rt1711h_chip *chip) +{ + int ret = 0, len = 0; + char *name = NULL; + struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; + + rt1711h_reg_write_word(chip, RT1711H_REG_ALERT_MASK, 0); + rt1711h_reg_write_word(chip, RT1711H_REG_ALERT, 0xffff); + + len = strlen(chip->name); + name = devm_kzalloc(chip->dev, len + 5, GFP_KERNEL); + if (!name) + return -ENOMEM; + + snprintf(name, len, "%s-IRQ", chip->name); + + dev_info(chip->dev, "%s name = %s, gpio = %d\n", __func__, chip->name, + chip->irq_gpio); + + ret = devm_gpio_request_one(chip->dev, chip->irq_gpio, + GPIOF_IN, name); + if (ret < 0) { + dev_err(chip->dev, "%s request gpio fail(%d)\n", + __func__, ret); + goto err_init_alert; + } + + chip->irq = gpio_to_irq(chip->irq_gpio); + if (chip->irq <= 0) { + dev_err(chip->dev, "%s gpio2irq fail(%d)\n", + __func__, chip->irq); + ret = -EINVAL; + goto err_init_alert; + } + dev_info(chip->dev, "%s irq = %d\n", __func__, chip->irq); + + kthread_init_worker(&chip->irq_worker); + chip->irq_worker_task = kthread_run(kthread_worker_fn, + &chip->irq_worker, chip->name); + if (IS_ERR(chip->irq_worker_task)) { + dev_err(chip->dev, "%s could not create tcpc task\n", __func__); + goto err_init_alert; + } + + sched_setscheduler(chip->irq_worker_task, SCHED_FIFO, ¶m); + kthread_init_work(&chip->irq_work, rt1711h_irq_work_handler); + + ret = devm_request_irq(chip->dev, chip->irq, rt1711h_intr_handler, + IRQF_TRIGGER_FALLING | IRQF_NO_THREAD | IRQF_NO_SUSPEND, name, + chip); + if (ret < 0) { + dev_err(chip->dev, "%s request irq%d fail(%d)\n", + __func__, chip->irq, ret); + goto err_init_alert; + } + enable_irq_wake(chip->irq); + return 0; + +err_init_alert: + devm_kfree(chip->dev, name); + return ret; +} + +static int rt1711h_check_revision(struct i2c_client *i2c) +{ + int ret = 0; + + ret = i2c_smbus_read_word_data(i2c, 0x00); + if (ret < 0) + return ret; + if (ret != 0x29cf) { + dev_err(&i2c->dev, "vid is not correct, 0x%04x\n", ret); + return -ENODEV; + } + ret = i2c_smbus_read_word_data(i2c, 0x02); + if (ret < 0) + return ret; + if (ret != 0x1711) { + dev_err(&i2c->dev, "pid is not correct, 0x%04x\n", ret); + return -ENODEV; + } + ret = i2c_smbus_read_word_data(i2c, 0x04); + if (ret < 0) + return ret; + /* return did */ + return ret; +} + +static int rt1711h_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + uint16_t did = 0; + struct rt1711h_chip *chip = NULL; + struct power_supply_config cfg = {}; + + pr_info("%s %s\n", __func__, RT1711H_DRV_VERSION); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) { + dev_err(&client->dev, + "I2C/SMBusyy block functionality not supported!\n"); + return -ENODEV; + } + ret = rt1711h_check_revision(client); + if (ret < 0) { + dev_err(&client->dev, "check vid/pid/did fail\n"); + return ret; + } + did = (uint16_t)ret; + dev_info(&client->dev, "did = 0x%04x\n", did); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + chip->i2c = client; + chip->dev = &client->dev; + chip->did = did; + mutex_init(&chip->lock); + mutex_init(&chip->wakeup_lock); + INIT_DELAYED_WORK(&chip->poll_work, rt1711h_poll_work); + INIT_DELAYED_WORK(&chip->wakeup_work, rt1711h_wakeup_work); + alarm_init(&chip->wakeup_timer, ALARM_REALTIME, + rt1711h_alarm_wakeup_handler); + i2c_set_clientdata(client, chip); + + ret = rt1711h_parse_dt(chip); + if (ret < 0) + goto out_parse_dt; + + cfg.drv_data = chip; + chip->psy = devm_power_supply_register(chip->dev, &rt1711h_psy_desc, + &cfg); + if (IS_ERR(chip->psy)) { + ret = PTR_ERR(chip->psy); + dev_err(chip->dev, "%s register psy fail(%d)\n", __func__, ret); + goto out_psy_reg; + } + + chip->vbus = devm_regulator_get(chip->dev, "vbus"); + if (IS_ERR(chip->vbus)) { + ret = PTR_ERR(chip->vbus); + goto out_reg_get; + } + + ret = rt1711h_debugfs_init(chip); + if (ret < 0) + goto out_dbgfs_init; + + ret = rt1711h_software_reset(chip); + if (ret < 0) + goto out_sw_reset; + + ret = rt1711h_init_alert(chip); + if (ret < 0) + goto out_init_alert; + + rt1711h_init_tcpc_dev(chip); + + chip->tcpm_port = tcpm_register_port(chip->dev, + &chip->tcpc_dev); + if (IS_ERR(chip->tcpm_port)) { + ret = PTR_ERR(chip->tcpm_port); + dev_err(chip->dev, "%s register tcpm port fail(%d)", + __func__, ret); + goto out_tcpm_reg; + } + + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + dev_info(chip->dev, "%s: successfully\n", __func__); + return 0; + +out_tcpm_reg: +out_init_alert: +out_sw_reset: + rt1711h_debugfs_exit(chip); +out_dbgfs_init: +out_reg_get: +out_psy_reg: +out_parse_dt: + mutex_destroy(&chip->lock); + devm_kfree(&client->dev, chip); + return 0; +} + +static int rt1711h_i2c_remove(struct i2c_client *client) +{ + struct rt1711h_chip *chip = i2c_get_clientdata(client); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + if (chip) { + rt1711h_debugfs_exit(chip); + mutex_destroy(&chip->lock); + } + dev_info(chip->dev, "%s: successfully\n", __func__); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int rt1711h_i2c_pm_suspend(struct device *dev) +{ + struct rt1711h_chip *chip = dev_get_drvdata(dev); + + if (chip) { + if (atomic_read(&chip->i2c_busy)) + return -EBUSY; + atomic_set(&chip->pm_suspend, 1); + } + return 0; +} + +static int rt1711h_i2c_pm_resume(struct device *dev) +{ + struct rt1711h_chip *chip = dev_get_drvdata(dev); + + if (chip) + atomic_set(&chip->pm_suspend, 0); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops rt1711h_i2c_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(rt1711h_i2c_pm_suspend, rt1711h_i2c_pm_resume) +}; + +static const struct of_device_id rt1711h_of_device_id[] = { + { .compatible = "richtek,typec_rt1711h",}, + { }, +}; +MODULE_DEVICE_TABLE(of, rt1711h_of_device_id); + +static const struct i2c_device_id rt1711h_i2c_device_id[] = { + { "typec_rt1711h", 0}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, rt1711h_i2c_device_id); + +static struct i2c_driver rt1711h_i2c_driver = { + .driver = { + .name = "typec_rt1711h", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rt1711h_of_device_id), + .pm = &rt1711h_i2c_pm_ops, + }, + .probe = rt1711h_i2c_probe, + .remove = rt1711h_i2c_remove, + .id_table = rt1711h_i2c_device_id, +}; +module_i2c_driver(rt1711h_i2c_driver); + +MODULE_AUTHOR("cy_huang "); +MODULE_DESCRIPTION("rt1711h typec driver"); +MODULE_VERSION(RT1711H_DRV_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/typec/rt1711h/rt1711h.h b/drivers/usb/typec/rt1711h/rt1711h.h new file mode 100644 index 0000000..8b67464 --- /dev/null +++ b/drivers/usb/typec/rt1711h/rt1711h.h @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 Richtek Technologh Corp. + * + * Richtek RT1711H Type-C Chip Driver + */ + +#ifndef __LINUX_RT1711H_H +#define __LINUX_RT1711H_H + +/* Device ID */ +#define RT1711H_DID_A 0x2170 +#define RT1711H_DID_B 0x2171 +#define RT1711H_DID_C 0x2172 +#define RT1711H_DID_D 0x2173 + +/* Registers */ +#define RT1711H_REG_VID (0x00) +#define RT1711H_REG_PID (0x02) +#define RT1711H_REG_DID (0x04) +#define RT1711H_REG_TYPEC_REV (0x06) +#define RT1711H_REG_PD_REV (0x08) +#define RT1711H_REG_PDIF_REV (0x0A) +#define RT1711H_REG_ALERT (0x10) +#define RT1711H_REG_ALERT_MASK (0x12) +#define RT1711H_REG_POWER_STATUS_MASK (0x14) +#define RT1711H_REG_FAULT_STATUS_MASK (0x15) +#define RT1711H_REG_TCPC_CTRL (0x19) +#define RT1711H_REG_ROLE_CTRL (0x1A) +#define RT1711H_REG_FAULT_CTRL (0x1B) +#define RT1711H_REG_POWER_CTRL (0x1C) +#define RT1711H_REG_CC_STATUS (0x1D) +#define RT1711H_REG_POWER_STATUS (0x1E) +#define RT1711H_REG_FAULT_STATUS (0x1F) +#define RT1711H_REG_COMMAND (0x23) +#define RT1711H_REG_MSG_HDR_INFO (0x2e) +#define RT1711H_REG_RX_DETECT (0x2f) +#define RT1711H_REG_RX_BYTE_CNT (0x30) +#define RT1711H_REG_RX_BUF_FRAME_TYPE (0x31) +#define RT1711H_REG_RX_HDR (0x32) +#define RT1711H_REG_RX_DATA (0x34) +#define RT1711H_REG_TRANSMIT (0x50) +#define RT1711H_REG_TX_BYTE_CNT (0x51) +#define RT1711H_REG_TX_HDR (0x52) +#define RT1711H_REG_TX_DATA (0x54) + +#define RT1711H_REG_CLK_CTRL2 (0x87) +#define RT1711H_REG_CLK_CTRL3 (0x88) +#define RT1711H_REG_BMC_CTRL (0x90) +#define RT1711H_REG_BMCIO_RXDZSEL (0x93) +#define RT1711H_REG_VCONN_CLIMITEN (0x95) +#define RT1711H_REG_RT_STATUS (0x97) +#define RT1711H_REG_RT_INT (0x98) +#define RT1711H_REG_RT_MASK (0x99) +#define RT1711H_REG_IDLE_CTRL (0x9B) +#define RT1711H_REG_INTRST_CTRL (0x9C) +#define RT1711H_REG_WATCHDOG_CTRL (0x9D) +#define RT1711H_REG_I2CRST_CTRL (0X9E) +#define RT1711H_REG_SWRESET (0xA0) +#define RT1711H_REG_TTCPC_FILTER (0xA1) +#define RT1711H_REG_DRP_TOGGLE_CYCLE (0xA2) +#define RT1711H_REG_DRP_DUTY_CTRL (0xA3) +#define RT1711H_REG_BMCIO_RXDZEN (0xAF) + + +#ifndef BIT +#define BIT(x) (1 << (x)) +#endif + +/* + * RT1711H_REG_ALERT (0x10) + * RT1711H_REG_ALERT_MASK (0x12) + */ +#define RT1711H_REG_VBUS_SINK_DISCONNECT BIT(11) +#define RT1711H_REG_ALERT_RX_BUF_OVF BIT(10) +#define RT1711H_REG_ALERT_FAULT BIT(9) +#define RT1711H_REG_ALERT_LO_VOLT BIT(8) +#define RT1711H_REG_ALERT_HI_VOLT BIT(7) +#define RT1711H_REG_ALERT_TX_SUCCESS BIT(6) +#define RT1711H_REG_ALERT_TX_DISCARDED BIT(5) +#define RT1711H_REG_ALERT_TX_FAILED BIT(4) +#define RT1711H_REG_ALERT_RX_HARD_RST BIT(3) +#define RT1711H_REG_ALERT_RX_STATUS BIT(2) +#define RT1711H_REG_ALERT_POWER_STATUS BIT(1) +#define RT1711H_REG_ALERT_CC_STATUS BIT(0) +#define RT1711H_REG_ALERT_RX_MASK \ + (RT1711H_REG_ALERT_RX_STATUS | RT1711H_REG_ALERT_RX_BUF_OVF) + +/* + * RT1711H_REG_POWER_STATUS_MASK (0x14) + * RT1711H_REG_POWER_STATUS (0x1E) + */ +#define RT1711H_REG_POWER_STATUS_TCPC_INITIAL BIT(6) +#define RT1711H_REG_POWER_STATUS_SRC_HV BIT(5) +#define RT1711H_REG_POWER_STATUS_SRC_VBUS BIT(4) +#define RT1711H_REG_POWER_STATUS_VBUS_PRES_DET BIT(3) +#define RT1711H_REG_POWER_STATUS_VBUS_PRES BIT(2) +#define RT1711H_REG_POWER_STATUS_VCONN_PRES BIT(1) +#define RT1711H_REG_POWER_STATUS_SINK_VBUS BIT(0) + +/* + * RT1711H_REG_FAULT_STATUS_MASK (0x15) + * RT1711H_REG_FAULT_STATUS (0x1F) + */ +#define RT1711H_REG_FAULT_STATUS_VCONN_OV BIT(7) +#define RT1711H_REG_FAULT_STATUS_FORCE_OFF_VBUS BIT(6) +#define RT1711H_REG_FAULT_STATUS_AUTO_DISC_FAIL BIT(5) +#define RT1711H_REG_FAULT_STATUS_FORCE_DISC_FAIL BIT(4) +#define RT1711H_REG_FAULT_STATUS_VBUS_OC BIT(3) +#define RT1711H_REG_FAULT_STATUS_VBUS_OV BIT(2) +#define RT1711H_REG_FAULT_STATUS_VCONN_OC BIT(1) +#define RT1711H_REG_FAULT_STATUS_I2C_ERROR BIT(0) + +/* + * RT1711H_REG_ROLE_CTRL (0x1A) + */ +#define RT1711H_REG_ROLE_CTRL_DRP BIT(6) +#define RT1711H_REG_ROLE_CTRL_RES_SET(drp, rp, cc1, cc2) \ + ((drp) << 6 | (rp) << 4 | (cc2) << 2 | (cc1)) +#define RT1711H_REG_ROLE_CTRL_CC2(reg) (((reg) & 0x0C) >> 2) +#define RT1711H_REG_ROLE_CTRL_CC1(reg) ((reg) & 0x03) +#define RT1711H_TYPEC_CC_PULL_GET_RP_LVL(pull) ((pull & 0x18) >> 3) +#define RT1711H_TYPEC_CC_PULL_GET_RES(pull) (pull & 0x07) + +enum typec_cc_pull { + TYPEC_CC_PULL_RA = 0, + TYPEC_CC_PULL_RP, + TYPEC_CC_PULL_RD, + TYPEC_CC_PULL_OPEN, + TYPEC_CC_PULL_DRP, /* from rd */ + + TYPEC_CC_PULL_RP_DEF = 1, /* 0x00 + 1 */ + TYPEC_CC_PULL_RP_1_5 = 9, /* 0x08 + 1 */ + TYPEC_CC_PULL_RP_3_0 = 17, /* 0x10 + 1 */ + + TYPEC_CC_PULL_DRP_DEF = 4, /* 0x00 + 4 */ + TYPEC_CC_PULL_DRP_1_5 = 12, /* 0x08 + 4 */ + TYPEC_CC_PULL_DRP_3_0 = 20, /* 0x10 + 4 */ +}; + +/* + * RT1711H_REG_TCPC_CTRL (0x19) + */ +#define RT1711H_REG_TCPC_CTRL_BIST_TEST_MODE BIT(1) +#define RT1711H_REG_TCPC_CTRL_PLUG_ORIENT BIT(0) + +/* + * RT1711H_REG_FAULT_CTRL (0x1B) + */ +#define RT1711H_REG_FAULT_CTRL_DIS_VCONN_OV BIT(7) +#define RT1711H_REG_FAULT_CTRL_DIS_SNK_VBUS_OC BIT(2) +#define RT1711H_REG_FAULT_CTRL_DIS_VCONN_OC BIT(0) + +/* + * RT1711H_REG_POWER_CTRL (0x1C) + */ +#define RT1711H_REG_POWER_CTRL_VCONN BIT(0) + +/* + * RT1711H_REG_CC_STATUS (0x1D) + */ +#define RT1711H_REG_CC_STATUS_DRP_TOGGLING BIT(5) +#define RT1711H_REG_CC_STATUS_DRP_RESULT(reg) (((reg) & 0x10) >> 4) +#define RT1711H_REG_CC_STATUS_CC2(reg) (((reg) & 0x0C) >> 2) +#define RT1711H_REG_CC_STATUS_CC1(reg) ((reg) & 0x03) +#define RT1711H_REG_CC_STATUS_RD2ENUM(cc) ((cc) + 2) + +/* + * RT1711H_REG_COMMAND (0x23) + */ +enum rt1711h_command { + RT1711H_CMD_WAKE_I2C = 0x11, + RT1711H_CMD_DISABLE_VBUS_DETECT = 0x22, + RT1711H_CMD_ENABLE_VBUS_DETECT = 0x33, + RT1711H_CMD_DISABLE_SINK_VBUS = 0x44, + RT1711H_CMD_ENABLE_SINK_VBUS = 0x55, + RT1711H_CMD_DISABLE_SOURCE_VBUS = 0x66, + RT1711H_CMD_ENABLE_SOURCE_VBUS = 0x77, + RT1711H_CMD_SOURCE_VBUS_HV = 0x88, + RT1711H_CMD_LOOK_CONNECTION = 0x99, + RT1711H_CMD_RX_ONE_MODE = 0xAA, + RT1711H_CMD_I2C_IDLE = 0xFF, +}; + + +/* + * RT1711H_REG_MSG_HDR_INFO (0x2E) + */ +#define RT1711H_REG_MSG_HDR_INFO_SET(drole, prole) \ + ((drole) << 3 | (PD_REV20 << 1) | (prole)) +#define RT1711H_REG_MSG_HDR_INFO_DROLE(reg) (((reg) & 0x08) >> 3) +#define RT1711H_REG_MSG_HDR_INFO_PROLE(reg) ((reg) & 0x01) + +/* + * RT1711H_REG_TRANSMIT (0x50) + */ +#define RT1711H_REG_TRANSMIT_SET(retry, type) ((retry) << 4 | (type)) + + +/* + * RT1711H_REG_CLK_CTRL2 (0x87) + */ +#define RT1711H_REG_CLK_DIV_600K_EN BIT(7) +#define RT1711H_REG_CLK_BCLK2_EN BIT(6) +#define RT1711H_REG_CLK_BCLK2_TG_EN BIT(5) +#define RT1711H_REG_CLK_DIV_300K_EN BIT(3) +#define RT1711H_REG_CLK_CK_300K_EN BIT(2) +#define RT1711H_REG_CLK_BCLK_EN BIT(1) +#define RT1711H_REG_CLK_BCLK_TH_EN BIT(0) + +/* + * RT1711H_REG_CLK_CTRL3 (0x88) + */ +#define RT1711H_REG_CLK_OSCMUX_RG_EN BIT(7) +#define RT1711H_REG_CLK_CK_24M_EN BIT(6) +#define RT1711H_REG_CLK_OSC_RG_EN BIT(5) +#define RT1711H_REG_CLK_DIV_2P4M_EN BIT(4) +#define RT1711H_REG_CLK_CK_2P4M_EN BIT(3) +#define RT1711H_REG_CLK_PCLK_EN BIT(2) +#define RT1711H_REG_CLK_PCLK_RG_EN BIT(1) +#define RT1711H_REG_CLK_PCLK_TG_EN BIT(0) + +/* + * RT1711H_REG_BMC_CTRL (0x90) + */ +#define RT1711H_REG_IDLE_EN BIT(6) +#define RT1711H_REG_DISCHARGE_EN BIT(5) +#define RT1711H_REG_BMCIO_LPRPRD BIT(4) +#define RT1711H_REG_BMCIO_LPEN BIT(3) +#define RT1711H_REG_BMCIO_BG_EN BIT(2) +#define RT1711H_REG_VBUS_DET_EN BIT(1) +#define RT1711H_REG_BMCIO_OSC_EN BIT(0) + +/* + * RT1711H_REG_RT_STATUS (0x97) + */ +#define RT1711H_REG_RA_DETACH BIT(5) +#define RT1711H_REG_VBUS_80 BIT(1) + +/* + * RT1711H_REG_RT_INT (0x98) + */ +#define RT1711H_REG_INT_RA_DETACH BIT(5) +#define RT1711H_REG_INT_WATCHDOG BIT(2) +#define RT1711H_REG_INT_VBUS_80 BIT(1) +#define RT1711H_REG_INT_WAKEUP BIT(0) + +/* + * RT1711H_REG_RT_MASK (0x99) + */ +#define RT1711H_REG_M_RA_DETACH BIT(5) +#define RT1711H_REG_M_WATCHDOG BIT(2) +#define RT1711H_REG_M_VBUS_80 BIT(1) +#define RT1711H_REG_M_WAKEUP BIT(0) +#define RT1711H_REG_ALERT_EXT_RA_DETACH (1 << (16 + 5)) +#define RT1711H_REG_ALERT_EXT_VBUS_80 (1 << (16 + 1)) + +/* + * RT1711H_REG_IDLE_CTRL (0x9B) + */ +#define RT1711H_REG_CK_300K_SEL BIT(7) +#define RT1711H_REG_SHIPPING_OFF BIT(5) +#define RT1711H_REG_AUTOIDLE_EN BIT(3) + +/* timeout = (tout*2+1) * 6.4ms */ +#define RT1711H_REG_IDLE_SET(ck300, ship_dis, auto_idle, tout) \ + (((ck300) << 7) | ((ship_dis) << 5) | \ + ((auto_idle) << 3) | ((tout) & 0x07)) + +/* + * RT1711H_REG_INTRST_CTRL (0x9C) + */ +#define RT1711H_REG_INTRST_EN BIT(7) + +/* timeout = (tout+1) * 0.2sec */ +#define RT1711H_REG_INTRST_SET(en, tout) (((en) << 7) | ((tout) & 0x03)) + +/* + * RT1711H_REG_WATCHDOG_CTRL (0x9D) + */ +#define RT1711H_REG_WATCHDOG_EN BIT(7) + +/* timeout = (tout+1) * 0.4sec */ +#define RT1711H_REG_WATCHDOG_CTRL_SET(en, tout) (((en) << 7) | ((tout) & 0x07)) + +/* + * RT1711H_REG_I2CRST_CTRL (0x9E) + */ +#define RT1711H_REG_I2CRST_EN BIT(7) + +/* timeout = (tout+1) * 12.5ms */ +#define RT1711H_REG_I2CRST_SET(en, tout) ((en << 7) | (tout & 0x0F)) + +/* + * RT1711H_REG_DRP_DUTY_CTRL (0xA3) + */ +#define RT1711H_LOW_RP_DUTY (100) /* 10% */ +#define RT1711H_NORMAL_RP_DUTY (330) /* 33% */ + +#endif /* __LINUX_RT1711H_H */ -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: USB TYPEC: RT1711H Type-C Chip Driver From: ShuFanLee Message-Id: <1515567552-7692-1-git-send-email-leechu729@gmail.com> Date: Wed, 10 Jan 2018 14:59:12 +0800 To: heikki.krogerus@linux.intel.com Cc: cy_huang@richtek.com, shufan_lee@richtek.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org List-ID: RnJvbTogU2h1RmFuTGVlIDxzaHVmYW5fbGVlQHJpY2h0ZWsuY29tPgoKUmljaHRlayBSVDE3MTFI IFR5cGUtQyBjaGlwIGRyaXZlciB0aGF0IHdvcmtzIHdpdGgKVHlwZS1DIFBvcnQgQ29udHJvbGxl ciBNYW5hZ2VyIHRvIHByb3ZpZGUgVVNCIFBEIGFuZApVU0IgVHlwZS1DIGZ1bmN0aW9uYWxpdGll cy4KClNpZ25lZC1vZmYtYnk6IFNodUZhbkxlZSA8c2h1ZmFuX2xlZUByaWNodGVrLmNvbT4KLS0t CiAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy91c2IvcmljaHRlayxydDE3MTFoLnR4dCAgICB8ICAg MzggKwogYXJjaC9hcm02NC9ib290L2R0cy9oaXNpbGljb24vcnQxNzExaC5kdHNpICAgICAgICAg fCAgIDExICsKIGRyaXZlcnMvdXNiL3R5cGVjL0tjb25maWcgICAgICAgICAgICAgICAgICAgICAg ICAgIHwgICAgMiArCiBkcml2ZXJzL3VzYi90eXBlYy9NYWtlZmlsZSAgICAgICAgICAgICAgICAg ICAgICAgICB8ICAgIDEgKwogZHJpdmVycy91c2IvdHlwZWMvcnQxNzExaC9LY29uZmlnICAgICAg ICAgICAgICAgICAgfCAgICA3ICsKIGRyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgvTWFrZWZpbGUg ICAgICAgICAgICAgICAgIHwgICAgMiArCiBkcml2ZXJzL3VzYi90eXBlYy9ydDE3MTFoL3J0MTcx MWguYyAgICAgICAgICAgICAgICB8IDIyNDEgKysrKysrKysrKysrKysrKysrKysKIGRyaXZlcnMv dXNiL3R5cGVjL3J0MTcxMWgvcnQxNzExaC5oICAgICAgICAgICAgICAgIHwgIDMwMCArKysKIDgg ZmlsZXMgY2hhbmdlZCwgMjYwMiBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgRG9j dW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3VzYi9yaWNodGVrLHJ0MTcxMWgudHh0CiBj cmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9hcm02NC9ib290L2R0cy9oaXNpbGljb24vcnQxNzExaC5k dHNpCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvdHlwZWMvcnQxNzExaC9LY29uZmln CiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvdHlwZWMvcnQxNzExaC9NYWtlZmlsZQog Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgvcnQxNzExaC5jCiBj cmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvdHlwZWMvcnQxNzExaC9ydDE3MTFoLmgKCmRp ZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvdXNiL3JpY2h0ZWss cnQxNzExaC50eHQgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvdXNiL3JpY2h0 ZWsscnQxNzExaC50eHQKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uYzI4Mjk5 YwotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy91 c2IvcmljaHRlayxydDE3MTFoLnR4dApAQCAtMCwwICsxLDM4IEBACitSaWNodGVrIFJUMTcxMUgg VHlwZS1DIFBvcnQgQ29udHJvbGxlci4KKworUmVxdWlyZWQgcHJvcGVydGllczoKKy0gY29tcGF0 aWJsZSA6IE11c3QgYmUgInJpY2h0ZWssdHlwZWNfcnQxNzExaCI7CistIHJlZyA6IE11c3QgYmUg MHg0ZSwgaXQncyBkZWZhdWx0IHNsYXZlIGFkZHJlc3Mgb2YgUlQxNzExSC4KKy0gcnQsaW50cl9n cGlvIDogSVJRIEdQSU8gcGluIHRoYXQncyBjb25uZWN0ZWQgdG8gUlQxNzExSCBpbnRlcnJ1cHQu CisKK09wdGlvbmFsIG5vZGU6CistIHJ0LG5hbWUgOiBOYW1lIHVzZWQgZm9yIHJlZ2lzdGVyaW5n IElSUSBhbmQgY3JlYXRpbmcga3RocmVhZC4KKwkgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBub3Qg c3BlY2lmaWVkLCAiZGVmYXVsdCIgd2lsbCBiZSBhcHBsaWVkLgorLSBydCxkZWZfcm9sZSA6IERl ZmF1bHQgcG9ydCByb2xlIChUWVBFQ19TSU5LKDApIG9yIFRZUEVDX1NPVVJDRSgxKSkuCisJCVNl dCB0byBUWVBFQ19OT19QUkVGRVJSRURfUk9MRSgtMSkgaWYgbm8gZGVmYXVsdCByb2xlLgorCQlJ ZiB0aGlzIHByb3BlcnR5IGlzIG5vdCBzcGVjaWZpZWQsIFRZUEVDX1NJTksgd2lsbCBiZSBhcHBs aWVkLgorLSBydCxwb3J0X3R5cGUgOiBQb3J0IHR5cGUgKFRZUEVDX1BPUlRfREZQKDApLCBUWVBF Q19QT1JUX1VGUCgxKSwKKwkJIG9yIFRZUEVDX1BPUlRfRFJQKDIpKS4gSWYgdGhpcyBwcm9wZXJ0 eSBpcyBub3Qgc3BlY2lmaWVkLAorCQkgVFlQRUNfUE9SVF9EUlAgd2lsbCBiZSBhcHBsaWVkLgor LSBydCxtYXhfc25rX212IDogTWF4aW11bSBhY2NlcHRhYmxlIHNpbmsgdm9sdGFnZSBpbiBtVi4K KwkJICBJZiB0aGlzIHByb3BlcnR5IGlzIG5vdCBzcGVjaWZpZWQsIDUwMDBtViB3aWxsIGJlIGFw cGxpZWQuCistIHJ0LG1heF9zbmtfbWEgOiBNYXhpbXVtIHNpbmsgY3VycmVudCBpbiBtQS4KKwkJ ICBJZiB0aGlzIHByb3BlcnR5IGlzIG5vdCBzcGVjaWZpZWQsIDMwMDBtQSB3aWxsIGJlIGFwcGxp ZWQuCistIHJ0LG1heF9zbmtfbXcgOiBNYXhpbXVtIHJlcXVpcmVkIHNpbmsgcG93ZXIgaW4gbVcu CisJCSAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBub3Qgc3BlY2lmaWVkLCAxNTAwMG1XIHdpbGwgYmUg YXBwbGllZC4KKy0gcnQsb3BlcmF0aW5nX3Nua19tdyA6IFJlcXVpcmVkIG9wZXJhdGluZyBzaW5r IHBvd2VyIGluIG1XLgorCQkJSWYgdGhpcyBwcm9wZXJ0eSBpcyBub3Qgc3BlY2lmaWVkLAorCQkJ MjUwMG1XIHdpbGwgYmUgYXBwbGllZC4KKy0gcnQsdHJ5X3JvbGVfaHcgOiBUcnVlIGlmIHRyeS57 U3JjLFNua30gaXMgaW1wbGVtZW50ZWQgaW4gaGFyZHdhcmUuCisJCSAgIElmIHRoaXMgcHJvcGVy dHkgaXMgbm90IHNwZWNpZmllZCwgRmFsc2Ugd2lsbCBiZSBhcHBsaWVkLgorCitFeGFtcGxlOgor cnQxNzExaEA0ZSB7CisJc3RhdHVzID0gIm9rIjsKKwljb21wYXRpYmxlID0gInJpY2h0ZWssdHlw ZWNfcnQxNzExaCI7CisJcmVnID0gPDB4NGU+OworCXJ0LGludHJfZ3BpbyA9IDwmZ3BpbzI2IDAg MHgwPjsKKwlydCxuYW1lID0gInJ0MTcxMWgiOworCXJ0LHBvcnRfdHlwZSA9IDwyPjsgLyogMDog REZQLCAxOiBVRlAsIDI6IERSUCAqLworCXJ0LGRlZl9yb2xlID0gPDA+OyAvKiAwOiBTTkssIDE6 IFNSQywgLTE6IFRZUEVDX05PX1BSRUZFUlJFRF9ST0xFICovCit9OwpkaWZmIC0tZ2l0IGEvYXJj aC9hcm02NC9ib290L2R0cy9oaXNpbGljb24vcnQxNzExaC5kdHNpIGIvYXJjaC9hcm02NC9ib290 L2R0cy9oaXNpbGljb24vcnQxNzExaC5kdHNpCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAw MDAwMDAuLjQxOTZjYzAKLS0tIC9kZXYvbnVsbAorKysgYi9hcmNoL2FybTY0L2Jvb3QvZHRzL2hp c2lsaWNvbi9ydDE3MTFoLmR0c2kKQEAgLTAsMCArMSwxMSBAQAorJmkyYzcgeworCXJ0MTcxMWhA NGUgeworCQlzdGF0dXMgPSAib2siOworCQljb21wYXRpYmxlID0gInJpY2h0ZWssdHlwZWNfcnQx NzExaCI7CisJCXJlZyA9IDwweDRlPjsKKwkJcnQsaW50cl9ncGlvID0gPCZncGlvMjYgMCAweDA+ OworCQlydCxuYW1lID0gInJ0MTcxMWgiOworCQlydCxwb3J0X3R5cGUgPSA8Mj47IC8qIDA6IERG UCwgMTogVUZQLCAyOiBEUlAgKi8KKwkJcnQsZGVmX3JvbGUgPSA8MD47IC8qIDA6IFNOSywgMTog U1JDICovCisJfTsKK307CmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi90eXBlYy9LY29uZmlnIGIv ZHJpdmVycy91c2IvdHlwZWMvS2NvbmZpZwppbmRleCBiY2IyNzQ0Li43YmVkZTBiIDEwMDY0NAot LS0gYS9kcml2ZXJzL3VzYi90eXBlYy9LY29uZmlnCisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL0tj b25maWcKQEAgLTU2LDYgKzU2LDggQEAgaWYgVFlQRUNfVENQTQogCiBzb3VyY2UgImRyaXZlcnMv dXNiL3R5cGVjL2Z1c2IzMDIvS2NvbmZpZyIKIAorc291cmNlICJkcml2ZXJzL3VzYi90eXBlYy9y dDE3MTFoL0tjb25maWciCisKIGNvbmZpZyBUWVBFQ19XQ09WRQogCXRyaXN0YXRlICJJbnRlbCBX aGlza2V5Q292ZSBQTUlDIFVTQiBUeXBlLUMgUEhZIGRyaXZlciIKIAlkZXBlbmRzIG9uIEFDUEkK ZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL3R5cGVjL01ha2VmaWxlIGIvZHJpdmVycy91c2IvdHlw ZWMvTWFrZWZpbGUKaW5kZXggYmIzMTM4YS4uZTNhYWYzYyAxMDA2NDQKLS0tIGEvZHJpdmVycy91 c2IvdHlwZWMvTWFrZWZpbGUKKysrIGIvZHJpdmVycy91c2IvdHlwZWMvTWFrZWZpbGUKQEAgLTIs NiArMiw3IEBACiBvYmotJChDT05GSUdfVFlQRUMpCQkrPSB0eXBlYy5vCiBvYmotJChDT05GSUdf VFlQRUNfVENQTSkJKz0gdGNwbS5vCiBvYmoteQkJCQkrPSBmdXNiMzAyLworb2JqLSQoQ09ORklH X1RZUEVDX1JUMTcxMUgpCSs9IHJ0MTcxMWgvCiBvYmotJChDT05GSUdfVFlQRUNfV0NPVkUpCSs9 IHR5cGVjX3djb3ZlLm8KIG9iai0kKENPTkZJR19UWVBFQ19VQ1NJKQkrPSB1Y3NpLwogb2JqLSQo Q09ORklHX1RZUEVDX1RQUzY1OThYKQkrPSB0cHM2NTk4eC5vCmRpZmYgLS1naXQgYS9kcml2ZXJz L3VzYi90eXBlYy9ydDE3MTFoL0tjb25maWcgYi9kcml2ZXJzL3VzYi90eXBlYy9ydDE3MTFoL0tj b25maWcKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uMmZiZmZmNQotLS0gL2Rl di9udWxsCisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgvS2NvbmZpZwpAQCAtMCwwICsx LDcgQEAKK2NvbmZpZyBUWVBFQ19SVDE3MTFICisJdHJpc3RhdGUgIlJpY2h0ZWsgUlQxNzExSCBU eXBlLUMgY2hpcCBkcml2ZXIiCisJZGVwZW5kcyBvbiBJMkMgJiYgUE9XRVJfU1VQUExZCisJaGVs cAorCSAgVGhlIFJpY2h0ZWsgUlQxNzExSCAgIFR5cGUtQyBjaGlwIGRyaXZlciB0aGF0IHdvcmtz IHdpdGgKKwkgIFR5cGUtQyBQb3J0IENvbnRyb2xsZXIgTWFuYWdlciB0byBwcm92aWRlIFVTQiBQ RCBhbmQgVVNCCisJICBUeXBlLUMgZnVuY3Rpb25hbGl0aWVzLgpkaWZmIC0tZ2l0IGEvZHJpdmVy cy91c2IvdHlwZWMvcnQxNzExaC9NYWtlZmlsZSBiL2RyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgv TWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNWZhYjhhZQotLS0g L2Rldi9udWxsCisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgvTWFrZWZpbGUKQEAgLTAs MCArMSwyIEBACisjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCitvYmotJChDT05G SUdfVFlQRUNfUlQxNzExSCkJKz0gcnQxNzExaC5vCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi90 eXBlYy9ydDE3MTFoL3J0MTcxMWguYyBiL2RyaXZlcnMvdXNiL3R5cGVjL3J0MTcxMWgvcnQxNzEx aC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjFhZWYzZTgKLS0tIC9kZXYv bnVsbAorKysgYi9kcml2ZXJzL3VzYi90eXBlYy9ydDE3MTFoL3J0MTcxMWguYwpAQCAtMCwwICsx LDIyNDEgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKworLyoKKyAqIENv cHlyaWdodCAyMDE3IFJpY2h0ZWsgVGVjaG5vbG9naCBDb3JwLgorICoKKyAqIFJpY2h0ZWsgUlQx NzExSCBUeXBlLUMgQ2hpcCBEcml2ZXIKKyAqLworCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+ CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvdmVyc2lvbi5oPgor I2luY2x1ZGUgPGxpbnV4L2Vyci5oPgorI2luY2x1ZGUgPGxpbnV4L2RlYnVnZnMuaD4KKyNpbmNs dWRlIDxsaW51eC9wbV9ydW50aW1lLmg+CisjaW5jbHVkZSA8bGludXgvaTJjLmg+CisjaW5jbHVk ZSA8bGludXgvdXNiL3R5cGVjLmg+CisjaW5jbHVkZSA8bGludXgvdXNiL3RjcG0uaD4KKyNpbmNs dWRlIDxsaW51eC91c2IvcGQuaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9ncGlvLmg+CisjaW5jbHVk ZSA8bGludXgvb2YuaD4KKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgorI2luY2x1ZGUgPGxpbnV4 L2ludGVycnVwdC5oPgorI2luY2x1ZGUgPGxpbnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgorI2lu Y2x1ZGUgPGxpbnV4L3Bvd2VyX3N1cHBseS5oPgorI2luY2x1ZGUgPGxpbnV4L2V4dGNvbi5oPgor I2luY2x1ZGUgPGxpbnV4L3dvcmtxdWV1ZS5oPgorI2luY2x1ZGUgPGxpbnV4L2t0aHJlYWQuaD4K KyNpbmNsdWRlIDxsaW51eC9jcHUuaD4KKyNpbmNsdWRlIDxsaW51eC9hbGFybXRpbWVyLmg+Cisj aW5jbHVkZSA8bGludXgvc2NoZWQvY2xvY2suaD4KKyNpbmNsdWRlIDx1YXBpL2xpbnV4L3NjaGVk L3R5cGVzLmg+CisKKyNpbmNsdWRlICJydDE3MTFoLmgiCisKKyNkZWZpbmUgUlQxNzExSF9EUlZf VkVSU0lPTgkiMS4wLjMiCisKKyNkZWZpbmUgTE9HX0JVRkZFUl9FTlRSSUVTCTEwMjQKKyNkZWZp bmUgTE9HX0JVRkZFUl9FTlRSWV9TSVpFCTEyOCAvKiAxMjggY2hhciBwZXIgbGluZSAqLworCitl bnVtIHsKKwlSVDE3MTFIX0RCR19MT0cgPSAwLAorCVJUMTcxMUhfREJHX1JFR1MsCisJUlQxNzEx SF9EQkdfUkVHX0FERFIsCisJUlQxNzExSF9EQkdfREFUQSwKKwlSVDE3MTFIX0RCR19NQVgsCit9 OworCitzdHJ1Y3QgcnQxNzExaF9kYmdfaW5mbyB7CisJc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hp cDsKKwlpbnQgaWQ7Cit9OworCisKK3N0cnVjdCBydDE3MTFoX2NoaXAgeworCXN0cnVjdCBpMmNf Y2xpZW50ICppMmM7CisJc3RydWN0IGRldmljZSAqZGV2OworCXVpbnQxNl90IGRpZDsKKwlpbnQg aXJxX2dwaW87CisJaW50IGlycTsKKwljaGFyICpuYW1lOworCXN0cnVjdCB0Y3BjX2RldiB0Y3Bj X2RldjsKKwlzdHJ1Y3QgdGNwY19jb25maWcgdGNwY19jZmc7CisJc3RydWN0IHRjcG1fcG9ydCAq dGNwbV9wb3J0OworCXN0cnVjdCByZWd1bGF0b3IgKnZidXM7CisJc3RydWN0IGV4dGNvbl9kZXYg KmV4dGNvbjsKKworCS8qIElSUSAqLworCXN0cnVjdCBrdGhyZWFkX3dvcmtlciBpcnFfd29ya2Vy OworCXN0cnVjdCBrdGhyZWFkX3dvcmsgaXJxX3dvcms7CisJc3RydWN0IHRhc2tfc3RydWN0ICpp cnFfd29ya2VyX3Rhc2s7CisJYXRvbWljX3QgcG9sbF9jb3VudDsKKwlzdHJ1Y3QgZGVsYXllZF93 b3JrIHBvbGxfd29yazsKKworCS8qIExQTSAqLworCXN0cnVjdCBkZWxheWVkX3dvcmsgd2FrZXVw X3dvcms7CisJc3RydWN0IGFsYXJtIHdha2V1cF90aW1lcjsKKwlzdHJ1Y3QgbXV0ZXggd2FrZXVw X2xvY2s7CisJZW51bSB0eXBlY19jY19wdWxsIGxwbV9wdWxsOworCWJvb2wgd2FrZXVwX29uY2U7 CisJYm9vbCBsb3dfcnBfZHV0eV9jbnRkb3duOworCWJvb2wgY2FibGVfb25seTsKKwlib29sIGxw bTsKKworCS8qIEkyQyAqLworCWF0b21pY190IGkyY19idXN5OworCWF0b21pY190IHBtX3N1c3Bl bmQ7CisKKwkvKiBwc3kgKyBwc3kgc3RhdHVzICovCisJc3RydWN0IHBvd2VyX3N1cHBseSAqcHN5 OworCXUzMiBjdXJyZW50X2xpbWl0OworCXUzMiBzdXBwbHlfdm9sdGFnZTsKKworCS8qIGxvY2sg Zm9yIHNoYXJpbmcgY2hpcCBzdGF0ZXMgKi8KKwlzdHJ1Y3QgbXV0ZXggbG9jazsKKworCS8qIHBv cnQgc3RhdHVzICovCisJYm9vbCB2Y29ubl9vbjsKKwlib29sIHZidXNfb247CisJYm9vbCBjaGFy Z2Vfb247CisJYm9vbCB2YnVzX3ByZXNlbnQ7CisJZW51bSB0eXBlY19jY19wb2xhcml0eSBwb2xh cml0eTsKKwllbnVtIHR5cGVjX2NjX3N0YXR1cyBjYzE7CisJZW51bSB0eXBlY19jY19zdGF0dXMg Y2MyOworCWVudW0gdHlwZWNfcm9sZSBwd3Jfcm9sZTsKKwlib29sIGRycF90b2dnbGluZzsKKwor I2lmZGVmIENPTkZJR19ERUJVR19GUworCXN0cnVjdCBkZW50cnkgKmRiZ2RpcjsKKwlzdHJ1Y3Qg cnQxNzExaF9kYmdfaW5mbyBkYmdfaW5mb1tSVDE3MTFIX0RCR19NQVhdOworCXN0cnVjdCBkZW50 cnkgKmRiZ19maWxlc1tSVDE3MTFIX0RCR19NQVhdOworCWludCBkYmdfcmVnaWR4OworCXN0cnVj dCBtdXRleCBkYmdvcHNfbG9jazsKKwkvKiBsb2NrIGZvciBsb2cgYnVmZmVyIGFjY2VzcyAqLwor CXN0cnVjdCBtdXRleCBsb2didWZmZXJfbG9jazsKKwlpbnQgbG9nYnVmZmVyX2hlYWQ7CisJaW50 IGxvZ2J1ZmZlcl90YWlsOworCXU4ICpsb2didWZmZXJbTE9HX0JVRkZFUl9FTlRSSUVTXTsKKyNl bmRpZiAvKiBDT05GSUdfREVCVUdfRlMgKi8KK307CisKKy8qCisgKiBMb2dnaW5nICYgZGVidWdn aW5nCisgKi8KKworI2lmZGVmIENPTkZJR19ERUJVR19GUworCitzdGF0aWMgaW50IHJ0MTcxMWhf cmVnX2Jsb2NrX3JlYWQoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDhfdCByZWcsCisJ aW50IGxlbiwgdWludDhfdCAqZGF0YSk7CitzdGF0aWMgaW50IHJ0MTcxMWhfcmVnX2Jsb2NrX3dy aXRlKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAsIHVpbnQ4X3QgcmVnLAorCWludCBsZW4sIGNv bnN0IHVpbnQ4X3QgKmRhdGEpOworCitzdHJ1Y3QgcmVnX2Rlc2MgeworCXVpbnQ4X3QgYWRkcjsK Kwl1aW50OF90IHNpemU7Cit9OworI2RlZmluZSBERUNMX1JFRyhfYWRkciwgX3NpemUpIHsuYWRk ciA9IF9hZGRyLCAuc2l6ZSA9IF9zaXplfQorCitzdGF0aWMgc3RydWN0IHJlZ19kZXNjIHJ0MTcx MWhfcmVnX2Rlc2NbXSA9IHsKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19WSUQsIDIpLAorCURFQ0xf UkVHKFJUMTcxMUhfUkVHX1BJRCwgMiksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfRElELCAyKSwK KwlERUNMX1JFRyhSVDE3MTFIX1JFR19UWVBFQ19SRVYsIDIpLAorCURFQ0xfUkVHKFJUMTcxMUhf UkVHX1BEX1JFViwgMiksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfUERJRl9SRVYsIDIpLAorCURF Q0xfUkVHKFJUMTcxMUhfUkVHX0FMRVJULCAyKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19BTEVS VF9NQVNLLCAyKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVNfTUFTSywgMSks CisJREVDTF9SRUcoUlQxNzExSF9SRUdfRkFVTFRfU1RBVFVTX01BU0ssIDEpLAorCURFQ0xfUkVH KFJUMTcxMUhfUkVHX1RDUENfQ1RSTCwgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfUk9MRV9D VFJMLCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19GQVVMVF9DVFJMLCAxKSwKKwlERUNMX1JF RyhSVDE3MTFIX1JFR19QT1dFUl9DVFJMLCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19DQ19T VEFUVVMsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhfUkVHX1BPV0VSX1NUQVRVUywgMSksCisJREVD TF9SRUcoUlQxNzExSF9SRUdfRkFVTFRfU1RBVFVTLCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JF R19DT01NQU5ELCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19NU0dfSERSX0lORk8sIDEpLAor CURFQ0xfUkVHKFJUMTcxMUhfUkVHX1JYX0RFVEVDVCwgMSksCisJREVDTF9SRUcoUlQxNzExSF9S RUdfUlhfQllURV9DTlQsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhfUkVHX1JYX0JVRl9GUkFNRV9U WVBFLCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19SWF9IRFIsIDIpLAorCURFQ0xfUkVHKFJU MTcxMUhfUkVHX1JYX0RBVEEsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhfUkVHX1RSQU5TTUlULCAx KSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19UWF9CWVRFX0NOVCwgMSksCisJREVDTF9SRUcoUlQx NzExSF9SRUdfVFhfSERSLCAyKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19UWF9EQVRBLCAxKSwK KwlERUNMX1JFRyhSVDE3MTFIX1JFR19DTEtfQ1RSTDIsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhf UkVHX0NMS19DVFJMMywgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfQk1DX0NUUkwsIDEpLAor CURFQ0xfUkVHKFJUMTcxMUhfUkVHX0JNQ0lPX1JYRFpTRUwsIDEpLAorCURFQ0xfUkVHKFJUMTcx MUhfUkVHX1ZDT05OX0NMSU1JVEVOLCAxKSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19SVF9TVEFU VVMsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhfUkVHX1JUX0lOVCwgMSksCisJREVDTF9SRUcoUlQx NzExSF9SRUdfUlRfTUFTSywgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfSURMRV9DVFJMLCAx KSwKKwlERUNMX1JFRyhSVDE3MTFIX1JFR19JTlRSU1RfQ1RSTCwgMSksCisJREVDTF9SRUcoUlQx NzExSF9SRUdfV0FUQ0hET0dfQ1RSTCwgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfSTJDUlNU X0NUUkwsIDEpLAorCURFQ0xfUkVHKFJUMTcxMUhfUkVHX1NXUkVTRVQsIDEpLAorCURFQ0xfUkVH KFJUMTcxMUhfUkVHX1RUQ1BDX0ZJTFRFUiwgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfRFJQ X1RPR0dMRV9DWUNMRSwgMSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfRFJQX0RVVFlfQ1RSTCwg MSksCisJREVDTF9SRUcoUlQxNzExSF9SRUdfQk1DSU9fUlhEWkVOLCAxKSwKK307CisKK3N0YXRp YyBjb25zdCBjaGFyICpydDE3MTFoX2RiZ19maWxlbmFtZVtSVDE3MTFIX0RCR19NQVhdID0gewor CSJsb2ciLCAicmVncyIsICJyZWdfYWRkciIsICJkYXRhIiwKK307CisKK3N0YXRpYyBib29sIHJ0 MTcxMWhfbG9nX2Z1bGwoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlyZXR1cm4gY2hp cC0+bG9nYnVmZmVyX3RhaWwgPT0KKwkJKGNoaXAtPmxvZ2J1ZmZlcl9oZWFkICsgMSkgJSBMT0df QlVGRkVSX0VOVFJJRVM7Cit9CisKK3N0YXRpYyB2b2lkIF9ydDE3MTFoX2xvZyhzdHJ1Y3QgcnQx NzExaF9jaGlwICpjaGlwLCBjb25zdCBjaGFyICpmbXQsCisJCQkgdmFfbGlzdCBhcmdzKQorewor CWNoYXIgdG1wYnVmZmVyW0xPR19CVUZGRVJfRU5UUllfU0laRV07CisJdTY0IHRzX25zZWMgPSBs b2NhbF9jbG9jaygpOworCXVuc2lnbmVkIGxvbmcgcmVtX25zZWM7CisKKwlpZiAoIWNoaXAtPmxv Z2J1ZmZlcltjaGlwLT5sb2didWZmZXJfaGVhZF0pIHsKKwkJY2hpcC0+bG9nYnVmZmVyW2NoaXAt PmxvZ2J1ZmZlcl9oZWFkXSA9CisJCWRldm1fa3phbGxvYyhjaGlwLT5kZXYsIExPR19CVUZGRVJf RU5UUllfU0laRSwgR0ZQX0tFUk5FTCk7CisJCWlmICghY2hpcC0+bG9nYnVmZmVyW2NoaXAtPmxv Z2J1ZmZlcl9oZWFkXSkKKwkJCXJldHVybjsKKwl9CisKKwl2c25wcmludGYodG1wYnVmZmVyLCBz aXplb2YodG1wYnVmZmVyKSwgZm10LCBhcmdzKTsKKworCW11dGV4X2xvY2soJmNoaXAtPmxvZ2J1 ZmZlcl9sb2NrKTsKKworCWlmIChydDE3MTFoX2xvZ19mdWxsKGNoaXApKSB7CisJCWNoaXAtPmxv Z2J1ZmZlcl9oZWFkID0gbWF4KGNoaXAtPmxvZ2J1ZmZlcl9oZWFkIC0gMSwgMCk7CisJCXN0cmxj cHkodG1wYnVmZmVyLCAib3ZlcmZsb3ciLCBzaXplb2YodG1wYnVmZmVyKSk7CisJfQorCisJaWYg KGNoaXAtPmxvZ2J1ZmZlcl9oZWFkIDwgMCB8fAorCQljaGlwLT5sb2didWZmZXJfaGVhZCA+PSBM T0dfQlVGRkVSX0VOVFJJRVMpIHsKKwkJZGV2X3dhcm4oY2hpcC0+ZGV2LCAiJXMgYmFkIGxvZyBi dWZmZXIgaW5kZXggJWRcbiIsIF9fZnVuY19fLAorCQkJY2hpcC0+bG9nYnVmZmVyX2hlYWQpOwor CQlnb3RvIGFib3J0OworCX0KKworCWlmICghY2hpcC0+bG9nYnVmZmVyW2NoaXAtPmxvZ2J1ZmZl cl9oZWFkXSkgeworCQlkZXZfd2FybihjaGlwLT5kZXYsICIlcyBsb2cgYnVmZmVyIGluZGV4ICVk IGlzIE5VTExcbiIsCisJCQlfX2Z1bmNfXywgY2hpcC0+bG9nYnVmZmVyX2hlYWQpOworCQlnb3Rv IGFib3J0OworCX0KKworCXJlbV9uc2VjID0gZG9fZGl2KHRzX25zZWMsIDEwMDAwMDAwMDApOwor CXNjbnByaW50ZihjaGlwLT5sb2didWZmZXJbY2hpcC0+bG9nYnVmZmVyX2hlYWRdLCBMT0dfQlVG RkVSX0VOVFJZX1NJWkUsCisJCSJbJTVsdS4lMDZsdV0gJXMiLCAodW5zaWduZWQgbG9uZyl0c19u c2VjLCByZW1fbnNlYyAvIDEwMDAsCisJCSAgdG1wYnVmZmVyKTsKKwljaGlwLT5sb2didWZmZXJf aGVhZCA9IChjaGlwLT5sb2didWZmZXJfaGVhZCArIDEpICUgTE9HX0JVRkZFUl9FTlRSSUVTOwor CithYm9ydDoKKwltdXRleF91bmxvY2soJmNoaXAtPmxvZ2J1ZmZlcl9sb2NrKTsKK30KKworc3Rh dGljIHZvaWQgcnQxNzExaF9sb2coc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwKKwljb25zdCBj aGFyICpmbXQsIC4uLikKK3sKKwl2YV9saXN0IGFyZ3M7CisKKwl2YV9zdGFydChhcmdzLCBmbXQp OworCV9ydDE3MTFoX2xvZyhjaGlwLCBmbXQsIGFyZ3MpOworCXZhX2VuZChhcmdzKTsKK30KKwor c3RhdGljIGludCBydDE3MTFoX2xvZ19zaG93KHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAsIHN0 cnVjdCBzZXFfZmlsZSAqcykKK3sKKwlpbnQgdGFpbDsKKworCW11dGV4X2xvY2soJmNoaXAtPmxv Z2J1ZmZlcl9sb2NrKTsKKwl0YWlsID0gY2hpcC0+bG9nYnVmZmVyX3RhaWw7CisJd2hpbGUgKHRh aWwgIT0gY2hpcC0+bG9nYnVmZmVyX2hlYWQpIHsKKwkJc2VxX3ByaW50ZihzLCAiJXMiLCBjaGlw LT5sb2didWZmZXJbdGFpbF0pOworCQl0YWlsID0gKHRhaWwgKyAxKSAlIExPR19CVUZGRVJfRU5U UklFUzsKKwl9CisJaWYgKCFzZXFfaGFzX292ZXJmbG93ZWQocykpCisJCWNoaXAtPmxvZ2J1ZmZl cl90YWlsID0gdGFpbDsKKwltdXRleF91bmxvY2soJmNoaXAtPmxvZ2J1ZmZlcl9sb2NrKTsKKwor CXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfcmVnc19zaG93KHN0cnVjdCBydDE3 MTFoX2NoaXAgKmNoaXAsIHN0cnVjdCBzZXFfZmlsZSAqcykKK3sKKwlpbnQgcmV0ID0gMDsKKwlp bnQgaSA9IDAsIGogPSAwOworCXN0cnVjdCByZWdfZGVzYyAqZGVzYyA9IE5VTEw7CisJdWludDhf dCByZWd2YWxbMl0gPSB7MH07CisKKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShydDE3MTFo X3JlZ19kZXNjKTsgaSsrKSB7CisJCWRlc2MgPSAmcnQxNzExaF9yZWdfZGVzY1tpXTsKKwkJcmV0 ID0gcnQxNzExaF9yZWdfYmxvY2tfcmVhZChjaGlwLCBkZXNjLT5hZGRyLCBkZXNjLT5zaXplLAor CQkJcmVndmFsKTsKKwkJaWYgKHJldCA8IDApIHsKKwkJCWRldl9lcnIoY2hpcC0+ZGV2LCAiJXMg cmVhZCByZWcweCUwMlggZmFpbFxuIiwKKwkJCQlfX2Z1bmNfXywgZGVzYy0+YWRkcik7CisJCQlj b250aW51ZTsKKwkJfQorCisJCXNlcV9wcmludGYocywgInJlZzB4JTAyeDoweCIsIGRlc2MtPmFk ZHIpOworCQlmb3IgKGogPSAwOyBqIDwgZGVzYy0+c2l6ZTsgaisrKQorCQkJc2VxX3ByaW50Zihz LCAiJTAyeCwiLCByZWd2YWxbal0pOworCQlzZXFfcHV0cyhzLCAiXG4iKTsKKwl9CisKKwlyZXR1 cm4gMDsKK30KKworc3RhdGljIGlubGluZSBpbnQgcnQxNzExaF9yZWdfYWRkcl9zaG93KHN0cnVj dCBydDE3MTFoX2NoaXAgKmNoaXAsCisJc3RydWN0IHNlcV9maWxlICpzKQoreworCXN0cnVjdCBy ZWdfZGVzYyAqZGVzYyA9ICZydDE3MTFoX3JlZ19kZXNjW2NoaXAtPmRiZ19yZWdpZHhdOworCisJ c2VxX3ByaW50ZihzLCAiMHglMDJ4XG4iLCBkZXNjLT5hZGRyKTsKKwlyZXR1cm4gMDsKK30KKwor c3RhdGljIGlubGluZSBpbnQgcnQxNzExaF9kYXRhX3Nob3coc3RydWN0IHJ0MTcxMWhfY2hpcCAq Y2hpcCwKKwlzdHJ1Y3Qgc2VxX2ZpbGUgKnMpCit7CisJaW50IHJldCA9IDAsIGkgPSAwOworCXN0 cnVjdCByZWdfZGVzYyAqZGVzYyA9ICZydDE3MTFoX3JlZ19kZXNjW2NoaXAtPmRiZ19yZWdpZHhd OworCXVpbnQ4X3QgcmVndmFsWzJdID0gezB9OworCisJcmV0ID0gcnQxNzExaF9yZWdfYmxvY2tf cmVhZChjaGlwLCBkZXNjLT5hZGRyLCBkZXNjLT5zaXplLCByZWd2YWwpOworCWlmIChyZXQgPCAw KQorCQlyZXR1cm4gcmV0OworCisJc2VxX3ByaW50ZihzLCAicmVnMHglMDJ4PTB4IiwgZGVzYy0+ YWRkcik7CisJZm9yIChpID0gMDsgaSA8IGRlc2MtPnNpemU7IGkrKykKKwkJc2VxX3ByaW50Zihz LCAiJTAyeCwiLCByZWd2YWxbaV0pOworCXNlcV9wdXRzKHMsICJcbiIpOworCXJldHVybiAwOwor fQorCitzdGF0aWMgaW50IHJ0MTcxMWhfZGJnX3Nob3coc3RydWN0IHNlcV9maWxlICpzLCB2b2lk ICp2KQoreworCWludCByZXQgPSAwOworCXN0cnVjdCBydDE3MTFoX2RiZ19pbmZvICppbmZvID0g KHN0cnVjdCBydDE3MTFoX2RiZ19pbmZvICopcy0+cHJpdmF0ZTsKKwlzdHJ1Y3QgcnQxNzExaF9j aGlwICpjaGlwID0gaW5mby0+Y2hpcDsKKworCW11dGV4X2xvY2soJmNoaXAtPmRiZ29wc19sb2Nr KTsKKwlzd2l0Y2ggKGluZm8tPmlkKSB7CisJY2FzZSBSVDE3MTFIX0RCR19MT0c6CisJCXJldCA9 IHJ0MTcxMWhfbG9nX3Nob3coY2hpcCwgcyk7CisJCWJyZWFrOworCWNhc2UgUlQxNzExSF9EQkdf UkVHUzoKKwkJcmV0ID0gcnQxNzExaF9yZWdzX3Nob3coY2hpcCwgcyk7CisJCWJyZWFrOworCWNh c2UgUlQxNzExSF9EQkdfUkVHX0FERFI6CisJCXJldCA9IHJ0MTcxMWhfcmVnX2FkZHJfc2hvdyhj aGlwLCBzKTsKKwkJYnJlYWs7CisJY2FzZSBSVDE3MTFIX0RCR19EQVRBOgorCQlyZXQgPSBydDE3 MTFoX2RhdGFfc2hvdyhjaGlwLCBzKTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0ID0gLUVJ TlZBTDsKKwkJYnJlYWs7CisJfQorCisJbXV0ZXhfdW5sb2NrKCZjaGlwLT5kYmdvcHNfbG9jayk7 CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2RiZ19vcGVuKHN0cnVjdCBp bm9kZSAqaW5vZGUsIHN0cnVjdCBmaWxlICpmaWxlKQoreworCWlmIChmaWxlLT5mX21vZGUgJiBG TU9ERV9SRUFEKQorCQlyZXR1cm4gc2luZ2xlX29wZW4oZmlsZSwgcnQxNzExaF9kYmdfc2hvdywg aW5vZGUtPmlfcHJpdmF0ZSk7CisJZmlsZS0+cHJpdmF0ZV9kYXRhID0gaW5vZGUtPmlfcHJpdmF0 ZTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBnZXRfcGFyYW1ldGVycyhjaGFyICpidWYs IGxvbmcgaW50ICpwYXJhbTEsIGludCBudW1fb2ZfcGFyKQoreworCWNoYXIgKnRva2VuOworCWlu dCBiYXNlLCBjbnQ7CisKKwl0b2tlbiA9IHN0cnNlcCgmYnVmLCAiICIpOworCisJZm9yIChjbnQg PSAwOyBjbnQgPCBudW1fb2ZfcGFyOyBjbnQrKykgeworCQlpZiAodG9rZW4gIT0gTlVMTCkgewor CQkJaWYgKCh0b2tlblsxXSA9PSAneCcpIHx8ICh0b2tlblsxXSA9PSAnWCcpKQorCQkJCWJhc2Ug PSAxNjsKKwkJCWVsc2UKKwkJCQliYXNlID0gMTA7CisKKwkJCWlmIChrc3RydG91bCh0b2tlbiwg YmFzZSwgJnBhcmFtMVtjbnRdKSAhPSAwKQorCQkJCXJldHVybiAtRUlOVkFMOworCisJCQl0b2tl biA9IHN0cnNlcCgmYnVmLCAiICIpOworCQl9IGVsc2UKKwkJCXJldHVybiAtRUlOVkFMOworCX0K KwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBnZXRfZGF0YXMoY29uc3QgY2hhciAqYnVmLCBj b25zdCBpbnQgbGVuZ3RoLAorCXVuc2lnbmVkIGNoYXIgKmRhdGFfYnVmZmVyLCB1bnNpZ25lZCBj aGFyIGRhdGFfbGVuZ3RoKQoreworCWludCBpLCBwdHI7CisJbG9uZyBpbnQgdmFsdWU7CisJY2hh ciB0b2tlbls1XTsKKworCXRva2VuWzBdID0gJzAnOworCXRva2VuWzFdID0gJ3gnOworCXRva2Vu WzRdID0gMDsKKwlpZiAoYnVmWzBdICE9ICcwJyB8fCBidWZbMV0gIT0gJ3gnKQorCQlyZXR1cm4g LUVJTlZBTDsKKworCXB0ciA9IDI7CisJZm9yIChpID0gMDsgKGkgPCBkYXRhX2xlbmd0aCkgJiYg KHB0ciArIDIgPD0gbGVuZ3RoKTsgaSsrKSB7CisJCXRva2VuWzJdID0gYnVmW3B0cisrXTsKKwkJ dG9rZW5bM10gPSBidWZbcHRyKytdOworCQlwdHIrKzsKKwkJaWYgKGtzdHJ0b3VsKHRva2VuLCAx NiwgJnZhbHVlKSAhPSAwKQorCQkJcmV0dXJuIC1FSU5WQUw7CisJCWRhdGFfYnVmZmVyW2ldID0g dmFsdWU7CisJfQorCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfcmVnYWRkcjJp ZHgodWludDhfdCByZWdfYWRkcikKK3sKKwlpbnQgaSA9IDA7CisJc3RydWN0IHJlZ19kZXNjICpk ZXNjID0gTlVMTDsKKworCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKHJ0MTcxMWhfcmVnX2Rl c2MpOyBpKyspIHsKKwkJZGVzYyA9ICZydDE3MTFoX3JlZ19kZXNjW2ldOworCQlpZiAoZGVzYy0+ YWRkciA9PSByZWdfYWRkcikKKwkJCXJldHVybiBpOworCX0KKwlyZXR1cm4gLUVJTlZBTDsKK30K Kworc3RhdGljIHNzaXplX3QgcnQxNzExaF9kYmdfd3JpdGUoc3RydWN0IGZpbGUgKmZpbGUsIGNv bnN0IGNoYXIgX191c2VyICp1YnVmLAorCXNpemVfdCBjb3VudCwgbG9mZl90ICpwcG9zKQorewor CWludCByZXQgPSAwOworCXN0cnVjdCBydDE3MTFoX2RiZ19pbmZvICppbmZvID0KKwkJKHN0cnVj dCBydDE3MTFoX2RiZ19pbmZvICopZmlsZS0+cHJpdmF0ZV9kYXRhOworCXN0cnVjdCBydDE3MTFo X2NoaXAgKmNoaXAgPSBpbmZvLT5jaGlwOworCXN0cnVjdCByZWdfZGVzYyAqZGVzYyA9IE5VTEw7 CisJY2hhciBsYnVmWzEyOF07CisJbG9uZyBpbnQgcGFyYW1bNV07CisJdW5zaWduZWQgY2hhciBy ZWdfZGF0YVsyXSA9IHswfTsKKworCWlmIChjb3VudCA+IHNpemVvZihsYnVmKSAtIDEpCisJCXJl dHVybiAtRUZBVUxUOworCisJcmV0ID0gY29weV9mcm9tX3VzZXIobGJ1ZiwgdWJ1ZiwgY291bnQp OworCWlmIChyZXQpCisJCXJldHVybiAtRUZBVUxUOworCWxidWZbY291bnRdID0gJ1wwJzsKKwor CW11dGV4X2xvY2soJmNoaXAtPmRiZ29wc19sb2NrKTsKKwlzd2l0Y2ggKGluZm8tPmlkKSB7CisJ Y2FzZSBSVDE3MTFIX0RCR19SRUdfQUREUjoKKwkJcmV0ID0gZ2V0X3BhcmFtZXRlcnMobGJ1Ziwg cGFyYW0sIDEpOworCQlpZiAocmV0IDwgMCkgeworCQkJZGV2X2VycihjaGlwLT5kZXYsICIlcyBn ZXQgcGFyYW0gZmFpbFxuIiwgX19mdW5jX18pOworCQkJcmV0ID0gLUVJTlZBTDsKKwkJCWdvdG8g b3V0OworCQl9CisJCXJldCA9IHJ0MTcxMWhfcmVnYWRkcjJpZHgocGFyYW1bMF0pOworCQlpZiAo cmV0IDwgMCkgeworCQkJZGV2X2VycihjaGlwLT5kZXYsICIlcyBhZGRyMmlkeCBmYWlsXG4iLCBf X2Z1bmNfXyk7CisJCQlyZXQgPSAtRUlOVkFMOworCQkJZ290byBvdXQ7CisJCX0KKwkJY2hpcC0+ ZGJnX3JlZ2lkeCA9IHJldDsKKwkJYnJlYWs7CisJY2FzZSBSVDE3MTFIX0RCR19EQVRBOgorCQlk ZXNjID0gJnJ0MTcxMWhfcmVnX2Rlc2NbY2hpcC0+ZGJnX3JlZ2lkeF07CisJCWlmICgoZGVzYy0+ c2l6ZSAtIDEpICogMyArIDUgIT0gY291bnQpIHsKKwkJCWRldl9lcnIoY2hpcC0+ZGV2LCAiJXMg aW5jb3JyZWN0IGlucHV0IGxlbmd0aFxuIiwKKwkJCQlfX2Z1bmNfXyk7CisJCQlyZXQgPSAtRUlO VkFMOworCQkJZ290byBvdXQ7CisJCX0KKwkJcmV0ID0gZ2V0X2RhdGFzKChjaGFyICopdWJ1Ziwg Y291bnQsIHJlZ19kYXRhLCBkZXNjLT5zaXplKTsKKwkJaWYgKHJldCA8IDApIHsKKwkJCWRldl9l cnIoY2hpcC0+ZGV2LCAiJXMgZ2V0IGRhdGEgZmFpbFxuIiwgX19mdW5jX18pOworCQkJcmV0ID0g LUVJTlZBTDsKKwkJCWdvdG8gb3V0OworCQl9CisJCXJldCA9IHJ0MTcxMWhfcmVnX2Jsb2NrX3dy aXRlKGNoaXAsIGRlc2MtPmFkZHIsIGRlc2MtPnNpemUsCisJCQlyZWdfZGF0YSk7CisJCWJyZWFr OworCWRlZmF1bHQ6CisJCXJldCA9IC1FSU5WQUw7CisJCWJyZWFrOworCX0KKworb3V0OgorCW11 dGV4X3VubG9jaygmY2hpcC0+ZGJnb3BzX2xvY2spOworCXJldHVybiByZXQgPCAwID8gcmV0IDog Y291bnQ7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9kYmdfcmVsZWFzZShzdHJ1Y3QgaW5vZGUg Kmlub2RlLCBzdHJ1Y3QgZmlsZSAqZmlsZSkKK3sKKwlpZiAoZmlsZS0+Zl9tb2RlICYgRk1PREVf UkVBRCkKKwkJcmV0dXJuIHNpbmdsZV9yZWxlYXNlKGlub2RlLCBmaWxlKTsKKwlyZXR1cm4gMDsK K30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgcnQxNzExaF9kYmdfb3Bz ID0geworCS5vcGVuCQk9IHJ0MTcxMWhfZGJnX29wZW4sCisJLmxsc2VlawkJPSBzZXFfbHNlZWss CisJLnJlYWQJCT0gc2VxX3JlYWQsCisJLndyaXRlCQk9IHJ0MTcxMWhfZGJnX3dyaXRlLAorCS5y ZWxlYXNlCT0gcnQxNzExaF9kYmdfcmVsZWFzZSwKK307CisKKworc3RhdGljIGludCBydDE3MTFo X2RlYnVnZnNfaW5pdChzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWludCByZXQgPSAw LCBpID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9kYmdfaW5mbyAqaW5mbyA9IE5VTEw7CisJaW50IGxl biA9IDA7CisJY2hhciAqZGlybmFtZSA9IE5VTEw7CisKKwltdXRleF9pbml0KCZjaGlwLT5sb2di dWZmZXJfbG9jayk7CisJbXV0ZXhfaW5pdCgmY2hpcC0+ZGJnb3BzX2xvY2spOworCWxlbiA9IHN0 cmxlbihkZXZfbmFtZShjaGlwLT5kZXYpKTsKKwlkaXJuYW1lID0gZGV2bV9remFsbG9jKGNoaXAt PmRldiwgbGVuICsgOSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFkaXJuYW1lKQorCQlyZXR1cm4gLUVO T01FTTsKKwlzbnByaW50ZihkaXJuYW1lLCBsZW4gKyA5LCAicnQxNzExaC0lcyIsIGRldl9uYW1l KGNoaXAtPmRldikpOworCWlmICghY2hpcC0+ZGJnZGlyKSB7CisJCWNoaXAtPmRiZ2RpciA9IGRl YnVnZnNfY3JlYXRlX2RpcihkaXJuYW1lLCBOVUxMKTsKKwkJaWYgKCFjaGlwLT5kYmdkaXIpCisJ CQlyZXR1cm4gLUVOT01FTTsKKwl9CisKKwlmb3IgKGkgPSAwOyBpIDwgUlQxNzExSF9EQkdfTUFY OyBpKyspIHsKKwkJaW5mbyA9ICZjaGlwLT5kYmdfaW5mb1tpXTsKKwkJaW5mby0+Y2hpcCA9IGNo aXA7CisJCWluZm8tPmlkID0gaTsKKwkJY2hpcC0+ZGJnX2ZpbGVzW2ldID0gZGVidWdmc19jcmVh dGVfZmlsZSgKKwkJCXJ0MTcxMWhfZGJnX2ZpbGVuYW1lW2ldLCBTX0lGUkVHIHwgMDQ0NCwKKwkJ CWNoaXAtPmRiZ2RpciwgaW5mbywgJnJ0MTcxMWhfZGJnX29wcyk7CisJCWlmICghY2hpcC0+ZGJn X2ZpbGVzW2ldKSB7CisJCQlyZXQgPSAtRUlOVkFMOworCQkJZ290byBlcnI7CisJCX0KKwl9CisK KwlyZXR1cm4gMDsKK2VycjoKKwlkZWJ1Z2ZzX3JlbW92ZV9yZWN1cnNpdmUoY2hpcC0+ZGJnZGly KTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBydDE3MTFoX2RlYnVnZnNfZXhpdChz dHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWRlYnVnZnNfcmVtb3ZlX3JlY3Vyc2l2ZShj aGlwLT5kYmdkaXIpOworfQorCisjZWxzZQorCitzdGF0aWMgdm9pZCBydDE3MTFoX2xvZyhjb25z dCBzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwLCBjb25zdCBjaGFyICpmbXQsIC4uLikKK3sKK30K Kworc3RhdGljIGludCBydDE3MTFoX2RlYnVnZnNfaW5pdChjb25zdCBzdHJ1Y3QgcnQxNzExaF9j aGlwICpjaGlwKQoreworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBydDE3MTFoX2RlYnVn ZnNfZXhpdChjb25zdCBzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworfQorCisjZW5kaWYg LyogQ09ORklHX0RFQlVHX0ZTICovCisKK3N0YXRpYyBjb25zdCBjaGFyICogY29uc3QgdHlwZWNf Y2Nfc3RhdHVzX25hbWVbXSA9IHsKKwlbVFlQRUNfQ0NfT1BFTl0JCT0gIk9wZW4iLAorCVtUWVBF Q19DQ19SQV0JCT0gIlJhIiwKKwlbVFlQRUNfQ0NfUkRdCQk9ICJSZCIsCisJW1RZUEVDX0NDX1JQ X0RFRl0JPSAiUnAtZGVmIiwKKwlbVFlQRUNfQ0NfUlBfMV81XQk9ICJScC0xLjUiLAorCVtUWVBF Q19DQ19SUF8zXzBdCT0gIlJwLTMuMCIsCit9OworCitzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0 IGNjX3BvbGFyaXR5X25hbWVbXSA9IHsKKwlbVFlQRUNfUE9MQVJJVFlfQ0MxXQk9ICJQb2xhcml0 eV9DQzEiLAorCVtUWVBFQ19QT0xBUklUWV9DQzJdCT0gIlBvbGFyaXR5X0NDMiIsCit9OworCitz dGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IHRyYW5zbWl0X3R5cGVfbmFtZVtdID0geworCVtUQ1BD X1RYX1NPUF0JCQk9ICJTT1AiLAorCVtUQ1BDX1RYX1NPUF9QUklNRV0JCT0gIlNPUCciLAorCVtU Q1BDX1RYX1NPUF9QUklNRV9QUklNRV0JPSAiU09QJyciLAorCVtUQ1BDX1RYX1NPUF9ERUJVR19Q UklNRV0JPSAiREVCVUcnIiwKKwlbVENQQ19UWF9TT1BfREVCVUdfUFJJTUVfUFJJTUVdCT0gIkRF QlVHJyciLAorCVtUQ1BDX1RYX0hBUkRfUkVTRVRdCQk9ICJIQVJEX1JFU0VUIiwKKwlbVENQQ19U WF9DQUJMRV9SRVNFVF0JCT0gIkNBQkxFX1JFU0VUIiwKKwlbVENQQ19UWF9CSVNUX01PREVfMl0J CT0gIkJJU1RfTU9ERV8yIiwKK307CisKK3N0YXRpYyBjb25zdCBjaGFyICogY29uc3QgdHlwZWNf cm9sZV9uYW1lW10gPSB7CisJW1RZUEVDX1NJTktdCQk9ICJTaW5rIiwKKwlbVFlQRUNfU09VUkNF XQkJPSAiU291cmNlIiwKK307CisKK3N0YXRpYyBjb25zdCBjaGFyICogY29uc3QgdHlwZWNfZGF0 YV9yb2xlX25hbWVbXSA9IHsKKwlbVFlQRUNfREVWSUNFXQkJPSAiRGV2aWNlIiwKKwlbVFlQRUNf SE9TVF0JCT0gIkhvc3QiLAorfTsKKworc3RhdGljIGNvbnN0IGVudW0gdHlwZWNfY2NfcHVsbCB0 eXBlY19jY19zdGF0dXNfcHVsbF9tYXBwaW5nW10gPSB7CisJW1RZUEVDX0NDX09QRU5dID0gVFlQ RUNfQ0NfUFVMTF9PUEVOLAorCVtUWVBFQ19DQ19SQV0gPSBUWVBFQ19DQ19QVUxMX1JBLAorCVtU WVBFQ19DQ19SRF0gPSBUWVBFQ19DQ19QVUxMX1JELAorCVtUWVBFQ19DQ19SUF9ERUZdID0gVFlQ RUNfQ0NfUFVMTF9SUF9ERUYsCisJW1RZUEVDX0NDX1JQXzFfNV0gPSBUWVBFQ19DQ19QVUxMX1JQ XzFfNSwKKwlbVFlQRUNfQ0NfUlBfM18wXSA9IFRZUEVDX0NDX1BVTExfUlBfM18wLAorfTsKKwor c3RhdGljIGlubGluZSBlbnVtIHR5cGVjX2NjX3B1bGwgcnQxNzExaF9jY19zdGF0dXMycHVsbChl bnVtIHR5cGVjX2NjX3N0YXR1cyBjYykKK3sKKwlyZXR1cm4gdHlwZWNfY2Nfc3RhdHVzX3B1bGxf bWFwcGluZ1tjY107Cit9CisKKyNkZWZpbmUgUERPX0ZJWEVEX0ZMQUdTIFwKKwkoUERPX0ZJWEVE X0RVQUxfUk9MRSB8IFBET19GSVhFRF9EQVRBX1NXQVAgfCBQRE9fRklYRURfVVNCX0NPTU0pCisK K3N0YXRpYyBjb25zdCB1MzIgc3JjX3Bkb1tdID0geworCVBET19GSVhFRCg1MDAwLCA1MDAsIFBE T19GSVhFRF9GTEFHUyksCit9OworCitzdGF0aWMgY29uc3QgdTMyIHNua19wZG9bXSA9IHsKKwlQ RE9fRklYRUQoNTAwMCwgNTAwLCBQRE9fRklYRURfRkxBR1MpLAorfTsKKworc3RhdGljIGNvbnN0 IHN0cnVjdCB0Y3BjX2NvbmZpZyBydDE3MTFoX3RjcGNfY29uZmlnID0geworCS5zcmNfcGRvID0g c3JjX3BkbywKKwkubnJfc3JjX3BkbyA9IEFSUkFZX1NJWkUoc3JjX3BkbyksCisJLnNua19wZG8g PSBzbmtfcGRvLAorCS5ucl9zbmtfcGRvID0gQVJSQVlfU0laRShzbmtfcGRvKSwKKwkubWF4X3Nu a19tdiA9IDUwMDAsCisJLm1heF9zbmtfbWEgPSAzMDAwLAorCS5tYXhfc25rX213ID0gMTUwMDAs CisJLm9wZXJhdGluZ19zbmtfbXcgPSAyNTAwLAorCS50eXBlID0gVFlQRUNfUE9SVF9EUlAsCisJ LmRlZmF1bHRfcm9sZSA9IFRZUEVDX1NJTkssCisJLmFsdF9tb2RlcyA9IE5VTEwsCit9OworCisj ZGVmaW5lIFJUMTcxMUhfUkVTVU1FX1JFVFJZIDEwCisjZGVmaW5lIFJUMTcxMUhfUkVTVU1FX1JF VFJZX1NMRUVQIDUwCisKK3N0YXRpYyBpbmxpbmUgYm9vbCBydDE3MTFoX2lzX3N1c3BlbmRlZChz dHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWludCByZXRyeV9jbnQgPSAwOworCisJZm9y IChyZXRyeV9jbnQgPSAwOyByZXRyeV9jbnQgPCBSVDE3MTFIX1JFU1VNRV9SRVRSWTsgcmV0cnlf Y250KyspIHsKKwkJaWYgKGF0b21pY19yZWFkKCZjaGlwLT5wbV9zdXNwZW5kKSkgeworCQkJcnQx NzExaF9sb2coY2hpcCwgIiVzIHJldHJ5ICVkLyVkXG4iLCBfX2Z1bmNfXywKKwkJCQlyZXRyeV9j bnQgKyAxLCBSVDE3MTFIX1JFU1VNRV9SRVRSWSk7CisJCQltc2xlZXAoUlQxNzExSF9SRVNVTUVf UkVUUllfU0xFRVApOworCQl9IGVsc2UKKwkJCXJldHVybiBmYWxzZTsKKwl9CisKKwlyZXR1cm4g dHJ1ZTsKK30KKworc3RhdGljIGludCBydDE3MTFoX3JlZ19yZWFkKHN0cnVjdCBydDE3MTFoX2No aXAgKmNoaXAsIHVpbnQ4X3QgcmVnLAorCXVpbnQ4X3QgKmRhdGEpCit7CisJaW50IHJldCA9IDA7 CisKKwlhdG9taWNfc2V0KCZjaGlwLT5pMmNfYnVzeSwgMSk7CisJaWYgKHJ0MTcxMWhfaXNfc3Vz cGVuZGVkKGNoaXApKSB7CisJCWF0b21pY19zZXQoJmNoaXAtPmkyY19idXN5LCAwKTsKKwkJcmV0 dXJuIC1FVElNRURPVVQ7CisJfQorCisJcmV0ID0gaTJjX3NtYnVzX3JlYWRfaTJjX2Jsb2NrX2Rh dGEoY2hpcC0+aTJjLCByZWcsIDEsIGRhdGEpOworCWlmIChyZXQgPCAwKQorCQlydDE3MTFoX2xv ZyhjaGlwLCAiJXMgcmVnJTAyWCBmYWlsKCVkKVxuIiwgX19mdW5jX18sIHJlZywgcmV0KTsKKwlh dG9taWNfc2V0KCZjaGlwLT5pMmNfYnVzeSwgMCk7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0 aWMgaW50IHJ0MTcxMWhfcmVnX3dyaXRlKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAsIHVpbnQ4 X3QgcmVnLAorCXVpbnQ4X3QgZGF0YSkKK3sKKwlpbnQgcmV0ID0gMDsKKworCWF0b21pY19zZXQo JmNoaXAtPmkyY19idXN5LCAxKTsKKwlpZiAocnQxNzExaF9pc19zdXNwZW5kZWQoY2hpcCkpIHsK KwkJYXRvbWljX3NldCgmY2hpcC0+aTJjX2J1c3ksIDApOworCQlyZXR1cm4gLUVUSU1FRE9VVDsK Kwl9CisKKwlyZXQgPSBpMmNfc21idXNfd3JpdGVfaTJjX2Jsb2NrX2RhdGEoY2hpcC0+aTJjLCBy ZWcsIDEsICZkYXRhKTsKKwlpZiAocmV0IDwgMCkKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIHJl ZyUwMlggPSAlMDJYIGZhaWwoJWQpXG4iLCBfX2Z1bmNfXywgcmVnLAorCQkJZGF0YSwgcmV0KTsK KwlhdG9taWNfc2V0KCZjaGlwLT5pMmNfYnVzeSwgMCk7CisKKwlyZXR1cm4gcmV0OworfQorCitz dGF0aWMgaW50IHJ0MTcxMWhfcmVnX2Jsb2NrX3dyaXRlKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNo aXAsIHVpbnQ4X3QgcmVnLAorCWludCBsZW4sIGNvbnN0IHVpbnQ4X3QgKmRhdGEpCit7CisJaW50 IHJldCA9IDA7CisKKwlhdG9taWNfc2V0KCZjaGlwLT5pMmNfYnVzeSwgMSk7CisJaWYgKHJ0MTcx MWhfaXNfc3VzcGVuZGVkKGNoaXApKSB7CisJCWF0b21pY19zZXQoJmNoaXAtPmkyY19idXN5LCAw KTsKKwkJcmV0dXJuIC1FVElNRURPVVQ7CisJfQorCisJcmV0ID0gaTJjX3NtYnVzX3dyaXRlX2ky Y19ibG9ja19kYXRhKGNoaXAtPmkyYywgcmVnLCBsZW4sIGRhdGEpOworCWlmIChyZXQgPCAwKQor CQlydDE3MTFoX2xvZyhjaGlwLCAiJXMgcmVnJTAyWCwgbGVuID0gJWQgZmFpbCglZClcbiIsIF9f ZnVuY19fLAorCQkJcmVnLCBsZW4sIHJldCk7CisJYXRvbWljX3NldCgmY2hpcC0+aTJjX2J1c3ks IDApOworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBydDE3MTFoX3JlZ19ibG9ja19y ZWFkKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAsIHVpbnQ4X3QgcmVnLAorCWludCBsZW4sIHVp bnQ4X3QgKmRhdGEpCit7CisJaW50IHJldCA9IDA7CisKKwlhdG9taWNfc2V0KCZjaGlwLT5pMmNf YnVzeSwgMSk7CisJaWYgKHJ0MTcxMWhfaXNfc3VzcGVuZGVkKGNoaXApKSB7CisJCWF0b21pY19z ZXQoJmNoaXAtPmkyY19idXN5LCAwKTsKKwkJcmV0dXJuIC1FVElNRURPVVQ7CisJfQorCisJcmV0 ID0gaTJjX3NtYnVzX3JlYWRfaTJjX2Jsb2NrX2RhdGEoY2hpcC0+aTJjLCByZWcsIGxlbiwgZGF0 YSk7CisJaWYgKHJldCA8IDApCisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyByZWclMDJYLCBsZW4g PSAlZCBmYWlsKCVkKVxuIiwgX19mdW5jX18sCisJCQlyZWcsIGxlbiwgcmV0KTsKKwlhdG9taWNf c2V0KCZjaGlwLT5pMmNfYnVzeSwgMCk7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW5s aW5lIGludCBydDE3MTFoX3JlZ193cml0ZV93b3JkKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAs IHVpbnQ4X3QgcmVnLAorCXVpbnQxNl90IGRhdGEpCit7CisJZGF0YSA9IGNwdV90b19sZTE2KGRh dGEpOworCXJldHVybiBydDE3MTFoX3JlZ19ibG9ja193cml0ZShjaGlwLCByZWcsIDIsICh1aW50 OF90ICopJmRhdGEpOworfQorCitzdGF0aWMgaW5saW5lIGludCBydDE3MTFoX3JlZ19yZWFkX3dv cmQoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDhfdCByZWcsCisJdWludDE2X3QgKmRh dGEpCit7CisJaW50IHJldCA9IDA7CisKKwlyZXQgPSBydDE3MTFoX3JlZ19ibG9ja19yZWFkKGNo aXAsIHJlZywgMiwgKHVpbnQ4X3QgKilkYXRhKTsKKwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJl dDsKKwkqZGF0YSA9IGxlMTZfdG9fY3B1KCpkYXRhKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGlj IGludCBydDE3MTFoX3BzeV9nZXRfcHJvcGVydHkoc3RydWN0IHBvd2VyX3N1cHBseSAqcHN5LAor CWVudW0gcG93ZXJfc3VwcGx5X3Byb3BlcnR5IHBzcCwgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2 YWwgKnZhbCkKK3sKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gcG93ZXJfc3VwcGx5X2dl dF9kcnZkYXRhKHBzeSk7CisKKwlzd2l0Y2ggKHBzcCkgeworCWNhc2UgUE9XRVJfU1VQUExZX1BS T1BfT05MSU5FOgorCQl2YWwtPmludHZhbCA9IGNoaXAtPmNoYXJnZV9vbjsKKwkJYnJlYWs7CisJ Y2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdFX05PVzoKKwkJdmFsLT5pbnR2YWwgPSBjaGlw LT5zdXBwbHlfdm9sdGFnZSAqIDEwMDA7IC8qIG1WIC0+IMK1ViAqLworCQlicmVhazsKKwljYXNl IFBPV0VSX1NVUFBMWV9QUk9QX0NVUlJFTlRfTUFYOgorCQl2YWwtPmludHZhbCA9IGNoaXAtPmN1 cnJlbnRfbGltaXQgKiAxMDAwOyAvKiBtQSAtPiDCtUEgKi8KKwkJYnJlYWs7CisJZGVmYXVsdDoK KwkJcmV0dXJuIC1FTk9EQVRBOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgZW51bSBw b3dlcl9zdXBwbHlfcHJvcGVydHkgcnQxNzExaF9wc3lfcHJvcGVydGllc1tdID0geworCVBPV0VS X1NVUFBMWV9QUk9QX09OTElORSwKKwlQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdFX05PVywKKwlQ T1dFUl9TVVBQTFlfUFJPUF9DVVJSRU5UX01BWCwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg cG93ZXJfc3VwcGx5X2Rlc2MgcnQxNzExaF9wc3lfZGVzYyA9IHsKKwkubmFtZQkJPSAicnQxNzEx aC10eXBlYy1zb3VyY2UiLAorCS50eXBlCQk9IFBPV0VSX1NVUFBMWV9UWVBFX1VTQl9UWVBFX0Ms CisJLnByb3BlcnRpZXMJPSBydDE3MTFoX3BzeV9wcm9wZXJ0aWVzLAorCS5udW1fcHJvcGVydGll cwk9IEFSUkFZX1NJWkUocnQxNzExaF9wc3lfcHJvcGVydGllcyksCisJLmdldF9wcm9wZXJ0eQk9 IHJ0MTcxMWhfcHN5X2dldF9wcm9wZXJ0eSwKK307CisKK3N0YXRpYyBpbmxpbmUgaW50IHJ0MTcx MWhfc29mdHdhcmVfcmVzZXQoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlpbnQgcmV0 ID0gMDsKKworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX1NXUkVT RVQsIDB4MDEpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJdXNsZWVwX3Jhbmdl KDEwMDAsIDIwMDApOworCXJldHVybiAwOworfQorCitzdGF0aWMgaW5saW5lIGludCBydDE3MTFo X2NvbW1hbmQoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDhfdCBjbWQpCit7CisJcmV0 dXJuIHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX0NPTU1BTkQsIGNtZCk7Cit9 CisKK3N0YXRpYyBpbmxpbmUgaW50IHJ0MTcxMWhfaW5pdF9jY19wYXJhbXMoc3RydWN0IHJ0MTcx MWhfY2hpcCAqY2hpcCwKKwljb25zdCBlbnVtIHR5cGVjX2NjX3N0YXR1cyAqY2MpCit7CisJaW50 IHJldCA9IDA7CisJdWludDhfdCBlbiA9IDAsIHNlbCA9IDA7CisKKwlpZiAoKmNjID09IFRZUEVD X0NDX1JQX0RFRikgeyAvKiAwLjU1ICovCisJCWVuID0gMDsKKwkJc2VsID0gMHg4MTsKKwl9IGVs c2UgaWYgKGNoaXAtPmRpZCA+PSBSVDE3MTFIX0RJRF9EKSB7IC8qIDAuMzUgJiAwLjc1ICovCisJ CWVuID0gMTsKKwkJc2VsID0gMHg4MTsKKwl9IGVsc2UgeyAvKiAwLjQgJiAwLjcgKi8KKwkJZW4g PSAxOworCQlzZWwgPSAweDgwOworCX0KKworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAs IFJUMTcxMUhfUkVHX0JNQ0lPX1JYRFpFTiwgZW4pOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4g cmV0OworCisJcmV0dXJuIHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX0JNQ0lP X1JYRFpTRUwsIHNlbCk7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9hbGVydF9zdGF0dXNfY2xl YXIoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDMyX3QgbWFzaykKK3sKKwlpbnQgcmV0 ID0gMDsKKwl1aW50MTZfdCBtYXNrX3QxID0gMDsKKwl1aW50OF90IG1hc2tfdDIgPSAwOworCisJ LyogV3JpdGUgMSBjbGVhciAqLworCW1hc2tfdDEgPSAodWludDE2X3QpbWFzazsKKwlyZXQgPSBy dDE3MTFoX3JlZ193cml0ZV93b3JkKGNoaXAsIFJUMTcxMUhfUkVHX0FMRVJULCBtYXNrX3QxKTsK KwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKworCW1hc2tfdDIgPSBtYXNrID4+IDE2Owor CWlmIChtYXNrX3QyKSB7CisJCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhf UkVHX1JUX0lOVCwgbWFza190Mik7CisJCWlmIChyZXQgPCAwKQorCQkJcmV0dXJuIHJldDsKKwl9 CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2luaXRfYWxlcnRfbWFzayhz dHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCXVpbnQxNl90IG1hc2sgPSAwOworCisJbWFz ayA9IFJUMTcxMUhfUkVHX0FMRVJUX0NDX1NUQVRVUyB8IFJUMTcxMUhfUkVHX0FMRVJUX1BPV0VS X1NUQVRVUzsKKworCW1hc2sgfD0gUlQxNzExSF9SRUdfQUxFUlRfVFhfU1VDQ0VTUyB8IFJUMTcx MUhfUkVHX0FMRVJUX1RYX0RJU0NBUkRFRAorCQl8IFJUMTcxMUhfUkVHX0FMRVJUX1RYX0ZBSUxF RCB8IFJUMTcxMUhfUkVHX0FMRVJUX1JYX0hBUkRfUlNUCisJCXwgUlQxNzExSF9SRUdfQUxFUlRf UlhfU1RBVFVTIHwgUlQxNzExSF9SRUdfQUxFUlRfUlhfQlVGX09WRjsKKworCW1hc2sgfD0gUlQx NzExSF9SRUdfQUxFUlRfRkFVTFQ7CisKKwlyZXR1cm4gcnQxNzExaF9yZWdfd3JpdGVfd29yZChj aGlwLCBSVDE3MTFIX1JFR19BTEVSVF9NQVNLLCBtYXNrKTsKK30KKworc3RhdGljIGludCBydDE3 MTFoX2luaXRfcG93ZXJfc3RhdHVzX21hc2soc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sK Kwl1aW50OF90IG1hc2sgPSBSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVNfVkJVU19QUkVTOworCisJ cmV0dXJuIHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX1BPV0VSX1NUQVRVU19N QVNLLCBtYXNrKTsKK30KKworc3RhdGljIGludCBydDE3MTFoX2luaXRfZmF1bHRfbWFzayhzdHJ1 Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWNvbnN0IHVpbnQ4X3QgbWFzayA9IFJUMTcxMUhf UkVHX0ZBVUxUX1NUQVRVU19WQ09OTl9PVgorCQl8IFJUMTcxMUhfUkVHX0ZBVUxUX1NUQVRVU19W Q09OTl9PQzsKKworCXJldHVybiBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19G QVVMVF9TVEFUVVNfTUFTSywgbWFzayk7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9pbml0X3J0 X21hc2soc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwl1aW50OF90IHJ0X21hc2sgPSBS VDE3MTFIX1JFR19NX1ZCVVNfODA7CisKKwlpZiAoY2hpcC0+ZGlkIDwgUlQxNzExSF9ESURfRCkK KwkJcnRfbWFzayB8PSAoUlQxNzExSF9SRUdfTV9XQUtFVVAgfCBSVDE3MTFIX1JFR19NX1JBX0RF VEFDSCk7CisKKwlyZXR1cm4gcnQxNzExaF9yZWdfd3JpdGUoY2hpcCwgUlQxNzExSF9SRUdfUlRf TUFTSywgcnRfbWFzayk7Cit9CisKKyNkZWZpbmUgUlQxNzExSF9XQUtFVVBfV09SS19USU1FCSgx MDAwKQorc3RhdGljIGVudW0gYWxhcm10aW1lcl9yZXN0YXJ0CisJcnQxNzExaF9hbGFybV93YWtl dXBfaGFuZGxlcihzdHJ1Y3QgYWxhcm0gKmFsYXJtLCBrdGltZV90IG5vdykKK3sKKwlzdHJ1Y3Qg cnQxNzExaF9jaGlwICpjaGlwID0KKwkJY29udGFpbmVyX29mKGFsYXJtLCBzdHJ1Y3QgcnQxNzEx aF9jaGlwLCB3YWtldXBfdGltZXIpOworCisJcnQxNzExaF9sb2coY2hpcCwgIiVzXG4iLCBfX2Z1 bmNfXyk7CisJcG1fd2FrZXVwX2V2ZW50KGNoaXAtPmRldiwgUlQxNzExSF9XQUtFVVBfV09SS19U SU1FKTsKKwlzY2hlZHVsZV9kZWxheWVkX3dvcmsoJmNoaXAtPndha2V1cF93b3JrLCAwKTsKKwly ZXR1cm4gQUxBUk1USU1FUl9OT1JFU1RBUlQ7Cit9CisKK3N0YXRpYyB2b2lkIHJ0MTcxMWhfZW5h YmxlX3dha2V1cF90aW1lcihzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwLCBib29sIGVuKQorewor CWludCB0b3V0ID0gMzAwOyAvKiBzICovCisKKwlydDE3MTFoX2xvZyhjaGlwLCAiJXMgJWRcbiIs IF9fZnVuY19fLCBlbik7CisJaWYgKGVuKSB7CisJCWlmICghY2hpcC0+d2FrZXVwX29uY2UpCisJ CQl0b3V0ID0gKGNoaXAtPmxvd19ycF9kdXR5X2NudGRvd24pID8gNSA6IDIwOworCQlhbGFybV9z dGFydF9yZWxhdGl2ZSgmY2hpcC0+d2FrZXVwX3RpbWVyLCBrdGltZV9zZXQodG91dCwgMCkpOwor CX0gZWxzZQorCQlhbGFybV9jYW5jZWwoJmNoaXAtPndha2V1cF90aW1lcik7Cit9CisKK3N0YXRp YyBpbmxpbmUgYm9vbCBydDE3MTFoX2lzX2NjX29wZW4oc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hp cCkKK3sKKwlpZiAoIWNoaXAtPmRycF90b2dnbGluZyAmJiBjaGlwLT5jYzEgPT0gVFlQRUNfQ0Nf T1BFTiAmJgorCQljaGlwLT5jYzIgPT0gVFlQRUNfQ0NfT1BFTikKKwkJcmV0dXJuIHRydWU7CisJ cmV0dXJuIGZhbHNlOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfc2V0X2xvd19ycF9kdXR5KHN0 cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAsIGJvb2wgbG93X3JwKQoreworCXVpbnQxNl90IGR1dHkg PSBsb3dfcnAgPyBSVDE3MTFIX0xPV19SUF9EVVRZIDogUlQxNzExSF9OT1JNQUxfUlBfRFVUWTsK KworCXJldHVybiBydDE3MTFoX3JlZ193cml0ZV93b3JkKGNoaXAsIFJUMTcxMUhfUkVHX0RSUF9E VVRZX0NUUkwsIGR1dHkpOworfQorCisvKgorICogcnQxNzExaF9jaGVja19mYWxzZV9yYV9kZXRh Y2gKKyAqCisgKiBDaGVjayBzaW5nbGUgUmEgcmVzaXN0YW5jZSAoZU1hcmspIGV4aXN0cyBvciBu b3Qgd2hlbgorICoJMSkgcmEgZGV0YWNoIGludCB0cmlnZ2VyZWQKKyAqCTIpIHdha2V1cCB0aW1l ciB0cmlnZ2VyZWQKKyAqCisgKiBJZiByZWVudGVyaW5nIGxvdy1wb3dlciBtb2RlIGFuZCBlTWFy ayBzdGlsbCBleGlzdHMsCisgKiBpdCBtYXkgY2F1c2UgYW4gaW5maW5pdGUgbG9vcC4KKyAqCisg KiBJZiBjYyBzdGF0dXMgaXMgYm90aCBvcGVuLCByZXR1cm4gdHJ1ZTsgb3RoZXJ3aXNlIHJldHVy biBmYWxzZQorICovCitzdGF0aWMgaW50IF9fdGNwbV9nZXRfY2Moc3RydWN0IHJ0MTcxMWhfY2hp cCAqY2hpcCk7CitzdGF0aWMgaW50IF9fdGNwbV9zZXRfY2Moc3RydWN0IHJ0MTcxMWhfY2hpcCAq Y2hpcCwgZW51bSB0eXBlY19jY19zdGF0dXMgY2MpOworc3RhdGljIGlubGluZSBpbnQgX190Y3Bt X3N0YXJ0X2RycF90b2dnbGluZyhzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKTsKK3N0YXRpYyBp bmxpbmUgYm9vbCBydDE3MTFoX2NoZWNrX2ZhbHNlX3JhX2RldGFjaChzdHJ1Y3QgcnQxNzExaF9j aGlwICpjaGlwKQoreworCWJvb2wgZHJwID0gKGNoaXAtPnRjcGNfY2ZnLnR5cGUgPT0gVFlQRUNf UE9SVF9EUlApID8gdHJ1ZSA6IGZhbHNlOworCisJcnQxNzExaF9sb2coY2hpcCwgIiVzXG4iLCBf X2Z1bmNfXyk7CisKKwkvKgorCSAqIElmIHRoZSBEVVQgaXMgRFJQIGFuZCBjdXJyZW50IENDIHN0 YXR1cyBoYXMgc3RvcHBlZCB0b2dnbGluZywKKwkgKiBsZXQgY2NfaGFuZGxlciB0byBoYW5kbGUg aXQgbGF0ZXIuCisJICoKKwkgKiBJZiBDQyBpcyB0b2dnbGluZywgZm9yY2UgQ0MgdG8gcHJlc2Vu dCBScAorCSAqLworCWlmIChkcnApIHsKKwkJX190Y3BtX2dldF9jYyhjaGlwKTsKKworCQlpZiAo IWNoaXAtPmRycF90b2dnbGluZykgeworCQkJcnQxNzExaF9sb2coY2hpcCwgIiVzIDEoJXMsICVz KVxuIiwgX19mdW5jX18sCisJCQkJdHlwZWNfY2Nfc3RhdHVzX25hbWVbY2hpcC0+Y2MxXSwKKwkJ CQl0eXBlY19jY19zdGF0dXNfbmFtZVtjaGlwLT5jYzJdKTsKKwkJCXJldHVybiB0cnVlOworCQl9 CisJCV9fdGNwbV9zZXRfY2MoY2hpcCwgVFlQRUNfQ0NfUlBfREVGKTsKKwkJdXNsZWVwX3Jhbmdl KDEwMDAsIDIwMDApOworCX0KKworCS8qCisJICogQ2hlY2sgQ0Mgc3RhdHVzCisJICogUmQgKGRl dmljZSkgLT4gbGV0IGNjX2hhbmRsZXIgdG8gaGFuZGxlIGl0IGxhdGVyCisJICogZU1hcmsgb25s eSAtPiBSZXNjaGVkdWxlIHdha2V1cCB0aW1lcgorCSAqIE9wZW4gLT4gKHRydWUgY29uZGl0aW9u KQorCSAqIFJlYWQgdG8gcmVlbnRlciBsb3ctcG93ZXIgbW9kZS4KKwkgKiBJZiB3ZSByZXBlYXRl ZGx5IGVudGVyIHRoaXMgc2l0dWF0aW9uLAorCSAqIGl0IHdpbGwgdHJpZ2dlciBsb3cgcnAgZHV0 eSBwcm90ZWN0aW9uCisJICovCisJX190Y3BtX2dldF9jYyhjaGlwKTsKKwlpZiAocnQxNzExaF9p c19jY19vcGVuKGNoaXApKQorCQljaGlwLT5jYWJsZV9vbmx5ID0gZmFsc2U7CisJZWxzZSBpZiAo KGNoaXAtPmNjMSArIGNoaXAtPmNjMikgPT0gVFlQRUNfQ0NfUkEpIHsKKwkJY2hpcC0+Y2FibGVf b25seSA9IHRydWU7CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyAyKGVtYXJrKVxuIiwgX19mdW5j X18pOworCX0gZWxzZSB7CisJCWNoaXAtPmNhYmxlX29ubHkgPSBmYWxzZTsKKwkJcnQxNzExaF9s b2coY2hpcCwgIiVzIDMoJXMgJXMpXG4iLCBfX2Z1bmNfXywKKwkJCXR5cGVjX2NjX3N0YXR1c19u YW1lW2NoaXAtPmNjMV0sCisJCQl0eXBlY19jY19zdGF0dXNfbmFtZVtjaGlwLT5jYzJdKTsKKwkJ cmV0dXJuIHRydWU7CisJfQorCisJaWYgKGNoaXAtPmNhYmxlX29ubHkpCisJCXJ0MTcxMWhfZW5h YmxlX3dha2V1cF90aW1lcihjaGlwLCB0cnVlKTsKKwllbHNlIHsKKwkJaWYgKGNoaXAtPmxvd19y cF9kdXR5X2NudGRvd24pCisJCQlydDE3MTFoX3NldF9sb3dfcnBfZHV0eShjaGlwLCB0cnVlKTsK KwkJZWxzZSB7CisJCQljaGlwLT53YWtldXBfb25jZSA9IGZhbHNlOworCQkJY2hpcC0+bG93X3Jw X2R1dHlfY250ZG93biA9IHRydWU7CisJCX0KKwl9CisKKwkvKiBJZiBEVVAgaXMgRFJQLCBmb3Jj ZSBDQyB0byB0b2dnbGUgYWdhaW4gKi8KKwlpZiAoZHJwKSB7CisJCV9fdGNwbV9zdGFydF9kcnBf dG9nZ2xpbmcoY2hpcCk7CisJCXJ0MTcxMWhfYWxlcnRfc3RhdHVzX2NsZWFyKGNoaXAsCisJCQlS VDE3MTFIX1JFR19BTEVSVF9FWFRfUkFfREVUQUNIKTsKKwl9CisKKwlyZXR1cm4gY2hpcC0+Y2Fi bGVfb25seTsKK30KKworc3RhdGljIGludCBydDE3MTFoX3NldF9sb3dfcG93ZXJfbW9kZShzdHJ1 Y3QgcnQxNzExaF9jaGlwICpjaGlwLCBib29sIGVuLAorCWVudW0gdHlwZWNfY2NfcHVsbCBwdWxs KQoreworCXVpbnQ4X3QgZGF0YSA9IDA7CisKKwlydDE3MTFoX2xvZyhjaGlwLCAiJXMgJWRcbiIs IF9fZnVuY19fLCBlbik7CisKKwlpZiAoZW4pIHsKKwkJZGF0YSA9IFJUMTcxMUhfUkVHX0JNQ0lP X0xQRU47CisKKwkJaWYgKHB1bGwgJiBUWVBFQ19DQ19QVUxMX1JQKQorCQkJZGF0YSB8PSBSVDE3 MTFIX1JFR19CTUNJT19MUFJQUkQ7CisJfSBlbHNlCisJCWRhdGEgPSBSVDE3MTFIX1JFR19CTUNJ T19CR19FTiB8CisJCQlSVDE3MTFIX1JFR19WQlVTX0RFVF9FTiB8IFJUMTcxMUhfUkVHX0JNQ0lP X09TQ19FTjsKKworCXJldHVybiBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19C TUNfQ1RSTCwgZGF0YSk7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9lbnRlcl9scG1fYWdhaW4o c3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlib29sIGNoZWNrX3JhID0gKGNoaXAtPmxw bSkgfHwgKGNoaXAtPmNhYmxlX29ubHkpOworCisJaWYgKGNoZWNrX3JhICYmIHJ0MTcxMWhfY2hl Y2tfZmFsc2VfcmFfZGV0YWNoKGNoaXApKQorCQlyZXR1cm4gMDsKKworCXJ0MTcxMWhfbG9nKGNo aXAsICIlcyByZXRyeSBscG1cbiIsIF9fZnVuY19fKTsKKwljaGlwLT5scG0gPSB0cnVlOworCisJ cnQxNzExaF9zZXRfbG93X3Bvd2VyX21vZGUoY2hpcCwgdHJ1ZSwKKwkJKGNoaXAtPnB3cl9yb2xl ICE9IFRZUEVDX1NPVVJDRSkgPworCQlUWVBFQ19DQ19QVUxMX0RSUCA6IFRZUEVDX0NDX1BVTExf UlApOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIHJ0MTcxMWhfd2FrZXVwX3dvcmso c3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQoreworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAg PQorCQljb250YWluZXJfb2Yod29yaywgc3RydWN0IHJ0MTcxMWhfY2hpcCwgd2FrZXVwX3dvcmsu d29yayk7CisKKwltdXRleF9sb2NrKCZjaGlwLT53YWtldXBfbG9jayk7CisJbXV0ZXhfbG9jaygm Y2hpcC0+bG9jayk7CisJcnQxNzExaF9sb2coY2hpcCwgIiVzXG4iLCBfX2Z1bmNfXyk7CisJY2hp cC0+d2FrZXVwX29uY2UgPSB0cnVlOworCXJ0MTcxMWhfZW50ZXJfbHBtX2FnYWluKGNoaXApOwor CW11dGV4X3VubG9jaygmY2hpcC0+bG9jayk7CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT53YWtldXBf bG9jayk7CisJcG1fcmVsYXgoY2hpcC0+ZGV2KTsKK30KKworc3RhdGljIGlubGluZSBpbnQgcnQx NzExaF90cnlfbG93X3Bvd2VyX21vZGUoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwly ZXR1cm4gcnQxNzExaF9zZXRfbG93X3Bvd2VyX21vZGUoY2hpcCwgdHJ1ZSwgY2hpcC0+bHBtX3B1 bGwpOworfQorCitzdGF0aWMgaW5saW5lIGludCBydDE3MTFoX2VudGVyX2xvd19wb3dlcl9tb2Rl KHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXApCit7CisJcmV0dXJuIHJ0MTcxMWhfdHJ5X2xvd19w b3dlcl9tb2RlKGNoaXApOworfQorCitzdGF0aWMgaW5saW5lIGludCBydDE3MTFoX2VuYWJsZV9s b3dfcG93ZXJfbW9kZShzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwLAorCWVudW0gdHlwZWNfY2Nf cHVsbCBwdWxsKQoreworCWlmIChjaGlwLT5jYWJsZV9vbmx5KSB7CisJCXJ0MTcxMWhfbG9nKGNo aXAsICIlcyByYSBvbmx5XG4iLCBfX2Z1bmNfXyk7CisJCXJ0MTcxMWhfZW5hYmxlX3dha2V1cF90 aW1lcihjaGlwLCB0cnVlKTsKKwkJcmV0dXJuIDA7CisJfQorCisJaWYgKGNoaXAtPmxwbSAhPSB0 cnVlKSB7CisJCWNoaXAtPmxwbSA9IHRydWU7CisJCWNoaXAtPmxwbV9wdWxsID0gcHVsbDsKKwkJ cmV0dXJuIHJ0MTcxMWhfZW50ZXJfbG93X3Bvd2VyX21vZGUoY2hpcCk7CisJfQorCisJcmV0dXJu IDA7Cit9CisKK3N0YXRpYyBpbmxpbmUgaW50IHJ0MTcxMWhfZGlzYWJsZV9sb3dfcG93ZXJfbW9k ZShzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWludCByZXQgPSAwOworCisJaWYgKGNo aXAtPmxwbSAhPSBmYWxzZSkgeworCQljaGlwLT5scG0gPSBmYWxzZTsKKwkJcnQxNzExaF9zZXRf bG93X3JwX2R1dHkoY2hpcCwgZmFsc2UpOworCQlyZXQgPSBydDE3MTFoX3NldF9sb3dfcG93ZXJf bW9kZShjaGlwLCBmYWxzZSwKKwkJCVRZUEVDX0NDX1BVTExfRFJQKTsKKwl9CisKKwljaGlwLT53 YWtldXBfb25jZSA9IGZhbHNlOworCWNoaXAtPmxvd19ycF9kdXR5X2NudGRvd24gPSBmYWxzZTsK KwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IHRjcG1faW5pdChzdHJ1Y3QgdGNwY19kZXYg KmRldikKK3sKKwlpbnQgcmV0ID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gY29u dGFpbmVyX29mKGRldiwKKwkJc3RydWN0IHJ0MTcxMWhfY2hpcCwgdGNwY19kZXYpOworCisJcnQx NzExaF9sb2coY2hpcCwgIiVzXG4iLCBfX2Z1bmNfXyk7CisKKwkvKiBDSyAzMDBLIGZyb20gMzIw Sywgc2hpcHBpbmcgb2ZmLCBhdXRvX2lkbGUgZW5hYmxlLCB0b3V0ID0gMzJtcyAqLworCXJldCA9 IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX0lETEVfQ1RSTCwKKwkJUlQxNzEx SF9SRUdfSURMRV9TRVQoMCwgMSwgMSwgMikpOworCWlmIChyZXQgPCAwKSB7CisJCXJ0MTcxMWhf bG9nKGNoaXAsICIlcyBzZXQgaWRsZSBjdHJsIGZhaWwoJWQpXG4iLCBfX2Z1bmNfXywgcmV0KTsK KwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXQgPSBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3 MTFIX1JFR19JMkNSU1RfQ1RSTCwKKwkJUlQxNzExSF9SRUdfSTJDUlNUX1NFVCh0cnVlLCAweDBG KSk7CisJaWYgKHJldCA8IDApIHsKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIHNldCBpMmNyc3Qg ZmFpbCglZClcbiIsIF9fZnVuY19fLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCS8qIFVG UCBCb3RoIFJEIHNldHRpbmcgKi8KKwkvKiBEUlAgPSAwLCBScFZhbCA9IDAgKERlZmF1bHQpLCBS ZCwgUmQgKi8KKwlyZXQgPSBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19ST0xF X0NUUkwsCisJCVJUMTcxMUhfUkVHX1JPTEVfQ1RSTF9SRVNfU0VUKDAsIDAsIFRZUEVDX0NDX1BV TExfUkQsCisJCVRZUEVDX0NDX1BVTExfUkQpKTsKKwlpZiAocmV0IDwgMCkgeworCQlydDE3MTFo X2xvZyhjaGlwLCAiJXMgc2V0IHJvbGUgY3RybCBmYWlsKCVkKVxuIiwgX19mdW5jX18sIHJldCk7 CisJCXJldHVybiByZXQ7CisJfQorCisJLyoKKwkgKiBDQyBEZXRlY3QgRGVib3VuY2UgOiAoMjYu NyAqIHZhbCkgdXMKKwkgKiBUcmFuc2l0aW9uIHdpbmRvdyBjb3VudCA6IHNwZWMgMTJ+MjB1cywg YmFzZWQgb24gMi40TUh6CisJICovCisJcmV0ID0gcnQxNzExaF9yZWdfd3JpdGUoY2hpcCwgUlQx NzExSF9SRUdfVFRDUENfRklMVEVSLCAweDBGKTsKKwlpZiAocmV0IDwgMCkgeworCQlydDE3MTFo X2xvZyhjaGlwLCAiJXMgc2V0IGNjIGRlYiBmYWlsKCVkKVxuIiwgX19mdW5jX18sIHJldCk7CisJ CXJldHVybiByZXQ7CisJfQorCisJLyogIERSUCBUb2dnbGUgQ3ljbGUgOiAoNTEuMiArIDYuNCAq IHZhbCkgbXMgKi8KKwlydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19EUlBfVE9H R0xFX0NZQ0xFLCA0KTsKKwlpZiAocmV0IDwgMCkgeworCQlydDE3MTFoX2xvZyhjaGlwLCAiJXMg c2V0IHRvZyBjeWMgZmFpbCglZClcbiIsIF9fZnVuY19fLCByZXQpOworCQlyZXR1cm4gcmV0Owor CX0KKworCS8qIERSUCBEdXR5IEN0cmw6IDMzJSAqLworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRl X3dvcmQoY2hpcCwgUlQxNzExSF9SRUdfRFJQX0RVVFlfQ1RSTCwKKwkJUlQxNzExSF9OT1JNQUxf UlBfRFVUWSk7CisJaWYgKHJldCA8IDApIHsKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIHNldCBk cnAgZHV0eSBmYWlsKCVkKVxuIiwgX19mdW5jX18sIHJldCk7CisJCXJldHVybiByZXQ7CisJfQor CisJLyogVmNvbm4gT0MgKi8KKwlyZXQgPSBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFI X1JFR19WQ09OTl9DTElNSVRFTiwgMSk7CisJaWYgKHJldCA8IDApIHsKKwkJcnQxNzExaF9sb2co Y2hpcCwgIiVzIGVuIHZjb25uIG9jIGZhaWwoJWQpXG4iLCBfX2Z1bmNfXywgcmV0KTsKKwkJcmV0 dXJuIHJldDsKKwl9CisKKwkvKiBBbGVydCAmIE1hc2sgKi8KKwlyZXQgPSBydDE3MTFoX2FsZXJ0 X3N0YXR1c19jbGVhcihjaGlwLCAweGZmZmZmZmZmKTsKKwlpZiAocmV0IDwgMCkgeworCQlydDE3 MTFoX2xvZyhjaGlwLCAiJXMgY2xlYXIgYWxlcnQgZmFpbCglZClcbiIsIF9fZnVuY19fLCByZXQp OworCQlyZXR1cm4gcmV0OworCX0KKwlyZXQgPSBydDE3MTFoX2luaXRfcG93ZXJfc3RhdHVzX21h c2soY2hpcCk7CisJaWYgKHJldCA8IDApIHsKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIGluaXQg cHdyIG1hc2sgZmFpbCglZClcbiIsIF9fZnVuY19fLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0K KwlyZXQgPSBydDE3MTFoX2luaXRfYWxlcnRfbWFzayhjaGlwKTsKKwlpZiAocmV0IDwgMCkgewor CQlydDE3MTFoX2xvZyhjaGlwLCAiJXMgaW5pdCBhbGVydCBtYXNrIGZhaWwoJWQpXG4iLCBfX2Z1 bmNfXywKKwkJCXJldCk7CisJCXJldHVybiByZXQ7CisJfQorCXJldCA9IHJ0MTcxMWhfaW5pdF9m YXVsdF9tYXNrKGNoaXApOworCWlmIChyZXQgPCAwKSB7CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIl cyBpbml0IGZhdWx0IG1hc2sgZmFpbCglZClcbiIsIF9fZnVuY19fLAorCQkJcmV0KTsKKwkJcmV0 dXJuIHJldDsKKwl9CisJcmV0ID0gcnQxNzExaF9pbml0X3J0X21hc2soY2hpcCk7CisJaWYgKHJl dCA8IDApIHsKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIGluaXQgcnQgbWFzayBmYWlsKCVkKVxu IiwgX19mdW5jX18sIHJldCk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisK K3N0YXRpYyBpbnQgdGNwbV9nZXRfdmJ1cyhzdHJ1Y3QgdGNwY19kZXYgKmRldikKK3sKKwlpbnQg cmV0ID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gY29udGFpbmVyX29mKGRldiwg c3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNwY19kZXYpOworCisJcnQxNzExaF9sb2coY2hpcCwg IiVzXG4iLCBfX2Z1bmNfXyk7CisJbXV0ZXhfbG9jaygmY2hpcC0+bG9jayk7CisJcmV0ID0gY2hp cC0+dmJ1c19wcmVzZW50ID8gMSA6IDA7CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT5sb2NrKTsKKwor CXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgdGNwbV9nZXRfY3VycmVudF9saW1pdChzdHJ1 Y3QgdGNwY19kZXYgKmRldikKK3sKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gY29udGFp bmVyX29mKGRldiwgc3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNwY19kZXYpOworCWludCBjdXJy ZW50X2xpbWl0ID0gMDsKKwl1bnNpZ25lZCBsb25nIHRpbWVvdXQ7CisKKwlydDE3MTFoX2xvZyhj aGlwLCAiJXNcbiIsIF9fZnVuY19fKTsKKwlpZiAoIWNoaXAtPmV4dGNvbikKKwkJcmV0dXJuIDA7 CisKKwkvKgorCSAqIFVTQjIgQ2hhcmdlciBkZXRlY3Rpb24gbWF5IHN0aWxsIGJlIGluIHByb2dy ZXNzIHdoZW4gd2UgZ2V0IGhlcmUsCisJICogdGhpcyBjYW4gdGFrZSB1cHRvIDYwMG1zLCB3YWl0 IDgwMG1zIG1heC4KKwkgKi8KKwl0aW1lb3V0ID0gamlmZmllcyArIG1zZWNzX3RvX2ppZmZpZXMo ODAwKTsKKwlkbyB7CisJCWlmIChleHRjb25fZ2V0X3N0YXRlKGNoaXAtPmV4dGNvbiwgRVhUQ09O X0NIR19VU0JfU0RQKSA9PSAxKQorCQkJY3VycmVudF9saW1pdCA9IDUwMDsKKworCQlpZiAoZXh0 Y29uX2dldF9zdGF0ZShjaGlwLT5leHRjb24sIEVYVENPTl9DSEdfVVNCX0NEUCkgPT0gMSB8fAor CQkgICAgZXh0Y29uX2dldF9zdGF0ZShjaGlwLT5leHRjb24sIEVYVENPTl9DSEdfVVNCX0FDQSkg PT0gMSkKKwkJCWN1cnJlbnRfbGltaXQgPSAxNTAwOworCisJCWlmIChleHRjb25fZ2V0X3N0YXRl KGNoaXAtPmV4dGNvbiwgRVhUQ09OX0NIR19VU0JfRENQKSA9PSAxKQorCQkJY3VycmVudF9saW1p dCA9IDIwMDA7CisKKwkJbXNsZWVwKDUwKTsKKwl9IHdoaWxlIChjdXJyZW50X2xpbWl0ID09IDAg JiYgdGltZV9iZWZvcmUoamlmZmllcywgdGltZW91dCkpOworCisJcmV0dXJuIGN1cnJlbnRfbGlt aXQ7Cit9CisKK3N0YXRpYyBpbnQgX190Y3BtX3NldF9jYyhzdHJ1Y3QgcnQxNzExaF9jaGlwICpj aGlwLCBlbnVtIHR5cGVjX2NjX3N0YXR1cyBjYykKK3sKKwl1aW50OF90IGRhdGEgPSAwLCBwdWxs ID0gMCwgcnBfbHZsID0gMDsKKworCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyAlc1xuIiwgX19mdW5j X18sIHR5cGVjX2NjX3N0YXR1c19uYW1lW2NjXSk7CisJc3dpdGNoIChjYykgeworCWNhc2UgVFlQ RUNfQ0NfT1BFTjoKKwljYXNlIFRZUEVDX0NDX1JEOgorCWNhc2UgVFlQRUNfQ0NfUlBfREVGOgor CWNhc2UgVFlQRUNfQ0NfUlBfMV81OgorCWNhc2UgVFlQRUNfQ0NfUlBfM18wOgorCQlwdWxsID0g cnQxNzExaF9jY19zdGF0dXMycHVsbChjYyk7CisJCXJwX2x2bCA9IFJUMTcxMUhfVFlQRUNfQ0Nf UFVMTF9HRVRfUlBfTFZMKHB1bGwpOworCQlwdWxsID0gUlQxNzExSF9UWVBFQ19DQ19QVUxMX0dF VF9SRVMocHVsbCk7CisJCWRhdGEgPSBSVDE3MTFIX1JFR19ST0xFX0NUUkxfUkVTX1NFVCgwLCBy cF9sdmwsIHB1bGwsIHB1bGwpOworCQlicmVhazsKKwlkZWZhdWx0OgorCQlydDE3MTFoX2xvZyhj aGlwLCAiJXMgdW5zdXBwb3J0ZWQgY2MgdmFsdWUgJXNcbiIsIF9fZnVuY19fLAorCQkJdHlwZWNf Y2Nfc3RhdHVzX25hbWVbY2NdKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJcmV0dXJuIHJ0 MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX1JPTEVfQ1RSTCwgZGF0YSk7Cit9CisK K3N0YXRpYyBpbnQgdGNwbV9zZXRfY2Moc3RydWN0IHRjcGNfZGV2ICpkZXYsIGVudW0gdHlwZWNf Y2Nfc3RhdHVzIGNjKQoreworCWludCByZXQgPSAwOworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNo aXAgPSBjb250YWluZXJfb2YoZGV2LCBzdHJ1Y3QgcnQxNzExaF9jaGlwLAorCQl0Y3BjX2Rldik7 CisKKwltdXRleF9sb2NrKCZjaGlwLT5sb2NrKTsKKwlyZXQgPSBfX3RjcG1fc2V0X2NjKGNoaXAs IGNjKTsKKwltdXRleF91bmxvY2soJmNoaXAtPmxvY2spOworCisJcmV0dXJuIHJldDsKK30KKwor c3RhdGljIGlubGluZSBlbnVtIHR5cGVjX2NjX3N0YXR1cyBydDE3MTFoX2NjMmVudW0oZW51bSB0 eXBlY19jY19zdGF0dXMgY2MsCisJYm9vbCBhY3RfYXNfc2luaykKK3sKKwlyZXR1cm4gYWN0X2Fz X3NpbmsgPyBjYyArIDIgOiBjYzsKK30KKworc3RhdGljIGludCBfX3RjcG1fZ2V0X2NjKHN0cnVj dCBydDE3MTFoX2NoaXAgKmNoaXApCit7CisJaW50IHJldCA9IDA7CisJdWludDhfdCBzdGF0dXMg PSAwLCByb2xlX2N0cmwgPSAwLCBjY19yb2xlID0gMDsKKwlib29sIGFjdF9hc19zaW5rLCBhY3Rf YXNfZHJwOworCisJcmV0ID0gcnQxNzExaF9yZWdfcmVhZChjaGlwLCBSVDE3MTFIX1JFR19DQ19T VEFUVVMsICZzdGF0dXMpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJcmV0ID0g cnQxNzExaF9yZWdfcmVhZChjaGlwLCBSVDE3MTFIX1JFR19ST0xFX0NUUkwsICZyb2xlX2N0cmwp OworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJaWYgKHN0YXR1cyAmIFJUMTcxMUhf UkVHX0NDX1NUQVRVU19EUlBfVE9HR0xJTkcpIHsKKwkJLyogZHVyaW5nIHRvZ2dsaW5nLCBjb25z aWRlciBjYyBhcyBPcGVuICovCisJCWNoaXAtPmNjMSA9IFRZUEVDX0NDX09QRU47CisJCWNoaXAt PmNjMiA9IFRZUEVDX0NDX09QRU47CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyBkcnAgdG9nZ2xp bmdcbiIsIF9fZnVuY19fKTsKKwkJcmV0dXJuIDA7CisJfQorCWNoaXAtPmRycF90b2dnbGluZyA9 IGZhbHNlOworCisJYWN0X2FzX2RycCA9IFJUMTcxMUhfUkVHX1JPTEVfQ1RSTF9EUlAgJiByb2xl X2N0cmw7CisKKwlpZiAoYWN0X2FzX2RycCkKKwkJYWN0X2FzX3NpbmsgPSBSVDE3MTFIX1JFR19D Q19TVEFUVVNfRFJQX1JFU1VMVChzdGF0dXMpOworCWVsc2UgeworCQljY19yb2xlID0gUlQxNzEx SF9SRUdfUk9MRV9DVFJMX0NDMShyb2xlX2N0cmwpOworCQlhY3RfYXNfc2luayA9IChjY19yb2xl ID09IFRZUEVDX0NDX1BVTExfUlApID8gZmFsc2UgOiB0cnVlOworCX0KKworCWNoaXAtPmNjMSA9 IFJUMTcxMUhfUkVHX0NDX1NUQVRVU19DQzEoc3RhdHVzKTsKKwljaGlwLT5jYzIgPSBSVDE3MTFI X1JFR19DQ19TVEFUVVNfQ0MyKHN0YXR1cyk7CisJaWYgKGNoaXAtPmNjMSAhPSBUWVBFQ19DQ19P UEVOKQorCQljaGlwLT5jYzEgPSBydDE3MTFoX2NjMmVudW0oY2hpcC0+Y2MxLCBhY3RfYXNfc2lu ayk7CisJaWYgKGNoaXAtPmNjMiAhPSBUWVBFQ19DQ19PUEVOKQorCQljaGlwLT5jYzIgPSBydDE3 MTFoX2NjMmVudW0oY2hpcC0+Y2MyLCBhY3RfYXNfc2luayk7CisKKwlyZXQgPSBydDE3MTFoX2lu aXRfY2NfcGFyYW1zKGNoaXAsIGNoaXAtPnBvbGFyaXR5ID8KKwkJJmNoaXAtPmNjMiA6ICZjaGlw LT5jYzEpOworCWlmIChyZXQgPCAwKQorCQlydDE3MTFoX2xvZyhjaGlwLCAiJXMgaW5pdCBjYyBw YXJhbSBmYWlsKCVkKVxuIiwgX19mdW5jX18sIHJldCk7CisKKwlydDE3MTFoX2xvZyhjaGlwLCAi JXMgY2MxID0gJXMsIGNjMiA9ICVzXG4iLCBfX2Z1bmNfXywKKwkJdHlwZWNfY2Nfc3RhdHVzX25h bWVbY2hpcC0+Y2MxXSwKKwkJdHlwZWNfY2Nfc3RhdHVzX25hbWVbY2hpcC0+Y2MyXSk7CisKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIGludCB0Y3BtX2dldF9jYyhzdHJ1Y3QgdGNwY19kZXYgKmRl diwKKwllbnVtIHR5cGVjX2NjX3N0YXR1cyAqY2MxLCBlbnVtIHR5cGVjX2NjX3N0YXR1cyAqY2My KQoreworCWludCByZXQgPSAwOworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAgPSBjb250YWlu ZXJfb2YoZGV2LCBzdHJ1Y3QgcnQxNzExaF9jaGlwLAorCQl0Y3BjX2Rldik7CisKKwltdXRleF9s b2NrKCZjaGlwLT5sb2NrKTsKKwlyZXQgPSBfX3RjcG1fZ2V0X2NjKGNoaXApOworCWlmIChyZXQg PCAwKQorCQlnb3RvIG91dDsKKwkqY2MxID0gY2hpcC0+Y2MxOworCSpjYzIgPSBjaGlwLT5jYzI7 CitvdXQ6CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT5sb2NrKTsKKwlyZXR1cm4gcmV0OworfQorCitz dGF0aWMgaW50IHRjcG1fc2V0X3BvbGFyaXR5KHN0cnVjdCB0Y3BjX2RldiAqZGV2LAorCWVudW0g dHlwZWNfY2NfcG9sYXJpdHkgcG9sYXJpdHkpCit7CisJaW50IHJldCA9IDA7CisJdWludDhfdCBk YXRhID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gY29udGFpbmVyX29mKGRldiwg c3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNwY19kZXYpOworCisJbXV0ZXhfbG9jaygmY2hpcC0+ bG9jayk7CisJcnQxNzExaF9sb2coY2hpcCwgIiVzICVzXG4iLCBfX2Z1bmNfXywgY2NfcG9sYXJp dHlfbmFtZVtwb2xhcml0eV0pOworCXJldCA9IHJ0MTcxMWhfaW5pdF9jY19wYXJhbXMoY2hpcCwg cG9sYXJpdHkgPyAmY2hpcC0+Y2MyIDogJmNoaXAtPmNjMSk7CisJaWYgKHJldCA8IDApCisJCWdv dG8gb3V0OworCisJcmV0ID0gcnQxNzExaF9yZWdfcmVhZChjaGlwLCBSVDE3MTFIX1JFR19UQ1BD X0NUUkwsICZkYXRhKTsKKwlpZiAocmV0IDwgMCkKKwkJZ290byBvdXQ7CisKKwlkYXRhICY9IH5S VDE3MTFIX1JFR19UQ1BDX0NUUkxfUExVR19PUklFTlQ7CisJZGF0YSB8PSBwb2xhcml0eSA/IFJU MTcxMUhfUkVHX1RDUENfQ1RSTF9QTFVHX09SSUVOVCA6IDA7CisKKwlyZXQgPSBydDE3MTFoX3Jl Z193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19UQ1BDX0NUUkwsIGRhdGEpOworb3V0OgorCW11dGV4 X3VubG9jaygmY2hpcC0+bG9jayk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCB0Y3Bt X3NldF92Y29ubihzdHJ1Y3QgdGNwY19kZXYgKmRldiwgYm9vbCBvbikKK3sKKwlpbnQgcmV0ID0g MDsKKwl1aW50OF90IGRhdGEgPSAwOworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAgPSBjb250 YWluZXJfb2YoZGV2LCBzdHJ1Y3QgcnQxNzExaF9jaGlwLAorCQl0Y3BjX2Rldik7CisKKwltdXRl eF9sb2NrKCZjaGlwLT5sb2NrKTsKKwlpZiAoY2hpcC0+dmNvbm5fb24gPT0gb24pIHsKKwkJcnQx NzExaF9sb2coY2hpcCwgIiVzIHZjb25uIGlzIGFscmVhZHkgJWRcbiIsIF9fZnVuY19fLCBvbik7 CisJCWdvdG8gb3V0OworCX0KKwlyZXQgPSBydDE3MTFoX3JlZ19yZWFkKGNoaXAsIFJUMTcxMUhf UkVHX1BPV0VSX0NUUkwsICZkYXRhKTsKKwlpZiAocmV0IDwgMCkKKwkJZ290byBvdXQ7CisKKwlk YXRhICY9IH5SVDE3MTFIX1JFR19QT1dFUl9DVFJMX1ZDT05OOworCWRhdGEgfD0gb24gPyBSVDE3 MTFIX1JFR19QT1dFUl9DVFJMX1ZDT05OIDogMDsKKworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRl KGNoaXAsIFJUMTcxMUhfUkVHX1BPV0VSX0NUUkwsIGRhdGEpOworCWlmIChyZXQgPCAwKQorCQln b3RvIG91dDsKKworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJUMTcxMUhfUkVHX0lE TEVfQ1RSTCwKKwkJUlQxNzExSF9SRUdfSURMRV9TRVQoMCwgMSwgb24gPyAwIDogMSwgMikpOwor CWlmIChyZXQgPCAwKQorCQlnb3RvIG91dDsKKworCWNoaXAtPnZjb25uX29uID0gb247CisJcnQx NzExaF9sb2coY2hpcCwgIiVzIHZjb25uID0gJWRcbiIsIF9fZnVuY19fLCBvbik7CisKK291dDoK KwltdXRleF91bmxvY2soJmNoaXAtPmxvY2spOworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBp bnQgdGNwbV9zZXRfdmJ1cyhzdHJ1Y3QgdGNwY19kZXYgKmRldiwgYm9vbCBvbiwgYm9vbCBjaGFy Z2UpCit7CisJaW50IHJldCA9IDA7CisJc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCA9IGNvbnRh aW5lcl9vZihkZXYsIHN0cnVjdCBydDE3MTFoX2NoaXAsCisJCXRjcGNfZGV2KTsKKworCW11dGV4 X2xvY2soJmNoaXAtPmxvY2spOworCWlmIChjaGlwLT52YnVzX29uID09IG9uKQorCQlydDE3MTFo X2xvZyhjaGlwLCAiJXMgdmJ1cyBpcyBhbHJlYWR5ICVkXG4iLCBfX2Z1bmNfXywgb24pOworCWVs c2UgeworCQlyZXQgPSAob24gPyByZWd1bGF0b3JfZW5hYmxlIDogcmVndWxhdG9yX2Rpc2FibGUp KGNoaXAtPnZidXMpOworCQlpZiAocmV0IDwgMCkgeworCQkJcnQxNzExaF9sb2coY2hpcCwgIiVz IGNhbm5vdCAlcyB2YnVzIHJlZ3VsYXRvciglZClcbiIsCisJCQkJX19mdW5jX18sIG9uID8gImVu YWJsZSIgOiAiZGlzYWJsZSIsIHJldCk7CisJCQlnb3RvIG91dDsKKwkJfQorCQljaGlwLT52YnVz X29uID0gb247CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyB2YnVzID0gJWRcbiIsIF9fZnVuY19f LCBvbik7CisJfQorCWlmIChjaGlwLT5jaGFyZ2Vfb24gPT0gY2hhcmdlKQorCQlydDE3MTFoX2xv ZyhjaGlwLCAiJXMgY2hnIGlzIGFscmVhZHkgJWRcbiIsIF9fZnVuY19fLCBjaGFyZ2UpOworCWVs c2UgeworCQljaGlwLT5jaGFyZ2Vfb24gPSBjaGFyZ2U7CisJCXBvd2VyX3N1cHBseV9jaGFuZ2Vk KGNoaXAtPnBzeSk7CisJfQorCitvdXQ6CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT5sb2NrKTsKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIGludCB0Y3BtX3NldF9jdXJyZW50X2xpbWl0KHN0cnVjdCB0 Y3BjX2RldiAqZGV2LCB1MzIgbWF4X21hLAorCXUzMiBtdikKK3sKKwlzdHJ1Y3QgcnQxNzExaF9j aGlwICpjaGlwID0gY29udGFpbmVyX29mKGRldiwgc3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNw Y19kZXYpOworCisJcnQxNzExaF9sb2coY2hpcCwgIiVzICVkIG1hLCAlZCBtdiAobm90IGltcGxl bWVudGVkKVxuIiwgX19mdW5jX18sCisJCW1heF9tYSwgbXYpOworCisJbXV0ZXhfbG9jaygmY2hp cC0+bG9jayk7CisJY2hpcC0+c3VwcGx5X3ZvbHRhZ2UgPSBtdjsKKwljaGlwLT5jdXJyZW50X2xp bWl0ID0gbWF4X21hOworCW11dGV4X3VubG9jaygmY2hpcC0+bG9jayk7CisKKwlwb3dlcl9zdXBw bHlfY2hhbmdlZChjaGlwLT5wc3kpOworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHRjcG1f c2V0X3BkX3J4KHN0cnVjdCB0Y3BjX2RldiAqZGV2LCBib29sIG9uKQoreworCWludCByZXQgPSAw OworCXVpbnQ4X3QgcnhfZW4gPSAweDAwOworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAgPSBj b250YWluZXJfb2YoZGV2LCBzdHJ1Y3QgcnQxNzExaF9jaGlwLAorCQl0Y3BjX2Rldik7CisKKwlt dXRleF9sb2NrKCZjaGlwLT5sb2NrKTsKKwlydDE3MTFoX2xvZyhjaGlwLCAiJXMgJWRcbiIsIF9f ZnVuY19fLCBvbik7CisJaWYgKG9uKQorCQlyeF9lbiA9IEJJVChUQ1BDX1RYX1NPUCkgfCBCSVQo VENQQ19UWF9IQVJEX1JFU0VUKTsKKworCXJldCA9IHJ0MTcxMWhfcmVnX3dyaXRlKGNoaXAsIFJU MTcxMUhfUkVHX1JYX0RFVEVDVCwgcnhfZW4pOworCW11dGV4X3VubG9jaygmY2hpcC0+bG9jayk7 CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCB0Y3BtX3NldF9yb2xlcyhzdHJ1Y3QgdGNw Y19kZXYgKmRldiwgYm9vbCBhdHRhY2hlZCwKKwllbnVtIHR5cGVjX3JvbGUgcHdyLCBlbnVtIHR5 cGVjX2RhdGFfcm9sZSBkYXRhKQoreworCWludCByZXQgPSAwOworCXVpbnQ4X3QgbXNnX2hkciA9 IFJUMTcxMUhfUkVHX01TR19IRFJfSU5GT19TRVQoZGF0YSwgcHdyKTsKKwlzdHJ1Y3QgcnQxNzEx aF9jaGlwICpjaGlwID0gY29udGFpbmVyX29mKGRldiwgc3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJ dGNwY19kZXYpOworCisJbXV0ZXhfbG9jaygmY2hpcC0+bG9jayk7CisJcnQxNzExaF9sb2coY2hp cCwgIiVzICVzICVzXG4iLCBfX2Z1bmNfXywgdHlwZWNfcm9sZV9uYW1lW3B3cl0sCisJCXR5cGVj X2RhdGFfcm9sZV9uYW1lW2RhdGFdKTsKKwlyZXQgPSBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBS VDE3MTFIX1JFR19NU0dfSERSX0lORk8sIG1zZ19oZHIpOworCWlmIChyZXQgPCAwKQorCQlnb3Rv IG91dDsKKwljaGlwLT5wd3Jfcm9sZSA9IHB3cjsKK291dDoKKwltdXRleF91bmxvY2soJmNoaXAt PmxvY2spOworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbmxpbmUgaW50IF9fdGNwbV9zdGFy dF9kcnBfdG9nZ2xpbmcoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlpbnQgcmV0ID0g MDsKKwl1aW50OF90IGRhdGEgPSAwOworCXVpbnQ4X3QgcnBfZGVmID0gUlQxNzExSF9UWVBFQ19D Q19QVUxMX0dFVF9SUF9MVkwoVFlQRUNfQ0NfUFVMTF9SUF9ERUYpOworCXVpbnQ4X3QgY2Nfcm9s ZSA9IFRZUEVDX0NDX1BVTExfUkQ7CisKKwlkYXRhID0gUlQxNzExSF9SRUdfUk9MRV9DVFJMX1JF U19TRVQoMCwgcnBfZGVmLCBjY19yb2xlLCBjY19yb2xlKTsKKwlyZXQgPSBydDE3MTFoX3JlZ193 cml0ZShjaGlwLCBSVDE3MTFIX1JFR19ST0xFX0NUUkwsIGRhdGEpOworCWlmIChyZXQgPCAwKQor CQlyZXR1cm4gcmV0OworCW1kZWxheSgxKTsKKwlkYXRhID0gUlQxNzExSF9SRUdfUk9MRV9DVFJM X1JFU19TRVQoMSwgcnBfZGVmLCBjY19yb2xlLCBjY19yb2xlKTsKKwlyZXQgPSBydDE3MTFoX3Jl Z193cml0ZShjaGlwLCBSVDE3MTFIX1JFR19ST0xFX0NUUkwsIGRhdGEpOworCWlmIChyZXQgPCAw KQorCQlyZXR1cm4gcmV0OworCXJldCA9IHJ0MTcxMWhfY29tbWFuZChjaGlwLCBSVDE3MTFIX0NN RF9MT09LX0NPTk5FQ1RJT04pOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCWNoaXAt PmRycF90b2dnbGluZyA9IHRydWU7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCB0Y3Bt X3N0YXJ0X2RycF90b2dnbGluZyhzdHJ1Y3QgdGNwY19kZXYgKmRldiwKKwllbnVtIHR5cGVjX2Nj X3N0YXR1cyBjYykKK3sKKwlpbnQgcmV0ID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlw ID0gY29udGFpbmVyX29mKGRldiwgc3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNwY19kZXYpOwor CisJbXV0ZXhfbG9jaygmY2hpcC0+bG9jayk7CisJcnQxNzExaF9sb2coY2hpcCwgIiVzXG4iLCBf X2Z1bmNfXyk7CisJcmV0ID0gX190Y3BtX3N0YXJ0X2RycF90b2dnbGluZyhjaGlwKTsKKwlpZiAo cmV0IDwgMCkKKwkJZ290byBvdXQ7CisJaWYgKGNoaXAtPmRpZCA8IFJUMTcxMUhfRElEX0QpCisJ CXJldCA9IHJ0MTcxMWhfZW5hYmxlX2xvd19wb3dlcl9tb2RlKGNoaXAsIFRZUEVDX0NDX1BVTExf RFJQKTsKKworb3V0OgorCW11dGV4X3VubG9jaygmY2hpcC0+bG9jayk7CisJcmV0dXJuIHJldDsK K30KKworI3ByYWdtYSBwYWNrKHB1c2gsIDEpCitzdHJ1Y3QgdGNwY190cmFuc21pdF9wYWNrZXQg eworCXVpbnQ4X3QgY250OworCXVpbnQxNl90IG1zZ19oZWFkZXI7CisJdWludDhfdCBkYXRhW3Np emVvZih1aW50MzJfdCkgKiBQRF9NQVhfUEFZTE9BRF07Cit9OworI3ByYWdtYSBwYWNrKHBvcCkK Kworc3RhdGljIGludCB0Y3BtX3BkX3RyYW5zbWl0KHN0cnVjdCB0Y3BjX2RldiAqZGV2LAorCWVu dW0gdGNwbV90cmFuc21pdF90eXBlIHR5cGUsIGNvbnN0IHN0cnVjdCBwZF9tZXNzYWdlICptc2cp Cit7CisJaW50IHJldCA9IDA7CisJaW50IGRhdGFfY250ID0gMDsKKwlzdHJ1Y3QgcnQxNzExaF9j aGlwICpjaGlwID0gY29udGFpbmVyX29mKGRldiwgc3RydWN0IHJ0MTcxMWhfY2hpcCwKKwkJdGNw Y19kZXYpOworCXN0cnVjdCB0Y3BjX3RyYW5zbWl0X3BhY2tldCBwYWNrZXQ7CisKKwlydDE3MTFo X2xvZyhjaGlwLCAiJXMgJXNcbiIsIF9fZnVuY19fLCB0cmFuc21pdF90eXBlX25hbWVbdHlwZV0p OworCW11dGV4X2xvY2soJmNoaXAtPmxvY2spOworCXN3aXRjaCAodHlwZSkgeworCWNhc2UgVENQ Q19UWF9TT1A6CisJCWRhdGFfY250ID0gc2l6ZW9mKHVpbnQzMl90KSAqIHBkX2hlYWRlcl9jbnRf bGUobXNnLT5oZWFkZXIpOworCQlwYWNrZXQuY250ID0gZGF0YV9jbnQgKyBzaXplb2YodWludDE2 X3QpOworCQlwYWNrZXQubXNnX2hlYWRlciA9IG1zZy0+aGVhZGVyOworCQlpZiAoZGF0YV9jbnQg PiAwKQorCQkJbWVtY3B5KHBhY2tldC5kYXRhLCAodWludDhfdCAqKW1zZy0+cGF5bG9hZCwgZGF0 YV9jbnQpOworCisJCXJldCA9IHJ0MTcxMWhfcmVnX2Jsb2NrX3dyaXRlKGNoaXAsIFJUMTcxMUhf UkVHX1RYX0JZVEVfQ05ULAorCQkJcGFja2V0LmNudCArIDEsICh1aW50OF90ICopJnBhY2tldCk7 CisJCWlmIChyZXQgPCAwKSB7CisJCQlydDE3MTFoX2xvZyhjaGlwLCAiJXMgZmFpbCAoJWQpXG4i LCBfX2Z1bmNfXywgcmV0KTsKKwkJCWdvdG8gb3V0OworCQl9CisJCWJyZWFrOworCWNhc2UgVENQ Q19UWF9IQVJEX1JFU0VUOgorCQlicmVhazsKKwlkZWZhdWx0OgorCQlydDE3MTFoX2xvZyhjaGlw LCAidHlwZSAlcyBub3Qgc3VwcG9ydGVkXG4iLAorCQkJdHJhbnNtaXRfdHlwZV9uYW1lW3R5cGVd KTsKKwkJcmV0ID0gLUVJTlZBTDsKKwkJZ290byBvdXQ7CisJfQorCisJcmV0ID0gcnQxNzExaF9y ZWdfd3JpdGUoY2hpcCwgUlQxNzExSF9SRUdfVFJBTlNNSVQsCisJCVJUMTcxMUhfUkVHX1RSQU5T TUlUX1NFVCgzLCB0eXBlKSk7CitvdXQ6CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT5sb2NrKTsKKwly ZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfcGFyc2VfZHQoc3RydWN0IHJ0MTcx MWhfY2hpcCAqY2hpcCkKK3sKKwlpbnQgcmV0ID0gMCwgbGVuID0gMDsKKwl1aW50MzJfdCB2YWwg PSAwOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBjaGlwLT5kZXYtPm9mX25vZGU7CisJc3Ry dWN0IHRjcGNfY29uZmlnICpjZmcgPSAmY2hpcC0+dGNwY19jZmc7CisJY29uc3QgY2hhciAqbmFt ZSA9ICJkZWZhdWx0IjsKKworCWlmICghbnApCisJCXJldHVybiAtRUlOVkFMOworCisJZGV2X2lu Zm8oY2hpcC0+ZGV2LCAiJXNcbiIsIF9fZnVuY19fKTsKKworCW1lbWNweShjZmcsICZydDE3MTFo X3RjcGNfY29uZmlnLCBzaXplb2Yoc3RydWN0IHRjcGNfY29uZmlnKSk7CisKKwlyZXQgPSBvZl9n ZXRfbmFtZWRfZ3BpbyhucCwgInJ0LGludHJfZ3BpbyIsIDApOworCWlmIChyZXQgPCAwKSB7CisJ CWRldl9lcnIoY2hpcC0+ZGV2LCAiJXMgZ2V0IGludCBncGlvIGZhaWwoJWQpXG4iLAorCQkJX19m dW5jX18sIHJldCk7CisJCXJldHVybiByZXQ7CisJfQorCWNoaXAtPmlycV9ncGlvID0gcmV0Owor CWRldl9pbmZvKGNoaXAtPmRldiwgIiVzIGlycV9ncGlvID0gJWRcbiIsIF9fZnVuY19fLCBjaGlw LT5pcnFfZ3Bpbyk7CisKKwlvZl9wcm9wZXJ0eV9yZWFkX3N0cmluZyhucCwgInJ0LG5hbWUiLCAm bmFtZSk7CisKKwlsZW4gPSBzdHJsZW4obmFtZSk7CisJY2hpcC0+bmFtZSA9IGRldm1fa3phbGxv YyhjaGlwLT5kZXYsIGxlbiArIDEsIEdGUF9LRVJORUwpOworCWlmICghY2hpcC0+bmFtZSkKKwkJ cmV0dXJuIC1FTk9NRU07CisJc3RybGNweShjaGlwLT5uYW1lLCBuYW1lLCBzdHJsZW4obmFtZSkg KyAxKTsKKworCWlmIChvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInJ0LGRlZl9yb2xlIiwgJnZh bCkgPT0gMCkKKwkJY2ZnLT5kZWZhdWx0X3JvbGUgPSB2YWw7CisKKwlpZiAob2ZfcHJvcGVydHlf cmVhZF91MzIobnAsICJydCxwb3J0X3R5cGUiLCAmdmFsKSA9PSAwKQorCQljZmctPnR5cGUgPSB2 YWw7CisKKwlpZiAob2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJydCxtYXhfc25rX212IiwgJnZh bCkgPT0gMCkKKwkJY2ZnLT5tYXhfc25rX212ID0gdmFsOworCisJaWYgKG9mX3Byb3BlcnR5X3Jl YWRfdTMyKG5wLCAicnQsbWF4X3Nua19tYSIsICZ2YWwpID09IDApCisJCWNmZy0+bWF4X3Nua19t YSA9IHZhbDsKKworCWlmIChvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInJ0LG1heF9zbmtfbXci LCAmdmFsKSA9PSAwKQorCQljZmctPm1heF9zbmtfbXcgPSB2YWw7CisKKwlpZiAob2ZfcHJvcGVy dHlfcmVhZF91MzIobnAsICJydCxvcGVyYXRpbmdfc25rX213IiwgJnZhbCkgPT0gMCkKKwkJY2Zn LT5vcGVyYXRpbmdfc25rX213ID0gdmFsOworCisJY2ZnLT50cnlfcm9sZV9odyA9IG9mX3Byb3Bl cnR5X3JlYWRfYm9vbChucCwgInJ0LHRyeV9yb2xlX2h3Iik7CisKKwlyZXR1cm4gMDsKK30KKwor c3RhdGljIHZvaWQgcnQxNzExaF9pbml0X3RjcGNfZGV2KHN0cnVjdCBydDE3MTFoX2NoaXAgKmNo aXApCit7CisJY2hpcC0+dGNwY19kZXYuY29uZmlnID0gJmNoaXAtPnRjcGNfY2ZnOworCWNoaXAt PnRjcGNfZGV2LmluaXQgPSB0Y3BtX2luaXQ7CisJY2hpcC0+dGNwY19kZXYuZ2V0X3ZidXMgPSB0 Y3BtX2dldF92YnVzOworCWNoaXAtPnRjcGNfZGV2LmdldF9jdXJyZW50X2xpbWl0ID0gdGNwbV9n ZXRfY3VycmVudF9saW1pdDsKKwljaGlwLT50Y3BjX2Rldi5zZXRfY2MgPSB0Y3BtX3NldF9jYzsK KwljaGlwLT50Y3BjX2Rldi5nZXRfY2MgPSB0Y3BtX2dldF9jYzsKKwljaGlwLT50Y3BjX2Rldi5z ZXRfcG9sYXJpdHkgPSB0Y3BtX3NldF9wb2xhcml0eTsKKwljaGlwLT50Y3BjX2Rldi5zZXRfdmNv bm4gPSB0Y3BtX3NldF92Y29ubjsKKwljaGlwLT50Y3BjX2Rldi5zZXRfdmJ1cyA9IHRjcG1fc2V0 X3ZidXM7CisJY2hpcC0+dGNwY19kZXYuc2V0X2N1cnJlbnRfbGltaXQgPSB0Y3BtX3NldF9jdXJy ZW50X2xpbWl0OworCWNoaXAtPnRjcGNfZGV2LnNldF9wZF9yeCA9IHRjcG1fc2V0X3BkX3J4Owor CWNoaXAtPnRjcGNfZGV2LnNldF9yb2xlcyA9IHRjcG1fc2V0X3JvbGVzOworCWNoaXAtPnRjcGNf ZGV2LnN0YXJ0X2RycF90b2dnbGluZyA9IHRjcG1fc3RhcnRfZHJwX3RvZ2dsaW5nOworCWNoaXAt PnRjcGNfZGV2LnBkX3RyYW5zbWl0ID0gdGNwbV9wZF90cmFuc21pdDsKKwljaGlwLT50Y3BjX2Rl di5tdXggPSBOVUxMOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfZ2V0X2FsZXJ0X3N0YXR1cyhz dHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwLAorCXVpbnQzMl90ICphbGVydCkKK3sKKwlpbnQgcmV0 ID0gMDsKKwl1aW50MTZfdCBkYXRhID0gMDsKKwl1aW50OF90IHJ0X2ludCA9IDA7CisKKwlyZXQg PSBydDE3MTFoX3JlZ19yZWFkX3dvcmQoY2hpcCwgUlQxNzExSF9SRUdfQUxFUlQsICZkYXRhKTsK KwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKwkqYWxlcnQgPSBkYXRhOworCisJcmV0ID0g cnQxNzExaF9yZWdfcmVhZChjaGlwLCBSVDE3MTFIX1JFR19SVF9JTlQsICZydF9pbnQpOworCWlm IChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCSphbGVydCB8PSBydF9pbnQgPDwgMTY7CisKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2dldF9mYXVsdF9zdGF0dXMoc3RydWN0 IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDhfdCAqc3RhdHVzKQoreworCXJldHVybiBydDE3MTFo X3JlZ19yZWFkKGNoaXAsIFJUMTcxMUhfUkVHX0ZBVUxUX1NUQVRVUywgc3RhdHVzKTsKK30KKwor c3RhdGljIGlubGluZSBpbnQgcnQxNzExaF9mYXVsdF9zdGF0dXNfdmNvbm5fb3Yoc3RydWN0IHJ0 MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlpbnQgcmV0ID0gMDsKKwl1aW50OF90IGRhdGEgPSAwOwor CisJcmV0ID0gcnQxNzExaF9yZWdfcmVhZChjaGlwLCBSVDE3MTFIX1JFR19CTUNfQ1RSTCwgJmRh dGEpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJZGF0YSAmPSB+UlQxNzExSF9S RUdfRElTQ0hBUkdFX0VOOworCXJldHVybiBydDE3MTFoX3JlZ193cml0ZShjaGlwLCBSVDE3MTFI X1JFR19CTUNfQ1RSTCwgZGF0YSk7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9mYXVsdF9zdGF0 dXNfY2xlYXIoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCwgdWludDhfdCBzdGF0dXMpCit7CisJ aWYgKHN0YXR1cyAmIFJUMTcxMUhfUkVHX0ZBVUxUX1NUQVRVU19WQ09OTl9PVikKKwkJcnQxNzEx aF9mYXVsdF9zdGF0dXNfdmNvbm5fb3YoY2hpcCk7CisKKwlyZXR1cm4gcnQxNzExaF9yZWdfd3Jp dGUoY2hpcCwgUlQxNzExSF9SRUdfRkFVTFRfU1RBVFVTLCBzdGF0dXMpOworfQorCisvKiBBbGVy dCBoYW5kbGVycyAqLworCitzdGF0aWMgaW50IHJ0MTcxMWhfYWxlcnRfY2NfY2hhbmdlZChzdHJ1 Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWludCByZXQgPSAwOworCisJcmV0ID0gX190Y3Bt X2dldF9jYyhjaGlwKTsKKwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKworCWlmIChjaGlw LT5kcnBfdG9nZ2xpbmcpIHsKKwkJcnQxNzExaF9sb2coY2hpcCwgIiVzIERSUCB0b2dnbGluZ1xu IiwgX19mdW5jX18pOworCQlpZiAoY2hpcC0+ZGlkIDwgUlQxNzExSF9ESURfRCAmJiBjaGlwLT5s cG0gJiYgIWNoaXAtPmNhYmxlX29ubHkpCisJCQlydDE3MTFoX2VudGVyX2xvd19wb3dlcl9tb2Rl KGNoaXApOworCQlyZXR1cm4gMDsKKwl9CisJaWYgKGNoaXAtPmRpZCA8IFJUMTcxMUhfRElEX0Qp CisJCXJ0MTcxMWhfZGlzYWJsZV9sb3dfcG93ZXJfbW9kZShjaGlwKTsKKworCXRjcG1fY2NfY2hh bmdlKGNoaXAtPnRjcG1fcG9ydCk7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzEx aF9hbGVydF9wb3dlcl9zdGF0dXNfY2hhbmdlZChzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQor eworCWludCByZXQgPSAwOworCWJvb2wgdmJ1c19wcmVzID0gZmFsc2U7CisJdWludDhfdCBkYXRh ID0gMDsKKworCXJldCA9IHJ0MTcxMWhfcmVnX3JlYWQoY2hpcCwgUlQxNzExSF9SRUdfUE9XRVJf U1RBVFVTLCAmZGF0YSk7CisJaWYgKHJldCA8IDApCisJCWdvdG8gb3V0OworCisJdmJ1c19wcmVz ID0gKGRhdGEgJiBSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVNfVkJVU19QUkVTKSA/IHRydWUgOiBm YWxzZTsKKwlpZiAodmJ1c19wcmVzICE9IGNoaXAtPnZidXNfcHJlc2VudCkgeworCQljaGlwLT52 YnVzX3ByZXNlbnQgPSB2YnVzX3ByZXM7CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyB2YnVzID0g JWRcbiIsIF9fZnVuY19fLCB2YnVzX3ByZXMpOworCQl0Y3BtX3ZidXNfY2hhbmdlKGNoaXAtPnRj cG1fcG9ydCk7CisJfQorCitvdXQ6CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBydDE3 MTFoX2FsZXJ0X3JlY3ZfbXNnKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXApCit7CisJaW50IHJl dCA9IDAsIGxlbiA9IDA7CisJdWludDhfdCBidWZbMl07CisJc3RydWN0IHBkX21lc3NhZ2UgbXNn OworCWNvbnN0IHVpbnQzMl90IGFsZXJ0X3J4ID0KKwkJUlQxNzExSF9SRUdfQUxFUlRfUlhfU1RB VFVTIHwgUlQxNzExSF9SRUdfQUxFUlRfUlhfQlVGX09WRjsKKworCXJ0MTcxMWhfbG9nKGNoaXAs ICIlc1xuIiwgX19mdW5jX18pOworCXJldCA9IHJ0MTcxMWhfcmVnX2Jsb2NrX3JlYWQoY2hpcCwg UlQxNzExSF9SRUdfUlhfSERSLCAyLCBidWYpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0 OworCisJbWVtY3B5KCYobXNnLmhlYWRlciksIGJ1ZiwgMik7CisKKwlsZW4gPSBwZF9oZWFkZXJf Y250X2xlKG1zZy5oZWFkZXIpICogNDsKKwlpZiAobGVuID4gUERfTUFYX1BBWUxPQUQgKiA0KSB7 CisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyBQRCBtZXNzYWdlIHRvbyBsb25nICVkXG4iLCBfX2Z1 bmNfXywgbGVuKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCWlmIChsZW4gPiAwKQorCQlyZXQg PSBydDE3MTFoX3JlZ19ibG9ja19yZWFkKGNoaXAsIFJUMTcxMUhfUkVHX1JYX0RBVEEsIGxlbiwK KwkJCSh1aW50OF90ICopbXNnLnBheWxvYWQpOworCisJLyogUmVhZCBjb21wbGV0ZSwgY2xlYXIg Ulggc3RhdHVzIGFsZXJ0IGJpdCAqLworCXJ0MTcxMWhfYWxlcnRfc3RhdHVzX2NsZWFyKGNoaXAs IGFsZXJ0X3J4KTsKKworCXRjcG1fcGRfcmVjZWl2ZShjaGlwLT50Y3BtX3BvcnQsICZtc2cpOwor CXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9hbGVydF9yZWN2X2hhcmRfcmVz ZXQoc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwl0Y3BtX3BkX2hhcmRfcmVzZXQoY2hp cC0+dGNwbV9wb3J0KTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2FsZXJ0 X3R4X2ZhaWxlZChzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCXRjcG1fcGRfdHJhbnNt aXRfY29tcGxldGUoY2hpcC0+dGNwbV9wb3J0LCBUQ1BDX1RYX0ZBSUxFRCk7CisJcmV0dXJuIDA7 Cit9CisKK3N0YXRpYyBpbnQgcnQxNzExaF9hbGVydF90eF9kaXNjYXJkKHN0cnVjdCBydDE3MTFo X2NoaXAgKmNoaXApCit7CisJdGNwbV9wZF90cmFuc21pdF9jb21wbGV0ZShjaGlwLT50Y3BtX3Bv cnQsIFRDUENfVFhfRElTQ0FSREVEKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3 MTFoX2FsZXJ0X3R4X3N1Y2Nlc3Moc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwl0Y3Bt X3BkX3RyYW5zbWl0X2NvbXBsZXRlKGNoaXAtPnRjcG1fcG9ydCwgVENQQ19UWF9TVUNDRVNTKTsK KwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2FsZXJ0X2ZhdWx0KHN0cnVjdCBy dDE3MTFoX2NoaXAgKmNoaXApCit7CisJaW50IHJldCA9IDA7CisJdWludDhfdCBzdGF0dXMgPSAw OworCisJcmV0ID0gcnQxNzExaF9nZXRfZmF1bHRfc3RhdHVzKGNoaXAsICZzdGF0dXMpOworCWlm IChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJcnQxNzExaF9sb2coY2hpcCwgIiVzIDB4JTAy WFxuIiwgX19mdW5jX18sIHN0YXR1cyk7CisJcnQxNzExaF9mYXVsdF9zdGF0dXNfY2xlYXIoY2hp cCwgc3RhdHVzKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFoX2FsZXJ0X3J4 X292ZXJmbG93KHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXApCit7CisJaW50IHJldCA9IDA7CisJ dWludDMyX3QgYWxlcnRfc3RhdHVzID0gMDsKKworCXJ0MTcxMWhfbG9nKGNoaXAsICIlc1xuIiwg X19mdW5jX18pOworCisJcmV0ID0gcnQxNzExaF9nZXRfYWxlcnRfc3RhdHVzKGNoaXAsICZhbGVy dF9zdGF0dXMpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJaWYgKGFsZXJ0X3N0 YXR1cyAmIFJUMTcxMUhfUkVHX0FMRVJUX1JYX1NUQVRVUykKKwkJcmV0dXJuIHJ0MTcxMWhfYWxl cnRfcmVjdl9tc2coY2hpcCk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBydDE3MTFo X2FsZXJ0X3dha2V1cChzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCXJ0MTcxMWhfbG9n KGNoaXAsICIlc1xuIiwgX19mdW5jX18pOworCWlmIChjaGlwLT5kcnBfdG9nZ2xpbmcpCisJCXJ0 MTcxMWhfZW5hYmxlX3dha2V1cF90aW1lcihjaGlwLCB0cnVlKTsKKwlyZXR1cm4gMDsKK30KKwor c3RhdGljIGludCBydDE3MTFoX2FsZXJ0X3JhX2RldGFjaChzdHJ1Y3QgcnQxNzExaF9jaGlwICpj aGlwKQoreworCXJ0MTcxMWhfbG9nKGNoaXAsICIlc1xuIiwgX19mdW5jX18pOworCWlmIChjaGlw LT5kcnBfdG9nZ2xpbmcpCisJCXJ0MTcxMWhfZW50ZXJfbHBtX2FnYWluKGNoaXApOworCisJcmV0 dXJuIDA7Cit9CisKK3N0cnVjdCBydDE3MTFoX2FsZXJ0X2hhbmRsZXIgeworCXVpbnQzMl90IGJp dF9tYXNrOworCWludCAoKmhhbmRsZXIpKHN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXApOworfTsK KworI2RlZmluZSBSVDE3MTFIX0RFQ0xfQUxFUlRfSEFORExFUih4Yml0LCB4aGFuZGxlcikgeyBc CisJLmJpdF9tYXNrID0gMSA8PCB4Yml0LCBcCisJLmhhbmRsZXIgPSB4aGFuZGxlciwgXAorfQor CitzdGF0aWMgY29uc3Qgc3RydWN0IHJ0MTcxMWhfYWxlcnRfaGFuZGxlciBydDE3MTFoX2FsZXJ0 X2hhbmRsZXJzW10gPSB7CisJUlQxNzExSF9ERUNMX0FMRVJUX0hBTkRMRVIoNCwgcnQxNzExaF9h bGVydF90eF9mYWlsZWQpLAorCVJUMTcxMUhfREVDTF9BTEVSVF9IQU5ETEVSKDUsIHJ0MTcxMWhf YWxlcnRfdHhfZGlzY2FyZCksCisJUlQxNzExSF9ERUNMX0FMRVJUX0hBTkRMRVIoNiwgcnQxNzEx aF9hbGVydF90eF9zdWNjZXNzKSwKKwlSVDE3MTFIX0RFQ0xfQUxFUlRfSEFORExFUigyLCBydDE3 MTFoX2FsZXJ0X3JlY3ZfbXNnKSwKKwlSVDE3MTFIX0RFQ0xfQUxFUlRfSEFORExFUig3LCBOVUxM KSwKKwlSVDE3MTFIX0RFQ0xfQUxFUlRfSEFORExFUig4LCBOVUxMKSwKKwlSVDE3MTFIX0RFQ0xf QUxFUlRfSEFORExFUigzLCBydDE3MTFoX2FsZXJ0X3JlY3ZfaGFyZF9yZXNldCksCisJUlQxNzEx SF9ERUNMX0FMRVJUX0hBTkRMRVIoMTAsIHJ0MTcxMWhfYWxlcnRfcnhfb3ZlcmZsb3cpLAorCVJU MTcxMUhfREVDTF9BTEVSVF9IQU5ETEVSKDE2LCBydDE3MTFoX2FsZXJ0X3dha2V1cCksCisJUlQx NzExSF9ERUNMX0FMRVJUX0hBTkRMRVIoMjEsIHJ0MTcxMWhfYWxlcnRfcmFfZGV0YWNoKSwKKwlS VDE3MTFIX0RFQ0xfQUxFUlRfSEFORExFUig5LCBydDE3MTFoX2FsZXJ0X2ZhdWx0KSwKKwlSVDE3 MTFIX0RFQ0xfQUxFUlRfSEFORExFUigwLCBydDE3MTFoX2FsZXJ0X2NjX2NoYW5nZWQpLAorCVJU MTcxMUhfREVDTF9BTEVSVF9IQU5ETEVSKDEsIHJ0MTcxMWhfYWxlcnRfcG93ZXJfc3RhdHVzX2No YW5nZWQpLAorfTsKKworc3RhdGljIGludCBfX3J0MTcxMWhfaXJxX2hhbmRsZXIoc3RydWN0IHJ0 MTcxMWhfY2hpcCAqY2hpcCkKK3sKKwlpbnQgaSA9IDAsIHJldCA9IDA7CisJdWludDMyX3QgYWxl cnRfc3RhdHVzID0gMDsKKworCXJldCA9IHJ0MTcxMWhfZ2V0X2FsZXJ0X3N0YXR1cyhjaGlwLCAm YWxlcnRfc3RhdHVzKTsKKwlpZiAocmV0IDwgMCkgeworCQlydDE3MTFoX2xvZyhjaGlwLCAiJXMg Z2V0IGFsZXJ0IHN0YXR1cyBmYWlsKCVkKVxuIiwKKwkJCV9fZnVuY19fLCByZXQpOworCQlnb3Rv IG91dDsKKwl9CisKKwlydDE3MTFoX2FsZXJ0X3N0YXR1c19jbGVhcihjaGlwLAorCQlhbGVydF9z dGF0dXMgJiAoflJUMTcxMUhfUkVHX0FMRVJUX1JYX01BU0spKTsKKworCWlmIChhbGVydF9zdGF0 dXMpCisJCXJ0MTcxMWhfbG9nKGNoaXAsICIlcyAweCUwNFhcbiIsIF9fZnVuY19fLCBhbGVydF9z dGF0dXMpOworCisJaWYgKGFsZXJ0X3N0YXR1cyAmIFJUMTcxMUhfUkVHX0FMRVJUX0VYVF9WQlVT XzgwKQorCQlhbGVydF9zdGF0dXMgfD0gUlQxNzExSF9SRUdfQUxFUlRfUE9XRVJfU1RBVFVTOwor CisJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUocnQxNzExaF9hbGVydF9oYW5kbGVycyk7IGkr KykgeworCQlpZiAocnQxNzExaF9hbGVydF9oYW5kbGVyc1tpXS5iaXRfbWFzayAmIGFsZXJ0X3N0 YXR1cykgeworCQkJaWYgKHJ0MTcxMWhfYWxlcnRfaGFuZGxlcnNbaV0uaGFuZGxlciAhPSAwKQor CQkJCXJ0MTcxMWhfYWxlcnRfaGFuZGxlcnNbaV0uaGFuZGxlcihjaGlwKTsKKwkJfQorCX0KKwor b3V0OgorCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCBydDE3MTFoX3BvbGxf Y3RybChzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWNhbmNlbF9kZWxheWVkX3dvcmtf c3luYygmY2hpcC0+cG9sbF93b3JrKTsKKworCWlmIChhdG9taWNfcmVhZCgmY2hpcC0+cG9sbF9j b3VudCkgPT0gMCkgeworCQlhdG9taWNfaW5jKCZjaGlwLT5wb2xsX2NvdW50KTsKKwkJY3B1X2lk bGVfcG9sbF9jdHJsKHRydWUpOworCX0KKworCXNjaGVkdWxlX2RlbGF5ZWRfd29yaygmY2hpcC0+ cG9sbF93b3JrLCBtc2Vjc190b19qaWZmaWVzKDQwKSk7Cit9CisKK3N0YXRpYyB2b2lkIHJ0MTcx MWhfaXJxX3dvcmtfaGFuZGxlcihzdHJ1Y3Qga3RocmVhZF93b3JrICp3b3JrKQoreworCXN0cnVj dCBydDE3MTFoX2NoaXAgKmNoaXAgPQorCQljb250YWluZXJfb2Yod29yaywgc3RydWN0IHJ0MTcx MWhfY2hpcCwgaXJxX3dvcmspOworCWludCByZXQgPSAwLCBncGlvX3ZhbCA9IDA7CisKKwlydDE3 MTFoX3BvbGxfY3RybChjaGlwKTsKKwltdXRleF9sb2NrKCZjaGlwLT53YWtldXBfbG9jayk7CisJ bXV0ZXhfbG9jaygmY2hpcC0+bG9jayk7CisJZG8geworCQlyZXQgPSBfX3J0MTcxMWhfaXJxX2hh bmRsZXIoY2hpcCk7CisJCWlmIChyZXQgPCAwKQorCQkJYnJlYWs7CisJCWdwaW9fdmFsID0gZ3Bp b19nZXRfdmFsdWUoY2hpcC0+aXJxX2dwaW8pOworCX0gd2hpbGUgKGdwaW9fdmFsID09IDApOwor CW11dGV4X3VubG9jaygmY2hpcC0+bG9jayk7CisJbXV0ZXhfdW5sb2NrKCZjaGlwLT53YWtldXBf bG9jayk7Cit9CisKK3N0YXRpYyB2b2lkIHJ0MTcxMWhfcG9sbF93b3JrKHN0cnVjdCB3b3JrX3N0 cnVjdCAqd29yaykKK3sKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gY29udGFpbmVyX29m KHdvcmssIHN0cnVjdCBydDE3MTFoX2NoaXAsCisJCXBvbGxfd29yay53b3JrKTsKKworCWlmICAo YXRvbWljX2RlY19hbmRfdGVzdCgmY2hpcC0+cG9sbF9jb3VudCkpCisJCWNwdV9pZGxlX3BvbGxf Y3RybChmYWxzZSk7Cit9CisjZGVmaW5lIFJUMTcxMUhfSVJRX1dBS0VfVElNRQkoNTAwKSAvKiBt cyAqLworCitzdGF0aWMgaXJxcmV0dXJuX3QgcnQxNzExaF9pbnRyX2hhbmRsZXIoaW50IGlycSwg dm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgcnQxNzExaF9jaGlwICpjaGlwID0gZGF0YTsKKworCXBt X3dha2V1cF9ldmVudChjaGlwLT5kZXYsIFJUMTcxMUhfSVJRX1dBS0VfVElNRSk7CisJa3RocmVh ZF9xdWV1ZV93b3JrKCZjaGlwLT5pcnFfd29ya2VyLCAmY2hpcC0+aXJxX3dvcmspOworCisJcmV0 dXJuIElSUV9IQU5ETEVEOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfaW5pdF9hbGVydChzdHJ1 Y3QgcnQxNzExaF9jaGlwICpjaGlwKQoreworCWludCByZXQgPSAwLCBsZW4gPSAwOworCWNoYXIg Km5hbWUgPSBOVUxMOworCXN0cnVjdCBzY2hlZF9wYXJhbSBwYXJhbSA9IHsuc2NoZWRfcHJpb3Jp dHkgPSBNQVhfUlRfUFJJTyAtIDF9OworCisJcnQxNzExaF9yZWdfd3JpdGVfd29yZChjaGlwLCBS VDE3MTFIX1JFR19BTEVSVF9NQVNLLCAwKTsKKwlydDE3MTFoX3JlZ193cml0ZV93b3JkKGNoaXAs IFJUMTcxMUhfUkVHX0FMRVJULCAweGZmZmYpOworCisJbGVuID0gc3RybGVuKGNoaXAtPm5hbWUp OworCW5hbWUgPSBkZXZtX2t6YWxsb2MoY2hpcC0+ZGV2LCBsZW4gKyA1LCBHRlBfS0VSTkVMKTsK KwlpZiAoIW5hbWUpCisJCXJldHVybiAtRU5PTUVNOworCisJc25wcmludGYobmFtZSwgbGVuLCAi JXMtSVJRIiwgY2hpcC0+bmFtZSk7CisKKwlkZXZfaW5mbyhjaGlwLT5kZXYsICIlcyBuYW1lID0g JXMsIGdwaW8gPSAlZFxuIiwgX19mdW5jX18sIGNoaXAtPm5hbWUsCisJCWNoaXAtPmlycV9ncGlv KTsKKworCXJldCA9IGRldm1fZ3Bpb19yZXF1ZXN0X29uZShjaGlwLT5kZXYsIGNoaXAtPmlycV9n cGlvLAorCQlHUElPRl9JTiwgbmFtZSk7CisJaWYgKHJldCA8IDApIHsKKwkJZGV2X2VycihjaGlw LT5kZXYsICIlcyByZXF1ZXN0IGdwaW8gZmFpbCglZClcbiIsCisJCQlfX2Z1bmNfXywgcmV0KTsK KwkJZ290byBlcnJfaW5pdF9hbGVydDsKKwl9CisKKwljaGlwLT5pcnEgPSBncGlvX3RvX2lycShj aGlwLT5pcnFfZ3Bpbyk7CisJaWYgKGNoaXAtPmlycSA8PSAwKSB7CisJCWRldl9lcnIoY2hpcC0+ ZGV2LCAiJXMgZ3BpbzJpcnEgZmFpbCglZClcbiIsCisJCQlfX2Z1bmNfXywgY2hpcC0+aXJxKTsK KwkJcmV0ID0gLUVJTlZBTDsKKwkJZ290byBlcnJfaW5pdF9hbGVydDsKKwl9CisJZGV2X2luZm8o Y2hpcC0+ZGV2LCAiJXMgaXJxID0gJWRcbiIsIF9fZnVuY19fLCBjaGlwLT5pcnEpOworCisJa3Ro cmVhZF9pbml0X3dvcmtlcigmY2hpcC0+aXJxX3dvcmtlcik7CisJY2hpcC0+aXJxX3dvcmtlcl90 YXNrID0ga3RocmVhZF9ydW4oa3RocmVhZF93b3JrZXJfZm4sCisJCSZjaGlwLT5pcnFfd29ya2Vy LCBjaGlwLT5uYW1lKTsKKwlpZiAoSVNfRVJSKGNoaXAtPmlycV93b3JrZXJfdGFzaykpIHsKKwkJ ZGV2X2VycihjaGlwLT5kZXYsICIlcyBjb3VsZCBub3QgY3JlYXRlIHRjcGMgdGFza1xuIiwgX19m dW5jX18pOworCQlnb3RvIGVycl9pbml0X2FsZXJ0OworCX0KKworCXNjaGVkX3NldHNjaGVkdWxl cihjaGlwLT5pcnFfd29ya2VyX3Rhc2ssIFNDSEVEX0ZJRk8sICZwYXJhbSk7CisJa3RocmVhZF9p bml0X3dvcmsoJmNoaXAtPmlycV93b3JrLCBydDE3MTFoX2lycV93b3JrX2hhbmRsZXIpOworCisJ cmV0ID0gZGV2bV9yZXF1ZXN0X2lycShjaGlwLT5kZXYsIGNoaXAtPmlycSwgcnQxNzExaF9pbnRy X2hhbmRsZXIsCisJCUlSUUZfVFJJR0dFUl9GQUxMSU5HIHwgSVJRRl9OT19USFJFQUQgfCBJUlFG X05PX1NVU1BFTkQsIG5hbWUsCisJCWNoaXApOworCWlmIChyZXQgPCAwKSB7CisJCWRldl9lcnIo Y2hpcC0+ZGV2LCAiJXMgcmVxdWVzdCBpcnElZCBmYWlsKCVkKVxuIiwKKwkJCV9fZnVuY19fLCBj aGlwLT5pcnEsIHJldCk7CisJCWdvdG8gZXJyX2luaXRfYWxlcnQ7CisJfQorCWVuYWJsZV9pcnFf d2FrZShjaGlwLT5pcnEpOworCXJldHVybiAwOworCitlcnJfaW5pdF9hbGVydDoKKwlkZXZtX2tm cmVlKGNoaXAtPmRldiwgbmFtZSk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBydDE3 MTFoX2NoZWNrX3JldmlzaW9uKHN0cnVjdCBpMmNfY2xpZW50ICppMmMpCit7CisJaW50IHJldCA9 IDA7CisKKwlyZXQgPSBpMmNfc21idXNfcmVhZF93b3JkX2RhdGEoaTJjLCAweDAwKTsKKwlpZiAo cmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKwlpZiAocmV0ICE9IDB4MjljZikgeworCQlkZXZfZXJy KCZpMmMtPmRldiwgInZpZCBpcyBub3QgY29ycmVjdCwgMHglMDR4XG4iLCByZXQpOworCQlyZXR1 cm4gLUVOT0RFVjsKKwl9CisJcmV0ID0gaTJjX3NtYnVzX3JlYWRfd29yZF9kYXRhKGkyYywgMHgw Mik7CisJaWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisJaWYgKHJldCAhPSAweDE3MTEpIHsK KwkJZGV2X2VycigmaTJjLT5kZXYsICJwaWQgaXMgbm90IGNvcnJlY3QsIDB4JTA0eFxuIiwgcmV0 KTsKKwkJcmV0dXJuIC1FTk9ERVY7CisJfQorCXJldCA9IGkyY19zbWJ1c19yZWFkX3dvcmRfZGF0 YShpMmMsIDB4MDQpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCS8qIHJldHVybiBk aWQgKi8KKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfaTJjX3Byb2JlKHN0 cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCisJCQkgICAgIGNvbnN0IHN0cnVjdCBpMmNfZGV2aWNl X2lkICppZCkKK3sKKwlpbnQgcmV0ID0gMDsKKwl1aW50MTZfdCBkaWQgPSAwOworCXN0cnVjdCBy dDE3MTFoX2NoaXAgKmNoaXAgPSBOVUxMOworCXN0cnVjdCBwb3dlcl9zdXBwbHlfY29uZmlnIGNm ZyA9IHt9OworCisJcHJfaW5mbygiJXMgJXNcbiIsIF9fZnVuY19fLCBSVDE3MTFIX0RSVl9WRVJT SU9OKTsKKworCWlmICghaTJjX2NoZWNrX2Z1bmN0aW9uYWxpdHkoY2xpZW50LT5hZGFwdGVyLAor CQlJMkNfRlVOQ19TTUJVU19JMkNfQkxPQ0spKSB7CisJCWRldl9lcnIoJmNsaWVudC0+ZGV2LAor CQkJIkkyQy9TTUJ1c3l5IGJsb2NrIGZ1bmN0aW9uYWxpdHkgbm90IHN1cHBvcnRlZCFcbiIpOwor CQlyZXR1cm4gLUVOT0RFVjsKKwl9CisJcmV0ID0gcnQxNzExaF9jaGVja19yZXZpc2lvbihjbGll bnQpOworCWlmIChyZXQgPCAwKSB7CisJCWRldl9lcnIoJmNsaWVudC0+ZGV2LCAiY2hlY2sgdmlk L3BpZC9kaWQgZmFpbFxuIik7CisJCXJldHVybiByZXQ7CisJfQorCWRpZCA9ICh1aW50MTZfdCly ZXQ7CisJZGV2X2luZm8oJmNsaWVudC0+ZGV2LCAiZGlkID0gMHglMDR4XG4iLCBkaWQpOworCWNo aXAgPSBkZXZtX2t6YWxsb2MoJmNsaWVudC0+ZGV2LCBzaXplb2YoKmNoaXApLCBHRlBfS0VSTkVM KTsKKwlpZiAoIWNoaXApCisJCXJldHVybiAtRU5PTUVNOworCWNoaXAtPmkyYyA9IGNsaWVudDsK KwljaGlwLT5kZXYgPSAmY2xpZW50LT5kZXY7CisJY2hpcC0+ZGlkID0gZGlkOworCW11dGV4X2lu aXQoJmNoaXAtPmxvY2spOworCW11dGV4X2luaXQoJmNoaXAtPndha2V1cF9sb2NrKTsKKwlJTklU X0RFTEFZRURfV09SSygmY2hpcC0+cG9sbF93b3JrLCBydDE3MTFoX3BvbGxfd29yayk7CisJSU5J VF9ERUxBWUVEX1dPUksoJmNoaXAtPndha2V1cF93b3JrLCBydDE3MTFoX3dha2V1cF93b3JrKTsK KwlhbGFybV9pbml0KCZjaGlwLT53YWtldXBfdGltZXIsIEFMQVJNX1JFQUxUSU1FLAorCQlydDE3 MTFoX2FsYXJtX3dha2V1cF9oYW5kbGVyKTsKKwlpMmNfc2V0X2NsaWVudGRhdGEoY2xpZW50LCBj aGlwKTsKKworCXJldCA9IHJ0MTcxMWhfcGFyc2VfZHQoY2hpcCk7CisJaWYgKHJldCA8IDApCisJ CWdvdG8gb3V0X3BhcnNlX2R0OworCisJY2ZnLmRydl9kYXRhID0gY2hpcDsKKwljaGlwLT5wc3kg PSBkZXZtX3Bvd2VyX3N1cHBseV9yZWdpc3RlcihjaGlwLT5kZXYsICZydDE3MTFoX3BzeV9kZXNj LAorCQkmY2ZnKTsKKwlpZiAoSVNfRVJSKGNoaXAtPnBzeSkpIHsKKwkJcmV0ID0gUFRSX0VSUihj aGlwLT5wc3kpOworCQlkZXZfZXJyKGNoaXAtPmRldiwgIiVzIHJlZ2lzdGVyIHBzeSBmYWlsKCVk KVxuIiwgX19mdW5jX18sIHJldCk7CisJCWdvdG8gb3V0X3BzeV9yZWc7CisJfQorCisJY2hpcC0+ dmJ1cyA9IGRldm1fcmVndWxhdG9yX2dldChjaGlwLT5kZXYsICJ2YnVzIik7CisJaWYgKElTX0VS UihjaGlwLT52YnVzKSkgeworCQlyZXQgPSBQVFJfRVJSKGNoaXAtPnZidXMpOworCQlnb3RvIG91 dF9yZWdfZ2V0OworCX0KKworCXJldCA9IHJ0MTcxMWhfZGVidWdmc19pbml0KGNoaXApOworCWlm IChyZXQgPCAwKQorCQlnb3RvIG91dF9kYmdmc19pbml0OworCisJcmV0ID0gcnQxNzExaF9zb2Z0 d2FyZV9yZXNldChjaGlwKTsKKwlpZiAocmV0IDwgMCkKKwkJZ290byBvdXRfc3dfcmVzZXQ7CisK KwlyZXQgPSBydDE3MTFoX2luaXRfYWxlcnQoY2hpcCk7CisJaWYgKHJldCA8IDApCisJCWdvdG8g b3V0X2luaXRfYWxlcnQ7CisKKwlydDE3MTFoX2luaXRfdGNwY19kZXYoY2hpcCk7CisKKwljaGlw LT50Y3BtX3BvcnQgPSB0Y3BtX3JlZ2lzdGVyX3BvcnQoY2hpcC0+ZGV2LAorCQkmY2hpcC0+dGNw Y19kZXYpOworCWlmIChJU19FUlIoY2hpcC0+dGNwbV9wb3J0KSkgeworCQlyZXQgPSBQVFJfRVJS KGNoaXAtPnRjcG1fcG9ydCk7CisJCWRldl9lcnIoY2hpcC0+ZGV2LCAiJXMgcmVnaXN0ZXIgdGNw bSBwb3J0IGZhaWwoJWQpIiwKKwkJCV9fZnVuY19fLCByZXQpOworCQlnb3RvIG91dF90Y3BtX3Jl ZzsKKwl9CisKKwlwbV9ydW50aW1lX3NldF9hY3RpdmUoJmNsaWVudC0+ZGV2KTsKKwlwbV9ydW50 aW1lX2VuYWJsZSgmY2xpZW50LT5kZXYpOworCWRldl9pbmZvKGNoaXAtPmRldiwgIiVzOiBzdWNj ZXNzZnVsbHlcbiIsIF9fZnVuY19fKTsKKwlyZXR1cm4gMDsKKworb3V0X3RjcG1fcmVnOgorb3V0 X2luaXRfYWxlcnQ6CitvdXRfc3dfcmVzZXQ6CisJcnQxNzExaF9kZWJ1Z2ZzX2V4aXQoY2hpcCk7 CitvdXRfZGJnZnNfaW5pdDoKK291dF9yZWdfZ2V0Ogorb3V0X3BzeV9yZWc6CitvdXRfcGFyc2Vf ZHQ6CisJbXV0ZXhfZGVzdHJveSgmY2hpcC0+bG9jayk7CisJZGV2bV9rZnJlZSgmY2xpZW50LT5k ZXYsIGNoaXApOworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfaTJjX3JlbW92 ZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50KQoreworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNo aXAgPSBpMmNfZ2V0X2NsaWVudGRhdGEoY2xpZW50KTsKKworCXBtX3J1bnRpbWVfZGlzYWJsZSgm Y2xpZW50LT5kZXYpOworCXBtX3J1bnRpbWVfc2V0X3N1c3BlbmRlZCgmY2xpZW50LT5kZXYpOwor CWlmIChjaGlwKSB7CisJCXJ0MTcxMWhfZGVidWdmc19leGl0KGNoaXApOworCQltdXRleF9kZXN0 cm95KCZjaGlwLT5sb2NrKTsKKwl9CisJZGV2X2luZm8oY2hpcC0+ZGV2LCAiJXM6IHN1Y2Nlc3Nm dWxseVxuIiwgX19mdW5jX18pOworCXJldHVybiAwOworfQorCisjaWZkZWYgQ09ORklHX1BNX1NM RUVQCitzdGF0aWMgaW50IHJ0MTcxMWhfaTJjX3BtX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2 KQoreworCXN0cnVjdCBydDE3MTFoX2NoaXAgKmNoaXAgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsK KworCWlmIChjaGlwKSB7CisJCWlmIChhdG9taWNfcmVhZCgmY2hpcC0+aTJjX2J1c3kpKQorCQkJ cmV0dXJuIC1FQlVTWTsKKwkJYXRvbWljX3NldCgmY2hpcC0+cG1fc3VzcGVuZCwgMSk7CisJfQor CXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHJ0MTcxMWhfaTJjX3BtX3Jlc3VtZShzdHJ1Y3Qg ZGV2aWNlICpkZXYpCit7CisJc3RydWN0IHJ0MTcxMWhfY2hpcCAqY2hpcCA9IGRldl9nZXRfZHJ2 ZGF0YShkZXYpOworCisJaWYgKGNoaXApCisJCWF0b21pY19zZXQoJmNoaXAtPnBtX3N1c3BlbmQs IDApOworCXJldHVybiAwOworfQorI2VuZGlmIC8qIENPTkZJR19QTV9TTEVFUCAqLworCitzdGF0 aWMgY29uc3Qgc3RydWN0IGRldl9wbV9vcHMgcnQxNzExaF9pMmNfcG1fb3BzID0geworCVNFVF9T WVNURU1fU0xFRVBfUE1fT1BTKHJ0MTcxMWhfaTJjX3BtX3N1c3BlbmQsIHJ0MTcxMWhfaTJjX3Bt X3Jlc3VtZSkKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIHJ0MTcxMWhf b2ZfZGV2aWNlX2lkW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJyaWNodGVrLHR5cGVjX3J0MTcx MWgiLH0sCisJeyB9LAorfTsKK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIHJ0MTcxMWhfb2ZfZGV2 aWNlX2lkKTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBpMmNfZGV2aWNlX2lkIHJ0MTcxMWhfaTJj X2RldmljZV9pZFtdID0geworCXsgInR5cGVjX3J0MTcxMWgiLCAwfSwKKwl7IH0sCit9OworTU9E VUxFX0RFVklDRV9UQUJMRShpMmMsIHJ0MTcxMWhfaTJjX2RldmljZV9pZCk7CisKK3N0YXRpYyBz dHJ1Y3QgaTJjX2RyaXZlciBydDE3MTFoX2kyY19kcml2ZXIgPSB7CisJLmRyaXZlciA9IHsKKwkJ Lm5hbWUgPSAidHlwZWNfcnQxNzExaCIsCisJCS5vd25lciA9IFRISVNfTU9EVUxFLAorCQkub2Zf bWF0Y2hfdGFibGUgPSBvZl9tYXRjaF9wdHIocnQxNzExaF9vZl9kZXZpY2VfaWQpLAorCQkucG0g PSAmcnQxNzExaF9pMmNfcG1fb3BzLAorCX0sCisJLnByb2JlID0gcnQxNzExaF9pMmNfcHJvYmUs CisJLnJlbW92ZSA9IHJ0MTcxMWhfaTJjX3JlbW92ZSwKKwkuaWRfdGFibGUgPSBydDE3MTFoX2ky Y19kZXZpY2VfaWQsCit9OworbW9kdWxlX2kyY19kcml2ZXIocnQxNzExaF9pMmNfZHJpdmVyKTsK KworTU9EVUxFX0FVVEhPUigiY3lfaHVhbmcgPGN5X2h1YW5nQHJpY2h0ZWsuY29tPiIpOworTU9E VUxFX0RFU0NSSVBUSU9OKCJydDE3MTFoIHR5cGVjIGRyaXZlciIpOworTU9EVUxFX1ZFUlNJT04o UlQxNzExSF9EUlZfVkVSU0lPTik7CitNT0RVTEVfTElDRU5TRSgiR1BMIik7CmRpZmYgLS1naXQg YS9kcml2ZXJzL3VzYi90eXBlYy9ydDE3MTFoL3J0MTcxMWguaCBiL2RyaXZlcnMvdXNiL3R5cGVj L3J0MTcxMWgvcnQxNzExaC5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjhi Njc0NjQKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3VzYi90eXBlYy9ydDE3MTFoL3J0MTcx MWguaApAQCAtMCwwICsxLDMwMCBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0y LjArCisvKgorICogQ29weXJpZ2h0IDIwMTcgUmljaHRlayBUZWNobm9sb2doIENvcnAuCisgKgor ICogUmljaHRlayBSVDE3MTFIIFR5cGUtQyBDaGlwIERyaXZlcgorICovCisKKyNpZm5kZWYgX19M SU5VWF9SVDE3MTFIX0gKKyNkZWZpbmUgX19MSU5VWF9SVDE3MTFIX0gKKworLyogRGV2aWNlIElE ICovCisjZGVmaW5lIFJUMTcxMUhfRElEX0EJMHgyMTcwCisjZGVmaW5lIFJUMTcxMUhfRElEX0IJ MHgyMTcxCisjZGVmaW5lIFJUMTcxMUhfRElEX0MJMHgyMTcyCisjZGVmaW5lIFJUMTcxMUhfRElE X0QJMHgyMTczCisKKy8qIFJlZ2lzdGVycyAqLworI2RlZmluZSBSVDE3MTFIX1JFR19WSUQJCQkJ KDB4MDApCisjZGVmaW5lIFJUMTcxMUhfUkVHX1BJRAkJCQkoMHgwMikKKyNkZWZpbmUgUlQxNzEx SF9SRUdfRElECQkJCSgweDA0KQorI2RlZmluZSBSVDE3MTFIX1JFR19UWVBFQ19SRVYJCQkoMHgw NikKKyNkZWZpbmUgUlQxNzExSF9SRUdfUERfUkVWCQkJKDB4MDgpCisjZGVmaW5lIFJUMTcxMUhf UkVHX1BESUZfUkVWCQkJKDB4MEEpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0FMRVJUCQkJKDB4MTAp CisjZGVmaW5lIFJUMTcxMUhfUkVHX0FMRVJUX01BU0sJCQkoMHgxMikKKyNkZWZpbmUgUlQxNzEx SF9SRUdfUE9XRVJfU1RBVFVTX01BU0sJCSgweDE0KQorI2RlZmluZSBSVDE3MTFIX1JFR19GQVVM VF9TVEFUVVNfTUFTSwkJKDB4MTUpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1RDUENfQ1RSTAkJCSgw eDE5KQorI2RlZmluZSBSVDE3MTFIX1JFR19ST0xFX0NUUkwJCQkoMHgxQSkKKyNkZWZpbmUgUlQx NzExSF9SRUdfRkFVTFRfQ1RSTAkJCSgweDFCKQorI2RlZmluZSBSVDE3MTFIX1JFR19QT1dFUl9D VFJMCQkJKDB4MUMpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0NDX1NUQVRVUwkJCSgweDFEKQorI2Rl ZmluZSBSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVMJCSgweDFFKQorI2RlZmluZSBSVDE3MTFIX1JF R19GQVVMVF9TVEFUVVMJCSgweDFGKQorI2RlZmluZSBSVDE3MTFIX1JFR19DT01NQU5ECQkJKDB4 MjMpCisjZGVmaW5lIFJUMTcxMUhfUkVHX01TR19IRFJfSU5GTwkJKDB4MmUpCisjZGVmaW5lIFJU MTcxMUhfUkVHX1JYX0RFVEVDVAkJCSgweDJmKQorI2RlZmluZSBSVDE3MTFIX1JFR19SWF9CWVRF X0NOVAkJCSgweDMwKQorI2RlZmluZSBSVDE3MTFIX1JFR19SWF9CVUZfRlJBTUVfVFlQRQkJKDB4 MzEpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1JYX0hEUgkJCSgweDMyKQorI2RlZmluZSBSVDE3MTFI X1JFR19SWF9EQVRBCQkJKDB4MzQpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1RSQU5TTUlUCQkJKDB4 NTApCisjZGVmaW5lIFJUMTcxMUhfUkVHX1RYX0JZVEVfQ05UCQkJKDB4NTEpCisjZGVmaW5lIFJU MTcxMUhfUkVHX1RYX0hEUgkJCSgweDUyKQorI2RlZmluZSBSVDE3MTFIX1JFR19UWF9EQVRBCQkJ KDB4NTQpCisKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0NUUkwyCQkJKDB4ODcpCisjZGVmaW5l IFJUMTcxMUhfUkVHX0NMS19DVFJMMwkJCSgweDg4KQorI2RlZmluZSBSVDE3MTFIX1JFR19CTUNf Q1RSTAkJCSgweDkwKQorI2RlZmluZSBSVDE3MTFIX1JFR19CTUNJT19SWERaU0VMCQkoMHg5MykK KyNkZWZpbmUgUlQxNzExSF9SRUdfVkNPTk5fQ0xJTUlURU4JCSgweDk1KQorI2RlZmluZSBSVDE3 MTFIX1JFR19SVF9TVEFUVVMJCQkoMHg5NykKKyNkZWZpbmUgUlQxNzExSF9SRUdfUlRfSU5UCQkJ KDB4OTgpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1JUX01BU0sJCQkoMHg5OSkKKyNkZWZpbmUgUlQx NzExSF9SRUdfSURMRV9DVFJMCQkJKDB4OUIpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0lOVFJTVF9D VFJMCQkJKDB4OUMpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1dBVENIRE9HX0NUUkwJCSgweDlEKQor I2RlZmluZSBSVDE3MTFIX1JFR19JMkNSU1RfQ1RSTAkJCSgwWDlFKQorI2RlZmluZSBSVDE3MTFI X1JFR19TV1JFU0VUCQkJKDB4QTApCisjZGVmaW5lIFJUMTcxMUhfUkVHX1RUQ1BDX0ZJTFRFUgkJ KDB4QTEpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0RSUF9UT0dHTEVfQ1lDTEUJCSgweEEyKQorI2Rl ZmluZSBSVDE3MTFIX1JFR19EUlBfRFVUWV9DVFJMCQkoMHhBMykKKyNkZWZpbmUgUlQxNzExSF9S RUdfQk1DSU9fUlhEWkVOCQkoMHhBRikKKworCisjaWZuZGVmIEJJVAorI2RlZmluZSBCSVQoeCkJ KDEgPDwgKHgpKQorI2VuZGlmCisKKy8qCisgKiBSVDE3MTFIX1JFR19BTEVSVAkJCQkoMHgxMCkK KyAqIFJUMTcxMUhfUkVHX0FMRVJUX01BU0sJCQkoMHgxMikKKyAqLworI2RlZmluZSBSVDE3MTFI X1JFR19WQlVTX1NJTktfRElTQ09OTkVDVAlCSVQoMTEpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0FM RVJUX1JYX0JVRl9PVkYJCUJJVCgxMCkKKyNkZWZpbmUgUlQxNzExSF9SRUdfQUxFUlRfRkFVTFQJ CQlCSVQoOSkKKyNkZWZpbmUgUlQxNzExSF9SRUdfQUxFUlRfTE9fVk9MVAkJQklUKDgpCisjZGVm aW5lIFJUMTcxMUhfUkVHX0FMRVJUX0hJX1ZPTFQJCUJJVCg3KQorI2RlZmluZSBSVDE3MTFIX1JF R19BTEVSVF9UWF9TVUNDRVNTCQlCSVQoNikKKyNkZWZpbmUgUlQxNzExSF9SRUdfQUxFUlRfVFhf RElTQ0FSREVECQlCSVQoNSkKKyNkZWZpbmUgUlQxNzExSF9SRUdfQUxFUlRfVFhfRkFJTEVECQlC SVQoNCkKKyNkZWZpbmUgUlQxNzExSF9SRUdfQUxFUlRfUlhfSEFSRF9SU1QJCUJJVCgzKQorI2Rl ZmluZSBSVDE3MTFIX1JFR19BTEVSVF9SWF9TVEFUVVMJCUJJVCgyKQorI2RlZmluZSBSVDE3MTFI X1JFR19BTEVSVF9QT1dFUl9TVEFUVVMJCUJJVCgxKQorI2RlZmluZSBSVDE3MTFIX1JFR19BTEVS VF9DQ19TVEFUVVMJCUJJVCgwKQorI2RlZmluZSBSVDE3MTFIX1JFR19BTEVSVF9SWF9NQVNLIFwK KwkoUlQxNzExSF9SRUdfQUxFUlRfUlhfU1RBVFVTIHwgUlQxNzExSF9SRUdfQUxFUlRfUlhfQlVG X09WRikKKworLyoKKyAqIFJUMTcxMUhfUkVHX1BPV0VSX1NUQVRVU19NQVNLCQkoMHgxNCkKKyAq IFJUMTcxMUhfUkVHX1BPV0VSX1NUQVRVUwkJCSgweDFFKQorICovCisjZGVmaW5lIFJUMTcxMUhf UkVHX1BPV0VSX1NUQVRVU19UQ1BDX0lOSVRJQUwJQklUKDYpCisjZGVmaW5lIFJUMTcxMUhfUkVH X1BPV0VSX1NUQVRVU19TUkNfSFYJCUJJVCg1KQorI2RlZmluZSBSVDE3MTFIX1JFR19QT1dFUl9T VEFUVVNfU1JDX1ZCVVMJQklUKDQpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1BPV0VSX1NUQVRVU19W QlVTX1BSRVNfREVUCUJJVCgzKQorI2RlZmluZSBSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVNfVkJV U19QUkVTCUJJVCgyKQorI2RlZmluZSBSVDE3MTFIX1JFR19QT1dFUl9TVEFUVVNfVkNPTk5fUFJF UwlCSVQoMSkKKyNkZWZpbmUgUlQxNzExSF9SRUdfUE9XRVJfU1RBVFVTX1NJTktfVkJVUwlCSVQo MCkKKworLyoKKyAqIFJUMTcxMUhfUkVHX0ZBVUxUX1NUQVRVU19NQVNLCQkoMHgxNSkKKyAqIFJU MTcxMUhfUkVHX0ZBVUxUX1NUQVRVUwkJCSgweDFGKQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVH X0ZBVUxUX1NUQVRVU19WQ09OTl9PVgkJQklUKDcpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0ZBVUxU X1NUQVRVU19GT1JDRV9PRkZfVkJVUwkJQklUKDYpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0ZBVUxU X1NUQVRVU19BVVRPX0RJU0NfRkFJTAkJQklUKDUpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0ZBVUxU X1NUQVRVU19GT1JDRV9ESVNDX0ZBSUwJQklUKDQpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0ZBVUxU X1NUQVRVU19WQlVTX09DCQlCSVQoMykKKyNkZWZpbmUgUlQxNzExSF9SRUdfRkFVTFRfU1RBVFVT X1ZCVVNfT1YJCUJJVCgyKQorI2RlZmluZSBSVDE3MTFIX1JFR19GQVVMVF9TVEFUVVNfVkNPTk5f T0MJCUJJVCgxKQorI2RlZmluZSBSVDE3MTFIX1JFR19GQVVMVF9TVEFUVVNfSTJDX0VSUk9SCQlC SVQoMCkKKworLyoKKyAqIFJUMTcxMUhfUkVHX1JPTEVfQ1RSTAkJCSgweDFBKQorICovCisjZGVm aW5lIFJUMTcxMUhfUkVHX1JPTEVfQ1RSTF9EUlAJCUJJVCg2KQorI2RlZmluZSBSVDE3MTFIX1JF R19ST0xFX0NUUkxfUkVTX1NFVChkcnAsIHJwLCBjYzEsIGNjMikgXAorCSgoZHJwKSA8PCA2IHwg KHJwKSA8PCA0IHwgKGNjMikgPDwgMiB8IChjYzEpKQorI2RlZmluZSBSVDE3MTFIX1JFR19ST0xF X0NUUkxfQ0MyKHJlZykJCQkoKChyZWcpICYgMHgwQykgPj4gMikKKyNkZWZpbmUgUlQxNzExSF9S RUdfUk9MRV9DVFJMX0NDMShyZWcpCQkJKChyZWcpICYgMHgwMykKKyNkZWZpbmUgUlQxNzExSF9U WVBFQ19DQ19QVUxMX0dFVF9SUF9MVkwocHVsbCkJCSgocHVsbCAmIDB4MTgpID4+IDMpCisjZGVm aW5lIFJUMTcxMUhfVFlQRUNfQ0NfUFVMTF9HRVRfUkVTKHB1bGwpCQkocHVsbCAmIDB4MDcpCisK K2VudW0gdHlwZWNfY2NfcHVsbCB7CisJVFlQRUNfQ0NfUFVMTF9SQSA9IDAsCisJVFlQRUNfQ0Nf UFVMTF9SUCwKKwlUWVBFQ19DQ19QVUxMX1JELAorCVRZUEVDX0NDX1BVTExfT1BFTiwKKwlUWVBF Q19DQ19QVUxMX0RSUCwJLyogZnJvbSByZCAqLworCisJVFlQRUNfQ0NfUFVMTF9SUF9ERUYgPSAx LAkvKiAweDAwICsgMSAqLworCVRZUEVDX0NDX1BVTExfUlBfMV81ID0gOSwJLyogMHgwOCArIDEg Ki8KKwlUWVBFQ19DQ19QVUxMX1JQXzNfMCA9IDE3LAkvKiAweDEwICsgMSAqLworCisJVFlQRUNf Q0NfUFVMTF9EUlBfREVGID0gNCwJLyogMHgwMCArIDQgKi8KKwlUWVBFQ19DQ19QVUxMX0RSUF8x XzUgPSAxMiwJLyogMHgwOCArIDQgKi8KKwlUWVBFQ19DQ19QVUxMX0RSUF8zXzAgPSAyMCwJLyog MHgxMCArIDQgKi8KK307CisKKy8qCisgKiBSVDE3MTFIX1JFR19UQ1BDX0NUUkwJCQkoMHgxOSkK KyAqLworI2RlZmluZSBSVDE3MTFIX1JFR19UQ1BDX0NUUkxfQklTVF9URVNUX01PREUJQklUKDEp CisjZGVmaW5lIFJUMTcxMUhfUkVHX1RDUENfQ1RSTF9QTFVHX09SSUVOVAlCSVQoMCkKKworLyoK KyAqIFJUMTcxMUhfUkVHX0ZBVUxUX0NUUkwJCQkoMHgxQikKKyAqLworI2RlZmluZSBSVDE3MTFI X1JFR19GQVVMVF9DVFJMX0RJU19WQ09OTl9PVglCSVQoNykKKyNkZWZpbmUgUlQxNzExSF9SRUdf RkFVTFRfQ1RSTF9ESVNfU05LX1ZCVVNfT0MJQklUKDIpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0ZB VUxUX0NUUkxfRElTX1ZDT05OX09DCUJJVCgwKQorCisvKgorICogUlQxNzExSF9SRUdfUE9XRVJf Q1RSTAkJCSgweDFDKQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX1BPV0VSX0NUUkxfVkNPTk4J CUJJVCgwKQorCisvKgorICogUlQxNzExSF9SRUdfQ0NfU1RBVFVTCQkJKDB4MUQpCisgKi8KKyNk ZWZpbmUgUlQxNzExSF9SRUdfQ0NfU1RBVFVTX0RSUF9UT0dHTElORwlCSVQoNSkKKyNkZWZpbmUg UlQxNzExSF9SRUdfQ0NfU1RBVFVTX0RSUF9SRVNVTFQocmVnKQkoKChyZWcpICYgMHgxMCkgPj4g NCkKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0NfU1RBVFVTX0NDMihyZWcpCQkoKChyZWcpICYgMHgw QykgPj4gMikKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0NfU1RBVFVTX0NDMShyZWcpCQkoKHJlZykg JiAweDAzKQorI2RlZmluZSBSVDE3MTFIX1JFR19DQ19TVEFUVVNfUkQyRU5VTShjYykJKChjYykg KyAyKQorCisvKgorICogUlQxNzExSF9SRUdfQ09NTUFORAkJCQkoMHgyMykKKyAqLworZW51bSBy dDE3MTFoX2NvbW1hbmQgeworCVJUMTcxMUhfQ01EX1dBS0VfSTJDID0gMHgxMSwKKwlSVDE3MTFI X0NNRF9ESVNBQkxFX1ZCVVNfREVURUNUID0gMHgyMiwKKwlSVDE3MTFIX0NNRF9FTkFCTEVfVkJV U19ERVRFQ1QgPSAweDMzLAorCVJUMTcxMUhfQ01EX0RJU0FCTEVfU0lOS19WQlVTID0gMHg0NCwK KwlSVDE3MTFIX0NNRF9FTkFCTEVfU0lOS19WQlVTID0gMHg1NSwKKwlSVDE3MTFIX0NNRF9ESVNB QkxFX1NPVVJDRV9WQlVTID0gMHg2NiwKKwlSVDE3MTFIX0NNRF9FTkFCTEVfU09VUkNFX1ZCVVMg PSAweDc3LAorCVJUMTcxMUhfQ01EX1NPVVJDRV9WQlVTX0hWID0gMHg4OCwKKwlSVDE3MTFIX0NN RF9MT09LX0NPTk5FQ1RJT04gPSAweDk5LAorCVJUMTcxMUhfQ01EX1JYX09ORV9NT0RFID0gMHhB QSwKKwlSVDE3MTFIX0NNRF9JMkNfSURMRSA9IDB4RkYsCit9OworCisKKy8qCisgKiBSVDE3MTFI X1JFR19NU0dfSERSX0lORk8JCQkoMHgyRSkKKyAqLworI2RlZmluZSBSVDE3MTFIX1JFR19NU0df SERSX0lORk9fU0VUKGRyb2xlLCBwcm9sZSkgXAorCSgoZHJvbGUpIDw8IDMgfCAoUERfUkVWMjAg PDwgMSkgfCAocHJvbGUpKQorI2RlZmluZSBSVDE3MTFIX1JFR19NU0dfSERSX0lORk9fRFJPTEUo cmVnKQkoKChyZWcpICYgMHgwOCkgPj4gMykKKyNkZWZpbmUgUlQxNzExSF9SRUdfTVNHX0hEUl9J TkZPX1BST0xFKHJlZykJKChyZWcpICYgMHgwMSkKKworLyoKKyAqIFJUMTcxMUhfUkVHX1RSQU5T TUlUCQkJCSgweDUwKQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX1RSQU5TTUlUX1NFVChyZXRy eSwgdHlwZSkJKChyZXRyeSkgPDwgNCB8ICh0eXBlKSkKKworCisvKgorICogUlQxNzExSF9SRUdf Q0xLX0NUUkwyCQkJKDB4ODcpCisgKi8KKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0RJVl82MDBL X0VOCQlCSVQoNykKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0JDTEsyX0VOCQlCSVQoNikKKyNk ZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0JDTEsyX1RHX0VOCQlCSVQoNSkKKyNkZWZpbmUgUlQxNzEx SF9SRUdfQ0xLX0RJVl8zMDBLX0VOCQlCSVQoMykKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0NL XzMwMEtfRU4JCUJJVCgyKQorI2RlZmluZSBSVDE3MTFIX1JFR19DTEtfQkNMS19FTgkJCUJJVCgx KQorI2RlZmluZSBSVDE3MTFIX1JFR19DTEtfQkNMS19USF9FTgkJQklUKDApCisKKy8qCisgKiBS VDE3MTFIX1JFR19DTEtfQ1RSTDMJCQkoMHg4OCkKKyAqLworI2RlZmluZSBSVDE3MTFIX1JFR19D TEtfT1NDTVVYX1JHX0VOCQlCSVQoNykKKyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX0NLXzI0TV9F TgkJQklUKDYpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0NMS19PU0NfUkdfRU4JCUJJVCg1KQorI2Rl ZmluZSBSVDE3MTFIX1JFR19DTEtfRElWXzJQNE1fRU4JCUJJVCg0KQorI2RlZmluZSBSVDE3MTFI X1JFR19DTEtfQ0tfMlA0TV9FTgkJQklUKDMpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0NMS19QQ0xL X0VOCQkJQklUKDIpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0NMS19QQ0xLX1JHX0VOCQlCSVQoMSkK KyNkZWZpbmUgUlQxNzExSF9SRUdfQ0xLX1BDTEtfVEdfRU4JCUJJVCgwKQorCisvKgorICogUlQx NzExSF9SRUdfQk1DX0NUUkwJCQkJKDB4OTApCisgKi8KKyNkZWZpbmUgUlQxNzExSF9SRUdfSURM RV9FTgkJCUJJVCg2KQorI2RlZmluZSBSVDE3MTFIX1JFR19ESVNDSEFSR0VfRU4JCUJJVCg1KQor I2RlZmluZSBSVDE3MTFIX1JFR19CTUNJT19MUFJQUkQJCUJJVCg0KQorI2RlZmluZSBSVDE3MTFI X1JFR19CTUNJT19MUEVOCQkJQklUKDMpCisjZGVmaW5lIFJUMTcxMUhfUkVHX0JNQ0lPX0JHX0VO CQkJQklUKDIpCisjZGVmaW5lIFJUMTcxMUhfUkVHX1ZCVVNfREVUX0VOCQkJQklUKDEpCisjZGVm aW5lIFJUMTcxMUhfUkVHX0JNQ0lPX09TQ19FTgkJQklUKDApCisKKy8qCisgKiBSVDE3MTFIX1JF R19SVF9TVEFUVVMJCQkoMHg5NykKKyAqLworI2RlZmluZSBSVDE3MTFIX1JFR19SQV9ERVRBQ0gJ CQlCSVQoNSkKKyNkZWZpbmUgUlQxNzExSF9SRUdfVkJVU184MAkJCUJJVCgxKQorCisvKgorICog UlQxNzExSF9SRUdfUlRfSU5UCQkJCSgweDk4KQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX0lO VF9SQV9ERVRBQ0gJCUJJVCg1KQorI2RlZmluZSBSVDE3MTFIX1JFR19JTlRfV0FUQ0hET0cJCUJJ VCgyKQorI2RlZmluZSBSVDE3MTFIX1JFR19JTlRfVkJVU184MAkJCUJJVCgxKQorI2RlZmluZSBS VDE3MTFIX1JFR19JTlRfV0FLRVVQCQkJQklUKDApCisKKy8qCisgKiBSVDE3MTFIX1JFR19SVF9N QVNLCQkJCSgweDk5KQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX01fUkFfREVUQUNICQkJQklU KDUpCisjZGVmaW5lIFJUMTcxMUhfUkVHX01fV0FUQ0hET0cJCQlCSVQoMikKKyNkZWZpbmUgUlQx NzExSF9SRUdfTV9WQlVTXzgwCQkJQklUKDEpCisjZGVmaW5lIFJUMTcxMUhfUkVHX01fV0FLRVVQ CQkJQklUKDApCisjZGVmaW5lIFJUMTcxMUhfUkVHX0FMRVJUX0VYVF9SQV9ERVRBQ0gJCSgxIDw8 ICgxNiArIDUpKQorI2RlZmluZSBSVDE3MTFIX1JFR19BTEVSVF9FWFRfVkJVU184MAkJKDEgPDwg KDE2ICsgMSkpCisKKy8qCisgKiBSVDE3MTFIX1JFR19JRExFX0NUUkwJCQkoMHg5QikKKyAqLwor I2RlZmluZSBSVDE3MTFIX1JFR19DS18zMDBLX1NFTAkJCUJJVCg3KQorI2RlZmluZSBSVDE3MTFI X1JFR19TSElQUElOR19PRkYJCUJJVCg1KQorI2RlZmluZSBSVDE3MTFIX1JFR19BVVRPSURMRV9F TgkJCUJJVCgzKQorCisvKiB0aW1lb3V0ID0gKHRvdXQqMisxKSAqIDYuNG1zICovCisjZGVmaW5l IFJUMTcxMUhfUkVHX0lETEVfU0VUKGNrMzAwLCBzaGlwX2RpcywgYXV0b19pZGxlLCB0b3V0KSBc CisJKCgoY2szMDApIDw8IDcpIHwgKChzaGlwX2RpcykgPDwgNSkgfCBcCisJICgoYXV0b19pZGxl KSA8PCAzKSB8ICgodG91dCkgJiAweDA3KSkKKworLyoKKyAqIFJUMTcxMUhfUkVHX0lOVFJTVF9D VFJMCQkJKDB4OUMpCisgKi8KKyNkZWZpbmUgUlQxNzExSF9SRUdfSU5UUlNUX0VOCQkJQklUKDcp CisKKy8qIHRpbWVvdXQgPSAodG91dCsxKSAqIDAuMnNlYyAqLworI2RlZmluZSBSVDE3MTFIX1JF R19JTlRSU1RfU0VUKGVuLCB0b3V0KQkoKChlbikgPDwgNykgfCAoKHRvdXQpICYgMHgwMykpCisK Ky8qCisgKiBSVDE3MTFIX1JFR19XQVRDSERPR19DVFJMCQkJKDB4OUQpCisgKi8KKyNkZWZpbmUg UlQxNzExSF9SRUdfV0FUQ0hET0dfRU4JCQlCSVQoNykKKworLyogdGltZW91dCA9ICh0b3V0KzEp ICogMC40c2VjICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX1dBVENIRE9HX0NUUkxfU0VUKGVuLCB0 b3V0KQkoKChlbikgPDwgNykgfCAoKHRvdXQpICYgMHgwNykpCisKKy8qCisgKiBSVDE3MTFIX1JF R19JMkNSU1RfQ1RSTAkJCSgweDlFKQorICovCisjZGVmaW5lIFJUMTcxMUhfUkVHX0kyQ1JTVF9F TgkJCUJJVCg3KQorCisvKiB0aW1lb3V0ID0gKHRvdXQrMSkgKiAxMi41bXMgKi8KKyNkZWZpbmUg UlQxNzExSF9SRUdfSTJDUlNUX1NFVChlbiwgdG91dCkJKChlbiA8PCA3KSB8ICh0b3V0ICYgMHgw RikpCisKKy8qCisgKiBSVDE3MTFIX1JFR19EUlBfRFVUWV9DVFJMCQkJKDB4QTMpCisgKi8KKyNk ZWZpbmUgUlQxNzExSF9MT1dfUlBfRFVUWQkJCSgxMDApCS8qIDEwJSAqLworI2RlZmluZSBSVDE3 MTFIX05PUk1BTF9SUF9EVVRZCQkJKDMzMCkJLyogMzMlICovCisKKyNlbmRpZiAvKiBfX0xJTlVY X1JUMTcxMUhfSCAqLwo=