From mboxrd@z Thu Jan 1 00:00:00 1970 From: mgreer@mvista.com (Mark A. Greer) Date: Thu, 19 May 2005 06:25:35 +0000 Subject: [PATCH][I2C] Marvell mv64xxx i2c driver Message-Id: <4202779C.6010304@mvista.com> List-Id: References: <200502020315.14281.adobriyan@mail.ru> <42010D5A.4090302@mvista.com> <200502031556.59319.adobriyan@mail.ru> In-Reply-To: <200502031556.59319.adobriyan@mail.ru> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: Alexey Dobriyan Cc: Greg KH , phil@netroedge.com, sensors@stimpy.netroedge.com, linux-kernel@vger.kernel.org Hi, Alexey. -- Alexey Dobriyan wrote: >On Wednesday 02 February 2005 19:26, Mark A. Greer wrote: > > > >>How's this (a complete replacement for previous patch)? >> >> > > > >>--- a/drivers/i2c/busses/Kconfig >>+++ b/drivers/i2c/busses/Kconfig >> >> > > > >>+ If you say yes to this option, support will be included for the >>+ built-in I2C interface on the Marvell 64xxx line of host bridges >> >> > >Dot at the end. Should have noticed it earlier... > Gahh, I noticed that too a while back. I thought I'd fixed it... Done. > > >>+ if (drv_data->state = MV64XXX_I2C_STATE_IDLE) { >>+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; >>+ drv_data->state = MV64XXX_I2C_STATE_IDLE; >> >> > >drv_data->state is already MV64XXX_I2C_STATE_IDLE. Gcc will probably optimize >this line away, but... > Done away with. > > >>+ } >>+ else { >> >> > >It should be "} else {" according to CodingStyle. > Done. > > >>+static int >>+mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs) >> >> > > > >>+ while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & >>+ MV64XXX_I2C_REG_CONTROL_IFLG) { >>+ status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); >>+ mv64xxx_i2c_fsm(drv_data, status); >> >> > >It can set drv_data->rc to -ENODEV or -EIO. In both cases ->action goes to >MV64XXX_I2C_ACTION_SEND_STOP and mv64xxx_i2c_do_action() will writel() >something. Is it correct to _not_ check ->rc here? > I think so. It still needs to go into do_action even when rc != 0 (in which case it'll do a STOP condition). > If it isn't then would it be >better to make all functions that set it return -E___ instead and drop >struct mv64xxx_i2c_data.rc altogether? > I may not be understanding what you mean but I think I need something like mv64xxx_i2c_data.rc or a plain old global to hang onto the return code. I need that so when the wait_event_interruptible_timeout() returns, that thread can find out what happened while it was blocked. This is what I mean: - calling thread enters i2c_xfer - eventually the initial i2c action is executed and the thread blocks in wait_event_interruptible_timeout() - other processes run - several interrupts happen, last one causing an error which is stored in mv64xxx_i2c_data.rc - do_action issues a stop on the i2c bus - thread is unblocked and now has to dig out the rc from mv64xxx_i2c_data.rc Or am I not understanding what you mean? >+ >+ if (!time_left <= 0) { > > > >Confusing. You meant "if (time_left)" or "if (time_left > 0)"? > No, I'm blind. I meant "if (time_left <=0)". Should be fixed now. Good catch. > > >>+static struct i2c_algorithm mv64xxx_i2c_algo = { >>+ .name = MV64XXX_I2C_CTLR_NAME "algorithm", >> >> > >MV64XXX_I2C_CTLR_NAME doesn't end with space. " algorithm" here. > Space added. > > >>+ dev_err(dev, "mv64xxx: Can't register intr handler " >>+ "irq: %d\\n", drv_data->irq); >> >> > >You snipped s# \\n # \n # suggestion in my previous email. ;-) > Ah, got it this time. :) This patch is a replacement patch that should address your concerns except maybe the mv64xxx_i2c_data.rc one. Signed-off-by: Mark A. Greer -- -------------- next part -------------- diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig --- a/drivers/i2c/busses/Kconfig 2005-02-03 12:10:35 -07:00 +++ b/drivers/i2c/busses/Kconfig 2005-02-03 12:10:35 -07:00 @@ -476,4 +476,14 @@ This driver can also be built as a module. If so, the module will be called i2c-pca-isa. +config I2C_MV64XXX + tristate "Marvell mv64xxx I2C Controller" + depends on I2C && MV64X60 && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + built-in I2C interface on the Marvell 64xxx line of host bridges. + + This driver can also be built as a module. If so, the module + will be called i2c-mv64xxx. + endmenu diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile --- a/drivers/i2c/busses/Makefile 2005-02-03 12:10:35 -07:00 +++ b/drivers/i2c/busses/Makefile 2005-02-03 12:10:35 -07:00 @@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o +obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o diff -Nru a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/i2c/busses/i2c-mv64xxx.c 2005-02-03 12:10:35 -07:00 @@ -0,0 +1,606 @@ +/* + * drivers/i2c/busses/i2c-mv64xxx.c + * + * Driver for the i2c controller on the Marvell line of host bridges for MIPS + * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0). + * + * Author: Mark A. Greer + * + * 2005 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include +#include +#include +#include + +/* Register defines */ +#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 +#define MV64XXX_I2C_REG_DATA 0x04 +#define MV64XXX_I2C_REG_CONTROL 0x08 +#define MV64XXX_I2C_REG_STATUS 0x0c +#define MV64XXX_I2C_REG_BAUD 0x0c +#define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x10 +#define MV64XXX_I2C_REG_SOFT_RESET 0x1c + +#define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 +#define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 +#define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010 +#define MV64XXX_I2C_REG_CONTROL_START 0x00000020 +#define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040 +#define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080 + +/* Ctlr status values */ +#define MV64XXX_I2C_STATUS_BUS_ERR 0x00 +#define MV64XXX_I2C_STATUS_MAST_START 0x08 +#define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x10 +#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 +#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 +#define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x28 +#define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x30 +#define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x38 +#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 +#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 +#define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x50 +#define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 +#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 +#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 +#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 +#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 +#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 + +/* Driver states */ +enum { + MV64XXX_I2C_STATE_INVALID, + MV64XXX_I2C_STATE_IDLE, + MV64XXX_I2C_STATE_WAITING_FOR_START_COND, + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, + MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, + MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, + MV64XXX_I2C_STATE_ABORTING, +}; + +/* Driver actions */ +enum { + MV64XXX_I2C_ACTION_INVALID, + MV64XXX_I2C_ACTION_CONTINUE, + MV64XXX_I2C_ACTION_SEND_START, + MV64XXX_I2C_ACTION_SEND_ADDR_1, + MV64XXX_I2C_ACTION_SEND_ADDR_2, + MV64XXX_I2C_ACTION_SEND_DATA, + MV64XXX_I2C_ACTION_RCV_DATA, + MV64XXX_I2C_ACTION_RCV_DATA_STOP, + MV64XXX_I2C_ACTION_SEND_STOP, +}; + +struct mv64xxx_i2c_data { + int irq; + u32 state; + u32 action; + u32 cntl_bits; + void __iomem *reg_base; + u32 reg_base_p; + u32 addr1; + u32 addr2; + u32 bytes_left; + u32 byte_posn; + u32 block; + int rc; + u32 freq_m; + u32 freq_n; + wait_queue_head_t waitq; + spinlock_t lock; + struct i2c_msg *msg; + struct i2c_adapter adapter; +}; + +/* + ***************************************************************************** + * + * Finite State Machine & Interrupt Routines + * + ***************************************************************************** + */ +static void +mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) +{ + /* + * If state is idle, then this is likely the remnants of an old + * operation that driver has given up on or the user has killed. + * If so, issue the stop condition and go to idle. + */ + if (drv_data->state = MV64XXX_I2C_STATE_IDLE) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + return; + } + + if (drv_data->state = MV64XXX_I2C_STATE_ABORTING) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + return; + } + + /* The status from the ctlr [mostly] tells us what to do next */ + switch (status) { + /* Start condition interrupt */ + case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */ + case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */ + drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; + break; + + /* Performing a write */ + case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */ + if (drv_data->msg->flags & I2C_M_TEN) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; + drv_data->state + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; + break; + } + /* FALLTHRU */ + case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ + case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ + if (drv_data->bytes_left > 0) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; + drv_data->state + MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; + drv_data->bytes_left--; + } else { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + } + break; + + /* Performing a read */ + case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */ + if (drv_data->msg->flags & I2C_M_TEN) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; + drv_data->state + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; + break; + } + /* FALLTHRU */ + case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ + if (drv_data->bytes_left = 0) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + break; + } + /* FALLTHRU */ + case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */ + if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK) + drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; + else { + drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA; + drv_data->bytes_left--; + } + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; + + if (drv_data->bytes_left = 1) + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; + break; + + case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */ + drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + break; + + case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */ + case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */ + case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */ + /* Doesn't seem to be a device at other end */ + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + drv_data->rc = -ENODEV; + break; + + default: + dev_err(&drv_data->adapter.dev, + "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " + "status: 0x%x, addr: 0x%x, flags: 0x%x\n", + drv_data->state, status, drv_data->msg->addr, + drv_data->msg->flags); + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + drv_data->rc = -EIO; + } + + return; +} + +static void +mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) +{ + switch(drv_data->action) { + case MV64XXX_I2C_ACTION_CONTINUE: + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_SEND_START: + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_SEND_ADDR_1: + writel(drv_data->addr1, + drv_data->reg_base + MV64XXX_I2C_REG_DATA); + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_SEND_ADDR_2: + writel(drv_data->addr2, + drv_data->reg_base + MV64XXX_I2C_REG_DATA); + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_SEND_DATA: + writel(drv_data->msg->buf[drv_data->byte_posn++], + drv_data->reg_base + MV64XXX_I2C_REG_DATA); + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_RCV_DATA: + drv_data->msg->buf[drv_data->byte_posn++] + readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + break; + + case MV64XXX_I2C_ACTION_RCV_DATA_STOP: + drv_data->msg->buf[drv_data->byte_posn++] + readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->block = 0; + wake_up_interruptible(&drv_data->waitq); + break; + + case MV64XXX_I2C_ACTION_INVALID: + default: + dev_err(&drv_data->adapter.dev, + "mv64xxx_i2c_do_action: Invalid action: %d\n", + drv_data->action); + drv_data->rc = -EIO; + /* FALLTHRU */ + case MV64XXX_I2C_ACTION_SEND_STOP: + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->block = 0; + wake_up_interruptible(&drv_data->waitq); + break; + } + + return; +} + +static int +mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mv64xxx_i2c_data *drv_data = dev_id; + u32 status; + long flags; + int rc = IRQ_NONE; + + spin_lock_irqsave(&drv_data->lock, flags); + while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & + MV64XXX_I2C_REG_CONTROL_IFLG) { + status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); + mv64xxx_i2c_fsm(drv_data, status); + mv64xxx_i2c_do_action(drv_data); + rc = IRQ_HANDLED; + } + spin_unlock_irqrestore(&drv_data->lock, flags); + + return rc; +} + +/* + ***************************************************************************** + * + * I2C Msg Execution Routines + * + ***************************************************************************** + */ +static void +mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, + struct i2c_msg *msg) +{ + u32 dir = 0; + + drv_data->msg = msg; + drv_data->byte_posn = 0; + drv_data->bytes_left = msg->len; + drv_data->rc = 0; + drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | + MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; + + if (msg->flags & I2C_M_RD) + dir = 1; + + if (msg->flags & I2C_M_REV_DIR_ADDR) + dir ^= 1; + + if (msg->flags & I2C_M_TEN) { + drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; + drv_data->addr2 = (u32)msg->addr & 0xff; + } else { + drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; + drv_data->addr2 = 0; + } + + return; +} + +static void +mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) +{ + long flags, time_left; + char abort = 0; + + time_left = wait_event_interruptible_timeout(drv_data->waitq, + !drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout)); + + spin_lock_irqsave(&drv_data->lock, flags); + if (!time_left) { /* Timed out */ + drv_data->rc = -ETIMEDOUT; + abort = 1; + } else if (time_left < 0) { /* Interrupted/Error */ + drv_data->rc = time_left; /* errno value */ + abort = 1; + } + + if (abort && drv_data->block) { + drv_data->state = MV64XXX_I2C_STATE_ABORTING; + spin_unlock_irqrestore(&drv_data->lock, flags); + + time_left = wait_event_timeout(drv_data->waitq, + !drv_data->block, + msecs_to_jiffies(drv_data->adapter.timeout)); + + if (time_left <= 0) { + drv_data->state = MV64XXX_I2C_STATE_IDLE; + dev_err(&drv_data->adapter.dev, + "mv64xxx: I2C bus locked\n"); + } + } else + spin_unlock_irqrestore(&drv_data->lock, flags); + + return; +} + +static int +mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) +{ + long flags; + + spin_lock_irqsave(&drv_data->lock, flags); + mv64xxx_i2c_prepare_for_io(drv_data, msg); + + if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */ + if (drv_data->msg->flags & I2C_M_RD) { + /* No action to do, wait for slave to send a byte */ + drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; + drv_data->state + MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; + } else { + drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; + drv_data->state + MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; + drv_data->bytes_left--; + } + } else { + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + } + + drv_data->block = 1; + mv64xxx_i2c_do_action(drv_data); + spin_unlock_irqrestore(&drv_data->lock, flags); + + mv64xxx_i2c_wait_for_completion(drv_data); + return drv_data->rc; +} + +/* + ***************************************************************************** + * + * I2C Core Support Routines (Interface to higher level I2C code) + * + ***************************************************************************** + */ +static u32 +mv64xxx_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; +} + +static int +mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); + int i, rc = 0; + + for (i=0; ireg_base + MV64XXX_I2C_REG_SOFT_RESET); + writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)), + drv_data->reg_base + MV64XXX_I2C_REG_BAUD); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); + writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->state = MV64XXX_I2C_STATE_IDLE; + return; +} + +static int __devinit +mv64xxx_i2c_map_regs(struct platform_device *pd, + struct mv64xxx_i2c_data *drv_data) +{ + struct resource *r; + + if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) && + request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE, + drv_data->adapter.name)) { + + drv_data->reg_base = ioremap(r->start, + MV64XXX_I2C_REG_BLOCK_SIZE); + drv_data->reg_base_p = r->start; + } else + return -ENOMEM; + + return 0; +} + +static void __devexit +mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) +{ + if (drv_data->reg_base) { + iounmap(drv_data->reg_base); + release_mem_region(drv_data->reg_base_p, + MV64XXX_I2C_REG_BLOCK_SIZE); + } + + drv_data->reg_base = NULL; + drv_data->reg_base_p = 0; + return; +} + +static int __devinit +mv64xxx_i2c_probe(struct device *dev) +{ + struct platform_device *pd = to_platform_device(dev); + struct mv64xxx_i2c_data *drv_data; + struct mv64xxx_i2c_pdata *pdata = dev->platform_data; + int rc; + + if ((pd->id != 0) || !pdata) + return -ENODEV; + + drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); + + if (!drv_data) + return -ENOMEM; + + memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data)); + + if (mv64xxx_i2c_map_regs(pd, drv_data)) { + rc = -ENODEV; + goto exit_kfree; + } + + strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", + I2C_NAME_SIZE); + + init_waitqueue_head(&drv_data->waitq); + spin_lock_init(&drv_data->lock); + + drv_data->freq_m = pdata->freq_m; + drv_data->freq_n = pdata->freq_n; + drv_data->irq = platform_get_irq(pd, 0); + drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX; + drv_data->adapter.algo = &mv64xxx_i2c_algo; + drv_data->adapter.timeout = pdata->timeout; + drv_data->adapter.retries = pdata->retries; + dev_set_drvdata(dev, drv_data); + i2c_set_adapdata(&drv_data->adapter, drv_data); + + if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, + MV64XXX_I2C_CTLR_NAME, drv_data)) { + + dev_err(dev, "mv64xxx: Can't register intr handler " + "irq: %d\n", drv_data->irq); + rc = -EINVAL; + goto exit_unmap_regs; + } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) { + dev_err(dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); + goto exit_free_irq; + } + + mv64xxx_i2c_hw_init(drv_data); + + return 0; + + exit_free_irq: + free_irq(drv_data->irq, drv_data); + exit_unmap_regs: + mv64xxx_i2c_unmap_regs(drv_data); + exit_kfree: + kfree(drv_data); + return rc; +} + +static int __devexit +mv64xxx_i2c_remove(struct device *dev) +{ + struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); + int rc; + + rc = i2c_del_adapter(&drv_data->adapter); + free_irq(drv_data->irq, drv_data); + mv64xxx_i2c_unmap_regs(drv_data); + kfree(drv_data); + + return rc; +} + +static struct device_driver mv64xxx_i2c_driver = { + .name = MV64XXX_I2C_CTLR_NAME, + .bus = &platform_bus_type, + .probe = mv64xxx_i2c_probe, + .remove = mv64xxx_i2c_remove, +}; + +static int __devinit +mv64xxx_i2c_init(void) +{ + return driver_register(&mv64xxx_i2c_driver); +} + +static void __devexit +mv64xxx_i2c_exit(void) +{ + driver_unregister(&mv64xxx_i2c_driver); + return; +} + +module_init(mv64xxx_i2c_init); +module_exit(mv64xxx_i2c_exit); + +MODULE_AUTHOR("Mark A. Greer "); +MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver"); +MODULE_LICENSE("GPL"); diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h --- a/include/linux/i2c-id.h 2005-02-03 12:10:35 -07:00 +++ b/include/linux/i2c-id.h 2005-02-03 12:10:35 -07:00 @@ -200,6 +200,9 @@ #define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */ #define I2C_ALGO_SGI 0x160000 /* SGI algorithm */ + /* 0x170000 - USB */ + /* 0x180000 - Virtual buses */ +#define I2C_ALGO_MV64XXX 0x190000 /* Marvell mv64xxx i2c ctlr */ #define I2C_ALGO_EXP 0x800000 /* experimental */ @@ -305,5 +308,8 @@ /* --- MCP107 adapter */ #define I2C_HW_MPC107 0x00 + +/* --- Marvell mv64xxx i2c adapter */ +#define I2C_HW_MV64XXX 0x00 #endif /* LINUX_I2C_ID_H */ diff -Nru a/include/linux/mv643xx.h b/include/linux/mv643xx.h --- a/include/linux/mv643xx.h 2005-02-03 12:10:35 -07:00 +++ b/include/linux/mv643xx.h 2005-02-03 12:10:35 -07:00 @@ -977,12 +977,9 @@ /* I2C Registers */ /****************************************/ -#define MV64340_I2C_SLAVE_ADDR 0xc000 -#define MV64340_I2C_EXTENDED_SLAVE_ADDR 0xc010 -#define MV64340_I2C_DATA 0xc004 -#define MV64340_I2C_CONTROL 0xc008 -#define MV64340_I2C_STATUS_BAUDE_RATE 0xc00C -#define MV64340_I2C_SOFT_RESET 0xc01c +#define MV64XXX_I2C_CTLR_NAME "mv64xxx i2c" +#define MV64XXX_I2C_OFFSET 0xc000 +#define MV64XXX_I2C_REG_BLOCK_SIZE 0x0020 /****************************************/ /* GPP Interface Registers */ @@ -1083,6 +1080,14 @@ u8 brg_can_tune; u8 brg_clk_src; u32 brg_clk_freq; +}; + +/* i2c Platform Device, Driver Data */ +struct mv64xxx_i2c_pdata { + u32 freq_m; + u32 freq_n; + u32 timeout; /* In milliseconds */ + u32 retries; }; #endif /* __ASM_MV64340_H */ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S263880AbVBCTnX (ORCPT ); Thu, 3 Feb 2005 14:43:23 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S263625AbVBCTTv (ORCPT ); Thu, 3 Feb 2005 14:19:51 -0500 Received: from gateway-1237.mvista.com ([12.44.186.158]:21493 "EHLO av.mvista.com") by vger.kernel.org with ESMTP id S263636AbVBCTMp (ORCPT ); Thu, 3 Feb 2005 14:12:45 -0500 Message-ID: <4202779C.6010304@mvista.com> Date: Thu, 03 Feb 2005 12:12:28 -0700 From: "Mark A. Greer" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030701 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Alexey Dobriyan CC: Greg KH , phil@netroedge.com, sensors@stimpy.netroedge.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH][I2C] Marvell mv64xxx i2c driver References: <200502020315.14281.adobriyan@mail.ru> <42010D5A.4090302@mvista.com> <200502031556.59319.adobriyan@mail.ru> In-Reply-To: <200502031556.59319.adobriyan@mail.ru> Content-Type: multipart/mixed; boundary="------------000403080908090506040000" Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org This is a multi-part message in MIME format. --------------000403080908090506040000 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi, Alexey. -- Alexey Dobriyan wrote: >On Wednesday 02 February 2005 19:26, Mark A. Greer wrote: > > > >>How's this (a complete replacement for previous patch)? >> >> > > > >>--- a/drivers/i2c/busses/Kconfig >>+++ b/drivers/i2c/busses/Kconfig >> >> > > > >>+ If you say yes to this option, support will be included for the >>+ built-in I2C interface on the Marvell 64xxx line of host bridges >> >> > >Dot at the end. Should have noticed it earlier... > Gahh, I noticed that too a while back. I thought I'd fixed it... Done. > > >>+ if (drv_data->state == MV64XXX_I2C_STATE_IDLE) { >>+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; >>+ drv_data->state = MV64XXX_I2C_STATE_IDLE; >> >> > >drv_data->state is already MV64XXX_I2C_STATE_IDLE. Gcc will probably optimize >this line away, but... > Done away with. > > >>+ } >>+ else { >> >> > >It should be "} else {" according to CodingStyle. > Done. > > >>+static int >>+mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs) >> >> > > > >>+ while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & >>+ MV64XXX_I2C_REG_CONTROL_IFLG) { >>+ status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); >>+ mv64xxx_i2c_fsm(drv_data, status); >> >> > >It can set drv_data->rc to -ENODEV or -EIO. In both cases ->action goes to >MV64XXX_I2C_ACTION_SEND_STOP and mv64xxx_i2c_do_action() will writel() >something. Is it correct to _not_ check ->rc here? > I think so. It still needs to go into do_action even when rc != 0 (in which case it'll do a STOP condition). > If it isn't then would it be >better to make all functions that set it return -E___ instead and drop >struct mv64xxx_i2c_data.rc altogether? > I may not be understanding what you mean but I think I need something like mv64xxx_i2c_data.rc or a plain old global to hang onto the return code. I need that so when the wait_event_interruptible_timeout() returns, that thread can find out what happened while it was blocked. This is what I mean: - calling thread enters i2c_xfer - eventually the initial i2c action is executed and the thread blocks in wait_event_interruptible_timeout() - other processes run - several interrupts happen, last one causing an error which is stored in mv64xxx_i2c_data.rc - do_action issues a stop on the i2c bus - thread is unblocked and now has to dig out the rc from mv64xxx_i2c_data.rc Or am I not understanding what you mean? >+ >+ if (!time_left <= 0) { > > > >Confusing. You meant "if (time_left)" or "if (time_left > 0)"? > No, I'm blind. I meant "if (time_left <=0)". Should be fixed now. Good catch. > > >>+static struct i2c_algorithm mv64xxx_i2c_algo = { >>+ .name = MV64XXX_I2C_CTLR_NAME "algorithm", >> >> > >MV64XXX_I2C_CTLR_NAME doesn't end with space. " algorithm" here. > Space added. > > >>+ dev_err(dev, "mv64xxx: Can't register intr handler " >>+ "irq: %d\\n", drv_data->irq); >> >> > >You snipped s# \\n # \n # suggestion in my previous email. ;-) > Ah, got it this time. :) This patch is a replacement patch that should address your concerns except maybe the mv64xxx_i2c_data.rc one. Signed-off-by: Mark A. Greer -- --------------000403080908090506040000 Content-Type: text/plain; name="i2c_6.patch" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="i2c_6.patch" ZGlmZiAtTnJ1IGEvZHJpdmVycy9pMmMvYnVzc2VzL0tjb25maWcgYi9kcml2ZXJzL2kyYy9i dXNzZXMvS2NvbmZpZwotLS0gYS9kcml2ZXJzL2kyYy9idXNzZXMvS2NvbmZpZwkyMDA1LTAy LTAzIDEyOjEwOjM1IC0wNzowMAorKysgYi9kcml2ZXJzL2kyYy9idXNzZXMvS2NvbmZpZwky MDA1LTAyLTAzIDEyOjEwOjM1IC0wNzowMApAQCAtNDc2LDQgKzQ3NiwxNCBAQAogCSAgVGhp cyBkcml2ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuICBJZiBzbywgdGhlIG1v ZHVsZQogCSAgd2lsbCBiZSBjYWxsZWQgaTJjLXBjYS1pc2EuCiAKK2NvbmZpZyBJMkNfTVY2 NFhYWAorCXRyaXN0YXRlICJNYXJ2ZWxsIG12NjR4eHggSTJDIENvbnRyb2xsZXIiCisJZGVw ZW5kcyBvbiBJMkMgJiYgTVY2NFg2MCAmJiBFWFBFUklNRU5UQUwKKwloZWxwCisJICBJZiB5 b3Ugc2F5IHllcyB0byB0aGlzIG9wdGlvbiwgc3VwcG9ydCB3aWxsIGJlIGluY2x1ZGVkIGZv ciB0aGUKKwkgIGJ1aWx0LWluIEkyQyBpbnRlcmZhY2Ugb24gdGhlIE1hcnZlbGwgNjR4eHgg bGluZSBvZiBob3N0IGJyaWRnZXMuCisKKwkgIFRoaXMgZHJpdmVyIGNhbiBhbHNvIGJlIGJ1 aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVk IGkyYy1tdjY0eHh4LgorCiBlbmRtZW51CmRpZmYgLU5ydSBhL2RyaXZlcnMvaTJjL2J1c3Nl cy9NYWtlZmlsZSBiL2RyaXZlcnMvaTJjL2J1c3Nlcy9NYWtlZmlsZQotLS0gYS9kcml2ZXJz L2kyYy9idXNzZXMvTWFrZWZpbGUJMjAwNS0wMi0wMyAxMjoxMDozNSAtMDc6MDAKKysrIGIv ZHJpdmVycy9pMmMvYnVzc2VzL01ha2VmaWxlCTIwMDUtMDItMDMgMTI6MTA6MzUgLTA3OjAw CkBAIC0yMCw2ICsyMCw3IEBACiBvYmotJChDT05GSUdfSTJDX0lYUDRYWCkJKz0gaTJjLWl4 cDR4eC5vCiBvYmotJChDT05GSUdfSTJDX0tFWVdFU1QpCSs9IGkyYy1rZXl3ZXN0Lm8KIG9i ai0kKENPTkZJR19JMkNfTVBDKQkJKz0gaTJjLW1wYy5vCitvYmotJChDT05GSUdfSTJDX01W NjRYWFgpCSs9IGkyYy1tdjY0eHh4Lm8KIG9iai0kKENPTkZJR19JMkNfTkZPUkNFMikJKz0g aTJjLW5mb3JjZTIubwogb2JqLSQoQ09ORklHX0kyQ19QQVJQT1JUKQkrPSBpMmMtcGFycG9y dC5vCiBvYmotJChDT05GSUdfSTJDX1BBUlBPUlRfTElHSFQpCSs9IGkyYy1wYXJwb3J0LWxp Z2h0Lm8KZGlmZiAtTnJ1IGEvZHJpdmVycy9pMmMvYnVzc2VzL2kyYy1tdjY0eHh4LmMgYi9k cml2ZXJzL2kyYy9idXNzZXMvaTJjLW12NjR4eHguYwotLS0gL2Rldi9udWxsCVdlZCBEZWMg MzEgMTY6MDA6MDAgMTk2OTAwCisrKyBiL2RyaXZlcnMvaTJjL2J1c3Nlcy9pMmMtbXY2NHh4 eC5jCTIwMDUtMDItMDMgMTI6MTA6MzUgLTA3OjAwCkBAIC0wLDAgKzEsNjA2IEBACisvKgor ICogZHJpdmVycy9pMmMvYnVzc2VzL2kyYy1tdjY0eHh4LmMKKyAqIAorICogRHJpdmVyIGZv ciB0aGUgaTJjIGNvbnRyb2xsZXIgb24gdGhlIE1hcnZlbGwgbGluZSBvZiBob3N0IGJyaWRn ZXMgZm9yIE1JUFMKKyAqIGFuZCBQUEMgKGUuZywgZ3Q2NDJbNDZdMCwgbXY2NDNbNDZdMCwg bXY2NDRbNDZdMCkuCisgKgorICogQXV0aG9yOiBNYXJrIEEuIEdyZWVyIDxtZ3JlZXJAbXZp c3RhLmNvbT4KKyAqCisgKiAyMDA1IChjKSBNb250YVZpc3RhLCBTb2Z0d2FyZSwgSW5jLiAg VGhpcyBmaWxlIGlzIGxpY2Vuc2VkIHVuZGVyCisgKiB0aGUgdGVybXMgb2YgdGhlIEdOVSBH ZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMi4gIFRoaXMgcHJvZ3JhbQorICogaXMg bGljZW5zZWQgImFzIGlzIiB3aXRob3V0IGFueSB3YXJyYW50eSBvZiBhbnkga2luZCwgd2hl dGhlciBleHByZXNzCisgKiBvciBpbXBsaWVkLgorICovCisjaW5jbHVkZSA8bGludXgva2Vy bmVsLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgvc3Bp bmxvY2suaD4KKyNpbmNsdWRlIDxsaW51eC9pMmMuaD4KKyNpbmNsdWRlIDxsaW51eC9pbnRl cnJ1cHQuaD4KKyNpbmNsdWRlIDxsaW51eC9tdjY0M3h4Lmg+CisjaW5jbHVkZSA8YXNtL2lv Lmg+CisKKy8qIFJlZ2lzdGVyIGRlZmluZXMgKi8KKyNkZWZpbmUJTVY2NFhYWF9JMkNfUkVH X1NMQVZFX0FERFIJCQkweDAwCisjZGVmaW5lCU1WNjRYWFhfSTJDX1JFR19EQVRBCQkJCTB4 MDQKKyNkZWZpbmUJTVY2NFhYWF9JMkNfUkVHX0NPTlRST0wJCQkJMHgwOAorI2RlZmluZQlN VjY0WFhYX0kyQ19SRUdfU1RBVFVTCQkJCTB4MGMKKyNkZWZpbmUJTVY2NFhYWF9JMkNfUkVH X0JBVUQJCQkJMHgwYworI2RlZmluZQlNVjY0WFhYX0kyQ19SRUdfRVhUX1NMQVZFX0FERFIJ CQkweDEwCisjZGVmaW5lCU1WNjRYWFhfSTJDX1JFR19TT0ZUX1JFU0VUCQkJMHgxYworCisj ZGVmaW5lCU1WNjRYWFhfSTJDX1JFR19DT05UUk9MX0FDSwkJCTB4MDAwMDAwMDQKKyNkZWZp bmUJTVY2NFhYWF9JMkNfUkVHX0NPTlRST0xfSUZMRwkJCTB4MDAwMDAwMDgKKyNkZWZpbmUJ TVY2NFhYWF9JMkNfUkVHX0NPTlRST0xfU1RPUAkJCTB4MDAwMDAwMTAKKyNkZWZpbmUJTVY2 NFhYWF9JMkNfUkVHX0NPTlRST0xfU1RBUlQJCQkweDAwMDAwMDIwCisjZGVmaW5lCU1WNjRY WFhfSTJDX1JFR19DT05UUk9MX1RXU0lFTgkJCTB4MDAwMDAwNDAKKyNkZWZpbmUJTVY2NFhY WF9JMkNfUkVHX0NPTlRST0xfSU5URU4JCQkweDAwMDAwMDgwCisKKy8qIEN0bHIgc3RhdHVz IHZhbHVlcyAqLworI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfQlVTX0VSUgkJCTB4MDAK KyNkZWZpbmUJTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfU1RBUlQJCQkweDA4CisjZGVmaW5l CU1WNjRYWFhfSTJDX1NUQVRVU19NQVNUX1JFUEVBVF9TVEFSVAkJMHgxMAorI2RlZmluZQlN VjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9BRERSX0FDSwkJMHgxOAorI2RlZmluZQlNVjY0 WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9BRERSX05PX0FDSwkJMHgyMAorI2RlZmluZQlNVjY0 WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9BQ0sJCQkweDI4CisjZGVmaW5lCU1WNjRYWFhfSTJD X1NUQVRVU19NQVNUX1dSX05PX0FDSwkJMHgzMAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFU VVNfTUFTVF9MT1NUX0FSQgkJMHgzOAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFT VF9SRF9BRERSX0FDSwkJMHg0MAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9S RF9BRERSX05PX0FDSwkJMHg0OAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9S RF9EQVRBX0FDSwkJMHg1MAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9SRF9E QVRBX05PX0FDSwkJMHg1OAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9B RERSXzJfQUNLCQkweGQwCisjZGVmaW5lCU1WNjRYWFhfSTJDX1NUQVRVU19NQVNUX1dSX0FE RFJfMl9OT19BQ0sJMHhkOAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9SRF9B RERSXzJfQUNLCQkweGUwCisjZGVmaW5lCU1WNjRYWFhfSTJDX1NUQVRVU19NQVNUX1JEX0FE RFJfMl9OT19BQ0sJMHhlOAorI2RlZmluZQlNVjY0WFhYX0kyQ19TVEFUVVNfTk9fU1RBVFVT CQkJMHhmOAorCisvKiBEcml2ZXIgc3RhdGVzICovCitlbnVtIHsKKwlNVjY0WFhYX0kyQ19T VEFURV9JTlZBTElELAorCU1WNjRYWFhfSTJDX1NUQVRFX0lETEUsCisJTVY2NFhYWF9JMkNf U1RBVEVfV0FJVElOR19GT1JfU1RBUlRfQ09ORCwKKwlNVjY0WFhYX0kyQ19TVEFURV9XQUlU SU5HX0ZPUl9BRERSXzFfQUNLLAorCU1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9SX0FE RFJfMl9BQ0ssCisJTVY2NFhYWF9JMkNfU1RBVEVfV0FJVElOR19GT1JfU0xBVkVfQUNLLAor CU1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9SX1NMQVZFX0RBVEEsCisJTVY2NFhYWF9J MkNfU1RBVEVfQUJPUlRJTkcsCit9OworCisvKiBEcml2ZXIgYWN0aW9ucyAqLworZW51bSB7 CisJTVY2NFhYWF9JMkNfQUNUSU9OX0lOVkFMSUQsCisJTVY2NFhYWF9JMkNfQUNUSU9OX0NP TlRJTlVFLAorCU1WNjRYWFhfSTJDX0FDVElPTl9TRU5EX1NUQVJULAorCU1WNjRYWFhfSTJD X0FDVElPTl9TRU5EX0FERFJfMSwKKwlNVjY0WFhYX0kyQ19BQ1RJT05fU0VORF9BRERSXzIs CisJTVY2NFhYWF9JMkNfQUNUSU9OX1NFTkRfREFUQSwKKwlNVjY0WFhYX0kyQ19BQ1RJT05f UkNWX0RBVEEsCisJTVY2NFhYWF9JMkNfQUNUSU9OX1JDVl9EQVRBX1NUT1AsCisJTVY2NFhY WF9JMkNfQUNUSU9OX1NFTkRfU1RPUCwKK307CisKK3N0cnVjdCBtdjY0eHh4X2kyY19kYXRh IHsKKwlpbnQJCQlpcnE7CisJdTMyCQkJc3RhdGU7CisJdTMyCQkJYWN0aW9uOworCXUzMgkJ CWNudGxfYml0czsKKwl2b2lkIF9faW9tZW0JCSpyZWdfYmFzZTsKKwl1MzIJCQlyZWdfYmFz ZV9wOworCXUzMgkJCWFkZHIxOworCXUzMgkJCWFkZHIyOworCXUzMgkJCWJ5dGVzX2xlZnQ7 CisJdTMyCQkJYnl0ZV9wb3NuOworCXUzMgkJCWJsb2NrOworCWludAkJCXJjOworCXUzMgkJ CWZyZXFfbTsKKwl1MzIJCQlmcmVxX247CisJd2FpdF9xdWV1ZV9oZWFkX3QJd2FpdHE7CisJ c3BpbmxvY2tfdAkJbG9jazsKKwlzdHJ1Y3QgaTJjX21zZwkJKm1zZzsKKwlzdHJ1Y3QgaTJj X2FkYXB0ZXIJYWRhcHRlcjsKK307CisKKy8qCisgKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioK KyAqCisgKglGaW5pdGUgU3RhdGUgTWFjaGluZSAmIEludGVycnVwdCBSb3V0aW5lcworICoK KyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKgorICovCitzdGF0aWMgdm9pZAorbXY2NHh4eF9p MmNfZnNtKHN0cnVjdCBtdjY0eHh4X2kyY19kYXRhICpkcnZfZGF0YSwgdTMyIHN0YXR1cykK K3sKKwkvKgorCSAqIElmIHN0YXRlIGlzIGlkbGUsIHRoZW4gdGhpcyBpcyBsaWtlbHkgdGhl IHJlbW5hbnRzIG9mIGFuIG9sZAorCSAqIG9wZXJhdGlvbiB0aGF0IGRyaXZlciBoYXMgZ2l2 ZW4gdXAgb24gb3IgdGhlIHVzZXIgaGFzIGtpbGxlZC4KKwkgKiBJZiBzbywgaXNzdWUgdGhl IHN0b3AgY29uZGl0aW9uIGFuZCBnbyB0byBpZGxlLgorCSAqLworCWlmIChkcnZfZGF0YS0+ c3RhdGUgPT0gTVY2NFhYWF9JMkNfU1RBVEVfSURMRSkgeworCQlkcnZfZGF0YS0+YWN0aW9u ID0gTVY2NFhYWF9JMkNfQUNUSU9OX1NFTkRfU1RPUDsKKwkJcmV0dXJuOworCX0KKworCWlm IChkcnZfZGF0YS0+c3RhdGUgPT0gTVY2NFhYWF9JMkNfU1RBVEVfQUJPUlRJTkcpIHsKKwkJ ZHJ2X2RhdGEtPmFjdGlvbiA9IE1WNjRYWFhfSTJDX0FDVElPTl9TRU5EX1NUT1A7CisJCWRy dl9kYXRhLT5zdGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX0lETEU7CisJCXJldHVybjsKKwl9 CisKKwkvKiBUaGUgc3RhdHVzIGZyb20gdGhlIGN0bHIgW21vc3RseV0gdGVsbHMgdXMgd2hh dCB0byBkbyBuZXh0ICovCisJc3dpdGNoIChzdGF0dXMpIHsKKwkvKiBTdGFydCBjb25kaXRp b24gaW50ZXJydXB0ICovCisJY2FzZSBNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9TVEFSVDog LyogMHgwOCAqLworCWNhc2UgTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfUkVQRUFUX1NUQVJU OiAvKiAweDEwICovCisJCWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0WFhYX0kyQ19BQ1RJT05f U0VORF9BRERSXzE7CisJCWRydl9kYXRhLT5zdGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX1dB SVRJTkdfRk9SX0FERFJfMV9BQ0s7CisJCWJyZWFrOworCisJLyogUGVyZm9ybWluZyBhIHdy aXRlICovCisJY2FzZSBNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9BRERSX0FDSzogLyog MHgxOCAqLworCQlpZiAoZHJ2X2RhdGEtPm1zZy0+ZmxhZ3MgJiBJMkNfTV9URU4pIHsKKwkJ CWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0WFhYX0kyQ19BQ1RJT05fU0VORF9BRERSXzI7CisJ CQlkcnZfZGF0YS0+c3RhdGUgPQorCQkJCU1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9S X0FERFJfMl9BQ0s7CisJCQlicmVhazsKKwkJfQorCQkvKiBGQUxMVEhSVSAqLworCWNhc2Ug TVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfV1JfQUREUl8yX0FDSzogLyogMHhkMCAqLworCWNh c2UgTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfV1JfQUNLOiAvKiAweDI4ICovCisJCWlmIChk cnZfZGF0YS0+Ynl0ZXNfbGVmdCA+IDApIHsKKwkJCWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0 WFhYX0kyQ19BQ1RJT05fU0VORF9EQVRBOworCQkJZHJ2X2RhdGEtPnN0YXRlID0KKwkJCQlN VjY0WFhYX0kyQ19TVEFURV9XQUlUSU5HX0ZPUl9TTEFWRV9BQ0s7CisJCQlkcnZfZGF0YS0+ Ynl0ZXNfbGVmdC0tOworCQl9IGVsc2UgeworCQkJZHJ2X2RhdGEtPmFjdGlvbiA9IE1WNjRY WFhfSTJDX0FDVElPTl9TRU5EX1NUT1A7CisJCQlkcnZfZGF0YS0+c3RhdGUgPSBNVjY0WFhY X0kyQ19TVEFURV9JRExFOworCQl9CisJCWJyZWFrOworCisJLyogUGVyZm9ybWluZyBhIHJl YWQgKi8KKwljYXNlIE1WNjRYWFhfSTJDX1NUQVRVU19NQVNUX1JEX0FERFJfQUNLOiAvKiA0 MCAqLworCQlpZiAoZHJ2X2RhdGEtPm1zZy0+ZmxhZ3MgJiBJMkNfTV9URU4pIHsKKwkJCWRy dl9kYXRhLT5hY3Rpb24gPSBNVjY0WFhYX0kyQ19BQ1RJT05fU0VORF9BRERSXzI7CisJCQlk cnZfZGF0YS0+c3RhdGUgPQorCQkJCU1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9SX0FE RFJfMl9BQ0s7CisJCQlicmVhazsKKwkJfQorCQkvKiBGQUxMVEhSVSAqLworCWNhc2UgTVY2 NFhYWF9JMkNfU1RBVFVTX01BU1RfUkRfQUREUl8yX0FDSzogLyogMHhlMCAqLworCQlpZiAo ZHJ2X2RhdGEtPmJ5dGVzX2xlZnQgPT0gMCkgeworCQkJZHJ2X2RhdGEtPmFjdGlvbiA9IE1W NjRYWFhfSTJDX0FDVElPTl9TRU5EX1NUT1A7CisJCQlkcnZfZGF0YS0+c3RhdGUgPSBNVjY0 WFhYX0kyQ19TVEFURV9JRExFOworCQkJYnJlYWs7CisJCX0KKwkJLyogRkFMTFRIUlUgKi8K KwljYXNlIE1WNjRYWFhfSTJDX1NUQVRVU19NQVNUX1JEX0RBVEFfQUNLOiAvKiAweDUwICov CisJCWlmIChzdGF0dXMgIT0gTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfUkRfREFUQV9BQ0sp CisJCQlkcnZfZGF0YS0+YWN0aW9uID0gTVY2NFhYWF9JMkNfQUNUSU9OX0NPTlRJTlVFOwor CQllbHNlIHsKKwkJCWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0WFhYX0kyQ19BQ1RJT05fUkNW X0RBVEE7CisJCQlkcnZfZGF0YS0+Ynl0ZXNfbGVmdC0tOworCQl9CisJCWRydl9kYXRhLT5z dGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9SX1NMQVZFX0RBVEE7CisKKwkJ aWYgKGRydl9kYXRhLT5ieXRlc19sZWZ0ID09IDEpCisJCQlkcnZfZGF0YS0+Y250bF9iaXRz ICY9IH5NVjY0WFhYX0kyQ19SRUdfQ09OVFJPTF9BQ0s7CisJCWJyZWFrOworCisJY2FzZSBN VjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9SRF9EQVRBX05PX0FDSzogLyogMHg1OCAqLworCQlk cnZfZGF0YS0+YWN0aW9uID0gTVY2NFhYWF9JMkNfQUNUSU9OX1JDVl9EQVRBX1NUT1A7CisJ CWRydl9kYXRhLT5zdGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX0lETEU7CisJCWJyZWFrOwor CisJY2FzZSBNVjY0WFhYX0kyQ19TVEFUVVNfTUFTVF9XUl9BRERSX05PX0FDSzogLyogMHgy MCAqLworCWNhc2UgTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfV1JfTk9fQUNLOiAvKiAzMCAq LworCWNhc2UgTVY2NFhYWF9JMkNfU1RBVFVTX01BU1RfUkRfQUREUl9OT19BQ0s6IC8qIDQ4 ICovCisJCS8qIERvZXNuJ3Qgc2VlbSB0byBiZSBhIGRldmljZSBhdCBvdGhlciBlbmQgKi8K KwkJZHJ2X2RhdGEtPmFjdGlvbiA9IE1WNjRYWFhfSTJDX0FDVElPTl9TRU5EX1NUT1A7CisJ CWRydl9kYXRhLT5zdGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX0lETEU7CisJCWRydl9kYXRh LT5yYyA9IC1FTk9ERVY7CisJCWJyZWFrOworCisJZGVmYXVsdDoKKwkJZGV2X2VycigmZHJ2 X2RhdGEtPmFkYXB0ZXIuZGV2LAorCQkJIm12NjR4eHhfaTJjX2ZzbTogQ3RsciBFcnJvciAt LSBzdGF0ZTogMHgleCwgIgorCQkJInN0YXR1czogMHgleCwgYWRkcjogMHgleCwgZmxhZ3M6 IDB4JXhcbiIsCisJCQkgZHJ2X2RhdGEtPnN0YXRlLCBzdGF0dXMsIGRydl9kYXRhLT5tc2ct PmFkZHIsCisJCQkgZHJ2X2RhdGEtPm1zZy0+ZmxhZ3MpOworCQlkcnZfZGF0YS0+YWN0aW9u ID0gTVY2NFhYWF9JMkNfQUNUSU9OX1NFTkRfU1RPUDsKKwkJZHJ2X2RhdGEtPnN0YXRlID0g TVY2NFhYWF9JMkNfU1RBVEVfSURMRTsKKwkJZHJ2X2RhdGEtPnJjID0gLUVJTzsKKwl9CisK KwlyZXR1cm47Cit9CisKK3N0YXRpYyB2b2lkCittdjY0eHh4X2kyY19kb19hY3Rpb24oc3Ry dWN0IG12NjR4eHhfaTJjX2RhdGEgKmRydl9kYXRhKQoreworCXN3aXRjaChkcnZfZGF0YS0+ YWN0aW9uKSB7CisJY2FzZSBNVjY0WFhYX0kyQ19BQ1RJT05fQ09OVElOVUU6CisJCXdyaXRl bChkcnZfZGF0YS0+Y250bF9iaXRzLAorCQkJZHJ2X2RhdGEtPnJlZ19iYXNlICsgTVY2NFhY WF9JMkNfUkVHX0NPTlRST0wpOworCQlicmVhazsKKworCWNhc2UgTVY2NFhYWF9JMkNfQUNU SU9OX1NFTkRfU1RBUlQ6CisJCXdyaXRlbChkcnZfZGF0YS0+Y250bF9iaXRzIHwgTVY2NFhY WF9JMkNfUkVHX0NPTlRST0xfU1RBUlQsCisJCQlkcnZfZGF0YS0+cmVnX2Jhc2UgKyBNVjY0 WFhYX0kyQ19SRUdfQ09OVFJPTCk7CisJCWJyZWFrOworCisJY2FzZSBNVjY0WFhYX0kyQ19B Q1RJT05fU0VORF9BRERSXzE6CisJCXdyaXRlbChkcnZfZGF0YS0+YWRkcjEsCisJCQlkcnZf ZGF0YS0+cmVnX2Jhc2UgKyBNVjY0WFhYX0kyQ19SRUdfREFUQSk7CisJCXdyaXRlbChkcnZf ZGF0YS0+Y250bF9iaXRzLAorCQkJZHJ2X2RhdGEtPnJlZ19iYXNlICsgTVY2NFhYWF9JMkNf UkVHX0NPTlRST0wpOworCQlicmVhazsKKworCWNhc2UgTVY2NFhYWF9JMkNfQUNUSU9OX1NF TkRfQUREUl8yOgorCQl3cml0ZWwoZHJ2X2RhdGEtPmFkZHIyLAorCQkJZHJ2X2RhdGEtPnJl Z19iYXNlICsgTVY2NFhYWF9JMkNfUkVHX0RBVEEpOworCQl3cml0ZWwoZHJ2X2RhdGEtPmNu dGxfYml0cywKKwkJCWRydl9kYXRhLT5yZWdfYmFzZSArIE1WNjRYWFhfSTJDX1JFR19DT05U Uk9MKTsKKwkJYnJlYWs7CisKKwljYXNlIE1WNjRYWFhfSTJDX0FDVElPTl9TRU5EX0RBVEE6 CisJCXdyaXRlbChkcnZfZGF0YS0+bXNnLT5idWZbZHJ2X2RhdGEtPmJ5dGVfcG9zbisrXSwK KwkJCWRydl9kYXRhLT5yZWdfYmFzZSArIE1WNjRYWFhfSTJDX1JFR19EQVRBKTsKKwkJd3Jp dGVsKGRydl9kYXRhLT5jbnRsX2JpdHMsCisJCQlkcnZfZGF0YS0+cmVnX2Jhc2UgKyBNVjY0 WFhYX0kyQ19SRUdfQ09OVFJPTCk7CisJCWJyZWFrOworCisJY2FzZSBNVjY0WFhYX0kyQ19B Q1RJT05fUkNWX0RBVEE6CisJCWRydl9kYXRhLT5tc2ctPmJ1ZltkcnZfZGF0YS0+Ynl0ZV9w b3NuKytdID0KKwkJCXJlYWRsKGRydl9kYXRhLT5yZWdfYmFzZSArIE1WNjRYWFhfSTJDX1JF R19EQVRBKTsKKwkJd3JpdGVsKGRydl9kYXRhLT5jbnRsX2JpdHMsCisJCQlkcnZfZGF0YS0+ cmVnX2Jhc2UgKyBNVjY0WFhYX0kyQ19SRUdfQ09OVFJPTCk7CisJCWJyZWFrOworCisJY2Fz ZSBNVjY0WFhYX0kyQ19BQ1RJT05fUkNWX0RBVEFfU1RPUDoKKwkJZHJ2X2RhdGEtPm1zZy0+ YnVmW2Rydl9kYXRhLT5ieXRlX3Bvc24rK10gPQorCQkJcmVhZGwoZHJ2X2RhdGEtPnJlZ19i YXNlICsgTVY2NFhYWF9JMkNfUkVHX0RBVEEpOworCQlkcnZfZGF0YS0+Y250bF9iaXRzICY9 IH5NVjY0WFhYX0kyQ19SRUdfQ09OVFJPTF9JTlRFTjsKKwkJd3JpdGVsKGRydl9kYXRhLT5j bnRsX2JpdHMgfCBNVjY0WFhYX0kyQ19SRUdfQ09OVFJPTF9TVE9QLAorCQkJZHJ2X2RhdGEt PnJlZ19iYXNlICsgTVY2NFhYWF9JMkNfUkVHX0NPTlRST0wpOworCQlkcnZfZGF0YS0+Ymxv Y2sgPSAwOworCQl3YWtlX3VwX2ludGVycnVwdGlibGUoJmRydl9kYXRhLT53YWl0cSk7CisJ CWJyZWFrOworCisJY2FzZSBNVjY0WFhYX0kyQ19BQ1RJT05fSU5WQUxJRDoKKwlkZWZhdWx0 OgorCQlkZXZfZXJyKCZkcnZfZGF0YS0+YWRhcHRlci5kZXYsCisJCQkibXY2NHh4eF9pMmNf ZG9fYWN0aW9uOiBJbnZhbGlkIGFjdGlvbjogJWRcbiIsCisJCQlkcnZfZGF0YS0+YWN0aW9u KTsKKwkJZHJ2X2RhdGEtPnJjID0gLUVJTzsKKwkJLyogRkFMTFRIUlUgKi8KKwljYXNlIE1W NjRYWFhfSTJDX0FDVElPTl9TRU5EX1NUT1A6CisJCWRydl9kYXRhLT5jbnRsX2JpdHMgJj0g fk1WNjRYWFhfSTJDX1JFR19DT05UUk9MX0lOVEVOOworCQl3cml0ZWwoZHJ2X2RhdGEtPmNu dGxfYml0cyB8IE1WNjRYWFhfSTJDX1JFR19DT05UUk9MX1NUT1AsCisJCQlkcnZfZGF0YS0+ cmVnX2Jhc2UgKyBNVjY0WFhYX0kyQ19SRUdfQ09OVFJPTCk7CisJCWRydl9kYXRhLT5ibG9j ayA9IDA7CisJCXdha2VfdXBfaW50ZXJydXB0aWJsZSgmZHJ2X2RhdGEtPndhaXRxKTsKKwkJ YnJlYWs7CisJfQorCisJcmV0dXJuOworfQorCitzdGF0aWMgaW50CittdjY0eHh4X2kyY19p bnRyKGludCBpcnEsIHZvaWQgKmRldl9pZCwgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCit7CisJ c3RydWN0IG12NjR4eHhfaTJjX2RhdGEJKmRydl9kYXRhID0gZGV2X2lkOworCXUzMglzdGF0 dXM7CisJbG9uZwlmbGFnczsKKwlpbnQJcmMgPSBJUlFfTk9ORTsKKworCXNwaW5fbG9ja19p cnFzYXZlKCZkcnZfZGF0YS0+bG9jaywgZmxhZ3MpOworCXdoaWxlIChyZWFkbChkcnZfZGF0 YS0+cmVnX2Jhc2UgKyBNVjY0WFhYX0kyQ19SRUdfQ09OVFJPTCkgJgorCQkJCQkJTVY2NFhY WF9JMkNfUkVHX0NPTlRST0xfSUZMRykgeworCQlzdGF0dXMgPSByZWFkbChkcnZfZGF0YS0+ cmVnX2Jhc2UgKyBNVjY0WFhYX0kyQ19SRUdfU1RBVFVTKTsKKwkJbXY2NHh4eF9pMmNfZnNt KGRydl9kYXRhLCBzdGF0dXMpOworCQltdjY0eHh4X2kyY19kb19hY3Rpb24oZHJ2X2RhdGEp OworCQlyYyA9IElSUV9IQU5ETEVEOworCX0KKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZk cnZfZGF0YS0+bG9jaywgZmxhZ3MpOworCisJcmV0dXJuIHJjOworfQorCisvKgorICoqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqCisgKgorICoJSTJDIE1zZyBFeGVjdXRpb24gUm91dGluZXMK KyAqCisgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAqLworc3RhdGljIHZvaWQKK212NjR4 eHhfaTJjX3ByZXBhcmVfZm9yX2lvKHN0cnVjdCBtdjY0eHh4X2kyY19kYXRhICpkcnZfZGF0 YSwKKwlzdHJ1Y3QgaTJjX21zZyAqbXNnKQoreworCXUzMglkaXIgPSAwOworCisJZHJ2X2Rh dGEtPm1zZyA9IG1zZzsKKwlkcnZfZGF0YS0+Ynl0ZV9wb3NuID0gMDsKKwlkcnZfZGF0YS0+ Ynl0ZXNfbGVmdCA9IG1zZy0+bGVuOworCWRydl9kYXRhLT5yYyA9IDA7CisJZHJ2X2RhdGEt PmNudGxfYml0cyA9IE1WNjRYWFhfSTJDX1JFR19DT05UUk9MX0FDSyB8CisJCU1WNjRYWFhf STJDX1JFR19DT05UUk9MX0lOVEVOIHwgTVY2NFhYWF9JMkNfUkVHX0NPTlRST0xfVFdTSUVO OworCisJaWYgKG1zZy0+ZmxhZ3MgJiBJMkNfTV9SRCkKKwkJZGlyID0gMTsKKworCWlmICht c2ctPmZsYWdzICYgSTJDX01fUkVWX0RJUl9BRERSKQorCQlkaXIgXj0gMTsKKworCWlmICht c2ctPmZsYWdzICYgSTJDX01fVEVOKSB7CisJCWRydl9kYXRhLT5hZGRyMSA9IDB4ZjAgfCAo KCh1MzIpbXNnLT5hZGRyICYgMHgzMDApID4+IDcpIHwgZGlyOworCQlkcnZfZGF0YS0+YWRk cjIgPSAodTMyKW1zZy0+YWRkciAmIDB4ZmY7CisJfSBlbHNlIHsKKwkJZHJ2X2RhdGEtPmFk ZHIxID0gKCh1MzIpbXNnLT5hZGRyICYgMHg3ZikgPDwgMSB8IGRpcjsKKwkJZHJ2X2RhdGEt PmFkZHIyID0gMDsKKwl9CisKKwlyZXR1cm47Cit9CisKK3N0YXRpYyB2b2lkCittdjY0eHh4 X2kyY193YWl0X2Zvcl9jb21wbGV0aW9uKHN0cnVjdCBtdjY0eHh4X2kyY19kYXRhICpkcnZf ZGF0YSkKK3sKKwlsb25nCWZsYWdzLCB0aW1lX2xlZnQ7CisJY2hhcglhYm9ydCA9IDA7CisK Kwl0aW1lX2xlZnQgPSB3YWl0X2V2ZW50X2ludGVycnVwdGlibGVfdGltZW91dChkcnZfZGF0 YS0+d2FpdHEsCisJCSFkcnZfZGF0YS0+YmxvY2ssIG1zZWNzX3RvX2ppZmZpZXMoZHJ2X2Rh dGEtPmFkYXB0ZXIudGltZW91dCkpOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmRydl9kYXRh LT5sb2NrLCBmbGFncyk7CisJaWYgKCF0aW1lX2xlZnQpIHsgLyogVGltZWQgb3V0ICovCisJ CWRydl9kYXRhLT5yYyA9IC1FVElNRURPVVQ7CisJCWFib3J0ID0gMTsKKwl9IGVsc2UgaWYg KHRpbWVfbGVmdCA8IDApIHsgLyogSW50ZXJydXB0ZWQvRXJyb3IgKi8KKwkJZHJ2X2RhdGEt PnJjID0gdGltZV9sZWZ0OyAvKiBlcnJubyB2YWx1ZSAqLworCQlhYm9ydCA9IDE7CisJfQor CisJaWYgKGFib3J0ICYmIGRydl9kYXRhLT5ibG9jaykgeworCQlkcnZfZGF0YS0+c3RhdGUg PSBNVjY0WFhYX0kyQ19TVEFURV9BQk9SVElORzsKKwkJc3Bpbl91bmxvY2tfaXJxcmVzdG9y ZSgmZHJ2X2RhdGEtPmxvY2ssIGZsYWdzKTsKKworCQl0aW1lX2xlZnQgPSB3YWl0X2V2ZW50 X3RpbWVvdXQoZHJ2X2RhdGEtPndhaXRxLAorCQkJIWRydl9kYXRhLT5ibG9jaywKKwkJCW1z ZWNzX3RvX2ppZmZpZXMoZHJ2X2RhdGEtPmFkYXB0ZXIudGltZW91dCkpOworCisJCWlmICh0 aW1lX2xlZnQgPD0gMCkgeworCQkJZHJ2X2RhdGEtPnN0YXRlID0gTVY2NFhYWF9JMkNfU1RB VEVfSURMRTsKKwkJCWRldl9lcnIoJmRydl9kYXRhLT5hZGFwdGVyLmRldiwKKwkJCQkibXY2 NHh4eDogSTJDIGJ1cyBsb2NrZWRcbiIpOworCQl9CisJfSBlbHNlCisJCXNwaW5fdW5sb2Nr X2lycXJlc3RvcmUoJmRydl9kYXRhLT5sb2NrLCBmbGFncyk7CisKKwlyZXR1cm47Cit9CisK K3N0YXRpYyBpbnQKK212NjR4eHhfaTJjX2V4ZWN1dGVfbXNnKHN0cnVjdCBtdjY0eHh4X2ky Y19kYXRhICpkcnZfZGF0YSwgc3RydWN0IGkyY19tc2cgKm1zZykKK3sKKwlsb25nCWZsYWdz OworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmRydl9kYXRhLT5sb2NrLCBmbGFncyk7CisJbXY2 NHh4eF9pMmNfcHJlcGFyZV9mb3JfaW8oZHJ2X2RhdGEsIG1zZyk7CisKKwlpZiAodW5saWtl bHkobXNnLT5mbGFncyAmIEkyQ19NX05PU1RBUlQpKSB7IC8qIFNraXAgc3RhcnQvYWRkciBw aGFzZXMgKi8KKwkJaWYgKGRydl9kYXRhLT5tc2ctPmZsYWdzICYgSTJDX01fUkQpIHsKKwkJ CS8qIE5vIGFjdGlvbiB0byBkbywgd2FpdCBmb3Igc2xhdmUgdG8gc2VuZCBhIGJ5dGUgKi8K KwkJCWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0WFhYX0kyQ19BQ1RJT05fQ09OVElOVUU7CisJ CQlkcnZfZGF0YS0+c3RhdGUgPQorCQkJCU1WNjRYWFhfSTJDX1NUQVRFX1dBSVRJTkdfRk9S X1NMQVZFX0RBVEE7CisJCX0gZWxzZSB7CisJCQlkcnZfZGF0YS0+YWN0aW9uID0gTVY2NFhY WF9JMkNfQUNUSU9OX1NFTkRfREFUQTsKKwkJCWRydl9kYXRhLT5zdGF0ZSA9CisJCQkJTVY2 NFhYWF9JMkNfU1RBVEVfV0FJVElOR19GT1JfU0xBVkVfQUNLOworCQkJZHJ2X2RhdGEtPmJ5 dGVzX2xlZnQtLTsKKwkJfQorCX0gZWxzZSB7CisJCWRydl9kYXRhLT5hY3Rpb24gPSBNVjY0 WFhYX0kyQ19BQ1RJT05fU0VORF9TVEFSVDsKKwkJZHJ2X2RhdGEtPnN0YXRlID0gTVY2NFhY WF9JMkNfU1RBVEVfV0FJVElOR19GT1JfU1RBUlRfQ09ORDsKKwl9CisKKwlkcnZfZGF0YS0+ YmxvY2sgPSAxOworCW12NjR4eHhfaTJjX2RvX2FjdGlvbihkcnZfZGF0YSk7CisJc3Bpbl91 bmxvY2tfaXJxcmVzdG9yZSgmZHJ2X2RhdGEtPmxvY2ssIGZsYWdzKTsKKworCW12NjR4eHhf aTJjX3dhaXRfZm9yX2NvbXBsZXRpb24oZHJ2X2RhdGEpOworCXJldHVybiBkcnZfZGF0YS0+ cmM7Cit9CisKKy8qCisgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAqCisgKglJMkMgQ29y ZSBTdXBwb3J0IFJvdXRpbmVzIChJbnRlcmZhY2UgdG8gaGlnaGVyIGxldmVsIEkyQyBjb2Rl KQorICoKKyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgorICovCitzdGF0aWMgdTMyCittdjY0 eHh4X2kyY19mdW5jdGlvbmFsaXR5KHN0cnVjdCBpMmNfYWRhcHRlciAqYWRhcCkKK3sKKwly ZXR1cm4gSTJDX0ZVTkNfSTJDIHwgSTJDX0ZVTkNfMTBCSVRfQUREUiB8IEkyQ19GVU5DX1NN QlVTX0VNVUw7Cit9CisKK3N0YXRpYyBpbnQKK212NjR4eHhfaTJjX3hmZXIoc3RydWN0IGky Y19hZGFwdGVyICphZGFwLCBzdHJ1Y3QgaTJjX21zZyBtc2dzW10sIGludCBudW0pCit7CisJ c3RydWN0IG12NjR4eHhfaTJjX2RhdGEgKmRydl9kYXRhID0gaTJjX2dldF9hZGFwZGF0YShh ZGFwKTsKKwlpbnQJaSwgcmMgPSAwOworCisJZm9yIChpPTA7IGk8bnVtOyBpKyspCisJCWlm ICgocmMgPSBtdjY0eHh4X2kyY19leGVjdXRlX21zZyhkcnZfZGF0YSwgJm1zZ3NbaV0pKSAh PSAwKQorCQkJYnJlYWs7CisKKwlyZXR1cm4gcmM7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgaTJj X2FsZ29yaXRobSBtdjY0eHh4X2kyY19hbGdvID0geworCS5uYW1lID0gTVY2NFhYWF9JMkNf Q1RMUl9OQU1FICIgYWxnb3JpdGhtIiwKKwkuaWQgPSBJMkNfQUxHT19NVjY0WFhYLAorCS5t YXN0ZXJfeGZlciA9IG12NjR4eHhfaTJjX3hmZXIsCisJLmZ1bmN0aW9uYWxpdHkgPSBtdjY0 eHh4X2kyY19mdW5jdGlvbmFsaXR5LAorfTsKKworLyoKKyAqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKgorICoKKyAqCURyaXZlciBJbnRlcmZhY2UgJiBFYXJseSBJbml0IFJvdXRpbmVzCisg KgorICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqCisgKi8KK3N0YXRpYyB2b2lkIF9fZGV2aW5p dAorbXY2NHh4eF9pMmNfaHdfaW5pdChzdHJ1Y3QgbXY2NHh4eF9pMmNfZGF0YSAqZHJ2X2Rh dGEpCit7CisJd3JpdGVsKDAsIGRydl9kYXRhLT5yZWdfYmFzZSArIE1WNjRYWFhfSTJDX1JF R19TT0ZUX1JFU0VUKTsKKwl3cml0ZWwoKCgoZHJ2X2RhdGEtPmZyZXFfbSAmIDB4ZikgPDwg MykgfCAoZHJ2X2RhdGEtPmZyZXFfbiAmIDB4NykpLAorCQlkcnZfZGF0YS0+cmVnX2Jhc2Ug KyBNVjY0WFhYX0kyQ19SRUdfQkFVRCk7CisJd3JpdGVsKDAsIGRydl9kYXRhLT5yZWdfYmFz ZSArIE1WNjRYWFhfSTJDX1JFR19TTEFWRV9BRERSKTsKKwl3cml0ZWwoMCwgZHJ2X2RhdGEt PnJlZ19iYXNlICsgTVY2NFhYWF9JMkNfUkVHX0VYVF9TTEFWRV9BRERSKTsKKwl3cml0ZWwo TVY2NFhYWF9JMkNfUkVHX0NPTlRST0xfVFdTSUVOIHwgTVY2NFhYWF9JMkNfUkVHX0NPTlRS T0xfU1RPUCwKKwkJZHJ2X2RhdGEtPnJlZ19iYXNlICsgTVY2NFhYWF9JMkNfUkVHX0NPTlRS T0wpOworCWRydl9kYXRhLT5zdGF0ZSA9IE1WNjRYWFhfSTJDX1NUQVRFX0lETEU7CisJcmV0 dXJuOworfQorCitzdGF0aWMgaW50IF9fZGV2aW5pdAorbXY2NHh4eF9pMmNfbWFwX3JlZ3Mo c3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGQsCisJc3RydWN0IG12NjR4eHhfaTJjX2RhdGEg KmRydl9kYXRhKQoreworCXN0cnVjdCByZXNvdXJjZQkqcjsKKworCWlmICgociA9IHBsYXRm b3JtX2dldF9yZXNvdXJjZShwZCwgSU9SRVNPVVJDRV9NRU0sIDApKSAmJgorCQlyZXF1ZXN0 X21lbV9yZWdpb24oci0+c3RhcnQsIE1WNjRYWFhfSTJDX1JFR19CTE9DS19TSVpFLAorCQkJ ZHJ2X2RhdGEtPmFkYXB0ZXIubmFtZSkpIHsKKworCQlkcnZfZGF0YS0+cmVnX2Jhc2UgPSBp b3JlbWFwKHItPnN0YXJ0LAorCQkJTVY2NFhYWF9JMkNfUkVHX0JMT0NLX1NJWkUpOworCQlk cnZfZGF0YS0+cmVnX2Jhc2VfcCA9IHItPnN0YXJ0OworCX0gZWxzZQorCQlyZXR1cm4gLUVO T01FTTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBfX2RldmV4aXQKK212NjR4 eHhfaTJjX3VubWFwX3JlZ3Moc3RydWN0IG12NjR4eHhfaTJjX2RhdGEgKmRydl9kYXRhKQor eworCWlmIChkcnZfZGF0YS0+cmVnX2Jhc2UpIHsKKwkJaW91bm1hcChkcnZfZGF0YS0+cmVn X2Jhc2UpOworCQlyZWxlYXNlX21lbV9yZWdpb24oZHJ2X2RhdGEtPnJlZ19iYXNlX3AsCisJ CQlNVjY0WFhYX0kyQ19SRUdfQkxPQ0tfU0laRSk7CisJfQorCisJZHJ2X2RhdGEtPnJlZ19i YXNlID0gTlVMTDsKKwlkcnZfZGF0YS0+cmVnX2Jhc2VfcCA9IDA7CisJcmV0dXJuOworfQor CitzdGF0aWMgaW50IF9fZGV2aW5pdAorbXY2NHh4eF9pMmNfcHJvYmUoc3RydWN0IGRldmlj ZSAqZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UJCSpwZCA9IHRvX3BsYXRmb3Jt X2RldmljZShkZXYpOworCXN0cnVjdCBtdjY0eHh4X2kyY19kYXRhCQkqZHJ2X2RhdGE7CisJ c3RydWN0IG12NjR4eHhfaTJjX3BkYXRhCSpwZGF0YSA9IGRldi0+cGxhdGZvcm1fZGF0YTsK KwlpbnQJcmM7CisKKwlpZiAoKHBkLT5pZCAhPSAwKSB8fCAhcGRhdGEpCisJCXJldHVybiAt RU5PREVWOworCisJZHJ2X2RhdGEgPSBrbWFsbG9jKHNpemVvZihzdHJ1Y3QgbXY2NHh4eF9p MmNfZGF0YSksIEdGUF9LRVJORUwpOworCisJaWYgKCFkcnZfZGF0YSkKKwkJcmV0dXJuIC1F Tk9NRU07CisKKwltZW1zZXQoZHJ2X2RhdGEsIDAsIHNpemVvZihzdHJ1Y3QgbXY2NHh4eF9p MmNfZGF0YSkpOworCisJaWYgKG12NjR4eHhfaTJjX21hcF9yZWdzKHBkLCBkcnZfZGF0YSkp IHsKKwkJcmMgPSAtRU5PREVWOworCQlnb3RvIGV4aXRfa2ZyZWU7CisJfQorCisJc3RybmNw eShkcnZfZGF0YS0+YWRhcHRlci5uYW1lLCBNVjY0WFhYX0kyQ19DVExSX05BTUUgIiBhZGFw dGVyIiwKKwkJSTJDX05BTUVfU0laRSk7CisKKwlpbml0X3dhaXRxdWV1ZV9oZWFkKCZkcnZf ZGF0YS0+d2FpdHEpOworCXNwaW5fbG9ja19pbml0KCZkcnZfZGF0YS0+bG9jayk7CisKKwlk cnZfZGF0YS0+ZnJlcV9tID0gcGRhdGEtPmZyZXFfbTsKKwlkcnZfZGF0YS0+ZnJlcV9uID0g cGRhdGEtPmZyZXFfbjsKKwlkcnZfZGF0YS0+aXJxID0gcGxhdGZvcm1fZ2V0X2lycShwZCwg MCk7CisJZHJ2X2RhdGEtPmFkYXB0ZXIuaWQgPSBJMkNfQUxHT19NVjY0WFhYIHwgSTJDX0hX X01WNjRYWFg7CisJZHJ2X2RhdGEtPmFkYXB0ZXIuYWxnbyA9ICZtdjY0eHh4X2kyY19hbGdv OworCWRydl9kYXRhLT5hZGFwdGVyLnRpbWVvdXQgPSBwZGF0YS0+dGltZW91dDsKKwlkcnZf ZGF0YS0+YWRhcHRlci5yZXRyaWVzID0gcGRhdGEtPnJldHJpZXM7CisJZGV2X3NldF9kcnZk YXRhKGRldiwgZHJ2X2RhdGEpOworCWkyY19zZXRfYWRhcGRhdGEoJmRydl9kYXRhLT5hZGFw dGVyLCBkcnZfZGF0YSk7CisKKwlpZiAocmVxdWVzdF9pcnEoZHJ2X2RhdGEtPmlycSwgbXY2 NHh4eF9pMmNfaW50ciwgMCwKKwkJTVY2NFhYWF9JMkNfQ1RMUl9OQU1FLCBkcnZfZGF0YSkp IHsKKworCQlkZXZfZXJyKGRldiwgIm12NjR4eHg6IENhbid0IHJlZ2lzdGVyIGludHIgaGFu ZGxlciAiCisJCQkiaXJxOiAlZFxuIiwgZHJ2X2RhdGEtPmlycSk7CisJCXJjID0gLUVJTlZB TDsKKwkJZ290byBleGl0X3VubWFwX3JlZ3M7CisJfSBlbHNlIGlmICgocmMgPSBpMmNfYWRk X2FkYXB0ZXIoJmRydl9kYXRhLT5hZGFwdGVyKSkgIT0gMCkgeworCQlkZXZfZXJyKGRldiwg Im12NjR4eHg6IENhbid0IGFkZCBpMmMgYWRhcHRlciwgcmM6ICVkXG4iLCAtcmMpOworCQln b3RvIGV4aXRfZnJlZV9pcnE7CisJfQorCisJbXY2NHh4eF9pMmNfaHdfaW5pdChkcnZfZGF0 YSk7CisKKwlyZXR1cm4gMDsKKworCWV4aXRfZnJlZV9pcnE6CisJCWZyZWVfaXJxKGRydl9k YXRhLT5pcnEsIGRydl9kYXRhKTsKKwlleGl0X3VubWFwX3JlZ3M6CisJCW12NjR4eHhfaTJj X3VubWFwX3JlZ3MoZHJ2X2RhdGEpOworCWV4aXRfa2ZyZWU6CisJCWtmcmVlKGRydl9kYXRh KTsKKwlyZXR1cm4gcmM7Cit9CisKK3N0YXRpYyBpbnQgX19kZXZleGl0CittdjY0eHh4X2ky Y19yZW1vdmUoc3RydWN0IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBtdjY0eHh4X2kyY19k YXRhCQkqZHJ2X2RhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlpbnQJcmM7CisKKwly YyA9IGkyY19kZWxfYWRhcHRlcigmZHJ2X2RhdGEtPmFkYXB0ZXIpOworCWZyZWVfaXJxKGRy dl9kYXRhLT5pcnEsIGRydl9kYXRhKTsKKwltdjY0eHh4X2kyY191bm1hcF9yZWdzKGRydl9k YXRhKTsKKwlrZnJlZShkcnZfZGF0YSk7CisKKwlyZXR1cm4gcmM7Cit9CisKK3N0YXRpYyBz dHJ1Y3QgZGV2aWNlX2RyaXZlciBtdjY0eHh4X2kyY19kcml2ZXIgPSB7CisJLm5hbWUJPSBN VjY0WFhYX0kyQ19DVExSX05BTUUsCisJLmJ1cwk9ICZwbGF0Zm9ybV9idXNfdHlwZSwKKwku cHJvYmUJPSBtdjY0eHh4X2kyY19wcm9iZSwKKwkucmVtb3ZlCT0gbXY2NHh4eF9pMmNfcmVt b3ZlLAorfTsKKworc3RhdGljIGludCBfX2RldmluaXQKK212NjR4eHhfaTJjX2luaXQodm9p ZCkKK3sKKwlyZXR1cm4gZHJpdmVyX3JlZ2lzdGVyKCZtdjY0eHh4X2kyY19kcml2ZXIpOwor fQorCitzdGF0aWMgdm9pZCBfX2RldmV4aXQKK212NjR4eHhfaTJjX2V4aXQodm9pZCkKK3sK Kwlkcml2ZXJfdW5yZWdpc3RlcigmbXY2NHh4eF9pMmNfZHJpdmVyKTsKKwlyZXR1cm47Cit9 CisKK21vZHVsZV9pbml0KG12NjR4eHhfaTJjX2luaXQpOworbW9kdWxlX2V4aXQobXY2NHh4 eF9pMmNfZXhpdCk7CisKK01PRFVMRV9BVVRIT1IoIk1hcmsgQS4gR3JlZXIgPG1ncmVlckBt dmlzdGEuY29tPiIpOworTU9EVUxFX0RFU0NSSVBUSU9OKCJNYXJ2ZWxsIG12NjR4eHggaG9z dCBicmlkZ2UgaTJjIGN0bHIgZHJpdmVyIik7CitNT0RVTEVfTElDRU5TRSgiR1BMIik7CmRp ZmYgLU5ydSBhL2luY2x1ZGUvbGludXgvaTJjLWlkLmggYi9pbmNsdWRlL2xpbnV4L2kyYy1p ZC5oCi0tLSBhL2luY2x1ZGUvbGludXgvaTJjLWlkLmgJMjAwNS0wMi0wMyAxMjoxMDozNSAt MDc6MDAKKysrIGIvaW5jbHVkZS9saW51eC9pMmMtaWQuaAkyMDA1LTAyLTAzIDEyOjEwOjM1 IC0wNzowMApAQCAtMjAwLDYgKzIwMCw5IEBACiAKICNkZWZpbmUgSTJDX0FMR09fU0lCWVRF IDB4MTUwMDAwCS8qIEJyb2FkY29tIFNpQnl0ZSBTT0NzCQkqLwogI2RlZmluZSBJMkNfQUxH T19TR0kJMHgxNjAwMDAgICAgICAgIC8qIFNHSSBhbGdvcml0aG0gICAgICAgICAgICAgICAg Ki8KKwkJCQkJLyogMHgxNzAwMDAgLSBVU0IJCSovCisJCQkJCS8qIDB4MTgwMDAwIC0gVmly dHVhbCBidXNlcwkqLworI2RlZmluZSBJMkNfQUxHT19NVjY0WFhYIDB4MTkwMDAwICAgICAg IC8qIE1hcnZlbGwgbXY2NHh4eCBpMmMgY3RscgkqLwogCiAjZGVmaW5lIEkyQ19BTEdPX0VY UAkweDgwMDAwMAkvKiBleHBlcmltZW50YWwJCQkqLwogCkBAIC0zMDUsNSArMzA4LDggQEAK IAogLyogLS0tIE1DUDEwNyBhZGFwdGVyICovCiAjZGVmaW5lIEkyQ19IV19NUEMxMDcgMHgw MAorCisvKiAtLS0gTWFydmVsbCBtdjY0eHh4IGkyYyBhZGFwdGVyICovCisjZGVmaW5lIEky Q19IV19NVjY0WFhYIDB4MDAKIAogI2VuZGlmIC8qIExJTlVYX0kyQ19JRF9IICovCmRpZmYg LU5ydSBhL2luY2x1ZGUvbGludXgvbXY2NDN4eC5oIGIvaW5jbHVkZS9saW51eC9tdjY0M3h4 LmgKLS0tIGEvaW5jbHVkZS9saW51eC9tdjY0M3h4LmgJMjAwNS0wMi0wMyAxMjoxMDozNSAt MDc6MDAKKysrIGIvaW5jbHVkZS9saW51eC9tdjY0M3h4LmgJMjAwNS0wMi0wMyAxMjoxMDoz NSAtMDc6MDAKQEAgLTk3NywxMiArOTc3LDkgQEAKIC8qIEkyQyBSZWdpc3RlcnMgICAgICAg ICAgICAgICAgICAgICAgICAqLwogLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKiovCiAKLSNkZWZpbmUgTVY2NDM0MF9JMkNfU0xBVkVfQUREUiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhjMDAwCi0jZGVmaW5lIE1WNjQzNDBfSTJD X0VYVEVOREVEX1NMQVZFX0FERFIgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YzAx MAotI2RlZmluZSBNVjY0MzQwX0kyQ19EQVRBICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAweGMwMDQKLSNkZWZpbmUgTVY2NDM0MF9JMkNfQ09OVFJPTCAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhjMDA4Ci0jZGVmaW5l IE1WNjQzNDBfSTJDX1NUQVRVU19CQVVERV9SQVRFICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIDB4YzAwQwotI2RlZmluZSBNVjY0MzQwX0kyQ19TT0ZUX1JFU0VUICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGMwMWMKKyNkZWZpbmUgTVY2NFhYWF9J MkNfQ1RMUl9OQU1FCQkJCQkibXY2NHh4eCBpMmMiCisjZGVmaW5lIE1WNjRYWFhfSTJDX09G RlNFVCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YzAwMAor I2RlZmluZSBNVjY0WFhYX0kyQ19SRUdfQkxPQ0tfU0laRSAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAweDAwMjAKIAogLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKiovCiAvKiBHUFAgSW50ZXJmYWNlIFJlZ2lzdGVycyAgICAgICAgICAgICAg Ki8KQEAgLTEwODMsNiArMTA4MCwxNCBAQAogCXU4CWJyZ19jYW5fdHVuZTsKIAl1OAlicmdf Y2xrX3NyYzsKIAl1MzIJYnJnX2Nsa19mcmVxOworfTsKKworLyogaTJjIFBsYXRmb3JtIERl dmljZSwgRHJpdmVyIERhdGEgKi8KK3N0cnVjdCBtdjY0eHh4X2kyY19wZGF0YSB7CisJdTMy CWZyZXFfbTsKKwl1MzIJZnJlcV9uOworCXUzMgl0aW1lb3V0OwkvKiBJbiBtaWxsaXNlY29u ZHMgKi8KKwl1MzIJcmV0cmllczsKIH07CiAKICNlbmRpZiAvKiBfX0FTTV9NVjY0MzQwX0gg Ki8K --------------000403080908090506040000--