From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3A36C43460 for ; Thu, 22 Apr 2021 10:50:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D66161428 for ; Thu, 22 Apr 2021 10:50:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236003AbhDVKuh (ORCPT ); Thu, 22 Apr 2021 06:50:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235811AbhDVKue (ORCPT ); Thu, 22 Apr 2021 06:50:34 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C974CC06174A for ; Thu, 22 Apr 2021 03:49:58 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id c15so35366372wro.13 for ; Thu, 22 Apr 2021 03:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=qvOTcTVyYlflIk+Jb14S2f2tqpgUBhY30LBrMPd2EGD8cMH5aQ3wDD2CrnH86pGQlA zgQrUvShjT3qtiOTUJM9UY08kgKMi7erf0JfTRODPe7DK5T8KvpzSWuQ7ozbAcoizrEa amiLvOWmp38OX5Z/1Rd9c4qVHoLDlJRRcsVGgKUdNUN5LaSAIVAXZoxFQZ126L1R+2iG 9/842WURmR39JyKqs3CoBhn/yasfCEVJaa9wyj3LnAOJ/19Jw+Nc2uN1QVpjjpdtNtk/ WfBJOQWnOp3C6PbpxVhXSCkTsW6qVrAIKx/ZfpLsvHEfpiyxOtxxfbEmcn3ruMvlzSG9 LcaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=EHJtYsH7rIE7HuX61tbIfVMjvnqiuIHKZjcpC/nySHvqez3D6AxMS49Rru+ZYv98iJ hO450pnC06myRPW1GaGBTg/aWCOh//YBtwWsCdTWPQ93GgDagii7GoB3+osWOb/b2/8A CRp754AZpxkkzPwDvl3xlKe9Sgu6tncnIO+6C1ERJWKMxe3Ej0y+N6kHNzIrWZD015ZG wn3x9alsiRQTbYTL+Zn9dSRbNKnmGsfpOAp+hJDBhCl9dym8HcedPPDxekkfWtrZ6Vdg mGAJ7NvjHZGPyFD8AuKolEQfnyXC3SRNEHAFSCAsbIiU0mwoC/M6kzkavUdDXoUw7yMv dZDg== X-Gm-Message-State: AOAM531aXAlDp3NDP5a3Bkyj2+RSrwdF55H3I/Ff02Cbku4c8C+K3jS5 sCa/K/wZ5xOCZNHkhy9lGmlsmw== X-Google-Smtp-Source: ABdhPJyOwo77PTIJ1nQExQ7gKG4p91c+E78LEttfRaxFs5aN9WTMM99HM8dv2PocD/ipvsGg1ZUeBg== X-Received: by 2002:a05:6000:82:: with SMTP id m2mr3316986wrx.139.1619088597324; Thu, 22 Apr 2021 03:49:57 -0700 (PDT) Received: from ggregory-ubuntuvm ([62.3.69.143]) by smtp.gmail.com with ESMTPSA id q5sm2917256wrv.17.2021.04.22.03.49.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Apr 2021 03:49:56 -0700 (PDT) Date: Thu, 22 Apr 2021 11:49:54 +0100 From: Graeme Gregory To: Quan Nguyen Cc: Corey Minyard , Rob Herring , Joel Stanley , Andrew Jeffery , Wolfram Sang , Philipp Zabel , openipmi-developer@lists.sourceforge.net, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, openbmc@lists.ozlabs.org, "Thang Q . Nguyen" , Open Source Submission , Phong Vo Subject: Re: [PATCH v2 2/3] drivers: char: ipmi: Add Aspeed SSIF BMC driver Message-ID: <20210422104954.GB13153@ggregory-ubuntuvm> References: <20210330141029.20412-1-quan@os.amperecomputing.com> <20210330141029.20412-3-quan@os.amperecomputing.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20210330141029.20412-3-quan@os.amperecomputing.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Mar 30, 2021 at 09:10:28PM +0700, Quan Nguyen wrote: > The SMBus system interface (SSIF) IPMI BMC driver can be used to perform > in-band IPMI communication with their host in management (BMC) side. > > This commits adds support specifically for Aspeed AST2500 which commonly > used as Board Management Controllers. > > Signed-off-by: Quan Nguyen > --- > drivers/char/ipmi/Kconfig | 22 + > drivers/char/ipmi/Makefile | 2 + > drivers/char/ipmi/ssif_bmc.c | 645 ++++++++++++++++++++++++++++ > drivers/char/ipmi/ssif_bmc.h | 92 ++++ > drivers/char/ipmi/ssif_bmc_aspeed.c | 132 ++++++ > 5 files changed, 893 insertions(+) > create mode 100644 drivers/char/ipmi/ssif_bmc.c > create mode 100644 drivers/char/ipmi/ssif_bmc.h > create mode 100644 drivers/char/ipmi/ssif_bmc_aspeed.c > > diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig > index 07847d9a459a..45be57023577 100644 > --- a/drivers/char/ipmi/Kconfig > +++ b/drivers/char/ipmi/Kconfig > @@ -133,6 +133,28 @@ config ASPEED_BT_IPMI_BMC > found on Aspeed SOCs (AST2400 and AST2500). The driver > implements the BMC side of the BT interface. > > +config SSIF_IPMI_BMC > + tristate "SSIF IPMI BMC driver" > + select I2C > + select I2C_SLAVE > + help > + This enables the IPMI SMBus system interface (SSIF) at the > + management (BMC) side. > + > + The driver implements the BMC side of the SMBus system > + interface (SSIF). > + > +config ASPEED_SSIF_IPMI_BMC > + depends on ARCH_ASPEED || COMPILE_TEST > + select SSIF_IPMI_BMC > + tristate "Aspeed SSIF IPMI BMC driver" > + help > + Provides a driver for the SSIF IPMI interface found on > + Aspeed AST2500 SoC. > + > + The driver implements the BMC side of the SMBus system > + interface (SSIF), specific for Aspeed AST2500 SoC. > + > config IPMB_DEVICE_INTERFACE > tristate 'IPMB Interface handler' > depends on I2C > diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile > index 0822adc2ec41..05b993f7335b 100644 > --- a/drivers/char/ipmi/Makefile > +++ b/drivers/char/ipmi/Makefile > @@ -27,3 +27,5 @@ obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o > obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o > obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o > obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o > +obj-$(CONFIG_SSIF_IPMI_BMC) += ssif_bmc.o > +obj-$(CONFIG_ASPEED_SSIF_IPMI_BMC) += ssif_bmc_aspeed.o > diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c > new file mode 100644 > index 000000000000..ae6e8750c795 > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc.c > @@ -0,0 +1,645 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * The driver for BMC side of SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "ssif_bmc.h" > + > +/* > + * Call in WRITE context > + */ > +static int send_ssif_bmc_response(struct ssif_bmc_ctx *ssif_bmc, bool non_blocking) > +{ > + unsigned long flags; > + int ret; > + > + if (!non_blocking) { > +retry: > + ret = wait_event_interruptible(ssif_bmc->wait_queue, > + !ssif_bmc->response_in_progress); > + if (ret) > + return ret; > + } > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (ssif_bmc->response_in_progress) { > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + if (non_blocking) > + return -EAGAIN; > + > + goto retry; > + } > + > + /* > + * Check the response data length from userspace to determine the type > + * of the response message whether it is single-part or multi-part. > + */ > + ssif_bmc->is_singlepart_read = > + (ssif_msg_len(&ssif_bmc->response) <= (MAX_PAYLOAD_PER_TRANSACTION + 1)) ? > + true : false; /* 1: byte of length */ > + > + ssif_bmc->response_in_progress = true; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + return 0; > +} > + > +/* > + * Call in READ context > + */ > +static int receive_ssif_bmc_request(struct ssif_bmc_ctx *ssif_bmc, bool non_blocking) > +{ > + unsigned long flags; > + int ret; > + > + if (!non_blocking) { > +retry: > + ret = wait_event_interruptible(ssif_bmc->wait_queue, > + ssif_bmc->request_available); > + if (ret) > + return ret; > + } > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (!ssif_bmc->request_available) { > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + if (non_blocking) > + return -EAGAIN; > + goto retry; > + } > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + return 0; > +} > + > +/* Handle SSIF message that will be sent to user */ > +static ssize_t ssif_bmc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + struct ssif_msg msg; > + unsigned long flags; > + ssize_t ret; > + > + mutex_lock(&ssif_bmc->file_mutex); > + > + ret = receive_ssif_bmc_request(ssif_bmc, file->f_flags & O_NONBLOCK); > + if (ret < 0) > + goto out; > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + count = min_t(ssize_t, count, ssif_msg_len(&ssif_bmc->request)); > + memcpy(&msg, &ssif_bmc->request, count); > + ssif_bmc->request_available = false; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + ret = copy_to_user(buf, &msg, count); > +out: > + mutex_unlock(&ssif_bmc->file_mutex); > + > + return (ret < 0) ? ret : count; > +} > + > +/* Handle SSIF message that is written by user */ > +static ssize_t ssif_bmc_write(struct file *file, const char __user *buf, size_t count, > + loff_t *ppos) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + struct ssif_msg msg; > + unsigned long flags; > + ssize_t ret; > + > + if (count > sizeof(struct ssif_msg)) > + return -EINVAL; > + > + mutex_lock(&ssif_bmc->file_mutex); > + > + ret = copy_from_user(&msg, buf, count); > + if (ret) > + goto out; > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (count >= ssif_msg_len(&ssif_bmc->response)) > + memcpy(&ssif_bmc->response, &msg, count); > + else > + ret = -EINVAL; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + if (ret) > + goto out; > + > + ret = send_ssif_bmc_response(ssif_bmc, file->f_flags & O_NONBLOCK); > + if (!ret && ssif_bmc->set_ssif_bmc_status) > + ssif_bmc->set_ssif_bmc_status(ssif_bmc, SSIF_BMC_READY); > +out: > + mutex_unlock(&ssif_bmc->file_mutex); > + > + return (ret < 0) ? ret : count; > +} > + > +static long ssif_bmc_ioctl(struct file *file, unsigned int cmd, unsigned long param) > +{ > + return 0; > +} > + > +static unsigned int ssif_bmc_poll(struct file *file, poll_table *wait) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + unsigned int mask = 0; > + > + mutex_lock(&ssif_bmc->file_mutex); > + poll_wait(file, &ssif_bmc->wait_queue, wait); > + > + /* > + * The request message is now available so userspace application can > + * get the request > + */ > + if (ssif_bmc->request_available) > + mask |= POLLIN; > + > + mutex_unlock(&ssif_bmc->file_mutex); > + return mask; > +} > + > +/* > + * System calls to device interface for user apps > + */ > +static const struct file_operations ssif_bmc_fops = { > + .owner = THIS_MODULE, > + .read = ssif_bmc_read, > + .write = ssif_bmc_write, > + .poll = ssif_bmc_poll, > + .unlocked_ioctl = ssif_bmc_ioctl, > +}; > + > +/* Called with ssif_bmc->lock held. */ > +static int handle_request(struct ssif_bmc_ctx *ssif_bmc) > +{ > + if (ssif_bmc->set_ssif_bmc_status) > + ssif_bmc->set_ssif_bmc_status(ssif_bmc, SSIF_BMC_BUSY); > + > + /* Request message is available to process */ > + ssif_bmc->request_available = true; > + /* > + * This is the new READ request. > + * Clear the response buffer of the previous transaction > + */ > + memset(&ssif_bmc->response, 0, sizeof(struct ssif_msg)); > + wake_up_all(&ssif_bmc->wait_queue); > + return 0; > +} > + > +/* Called with ssif_bmc->lock held. */ > +static int complete_response(struct ssif_bmc_ctx *ssif_bmc) > +{ > + /* Invalidate response in buffer to denote it having been sent. */ > + ssif_bmc->response.len = 0; > + ssif_bmc->response_in_progress = false; > + ssif_bmc->nbytes_processed = 0; > + ssif_bmc->remain_len = 0; > + memset(&ssif_bmc->response_buf, 0, MAX_PAYLOAD_PER_TRANSACTION); > + wake_up_all(&ssif_bmc->wait_queue); > + return 0; > +} > + > +static void set_multipart_response_buffer(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 response_len = 0; > + int idx = 0; > + u8 data_len; > + > + data_len = ssif_bmc->response.len; > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_MULTIPART_READ_START: > + /* > + * Read Start length is 32 bytes. > + * Read Start transfer first 30 bytes of IPMI response > + * and 2 special code 0x00, 0x01. > + */ > + *val = MAX_PAYLOAD_PER_TRANSACTION; > + ssif_bmc->remain_len = data_len - MAX_IPMI_DATA_PER_START_TRANSACTION; > + ssif_bmc->block_num = 0; > + > + ssif_bmc->response_buf[idx++] = 0x00; /* Start Flag */ > + ssif_bmc->response_buf[idx++] = 0x01; /* Start Flag */ > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.netfn_lun; > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.cmd; > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.payload[0]; > + > + response_len = MAX_PAYLOAD_PER_TRANSACTION - idx; > + > + memcpy(&ssif_bmc->response_buf[idx], &ssif_bmc->response.payload[1], > + response_len); > + break; > + > + case SSIF_IPMI_MULTIPART_READ_MIDDLE: > + /* > + * IPMI READ Middle or READ End messages can carry up to 31 bytes > + * IPMI data plus block number byte. > + */ > + if (ssif_bmc->remain_len < MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION) { > + /* > + * This is READ End message > + * Return length is the remaining response data length > + * plus block number > + * Block number 0xFF is to indicate this is last message > + * > + * Return length is: remain response plus block number > + */ > + *val = ssif_bmc->remain_len + 1; > + ssif_bmc->block_num = 0xFF; > + ssif_bmc->response_buf[idx++] = ssif_bmc->block_num; > + response_len = ssif_bmc->remain_len; > + } else { > + /* > + * This is READ Middle message > + * Response length is the maximum SMBUS transfer length > + * Block number byte is incremented > + * Return length is maximum SMBUS transfer length > + */ > + *val = MAX_PAYLOAD_PER_TRANSACTION; > + ssif_bmc->remain_len -= MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION; > + response_len = MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION; > + ssif_bmc->response_buf[idx++] = ssif_bmc->block_num; > + ssif_bmc->block_num++; > + } > + > + memcpy(&ssif_bmc->response_buf[idx], > + ssif_bmc->response.payload + 1 + ssif_bmc->nbytes_processed, > + response_len); > + break; > + > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", ssif_bmc->smbus_cmd); > + break; > + } > + > + ssif_bmc->nbytes_processed += response_len; > +} > + > +static void set_singlepart_response_buffer(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf = (u8 *)&ssif_bmc->response; > + > + /* > + * Do not expect the IPMI response has data length 0. > + * With some I2C SMBus controllers (Aspeed I2C), return 0 for > + * the SMBus Read Request callback might cause bad state for > + * the bus. So return 1 byte length so that master will > + * resend the Read Request because the length of response is > + * less than a normal IPMI response. > + * > + * Otherwise, return the length of IPMI response > + */ > + *val = (buf[ssif_bmc->msg_idx]) ? buf[ssif_bmc->msg_idx] : 0x1; > +} > + > +/* Process the IPMI response that will be read by master */ > +static void handle_read_processed(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf; > + u8 pec_len, addr, len; > + u8 pec = 0; > + > + pec_len = ssif_bmc->pec_support ? 1 : 0; > + /* PEC - Start Read Address */ > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + pec = i2c_smbus_pec(pec, &addr, 1); > + /* PEC - SSIF Command */ > + pec = i2c_smbus_pec(pec, &ssif_bmc->smbus_cmd, 1); > + /* PEC - Restart Write Address */ > + addr = addr | 0x01; > + pec = i2c_smbus_pec(pec, &addr, 1); > + > + if (ssif_bmc->is_singlepart_read) { > + /* Single-part Read processing */ > + buf = (u8 *)&ssif_bmc->response; > + > + if (ssif_bmc->response.len && ssif_bmc->msg_idx < ssif_bmc->response.len) { > + ssif_bmc->msg_idx++; > + *val = buf[ssif_bmc->msg_idx]; > + } else if (ssif_bmc->response.len && > + (ssif_bmc->msg_idx == ssif_bmc->response.len)) { > + ssif_bmc->msg_idx++; > + *val = i2c_smbus_pec(pec, buf, ssif_msg_len(&ssif_bmc->response)); > + } else { > + *val = 0; > + } > + /* Invalidate response buffer to denote it is sent */ > + if (ssif_bmc->msg_idx + 1 >= (ssif_msg_len(&ssif_bmc->response) + pec_len)) > + complete_response(ssif_bmc); > + } else { > + /* Multi-part Read processing */ > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_MULTIPART_READ_START: > + case SSIF_IPMI_MULTIPART_READ_MIDDLE: > + buf = (u8 *)&ssif_bmc->response_buf; > + *val = buf[ssif_bmc->msg_idx]; > + ssif_bmc->msg_idx++; > + break; > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", > + ssif_bmc->smbus_cmd); > + break; > + } > + len = (ssif_bmc->block_num == 0xFF) ? > + ssif_bmc->remain_len + 1 : MAX_PAYLOAD_PER_TRANSACTION; > + if (ssif_bmc->msg_idx == (len + 1)) { > + pec = i2c_smbus_pec(pec, &len, 1); > + *val = i2c_smbus_pec(pec, ssif_bmc->response_buf, len); > + } > + /* Invalidate response buffer to denote last response is sent */ > + if (ssif_bmc->block_num == 0xFF && > + ssif_bmc->msg_idx > (ssif_bmc->remain_len + pec_len)) { > + complete_response(ssif_bmc); > + } > + } > +} > + > +static void handle_write_received(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf; > + u8 smbus_cmd; > + > + buf = (u8 *)&ssif_bmc->request; > + if (ssif_bmc->msg_idx >= sizeof(struct ssif_msg)) > + return; > + > + smbus_cmd = ssif_bmc->smbus_cmd; > + switch (smbus_cmd) { > + case SSIF_IPMI_SINGLEPART_WRITE: > + /* Single-part write */ > + buf[ssif_bmc->msg_idx - 1] = *val; > + ssif_bmc->msg_idx++; > + > + break; > + case SSIF_IPMI_MULTIPART_WRITE_START: > + /* Reset length to zero */ > + if (ssif_bmc->msg_idx == 1) > + ssif_bmc->request.len = 0; > + > + fallthrough; > + case SSIF_IPMI_MULTIPART_WRITE_MIDDLE: > + case SSIF_IPMI_MULTIPART_WRITE_END: > + /* Multi-part write, 2nd byte received is length */ > + if (ssif_bmc->msg_idx == 1) { > + ssif_bmc->request.len += *val; > + ssif_bmc->recv_len = *val; > + } else { > + buf[ssif_bmc->msg_idx - 1 + > + ssif_bmc->request.len - ssif_bmc->recv_len] = *val; > + } > + > + ssif_bmc->msg_idx++; > + > + break; > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", ssif_bmc->smbus_cmd); > + break; > + } > +} > + > +static bool validate_pec(struct ssif_bmc_ctx *ssif_bmc) > +{ > + u8 rpec = 0, cpec = 0; > + bool ret = true; > + u8 addr, index; > + u8 *buf; > + > + buf = (u8 *)&ssif_bmc->request; > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_SINGLEPART_WRITE: > + if ((ssif_bmc->msg_idx - 1) == ssif_msg_len(&ssif_bmc->request)) { > + /* PEC is not included */ > + ssif_bmc->pec_support = false; > + return true; > + } > + > + if ((ssif_bmc->msg_idx - 1) != (ssif_msg_len(&ssif_bmc->request) + 1)) > + goto error; > + > + /* PEC is included */ > + ssif_bmc->pec_support = true; > + rpec = buf[ssif_bmc->msg_idx - 2]; > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + cpec = i2c_smbus_pec(cpec, &addr, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->smbus_cmd, 1); > + cpec = i2c_smbus_pec(cpec, buf, ssif_msg_len(&ssif_bmc->request)); > + if (rpec != cpec) { > + pr_err("Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); > + ret = false; > + } > + > + break; > + case SSIF_IPMI_MULTIPART_WRITE_START: > + case SSIF_IPMI_MULTIPART_WRITE_MIDDLE: > + case SSIF_IPMI_MULTIPART_WRITE_END: > + index = ssif_bmc->request.len - ssif_bmc->recv_len; > + if ((ssif_bmc->msg_idx - 1 + index) == ssif_msg_len(&ssif_bmc->request)) { > + /* PEC is not included */ > + ssif_bmc->pec_support = false; > + return true; > + } > + > + if ((ssif_bmc->msg_idx - 1 + index) != (ssif_msg_len(&ssif_bmc->request) + 1)) > + goto error; > + > + /* PEC is included */ > + ssif_bmc->pec_support = true; > + rpec = buf[ssif_bmc->msg_idx - 2 + index]; > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + cpec = i2c_smbus_pec(cpec, &addr, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->smbus_cmd, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->recv_len, 1); > + /* As SMBus specification does not allow the length > + * (byte count) in the Write-Block protocol to be zero. > + * Therefore, it is illegal to have the last Middle > + * transaction in the sequence carry 32-bytes and have > + * a length of ‘0’ in the End transaction. > + * But some users may try to use this way and we should > + * prevent ssif_bmc driver broken in this case. > + */ > + if (ssif_bmc->recv_len != 0) > + cpec = i2c_smbus_pec(cpec, buf + 1 + index, ssif_bmc->recv_len); > + > + if (rpec != cpec) { > + pr_err("Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); > + ret = false; > + } > + > + break; > + default: > + break; > + } > + > + return ret; > +error: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected length received %d\n", ssif_msg_len(&ssif_bmc->request)); > + > + return false; > +} > + > +static void complete_write_received(struct ssif_bmc_ctx *ssif_bmc) > +{ > + u8 cmd = ssif_bmc->smbus_cmd; > + > + /* A BMC that receives an invalid PEC shall drop the data for the write > + * transaction and any further transactions (read or write) until > + * the next valid read or write Start transaction is received > + */ > + if (!validate_pec(ssif_bmc)) { > + pr_err("Received invalid PEC\n"); > + return; > + } > + > + if (cmd == SSIF_IPMI_SINGLEPART_WRITE || cmd == SSIF_IPMI_MULTIPART_WRITE_END) > + handle_request(ssif_bmc); > +} > + > +/* > + * Callback function to handle I2C slave events > + */ > +static int ssif_bmc_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) > +{ > + struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client); > + > + spin_lock(&ssif_bmc->lock); > + > + /* I2C Event Handler: > + * I2C_SLAVE_READ_REQUESTED 0x0 > + * I2C_SLAVE_WRITE_REQUESTED 0x1 > + * I2C_SLAVE_READ_PROCESSED 0x2 > + * I2C_SLAVE_WRITE_RECEIVED 0x3 > + * I2C_SLAVE_STOP 0x4 > + */ > + switch (event) { > + case I2C_SLAVE_READ_REQUESTED: > + ssif_bmc->msg_idx = 0; > + if (ssif_bmc->is_singlepart_read) > + set_singlepart_response_buffer(ssif_bmc, val); > + else > + set_multipart_response_buffer(ssif_bmc, val); > + break; > + > + case I2C_SLAVE_WRITE_REQUESTED: > + ssif_bmc->msg_idx = 0; > + break; > + > + case I2C_SLAVE_READ_PROCESSED: > + handle_read_processed(ssif_bmc, val); > + break; > + > + case I2C_SLAVE_WRITE_RECEIVED: > + /* > + * First byte is SMBUS command, not a part of SSIF message. > + * SSIF request buffer starts with msg_idx 1 for the first > + * buffer byte. > + */ > + if (ssif_bmc->msg_idx == 0) { > + /* SMBUS command can vary (single or multi-part) */ > + ssif_bmc->smbus_cmd = *val; > + ssif_bmc->msg_idx++; > + } else { > + handle_write_received(ssif_bmc, val); > + } > + > + break; > + > + case I2C_SLAVE_STOP: > + /* > + * PEC byte is appended at the end of each transaction. > + * Detect PEC is support or not after receiving write request > + * completely. > + */ > + if (ssif_bmc->last_event == I2C_SLAVE_WRITE_RECEIVED) > + complete_write_received(ssif_bmc); > + /* Reset message index */ > + ssif_bmc->msg_idx = 0; > + break; > + > + default: > + break; > + } > + ssif_bmc->last_event = event; > + spin_unlock(&ssif_bmc->lock); > + > + return 0; > +} > + > +struct ssif_bmc_ctx *ssif_bmc_alloc(struct i2c_client *client, int sizeof_priv) > +{ > + struct ssif_bmc_ctx *ssif_bmc; > + int ret; > + > + ssif_bmc = devm_kzalloc(&client->dev, sizeof(*ssif_bmc) + sizeof_priv, GFP_KERNEL); > + if (!ssif_bmc) > + return ERR_PTR(-ENOMEM); > + > + spin_lock_init(&ssif_bmc->lock); > + > + init_waitqueue_head(&ssif_bmc->wait_queue); > + ssif_bmc->request_available = false; > + ssif_bmc->response_in_progress = false; > + > + mutex_init(&ssif_bmc->file_mutex); > + > + /* Register misc device interface */ > + ssif_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; > + ssif_bmc->miscdev.name = DEVICE_NAME; > + ssif_bmc->miscdev.fops = &ssif_bmc_fops; > + ssif_bmc->miscdev.parent = &client->dev; > + ret = misc_register(&ssif_bmc->miscdev); > + if (ret) > + goto out; > + > + ssif_bmc->client = client; > + ssif_bmc->client->flags |= I2C_CLIENT_SLAVE; > + > + /* Register I2C slave */ > + i2c_set_clientdata(client, ssif_bmc); > + ret = i2c_slave_register(client, ssif_bmc_cb); > + if (ret) { > + misc_deregister(&ssif_bmc->miscdev); > + goto out; > + } > + > + return ssif_bmc; > + > +out: > + devm_kfree(&client->dev, ssif_bmc); > + return ERR_PTR(ret); > +} > +EXPORT_SYMBOL(ssif_bmc_alloc); > + > +MODULE_AUTHOR("Chuong Tran "); > +MODULE_AUTHOR("Quan Nguyen "); > +MODULE_DESCRIPTION("Linux device driver of the BMC IPMI SSIF interface."); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/char/ipmi/ssif_bmc.h b/drivers/char/ipmi/ssif_bmc.h > new file mode 100644 > index 000000000000..a2ee090572db > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc.h > @@ -0,0 +1,92 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * The driver for BMC side of SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > +#ifndef __SSIF_BMC_H__ > +#define __SSIF_BMC_H__ > + > +#define DEVICE_NAME "ipmi-ssif-host" > + > +#define GET_8BIT_ADDR(addr_7bit) (((addr_7bit) << 1) & 0xff) > + > +#define MSG_PAYLOAD_LEN_MAX 252 > + > +/* A standard SMBus Transaction is limited to 32 data bytes */ > +#define MAX_PAYLOAD_PER_TRANSACTION 32 > + > +#define MAX_IPMI_DATA_PER_START_TRANSACTION 30 > +#define MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION 31 > + > +#define SSIF_IPMI_SINGLEPART_WRITE 0x2 > +#define SSIF_IPMI_SINGLEPART_READ 0x3 > +#define SSIF_IPMI_MULTIPART_WRITE_START 0x6 > +#define SSIF_IPMI_MULTIPART_WRITE_MIDDLE 0x7 > +#define SSIF_IPMI_MULTIPART_WRITE_END 0x8 > +#define SSIF_IPMI_MULTIPART_READ_START 0x3 > +#define SSIF_IPMI_MULTIPART_READ_MIDDLE 0x9 > + > +struct ssif_msg { > + u8 len; > + u8 netfn_lun; > + u8 cmd; > + u8 payload[MSG_PAYLOAD_LEN_MAX]; > +} __packed; > + > +static inline u32 ssif_msg_len(struct ssif_msg *ssif_msg) > +{ > + return ssif_msg->len + 1; > +} > + > +#define SSIF_BMC_BUSY 0x01 > +#define SSIF_BMC_READY 0x02 > + > +struct ssif_bmc_ctx { > + struct i2c_client *client; > + struct miscdevice miscdev; > + u8 smbus_cmd; > + struct ssif_msg request; > + bool request_available; > + struct ssif_msg response; > + bool response_in_progress; > + /* Response buffer for Multi-part Read Transaction */ > + u8 response_buf[MAX_PAYLOAD_PER_TRANSACTION]; > + /* Flag to identify a Multi-part Read Transaction */ > + bool is_singlepart_read; > + u8 nbytes_processed; > + u8 remain_len; > + u8 recv_len; > + /* Block Number of a Multi-part Read Transaction */ > + u8 block_num; > + size_t msg_idx; > + enum i2c_slave_event last_event; > + bool pec_support; > + spinlock_t lock; > + wait_queue_head_t wait_queue; > + struct mutex file_mutex; > + void (*set_ssif_bmc_status)(struct ssif_bmc_ctx *ssif_bmc, unsigned int flags); > + void *priv; > +}; > + > +static inline struct ssif_bmc_ctx *to_ssif_bmc(struct file *file) > +{ > + return container_of(file->private_data, struct ssif_bmc_ctx, miscdev); > +} > + > +struct ssif_bmc_ctx *ssif_bmc_alloc(struct i2c_client *client, int sizeof_priv); > + > +#endif /* __SSIF_BMC_H__ */ > diff --git a/drivers/char/ipmi/ssif_bmc_aspeed.c b/drivers/char/ipmi/ssif_bmc_aspeed.c > new file mode 100644 > index 000000000000..a563fcff5acc > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc_aspeed.c > @@ -0,0 +1,132 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * The driver for BMC side of Aspeed SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "ssif_bmc.h" > + > +struct aspeed_i2c_bus { > + struct i2c_adapter adap; > + struct device *dev; > + void __iomem *base; > + struct reset_control *rst; > + /* Synchronizes I/O mem access to base. */ > + spinlock_t lock; > +}; > + > +#define ASPEED_I2C_INTR_CTRL_REG 0x0c > +#define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7) > +#define ASPEED_I2CD_INTR_RX_DONE BIT(2) > +static void aspeed_i2c_enable_interrupt(struct aspeed_i2c_bus *bus, unsigned long mask) > +{ > + unsigned long current_mask; > + > + current_mask = readl(bus->base + ASPEED_I2C_INTR_CTRL_REG); > + writel(current_mask | mask, bus->base + ASPEED_I2C_INTR_CTRL_REG); > +} > + > +static void aspeed_i2c_disable_interrupt(struct aspeed_i2c_bus *bus, unsigned long mask) > +{ > + unsigned long current_mask; > + > + current_mask = readl(bus->base + ASPEED_I2C_INTR_CTRL_REG); > + writel(current_mask & ~mask, bus->base + ASPEED_I2C_INTR_CTRL_REG); > +} > + > +static void aspeed_set_ssif_bmc_status(struct ssif_bmc_ctx *ssif_bmc, unsigned int status) > +{ > + struct aspeed_i2c_bus *bus; > + unsigned long flags; > + > + bus = (struct aspeed_i2c_bus *)ssif_bmc->priv; > + if (!bus) > + return; > + > + spin_lock_irqsave(&bus->lock, flags); Trying to take this spinlock cannot succeed as its already taken by this point. The command sent over I2C to trigger this is 20 02 0C 2C 02 AE 00 00 00 00 00 00 00 00 00 46 CONFIG_SPINLOCK_DEBUG output below. Obviously this deadlocks the kernel. root@nuviamachine1:~# [ 38.790031] BUG: spinlock recursion on CPU#0, swapper/0/0 [ 38.796085] lock: 0x8114c33c, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0 [ 38.804637] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.30-51e4d5a-dirty-601c30e-00164-g463ecaa957f0 #7 [ 38.815410] Hardware name: Generic DT based system [ 38.820756] Backtrace: [ 38.823502] [<808e9408>] (dump_backtrace) from [<808e9664>] (show_stack+0x20/0x24) [ 38.831955] r7:855362a0 r6:600f0193 r5:00000000 r4:80ca3590 [ 38.838277] [<808e9644>] (show_stack) from [<808f45b4>] (dump_stack+0xa0/0xb4) [ 38.846342] [<808f4514>] (dump_stack) from [<808ea418>] (spin_dump+0x90/0x98) [ 38.854307] r7:855362a0 r6:8114c33c r5:80c10400 r4:8114c33c [ 38.860627] [<808ea388>] (spin_dump) from [<80171044>] (do_raw_spin_lock+0x12c/0x130) [ 38.869365] r5:ffffe000 r4:8114c33c [ 38.873360] [<80170f18>] (do_raw_spin_lock) from [<808fb628>] (_raw_spin_lock_irqsave+0x20/0x28) [ 38.883165] r5:00000001 r4:a00f0193 [ 38.887162] [<808fb608>] (_raw_spin_lock_irqsave) from [<80513648>] (aspeed_set_ssif_bmc_status+0x30/0xbc) [ 38.897937] r5:00000001 r4:8114c040 [ 38.901931] [<80513618>] (aspeed_set_ssif_bmc_status) from [<80512b00>] (ssif_bmc_cb+0x1c4/0x698) [ 38.911835] r7:855362a0 r6:8553606c r5:00000004 r4:85536040 [ 38.918158] [<8051293c>] (ssif_bmc_cb) from [<8067e648>] (aspeed_i2c_slave_irq+0xb8/0x264) [ 38.927386] r10:80c00000 r9:80c0a514 r8:00000010 r7:85545000 r6:00000010 r5:00000010 [ 38.936122] r4:8114c040 [ 38.938952] [<8067e590>] (aspeed_i2c_slave_irq) from [<8067ed68>] (aspeed_i2c_bus_irq+0xd0/0x154) [ 38.948855] r7:8114c33c r6:00000010 r5:811e106c r4:8114c040 [ 38.955175] [<8067ec98>] (aspeed_i2c_bus_irq) from [<8017ae3c>] (__handle_irq_event_percpu+0x68/0x204) [ 38.965568] r10:80c00000 r9:80c0a514 r8:00000030 r7:80c01e20 r6:00000000 r5:811e106c [ 38.974305] r4:855468c0 r3:8067ec98 [ 38.978299] [<8017add4>] (__handle_irq_event_percpu) from [<8017b018>] (handle_irq_event_percpu+0x40/0xa0) [ 38.989077] r10:10c5387d r9:80c00000 r8:81042800 r7:00000000 r6:811e106c r5:811e106c [ 38.997814] r4:811e1000 [ 39.000644] [<8017afd8>] (handle_irq_event_percpu) from [<8017b0c0>] (handle_irq_event+0x48/0x6c) [ 39.010546] r5:811e106c r4:811e1000 [ 39.014539] [<8017b078>] (handle_irq_event) from [<80180030>] (handle_fasteoi_irq+0xc8/0x170) [ 39.024056] r7:00000000 r6:80c0ac14 r5:811e106c r4:811e1000 [ 39.030376] [<8017ff68>] (handle_fasteoi_irq) from [<8017a428>] (generic_handle_irq+0x40/0x54) [ 39.039989] r7:00000000 r6:00000001 r5:00000000 r4:80b6c80c [ 39.046312] [<8017a3e8>] (generic_handle_irq) from [<8017a4a8>] (__handle_domain_irq+0x6c/0xc0) [ 39.056028] [<8017a43c>] (__handle_domain_irq) from [<8010134c>] (gic_handle_irq+0x7c/0x90) [ 39.065353] r9:80c00000 r8:bf80200c r7:80b6bdcc r6:bf802000 r5:80c01ee0 r4:80c0ac14 [ 39.073998] [<801012d0>] (gic_handle_irq) from [<80100b0c>] (__irq_svc+0x6c/0x90) [ 39.082340] Exception stack(0x80c01ee0 to 0x80c01f28) [ 39.087981] 1ee0: 00000000 00009a14 bd7dc484 8011a740 80c00000 00000000 80c0a514 80c0a550 [ 39.097111] 1f00: 80ca7f5b 80a0ea58 10c5387d 80c01f3c 80c01f40 80c01f30 8010907c 80109080 [ 39.106237] 1f20: 600f0013 ffffffff [ 39.110130] r9:80c00000 r8:80ca7f5b r7:80c01f14 r6:ffffffff r5:600f0013 r4:80109080 [ 39.118773] [<80109038>] (arch_cpu_idle) from [<808fb4c8>] (default_idle_call+0x38/0x108) [ 39.127907] [<808fb490>] (default_idle_call) from [<80156128>] (do_idle+0xe4/0x150) [ 39.136457] [<80156044>] (do_idle) from [<80156478>] (cpu_startup_entry+0x28/0x2c) [ 39.144908] r9:8ffff564 r8:80b3ba6c r7:00000000 r6:80cc7000 r5:00000001 r4:000000d8 [ 39.153545] [<80156450>] (cpu_startup_entry) from [<808f4f10>] (rest_init+0xbc/0xc4) [ 39.162192] [<808f4e54>] (rest_init) from [<80b00c94>] (arch_call_rest_init+0x18/0x1c) [ 39.171027] r5:00000001 r4:80cc7040 [ 39.175017] [<80b00c7c>] (arch_call_rest_init) from [<80b0124c>] (start_kernel+0x53c/0x584) [ 39.184330] [<80b00d10>] (start_kernel) from [<00000000>] (0x0) > + > + if (status & SSIF_BMC_BUSY) { > + /* Ignore RX_DONE and SLAVE_MATCH when slave busy processing */ > + aspeed_i2c_disable_interrupt(bus, ASPEED_I2CD_INTR_RX_DONE); > + aspeed_i2c_disable_interrupt(bus, ASPEED_I2CD_INTR_SLAVE_MATCH); > + } else if (status & SSIF_BMC_READY) { > + /* Enable RX_DONE and SLAVE_MATCH when slave ready */ > + aspeed_i2c_enable_interrupt(bus, ASPEED_I2CD_INTR_RX_DONE); > + aspeed_i2c_enable_interrupt(bus, ASPEED_I2CD_INTR_SLAVE_MATCH); > + } > + > + spin_unlock_irqrestore(&bus->lock, flags); > +} > + > +static int ssif_bmc_probe(struct i2c_client *client, const struct i2c_device_id *id) > +{ > + struct ssif_bmc_ctx *ssif_bmc; > + > + ssif_bmc = ssif_bmc_alloc(client, sizeof(struct aspeed_i2c_bus)); > + if (IS_ERR(ssif_bmc)) > + return PTR_ERR(ssif_bmc); > + > + ssif_bmc->priv = i2c_get_adapdata(client->adapter); > + ssif_bmc->set_ssif_bmc_status = aspeed_set_ssif_bmc_status; > + > + return 0; > +} > + > +static int ssif_bmc_remove(struct i2c_client *client) > +{ > + struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client); > + > + i2c_slave_unregister(client); > + misc_deregister(&ssif_bmc->miscdev); > + > + return 0; > +} > + > +static const struct of_device_id ssif_bmc_match[] = { > + { .compatible = "aspeed,ast2500-ssif-bmc" }, > + { }, > +}; > + > +static const struct i2c_device_id ssif_bmc_id[] = { > + { DEVICE_NAME, 0 }, > + { }, > +}; > + > +MODULE_DEVICE_TABLE(i2c, ssif_bmc_id); > + > +static struct i2c_driver ssif_bmc_driver = { > + .driver = { > + .name = DEVICE_NAME, > + .of_match_table = ssif_bmc_match, > + }, > + .probe = ssif_bmc_probe, > + .remove = ssif_bmc_remove, > + .id_table = ssif_bmc_id, > +}; > + > +module_i2c_driver(ssif_bmc_driver); > + > +MODULE_AUTHOR("Chuong Tran "); > +MODULE_AUTHOR("Quan Nguyen "); > +MODULE_DESCRIPTION("Linux device driver of Aspeed BMC IPMI SSIF interface."); > +MODULE_LICENSE("GPL v2"); > -- > 2.28.0 > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9DE8FC433ED for ; Thu, 22 Apr 2021 10:50:37 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 86E1860720 for ; Thu, 22 Apr 2021 10:50:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 86E1860720 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=nuviainc.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=openbmc-bounces+openbmc=archiver.kernel.org@lists.ozlabs.org Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FQvMt4hN5z2yxX for ; Thu, 22 Apr 2021 20:50:34 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nuviainc-com.20150623.gappssmtp.com header.i=@nuviainc-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=qvOTcTVy; dkim-atps=neutral Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nuviainc.com (client-ip=2a00:1450:4864:20::434; helo=mail-wr1-x434.google.com; envelope-from=graeme@nuviainc.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nuviainc-com.20150623.gappssmtp.com header.i=@nuviainc-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=qvOTcTVy; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FQvMM10zPz2yQm for ; Thu, 22 Apr 2021 20:50:05 +1000 (AEST) Received: by mail-wr1-x434.google.com with SMTP id e5so15648583wrg.7 for ; Thu, 22 Apr 2021 03:50:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=qvOTcTVyYlflIk+Jb14S2f2tqpgUBhY30LBrMPd2EGD8cMH5aQ3wDD2CrnH86pGQlA zgQrUvShjT3qtiOTUJM9UY08kgKMi7erf0JfTRODPe7DK5T8KvpzSWuQ7ozbAcoizrEa amiLvOWmp38OX5Z/1Rd9c4qVHoLDlJRRcsVGgKUdNUN5LaSAIVAXZoxFQZ126L1R+2iG 9/842WURmR39JyKqs3CoBhn/yasfCEVJaa9wyj3LnAOJ/19Jw+Nc2uN1QVpjjpdtNtk/ WfBJOQWnOp3C6PbpxVhXSCkTsW6qVrAIKx/ZfpLsvHEfpiyxOtxxfbEmcn3ruMvlzSG9 LcaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=KsVg9djLpXZg3mi8B2r6e3W/wavPNjsgsLfk4XcA5W9zt5h9XbMGQezfz1ploGFJAj ZLE8v8iO1L5TIeQdmyHq2ca7BsoYaWgXJHdNO2z31KIqr0UCFgXX5TlJnos6PCzsl2R5 3zU70RTieFZ14239Z9V8TyaSbeTIb/lu4xwHDuqjSlJceWaM38gMQTH+zjx2xubbZFma HvNXKnuWE8Jk3e7SJvNe+jNmAuWtD3pC1CxBiBjLHlBJY0klFWjHdhyMO7LgvpPhigaE yP4npoAVeoHzKxasRoWLTW6o1BK9iXXzQUDLWoG/OJbO7TtONVAr0mye4N9mJ5mQWVzl Aqug== X-Gm-Message-State: AOAM531ETuWVgCZN1OXOW+97O2TRKyNziV2DdnQkH6bElPMzm6s+Kf9Z VPrWRK/BOQPtNeIi/cWRPCweHg== X-Google-Smtp-Source: ABdhPJyOwo77PTIJ1nQExQ7gKG4p91c+E78LEttfRaxFs5aN9WTMM99HM8dv2PocD/ipvsGg1ZUeBg== X-Received: by 2002:a05:6000:82:: with SMTP id m2mr3316986wrx.139.1619088597324; Thu, 22 Apr 2021 03:49:57 -0700 (PDT) Received: from ggregory-ubuntuvm ([62.3.69.143]) by smtp.gmail.com with ESMTPSA id q5sm2917256wrv.17.2021.04.22.03.49.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Apr 2021 03:49:56 -0700 (PDT) Date: Thu, 22 Apr 2021 11:49:54 +0100 From: Graeme Gregory To: Quan Nguyen Subject: Re: [PATCH v2 2/3] drivers: char: ipmi: Add Aspeed SSIF BMC driver Message-ID: <20210422104954.GB13153@ggregory-ubuntuvm> References: <20210330141029.20412-1-quan@os.amperecomputing.com> <20210330141029.20412-3-quan@os.amperecomputing.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20210330141029.20412-3-quan@os.amperecomputing.com> X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, Corey Minyard , Andrew Jeffery , openbmc@lists.ozlabs.org, "Thang Q . Nguyen" , linux-kernel@vger.kernel.org, Phong Vo , Wolfram Sang , Rob Herring , Philipp Zabel , openipmi-developer@lists.sourceforge.net, Open Source Submission , linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org Errors-To: openbmc-bounces+openbmc=archiver.kernel.org@lists.ozlabs.org Sender: "openbmc" On Tue, Mar 30, 2021 at 09:10:28PM +0700, Quan Nguyen wrote: > The SMBus system interface (SSIF) IPMI BMC driver can be used to perform > in-band IPMI communication with their host in management (BMC) side. > > This commits adds support specifically for Aspeed AST2500 which commonly > used as Board Management Controllers. > > Signed-off-by: Quan Nguyen > --- > drivers/char/ipmi/Kconfig | 22 + > drivers/char/ipmi/Makefile | 2 + > drivers/char/ipmi/ssif_bmc.c | 645 ++++++++++++++++++++++++++++ > drivers/char/ipmi/ssif_bmc.h | 92 ++++ > drivers/char/ipmi/ssif_bmc_aspeed.c | 132 ++++++ > 5 files changed, 893 insertions(+) > create mode 100644 drivers/char/ipmi/ssif_bmc.c > create mode 100644 drivers/char/ipmi/ssif_bmc.h > create mode 100644 drivers/char/ipmi/ssif_bmc_aspeed.c > > diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig > index 07847d9a459a..45be57023577 100644 > --- a/drivers/char/ipmi/Kconfig > +++ b/drivers/char/ipmi/Kconfig > @@ -133,6 +133,28 @@ config ASPEED_BT_IPMI_BMC > found on Aspeed SOCs (AST2400 and AST2500). The driver > implements the BMC side of the BT interface. > > +config SSIF_IPMI_BMC > + tristate "SSIF IPMI BMC driver" > + select I2C > + select I2C_SLAVE > + help > + This enables the IPMI SMBus system interface (SSIF) at the > + management (BMC) side. > + > + The driver implements the BMC side of the SMBus system > + interface (SSIF). > + > +config ASPEED_SSIF_IPMI_BMC > + depends on ARCH_ASPEED || COMPILE_TEST > + select SSIF_IPMI_BMC > + tristate "Aspeed SSIF IPMI BMC driver" > + help > + Provides a driver for the SSIF IPMI interface found on > + Aspeed AST2500 SoC. > + > + The driver implements the BMC side of the SMBus system > + interface (SSIF), specific for Aspeed AST2500 SoC. > + > config IPMB_DEVICE_INTERFACE > tristate 'IPMB Interface handler' > depends on I2C > diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile > index 0822adc2ec41..05b993f7335b 100644 > --- a/drivers/char/ipmi/Makefile > +++ b/drivers/char/ipmi/Makefile > @@ -27,3 +27,5 @@ obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o > obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o > obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o > obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o > +obj-$(CONFIG_SSIF_IPMI_BMC) += ssif_bmc.o > +obj-$(CONFIG_ASPEED_SSIF_IPMI_BMC) += ssif_bmc_aspeed.o > diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c > new file mode 100644 > index 000000000000..ae6e8750c795 > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc.c > @@ -0,0 +1,645 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * The driver for BMC side of SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "ssif_bmc.h" > + > +/* > + * Call in WRITE context > + */ > +static int send_ssif_bmc_response(struct ssif_bmc_ctx *ssif_bmc, bool non_blocking) > +{ > + unsigned long flags; > + int ret; > + > + if (!non_blocking) { > +retry: > + ret = wait_event_interruptible(ssif_bmc->wait_queue, > + !ssif_bmc->response_in_progress); > + if (ret) > + return ret; > + } > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (ssif_bmc->response_in_progress) { > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + if (non_blocking) > + return -EAGAIN; > + > + goto retry; > + } > + > + /* > + * Check the response data length from userspace to determine the type > + * of the response message whether it is single-part or multi-part. > + */ > + ssif_bmc->is_singlepart_read = > + (ssif_msg_len(&ssif_bmc->response) <= (MAX_PAYLOAD_PER_TRANSACTION + 1)) ? > + true : false; /* 1: byte of length */ > + > + ssif_bmc->response_in_progress = true; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + return 0; > +} > + > +/* > + * Call in READ context > + */ > +static int receive_ssif_bmc_request(struct ssif_bmc_ctx *ssif_bmc, bool non_blocking) > +{ > + unsigned long flags; > + int ret; > + > + if (!non_blocking) { > +retry: > + ret = wait_event_interruptible(ssif_bmc->wait_queue, > + ssif_bmc->request_available); > + if (ret) > + return ret; > + } > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (!ssif_bmc->request_available) { > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + if (non_blocking) > + return -EAGAIN; > + goto retry; > + } > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + return 0; > +} > + > +/* Handle SSIF message that will be sent to user */ > +static ssize_t ssif_bmc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + struct ssif_msg msg; > + unsigned long flags; > + ssize_t ret; > + > + mutex_lock(&ssif_bmc->file_mutex); > + > + ret = receive_ssif_bmc_request(ssif_bmc, file->f_flags & O_NONBLOCK); > + if (ret < 0) > + goto out; > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + count = min_t(ssize_t, count, ssif_msg_len(&ssif_bmc->request)); > + memcpy(&msg, &ssif_bmc->request, count); > + ssif_bmc->request_available = false; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + ret = copy_to_user(buf, &msg, count); > +out: > + mutex_unlock(&ssif_bmc->file_mutex); > + > + return (ret < 0) ? ret : count; > +} > + > +/* Handle SSIF message that is written by user */ > +static ssize_t ssif_bmc_write(struct file *file, const char __user *buf, size_t count, > + loff_t *ppos) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + struct ssif_msg msg; > + unsigned long flags; > + ssize_t ret; > + > + if (count > sizeof(struct ssif_msg)) > + return -EINVAL; > + > + mutex_lock(&ssif_bmc->file_mutex); > + > + ret = copy_from_user(&msg, buf, count); > + if (ret) > + goto out; > + > + spin_lock_irqsave(&ssif_bmc->lock, flags); > + if (count >= ssif_msg_len(&ssif_bmc->response)) > + memcpy(&ssif_bmc->response, &msg, count); > + else > + ret = -EINVAL; > + spin_unlock_irqrestore(&ssif_bmc->lock, flags); > + > + if (ret) > + goto out; > + > + ret = send_ssif_bmc_response(ssif_bmc, file->f_flags & O_NONBLOCK); > + if (!ret && ssif_bmc->set_ssif_bmc_status) > + ssif_bmc->set_ssif_bmc_status(ssif_bmc, SSIF_BMC_READY); > +out: > + mutex_unlock(&ssif_bmc->file_mutex); > + > + return (ret < 0) ? ret : count; > +} > + > +static long ssif_bmc_ioctl(struct file *file, unsigned int cmd, unsigned long param) > +{ > + return 0; > +} > + > +static unsigned int ssif_bmc_poll(struct file *file, poll_table *wait) > +{ > + struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file); > + unsigned int mask = 0; > + > + mutex_lock(&ssif_bmc->file_mutex); > + poll_wait(file, &ssif_bmc->wait_queue, wait); > + > + /* > + * The request message is now available so userspace application can > + * get the request > + */ > + if (ssif_bmc->request_available) > + mask |= POLLIN; > + > + mutex_unlock(&ssif_bmc->file_mutex); > + return mask; > +} > + > +/* > + * System calls to device interface for user apps > + */ > +static const struct file_operations ssif_bmc_fops = { > + .owner = THIS_MODULE, > + .read = ssif_bmc_read, > + .write = ssif_bmc_write, > + .poll = ssif_bmc_poll, > + .unlocked_ioctl = ssif_bmc_ioctl, > +}; > + > +/* Called with ssif_bmc->lock held. */ > +static int handle_request(struct ssif_bmc_ctx *ssif_bmc) > +{ > + if (ssif_bmc->set_ssif_bmc_status) > + ssif_bmc->set_ssif_bmc_status(ssif_bmc, SSIF_BMC_BUSY); > + > + /* Request message is available to process */ > + ssif_bmc->request_available = true; > + /* > + * This is the new READ request. > + * Clear the response buffer of the previous transaction > + */ > + memset(&ssif_bmc->response, 0, sizeof(struct ssif_msg)); > + wake_up_all(&ssif_bmc->wait_queue); > + return 0; > +} > + > +/* Called with ssif_bmc->lock held. */ > +static int complete_response(struct ssif_bmc_ctx *ssif_bmc) > +{ > + /* Invalidate response in buffer to denote it having been sent. */ > + ssif_bmc->response.len = 0; > + ssif_bmc->response_in_progress = false; > + ssif_bmc->nbytes_processed = 0; > + ssif_bmc->remain_len = 0; > + memset(&ssif_bmc->response_buf, 0, MAX_PAYLOAD_PER_TRANSACTION); > + wake_up_all(&ssif_bmc->wait_queue); > + return 0; > +} > + > +static void set_multipart_response_buffer(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 response_len = 0; > + int idx = 0; > + u8 data_len; > + > + data_len = ssif_bmc->response.len; > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_MULTIPART_READ_START: > + /* > + * Read Start length is 32 bytes. > + * Read Start transfer first 30 bytes of IPMI response > + * and 2 special code 0x00, 0x01. > + */ > + *val = MAX_PAYLOAD_PER_TRANSACTION; > + ssif_bmc->remain_len = data_len - MAX_IPMI_DATA_PER_START_TRANSACTION; > + ssif_bmc->block_num = 0; > + > + ssif_bmc->response_buf[idx++] = 0x00; /* Start Flag */ > + ssif_bmc->response_buf[idx++] = 0x01; /* Start Flag */ > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.netfn_lun; > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.cmd; > + ssif_bmc->response_buf[idx++] = ssif_bmc->response.payload[0]; > + > + response_len = MAX_PAYLOAD_PER_TRANSACTION - idx; > + > + memcpy(&ssif_bmc->response_buf[idx], &ssif_bmc->response.payload[1], > + response_len); > + break; > + > + case SSIF_IPMI_MULTIPART_READ_MIDDLE: > + /* > + * IPMI READ Middle or READ End messages can carry up to 31 bytes > + * IPMI data plus block number byte. > + */ > + if (ssif_bmc->remain_len < MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION) { > + /* > + * This is READ End message > + * Return length is the remaining response data length > + * plus block number > + * Block number 0xFF is to indicate this is last message > + * > + * Return length is: remain response plus block number > + */ > + *val = ssif_bmc->remain_len + 1; > + ssif_bmc->block_num = 0xFF; > + ssif_bmc->response_buf[idx++] = ssif_bmc->block_num; > + response_len = ssif_bmc->remain_len; > + } else { > + /* > + * This is READ Middle message > + * Response length is the maximum SMBUS transfer length > + * Block number byte is incremented > + * Return length is maximum SMBUS transfer length > + */ > + *val = MAX_PAYLOAD_PER_TRANSACTION; > + ssif_bmc->remain_len -= MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION; > + response_len = MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION; > + ssif_bmc->response_buf[idx++] = ssif_bmc->block_num; > + ssif_bmc->block_num++; > + } > + > + memcpy(&ssif_bmc->response_buf[idx], > + ssif_bmc->response.payload + 1 + ssif_bmc->nbytes_processed, > + response_len); > + break; > + > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", ssif_bmc->smbus_cmd); > + break; > + } > + > + ssif_bmc->nbytes_processed += response_len; > +} > + > +static void set_singlepart_response_buffer(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf = (u8 *)&ssif_bmc->response; > + > + /* > + * Do not expect the IPMI response has data length 0. > + * With some I2C SMBus controllers (Aspeed I2C), return 0 for > + * the SMBus Read Request callback might cause bad state for > + * the bus. So return 1 byte length so that master will > + * resend the Read Request because the length of response is > + * less than a normal IPMI response. > + * > + * Otherwise, return the length of IPMI response > + */ > + *val = (buf[ssif_bmc->msg_idx]) ? buf[ssif_bmc->msg_idx] : 0x1; > +} > + > +/* Process the IPMI response that will be read by master */ > +static void handle_read_processed(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf; > + u8 pec_len, addr, len; > + u8 pec = 0; > + > + pec_len = ssif_bmc->pec_support ? 1 : 0; > + /* PEC - Start Read Address */ > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + pec = i2c_smbus_pec(pec, &addr, 1); > + /* PEC - SSIF Command */ > + pec = i2c_smbus_pec(pec, &ssif_bmc->smbus_cmd, 1); > + /* PEC - Restart Write Address */ > + addr = addr | 0x01; > + pec = i2c_smbus_pec(pec, &addr, 1); > + > + if (ssif_bmc->is_singlepart_read) { > + /* Single-part Read processing */ > + buf = (u8 *)&ssif_bmc->response; > + > + if (ssif_bmc->response.len && ssif_bmc->msg_idx < ssif_bmc->response.len) { > + ssif_bmc->msg_idx++; > + *val = buf[ssif_bmc->msg_idx]; > + } else if (ssif_bmc->response.len && > + (ssif_bmc->msg_idx == ssif_bmc->response.len)) { > + ssif_bmc->msg_idx++; > + *val = i2c_smbus_pec(pec, buf, ssif_msg_len(&ssif_bmc->response)); > + } else { > + *val = 0; > + } > + /* Invalidate response buffer to denote it is sent */ > + if (ssif_bmc->msg_idx + 1 >= (ssif_msg_len(&ssif_bmc->response) + pec_len)) > + complete_response(ssif_bmc); > + } else { > + /* Multi-part Read processing */ > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_MULTIPART_READ_START: > + case SSIF_IPMI_MULTIPART_READ_MIDDLE: > + buf = (u8 *)&ssif_bmc->response_buf; > + *val = buf[ssif_bmc->msg_idx]; > + ssif_bmc->msg_idx++; > + break; > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", > + ssif_bmc->smbus_cmd); > + break; > + } > + len = (ssif_bmc->block_num == 0xFF) ? > + ssif_bmc->remain_len + 1 : MAX_PAYLOAD_PER_TRANSACTION; > + if (ssif_bmc->msg_idx == (len + 1)) { > + pec = i2c_smbus_pec(pec, &len, 1); > + *val = i2c_smbus_pec(pec, ssif_bmc->response_buf, len); > + } > + /* Invalidate response buffer to denote last response is sent */ > + if (ssif_bmc->block_num == 0xFF && > + ssif_bmc->msg_idx > (ssif_bmc->remain_len + pec_len)) { > + complete_response(ssif_bmc); > + } > + } > +} > + > +static void handle_write_received(struct ssif_bmc_ctx *ssif_bmc, u8 *val) > +{ > + u8 *buf; > + u8 smbus_cmd; > + > + buf = (u8 *)&ssif_bmc->request; > + if (ssif_bmc->msg_idx >= sizeof(struct ssif_msg)) > + return; > + > + smbus_cmd = ssif_bmc->smbus_cmd; > + switch (smbus_cmd) { > + case SSIF_IPMI_SINGLEPART_WRITE: > + /* Single-part write */ > + buf[ssif_bmc->msg_idx - 1] = *val; > + ssif_bmc->msg_idx++; > + > + break; > + case SSIF_IPMI_MULTIPART_WRITE_START: > + /* Reset length to zero */ > + if (ssif_bmc->msg_idx == 1) > + ssif_bmc->request.len = 0; > + > + fallthrough; > + case SSIF_IPMI_MULTIPART_WRITE_MIDDLE: > + case SSIF_IPMI_MULTIPART_WRITE_END: > + /* Multi-part write, 2nd byte received is length */ > + if (ssif_bmc->msg_idx == 1) { > + ssif_bmc->request.len += *val; > + ssif_bmc->recv_len = *val; > + } else { > + buf[ssif_bmc->msg_idx - 1 + > + ssif_bmc->request.len - ssif_bmc->recv_len] = *val; > + } > + > + ssif_bmc->msg_idx++; > + > + break; > + default: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected SMBus command received 0x%x\n", ssif_bmc->smbus_cmd); > + break; > + } > +} > + > +static bool validate_pec(struct ssif_bmc_ctx *ssif_bmc) > +{ > + u8 rpec = 0, cpec = 0; > + bool ret = true; > + u8 addr, index; > + u8 *buf; > + > + buf = (u8 *)&ssif_bmc->request; > + switch (ssif_bmc->smbus_cmd) { > + case SSIF_IPMI_SINGLEPART_WRITE: > + if ((ssif_bmc->msg_idx - 1) == ssif_msg_len(&ssif_bmc->request)) { > + /* PEC is not included */ > + ssif_bmc->pec_support = false; > + return true; > + } > + > + if ((ssif_bmc->msg_idx - 1) != (ssif_msg_len(&ssif_bmc->request) + 1)) > + goto error; > + > + /* PEC is included */ > + ssif_bmc->pec_support = true; > + rpec = buf[ssif_bmc->msg_idx - 2]; > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + cpec = i2c_smbus_pec(cpec, &addr, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->smbus_cmd, 1); > + cpec = i2c_smbus_pec(cpec, buf, ssif_msg_len(&ssif_bmc->request)); > + if (rpec != cpec) { > + pr_err("Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); > + ret = false; > + } > + > + break; > + case SSIF_IPMI_MULTIPART_WRITE_START: > + case SSIF_IPMI_MULTIPART_WRITE_MIDDLE: > + case SSIF_IPMI_MULTIPART_WRITE_END: > + index = ssif_bmc->request.len - ssif_bmc->recv_len; > + if ((ssif_bmc->msg_idx - 1 + index) == ssif_msg_len(&ssif_bmc->request)) { > + /* PEC is not included */ > + ssif_bmc->pec_support = false; > + return true; > + } > + > + if ((ssif_bmc->msg_idx - 1 + index) != (ssif_msg_len(&ssif_bmc->request) + 1)) > + goto error; > + > + /* PEC is included */ > + ssif_bmc->pec_support = true; > + rpec = buf[ssif_bmc->msg_idx - 2 + index]; > + addr = GET_8BIT_ADDR(ssif_bmc->client->addr); > + cpec = i2c_smbus_pec(cpec, &addr, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->smbus_cmd, 1); > + cpec = i2c_smbus_pec(cpec, &ssif_bmc->recv_len, 1); > + /* As SMBus specification does not allow the length > + * (byte count) in the Write-Block protocol to be zero. > + * Therefore, it is illegal to have the last Middle > + * transaction in the sequence carry 32-bytes and have > + * a length of ‘0’ in the End transaction. > + * But some users may try to use this way and we should > + * prevent ssif_bmc driver broken in this case. > + */ > + if (ssif_bmc->recv_len != 0) > + cpec = i2c_smbus_pec(cpec, buf + 1 + index, ssif_bmc->recv_len); > + > + if (rpec != cpec) { > + pr_err("Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); > + ret = false; > + } > + > + break; > + default: > + break; > + } > + > + return ret; > +error: > + /* Do not expect to go to this case */ > + pr_err("Error: Unexpected length received %d\n", ssif_msg_len(&ssif_bmc->request)); > + > + return false; > +} > + > +static void complete_write_received(struct ssif_bmc_ctx *ssif_bmc) > +{ > + u8 cmd = ssif_bmc->smbus_cmd; > + > + /* A BMC that receives an invalid PEC shall drop the data for the write > + * transaction and any further transactions (read or write) until > + * the next valid read or write Start transaction is received > + */ > + if (!validate_pec(ssif_bmc)) { > + pr_err("Received invalid PEC\n"); > + return; > + } > + > + if (cmd == SSIF_IPMI_SINGLEPART_WRITE || cmd == SSIF_IPMI_MULTIPART_WRITE_END) > + handle_request(ssif_bmc); > +} > + > +/* > + * Callback function to handle I2C slave events > + */ > +static int ssif_bmc_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) > +{ > + struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client); > + > + spin_lock(&ssif_bmc->lock); > + > + /* I2C Event Handler: > + * I2C_SLAVE_READ_REQUESTED 0x0 > + * I2C_SLAVE_WRITE_REQUESTED 0x1 > + * I2C_SLAVE_READ_PROCESSED 0x2 > + * I2C_SLAVE_WRITE_RECEIVED 0x3 > + * I2C_SLAVE_STOP 0x4 > + */ > + switch (event) { > + case I2C_SLAVE_READ_REQUESTED: > + ssif_bmc->msg_idx = 0; > + if (ssif_bmc->is_singlepart_read) > + set_singlepart_response_buffer(ssif_bmc, val); > + else > + set_multipart_response_buffer(ssif_bmc, val); > + break; > + > + case I2C_SLAVE_WRITE_REQUESTED: > + ssif_bmc->msg_idx = 0; > + break; > + > + case I2C_SLAVE_READ_PROCESSED: > + handle_read_processed(ssif_bmc, val); > + break; > + > + case I2C_SLAVE_WRITE_RECEIVED: > + /* > + * First byte is SMBUS command, not a part of SSIF message. > + * SSIF request buffer starts with msg_idx 1 for the first > + * buffer byte. > + */ > + if (ssif_bmc->msg_idx == 0) { > + /* SMBUS command can vary (single or multi-part) */ > + ssif_bmc->smbus_cmd = *val; > + ssif_bmc->msg_idx++; > + } else { > + handle_write_received(ssif_bmc, val); > + } > + > + break; > + > + case I2C_SLAVE_STOP: > + /* > + * PEC byte is appended at the end of each transaction. > + * Detect PEC is support or not after receiving write request > + * completely. > + */ > + if (ssif_bmc->last_event == I2C_SLAVE_WRITE_RECEIVED) > + complete_write_received(ssif_bmc); > + /* Reset message index */ > + ssif_bmc->msg_idx = 0; > + break; > + > + default: > + break; > + } > + ssif_bmc->last_event = event; > + spin_unlock(&ssif_bmc->lock); > + > + return 0; > +} > + > +struct ssif_bmc_ctx *ssif_bmc_alloc(struct i2c_client *client, int sizeof_priv) > +{ > + struct ssif_bmc_ctx *ssif_bmc; > + int ret; > + > + ssif_bmc = devm_kzalloc(&client->dev, sizeof(*ssif_bmc) + sizeof_priv, GFP_KERNEL); > + if (!ssif_bmc) > + return ERR_PTR(-ENOMEM); > + > + spin_lock_init(&ssif_bmc->lock); > + > + init_waitqueue_head(&ssif_bmc->wait_queue); > + ssif_bmc->request_available = false; > + ssif_bmc->response_in_progress = false; > + > + mutex_init(&ssif_bmc->file_mutex); > + > + /* Register misc device interface */ > + ssif_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; > + ssif_bmc->miscdev.name = DEVICE_NAME; > + ssif_bmc->miscdev.fops = &ssif_bmc_fops; > + ssif_bmc->miscdev.parent = &client->dev; > + ret = misc_register(&ssif_bmc->miscdev); > + if (ret) > + goto out; > + > + ssif_bmc->client = client; > + ssif_bmc->client->flags |= I2C_CLIENT_SLAVE; > + > + /* Register I2C slave */ > + i2c_set_clientdata(client, ssif_bmc); > + ret = i2c_slave_register(client, ssif_bmc_cb); > + if (ret) { > + misc_deregister(&ssif_bmc->miscdev); > + goto out; > + } > + > + return ssif_bmc; > + > +out: > + devm_kfree(&client->dev, ssif_bmc); > + return ERR_PTR(ret); > +} > +EXPORT_SYMBOL(ssif_bmc_alloc); > + > +MODULE_AUTHOR("Chuong Tran "); > +MODULE_AUTHOR("Quan Nguyen "); > +MODULE_DESCRIPTION("Linux device driver of the BMC IPMI SSIF interface."); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/char/ipmi/ssif_bmc.h b/drivers/char/ipmi/ssif_bmc.h > new file mode 100644 > index 000000000000..a2ee090572db > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc.h > @@ -0,0 +1,92 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * The driver for BMC side of SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > +#ifndef __SSIF_BMC_H__ > +#define __SSIF_BMC_H__ > + > +#define DEVICE_NAME "ipmi-ssif-host" > + > +#define GET_8BIT_ADDR(addr_7bit) (((addr_7bit) << 1) & 0xff) > + > +#define MSG_PAYLOAD_LEN_MAX 252 > + > +/* A standard SMBus Transaction is limited to 32 data bytes */ > +#define MAX_PAYLOAD_PER_TRANSACTION 32 > + > +#define MAX_IPMI_DATA_PER_START_TRANSACTION 30 > +#define MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION 31 > + > +#define SSIF_IPMI_SINGLEPART_WRITE 0x2 > +#define SSIF_IPMI_SINGLEPART_READ 0x3 > +#define SSIF_IPMI_MULTIPART_WRITE_START 0x6 > +#define SSIF_IPMI_MULTIPART_WRITE_MIDDLE 0x7 > +#define SSIF_IPMI_MULTIPART_WRITE_END 0x8 > +#define SSIF_IPMI_MULTIPART_READ_START 0x3 > +#define SSIF_IPMI_MULTIPART_READ_MIDDLE 0x9 > + > +struct ssif_msg { > + u8 len; > + u8 netfn_lun; > + u8 cmd; > + u8 payload[MSG_PAYLOAD_LEN_MAX]; > +} __packed; > + > +static inline u32 ssif_msg_len(struct ssif_msg *ssif_msg) > +{ > + return ssif_msg->len + 1; > +} > + > +#define SSIF_BMC_BUSY 0x01 > +#define SSIF_BMC_READY 0x02 > + > +struct ssif_bmc_ctx { > + struct i2c_client *client; > + struct miscdevice miscdev; > + u8 smbus_cmd; > + struct ssif_msg request; > + bool request_available; > + struct ssif_msg response; > + bool response_in_progress; > + /* Response buffer for Multi-part Read Transaction */ > + u8 response_buf[MAX_PAYLOAD_PER_TRANSACTION]; > + /* Flag to identify a Multi-part Read Transaction */ > + bool is_singlepart_read; > + u8 nbytes_processed; > + u8 remain_len; > + u8 recv_len; > + /* Block Number of a Multi-part Read Transaction */ > + u8 block_num; > + size_t msg_idx; > + enum i2c_slave_event last_event; > + bool pec_support; > + spinlock_t lock; > + wait_queue_head_t wait_queue; > + struct mutex file_mutex; > + void (*set_ssif_bmc_status)(struct ssif_bmc_ctx *ssif_bmc, unsigned int flags); > + void *priv; > +}; > + > +static inline struct ssif_bmc_ctx *to_ssif_bmc(struct file *file) > +{ > + return container_of(file->private_data, struct ssif_bmc_ctx, miscdev); > +} > + > +struct ssif_bmc_ctx *ssif_bmc_alloc(struct i2c_client *client, int sizeof_priv); > + > +#endif /* __SSIF_BMC_H__ */ > diff --git a/drivers/char/ipmi/ssif_bmc_aspeed.c b/drivers/char/ipmi/ssif_bmc_aspeed.c > new file mode 100644 > index 000000000000..a563fcff5acc > --- /dev/null > +++ b/drivers/char/ipmi/ssif_bmc_aspeed.c > @@ -0,0 +1,132 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * The driver for BMC side of Aspeed SSIF interface > + * > + * Copyright (c) 2021, Ampere Computing LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "ssif_bmc.h" > + > +struct aspeed_i2c_bus { > + struct i2c_adapter adap; > + struct device *dev; > + void __iomem *base; > + struct reset_control *rst; > + /* Synchronizes I/O mem access to base. */ > + spinlock_t lock; > +}; > + > +#define ASPEED_I2C_INTR_CTRL_REG 0x0c > +#define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7) > +#define ASPEED_I2CD_INTR_RX_DONE BIT(2) > +static void aspeed_i2c_enable_interrupt(struct aspeed_i2c_bus *bus, unsigned long mask) > +{ > + unsigned long current_mask; > + > + current_mask = readl(bus->base + ASPEED_I2C_INTR_CTRL_REG); > + writel(current_mask | mask, bus->base + ASPEED_I2C_INTR_CTRL_REG); > +} > + > +static void aspeed_i2c_disable_interrupt(struct aspeed_i2c_bus *bus, unsigned long mask) > +{ > + unsigned long current_mask; > + > + current_mask = readl(bus->base + ASPEED_I2C_INTR_CTRL_REG); > + writel(current_mask & ~mask, bus->base + ASPEED_I2C_INTR_CTRL_REG); > +} > + > +static void aspeed_set_ssif_bmc_status(struct ssif_bmc_ctx *ssif_bmc, unsigned int status) > +{ > + struct aspeed_i2c_bus *bus; > + unsigned long flags; > + > + bus = (struct aspeed_i2c_bus *)ssif_bmc->priv; > + if (!bus) > + return; > + > + spin_lock_irqsave(&bus->lock, flags); Trying to take this spinlock cannot succeed as its already taken by this point. The command sent over I2C to trigger this is 20 02 0C 2C 02 AE 00 00 00 00 00 00 00 00 00 46 CONFIG_SPINLOCK_DEBUG output below. Obviously this deadlocks the kernel. root@nuviamachine1:~# [ 38.790031] BUG: spinlock recursion on CPU#0, swapper/0/0 [ 38.796085] lock: 0x8114c33c, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0 [ 38.804637] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.30-51e4d5a-dirty-601c30e-00164-g463ecaa957f0 #7 [ 38.815410] Hardware name: Generic DT based system [ 38.820756] Backtrace: [ 38.823502] [<808e9408>] (dump_backtrace) from [<808e9664>] (show_stack+0x20/0x24) [ 38.831955] r7:855362a0 r6:600f0193 r5:00000000 r4:80ca3590 [ 38.838277] [<808e9644>] (show_stack) from [<808f45b4>] (dump_stack+0xa0/0xb4) [ 38.846342] [<808f4514>] (dump_stack) from [<808ea418>] (spin_dump+0x90/0x98) [ 38.854307] r7:855362a0 r6:8114c33c r5:80c10400 r4:8114c33c [ 38.860627] [<808ea388>] (spin_dump) from [<80171044>] (do_raw_spin_lock+0x12c/0x130) [ 38.869365] r5:ffffe000 r4:8114c33c [ 38.873360] [<80170f18>] (do_raw_spin_lock) from [<808fb628>] (_raw_spin_lock_irqsave+0x20/0x28) [ 38.883165] r5:00000001 r4:a00f0193 [ 38.887162] [<808fb608>] (_raw_spin_lock_irqsave) from [<80513648>] (aspeed_set_ssif_bmc_status+0x30/0xbc) [ 38.897937] r5:00000001 r4:8114c040 [ 38.901931] [<80513618>] (aspeed_set_ssif_bmc_status) from [<80512b00>] (ssif_bmc_cb+0x1c4/0x698) [ 38.911835] r7:855362a0 r6:8553606c r5:00000004 r4:85536040 [ 38.918158] [<8051293c>] (ssif_bmc_cb) from [<8067e648>] (aspeed_i2c_slave_irq+0xb8/0x264) [ 38.927386] r10:80c00000 r9:80c0a514 r8:00000010 r7:85545000 r6:00000010 r5:00000010 [ 38.936122] r4:8114c040 [ 38.938952] [<8067e590>] (aspeed_i2c_slave_irq) from [<8067ed68>] (aspeed_i2c_bus_irq+0xd0/0x154) [ 38.948855] r7:8114c33c r6:00000010 r5:811e106c r4:8114c040 [ 38.955175] [<8067ec98>] (aspeed_i2c_bus_irq) from [<8017ae3c>] (__handle_irq_event_percpu+0x68/0x204) [ 38.965568] r10:80c00000 r9:80c0a514 r8:00000030 r7:80c01e20 r6:00000000 r5:811e106c [ 38.974305] r4:855468c0 r3:8067ec98 [ 38.978299] [<8017add4>] (__handle_irq_event_percpu) from [<8017b018>] (handle_irq_event_percpu+0x40/0xa0) [ 38.989077] r10:10c5387d r9:80c00000 r8:81042800 r7:00000000 r6:811e106c r5:811e106c [ 38.997814] r4:811e1000 [ 39.000644] [<8017afd8>] (handle_irq_event_percpu) from [<8017b0c0>] (handle_irq_event+0x48/0x6c) [ 39.010546] r5:811e106c r4:811e1000 [ 39.014539] [<8017b078>] (handle_irq_event) from [<80180030>] (handle_fasteoi_irq+0xc8/0x170) [ 39.024056] r7:00000000 r6:80c0ac14 r5:811e106c r4:811e1000 [ 39.030376] [<8017ff68>] (handle_fasteoi_irq) from [<8017a428>] (generic_handle_irq+0x40/0x54) [ 39.039989] r7:00000000 r6:00000001 r5:00000000 r4:80b6c80c [ 39.046312] [<8017a3e8>] (generic_handle_irq) from [<8017a4a8>] (__handle_domain_irq+0x6c/0xc0) [ 39.056028] [<8017a43c>] (__handle_domain_irq) from [<8010134c>] (gic_handle_irq+0x7c/0x90) [ 39.065353] r9:80c00000 r8:bf80200c r7:80b6bdcc r6:bf802000 r5:80c01ee0 r4:80c0ac14 [ 39.073998] [<801012d0>] (gic_handle_irq) from [<80100b0c>] (__irq_svc+0x6c/0x90) [ 39.082340] Exception stack(0x80c01ee0 to 0x80c01f28) [ 39.087981] 1ee0: 00000000 00009a14 bd7dc484 8011a740 80c00000 00000000 80c0a514 80c0a550 [ 39.097111] 1f00: 80ca7f5b 80a0ea58 10c5387d 80c01f3c 80c01f40 80c01f30 8010907c 80109080 [ 39.106237] 1f20: 600f0013 ffffffff [ 39.110130] r9:80c00000 r8:80ca7f5b r7:80c01f14 r6:ffffffff r5:600f0013 r4:80109080 [ 39.118773] [<80109038>] (arch_cpu_idle) from [<808fb4c8>] (default_idle_call+0x38/0x108) [ 39.127907] [<808fb490>] (default_idle_call) from [<80156128>] (do_idle+0xe4/0x150) [ 39.136457] [<80156044>] (do_idle) from [<80156478>] (cpu_startup_entry+0x28/0x2c) [ 39.144908] r9:8ffff564 r8:80b3ba6c r7:00000000 r6:80cc7000 r5:00000001 r4:000000d8 [ 39.153545] [<80156450>] (cpu_startup_entry) from [<808f4f10>] (rest_init+0xbc/0xc4) [ 39.162192] [<808f4e54>] (rest_init) from [<80b00c94>] (arch_call_rest_init+0x18/0x1c) [ 39.171027] r5:00000001 r4:80cc7040 [ 39.175017] [<80b00c7c>] (arch_call_rest_init) from [<80b0124c>] (start_kernel+0x53c/0x584) [ 39.184330] [<80b00d10>] (start_kernel) from [<00000000>] (0x0) > + > + if (status & SSIF_BMC_BUSY) { > + /* Ignore RX_DONE and SLAVE_MATCH when slave busy processing */ > + aspeed_i2c_disable_interrupt(bus, ASPEED_I2CD_INTR_RX_DONE); > + aspeed_i2c_disable_interrupt(bus, ASPEED_I2CD_INTR_SLAVE_MATCH); > + } else if (status & SSIF_BMC_READY) { > + /* Enable RX_DONE and SLAVE_MATCH when slave ready */ > + aspeed_i2c_enable_interrupt(bus, ASPEED_I2CD_INTR_RX_DONE); > + aspeed_i2c_enable_interrupt(bus, ASPEED_I2CD_INTR_SLAVE_MATCH); > + } > + > + spin_unlock_irqrestore(&bus->lock, flags); > +} > + > +static int ssif_bmc_probe(struct i2c_client *client, const struct i2c_device_id *id) > +{ > + struct ssif_bmc_ctx *ssif_bmc; > + > + ssif_bmc = ssif_bmc_alloc(client, sizeof(struct aspeed_i2c_bus)); > + if (IS_ERR(ssif_bmc)) > + return PTR_ERR(ssif_bmc); > + > + ssif_bmc->priv = i2c_get_adapdata(client->adapter); > + ssif_bmc->set_ssif_bmc_status = aspeed_set_ssif_bmc_status; > + > + return 0; > +} > + > +static int ssif_bmc_remove(struct i2c_client *client) > +{ > + struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client); > + > + i2c_slave_unregister(client); > + misc_deregister(&ssif_bmc->miscdev); > + > + return 0; > +} > + > +static const struct of_device_id ssif_bmc_match[] = { > + { .compatible = "aspeed,ast2500-ssif-bmc" }, > + { }, > +}; > + > +static const struct i2c_device_id ssif_bmc_id[] = { > + { DEVICE_NAME, 0 }, > + { }, > +}; > + > +MODULE_DEVICE_TABLE(i2c, ssif_bmc_id); > + > +static struct i2c_driver ssif_bmc_driver = { > + .driver = { > + .name = DEVICE_NAME, > + .of_match_table = ssif_bmc_match, > + }, > + .probe = ssif_bmc_probe, > + .remove = ssif_bmc_remove, > + .id_table = ssif_bmc_id, > +}; > + > +module_i2c_driver(ssif_bmc_driver); > + > +MODULE_AUTHOR("Chuong Tran "); > +MODULE_AUTHOR("Quan Nguyen "); > +MODULE_DESCRIPTION("Linux device driver of Aspeed BMC IPMI SSIF interface."); > +MODULE_LICENSE("GPL v2"); > -- > 2.28.0 > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0ADD5C433ED for ; Thu, 22 Apr 2021 10:52:23 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AD45161428 for ; Thu, 22 Apr 2021 10:52:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AD45161428 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=nuviainc.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References:Message-ID: Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=GBoExCoiroBQuFmnW+62iDNbhz3tFKAwTwuYrUAz4wY=; b=POoa0jqKI5uDWdzqfMCvoI266 rKNvGC5j67JraRXqOalKxBPRTluK4hz5OevACdL4dRluDfFhazNCaPy2szmhmerkVt7JvzBNA95Br B/Kx1G/j8pwvlIYsfErbxPn9IbZBVyIHaIx7u+kpntJBDAsg+S/DffN/F2lvrU+yMNqCGhkg9mUOL C6VKZpwuqTNSpMG5zNFiqFZCsnjcGgzNfz133s/4HFITfDBaVfchl8Z8+6bILR/tphZv/U1AYPfRI FAb3ISK70xCGvbxIhdkWdVrTc49JRNJKBC4lL4kiNcSfLAjQzW2eQJwIMoVjzbuAnc0yt34lGGkiG 2QcttB8Qw==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lZWuO-00GX6l-LH; Thu, 22 Apr 2021 10:50:10 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lZWuL-00GX6V-EZ for linux-arm-kernel@desiato.infradead.org; Thu, 22 Apr 2021 10:50:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=In-Reply-To:Content-Transfer-Encoding :Content-Type:MIME-Version:References:Message-ID:Subject:Cc:To:From:Date: Sender:Reply-To:Content-ID:Content-Description; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=04Ke28G+c8NAkDkTZ8VWcVv/8O vsEndJNvuAcF61ZnyWmOabQbW4nAkASDN1DF0YGnBSWcp04RGXOgFgo5pGpiN18/wQxIHgHXpg/Xf TK5XQb/SZWT1xxFOD8BAT1Z0JOIGPGQjvXwXQcUQMVC6FmvmpzRI7Xm5hLYpIR4/oboUQGZVvzLnW OCgtHUxCGBQw860xW6qyIWeAUispQohDRFWmHv33YuilWDEhvqeLxafb53KpcJeLHojPwJR0Ch0Rg mjCIKc/ysYpPpAHPMPdWs3Vw56mBAxlkvy+eAQk4DSWAjcdWK6Dscg+coAp4lgz8jNwGqnY6NI+7x qZ+ckvNA==; Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lZWuG-00Dal5-6b for linux-arm-kernel@lists.infradead.org; Thu, 22 Apr 2021 10:50:04 +0000 Received: by mail-wr1-x42b.google.com with SMTP id r7so32313352wrm.1 for ; Thu, 22 Apr 2021 03:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=qvOTcTVyYlflIk+Jb14S2f2tqpgUBhY30LBrMPd2EGD8cMH5aQ3wDD2CrnH86pGQlA zgQrUvShjT3qtiOTUJM9UY08kgKMi7erf0JfTRODPe7DK5T8KvpzSWuQ7ozbAcoizrEa amiLvOWmp38OX5Z/1Rd9c4qVHoLDlJRRcsVGgKUdNUN5LaSAIVAXZoxFQZ126L1R+2iG 9/842WURmR39JyKqs3CoBhn/yasfCEVJaa9wyj3LnAOJ/19Jw+Nc2uN1QVpjjpdtNtk/ WfBJOQWnOp3C6PbpxVhXSCkTsW6qVrAIKx/ZfpLsvHEfpiyxOtxxfbEmcn3ruMvlzSG9 LcaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=ll6D7BmbJcbU6CduAeau4wB1M0bbtDXqERKKeEgMh6U=; b=EkxznwXJd+evKaewf6uqMlbncWK+Bjf2szcVbDzwRRTdoz58t8Jy/ESegNRVCN8CxW QrsY6y/qaD4WetG63YI95GshY09q7Tl2z9w1sryV/uSyu8RlShwajj06kOZytrGBRmVl Gub89zQbjziUi3oBYLR6D3qkuzpBthtyEBDujvhJ6O8Woniu80fwW4+wcOZa51BG6O/Q X6VN2agEo9ywv8ZBqZF8WGALxq2HI2Mylb5xcTSt9lDlfiP8KmzI5CLmsWlLmpIzPnar jTdpG2ip47yK4eO0ZiyV3OBR7Lh8uedQxNm6vbH1AZuowQcyK2vHiB6x6KTaug9PJaxb OuHQ== X-Gm-Message-State: AOAM533vr1BiCRKhGbrOtjbOLiPt44OA8WHDFdRxphE06Gdj1RWAEW2D sFwhiOERBZ7SXSZ51MbYSbH/Kw== X-Google-Smtp-Source: ABdhPJyOwo77PTIJ1nQExQ7gKG4p91c+E78LEttfRaxFs5aN9WTMM99HM8dv2PocD/ipvsGg1ZUeBg== X-Received: by 2002:a05:6000:82:: with SMTP id m2mr3316986wrx.139.1619088597324; Thu, 22 Apr 2021 03:49:57 -0700 (PDT) Received: from ggregory-ubuntuvm ([62.3.69.143]) by smtp.gmail.com with ESMTPSA id q5sm2917256wrv.17.2021.04.22.03.49.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Apr 2021 03:49:56 -0700 (PDT) Date: Thu, 22 Apr 2021 11:49:54 +0100 From: Graeme Gregory To: Quan Nguyen Cc: Corey Minyard , Rob Herring , Joel Stanley , Andrew Jeffery , Wolfram Sang , Philipp Zabel , openipmi-developer@lists.sourceforge.net, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, openbmc@lists.ozlabs.org, "Thang Q . Nguyen" , Open Source Submission , Phong Vo Subject: Re: [PATCH v2 2/3] drivers: char: ipmi: Add Aspeed SSIF BMC driver Message-ID: <20210422104954.GB13153@ggregory-ubuntuvm> References: <20210330141029.20412-1-quan@os.amperecomputing.com> <20210330141029.20412-3-quan@os.amperecomputing.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20210330141029.20412-3-quan@os.amperecomputing.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210422_035000_465918_71161546 X-CRM114-Status: GOOD ( 47.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gVHVlLCBNYXIgMzAsIDIwMjEgYXQgMDk6MTA6MjhQTSArMDcwMCwgUXVhbiBOZ3V5ZW4gd3Jv dGU6Cj4gVGhlIFNNQnVzIHN5c3RlbSBpbnRlcmZhY2UgKFNTSUYpIElQTUkgQk1DIGRyaXZlciBj YW4gYmUgdXNlZCB0byBwZXJmb3JtCj4gaW4tYmFuZCBJUE1JIGNvbW11bmljYXRpb24gd2l0aCB0 aGVpciBob3N0IGluIG1hbmFnZW1lbnQgKEJNQykgc2lkZS4KPiAKPiBUaGlzIGNvbW1pdHMgYWRk cyBzdXBwb3J0IHNwZWNpZmljYWxseSBmb3IgQXNwZWVkIEFTVDI1MDAgd2hpY2ggY29tbW9ubHkK PiB1c2VkIGFzIEJvYXJkIE1hbmFnZW1lbnQgQ29udHJvbGxlcnMuCj4gCj4gU2lnbmVkLW9mZi1i eTogUXVhbiBOZ3V5ZW4gPHF1YW5Ab3MuYW1wZXJlY29tcHV0aW5nLmNvbT4KPiAtLS0KPiAgZHJp dmVycy9jaGFyL2lwbWkvS2NvbmZpZyAgICAgICAgICAgfCAgMjIgKwo+ICBkcml2ZXJzL2NoYXIv aXBtaS9NYWtlZmlsZSAgICAgICAgICB8ICAgMiArCj4gIGRyaXZlcnMvY2hhci9pcG1pL3NzaWZf Ym1jLmMgICAgICAgIHwgNjQ1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgZHJpdmVy cy9jaGFyL2lwbWkvc3NpZl9ibWMuaCAgICAgICAgfCAgOTIgKysrKwo+ICBkcml2ZXJzL2NoYXIv aXBtaS9zc2lmX2JtY19hc3BlZWQuYyB8IDEzMiArKysrKysKPiAgNSBmaWxlcyBjaGFuZ2VkLCA4 OTMgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9jaGFyL2lwbWkv c3NpZl9ibWMuYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9jaGFyL2lwbWkvc3NpZl9i bWMuaAo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9jaGFyL2lwbWkvc3NpZl9ibWNfYXNw ZWVkLmMKPiAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2lwbWkvS2NvbmZpZyBiL2RyaXZl cnMvY2hhci9pcG1pL0tjb25maWcKPiBpbmRleCAwNzg0N2Q5YTQ1OWEuLjQ1YmU1NzAyMzU3NyAx MDA2NDQKPiAtLS0gYS9kcml2ZXJzL2NoYXIvaXBtaS9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9j aGFyL2lwbWkvS2NvbmZpZwo+IEBAIC0xMzMsNiArMTMzLDI4IEBAIGNvbmZpZyBBU1BFRURfQlRf SVBNSV9CTUMKPiAgCSAgZm91bmQgb24gQXNwZWVkIFNPQ3MgKEFTVDI0MDAgYW5kIEFTVDI1MDAp LiBUaGUgZHJpdmVyCj4gIAkgIGltcGxlbWVudHMgdGhlIEJNQyBzaWRlIG9mIHRoZSBCVCBpbnRl cmZhY2UuCj4gIAo+ICtjb25maWcgU1NJRl9JUE1JX0JNQwo+ICsJdHJpc3RhdGUgIlNTSUYgSVBN SSBCTUMgZHJpdmVyIgo+ICsJc2VsZWN0IEkyQwo+ICsJc2VsZWN0IEkyQ19TTEFWRQo+ICsJaGVs cAo+ICsJICBUaGlzIGVuYWJsZXMgdGhlIElQTUkgU01CdXMgc3lzdGVtIGludGVyZmFjZSAoU1NJ RikgYXQgdGhlCj4gKwkgIG1hbmFnZW1lbnQgKEJNQykgc2lkZS4KPiArCj4gKwkgIFRoZSBkcml2 ZXIgaW1wbGVtZW50cyB0aGUgQk1DIHNpZGUgb2YgdGhlIFNNQnVzIHN5c3RlbQo+ICsJICBpbnRl cmZhY2UgKFNTSUYpLgo+ICsKPiArY29uZmlnIEFTUEVFRF9TU0lGX0lQTUlfQk1DCj4gKwlkZXBl bmRzIG9uIEFSQ0hfQVNQRUVEIHx8IENPTVBJTEVfVEVTVAo+ICsJc2VsZWN0IFNTSUZfSVBNSV9C TUMKPiArCXRyaXN0YXRlICJBc3BlZWQgU1NJRiBJUE1JIEJNQyBkcml2ZXIiCj4gKwloZWxwCj4g KwkgIFByb3ZpZGVzIGEgZHJpdmVyIGZvciB0aGUgU1NJRiBJUE1JIGludGVyZmFjZSBmb3VuZCBv bgo+ICsJICBBc3BlZWQgQVNUMjUwMCBTb0MuCj4gKwo+ICsJICBUaGUgZHJpdmVyIGltcGxlbWVu dHMgdGhlIEJNQyBzaWRlIG9mIHRoZSBTTUJ1cyBzeXN0ZW0KPiArCSAgaW50ZXJmYWNlIChTU0lG KSwgc3BlY2lmaWMgZm9yIEFzcGVlZCBBU1QyNTAwIFNvQy4KPiArCj4gIGNvbmZpZyBJUE1CX0RF VklDRV9JTlRFUkZBQ0UKPiAgCXRyaXN0YXRlICdJUE1CIEludGVyZmFjZSBoYW5kbGVyJwo+ICAJ ZGVwZW5kcyBvbiBJMkMKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2lwbWkvTWFrZWZpbGUg Yi9kcml2ZXJzL2NoYXIvaXBtaS9NYWtlZmlsZQo+IGluZGV4IDA4MjJhZGMyZWM0MS4uMDViOTkz ZjczMzViIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvY2hhci9pcG1pL01ha2VmaWxlCj4gKysrIGIv ZHJpdmVycy9jaGFyL2lwbWkvTWFrZWZpbGUKPiBAQCAtMjcsMyArMjcsNSBAQCBvYmotJChDT05G SUdfQVNQRUVEX0JUX0lQTUlfQk1DKSArPSBidC1ibWMubwo+ICBvYmotJChDT05GSUdfQVNQRUVE X0tDU19JUE1JX0JNQykgKz0ga2NzX2JtY19hc3BlZWQubwo+ICBvYmotJChDT05GSUdfTlBDTTdY WF9LQ1NfSVBNSV9CTUMpICs9IGtjc19ibWNfbnBjbTd4eC5vCj4gIG9iai0kKENPTkZJR19JUE1C X0RFVklDRV9JTlRFUkZBQ0UpICs9IGlwbWJfZGV2X2ludC5vCj4gK29iai0kKENPTkZJR19TU0lG X0lQTUlfQk1DKSArPSBzc2lmX2JtYy5vCj4gK29iai0kKENPTkZJR19BU1BFRURfU1NJRl9JUE1J X0JNQykgKz0gc3NpZl9ibWNfYXNwZWVkLm8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2lw bWkvc3NpZl9ibWMuYyBiL2RyaXZlcnMvY2hhci9pcG1pL3NzaWZfYm1jLmMKPiBuZXcgZmlsZSBt b2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uYWU2ZTg3NTBjNzk1Cj4gLS0tIC9kZXYv bnVsbAo+ICsrKyBiL2RyaXZlcnMvY2hhci9pcG1pL3NzaWZfYm1jLmMKPiBAQCAtMCwwICsxLDY0 NSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsKPiArLyoKPiArICog VGhlIGRyaXZlciBmb3IgQk1DIHNpZGUgb2YgU1NJRiBpbnRlcmZhY2UKPiArICoKPiArICogQ29w eXJpZ2h0IChjKSAyMDIxLCBBbXBlcmUgQ29tcHV0aW5nIExMQwo+ICsgKgo+ICsgKiBUaGlzIHBy b2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCj4g KyAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM aWNlbnNlIGFzCj4gKyAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9u OyBlaXRoZXIgdmVyc2lvbiAyIG9mCj4gKyAqIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRp b24pIGFueSBsYXRlciB2ZXJzaW9uLgo+ICsgKgo+ICsgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJp YnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPiArICogYnV0IFdJVEhP VVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKPiAr ICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAg U2VlIHRoZQo+ICsgKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxz Lgo+ICsgKgo+ICsgKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUg R2VuZXJhbCBQdWJsaWMgTGljZW5zZQo+ICsgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4gIElm IG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uCj4gKyAqLwo+ICsKPiAr I2luY2x1ZGUgPGxpbnV4L2kyYy5oPgo+ICsjaW5jbHVkZSA8bGludXgvbWlzY2RldmljZS5oPgo+ ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZi5oPgo+ICsj aW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wb2xs Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zY2hlZC5oPgo+ICsjaW5jbHVkZSA8bGludXgvbXV0ZXgu aD4KPiArI2luY2x1ZGUgPGxpbnV4L3NwaW5sb2NrLmg+Cj4gKwo+ICsjaW5jbHVkZSAic3NpZl9i bWMuaCIKPiArCj4gKy8qCj4gKyAqIENhbGwgaW4gV1JJVEUgY29udGV4dAo+ICsgKi8KPiArc3Rh dGljIGludCBzZW5kX3NzaWZfYm1jX3Jlc3BvbnNlKHN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZf Ym1jLCBib29sIG5vbl9ibG9ja2luZykKPiArewo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsKPiAr CWludCByZXQ7Cj4gKwo+ICsJaWYgKCFub25fYmxvY2tpbmcpIHsKPiArcmV0cnk6Cj4gKwkJcmV0 ID0gd2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlKHNzaWZfYm1jLT53YWl0X3F1ZXVlLAo+ICsJCQkJ CSAgICAgICAhc3NpZl9ibWMtPnJlc3BvbnNlX2luX3Byb2dyZXNzKTsKPiArCQlpZiAocmV0KQo+ ICsJCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXNwaW5fbG9ja19pcnFzYXZlKCZzc2lmX2Jt Yy0+bG9jaywgZmxhZ3MpOwo+ICsJaWYgKHNzaWZfYm1jLT5yZXNwb25zZV9pbl9wcm9ncmVzcykg ewo+ICsJCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnNzaWZfYm1jLT5sb2NrLCBmbGFncyk7Cj4g KwkJaWYgKG5vbl9ibG9ja2luZykKPiArCQkJcmV0dXJuIC1FQUdBSU47Cj4gKwo+ICsJCWdvdG8g cmV0cnk7Cj4gKwl9Cj4gKwo+ICsJLyoKPiArCSAqIENoZWNrIHRoZSByZXNwb25zZSBkYXRhIGxl bmd0aCBmcm9tIHVzZXJzcGFjZSB0byBkZXRlcm1pbmUgdGhlIHR5cGUKPiArCSAqIG9mIHRoZSBy ZXNwb25zZSBtZXNzYWdlIHdoZXRoZXIgaXQgaXMgc2luZ2xlLXBhcnQgb3IgbXVsdGktcGFydC4K PiArCSAqLwo+ICsJc3NpZl9ibWMtPmlzX3NpbmdsZXBhcnRfcmVhZCA9Cj4gKwkJKHNzaWZfbXNn X2xlbigmc3NpZl9ibWMtPnJlc3BvbnNlKSA8PSAoTUFYX1BBWUxPQURfUEVSX1RSQU5TQUNUSU9O ICsgMSkpID8KPiArCQl0cnVlIDogZmFsc2U7IC8qIDE6IGJ5dGUgb2YgbGVuZ3RoICovCj4gKwo+ ICsJc3NpZl9ibWMtPnJlc3BvbnNlX2luX3Byb2dyZXNzID0gdHJ1ZTsKPiArCXNwaW5fdW5sb2Nr X2lycXJlc3RvcmUoJnNzaWZfYm1jLT5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gKy8qCj4gKyAqIENhbGwgaW4gUkVBRCBjb250ZXh0Cj4gKyAqLwo+ICtzdGF0aWMg aW50IHJlY2VpdmVfc3NpZl9ibWNfcmVxdWVzdChzdHJ1Y3Qgc3NpZl9ibWNfY3R4ICpzc2lmX2Jt YywgYm9vbCBub25fYmxvY2tpbmcpCj4gK3sKPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gKwlp bnQgcmV0Owo+ICsKPiArCWlmICghbm9uX2Jsb2NraW5nKSB7Cj4gK3JldHJ5Ogo+ICsJCXJldCA9 IHdhaXRfZXZlbnRfaW50ZXJydXB0aWJsZShzc2lmX2JtYy0+d2FpdF9xdWV1ZSwKPiArCQkJCQkg ICAgICAgc3NpZl9ibWMtPnJlcXVlc3RfYXZhaWxhYmxlKTsKPiArCQlpZiAocmV0KQo+ICsJCQly ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXNwaW5fbG9ja19pcnFzYXZlKCZzc2lmX2JtYy0+bG9j aywgZmxhZ3MpOwo+ICsJaWYgKCFzc2lmX2JtYy0+cmVxdWVzdF9hdmFpbGFibGUpIHsKPiArCQlz cGluX3VubG9ja19pcnFyZXN0b3JlKCZzc2lmX2JtYy0+bG9jaywgZmxhZ3MpOwo+ICsJCWlmIChu b25fYmxvY2tpbmcpCj4gKwkJCXJldHVybiAtRUFHQUlOOwo+ICsJCWdvdG8gcmV0cnk7Cj4gKwl9 Cj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzc2lmX2JtYy0+bG9jaywgZmxhZ3MpOwo+ICsK PiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKiBIYW5kbGUgU1NJRiBtZXNzYWdlIHRoYXQgd2ls bCBiZSBzZW50IHRvIHVzZXIgKi8KPiArc3RhdGljIHNzaXplX3Qgc3NpZl9ibWNfcmVhZChzdHJ1 Y3QgZmlsZSAqZmlsZSwgY2hhciBfX3VzZXIgKmJ1Ziwgc2l6ZV90IGNvdW50LCBsb2ZmX3QgKnBw b3MpCj4gK3sKPiArCXN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZfYm1jID0gdG9fc3NpZl9ibWMo ZmlsZSk7Cj4gKwlzdHJ1Y3Qgc3NpZl9tc2cgbXNnOwo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsK PiArCXNzaXplX3QgcmV0Owo+ICsKPiArCW11dGV4X2xvY2soJnNzaWZfYm1jLT5maWxlX211dGV4 KTsKPiArCj4gKwlyZXQgPSByZWNlaXZlX3NzaWZfYm1jX3JlcXVlc3Qoc3NpZl9ibWMsIGZpbGUt PmZfZmxhZ3MgJiBPX05PTkJMT0NLKTsKPiArCWlmIChyZXQgPCAwKQo+ICsJCWdvdG8gb3V0Owo+ ICsKPiArCXNwaW5fbG9ja19pcnFzYXZlKCZzc2lmX2JtYy0+bG9jaywgZmxhZ3MpOwo+ICsJY291 bnQgPSBtaW5fdChzc2l6ZV90LCBjb3VudCwgc3NpZl9tc2dfbGVuKCZzc2lmX2JtYy0+cmVxdWVz dCkpOwo+ICsJbWVtY3B5KCZtc2csICZzc2lmX2JtYy0+cmVxdWVzdCwgY291bnQpOwo+ICsJc3Np Zl9ibWMtPnJlcXVlc3RfYXZhaWxhYmxlID0gZmFsc2U7Cj4gKwlzcGluX3VubG9ja19pcnFyZXN0 b3JlKCZzc2lmX2JtYy0+bG9jaywgZmxhZ3MpOwo+ICsKPiArCXJldCA9IGNvcHlfdG9fdXNlcihi dWYsICZtc2csIGNvdW50KTsKPiArb3V0Ogo+ICsJbXV0ZXhfdW5sb2NrKCZzc2lmX2JtYy0+Zmls ZV9tdXRleCk7Cj4gKwo+ICsJcmV0dXJuIChyZXQgPCAwKSA/IHJldCA6IGNvdW50Owo+ICt9Cj4g Kwo+ICsvKiBIYW5kbGUgU1NJRiBtZXNzYWdlIHRoYXQgaXMgd3JpdHRlbiBieSB1c2VyICovCj4g K3N0YXRpYyBzc2l6ZV90IHNzaWZfYm1jX3dyaXRlKHN0cnVjdCBmaWxlICpmaWxlLCBjb25zdCBj aGFyIF9fdXNlciAqYnVmLCBzaXplX3QgY291bnQsCj4gKwkJCSAgICAgIGxvZmZfdCAqcHBvcykK PiArewo+ICsJc3RydWN0IHNzaWZfYm1jX2N0eCAqc3NpZl9ibWMgPSB0b19zc2lmX2JtYyhmaWxl KTsKPiArCXN0cnVjdCBzc2lmX21zZyBtc2c7Cj4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsJ c3NpemVfdCByZXQ7Cj4gKwo+ICsJaWYgKGNvdW50ID4gc2l6ZW9mKHN0cnVjdCBzc2lmX21zZykp Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJbXV0ZXhfbG9jaygmc3NpZl9ibWMtPmZpbGVf bXV0ZXgpOwo+ICsKPiArCXJldCA9IGNvcHlfZnJvbV91c2VyKCZtc2csIGJ1ZiwgY291bnQpOwo+ ICsJaWYgKHJldCkKPiArCQlnb3RvIG91dDsKPiArCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmc3Np Zl9ibWMtPmxvY2ssIGZsYWdzKTsKPiArCWlmIChjb3VudCA+PSBzc2lmX21zZ19sZW4oJnNzaWZf Ym1jLT5yZXNwb25zZSkpCj4gKwkJbWVtY3B5KCZzc2lmX2JtYy0+cmVzcG9uc2UsICZtc2csIGNv dW50KTsKPiArCWVsc2UKPiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJc3Bpbl91bmxvY2tfaXJxcmVz dG9yZSgmc3NpZl9ibWMtPmxvY2ssIGZsYWdzKTsKPiArCj4gKwlpZiAocmV0KQo+ICsJCWdvdG8g b3V0Owo+ICsKPiArCXJldCA9IHNlbmRfc3NpZl9ibWNfcmVzcG9uc2Uoc3NpZl9ibWMsIGZpbGUt PmZfZmxhZ3MgJiBPX05PTkJMT0NLKTsKPiArCWlmICghcmV0ICYmIHNzaWZfYm1jLT5zZXRfc3Np Zl9ibWNfc3RhdHVzKQo+ICsJCXNzaWZfYm1jLT5zZXRfc3NpZl9ibWNfc3RhdHVzKHNzaWZfYm1j LCBTU0lGX0JNQ19SRUFEWSk7Cj4gK291dDoKPiArCW11dGV4X3VubG9jaygmc3NpZl9ibWMtPmZp bGVfbXV0ZXgpOwo+ICsKPiArCXJldHVybiAocmV0IDwgMCkgPyByZXQgOiBjb3VudDsKPiArfQo+ ICsKPiArc3RhdGljIGxvbmcgc3NpZl9ibWNfaW9jdGwoc3RydWN0IGZpbGUgKmZpbGUsIHVuc2ln bmVkIGludCBjbWQsIHVuc2lnbmVkIGxvbmcgcGFyYW0pCj4gK3sKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgdW5zaWduZWQgaW50IHNzaWZfYm1jX3BvbGwoc3RydWN0IGZpbGUgKmZp bGUsIHBvbGxfdGFibGUgKndhaXQpCj4gK3sKPiArCXN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZf Ym1jID0gdG9fc3NpZl9ibWMoZmlsZSk7Cj4gKwl1bnNpZ25lZCBpbnQgbWFzayA9IDA7Cj4gKwo+ ICsJbXV0ZXhfbG9jaygmc3NpZl9ibWMtPmZpbGVfbXV0ZXgpOwo+ICsJcG9sbF93YWl0KGZpbGUs ICZzc2lmX2JtYy0+d2FpdF9xdWV1ZSwgd2FpdCk7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZSByZXF1 ZXN0IG1lc3NhZ2UgaXMgbm93IGF2YWlsYWJsZSBzbyB1c2Vyc3BhY2UgYXBwbGljYXRpb24gY2Fu Cj4gKwkgKiBnZXQgdGhlIHJlcXVlc3QKPiArCSAqLwo+ICsJaWYgKHNzaWZfYm1jLT5yZXF1ZXN0 X2F2YWlsYWJsZSkKPiArCQltYXNrIHw9IFBPTExJTjsKPiArCj4gKwltdXRleF91bmxvY2soJnNz aWZfYm1jLT5maWxlX211dGV4KTsKPiArCXJldHVybiBtYXNrOwo+ICt9Cj4gKwo+ICsvKgo+ICsg KiBTeXN0ZW0gY2FsbHMgdG8gZGV2aWNlIGludGVyZmFjZSBmb3IgdXNlciBhcHBzCj4gKyAqLwo+ ICtzdGF0aWMgY29uc3Qgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyBzc2lmX2JtY19mb3BzID0gewo+ ICsJLm93bmVyCQk9IFRISVNfTU9EVUxFLAo+ICsJLnJlYWQJCT0gc3NpZl9ibWNfcmVhZCwKPiAr CS53cml0ZQkJPSBzc2lmX2JtY193cml0ZSwKPiArCS5wb2xsCQk9IHNzaWZfYm1jX3BvbGwsCj4g KwkudW5sb2NrZWRfaW9jdGwJPSBzc2lmX2JtY19pb2N0bCwKPiArfTsKPiArCj4gKy8qIENhbGxl ZCB3aXRoIHNzaWZfYm1jLT5sb2NrIGhlbGQuICovCj4gK3N0YXRpYyBpbnQgaGFuZGxlX3JlcXVl c3Qoc3RydWN0IHNzaWZfYm1jX2N0eCAqc3NpZl9ibWMpCj4gK3sKPiArCWlmIChzc2lmX2JtYy0+ c2V0X3NzaWZfYm1jX3N0YXR1cykKPiArCQlzc2lmX2JtYy0+c2V0X3NzaWZfYm1jX3N0YXR1cyhz c2lmX2JtYywgU1NJRl9CTUNfQlVTWSk7Cj4gKwo+ICsJLyogUmVxdWVzdCBtZXNzYWdlIGlzIGF2 YWlsYWJsZSB0byBwcm9jZXNzICovCj4gKwlzc2lmX2JtYy0+cmVxdWVzdF9hdmFpbGFibGUgPSB0 cnVlOwo+ICsJLyoKPiArCSAqIFRoaXMgaXMgdGhlIG5ldyBSRUFEIHJlcXVlc3QuCj4gKwkgKiBD bGVhciB0aGUgcmVzcG9uc2UgYnVmZmVyIG9mIHRoZSBwcmV2aW91cyB0cmFuc2FjdGlvbgo+ICsJ ICovCj4gKwltZW1zZXQoJnNzaWZfYm1jLT5yZXNwb25zZSwgMCwgc2l6ZW9mKHN0cnVjdCBzc2lm X21zZykpOwo+ICsJd2FrZV91cF9hbGwoJnNzaWZfYm1jLT53YWl0X3F1ZXVlKTsKPiArCXJldHVy biAwOwo+ICt9Cj4gKwo+ICsvKiBDYWxsZWQgd2l0aCBzc2lmX2JtYy0+bG9jayBoZWxkLiAqLwo+ ICtzdGF0aWMgaW50IGNvbXBsZXRlX3Jlc3BvbnNlKHN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZf Ym1jKQo+ICt7Cj4gKwkvKiBJbnZhbGlkYXRlIHJlc3BvbnNlIGluIGJ1ZmZlciB0byBkZW5vdGUg aXQgaGF2aW5nIGJlZW4gc2VudC4gKi8KPiArCXNzaWZfYm1jLT5yZXNwb25zZS5sZW4gPSAwOwo+ ICsJc3NpZl9ibWMtPnJlc3BvbnNlX2luX3Byb2dyZXNzID0gZmFsc2U7Cj4gKwlzc2lmX2JtYy0+ bmJ5dGVzX3Byb2Nlc3NlZCA9IDA7Cj4gKwlzc2lmX2JtYy0+cmVtYWluX2xlbiA9IDA7Cj4gKwlt ZW1zZXQoJnNzaWZfYm1jLT5yZXNwb25zZV9idWYsIDAsIE1BWF9QQVlMT0FEX1BFUl9UUkFOU0FD VElPTik7Cj4gKwl3YWtlX3VwX2FsbCgmc3NpZl9ibWMtPndhaXRfcXVldWUpOwo+ICsJcmV0dXJu IDA7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHNldF9tdWx0aXBhcnRfcmVzcG9uc2VfYnVmZmVy KHN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZfYm1jLCB1OCAqdmFsKQo+ICt7Cj4gKwl1OCByZXNw b25zZV9sZW4gPSAwOwo+ICsJaW50IGlkeCA9IDA7Cj4gKwl1OCBkYXRhX2xlbjsKPiArCj4gKwlk YXRhX2xlbiA9IHNzaWZfYm1jLT5yZXNwb25zZS5sZW47Cj4gKwlzd2l0Y2ggKHNzaWZfYm1jLT5z bWJ1c19jbWQpIHsKPiArCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9SRUFEX1NUQVJUOgo+ICsJ CS8qCj4gKwkJICogUmVhZCBTdGFydCBsZW5ndGggaXMgMzIgYnl0ZXMuCj4gKwkJICogUmVhZCBT dGFydCB0cmFuc2ZlciBmaXJzdCAzMCBieXRlcyBvZiBJUE1JIHJlc3BvbnNlCj4gKwkJICogYW5k IDIgc3BlY2lhbCBjb2RlIDB4MDAsIDB4MDEuCj4gKwkJICovCj4gKwkJKnZhbCA9IE1BWF9QQVlM T0FEX1BFUl9UUkFOU0FDVElPTjsKPiArCQlzc2lmX2JtYy0+cmVtYWluX2xlbiA9IGRhdGFfbGVu IC0gTUFYX0lQTUlfREFUQV9QRVJfU1RBUlRfVFJBTlNBQ1RJT047Cj4gKwkJc3NpZl9ibWMtPmJs b2NrX251bSA9IDA7Cj4gKwo+ICsJCXNzaWZfYm1jLT5yZXNwb25zZV9idWZbaWR4KytdID0gMHgw MDsgLyogU3RhcnQgRmxhZyAqLwo+ICsJCXNzaWZfYm1jLT5yZXNwb25zZV9idWZbaWR4KytdID0g MHgwMTsgLyogU3RhcnQgRmxhZyAqLwo+ICsJCXNzaWZfYm1jLT5yZXNwb25zZV9idWZbaWR4Kytd ID0gc3NpZl9ibWMtPnJlc3BvbnNlLm5ldGZuX2x1bjsKPiArCQlzc2lmX2JtYy0+cmVzcG9uc2Vf YnVmW2lkeCsrXSA9IHNzaWZfYm1jLT5yZXNwb25zZS5jbWQ7Cj4gKwkJc3NpZl9ibWMtPnJlc3Bv bnNlX2J1ZltpZHgrK10gPSBzc2lmX2JtYy0+cmVzcG9uc2UucGF5bG9hZFswXTsKPiArCj4gKwkJ cmVzcG9uc2VfbGVuID0gTUFYX1BBWUxPQURfUEVSX1RSQU5TQUNUSU9OIC0gaWR4Owo+ICsKPiAr CQltZW1jcHkoJnNzaWZfYm1jLT5yZXNwb25zZV9idWZbaWR4XSwgJnNzaWZfYm1jLT5yZXNwb25z ZS5wYXlsb2FkWzFdLAo+ICsJCSAgICAgICByZXNwb25zZV9sZW4pOwo+ICsJCWJyZWFrOwo+ICsK PiArCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9SRUFEX01JRERMRToKPiArCQkvKgo+ICsJCSAq IElQTUkgUkVBRCBNaWRkbGUgb3IgUkVBRCBFbmQgbWVzc2FnZXMgY2FuIGNhcnJ5IHVwIHRvIDMx IGJ5dGVzCj4gKwkJICogSVBNSSBkYXRhIHBsdXMgYmxvY2sgbnVtYmVyIGJ5dGUuCj4gKwkJICov Cj4gKwkJaWYgKHNzaWZfYm1jLT5yZW1haW5fbGVuIDwgTUFYX0lQTUlfREFUQV9QRVJfTUlERExF X1RSQU5TQUNUSU9OKSB7Cj4gKwkJCS8qCj4gKwkJCSAqIFRoaXMgaXMgUkVBRCBFbmQgbWVzc2Fn ZQo+ICsJCQkgKiAgUmV0dXJuIGxlbmd0aCBpcyB0aGUgcmVtYWluaW5nIHJlc3BvbnNlIGRhdGEg bGVuZ3RoCj4gKwkJCSAqICBwbHVzIGJsb2NrIG51bWJlcgo+ICsJCQkgKiAgQmxvY2sgbnVtYmVy IDB4RkYgaXMgdG8gaW5kaWNhdGUgdGhpcyBpcyBsYXN0IG1lc3NhZ2UKPiArCQkJICoKPiArCQkJ ICogUmV0dXJuIGxlbmd0aCBpczogcmVtYWluIHJlc3BvbnNlIHBsdXMgYmxvY2sgbnVtYmVyCj4g KwkJCSAqLwo+ICsJCQkqdmFsID0gc3NpZl9ibWMtPnJlbWFpbl9sZW4gKyAxOwo+ICsJCQlzc2lm X2JtYy0+YmxvY2tfbnVtID0gMHhGRjsKPiArCQkJc3NpZl9ibWMtPnJlc3BvbnNlX2J1ZltpZHgr K10gPSBzc2lmX2JtYy0+YmxvY2tfbnVtOwo+ICsJCQlyZXNwb25zZV9sZW4gPSBzc2lmX2JtYy0+ cmVtYWluX2xlbjsKPiArCQl9IGVsc2Ugewo+ICsJCQkvKgo+ICsJCQkgKiBUaGlzIGlzIFJFQUQg TWlkZGxlIG1lc3NhZ2UKPiArCQkJICogIFJlc3BvbnNlIGxlbmd0aCBpcyB0aGUgbWF4aW11bSBT TUJVUyB0cmFuc2ZlciBsZW5ndGgKPiArCQkJICogIEJsb2NrIG51bWJlciBieXRlIGlzIGluY3Jl bWVudGVkCj4gKwkJCSAqIFJldHVybiBsZW5ndGggaXMgbWF4aW11bSBTTUJVUyB0cmFuc2ZlciBs ZW5ndGgKPiArCQkJICovCj4gKwkJCSp2YWwgPSBNQVhfUEFZTE9BRF9QRVJfVFJBTlNBQ1RJT047 Cj4gKwkJCXNzaWZfYm1jLT5yZW1haW5fbGVuIC09IE1BWF9JUE1JX0RBVEFfUEVSX01JRERMRV9U UkFOU0FDVElPTjsKPiArCQkJcmVzcG9uc2VfbGVuID0gTUFYX0lQTUlfREFUQV9QRVJfTUlERExF X1RSQU5TQUNUSU9OOwo+ICsJCQlzc2lmX2JtYy0+cmVzcG9uc2VfYnVmW2lkeCsrXSA9IHNzaWZf Ym1jLT5ibG9ja19udW07Cj4gKwkJCXNzaWZfYm1jLT5ibG9ja19udW0rKzsKPiArCQl9Cj4gKwo+ ICsJCW1lbWNweSgmc3NpZl9ibWMtPnJlc3BvbnNlX2J1ZltpZHhdLAo+ICsJCSAgICAgICBzc2lm X2JtYy0+cmVzcG9uc2UucGF5bG9hZCArIDEgKyBzc2lmX2JtYy0+bmJ5dGVzX3Byb2Nlc3NlZCwK PiArCQkgICAgICAgcmVzcG9uc2VfbGVuKTsKPiArCQlicmVhazsKPiArCj4gKwlkZWZhdWx0Ogo+ ICsJCS8qIERvIG5vdCBleHBlY3QgdG8gZ28gdG8gdGhpcyBjYXNlICovCj4gKwkJcHJfZXJyKCJF cnJvcjogVW5leHBlY3RlZCBTTUJ1cyBjb21tYW5kIHJlY2VpdmVkIDB4JXhcbiIsIHNzaWZfYm1j LT5zbWJ1c19jbWQpOwo+ICsJCWJyZWFrOwo+ICsJfQo+ICsKPiArCXNzaWZfYm1jLT5uYnl0ZXNf cHJvY2Vzc2VkICs9IHJlc3BvbnNlX2xlbjsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgc2V0X3Np bmdsZXBhcnRfcmVzcG9uc2VfYnVmZmVyKHN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZfYm1jLCB1 OCAqdmFsKQo+ICt7Cj4gKwl1OCAqYnVmID0gKHU4ICopJnNzaWZfYm1jLT5yZXNwb25zZTsKPiAr Cj4gKwkvKgo+ICsJICogRG8gbm90IGV4cGVjdCB0aGUgSVBNSSByZXNwb25zZSBoYXMgZGF0YSBs ZW5ndGggMC4KPiArCSAqIFdpdGggc29tZSBJMkMgU01CdXMgY29udHJvbGxlcnMgKEFzcGVlZCBJ MkMpLCByZXR1cm4gMCBmb3IKPiArCSAqIHRoZSBTTUJ1cyBSZWFkIFJlcXVlc3QgY2FsbGJhY2sg bWlnaHQgY2F1c2UgYmFkIHN0YXRlIGZvcgo+ICsJICogdGhlIGJ1cy4gU28gcmV0dXJuIDEgYnl0 ZSBsZW5ndGggc28gdGhhdCBtYXN0ZXIgd2lsbAo+ICsJICogcmVzZW5kIHRoZSBSZWFkIFJlcXVl c3QgYmVjYXVzZSB0aGUgbGVuZ3RoIG9mIHJlc3BvbnNlIGlzCj4gKwkgKiBsZXNzIHRoYW4gYSBu b3JtYWwgSVBNSSByZXNwb25zZS4KPiArCSAqCj4gKwkgKiBPdGhlcndpc2UsIHJldHVybiB0aGUg bGVuZ3RoIG9mIElQTUkgcmVzcG9uc2UKPiArCSAqLwo+ICsJKnZhbCA9IChidWZbc3NpZl9ibWMt Pm1zZ19pZHhdKSA/IGJ1Zltzc2lmX2JtYy0+bXNnX2lkeF0gOiAweDE7Cj4gK30KPiArCj4gKy8q IFByb2Nlc3MgdGhlIElQTUkgcmVzcG9uc2UgdGhhdCB3aWxsIGJlIHJlYWQgYnkgbWFzdGVyICov Cj4gK3N0YXRpYyB2b2lkIGhhbmRsZV9yZWFkX3Byb2Nlc3NlZChzdHJ1Y3Qgc3NpZl9ibWNfY3R4 ICpzc2lmX2JtYywgdTggKnZhbCkKPiArewo+ICsJdTggKmJ1ZjsKPiArCXU4IHBlY19sZW4sIGFk ZHIsIGxlbjsKPiArCXU4IHBlYyA9IDA7Cj4gKwo+ICsJcGVjX2xlbiA9IHNzaWZfYm1jLT5wZWNf c3VwcG9ydCA/IDEgOiAwOwo+ICsJLyogUEVDIC0gU3RhcnQgUmVhZCBBZGRyZXNzICovCj4gKwlh ZGRyID0gR0VUXzhCSVRfQUREUihzc2lmX2JtYy0+Y2xpZW50LT5hZGRyKTsKPiArCXBlYyA9IGky Y19zbWJ1c19wZWMocGVjLCAmYWRkciwgMSk7Cj4gKwkvKiBQRUMgLSBTU0lGIENvbW1hbmQgKi8K PiArCXBlYyA9IGkyY19zbWJ1c19wZWMocGVjLCAmc3NpZl9ibWMtPnNtYnVzX2NtZCwgMSk7Cj4g KwkvKiBQRUMgLSBSZXN0YXJ0IFdyaXRlIEFkZHJlc3MgKi8KPiArCWFkZHIgPSBhZGRyIHwgMHgw MTsKPiArCXBlYyA9IGkyY19zbWJ1c19wZWMocGVjLCAmYWRkciwgMSk7Cj4gKwo+ICsJaWYgKHNz aWZfYm1jLT5pc19zaW5nbGVwYXJ0X3JlYWQpIHsKPiArCQkvKiBTaW5nbGUtcGFydCBSZWFkIHBy b2Nlc3NpbmcgKi8KPiArCQlidWYgPSAodTggKikmc3NpZl9ibWMtPnJlc3BvbnNlOwo+ICsKPiAr CQlpZiAoc3NpZl9ibWMtPnJlc3BvbnNlLmxlbiAmJiBzc2lmX2JtYy0+bXNnX2lkeCA8IHNzaWZf Ym1jLT5yZXNwb25zZS5sZW4pIHsKPiArCQkJc3NpZl9ibWMtPm1zZ19pZHgrKzsKPiArCQkJKnZh bCA9IGJ1Zltzc2lmX2JtYy0+bXNnX2lkeF07Cj4gKwkJfSBlbHNlIGlmIChzc2lmX2JtYy0+cmVz cG9uc2UubGVuICYmCj4gKwkJCSAgIChzc2lmX2JtYy0+bXNnX2lkeCA9PSBzc2lmX2JtYy0+cmVz cG9uc2UubGVuKSkgewo+ICsJCQlzc2lmX2JtYy0+bXNnX2lkeCsrOwo+ICsJCQkqdmFsID0gaTJj X3NtYnVzX3BlYyhwZWMsIGJ1Ziwgc3NpZl9tc2dfbGVuKCZzc2lmX2JtYy0+cmVzcG9uc2UpKTsK PiArCQl9IGVsc2Ugewo+ICsJCQkqdmFsID0gMDsKPiArCQl9Cj4gKwkJLyogSW52YWxpZGF0ZSBy ZXNwb25zZSBidWZmZXIgdG8gZGVub3RlIGl0IGlzIHNlbnQgKi8KPiArCQlpZiAoc3NpZl9ibWMt Pm1zZ19pZHggKyAxID49IChzc2lmX21zZ19sZW4oJnNzaWZfYm1jLT5yZXNwb25zZSkgKyBwZWNf bGVuKSkKPiArCQkJY29tcGxldGVfcmVzcG9uc2Uoc3NpZl9ibWMpOwo+ICsJfSBlbHNlIHsKPiAr CQkvKiBNdWx0aS1wYXJ0IFJlYWQgcHJvY2Vzc2luZyAqLwo+ICsJCXN3aXRjaCAoc3NpZl9ibWMt PnNtYnVzX2NtZCkgewo+ICsJCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9SRUFEX1NUQVJUOgo+ ICsJCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9SRUFEX01JRERMRToKPiArCQkJYnVmID0gKHU4 ICopJnNzaWZfYm1jLT5yZXNwb25zZV9idWY7Cj4gKwkJCSp2YWwgPSBidWZbc3NpZl9ibWMtPm1z Z19pZHhdOwo+ICsJCQlzc2lmX2JtYy0+bXNnX2lkeCsrOwo+ICsJCQlicmVhazsKPiArCQlkZWZh dWx0Ogo+ICsJCQkvKiBEbyBub3QgZXhwZWN0IHRvIGdvIHRvIHRoaXMgY2FzZSAqLwo+ICsJCQlw cl9lcnIoIkVycm9yOiBVbmV4cGVjdGVkIFNNQnVzIGNvbW1hbmQgcmVjZWl2ZWQgMHgleFxuIiwK PiArCQkJICAgICAgIHNzaWZfYm1jLT5zbWJ1c19jbWQpOwo+ICsJCQlicmVhazsKPiArCQl9Cj4g KwkJbGVuID0gKHNzaWZfYm1jLT5ibG9ja19udW0gPT0gMHhGRikgPwo+ICsJCSAgICAgICBzc2lm X2JtYy0+cmVtYWluX2xlbiArIDEgOiBNQVhfUEFZTE9BRF9QRVJfVFJBTlNBQ1RJT047Cj4gKwkJ aWYgKHNzaWZfYm1jLT5tc2dfaWR4ID09IChsZW4gKyAxKSkgewo+ICsJCQlwZWMgPSBpMmNfc21i dXNfcGVjKHBlYywgJmxlbiwgMSk7Cj4gKwkJCSp2YWwgPSBpMmNfc21idXNfcGVjKHBlYywgc3Np Zl9ibWMtPnJlc3BvbnNlX2J1ZiwgbGVuKTsKPiArCQl9Cj4gKwkJLyogSW52YWxpZGF0ZSByZXNw b25zZSBidWZmZXIgdG8gZGVub3RlIGxhc3QgcmVzcG9uc2UgaXMgc2VudCAqLwo+ICsJCWlmIChz c2lmX2JtYy0+YmxvY2tfbnVtID09IDB4RkYgJiYKPiArCQkgICAgc3NpZl9ibWMtPm1zZ19pZHgg PiAoc3NpZl9ibWMtPnJlbWFpbl9sZW4gKyBwZWNfbGVuKSkgewo+ICsJCQljb21wbGV0ZV9yZXNw b25zZShzc2lmX2JtYyk7Cj4gKwkJfQo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBoYW5k bGVfd3JpdGVfcmVjZWl2ZWQoc3RydWN0IHNzaWZfYm1jX2N0eCAqc3NpZl9ibWMsIHU4ICp2YWwp Cj4gK3sKPiArCXU4ICpidWY7Cj4gKwl1OCBzbWJ1c19jbWQ7Cj4gKwo+ICsJYnVmID0gKHU4ICop JnNzaWZfYm1jLT5yZXF1ZXN0Owo+ICsJaWYgKHNzaWZfYm1jLT5tc2dfaWR4ID49IHNpemVvZihz dHJ1Y3Qgc3NpZl9tc2cpKQo+ICsJCXJldHVybjsKPiArCj4gKwlzbWJ1c19jbWQgPSBzc2lmX2Jt Yy0+c21idXNfY21kOwo+ICsJc3dpdGNoIChzbWJ1c19jbWQpIHsKPiArCWNhc2UgU1NJRl9JUE1J X1NJTkdMRVBBUlRfV1JJVEU6Cj4gKwkJLyogU2luZ2xlLXBhcnQgd3JpdGUgKi8KPiArCQlidWZb c3NpZl9ibWMtPm1zZ19pZHggLSAxXSA9ICp2YWw7Cj4gKwkJc3NpZl9ibWMtPm1zZ19pZHgrKzsK PiArCj4gKwkJYnJlYWs7Cj4gKwljYXNlIFNTSUZfSVBNSV9NVUxUSVBBUlRfV1JJVEVfU1RBUlQ6 Cj4gKwkJLyogUmVzZXQgbGVuZ3RoIHRvIHplcm8gKi8KPiArCQlpZiAoc3NpZl9ibWMtPm1zZ19p ZHggPT0gMSkKPiArCQkJc3NpZl9ibWMtPnJlcXVlc3QubGVuID0gMDsKPiArCj4gKwkJZmFsbHRo cm91Z2g7Cj4gKwljYXNlIFNTSUZfSVBNSV9NVUxUSVBBUlRfV1JJVEVfTUlERExFOgo+ICsJY2Fz ZSBTU0lGX0lQTUlfTVVMVElQQVJUX1dSSVRFX0VORDoKPiArCQkvKiBNdWx0aS1wYXJ0IHdyaXRl LCAybmQgYnl0ZSByZWNlaXZlZCBpcyBsZW5ndGggKi8KPiArCQlpZiAoc3NpZl9ibWMtPm1zZ19p ZHggPT0gMSkgewo+ICsJCQlzc2lmX2JtYy0+cmVxdWVzdC5sZW4gKz0gKnZhbDsKPiArCQkJc3Np Zl9ibWMtPnJlY3ZfbGVuID0gKnZhbDsKPiArCQl9IGVsc2Ugewo+ICsJCQlidWZbc3NpZl9ibWMt Pm1zZ19pZHggLSAxICsKPiArCQkJICAgIHNzaWZfYm1jLT5yZXF1ZXN0LmxlbiAtIHNzaWZfYm1j LT5yZWN2X2xlbl0JPSAqdmFsOwo+ICsJCX0KPiArCj4gKwkJc3NpZl9ibWMtPm1zZ19pZHgrKzsK PiArCj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCS8qIERvIG5vdCBleHBlY3QgdG8gZ28g dG8gdGhpcyBjYXNlICovCj4gKwkJcHJfZXJyKCJFcnJvcjogVW5leHBlY3RlZCBTTUJ1cyBjb21t YW5kIHJlY2VpdmVkIDB4JXhcbiIsIHNzaWZfYm1jLT5zbWJ1c19jbWQpOwo+ICsJCWJyZWFrOwo+ ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2YWxpZGF0ZV9wZWMoc3RydWN0IHNzaWZfYm1j X2N0eCAqc3NpZl9ibWMpCj4gK3sKPiArCXU4IHJwZWMgPSAwLCBjcGVjID0gMDsKPiArCWJvb2wg cmV0ID0gdHJ1ZTsKPiArCXU4IGFkZHIsIGluZGV4Owo+ICsJdTggKmJ1ZjsKPiArCj4gKwlidWYg PSAodTggKikmc3NpZl9ibWMtPnJlcXVlc3Q7Cj4gKwlzd2l0Y2ggKHNzaWZfYm1jLT5zbWJ1c19j bWQpIHsKPiArCWNhc2UgU1NJRl9JUE1JX1NJTkdMRVBBUlRfV1JJVEU6Cj4gKwkJaWYgKChzc2lm X2JtYy0+bXNnX2lkeCAtIDEpID09IHNzaWZfbXNnX2xlbigmc3NpZl9ibWMtPnJlcXVlc3QpKSB7 Cj4gKwkJCS8qIFBFQyBpcyBub3QgaW5jbHVkZWQgKi8KPiArCQkJc3NpZl9ibWMtPnBlY19zdXBw b3J0ID0gZmFsc2U7Cj4gKwkJCXJldHVybiB0cnVlOwo+ICsJCX0KPiArCj4gKwkJaWYgKChzc2lm X2JtYy0+bXNnX2lkeCAtIDEpICE9IChzc2lmX21zZ19sZW4oJnNzaWZfYm1jLT5yZXF1ZXN0KSAr IDEpKQo+ICsJCQlnb3RvIGVycm9yOwo+ICsKPiArCQkvKiBQRUMgaXMgaW5jbHVkZWQgKi8KPiAr CQlzc2lmX2JtYy0+cGVjX3N1cHBvcnQgPSB0cnVlOwo+ICsJCXJwZWMgPSBidWZbc3NpZl9ibWMt Pm1zZ19pZHggLSAyXTsKPiArCQlhZGRyID0gR0VUXzhCSVRfQUREUihzc2lmX2JtYy0+Y2xpZW50 LT5hZGRyKTsKPiArCQljcGVjID0gaTJjX3NtYnVzX3BlYyhjcGVjLCAmYWRkciwgMSk7Cj4gKwkJ Y3BlYyA9IGkyY19zbWJ1c19wZWMoY3BlYywgJnNzaWZfYm1jLT5zbWJ1c19jbWQsIDEpOwo+ICsJ CWNwZWMgPSBpMmNfc21idXNfcGVjKGNwZWMsIGJ1Ziwgc3NpZl9tc2dfbGVuKCZzc2lmX2JtYy0+ cmVxdWVzdCkpOwo+ICsJCWlmIChycGVjICE9IGNwZWMpIHsKPiArCQkJcHJfZXJyKCJCYWQgUEVD IDB4JTAyeCB2cy4gMHglMDJ4XG4iLCBycGVjLCBjcGVjKTsKPiArCQkJcmV0ID0gZmFsc2U7Cj4g KwkJfQo+ICsKPiArCQlicmVhazsKPiArCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9XUklURV9T VEFSVDoKPiArCWNhc2UgU1NJRl9JUE1JX01VTFRJUEFSVF9XUklURV9NSURETEU6Cj4gKwljYXNl IFNTSUZfSVBNSV9NVUxUSVBBUlRfV1JJVEVfRU5EOgo+ICsJCWluZGV4ID0gc3NpZl9ibWMtPnJl cXVlc3QubGVuIC0gc3NpZl9ibWMtPnJlY3ZfbGVuOwo+ICsJCWlmICgoc3NpZl9ibWMtPm1zZ19p ZHggLSAxICsgaW5kZXgpID09IHNzaWZfbXNnX2xlbigmc3NpZl9ibWMtPnJlcXVlc3QpKSB7Cj4g KwkJCS8qIFBFQyBpcyBub3QgaW5jbHVkZWQgKi8KPiArCQkJc3NpZl9ibWMtPnBlY19zdXBwb3J0 ID0gZmFsc2U7Cj4gKwkJCXJldHVybiB0cnVlOwo+ICsJCX0KPiArCj4gKwkJaWYgKChzc2lmX2Jt Yy0+bXNnX2lkeCAtIDEgKyBpbmRleCkgIT0gKHNzaWZfbXNnX2xlbigmc3NpZl9ibWMtPnJlcXVl c3QpICsgMSkpCj4gKwkJCWdvdG8gZXJyb3I7Cj4gKwo+ICsJCS8qIFBFQyBpcyBpbmNsdWRlZCAq Lwo+ICsJCXNzaWZfYm1jLT5wZWNfc3VwcG9ydCA9IHRydWU7Cj4gKwkJcnBlYyA9IGJ1Zltzc2lm X2JtYy0+bXNnX2lkeCAtIDIgKyBpbmRleF07Cj4gKwkJYWRkciA9IEdFVF84QklUX0FERFIoc3Np Zl9ibWMtPmNsaWVudC0+YWRkcik7Cj4gKwkJY3BlYyA9IGkyY19zbWJ1c19wZWMoY3BlYywgJmFk ZHIsIDEpOwo+ICsJCWNwZWMgPSBpMmNfc21idXNfcGVjKGNwZWMsICZzc2lmX2JtYy0+c21idXNf Y21kLCAxKTsKPiArCQljcGVjID0gaTJjX3NtYnVzX3BlYyhjcGVjLCAmc3NpZl9ibWMtPnJlY3Zf bGVuLCAxKTsKPiArCQkvKiBBcyBTTUJ1cyBzcGVjaWZpY2F0aW9uIGRvZXMgbm90IGFsbG93IHRo ZSBsZW5ndGgKPiArCQkgKiAoYnl0ZSBjb3VudCkgaW4gdGhlIFdyaXRlLUJsb2NrIHByb3RvY29s IHRvIGJlIHplcm8uCj4gKwkJICogVGhlcmVmb3JlLCBpdCBpcyBpbGxlZ2FsIHRvIGhhdmUgdGhl IGxhc3QgTWlkZGxlCj4gKwkJICogdHJhbnNhY3Rpb24gaW4gdGhlIHNlcXVlbmNlIGNhcnJ5IDMy LWJ5dGVzIGFuZCBoYXZlCj4gKwkJICogYSBsZW5ndGggb2Yg4oCYMOKAmSBpbiB0aGUgRW5kIHRy YW5zYWN0aW9uLgo+ICsJCSAqIEJ1dCBzb21lIHVzZXJzIG1heSB0cnkgdG8gdXNlIHRoaXMgd2F5 IGFuZCB3ZSBzaG91bGQKPiArCQkgKiBwcmV2ZW50IHNzaWZfYm1jIGRyaXZlciBicm9rZW4gaW4g dGhpcyBjYXNlLgo+ICsJCSAqLwo+ICsJCWlmIChzc2lmX2JtYy0+cmVjdl9sZW4gIT0gMCkKPiAr CQkJY3BlYyA9IGkyY19zbWJ1c19wZWMoY3BlYywgYnVmICsgMSArIGluZGV4LCBzc2lmX2JtYy0+ cmVjdl9sZW4pOwo+ICsKPiArCQlpZiAocnBlYyAhPSBjcGVjKSB7Cj4gKwkJCXByX2VycigiQmFk IFBFQyAweCUwMnggdnMuIDB4JTAyeFxuIiwgcnBlYywgY3BlYyk7Cj4gKwkJCXJldCA9IGZhbHNl Owo+ICsJCX0KPiArCj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCWJyZWFrOwo+ICsJfQo+ ICsKPiArCXJldHVybiByZXQ7Cj4gK2Vycm9yOgo+ICsJLyogRG8gbm90IGV4cGVjdCB0byBnbyB0 byB0aGlzIGNhc2UgKi8KPiArCXByX2VycigiRXJyb3I6IFVuZXhwZWN0ZWQgbGVuZ3RoIHJlY2Vp dmVkICVkXG4iLCBzc2lmX21zZ19sZW4oJnNzaWZfYm1jLT5yZXF1ZXN0KSk7Cj4gKwo+ICsJcmV0 dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjb21wbGV0ZV93cml0ZV9yZWNlaXZl ZChzdHJ1Y3Qgc3NpZl9ibWNfY3R4ICpzc2lmX2JtYykKPiArewo+ICsJdTggY21kID0gc3NpZl9i bWMtPnNtYnVzX2NtZDsKPiArCj4gKwkvKiBBIEJNQyB0aGF0IHJlY2VpdmVzIGFuIGludmFsaWQg UEVDIHNoYWxsIGRyb3AgdGhlIGRhdGEgZm9yIHRoZSB3cml0ZQo+ICsJICogdHJhbnNhY3Rpb24g YW5kIGFueSBmdXJ0aGVyIHRyYW5zYWN0aW9ucyAocmVhZCBvciB3cml0ZSkgdW50aWwKPiArCSAq IHRoZSBuZXh0IHZhbGlkIHJlYWQgb3Igd3JpdGUgU3RhcnQgdHJhbnNhY3Rpb24gaXMgcmVjZWl2 ZWQKPiArCSAqLwo+ICsJaWYgKCF2YWxpZGF0ZV9wZWMoc3NpZl9ibWMpKSB7Cj4gKwkJcHJfZXJy KCJSZWNlaXZlZCBpbnZhbGlkIFBFQ1xuIik7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsKPiArCWlm IChjbWQgPT0gU1NJRl9JUE1JX1NJTkdMRVBBUlRfV1JJVEUgfHwgY21kID09IFNTSUZfSVBNSV9N VUxUSVBBUlRfV1JJVEVfRU5EKQo+ICsJCWhhbmRsZV9yZXF1ZXN0KHNzaWZfYm1jKTsKPiArfQo+ ICsKPiArLyoKPiArICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gaGFuZGxlIEkyQyBzbGF2ZSBldmVu dHMKPiArICovCj4gK3N0YXRpYyBpbnQgc3NpZl9ibWNfY2Ioc3RydWN0IGkyY19jbGllbnQgKmNs aWVudCwgZW51bSBpMmNfc2xhdmVfZXZlbnQgZXZlbnQsIHU4ICp2YWwpCj4gK3sKPiArCXN0cnVj dCBzc2lmX2JtY19jdHggKnNzaWZfYm1jID0gaTJjX2dldF9jbGllbnRkYXRhKGNsaWVudCk7Cj4g Kwo+ICsJc3Bpbl9sb2NrKCZzc2lmX2JtYy0+bG9jayk7Cj4gKwo+ICsJLyogSTJDIEV2ZW50IEhh bmRsZXI6Cj4gKwkgKiAgIEkyQ19TTEFWRV9SRUFEX1JFUVVFU1RFRAkweDAKPiArCSAqICAgSTJD X1NMQVZFX1dSSVRFX1JFUVVFU1RFRAkweDEKPiArCSAqICAgSTJDX1NMQVZFX1JFQURfUFJPQ0VT U0VECTB4Mgo+ICsJICogICBJMkNfU0xBVkVfV1JJVEVfUkVDRUlWRUQJMHgzCj4gKwkgKiAgIEky Q19TTEFWRV9TVE9QCQkweDQKPiArCSAqLwo+ICsJc3dpdGNoIChldmVudCkgewo+ICsJY2FzZSBJ MkNfU0xBVkVfUkVBRF9SRVFVRVNURUQ6Cj4gKwkJc3NpZl9ibWMtPm1zZ19pZHggPSAwOwo+ICsJ CWlmIChzc2lmX2JtYy0+aXNfc2luZ2xlcGFydF9yZWFkKQo+ICsJCQlzZXRfc2luZ2xlcGFydF9y ZXNwb25zZV9idWZmZXIoc3NpZl9ibWMsIHZhbCk7Cj4gKwkJZWxzZQo+ICsJCQlzZXRfbXVsdGlw YXJ0X3Jlc3BvbnNlX2J1ZmZlcihzc2lmX2JtYywgdmFsKTsKPiArCQlicmVhazsKPiArCj4gKwlj YXNlIEkyQ19TTEFWRV9XUklURV9SRVFVRVNURUQ6Cj4gKwkJc3NpZl9ibWMtPm1zZ19pZHggPSAw Owo+ICsJCWJyZWFrOwo+ICsKPiArCWNhc2UgSTJDX1NMQVZFX1JFQURfUFJPQ0VTU0VEOgo+ICsJ CWhhbmRsZV9yZWFkX3Byb2Nlc3NlZChzc2lmX2JtYywgdmFsKTsKPiArCQlicmVhazsKPiArCj4g KwljYXNlIEkyQ19TTEFWRV9XUklURV9SRUNFSVZFRDoKPiArCQkvKgo+ICsJCSAqIEZpcnN0IGJ5 dGUgaXMgU01CVVMgY29tbWFuZCwgbm90IGEgcGFydCBvZiBTU0lGIG1lc3NhZ2UuCj4gKwkJICog U1NJRiByZXF1ZXN0IGJ1ZmZlciBzdGFydHMgd2l0aCBtc2dfaWR4IDEgZm9yIHRoZSBmaXJzdAo+ ICsJCSAqICBidWZmZXIgYnl0ZS4KPiArCQkgKi8KPiArCQlpZiAoc3NpZl9ibWMtPm1zZ19pZHgg PT0gMCkgewo+ICsJCQkvKiBTTUJVUyBjb21tYW5kIGNhbiB2YXJ5IChzaW5nbGUgb3IgbXVsdGkt cGFydCkgKi8KPiArCQkJc3NpZl9ibWMtPnNtYnVzX2NtZCA9ICp2YWw7Cj4gKwkJCXNzaWZfYm1j LT5tc2dfaWR4Kys7Cj4gKwkJfSBlbHNlIHsKPiArCQkJaGFuZGxlX3dyaXRlX3JlY2VpdmVkKHNz aWZfYm1jLCB2YWwpOwo+ICsJCX0KPiArCj4gKwkJYnJlYWs7Cj4gKwo+ICsJY2FzZSBJMkNfU0xB VkVfU1RPUDoKPiArCQkvKgo+ICsJCSAqIFBFQyBieXRlIGlzIGFwcGVuZGVkIGF0IHRoZSBlbmQg b2YgZWFjaCB0cmFuc2FjdGlvbi4KPiArCQkgKiBEZXRlY3QgUEVDIGlzIHN1cHBvcnQgb3Igbm90 IGFmdGVyIHJlY2VpdmluZyB3cml0ZSByZXF1ZXN0Cj4gKwkJICogY29tcGxldGVseS4KPiArCQkg Ki8KPiArCQlpZiAoc3NpZl9ibWMtPmxhc3RfZXZlbnQgPT0gSTJDX1NMQVZFX1dSSVRFX1JFQ0VJ VkVEKQo+ICsJCQljb21wbGV0ZV93cml0ZV9yZWNlaXZlZChzc2lmX2JtYyk7Cj4gKwkJLyogUmVz ZXQgbWVzc2FnZSBpbmRleCAqLwo+ICsJCXNzaWZfYm1jLT5tc2dfaWR4ID0gMDsKPiArCQlicmVh azsKPiArCj4gKwlkZWZhdWx0Ogo+ICsJCWJyZWFrOwo+ICsJfQo+ICsJc3NpZl9ibWMtPmxhc3Rf ZXZlbnQgPSBldmVudDsKPiArCXNwaW5fdW5sb2NrKCZzc2lmX2JtYy0+bG9jayk7Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZfYm1jX2FsbG9j KHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsIGludCBzaXplb2ZfcHJpdikKPiArewo+ICsJc3Ry dWN0IHNzaWZfYm1jX2N0eCAqc3NpZl9ibWM7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXNzaWZfYm1j ID0gZGV2bV9remFsbG9jKCZjbGllbnQtPmRldiwgc2l6ZW9mKCpzc2lmX2JtYykgKyBzaXplb2Zf cHJpdiwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNzaWZfYm1jKQo+ICsJCXJldHVybiBFUlJfUFRS KC1FTk9NRU0pOwo+ICsKPiArCXNwaW5fbG9ja19pbml0KCZzc2lmX2JtYy0+bG9jayk7Cj4gKwo+ ICsJaW5pdF93YWl0cXVldWVfaGVhZCgmc3NpZl9ibWMtPndhaXRfcXVldWUpOwo+ICsJc3NpZl9i bWMtPnJlcXVlc3RfYXZhaWxhYmxlID0gZmFsc2U7Cj4gKwlzc2lmX2JtYy0+cmVzcG9uc2VfaW5f cHJvZ3Jlc3MgPSBmYWxzZTsKPiArCj4gKwltdXRleF9pbml0KCZzc2lmX2JtYy0+ZmlsZV9tdXRl eCk7Cj4gKwo+ICsJLyogUmVnaXN0ZXIgbWlzYyBkZXZpY2UgaW50ZXJmYWNlICovCj4gKwlzc2lm X2JtYy0+bWlzY2Rldi5taW5vciA9IE1JU0NfRFlOQU1JQ19NSU5PUjsKPiArCXNzaWZfYm1jLT5t aXNjZGV2Lm5hbWUgPSBERVZJQ0VfTkFNRTsKPiArCXNzaWZfYm1jLT5taXNjZGV2LmZvcHMgPSAm c3NpZl9ibWNfZm9wczsKPiArCXNzaWZfYm1jLT5taXNjZGV2LnBhcmVudCA9ICZjbGllbnQtPmRl djsKPiArCXJldCA9IG1pc2NfcmVnaXN0ZXIoJnNzaWZfYm1jLT5taXNjZGV2KTsKPiArCWlmIChy ZXQpCj4gKwkJZ290byBvdXQ7Cj4gKwo+ICsJc3NpZl9ibWMtPmNsaWVudCA9IGNsaWVudDsKPiAr CXNzaWZfYm1jLT5jbGllbnQtPmZsYWdzIHw9IEkyQ19DTElFTlRfU0xBVkU7Cj4gKwo+ICsJLyog UmVnaXN0ZXIgSTJDIHNsYXZlICovCj4gKwlpMmNfc2V0X2NsaWVudGRhdGEoY2xpZW50LCBzc2lm X2JtYyk7Cj4gKwlyZXQgPSBpMmNfc2xhdmVfcmVnaXN0ZXIoY2xpZW50LCBzc2lmX2JtY19jYik7 Cj4gKwlpZiAocmV0KSB7Cj4gKwkJbWlzY19kZXJlZ2lzdGVyKCZzc2lmX2JtYy0+bWlzY2Rldik7 Cj4gKwkJZ290byBvdXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHNzaWZfYm1jOwo+ICsKPiArb3V0 Ogo+ICsJZGV2bV9rZnJlZSgmY2xpZW50LT5kZXYsIHNzaWZfYm1jKTsKPiArCXJldHVybiBFUlJf UFRSKHJldCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChzc2lmX2JtY19hbGxvYyk7Cj4gKwo+ICtN T0RVTEVfQVVUSE9SKCJDaHVvbmcgVHJhbiA8Y2h1b25nQG9zLmFtcGVyZWNvbXB1dGluZy5jb20+ Iik7Cj4gK01PRFVMRV9BVVRIT1IoIlF1YW4gTmd1eWVuIDxxdWFuQG9zLmFtcGVyZWNvbXB1dGlu Zy5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiTGludXggZGV2aWNlIGRyaXZlciBvZiB0 aGUgQk1DIElQTUkgU1NJRiBpbnRlcmZhY2UuIik7Cj4gK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIi KTsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2lwbWkvc3NpZl9ibWMuaCBiL2RyaXZlcnMv Y2hhci9pcG1pL3NzaWZfYm1jLmgKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAw MDAwMDAwMC4uYTJlZTA5MDU3MmRiCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvY2hh ci9pcG1pL3NzaWZfYm1jLmgKPiBAQCAtMCwwICsxLDkyIEBACj4gKy8qIFNQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBHUEwtMi4wKyAqLwo+ICsvKgo+ICsgKiBUaGUgZHJpdmVyIGZvciBCTUMgc2lk ZSBvZiBTU0lGIGludGVyZmFjZQo+ICsgKgo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMjEsIEFtcGVy ZSBDb21wdXRpbmcgTExDCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJl OyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKPiArICogbW9kaWZ5IGl0IHVuZGVyIHRo ZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMKPiArICogcHVibGlz aGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YK PiArICogdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24u Cj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0 IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhv dXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJVFkgb3Ig RklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdOVSBHZW5l cmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlvdSBzaG91 bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNl Cj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLiAgSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3 LmdudS5vcmcvbGljZW5zZXMvPi4KPiArICovCj4gKyNpZm5kZWYgX19TU0lGX0JNQ19IX18KPiAr I2RlZmluZSBfX1NTSUZfQk1DX0hfXwo+ICsKPiArI2RlZmluZSBERVZJQ0VfTkFNRQkJCQkiaXBt aS1zc2lmLWhvc3QiCj4gKwo+ICsjZGVmaW5lIEdFVF84QklUX0FERFIoYWRkcl83Yml0KQkJKCgo YWRkcl83Yml0KSA8PCAxKSAmIDB4ZmYpCj4gKwo+ICsjZGVmaW5lIE1TR19QQVlMT0FEX0xFTl9N QVgJCQkyNTIKPiArCj4gKy8qIEEgc3RhbmRhcmQgU01CdXMgVHJhbnNhY3Rpb24gaXMgbGltaXRl ZCB0byAzMiBkYXRhIGJ5dGVzICovCj4gKyNkZWZpbmUgTUFYX1BBWUxPQURfUEVSX1RSQU5TQUNU SU9OCQkzMgo+ICsKPiArI2RlZmluZSBNQVhfSVBNSV9EQVRBX1BFUl9TVEFSVF9UUkFOU0FDVElP TgkzMAo+ICsjZGVmaW5lIE1BWF9JUE1JX0RBVEFfUEVSX01JRERMRV9UUkFOU0FDVElPTgkzMQo+ ICsKPiArI2RlZmluZSBTU0lGX0lQTUlfU0lOR0xFUEFSVF9XUklURQkJMHgyCj4gKyNkZWZpbmUg U1NJRl9JUE1JX1NJTkdMRVBBUlRfUkVBRAkJMHgzCj4gKyNkZWZpbmUgU1NJRl9JUE1JX01VTFRJ UEFSVF9XUklURV9TVEFSVAkJMHg2Cj4gKyNkZWZpbmUgU1NJRl9JUE1JX01VTFRJUEFSVF9XUklU RV9NSURETEUJMHg3Cj4gKyNkZWZpbmUgU1NJRl9JUE1JX01VTFRJUEFSVF9XUklURV9FTkQJCTB4 OAo+ICsjZGVmaW5lIFNTSUZfSVBNSV9NVUxUSVBBUlRfUkVBRF9TVEFSVAkJMHgzCj4gKyNkZWZp bmUgU1NJRl9JUE1JX01VTFRJUEFSVF9SRUFEX01JRERMRQkJMHg5Cj4gKwo+ICtzdHJ1Y3Qgc3Np Zl9tc2cgewo+ICsJdTggbGVuOwo+ICsJdTggbmV0Zm5fbHVuOwo+ICsJdTggY21kOwo+ICsJdTgg cGF5bG9hZFtNU0dfUEFZTE9BRF9MRU5fTUFYXTsKPiArfSBfX3BhY2tlZDsKPiArCj4gK3N0YXRp YyBpbmxpbmUgdTMyIHNzaWZfbXNnX2xlbihzdHJ1Y3Qgc3NpZl9tc2cgKnNzaWZfbXNnKQo+ICt7 Cj4gKwlyZXR1cm4gc3NpZl9tc2ctPmxlbiArIDE7Cj4gK30KPiArCj4gKyNkZWZpbmUgU1NJRl9C TUNfQlVTWSAgIDB4MDEKPiArI2RlZmluZSBTU0lGX0JNQ19SRUFEWSAgMHgwMgo+ICsKPiArc3Ry dWN0IHNzaWZfYm1jX2N0eCB7Cj4gKwlzdHJ1Y3QgaTJjX2NsaWVudAkqY2xpZW50Owo+ICsJc3Ry dWN0IG1pc2NkZXZpY2UJbWlzY2RldjsKPiArCXU4CQkJc21idXNfY21kOwo+ICsJc3RydWN0IHNz aWZfbXNnCQlyZXF1ZXN0Owo+ICsJYm9vbAkJCXJlcXVlc3RfYXZhaWxhYmxlOwo+ICsJc3RydWN0 IHNzaWZfbXNnCQlyZXNwb25zZTsKPiArCWJvb2wJCQlyZXNwb25zZV9pbl9wcm9ncmVzczsKPiAr CS8qIFJlc3BvbnNlIGJ1ZmZlciBmb3IgTXVsdGktcGFydCBSZWFkIFRyYW5zYWN0aW9uICovCj4g Kwl1OAkJCXJlc3BvbnNlX2J1ZltNQVhfUEFZTE9BRF9QRVJfVFJBTlNBQ1RJT05dOwo+ICsJLyog RmxhZyB0byBpZGVudGlmeSBhIE11bHRpLXBhcnQgUmVhZCBUcmFuc2FjdGlvbiAqLwo+ICsJYm9v bAkJCWlzX3NpbmdsZXBhcnRfcmVhZDsKPiArCXU4CQkJbmJ5dGVzX3Byb2Nlc3NlZDsKPiArCXU4 CQkJcmVtYWluX2xlbjsKPiArCXU4CQkJcmVjdl9sZW47Cj4gKwkvKiBCbG9jayBOdW1iZXIgb2Yg YSBNdWx0aS1wYXJ0IFJlYWQgVHJhbnNhY3Rpb24gKi8KPiArCXU4CQkJYmxvY2tfbnVtOwo+ICsJ c2l6ZV90CQkJbXNnX2lkeDsKPiArCWVudW0gaTJjX3NsYXZlX2V2ZW50CWxhc3RfZXZlbnQ7Cj4g Kwlib29sCQkJcGVjX3N1cHBvcnQ7Cj4gKwlzcGlubG9ja190CQlsb2NrOwo+ICsJd2FpdF9xdWV1 ZV9oZWFkX3QJd2FpdF9xdWV1ZTsKPiArCXN0cnVjdCBtdXRleAkJZmlsZV9tdXRleDsKPiArCXZv aWQgKCpzZXRfc3NpZl9ibWNfc3RhdHVzKShzdHJ1Y3Qgc3NpZl9ibWNfY3R4ICpzc2lmX2JtYywg dW5zaWduZWQgaW50IGZsYWdzKTsKPiArCXZvaWQJCQkqcHJpdjsKPiArfTsKPiArCj4gK3N0YXRp YyBpbmxpbmUgc3RydWN0IHNzaWZfYm1jX2N0eCAqdG9fc3NpZl9ibWMoc3RydWN0IGZpbGUgKmZp bGUpCj4gK3sKPiArCXJldHVybiBjb250YWluZXJfb2YoZmlsZS0+cHJpdmF0ZV9kYXRhLCBzdHJ1 Y3Qgc3NpZl9ibWNfY3R4LCBtaXNjZGV2KTsKPiArfQo+ICsKPiArc3RydWN0IHNzaWZfYm1jX2N0 eCAqc3NpZl9ibWNfYWxsb2Moc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCwgaW50IHNpemVvZl9w cml2KTsKPiArCj4gKyNlbmRpZiAvKiBfX1NTSUZfQk1DX0hfXyAqLwo+IGRpZmYgLS1naXQgYS9k cml2ZXJzL2NoYXIvaXBtaS9zc2lmX2JtY19hc3BlZWQuYyBiL2RyaXZlcnMvY2hhci9pcG1pL3Nz aWZfYm1jX2FzcGVlZC5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAw MDAuLmE1NjNmY2ZmNWFjYwo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2NoYXIvaXBt aS9zc2lmX2JtY19hc3BlZWQuYwo+IEBAIC0wLDAgKzEsMTMyIEBACj4gKy8vIFNQRFgtTGljZW5z ZS1JZGVudGlmaWVyOiBHUEwtMi4wKwo+ICsvKgo+ICsgKiBUaGUgZHJpdmVyIGZvciBCTUMgc2lk ZSBvZiBBc3BlZWQgU1NJRiBpbnRlcmZhY2UKPiArICoKPiArICogQ29weXJpZ2h0IChjKSAyMDIx LCBBbXBlcmUgQ29tcHV0aW5nIExMQwo+ICsgKgo+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBz b2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCj4gKyAqIG1vZGlmeSBpdCB1 bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzCj4gKyAq IHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lv biAyIG9mCj4gKyAqIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2 ZXJzaW9uLgo+ICsgKgo+ICsgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhv cGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPiArICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZ OyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKPiArICogTUVSQ0hBTlRBQklM SVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQo+ICsgKiBH TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgo+ICsgKgo+ICsgKiBZ b3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMg TGljZW5zZQo+ICsgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4gIElmIG5vdCwgc2VlIDxodHRw czovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uCj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4 L2kyYy5oPgo+ICsjaW5jbHVkZSA8bGludXgvbWlzY2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9pb3BvbGwuaD4KPiArCj4gKyNpbmNsdWRlICJzc2lmX2JtYy5oIgo+ICsKPiArc3RydWN0IGFz cGVlZF9pMmNfYnVzIHsKPiArCXN0cnVjdCBpMmNfYWRhcHRlciAgICAgICAgICAgICAgYWRhcDsK PiArCXN0cnVjdCBkZXZpY2UgICAgICAgICAgICAgICAgICAgKmRldjsKPiArCXZvaWQgX19pb21l bSAgICAgICAgICAgICAgICAgICAgKmJhc2U7Cj4gKwlzdHJ1Y3QgcmVzZXRfY29udHJvbCAgICAg ICAgICAgICpyc3Q7Cj4gKwkvKiBTeW5jaHJvbml6ZXMgSS9PIG1lbSBhY2Nlc3MgdG8gYmFzZS4g Ki8KPiArCXNwaW5sb2NrX3QgICAgICAgICAgICAgICAgICAgICAgbG9jazsKPiArfTsKPiArCj4g KyNkZWZpbmUgQVNQRUVEX0kyQ19JTlRSX0NUUkxfUkVHCTB4MGMKPiArI2RlZmluZSBBU1BFRURf STJDRF9JTlRSX1NMQVZFX01BVENICUJJVCg3KQo+ICsjZGVmaW5lIEFTUEVFRF9JMkNEX0lOVFJf UlhfRE9ORQlCSVQoMikKPiArc3RhdGljIHZvaWQgYXNwZWVkX2kyY19lbmFibGVfaW50ZXJydXB0 KHN0cnVjdCBhc3BlZWRfaTJjX2J1cyAqYnVzLCB1bnNpZ25lZCBsb25nIG1hc2spCj4gK3sKPiAr CXVuc2lnbmVkIGxvbmcgY3VycmVudF9tYXNrOwo+ICsKPiArCWN1cnJlbnRfbWFzayA9IHJlYWRs KGJ1cy0+YmFzZSArIEFTUEVFRF9JMkNfSU5UUl9DVFJMX1JFRyk7Cj4gKwl3cml0ZWwoY3VycmVu dF9tYXNrIHwgbWFzaywgYnVzLT5iYXNlICsgQVNQRUVEX0kyQ19JTlRSX0NUUkxfUkVHKTsKPiAr fQo+ICsKPiArc3RhdGljIHZvaWQgYXNwZWVkX2kyY19kaXNhYmxlX2ludGVycnVwdChzdHJ1Y3Qg YXNwZWVkX2kyY19idXMgKmJ1cywgdW5zaWduZWQgbG9uZyBtYXNrKQo+ICt7Cj4gKwl1bnNpZ25l ZCBsb25nIGN1cnJlbnRfbWFzazsKPiArCj4gKwljdXJyZW50X21hc2sgPSByZWFkbChidXMtPmJh c2UgKyBBU1BFRURfSTJDX0lOVFJfQ1RSTF9SRUcpOwo+ICsJd3JpdGVsKGN1cnJlbnRfbWFzayAm IH5tYXNrLCBidXMtPmJhc2UgKyBBU1BFRURfSTJDX0lOVFJfQ1RSTF9SRUcpOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgdm9pZCBhc3BlZWRfc2V0X3NzaWZfYm1jX3N0YXR1cyhzdHJ1Y3Qgc3NpZl9ibWNf Y3R4ICpzc2lmX2JtYywgdW5zaWduZWQgaW50IHN0YXR1cykKPiArewo+ICsJc3RydWN0IGFzcGVl ZF9pMmNfYnVzICpidXM7Cj4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsKPiArCWJ1cyA9IChz dHJ1Y3QgYXNwZWVkX2kyY19idXMgKilzc2lmX2JtYy0+cHJpdjsKPiArCWlmICghYnVzKQo+ICsJ CXJldHVybjsKPiArCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmYnVzLT5sb2NrLCBmbGFncyk7CgpU cnlpbmcgdG8gdGFrZSB0aGlzIHNwaW5sb2NrIGNhbm5vdCBzdWNjZWVkIGFzIGl0cyBhbHJlYWR5 IHRha2VuIGJ5IHRoaXMKcG9pbnQuCgpUaGUgY29tbWFuZCBzZW50IG92ZXIgSTJDIHRvIHRyaWdn ZXIgdGhpcyBpcwoKMjAgMDIgMEMgMkMgMDIgQUUgMDAgMDAgMDAgMDAgMDAgMDAgMDAgMDAgMDAg NDYKCkNPTkZJR19TUElOTE9DS19ERUJVRyBvdXRwdXQgYmVsb3cuIE9idmlvdXNseSB0aGlzIGRl YWRsb2NrcyB0aGUga2VybmVsLgoKcm9vdEBudXZpYW1hY2hpbmUxOn4jIFsgICAzOC43OTAwMzFd IEJVRzogc3BpbmxvY2sgcmVjdXJzaW9uIG9uIENQVSMwLApzd2FwcGVyLzAvMApbICAgMzguNzk2 MDg1XSAgbG9jazogMHg4MTE0YzMzYywgLm1hZ2ljOiBkZWFkNGVhZCwgLm93bmVyOiBzd2FwcGVy LzAvMCwKLm93bmVyX2NwdTogMApbICAgMzguODA0NjM3XSBDUFU6IDAgUElEOiAwIENvbW06IHN3 YXBwZXIvMCBOb3QgdGFpbnRlZAo1LjEwLjMwLTUxZTRkNWEtZGlydHktNjAxYzMwZS0wMDE2NC1n NDYzZWNhYTk1N2YwICM3ClsgICAzOC44MTU0MTBdIEhhcmR3YXJlIG5hbWU6IEdlbmVyaWMgRFQg YmFzZWQgc3lzdGVtClsgICAzOC44MjA3NTZdIEJhY2t0cmFjZTogClsgICAzOC44MjM1MDJdIFs8 ODA4ZTk0MDg+XSAoZHVtcF9iYWNrdHJhY2UpIGZyb20gWzw4MDhlOTY2ND5dCihzaG93X3N0YWNr KzB4MjAvMHgyNCkKWyAgIDM4LjgzMTk1NV0gIHI3Ojg1NTM2MmEwIHI2OjYwMGYwMTkzIHI1OjAw MDAwMDAwIHI0OjgwY2EzNTkwClsgICAzOC44MzgyNzddIFs8ODA4ZTk2NDQ+XSAoc2hvd19zdGFj aykgZnJvbSBbPDgwOGY0NWI0Pl0KKGR1bXBfc3RhY2srMHhhMC8weGI0KQpbICAgMzguODQ2MzQy XSBbPDgwOGY0NTE0Pl0gKGR1bXBfc3RhY2spIGZyb20gWzw4MDhlYTQxOD5dCihzcGluX2R1bXAr MHg5MC8weDk4KQpbICAgMzguODU0MzA3XSAgcjc6ODU1MzYyYTAgcjY6ODExNGMzM2MgcjU6ODBj MTA0MDAgcjQ6ODExNGMzM2MKWyAgIDM4Ljg2MDYyN10gWzw4MDhlYTM4OD5dIChzcGluX2R1bXAp IGZyb20gWzw4MDE3MTA0ND5dCihkb19yYXdfc3Bpbl9sb2NrKzB4MTJjLzB4MTMwKQpbICAgMzgu ODY5MzY1XSAgcjU6ZmZmZmUwMDAgcjQ6ODExNGMzM2MKWyAgIDM4Ljg3MzM2MF0gWzw4MDE3MGYx OD5dIChkb19yYXdfc3Bpbl9sb2NrKSBmcm9tIFs8ODA4ZmI2Mjg+XQooX3Jhd19zcGluX2xvY2tf aXJxc2F2ZSsweDIwLzB4MjgpClsgICAzOC44ODMxNjVdICByNTowMDAwMDAwMSByNDphMDBmMDE5 MwpbICAgMzguODg3MTYyXSBbPDgwOGZiNjA4Pl0gKF9yYXdfc3Bpbl9sb2NrX2lycXNhdmUpIGZy b20gWzw4MDUxMzY0OD5dCihhc3BlZWRfc2V0X3NzaWZfYm1jX3N0YXR1cysweDMwLzB4YmMpClsg ICAzOC44OTc5MzddICByNTowMDAwMDAwMSByNDo4MTE0YzA0MApbICAgMzguOTAxOTMxXSBbPDgw NTEzNjE4Pl0gKGFzcGVlZF9zZXRfc3NpZl9ibWNfc3RhdHVzKSBmcm9tCls8ODA1MTJiMDA+XSAo c3NpZl9ibWNfY2IrMHgxYzQvMHg2OTgpClsgICAzOC45MTE4MzVdICByNzo4NTUzNjJhMCByNjo4 NTUzNjA2YyByNTowMDAwMDAwNCByNDo4NTUzNjA0MApbICAgMzguOTE4MTU4XSBbPDgwNTEyOTNj Pl0gKHNzaWZfYm1jX2NiKSBmcm9tIFs8ODA2N2U2NDg+XQooYXNwZWVkX2kyY19zbGF2ZV9pcnEr MHhiOC8weDI2NCkKWyAgIDM4LjkyNzM4Nl0gIHIxMDo4MGMwMDAwMCByOTo4MGMwYTUxNCByODow MDAwMDAxMCByNzo4NTU0NTAwMApyNjowMDAwMDAxMCByNTowMDAwMDAxMApbICAgMzguOTM2MTIy XSAgcjQ6ODExNGMwNDAKWyAgIDM4LjkzODk1Ml0gWzw4MDY3ZTU5MD5dIChhc3BlZWRfaTJjX3Ns YXZlX2lycSkgZnJvbSBbPDgwNjdlZDY4Pl0KKGFzcGVlZF9pMmNfYnVzX2lycSsweGQwLzB4MTU0 KQpbICAgMzguOTQ4ODU1XSAgcjc6ODExNGMzM2MgcjY6MDAwMDAwMTAgcjU6ODExZTEwNmMgcjQ6 ODExNGMwNDAKWyAgIDM4Ljk1NTE3NV0gWzw4MDY3ZWM5OD5dIChhc3BlZWRfaTJjX2J1c19pcnEp IGZyb20gWzw4MDE3YWUzYz5dCihfX2hhbmRsZV9pcnFfZXZlbnRfcGVyY3B1KzB4NjgvMHgyMDQp ClsgICAzOC45NjU1NjhdICByMTA6ODBjMDAwMDAgcjk6ODBjMGE1MTQgcjg6MDAwMDAwMzAgcjc6 ODBjMDFlMjAKcjY6MDAwMDAwMDAgcjU6ODExZTEwNmMKWyAgIDM4Ljk3NDMwNV0gIHI0Ojg1NTQ2 OGMwIHIzOjgwNjdlYzk4ClsgICAzOC45NzgyOTldIFs8ODAxN2FkZDQ+XSAoX19oYW5kbGVfaXJx X2V2ZW50X3BlcmNwdSkgZnJvbQpbPDgwMTdiMDE4Pl0gKGhhbmRsZV9pcnFfZXZlbnRfcGVyY3B1 KzB4NDAvMHhhMCkKWyAgIDM4Ljk4OTA3N10gIHIxMDoxMGM1Mzg3ZCByOTo4MGMwMDAwMCByODo4 MTA0MjgwMCByNzowMDAwMDAwMApyNjo4MTFlMTA2YyByNTo4MTFlMTA2YwpbICAgMzguOTk3ODE0 XSAgcjQ6ODExZTEwMDAKWyAgIDM5LjAwMDY0NF0gWzw4MDE3YWZkOD5dIChoYW5kbGVfaXJxX2V2 ZW50X3BlcmNwdSkgZnJvbSBbPDgwMTdiMGMwPl0KKGhhbmRsZV9pcnFfZXZlbnQrMHg0OC8weDZj KQpbICAgMzkuMDEwNTQ2XSAgcjU6ODExZTEwNmMgcjQ6ODExZTEwMDAKWyAgIDM5LjAxNDUzOV0g Wzw4MDE3YjA3OD5dIChoYW5kbGVfaXJxX2V2ZW50KSBmcm9tIFs8ODAxODAwMzA+XQooaGFuZGxl X2Zhc3Rlb2lfaXJxKzB4YzgvMHgxNzApClsgICAzOS4wMjQwNTZdICByNzowMDAwMDAwMCByNjo4 MGMwYWMxNCByNTo4MTFlMTA2YyByNDo4MTFlMTAwMApbICAgMzkuMDMwMzc2XSBbPDgwMTdmZjY4 Pl0gKGhhbmRsZV9mYXN0ZW9pX2lycSkgZnJvbSBbPDgwMTdhNDI4Pl0KKGdlbmVyaWNfaGFuZGxl X2lycSsweDQwLzB4NTQpClsgICAzOS4wMzk5ODldICByNzowMDAwMDAwMCByNjowMDAwMDAwMSBy NTowMDAwMDAwMCByNDo4MGI2YzgwYwpbICAgMzkuMDQ2MzEyXSBbPDgwMTdhM2U4Pl0gKGdlbmVy aWNfaGFuZGxlX2lycSkgZnJvbSBbPDgwMTdhNGE4Pl0KKF9faGFuZGxlX2RvbWFpbl9pcnErMHg2 Yy8weGMwKQpbICAgMzkuMDU2MDI4XSBbPDgwMTdhNDNjPl0gKF9faGFuZGxlX2RvbWFpbl9pcnEp IGZyb20gWzw4MDEwMTM0Yz5dCihnaWNfaGFuZGxlX2lycSsweDdjLzB4OTApClsgICAzOS4wNjUz NTNdICByOTo4MGMwMDAwMCByODpiZjgwMjAwYyByNzo4MGI2YmRjYyByNjpiZjgwMjAwMApyNTo4 MGMwMWVlMCByNDo4MGMwYWMxNApbICAgMzkuMDczOTk4XSBbPDgwMTAxMmQwPl0gKGdpY19oYW5k bGVfaXJxKSBmcm9tIFs8ODAxMDBiMGM+XQooX19pcnFfc3ZjKzB4NmMvMHg5MCkKWyAgIDM5LjA4 MjM0MF0gRXhjZXB0aW9uIHN0YWNrKDB4ODBjMDFlZTAgdG8gMHg4MGMwMWYyOCkKWyAgIDM5LjA4 Nzk4MV0gMWVlMDogMDAwMDAwMDAgMDAwMDlhMTQgYmQ3ZGM0ODQgODAxMWE3NDAgODBjMDAwMDAK MDAwMDAwMDAgODBjMGE1MTQgODBjMGE1NTAKWyAgIDM5LjA5NzExMV0gMWYwMDogODBjYTdmNWIg ODBhMGVhNTggMTBjNTM4N2QgODBjMDFmM2MgODBjMDFmNDAKODBjMDFmMzAgODAxMDkwN2MgODAx MDkwODAKWyAgIDM5LjEwNjIzN10gMWYyMDogNjAwZjAwMTMgZmZmZmZmZmYKWyAgIDM5LjExMDEz MF0gIHI5OjgwYzAwMDAwIHI4OjgwY2E3ZjViIHI3OjgwYzAxZjE0IHI2OmZmZmZmZmZmCnI1OjYw MGYwMDEzIHI0OjgwMTA5MDgwClsgICAzOS4xMTg3NzNdIFs8ODAxMDkwMzg+XSAoYXJjaF9jcHVf aWRsZSkgZnJvbSBbPDgwOGZiNGM4Pl0KKGRlZmF1bHRfaWRsZV9jYWxsKzB4MzgvMHgxMDgpClsg ICAzOS4xMjc5MDddIFs8ODA4ZmI0OTA+XSAoZGVmYXVsdF9pZGxlX2NhbGwpIGZyb20gWzw4MDE1 NjEyOD5dCihkb19pZGxlKzB4ZTQvMHgxNTApClsgICAzOS4xMzY0NTddIFs8ODAxNTYwNDQ+XSAo ZG9faWRsZSkgZnJvbSBbPDgwMTU2NDc4Pl0KKGNwdV9zdGFydHVwX2VudHJ5KzB4MjgvMHgyYykK WyAgIDM5LjE0NDkwOF0gIHI5OjhmZmZmNTY0IHI4OjgwYjNiYTZjIHI3OjAwMDAwMDAwIHI2Ojgw Y2M3MDAwCnI1OjAwMDAwMDAxIHI0OjAwMDAwMGQ4ClsgICAzOS4xNTM1NDVdIFs8ODAxNTY0NTA+ XSAoY3B1X3N0YXJ0dXBfZW50cnkpIGZyb20gWzw4MDhmNGYxMD5dCihyZXN0X2luaXQrMHhiYy8w eGM0KQpbICAgMzkuMTYyMTkyXSBbPDgwOGY0ZTU0Pl0gKHJlc3RfaW5pdCkgZnJvbSBbPDgwYjAw Yzk0Pl0KKGFyY2hfY2FsbF9yZXN0X2luaXQrMHgxOC8weDFjKQpbICAgMzkuMTcxMDI3XSAgcjU6 MDAwMDAwMDEgcjQ6ODBjYzcwNDAKWyAgIDM5LjE3NTAxN10gWzw4MGIwMGM3Yz5dIChhcmNoX2Nh bGxfcmVzdF9pbml0KSBmcm9tIFs8ODBiMDEyNGM+XQooc3RhcnRfa2VybmVsKzB4NTNjLzB4NTg0 KQpbICAgMzkuMTg0MzMwXSBbPDgwYjAwZDEwPl0gKHN0YXJ0X2tlcm5lbCkgZnJvbSBbPDAwMDAw MDAwPl0gKDB4MCkKCgo+ICsKPiArCWlmIChzdGF0dXMgJiBTU0lGX0JNQ19CVVNZKSB7Cj4gKwkJ LyogSWdub3JlIFJYX0RPTkUgYW5kIFNMQVZFX01BVENIIHdoZW4gc2xhdmUgYnVzeSBwcm9jZXNz aW5nICovCj4gKwkJYXNwZWVkX2kyY19kaXNhYmxlX2ludGVycnVwdChidXMsIEFTUEVFRF9JMkNE X0lOVFJfUlhfRE9ORSk7Cj4gKwkJYXNwZWVkX2kyY19kaXNhYmxlX2ludGVycnVwdChidXMsIEFT UEVFRF9JMkNEX0lOVFJfU0xBVkVfTUFUQ0gpOwo+ICsJfSBlbHNlIGlmIChzdGF0dXMgJiBTU0lG X0JNQ19SRUFEWSkgewo+ICsJCS8qIEVuYWJsZSBSWF9ET05FIGFuZCBTTEFWRV9NQVRDSCB3aGVu IHNsYXZlIHJlYWR5ICovCj4gKwkJYXNwZWVkX2kyY19lbmFibGVfaW50ZXJydXB0KGJ1cywgQVNQ RUVEX0kyQ0RfSU5UUl9SWF9ET05FKTsKPiArCQlhc3BlZWRfaTJjX2VuYWJsZV9pbnRlcnJ1cHQo YnVzLCBBU1BFRURfSTJDRF9JTlRSX1NMQVZFX01BVENIKTsKPiArCX0KPiArCj4gKwlzcGluX3Vu bG9ja19pcnFyZXN0b3JlKCZidXMtPmxvY2ssIGZsYWdzKTsKPiArfQo+ICsKPiArc3RhdGljIGlu dCBzc2lmX2JtY19wcm9iZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50LCBjb25zdCBzdHJ1Y3Qg aTJjX2RldmljZV9pZCAqaWQpCj4gK3sKPiArCXN0cnVjdCBzc2lmX2JtY19jdHggKnNzaWZfYm1j Owo+ICsKPiArCXNzaWZfYm1jID0gc3NpZl9ibWNfYWxsb2MoY2xpZW50LCBzaXplb2Yoc3RydWN0 IGFzcGVlZF9pMmNfYnVzKSk7Cj4gKwlpZiAoSVNfRVJSKHNzaWZfYm1jKSkKPiArCQlyZXR1cm4g UFRSX0VSUihzc2lmX2JtYyk7Cj4gKwo+ICsJc3NpZl9ibWMtPnByaXYgPSBpMmNfZ2V0X2FkYXBk YXRhKGNsaWVudC0+YWRhcHRlcik7Cj4gKwlzc2lmX2JtYy0+c2V0X3NzaWZfYm1jX3N0YXR1cyA9 IGFzcGVlZF9zZXRfc3NpZl9ibWNfc3RhdHVzOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHNzaWZfYm1jX3JlbW92ZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50KQo+ ICt7Cj4gKwlzdHJ1Y3Qgc3NpZl9ibWNfY3R4ICpzc2lmX2JtYyA9IGkyY19nZXRfY2xpZW50ZGF0 YShjbGllbnQpOwo+ICsKPiArCWkyY19zbGF2ZV91bnJlZ2lzdGVyKGNsaWVudCk7Cj4gKwltaXNj X2RlcmVnaXN0ZXIoJnNzaWZfYm1jLT5taXNjZGV2KTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgc3NpZl9ibWNfbWF0Y2hbXSA9 IHsKPiArCXsgLmNvbXBhdGlibGUgPSAiYXNwZWVkLGFzdDI1MDAtc3NpZi1ibWMiIH0sCj4gKwl7 IH0sCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGkyY19kZXZpY2VfaWQgc3NpZl9i bWNfaWRbXSA9IHsKPiArCXsgREVWSUNFX05BTUUsIDAgfSwKPiArCXsgfSwKPiArfTsKPiArCj4g K01PRFVMRV9ERVZJQ0VfVEFCTEUoaTJjLCBzc2lmX2JtY19pZCk7Cj4gKwo+ICtzdGF0aWMgc3Ry dWN0IGkyY19kcml2ZXIgc3NpZl9ibWNfZHJpdmVyID0gewo+ICsJLmRyaXZlcgkJPSB7Cj4gKwkJ Lm5hbWUJCT0gREVWSUNFX05BTUUsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gc3NpZl9ibWNfbWF0 Y2gsCj4gKwl9LAo+ICsJLnByb2JlCQk9IHNzaWZfYm1jX3Byb2JlLAo+ICsJLnJlbW92ZQkJPSBz c2lmX2JtY19yZW1vdmUsCj4gKwkuaWRfdGFibGUJPSBzc2lmX2JtY19pZCwKPiArfTsKPiArCj4g K21vZHVsZV9pMmNfZHJpdmVyKHNzaWZfYm1jX2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfQVVUSE9S KCJDaHVvbmcgVHJhbiA8Y2h1b25nQG9zLmFtcGVyZWNvbXB1dGluZy5jb20+Iik7Cj4gK01PRFVM RV9BVVRIT1IoIlF1YW4gTmd1eWVuIDxxdWFuQG9zLmFtcGVyZWNvbXB1dGluZy5jb20+Iik7Cj4g K01PRFVMRV9ERVNDUklQVElPTigiTGludXggZGV2aWNlIGRyaXZlciBvZiBBc3BlZWQgQk1DIElQ TUkgU1NJRiBpbnRlcmZhY2UuIik7Cj4gK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKPiAtLSAK PiAyLjI4LjAKPiAKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMu aW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZv L2xpbnV4LWFybS1rZXJuZWwK