* [PATCH 1/2] powerpc/dma/raidengine: add raidengine device
@ 2012-11-21 9:01 b29237
2012-11-21 9:01 ` [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device b29237
2012-11-25 13:21 ` [PATCH 1/2] powerpc/dma/raidengine: add raidengine device Kumar Gala
0 siblings, 2 replies; 4+ messages in thread
From: b29237 @ 2012-11-21 9:01 UTC (permalink / raw)
To: dan.j.williams, vinod.koul, linuxppc-dev, linux-kernel
Cc: Harninder Rai, Xuelin Shi, Naveen Burmi, iws
From: Xuelin Shi <b29237@freescale.com>
The RaidEngine is a new Freescale hardware that used for parity
computation offloading in RAID5/6.
This patch adds the device node in device tree and related binding
documentation.
Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Xuelin Shi <b29237@freescale.com>
---
.../devicetree/bindings/powerpc/fsl/raideng.txt | 81 +++++++++++++++++++
arch/powerpc/boot/dts/fsl/p5020si-post.dtsi | 1 +
arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi | 6 ++
arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi | 85 ++++++++++++++++++++
4 files changed, 173 insertions(+)
create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
new file mode 100644
index 0000000..4ad29b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
@@ -0,0 +1,81 @@
+* Freescale 85xx RAID Engine nodes
+
+RAID Engine nodes are defined to describe on-chip RAID accelerators. Each RAID
+Engine should have a separate node.
+
+Supported chips:
+P5020, P5040
+
+Required properties:
+
+- compatible: Should contain "fsl,raideng-v1.0" as the value
+ This identifies RAID Engine block. 1 in 1.0 represents
+ major number whereas 0 represents minor number. The
+ version matches the hardware IP version.
+- reg: offset and length of the register set for the device
+- ranges: standard ranges property specifying the translation
+ between child address space and parent address space
+
+Example:
+ /* P5020 */
+ raideng: raideng@320000 {
+ compatible = "fsl,raideng-v1.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x320000 0x10000>;
+ ranges = <0 0x320000 0x10000>;
+ };
+
+
+There must be a sub-node for each job queue present in RAID Engine
+This node must be a sub-node of the main RAID Engine node
+
+- compatible: Should contain "fsl,raideng-v1.0-job-queue" as the value
+ This identifies the job queue interface
+- reg: offset and length of the register set for job queue
+- ranges: standard ranges property specifying the translation
+ between child address space and parent address space
+
+Example:
+ /* P5020 */
+ raideng_jq0@1000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ reg = <0x1000 0x1000>;
+ ranges = <0x0 0x1000 0x1000>;
+ };
+
+
+There must be a sub-node for each job ring present in RAID Engine
+This node must be a sub-node of job queue node
+
+- compatible: Must contain "fsl,raideng-v1.0-job-ring" as the value
+ This identifies job ring. Should contain either
+ "fsl,raideng-v1.0-hp-ring" or "fsl,raideng-v1.0-lp-ring"
+ depending upon whether ring has high or low priority
+- reg: offset and length of the register set for job ring
+- interrupts: interrupt mapping for job ring IRQ
+
+Optional property:
+
+- fsl,liodn: Specifies the LIODN to be used for Job Ring. This
+ property is normally set by firmware. Value
+ is of 12-bits which is the LIODN number for this JR.
+ This property is used by the IOMMU (PAMU) to distinquish
+ transactions from this JR and than be able to do address
+ translation & protection accordingly.
+
+Example:
+ /* P5020 */
+ raideng_jq0@1000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ reg = <0x1000 0x1000>;
+ ranges = <0x0 0x1000 0x1000>;
+
+ raideng_jr0: jr@0 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+ reg = <0x0 0x400>;
+ interrupts = <139 2 0 0>;
+ interrupt-parent = <&mpic>;
+ fsl,liodn = <0x41>;
+ };
+ };
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
index 64b6abe..5d7205b 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
@@ -354,4 +354,5 @@
/include/ "qoriq-sata2-0.dtsi"
/include/ "qoriq-sata2-1.dtsi"
/include/ "qoriq-sec4.2-0.dtsi"
+/include/ "qoriq-raid1.0-0.dtsi"
};
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
index 0a198b0..8df47fc 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
@@ -73,6 +73,12 @@
rtic_c = &rtic_c;
rtic_d = &rtic_d;
sec_mon = &sec_mon;
+
+ raideng = &raideng;
+ raideng_jr0 = &raideng_jr0;
+ raideng_jr1 = &raideng_jr1;
+ raideng_jr2 = &raideng_jr2;
+ raideng_jr3 = &raideng_jr3;
};
cpus {
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
new file mode 100644
index 0000000..8d2e8aa
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
@@ -0,0 +1,85 @@
+/*
+ * QorIQ RAID 1.0 device tree stub [ controller @ offset 0x320000 ]
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+raideng: raideng@320000 {
+ compatible = "fsl,raideng-v1.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x320000 0x10000>;
+ ranges = <0 0x320000 0x10000>;
+
+ raideng_jq0@1000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1000 0x1000>;
+ ranges = <0x0 0x1000 0x1000>;
+
+ raideng_jr0: jr@0 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+ reg = <0x0 0x400>;
+ interrupts = <139 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ raideng_jr1: jr@400 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+ reg = <0x400 0x400>;
+ interrupts = <140 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+ };
+
+ raideng_jq1@2000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2000 0x1000>;
+ ranges = <0x0 0x2000 0x1000>;
+
+ raideng_jr2: jr@0 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+ reg = <0x0 0x400>;
+ interrupts = <141 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ raideng_jr3: jr@400 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+ reg = <0x400 0x400>;
+ interrupts = <142 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+ };
+};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device
2012-11-21 9:01 [PATCH 1/2] powerpc/dma/raidengine: add raidengine device b29237
@ 2012-11-21 9:01 ` b29237
2013-04-10 5:07 ` Shi Xuelin-B29237
2012-11-25 13:21 ` [PATCH 1/2] powerpc/dma/raidengine: add raidengine device Kumar Gala
1 sibling, 1 reply; 4+ messages in thread
From: b29237 @ 2012-11-21 9:01 UTC (permalink / raw)
To: dan.j.williams, vinod.koul, linuxppc-dev, linux-kernel
Cc: Harninder Rai, Xuelin Shi, Naveen Burmi, iws
From: Xuelin Shi <b29237@freescale.com>
The RaidEngine is a new FSL hardware that used as hardware acceration
for RAID5/6.
This patch enables the RaidEngine functionality and provides hardware
offloading capability for memcpy, xor and raid6 pq computation. It works
under dmaengine control with async_layer interface.
Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Xuelin Shi <b29237@freescale.com>
---
drivers/dma/Kconfig | 14 +
drivers/dma/Makefile | 1 +
drivers/dma/fsl_raid.c | 990 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/dma/fsl_raid.h | 317 ++++++++++++++++
4 files changed, 1322 insertions(+)
create mode 100644 drivers/dma/fsl_raid.c
create mode 100644 drivers/dma/fsl_raid.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..aa37279 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -320,6 +320,20 @@ config MMP_PDMA
help
Support the MMP PDMA engine for PXA and MMP platfrom.
+config FSL_RAID
+ tristate "Freescale RAID Engine Device Driver"
+ depends on FSL_SOC && !FSL_DMA
+ select DMA_ENGINE
+ select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+ select ASYNC_MEMCPY
+ select ASYNC_XOR
+ select ASYNC_PQ
+ ---help---
+ Enable support for Freescale RAID Engine. RAID Engine is
+ available on some QorIQ SoCs (like P5020). It has
+ the capability to offload RAID5/RAID6 operations from CPU.
+ RAID5 is XOR and memcpy. RAID6 is P/Q and memcpy
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7428fea..29b65eb 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
obj-$(CONFIG_MV_XOR) += mv_xor.o
obj-$(CONFIG_DW_DMAC) += dw_dmac.o
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644
index 0000000..ec19817
--- /dev/null
+++ b/drivers/dma/fsl_raid.c
@@ -0,0 +1,990 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Theory of operation:
+ *
+ * General capabilities:
+ * RAID Engine (RE) block is capable of offloading XOR, memcpy and P/Q
+ * calculations required in RAID5 and RAID6 operations. RE driver
+ * registers with Linux's ASYNC layer as dma driver. RE hardware
+ * maintains strict ordering of the requests through chained
+ * command queueing.
+ *
+ * Data flow:
+ * Software RAID layer of Linux (MD layer) maintains RAID partitions,
+ * strips, stripes etc. It sends requests to the underlying AYSNC layer
+ * which further passes it to RE driver. ASYNC layer decides which request
+ * goes to which job ring of RE hardware. For every request processed by
+ * RAID Engine, driver gets an interrupt unless coalescing is set. The
+ * per job ring interrupt handler checks the status register for errors,
+ * clears the interrupt and schedules a tasklet. Main request processing
+ * is done in tasklet. A software shadow copy of the HW ring is kept to
+ * maintain virtual to physical translation. Based on the internal indexes
+ * maintained, the tasklet picks the descriptor address from shadow copy,
+ * updates the corresponding cookie, updates the outbound ring job removed
+ * register in RE hardware and eventually calls the callback function. This
+ * callback function gets passed as part of request from MD layer.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include "fsl_raid.h"
+
+#define MAX_XOR_SRCS 16
+#define MAX_PQ_SRCS 16
+#define MAX_INITIAL_DESCS 256
+#define FRAME_FORMAT 0x1
+#define MAX_DATA_LENGTH (1024*1024)
+
+#define to_fsl_re_dma_desc(tx) container_of(tx, \
+ struct fsl_re_dma_async_tx_desc, async_tx)
+
+/* Add descriptors into per jr software queue - submit_q */
+static dma_cookie_t re_jr_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct fsl_re_dma_async_tx_desc *desc = NULL;
+ struct re_jr *jr = NULL;
+ dma_cookie_t cookie;
+
+ desc = container_of(tx, struct fsl_re_dma_async_tx_desc, async_tx);
+ jr = container_of(tx->chan, struct re_jr, chan);
+
+ spin_lock_bh(&jr->inb_lock);
+
+ jr->timer.data = (unsigned long)tx->chan;
+ cookie = jr->chan.cookie + 1;
+ if (cookie < 0)
+ cookie = 1;
+
+ desc->async_tx.cookie = cookie;
+ jr->chan.cookie = desc->async_tx.cookie;
+ jr->pend_count++;
+
+ if (!timer_pending(&jr->timer))
+ add_timer(&jr->timer);
+
+ spin_unlock_bh(&jr->inb_lock);
+
+ return cookie;
+}
+
+static void re_jr_unmap_dest_src(struct fsl_re_dma_async_tx_desc *desc)
+{
+ int i, j;
+ struct cmpnd_frame *cf;
+ dma_addr_t dest1 = 0, dest2 = 0, src;
+ struct device *dev;
+ enum dma_ctrl_flags flags;
+ enum dma_data_direction dir;
+
+ BUG_ON(!desc);
+ cf = desc->cf_addr;
+ dest1 = cf[1].address;
+ j = 2;
+ if (desc->dest_cnt == 2) {
+ dest2 = cf[2].address;
+ j = 3;
+ }
+ dev = desc->jr->chan.device->dev;
+ flags = desc->async_tx.flags;
+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ if (desc->cdb_opcode == RE_MOVE_OPCODE)
+ dir = DMA_FROM_DEVICE;
+ else
+ dir = DMA_BIDIRECTIONAL;
+
+ dma_unmap_page(dev, dest1, desc->dma_len, dir);
+
+ if (dest2)
+ dma_unmap_page(dev, dest2, desc->dma_len, dir);
+ }
+
+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ dir = DMA_TO_DEVICE;
+ for (i = j; i < desc->src_cnt+j; i++) {
+ src = cf[i].address;
+ if (src == dest1 || src == dest2)
+ continue;
+ dma_unmap_page(dev, src, desc->dma_len, dir);
+ }
+ }
+}
+
+static void re_jr_desc_done(struct fsl_re_dma_async_tx_desc *desc)
+{
+ struct re_jr *dma_jr = desc->jr;
+ dma_async_tx_callback callback;
+ void *callback_param;
+
+ callback = desc->async_tx.callback;
+ callback_param = desc->async_tx.callback_param;
+
+ dma_run_dependencies(&desc->async_tx);
+
+ if (dma_jr->completed_cookie < desc->async_tx.cookie) {
+ dma_jr->completed_cookie = desc->async_tx.cookie;
+ if (dma_jr->completed_cookie == DMA_MAX_COOKIE)
+ dma_jr->completed_cookie = DMA_MIN_COOKIE;
+ }
+
+ re_jr_unmap_dest_src(desc);
+
+ if (callback)
+ callback(callback_param);
+
+}
+
+/*
+ * Get the virtual address of software desc from virt_addr.
+ * Storing the address of software desc like this makes the
+ * order of alogorithm as O(1)
+ */
+static void re_jr_dequeue(unsigned long data)
+{
+ struct device *dev;
+ struct re_jr *jr;
+ struct fsl_re_dma_async_tx_desc *desc;
+ unsigned int count;
+ struct fsl_re_dma_async_tx_desc *ack_desc = NULL, *_ack_desc = NULL;
+
+ dev = (struct device *)data;
+ jr = dev_get_drvdata(dev);
+
+ while ((count =
+ RE_JR_OUB_SLOT_FULL(in_be32(&jr->jrregs->oubring_slot_full)))) {
+ while (count--) {
+ spin_lock_bh(&jr->oub_lock);
+ jr->oub_count &= RING_SIZE - 1;
+ desc = &jr->descs[jr->oub_count++];
+
+ /* One job processed */
+ out_be32(&jr->jrregs->oubring_job_rmvd,
+ RE_JR_OUB_JOB_REMOVE(1));
+ spin_unlock_bh(&jr->oub_lock);
+
+ spin_lock_bh(&jr->desc_lock);
+ list_add_tail(&desc->node, &jr->ack_q);
+ re_jr_desc_done(desc);
+ spin_unlock_bh(&jr->desc_lock);
+ }
+ }
+
+ /* To save memory, parse the ack_q and free up descs */
+ list_for_each_entry_safe(ack_desc, _ack_desc, &jr->ack_q, node) {
+ if (async_tx_test_ack(&ack_desc->async_tx)) {
+ spin_lock_bh(&jr->desc_lock);
+ list_del(&ack_desc->node);
+ ack_desc->state = RE_DESC_EMPTY;
+ ack_desc->async_tx.flags = 0;
+ spin_unlock_bh(&jr->desc_lock);
+ }
+ }
+}
+
+/* Per Job Ring interrupt handler */
+static irqreturn_t re_jr_interrupt(int irq, void *data)
+{
+ struct device *dev = data;
+ struct re_jr *jr = dev_get_drvdata(dev);
+ u32 irqstate, status;
+
+ irqstate = in_be32(&jr->jrregs->jr_interrupt_status);
+ if (!irqstate)
+ return IRQ_NONE;
+
+ /*
+ * There's no way in upper layer (read MD layer) to recover from
+ * error conditions except restart everything. In long term we
+ * need to do something more than just crashing
+ */
+ if (irqstate & RE_JR_ERROR) {
+ status = in_be32(&jr->jrregs->jr_status);
+ dev_err(dev, "%s: jr error irqstate: %x, status: %x\n",
+ __func__, irqstate, status);
+
+ BUG();
+ }
+
+ /* Clear interrupt */
+ out_be32(&jr->jrregs->jr_interrupt_status, RE_JR_CLEAR_INT);
+
+ tasklet_schedule(&jr->irqtask);
+
+ return IRQ_HANDLED;
+}
+
+static enum dma_status re_jr_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ struct re_jr *jr = NULL;
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+
+ jr = container_of(chan, struct re_jr, chan);
+ last_used = chan->cookie;
+ smp_mb();
+ last_complete = jr->completed_cookie;
+
+ dma_set_tx_state(txstate, last_complete, last_used, 0);
+
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+
+/* Copy descriptor from per jr software queue into hardware job ring */
+void re_jr_issue_pending(struct dma_chan *chan)
+{
+ struct re_jr *jr = NULL;
+ int avail = 0;
+
+ jr = container_of(chan, struct re_jr, chan);
+ if (timer_pending(&jr->timer))
+ del_timer_sync(&jr->timer);
+
+ spin_lock_bh(&jr->inb_lock);
+
+ avail = RE_JR_INB_SLOT_AVAIL(in_be32(&jr->jrregs->inbring_slot_avail));
+
+ if (!(avail && jr->pend_count))
+ goto out_unlock;
+
+ if (avail > jr->pend_count)
+ avail = jr->pend_count;
+
+ jr->pend_count -= avail;
+ jr->inb_count = (jr->inb_count + avail) & (RING_SIZE - 1);
+
+ /* add jobs into job ring */
+ out_be32(&jr->jrregs->inbring_add_job, RE_JR_INB_JOB_ADD(avail));
+
+out_unlock:
+ spin_unlock_bh(&jr->inb_lock);
+}
+
+/* Per Job Ring timer handler */
+static void raide_timer_handler(unsigned long data)
+{
+ struct dma_chan *chan = NULL;
+ chan = (struct dma_chan *)data;
+
+ re_jr_issue_pending(chan);
+
+ return;
+}
+
+inline void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
+ size_t length, dma_addr_t addr, bool final)
+{
+ cf[index].final = final;
+ cf[index].length = length;
+ cf[index].address = addr;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_init_desc(struct re_jr *jr,
+ struct fsl_re_dma_async_tx_desc *desc, void *cf, dma_addr_t paddr)
+{
+ desc->jr = jr;
+ desc->async_tx.tx_submit = re_jr_tx_submit;
+ dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
+ INIT_LIST_HEAD(&desc->node);
+
+ desc->hwdesc->format = FRAME_FORMAT;
+ desc->hwdesc->address = paddr;
+ desc->cf_addr = cf;
+
+ desc->cdb_addr = (void *)(cf + RE_CF_DESC_SIZE);
+ desc->cdb_paddr = paddr + RE_CF_DESC_SIZE;
+
+ return desc;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_alloc_desc(struct re_jr *jr,
+ unsigned long flags)
+{
+ struct fsl_re_dma_async_tx_desc *desc;
+
+ spin_lock_bh(&jr->inb_lock);
+
+ jr->inb_count &= RING_SIZE - 1;
+ desc = &jr->descs[jr->inb_count];
+
+ if (desc->state != RE_DESC_EMPTY) {
+ spin_unlock_bh(&jr->inb_lock);
+ re_jr_issue_pending(&jr->chan);
+ return NULL;
+ }
+ spin_unlock_bh(&jr->inb_lock);
+
+ desc->state = RE_DESC_ALLOC;
+ desc->async_tx.flags = flags;
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *re_jr_prep_genq(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct re_jr *jr = NULL;
+ struct fsl_re_dma_async_tx_desc *desc = NULL;
+ struct xor_cdb *xor = NULL;
+ struct cmpnd_frame *cf;
+ unsigned int i = 0;
+ unsigned int j = 0;
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("%s: Length greater than %d not supported\n",
+ __func__, MAX_DATA_LENGTH);
+ return NULL;
+ }
+ jr = container_of(chan, struct re_jr, chan);
+ desc = re_jr_alloc_desc(jr, flags);
+ if (!desc || desc < 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->dest_cnt = 1;
+ desc->src_cnt = src_cnt;
+
+ desc->cdb_opcode = RE_XOR_OPCODE;
+ desc->cdb_len = sizeof(struct xor_cdb);
+
+ /* Filling xor CDB */
+ xor = desc->cdb_addr;
+ xor->opcode = RE_XOR_OPCODE;
+ xor->nrcs = (src_cnt - 1);
+ xor->blk_size = RE_BLOCK_SIZE;
+ xor->error_attrib = INTERRUPT_ON_ERROR;
+ xor->data_depend = DATA_DEPENDENCY;
+
+ if (scf != NULL) {
+ /* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */
+ for (i = 0; i < src_cnt; i++)
+ xor->gfm[i] = scf[i];
+ } else {
+ /* compute P, that is XOR all srcs */
+ for (i = 0; i < src_cnt; i++)
+ xor->gfm[i] = 1;
+ }
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, len, dest, 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 2, j = 0; j < src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].final = 1;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for P parity calculation.In RAID Engine terminology,
+ * XOR calculation is called GenQ calculation done through GenQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_dma_xor(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, size_t len, unsigned long flags)
+{
+ /* NULL let genq take all coef as 1 */
+ return re_jr_prep_genq(chan, dest, src, src_cnt, NULL, len, flags);
+}
+
+/*
+ * Prep function for P/Q parity calculation.In RAID Engine terminology,
+ * P/Q calculation is called GenQQ done through GenQQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_pq(
+ struct dma_chan *chan, dma_addr_t *dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct re_jr *jr = NULL;
+ struct fsl_re_dma_async_tx_desc *desc = NULL;
+ struct pq_cdb *pq = NULL;
+ struct cmpnd_frame *cf;
+ u8 *p;
+ int gfmq_len, i, j;
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("%s: Length greater than %d not supported\n",
+ __func__, MAX_DATA_LENGTH);
+ return NULL;
+ }
+
+ /*
+ * RE requires at least 2 sources, if given only one source, we pass the
+ * second source same as the first one.
+ * With only one source, generate P is meaningless, only care Q.
+ */
+ if (src_cnt == 1) {
+ struct dma_async_tx_descriptor *tx = NULL;
+ dma_addr_t dma_src[2];
+ unsigned char coef[2];
+ dma_src[0] = *src;
+ coef[0] = *scf;
+ dma_src[1] = *src;
+ coef[1] = 0;
+ tx = re_jr_prep_genq(chan, dest[1], dma_src, 2, coef, len,
+ flags);
+ if (tx) {
+ desc = to_fsl_re_dma_desc(tx);
+ desc->src_cnt = 1;
+ }
+ return tx;
+ }
+
+ /*
+ * During RAID6 array creation, Linux's MD layer gets P and Q
+ * calculated separately in two steps. But our RAID Engine has
+ * the capability to calculate both P and Q with a single command
+ * Hence to merge well with MD layer, we need to provide a hook
+ * here and call re_jq_prep_genq() function
+ */
+
+ if (flags & DMA_PREP_PQ_DISABLE_P)
+ return re_jr_prep_genq(chan, dest[1], src, src_cnt,
+ scf, len, flags);
+
+ jr = container_of(chan, struct re_jr, chan);
+ desc = re_jr_alloc_desc(jr, flags);
+ if (!desc || desc < 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->dest_cnt = 2;
+ desc->src_cnt = src_cnt;
+
+ desc->cdb_opcode = RE_PQ_OPCODE;
+ desc->cdb_len = sizeof(struct pq_cdb);
+
+ /* Filling GenQQ CDB */
+ pq = desc->cdb_addr;
+ pq->opcode = RE_PQ_OPCODE;
+ pq->blk_size = RE_BLOCK_SIZE;
+ pq->buffer_attrib = BUFFERABLE_OUTPUT;
+ pq->data_depend = DATA_DEPENDENCY;
+ pq->nrcs = (src_cnt - 1);
+
+ p = pq->gfm_q1;
+ /* Init gfm_q1[] */
+ for (i = 0; i < src_cnt; i++)
+ p[i] = 1;
+
+ /* Align gfm[] to 32bit */
+ gfmq_len = ((src_cnt+3)/4)*4;
+
+ /* Init gfm_q2[] */
+ p += gfmq_len;
+ for (i = 0; i < src_cnt; i++)
+ p[i] = scf[i];
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st & 2nd frame with dest buffers */
+ for (i = 1, j = 0; i < 3; i++, j++)
+ fill_cfd_frame(cf, i, len, dest[j], 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 3, j = 0; j < src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].final = 1;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for memcpy. In RAID Engine, memcpy is done through MOVE
+ * command. Logic of this function will need to be modified once multipage
+ * support is added in Linux's MD/ASYNC Layer
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct re_jr *jr = NULL;
+ struct fsl_re_dma_async_tx_desc *desc = NULL;
+ size_t length = 0;
+ struct cmpnd_frame *cf = NULL;
+ struct move_cdb *move = NULL;
+
+ jr = container_of(chan, struct re_jr, chan);
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("%s: Length greater than %d not supported\n",
+ __func__, MAX_DATA_LENGTH);
+ return NULL;
+ }
+
+ desc = re_jr_alloc_desc(jr, flags);
+ if (!desc || desc < 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->src_cnt = 1;
+ desc->dest_cnt = 1;
+
+ desc->cdb_opcode = RE_MOVE_OPCODE;
+ desc->cdb_len = sizeof(struct move_cdb);
+
+ /* Filling move CDB */
+ move = desc->cdb_addr;
+ move->opcode = RE_MOVE_OPCODE; /* Unicast move */
+ move->blk_size = RE_BLOCK_SIZE;
+ move->error_attrib = INTERRUPT_ON_ERROR;
+ move->data_depend = DATA_DEPENDENCY;
+
+ /* Filling frame 0 of CFD with move CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ length = min_t(size_t, len, MAX_DATA_LENGTH);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, length, dest, 0);
+
+ /* Fill CFD's 2nd frame with src buffer */
+ fill_cfd_frame(cf, 2, length, src, 1);
+
+ return &desc->async_tx;
+}
+
+static int re_jr_alloc_chan_resources(struct dma_chan *chan)
+{
+ int i;
+ struct fsl_re_dma_async_tx_desc *desc;
+ struct re_jr *jr = container_of(chan, struct re_jr, chan);
+ void *cf = NULL;
+ dma_addr_t paddr;
+
+ jr->descs = kzalloc(sizeof(*desc) * RING_SIZE, GFP_KERNEL);
+ if (!jr->descs) {
+ dev_err(jr->dev, "%s: No memory for sw descriptor ring\n",
+ __func__);
+ goto err_free;
+ }
+
+ cf = dma_pool_alloc(jr->re_dev->desc_pool, GFP_ATOMIC, &paddr);
+ if (!cf) {
+ dev_err(jr->dev, "%s: No memory for dma descriptor ring\n",
+ __func__);
+ goto err_free;
+ }
+ memset(cf, 0, RE_CF_CDB_SIZE * RING_SIZE);
+ jr->cfs = cf;
+ jr->phys = paddr;
+
+ for (i = 0; i < RING_SIZE; i++) {
+ u32 offset = i * RE_CF_CDB_SIZE;
+ desc = &jr->descs[i];
+ desc->hwdesc = &jr->inb_ring_virt_addr[i];
+ re_jr_init_desc(jr, desc, cf + offset, paddr + offset);
+ desc->state = RE_DESC_EMPTY;
+ }
+ return 0;
+
+err_free:
+ kfree(jr->descs);
+ return -ENOMEM;
+}
+
+static void re_jr_free_chan_resources(struct dma_chan *chan)
+{
+ struct re_jr *jr = container_of(chan, struct re_jr, chan);
+ dma_pool_free(jr->re_dev->desc_pool, jr->cfs, jr->phys);
+ kfree(jr->descs);
+ return;
+}
+
+int re_jr_probe(struct platform_device *ofdev,
+ struct device_node *np, u8 q, u32 *off)
+{
+ struct device *dev = NULL;
+ struct re_drv_private *repriv = NULL;
+ struct re_jr *jr = NULL;
+ struct dma_device *dma_dev = NULL;
+ u32 *ptr = NULL;
+ u32 status;
+ int ret = 0;
+ struct platform_device *jr_ofdev = NULL;
+
+ dev = &ofdev->dev;
+ repriv = dev_get_drvdata(dev);
+ dma_dev = &repriv->dma_dev;
+
+ jr = kzalloc(sizeof(struct re_jr), GFP_KERNEL);
+ if (!jr) {
+ dev_err(dev, "%s: No free memory for allocating JR struct\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ jr_ofdev = of_platform_device_create(np, NULL, dev);
+ if (jr_ofdev == NULL) {
+ dev_err(dev, "%s: Not able to create ofdev for jr %d\n",
+ __func__, q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+ dev_set_drvdata(&jr_ofdev->dev, jr);
+
+ ptr = (u32 *)of_get_property(np, "reg", NULL);
+ if (!ptr) {
+ dev_err(dev, "%s: Reg property not found in JR number %d\n",
+ __func__, q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ jr->jrregs = (struct jr_config_regs *)((u8 *)repriv->re_regs +
+ *off + *ptr);
+
+ jr->irq = irq_of_parse_and_map(np, 0);
+ if (jr->irq == NO_IRQ) {
+ dev_err(dev, "%s: No IRQ defined for JR %d\n", __func__, q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ tasklet_init(&jr->irqtask, re_jr_dequeue,
+ (unsigned long)&jr_ofdev->dev);
+
+ ret = request_irq(jr->irq, re_jr_interrupt, 0, "re-jr", &jr_ofdev->dev);
+ if (ret) {
+ dev_err(dev, "%s: Unable to register JR interrupt for JR %d\n",
+ __func__, q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ repriv->re_jrs[q] = jr;
+ jr->chan.device = dma_dev;
+ jr->chan.private = jr;
+ jr->dev = &jr_ofdev->dev;
+ jr->re_dev = repriv;
+ jr->pend_count = 0;
+ INIT_LIST_HEAD(&jr->ack_q);
+ spin_lock_init(&jr->desc_lock);
+ spin_lock_init(&jr->inb_lock);
+ spin_lock_init(&jr->oub_lock);
+
+ init_timer(&jr->timer);
+ jr->timer.expires = jiffies + 10*HZ;
+ jr->timer.function = raide_timer_handler;
+
+ list_add_tail(&jr->chan.device_node, &dma_dev->channels);
+ dma_dev->chancnt++;
+
+ jr->inb_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+ GFP_ATOMIC, &jr->inb_phys_addr);
+
+ if (!jr->inb_ring_virt_addr) {
+ dev_err(dev, "%s:No dma memory for inb_ring_virt_addr\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ jr->oub_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+ GFP_ATOMIC, &jr->oub_phys_addr);
+
+ if (!jr->oub_ring_virt_addr) {
+ dev_err(dev, "%s:No dma memory for oub_ring_virt_addr\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ jr->inb_count = 0;
+ jr->pend_count = 0;
+ jr->oub_count = 0;
+
+ status = in_be32(&jr->jrregs->jr_status);
+
+ if (status & RE_JR_PAUSE) {
+ dev_info(dev, "%s: JR is in paused state...enable it\n",
+ __func__);
+ } else {
+ dev_err(dev, "%s: Error:- JR shud be in paused state\n",
+ __func__);
+ ret = -EINVAL;
+ goto pool_free;
+ }
+
+ /* Program the Inbound/Outbound ring base addresses and size */
+ out_be32(&jr->jrregs->inbring_base_h,
+ jr->inb_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+ out_be32(&jr->jrregs->oubring_base_h,
+ jr->oub_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+ out_be32(&jr->jrregs->inbring_base_l,
+ jr->inb_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+ out_be32(&jr->jrregs->oubring_base_l,
+ jr->oub_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+ out_be32(&jr->jrregs->inbring_size, RING_SIZE << RING_SIZE_SHIFT);
+ out_be32(&jr->jrregs->oubring_size, RING_SIZE << RING_SIZE_SHIFT);
+
+ /* Read LIODN value from u-boot */
+ status = in_be32(&jr->jrregs->jr_config_1) & RE_JR_REG_LIODN_MASK;
+
+ /* Program the CFG reg */
+ out_be32(&jr->jrregs->jr_config_1,
+ RE_JR_CFG1_CBSI | RE_JR_CFG1_CBS0 | status);
+
+ /* Enable RE/JR */
+ out_be32(&jr->jrregs->jr_command, RE_JR_ENABLE);
+
+ return 0;
+
+pool_free:
+ dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+ jr->inb_phys_addr);
+err_free:
+ kfree(jr);
+ return ret;
+}
+
+/* Probe function for RAID Engine */
+static int __devinit raide_probe(struct platform_device *ofdev)
+{
+ struct re_drv_private *repriv = NULL;
+ struct device *dev = NULL;
+ struct device_node *np = NULL;
+ struct device_node *child = NULL;
+ u32 *off = NULL;
+ u8 ridx = 0;
+ struct dma_device *dma_dev = NULL;
+ int ret = 0;
+
+ dev_info(&ofdev->dev, "Freescale RAID Engine driver\n");
+
+ repriv = kzalloc(sizeof(struct re_drv_private), GFP_KERNEL);
+ if (!repriv) {
+ dev_err(dev, "%s: No memory for repriv\n", __func__);
+ return -ENOMEM;
+ }
+
+ dev = &ofdev->dev;
+ dev_set_drvdata(dev, repriv);
+
+ /* IOMAP the entire RAID Engine region */
+ repriv->re_regs = of_iomap(ofdev->dev.of_node, 0);
+ if (repriv->re_regs == NULL) {
+ dev_err(dev, "%s: of_iomap failed\n", __func__);
+ kfree(repriv);
+ ret = -ENOMEM;
+ goto err_free_4;
+ }
+
+ /* Print the RE version to make sure RE is alive */
+ dev_info(dev, "Ver = %x\n", in_be32(&repriv->re_regs->re_version_id));
+
+ /* Program the RE mode */
+ out_be32(&repriv->re_regs->global_config, RE_NON_DPAA_MODE);
+ dev_info(dev, "%s:RE mode is %x\n", __func__,
+ in_be32(&repriv->re_regs->global_config));
+
+ /* Program Galois Field polynomial */
+ out_be32(&repriv->re_regs->galois_field_config, RE_GFM_POLY);
+ dev_info(dev, "%s:Galois Field Polynomial is %x\n", __func__,
+ in_be32(&repriv->re_regs->galois_field_config));
+
+ dma_dev = &repriv->dma_dev;
+ dma_dev->dev = dev;
+ INIT_LIST_HEAD(&dma_dev->channels);
+ dma_set_mask(dev, DMA_BIT_MASK(40));
+
+ dma_dev->device_alloc_chan_resources = re_jr_alloc_chan_resources;
+ dma_dev->device_tx_status = re_jr_tx_status;
+ dma_dev->device_issue_pending = re_jr_issue_pending;
+
+ dma_dev->max_xor = MAX_XOR_SRCS;
+ dma_dev->device_prep_dma_xor = re_jr_prep_dma_xor;
+ dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+ dma_dev->max_pq = MAX_PQ_SRCS;
+ dma_dev->device_prep_dma_pq = re_jr_prep_pq;
+ dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+
+ dma_dev->device_prep_dma_memcpy = re_jr_prep_memcpy;
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+
+ dma_dev->device_free_chan_resources = re_jr_free_chan_resources;
+
+ repriv->total_jrs = 0;
+
+ repriv->desc_pool = dma_pool_create("re_dma_desc_pool", dev,
+ RE_CF_CDB_SIZE * RING_SIZE,
+ RE_CF_CDB_ALIGN, 0);
+
+ if (!repriv->desc_pool) {
+ pr_err("%s:No memory for dma desc pool\n", __func__);
+ ret = -ENOMEM;
+ goto err_free_3;
+ }
+
+ repriv->hw_desc_pool = dma_pool_create("re_hw_desc_pool", dev,
+ sizeof(struct jr_hw_desc) * RING_SIZE,
+ FRAME_DESC_ALIGNMENT, 0);
+ if (!repriv->hw_desc_pool) {
+ pr_err("%s:No memory for hw desc pool\n", __func__);
+ ret = -ENOMEM;
+ goto err_free_2;
+ }
+
+ /* Parse Device tree to find out the total number of JQs present */
+ for_each_compatible_node(np, NULL, "fsl,raideng-v1.0-job-queue") {
+ off = (u32 *)of_get_property(np, "reg", NULL);
+ if (!off) {
+ dev_err(dev, "%s: Reg property not found in JQ node\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ /* Find out the Job Rings present under each JQ */
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child,
+ "fsl,raideng-v1.0-job-ring")) {
+ re_jr_probe(ofdev, child, ridx++, off);
+ repriv->total_jrs++;
+ }
+ }
+ }
+
+ dma_async_device_register(dma_dev);
+ return 0;
+
+err_free_2:
+ dma_pool_destroy(repriv->desc_pool);
+err_free_3:
+ iounmap(repriv->re_regs);
+err_free_4:
+ kfree(repriv);
+
+ return ret;
+}
+
+static void release_jr(struct re_jr *jr)
+{
+ /* Free the memory allocated from DMA pools and destroy them */
+ dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+ jr->inb_phys_addr);
+ kfree(jr);
+}
+
+static int raide_remove(struct platform_device *ofdev)
+{
+ struct re_drv_private *repriv = NULL;
+ struct device *dev = NULL;
+ int i;
+
+ dev = &ofdev->dev;
+ repriv = dev_get_drvdata(dev);
+
+ /* Cleanup JR related memory areas */
+ for (i = 0; i < repriv->total_jrs; i++)
+ release_jr(repriv->re_jrs[i]);
+
+ dma_pool_destroy(repriv->hw_desc_pool);
+ dma_pool_destroy(repriv->desc_pool);
+
+ /* Unregister the driver */
+ dma_async_device_unregister(&repriv->dma_dev);
+
+ /* Unmap the RAID Engine region */
+ iounmap(repriv->re_regs);
+
+ kfree(repriv);
+
+ return 0;
+}
+
+static struct of_device_id raide_ids[] = {
+ { .compatible = "fsl,raideng-v1.0", },
+ {}
+};
+
+static struct platform_driver raide_driver = {
+ .driver = {
+ .name = "fsl-raideng",
+ .owner = THIS_MODULE,
+ .of_match_table = raide_ids,
+ },
+ .probe = raide_probe,
+ .remove = raide_remove,
+};
+
+static __init int raide_init(void)
+{
+ int ret = 0;
+
+ ret = platform_driver_register(&raide_driver);
+ if (ret)
+ pr_err("fsl-raid: Failed to register platform driver\n");
+
+ return ret;
+}
+
+static void __exit raide_exit(void)
+{
+ platform_driver_unregister(&raide_driver);
+}
+
+subsys_initcall(raide_init);
+module_exit(raide_exit);
+
+MODULE_AUTHOR("Harninder Rai <harninder.rai@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Freescale RAID Engine Device Driver");
diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
new file mode 100644
index 0000000..3cb8454
--- /dev/null
+++ b/drivers/dma/fsl_raid.h
@@ -0,0 +1,317 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define RE_DPAA_MODE (1 << 30)
+#define RE_NON_DPAA_MODE (1 << 31)
+#define RE_GFM_POLY (0x1d000000)
+#define RE_JR_INB_JOB_ADD(x) ((x) << 16)
+#define RE_JR_OUB_JOB_REMOVE(x) ((x) << 16)
+#define RE_JR_CFG1_CBSI 0x08000000
+#define RE_JR_CFG1_CBS0 0x00080000
+#define RE_JR_OUB_SLOT_FULL_SHIFT 8
+#define RE_JR_OUB_SLOT_FULL(x) ((x) >> RE_JR_OUB_SLOT_FULL_SHIFT)
+#define RE_JR_INB_SLOT_AVAIL_SHIFT 8
+#define RE_JR_INB_SLOT_AVAIL(x) ((x) >> RE_JR_INB_SLOT_AVAIL_SHIFT)
+#define RE_PQ_OPCODE 0x1B
+#define RE_XOR_OPCODE 0x1A
+#define RE_MOVE_OPCODE 0x8
+#define FRAME_DESC_ALIGNMENT 16
+#define RE_BLOCK_SIZE 0x3 /* 4096 bytes */
+#define CACHEABLE_INPUT_OUTPUT 0x0
+#define BUFFERABLE_OUTPUT 0x0
+#define INTERRUPT_ON_ERROR 0x1
+#define DATA_DEPENDENCY 0x1
+#define ENABLE_DPI 0x0
+#define RING_SIZE 0x1000
+#define RING_SIZE_SHIFT 8
+#define RE_JR_ADDRESS_BIT_SHIFT 4
+#define RE_JR_ADDRESS_BIT_MASK ((1 << RE_JR_ADDRESS_BIT_SHIFT) - 1)
+#define RE_JR_ERROR 0x40000000
+#define RE_JR_INTERRUPT 0x80000000
+#define RE_JR_CLEAR_INT 0x80000000
+#define RE_JR_PAUSE 0x80000000
+#define RE_JR_ENABLE 0x80000000
+
+#define RE_JR_REG_LIODN_MASK 0x00000fff
+#define RE_CF_CDB_ALIGN 64
+/*
+ * the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
+ * here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
+ * the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
+ * 320+180=500, align to 64bytes, that is 512 bytes.
+ */
+#define RE_CF_DESC_SIZE 320
+#define RE_CF_CDB_SIZE 512
+
+struct re_ctrl {
+ /* General Configuration Registers */
+ __be32 global_config; /* Global Configuration Register */
+ u8 rsvd1[4];
+ __be32 galois_field_config; /* Galois Field Configuration Register */
+ u8 rsvd2[4];
+ __be32 jq_wrr_config; /* WRR Configuration register */
+ u8 rsvd3[4];
+ __be32 crc_config; /* CRC Configuration register */
+ u8 rsvd4[228];
+ __be32 system_reset; /* System Reset Register */
+ u8 rsvd5[252];
+ __be32 global_status; /* Global Status Register */
+ u8 rsvd6[832];
+ __be32 re_liodn_base; /* LIODN Base Register */
+ u8 rsvd7[1712];
+ __be32 re_version_id; /* Version ID register of RE */
+ __be32 re_version_id_2; /* Version ID 2 register of RE */
+ u8 rsvd8[512];
+ __be32 host_config; /* Host I/F Configuration Register */
+};
+
+struct jr_config_regs {
+ /* Registers for JR interface */
+ __be32 jr_config_0; /* Job Queue Configuration 0 Register */
+ __be32 jr_config_1; /* Job Queue Configuration 1 Register */
+ __be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
+ u8 rsvd1[4];
+ __be32 jr_command; /* Job Queue Command Register */
+ u8 rsvd2[4];
+ __be32 jr_status; /* Job Queue Status Register */
+ u8 rsvd3[228];
+
+ /* Input Ring */
+ __be32 inbring_base_h; /* Inbound Ring Base Address Register - High */
+ __be32 inbring_base_l; /* Inbound Ring Base Address Register - Low */
+ __be32 inbring_size; /* Inbound Ring Size Register */
+ u8 rsvd4[4];
+ __be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
+ u8 rsvd5[4];
+ __be32 inbring_add_job; /* Inbound Ring Add Job Register */
+ u8 rsvd6[4];
+ __be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
+ u8 rsvd7[220];
+
+ /* Output Ring */
+ __be32 oubring_base_h; /* Outbound Ring Base Address Register - High */
+ __be32 oubring_base_l; /* Outbound Ring Base Address Register - Low */
+ __be32 oubring_size; /* Outbound Ring Size Register */
+ u8 rsvd8[4];
+ __be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
+ u8 rsvd9[4];
+ __be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
+ u8 rsvd10[4];
+ __be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
+};
+
+/*
+ * Command Descriptor Block (CDB) for unicast move command.
+ * In RAID Engine terms, memcpy is done through move command
+ */
+struct move_cdb {
+ u32 opcode:5;
+ u32 rsvd1:11;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 rsvd2:6;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+} __packed;
+
+/* Data protection/integrity related fields */
+struct dpi_related {
+ u32 apps_mthd:2;
+ u32 ref_mthd:2;
+ u32 guard_mthd:2;
+ u32 dpi_attr:2;
+ u32 rsvd1:8;
+ u32 meta_tag:16;
+ u32 ref_tag:32;
+} __packed;
+
+/*
+ * CDB for GenQ command. In RAID Engine terminology, XOR is
+ * done through this command
+ */
+struct xor_cdb {
+ u32 opcode:5;
+ u32 rsvd1:11;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 nrcs:4;
+ u32 rsvd2:2;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+ u8 gfm[16];
+ struct dpi_related dpi_dest_spec;
+ struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* CDB for no-op command */
+struct noop_cdb {
+ u32 opcode:5;
+ u32 rsvd1:23;
+ u32 dependency:1;
+ u32 rsvd2:3;
+} __packed;
+
+/*
+ * CDB for GenQQ command. In RAID Engine terminology, P/Q is
+ * done through this command
+ */
+struct pq_cdb {
+ u32 opcode:5;
+ u32 rsvd1:1;
+ u32 excl_enable:2;
+ u32 excl_q1:4;
+ u32 excl_q2:4;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 nrcs:4;
+ u32 rsvd2:2;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+ u8 gfm_q1[16];
+ u8 gfm_q2[16];
+ struct dpi_related dpi_dest_spec[2];
+ struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* Compound frame */
+struct cmpnd_frame {
+ u64 rsvd1:24;
+ u64 address:40;
+ u32 extension:1;
+ u32 final:1;
+ u32 rsvd3:10;
+ u32 length:20;
+ u32 rsvd4:8;
+ u32 bpid:8;
+ u32 rsvd5:3;
+ u32 offset:13;
+} __packed;
+
+/* Frame descriptor */
+struct jr_hw_desc {
+ u64 debug:2;
+ u64 liodn_off:6;
+ u64 bpid:8;
+ u64 eliodn_off:4;
+ u64 rsvd1:4;
+ u64 address:40;
+ u64 format:3;
+ u64 rsvd2:29;
+ u64 status:32;
+} __packed;
+
+#define MAX_RE_JRS 4
+
+/* Raid Engine device private data */
+struct re_drv_private {
+ u8 total_jrs;
+ struct dma_device dma_dev;
+ struct re_ctrl *re_regs;
+ struct re_jr *re_jrs[MAX_RE_JRS];
+ struct dma_pool *desc_pool;
+ struct dma_pool *hw_desc_pool;
+};
+
+/* Per job ring data structure */
+struct re_jr {
+ dma_cookie_t completed_cookie;
+ spinlock_t desc_lock;
+ struct list_head ack_q;
+ struct device *dev;
+ struct re_drv_private *re_dev;
+ struct dma_chan chan;
+ struct jr_config_regs *jrregs;
+ int irq;
+ struct tasklet_struct irqtask;
+
+ /* hw descriptor ring for inbound queue*/
+ dma_addr_t inb_phys_addr;
+ struct jr_hw_desc *inb_ring_virt_addr;
+ u32 inb_count;
+ u32 pend_count;
+ spinlock_t inb_lock;
+
+ /* hw descriptor ring for outbound queue */
+ dma_addr_t oub_phys_addr;
+ struct jr_hw_desc *oub_ring_virt_addr;
+ u32 oub_count;
+ spinlock_t oub_lock;
+
+ struct fsl_re_dma_async_tx_desc *descs; /* sw descriptor ring */
+ void *cfs; /* dma descriptor ring */
+ dma_addr_t phys; /* phys addr for dma descriptor ring */
+
+ struct timer_list timer;
+};
+
+enum desc_state {
+ RE_DESC_EMPTY,
+ RE_DESC_ALLOC,
+};
+
+/* Async transaction descriptor */
+struct fsl_re_dma_async_tx_desc {
+ struct dma_async_tx_descriptor async_tx;
+ struct list_head node;
+ struct list_head tx_list;
+ struct jr_hw_desc *hwdesc;
+ struct re_jr *jr;
+
+ void *cf_addr;
+ int dma_len;
+ u8 dest_cnt;
+ u8 src_cnt;
+
+ u16 cdb_opcode;
+ void *cdb_addr;
+ dma_addr_t cdb_paddr;
+ int cdb_len;
+
+ enum desc_state state;
+};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] powerpc/dma/raidengine: add raidengine device
2012-11-21 9:01 [PATCH 1/2] powerpc/dma/raidengine: add raidengine device b29237
2012-11-21 9:01 ` [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device b29237
@ 2012-11-25 13:21 ` Kumar Gala
1 sibling, 0 replies; 4+ messages in thread
From: Kumar Gala @ 2012-11-25 13:21 UTC (permalink / raw)
To: <b29237@freescale.com>
Cc: Harninder Rai, iws, vinod.koul, linux-kernel, Naveen Burmi,
dan.j.williams, linuxppc-dev
On Nov 21, 2012, at 3:01 AM, <b29237@freescale.com> =
<b29237@freescale.com> wrote:
> From: Xuelin Shi <b29237@freescale.com>
>=20
> The RaidEngine is a new Freescale hardware that used for parity
> computation offloading in RAID5/6.
>=20
> This patch adds the device node in device tree and related binding
> documentation.
>=20
> Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
> Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
> Signed-off-by: Xuelin Shi <b29237@freescale.com>
> ---
> .../devicetree/bindings/powerpc/fsl/raideng.txt | 81 =
+++++++++++++++++++
> arch/powerpc/boot/dts/fsl/p5020si-post.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi | 6 ++
> arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi | 85 =
++++++++++++++++++++
> 4 files changed, 173 insertions(+)
> create mode 100644 =
Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
> create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
applied to next
- k=
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device
2012-11-21 9:01 ` [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device b29237
@ 2013-04-10 5:07 ` Shi Xuelin-B29237
0 siblings, 0 replies; 4+ messages in thread
From: Shi Xuelin-B29237 @ 2013-04-10 5:07 UTC (permalink / raw)
To: dan.j.williams@gmail.com, vinod.koul@intel.com
Cc: linuxppc-dev@lists.ozlabs.org, Burmi Naveen-B16502,
Rai Harninder-B01044, linux-kernel@vger.kernel.org,
iws@ovro.caltech.edu
SGkgRGFuICYgdmlub2QsDQoNCkRvIHlvdSBoYXZlIGFueSBjb21tZW50cyBhYm91dCB0aGlzIHBh
dGNoPw0KDQpUaGFua3MsDQpGb3JyZXN0DQoNCi0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQpG
cm9tOiBTaGkgWHVlbGluLUIyOTIzNyANClNlbnQ6IDIwMTLE6jEx1MIyMcjVIDE3OjAxDQpUbzog
ZGFuLmoud2lsbGlhbXNAZ21haWwuY29tOyB2aW5vZC5rb3VsQGludGVsLmNvbTsgbGludXhwcGMt
ZGV2QGxpc3RzLm96bGFicy5vcmc7IGxpbnV4LWtlcm5lbEB2Z2VyLmtlcm5lbC5vcmcNCkNjOiBp
d3NAb3Zyby5jYWx0ZWNoLmVkdTsgU2hpIFh1ZWxpbi1CMjkyMzc7IFJhaSBIYXJuaW5kZXItQjAx
MDQ0OyBCdXJtaSBOYXZlZW4tQjE2NTAyDQpTdWJqZWN0OiBbUEFUQ0ggMi8yXSBwb3dlcnBjL2Rt
YS9yYWlkZW5naW5lOiBlbmFibGUgRnJlZXNjYWxlIFJhaWRFbmdpbmUgZGV2aWNlDQoNCkZyb206
IFh1ZWxpbiBTaGkgPGIyOTIzN0BmcmVlc2NhbGUuY29tPg0KDQpUaGUgUmFpZEVuZ2luZSBpcyBh
IG5ldyBGU0wgaGFyZHdhcmUgdGhhdCB1c2VkIGFzIGhhcmR3YXJlIGFjY2VyYXRpb24gZm9yIFJB
SUQ1LzYuDQoNClRoaXMgcGF0Y2ggZW5hYmxlcyB0aGUgUmFpZEVuZ2luZSBmdW5jdGlvbmFsaXR5
IGFuZCBwcm92aWRlcyBoYXJkd2FyZSBvZmZsb2FkaW5nIGNhcGFiaWxpdHkgZm9yIG1lbWNweSwg
eG9yIGFuZCByYWlkNiBwcSBjb21wdXRhdGlvbi4gSXQgd29ya3MgdW5kZXIgZG1hZW5naW5lIGNv
bnRyb2wgd2l0aCBhc3luY19sYXllciBpbnRlcmZhY2UuDQoNClNpZ25lZC1vZmYtYnk6IEhhcm5p
bmRlciBSYWkgPGhhcm5pbmRlci5yYWlAZnJlZXNjYWxlLmNvbT4NClNpZ25lZC1vZmYtYnk6IE5h
dmVlbiBCdXJtaSA8bmF2ZWVuYnVybWlAZnJlZXNjYWxlLmNvbT4NClNpZ25lZC1vZmYtYnk6IFh1
ZWxpbiBTaGkgPGIyOTIzN0BmcmVlc2NhbGUuY29tPg0KLS0tDQogZHJpdmVycy9kbWEvS2NvbmZp
ZyAgICB8ICAgMTQgKw0KIGRyaXZlcnMvZG1hL01ha2VmaWxlICAgfCAgICAxICsNCiBkcml2ZXJz
L2RtYS9mc2xfcmFpZC5jIHwgIDk5MCArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysNCiBkcml2ZXJzL2RtYS9mc2xfcmFpZC5oIHwgIDMxNyArKysrKysrKysr
KysrKysrDQogNCBmaWxlcyBjaGFuZ2VkLCAxMzIyIGluc2VydGlvbnMoKykNCiBjcmVhdGUgbW9k
ZSAxMDA2NDQgZHJpdmVycy9kbWEvZnNsX3JhaWQuYyAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl
cnMvZG1hL2ZzbF9yYWlkLmgNCg0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hL0tjb25maWcgYi9k
cml2ZXJzL2RtYS9LY29uZmlnIGluZGV4IGQ0YzEyMTguLmFhMzcyNzkgMTAwNjQ0DQotLS0gYS9k
cml2ZXJzL2RtYS9LY29uZmlnDQorKysgYi9kcml2ZXJzL2RtYS9LY29uZmlnDQpAQCAtMzIwLDYg
KzMyMCwyMCBAQCBjb25maWcgTU1QX1BETUENCiAJaGVscA0KIAkgIFN1cHBvcnQgdGhlIE1NUCBQ
RE1BIGVuZ2luZSBmb3IgUFhBIGFuZCBNTVAgcGxhdGZyb20uDQogDQorY29uZmlnIEZTTF9SQUlE
DQorICAgICAgICB0cmlzdGF0ZSAiRnJlZXNjYWxlIFJBSUQgRW5naW5lIERldmljZSBEcml2ZXIi
DQorICAgICAgICBkZXBlbmRzIG9uIEZTTF9TT0MgJiYgIUZTTF9ETUENCisgICAgICAgIHNlbGVj
dCBETUFfRU5HSU5FDQorICAgICAgICBzZWxlY3QgQVNZTkNfVFhfRU5BQkxFX0NIQU5ORUxfU1dJ
VENIDQorICAgICAgICBzZWxlY3QgQVNZTkNfTUVNQ1BZDQorICAgICAgICBzZWxlY3QgQVNZTkNf
WE9SDQorICAgICAgICBzZWxlY3QgQVNZTkNfUFENCisgICAgICAgIC0tLWhlbHAtLS0NCisgICAg
ICAgICAgRW5hYmxlIHN1cHBvcnQgZm9yIEZyZWVzY2FsZSBSQUlEIEVuZ2luZS4gUkFJRCBFbmdp
bmUgaXMNCisgICAgICAgICAgYXZhaWxhYmxlIG9uIHNvbWUgUW9ySVEgU29DcyAobGlrZSBQNTAy
MCkuIEl0IGhhcw0KKyAgICAgICAgICB0aGUgY2FwYWJpbGl0eSB0byBvZmZsb2FkIFJBSUQ1L1JB
SUQ2IG9wZXJhdGlvbnMgZnJvbSBDUFUuDQorICAgICAgICAgIFJBSUQ1IGlzIFhPUiBhbmQgbWVt
Y3B5LiBSQUlENiBpcyBQL1EgYW5kIG1lbWNweQ0KKw0KIGNvbmZpZyBETUFfRU5HSU5FDQogCWJv
b2wNCiANCmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9NYWtlZmlsZSBiL2RyaXZlcnMvZG1hL01h
a2VmaWxlIGluZGV4IDc0MjhmZWEuLjI5YjY1ZWIgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL2RtYS9N
YWtlZmlsZQ0KKysrIGIvZHJpdmVycy9kbWEvTWFrZWZpbGUNCkBAIC05LDYgKzksNyBAQCBvYmot
JChDT05GSUdfRE1BVEVTVCkgKz0gZG1hdGVzdC5vDQogb2JqLSQoQ09ORklHX0lOVEVMX0lPQVRE
TUEpICs9IGlvYXQvDQogb2JqLSQoQ09ORklHX0lOVEVMX0lPUF9BRE1BKSArPSBpb3AtYWRtYS5v
DQogb2JqLSQoQ09ORklHX0ZTTF9ETUEpICs9IGZzbGRtYS5vDQorb2JqLSQoQ09ORklHX0ZTTF9S
QUlEKSArPSBmc2xfcmFpZC5vDQogb2JqLSQoQ09ORklHX01QQzUxMlhfRE1BKSArPSBtcGM1MTJ4
X2RtYS5vDQogb2JqLSQoQ09ORklHX01WX1hPUikgKz0gbXZfeG9yLm8NCiBvYmotJChDT05GSUdf
RFdfRE1BQykgKz0gZHdfZG1hYy5vDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvZnNsX3JhaWQu
YyBiL2RyaXZlcnMvZG1hL2ZzbF9yYWlkLmMgbmV3IGZpbGUgbW9kZSAxMDA2NDQgaW5kZXggMDAw
MDAwMC4uZWMxOTgxNw0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVycy9kbWEvZnNsX3JhaWQu
Yw0KQEAgLTAsMCArMSw5OTAgQEANCisvKg0KKyAqIGRyaXZlcnMvZG1hL2ZzbF9yYWlkLmMNCisg
Kg0KKyAqIEZyZWVzY2FsZSBSQUlEIEVuZ2luZSBkZXZpY2UgZHJpdmVyDQorICoNCisgKiBBdXRo
b3I6DQorICoJSGFybmluZGVyIFJhaSA8aGFybmluZGVyLnJhaUBmcmVlc2NhbGUuY29tPg0KKyAq
CU5hdmVlbiBCdXJtaSA8bmF2ZWVuYnVybWlAZnJlZXNjYWxlLmNvbT4NCisgKg0KKyAqIENvcHly
aWdodCAoYykgMjAxMC0yMDEyIEZyZWVzY2FsZSBTZW1pY29uZHVjdG9yLCBJbmMuDQorICoNCisg
KiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRo
IG9yIHdpdGhvdXQNCisgKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhh
dCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoNCisgKiAgICAgKiBSZWRpc3RyaWJ1
dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodA0KKyAq
ICAgICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcg
ZGlzY2xhaW1lci4NCisgKiAgICAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVz
dCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodA0KKyAqICAgICAgIG5vdGljZSwgdGhpcyBs
aXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUNCisg
KiAgICAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0
aCB0aGUgZGlzdHJpYnV0aW9uLg0KKyAqICAgICAqIE5laXRoZXIgdGhlIG5hbWUgb2YgRnJlZXNj
YWxlIFNlbWljb25kdWN0b3Igbm9yIHRoZQ0KKyAqICAgICAgIG5hbWVzIG9mIGl0cyBjb250cmli
dXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzDQorICogICAg
ICAgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dCBzcGVjaWZpYyBwcmlvciB3cml0
dGVuIHBlcm1pc3Npb24uDQorICoNCisgKiBBTFRFUk5BVElWRUxZLCB0aGlzIHNvZnR3YXJlIG1h
eSBiZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgDQordGhlDQorICogR05VIEdlbmVy
YWwgUHVibGljIExpY2Vuc2UgKCJHUEwiKSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdh
cmUNCisgKiBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoYXQgTGljZW5zZSBvciAo
YXQgeW91ciBvcHRpb24pIGFueQ0KKyAqIGxhdGVyIHZlcnNpb24uDQorICoNCisgKiBUSElTIFNP
RlRXQVJFIElTIFBST1ZJREVEIEJZIEZyZWVzY2FsZSBTZW1pY29uZHVjdG9yIGBgQVMgSVMnJyBB
TkQgDQorQU5ZDQorICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywg
QlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgDQorSU1QTElFRA0KKyAqIFdBUlJBTlRJRVMgT0YgTUVS
Q0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSANCitBUkUN
CisgKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBGcmVlc2NhbGUgU2VtaWNvbmR1Y3Rv
ciBCRSBMSUFCTEUgRk9SIA0KK0FOWQ0KKyAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUws
IFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCANCitEQU1BR0VTDQorICogKElO
Q0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdP
T0RTIE9SIA0KK1NFUlZJQ0VTOw0KKyAqIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBP
UiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgDQorQ0FVU0VEIEFORA0KKyAqIE9OIEFO
WSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklM
SVRZLCANCitPUiBUT1JUDQorICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkg
QVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgDQorVVNFIE9GIFRISVMNCisgKiBTT0ZUV0FS
RSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4NCisg
Kg0KKyAqIFRoZW9yeSBvZiBvcGVyYXRpb246DQorICoNCisgKiBHZW5lcmFsIGNhcGFiaWxpdGll
czoNCisgKglSQUlEIEVuZ2luZSAoUkUpIGJsb2NrIGlzIGNhcGFibGUgb2Ygb2ZmbG9hZGluZyBY
T1IsIG1lbWNweSBhbmQgUC9RDQorICoJY2FsY3VsYXRpb25zIHJlcXVpcmVkIGluIFJBSUQ1IGFu
ZCBSQUlENiBvcGVyYXRpb25zLiBSRSBkcml2ZXINCisgKglyZWdpc3RlcnMgd2l0aCBMaW51eCdz
IEFTWU5DIGxheWVyIGFzIGRtYSBkcml2ZXIuIFJFIGhhcmR3YXJlDQorICoJbWFpbnRhaW5zIHN0
cmljdCBvcmRlcmluZyBvZiB0aGUgcmVxdWVzdHMgdGhyb3VnaCBjaGFpbmVkDQorICoJY29tbWFu
ZCBxdWV1ZWluZy4NCisgKg0KKyAqIERhdGEgZmxvdzoNCisgKglTb2Z0d2FyZSBSQUlEIGxheWVy
IG9mIExpbnV4IChNRCBsYXllcikgbWFpbnRhaW5zIFJBSUQgcGFydGl0aW9ucywNCisgKglzdHJp
cHMsIHN0cmlwZXMgZXRjLiBJdCBzZW5kcyByZXF1ZXN0cyB0byB0aGUgdW5kZXJseWluZyBBWVNO
QyBsYXllcg0KKyAqCXdoaWNoIGZ1cnRoZXIgcGFzc2VzIGl0IHRvIFJFIGRyaXZlci4gQVNZTkMg
bGF5ZXIgZGVjaWRlcyB3aGljaCByZXF1ZXN0DQorICoJZ29lcyB0byB3aGljaCBqb2IgcmluZyBv
ZiBSRSBoYXJkd2FyZS4gRm9yIGV2ZXJ5IHJlcXVlc3QgcHJvY2Vzc2VkIGJ5DQorICoJUkFJRCBF
bmdpbmUsIGRyaXZlciBnZXRzIGFuIGludGVycnVwdCB1bmxlc3MgY29hbGVzY2luZyBpcyBzZXQu
IFRoZQ0KKyAqCXBlciBqb2IgcmluZyBpbnRlcnJ1cHQgaGFuZGxlciBjaGVja3MgdGhlIHN0YXR1
cyByZWdpc3RlciBmb3IgZXJyb3JzLA0KKyAqCWNsZWFycyB0aGUgaW50ZXJydXB0IGFuZCBzY2hl
ZHVsZXMgYSB0YXNrbGV0LiBNYWluIHJlcXVlc3QgcHJvY2Vzc2luZw0KKyAqCWlzIGRvbmUgaW4g
dGFza2xldC4gQSBzb2Z0d2FyZSBzaGFkb3cgY29weSBvZiB0aGUgSFcgcmluZyBpcyBrZXB0IHRv
DQorICoJbWFpbnRhaW4gdmlydHVhbCB0byBwaHlzaWNhbCB0cmFuc2xhdGlvbi4gQmFzZWQgb24g
dGhlIGludGVybmFsIGluZGV4ZXMNCisgKgltYWludGFpbmVkLCB0aGUgdGFza2xldCBwaWNrcyB0
aGUgZGVzY3JpcHRvciBhZGRyZXNzIGZyb20gc2hhZG93IGNvcHksDQorICoJdXBkYXRlcyB0aGUg
Y29ycmVzcG9uZGluZyBjb29raWUsIHVwZGF0ZXMgdGhlIG91dGJvdW5kIHJpbmcgam9iIHJlbW92
ZWQNCisgKglyZWdpc3RlciBpbiBSRSBoYXJkd2FyZSBhbmQgZXZlbnR1YWxseSBjYWxscyB0aGUg
Y2FsbGJhY2sgZnVuY3Rpb24uIFRoaXMNCisgKgljYWxsYmFjayBmdW5jdGlvbiBnZXRzIHBhc3Nl
ZCBhcyBwYXJ0IG9mIHJlcXVlc3QgZnJvbSBNRCBsYXllci4NCisgKi8NCisNCisjaW5jbHVkZSA8
bGludXgvaW50ZXJydXB0Lmg+DQorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPg0KKyNpbmNsdWRl
IDxsaW51eC9vZl9wbGF0Zm9ybS5oPg0KKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPg0K
KyNpbmNsdWRlIDxsaW51eC9kbWFwb29sLmg+DQorI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5o
Pg0KKyNpbmNsdWRlIDxsaW51eC9pby5oPg0KKyNpbmNsdWRlIDxsaW51eC9zcGlubG9jay5oPg0K
KyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+DQorDQorI2luY2x1ZGUgImZzbF9yYWlkLmgiDQorDQor
I2RlZmluZSBNQVhfWE9SX1NSQ1MJCTE2DQorI2RlZmluZSBNQVhfUFFfU1JDUwkJMTYNCisjZGVm
aW5lIE1BWF9JTklUSUFMX0RFU0NTCTI1Ng0KKyNkZWZpbmUgRlJBTUVfRk9STUFUCQkweDENCisj
ZGVmaW5lIE1BWF9EQVRBX0xFTkdUSAkJKDEwMjQqMTAyNCkNCisNCisjZGVmaW5lIHRvX2ZzbF9y
ZV9kbWFfZGVzYyh0eCkgY29udGFpbmVyX29mKHR4LCBcDQorCQlzdHJ1Y3QgZnNsX3JlX2RtYV9h
c3luY190eF9kZXNjLCBhc3luY190eCkNCisNCisvKiBBZGQgZGVzY3JpcHRvcnMgaW50byBwZXIg
anIgc29mdHdhcmUgcXVldWUgLSBzdWJtaXRfcSAqLyBzdGF0aWMgDQorZG1hX2Nvb2tpZV90IHJl
X2pyX3R4X3N1Ym1pdChzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnR4KSB7DQorCXN0
cnVjdCBmc2xfcmVfZG1hX2FzeW5jX3R4X2Rlc2MgKmRlc2MgPSBOVUxMOw0KKwlzdHJ1Y3QgcmVf
anIgKmpyID0gTlVMTDsNCisJZG1hX2Nvb2tpZV90IGNvb2tpZTsNCisNCisJZGVzYyA9IGNvbnRh
aW5lcl9vZih0eCwgc3RydWN0IGZzbF9yZV9kbWFfYXN5bmNfdHhfZGVzYywgYXN5bmNfdHgpOw0K
KwlqciA9IGNvbnRhaW5lcl9vZih0eC0+Y2hhbiwgc3RydWN0IHJlX2pyLCBjaGFuKTsNCisNCisJ
c3Bpbl9sb2NrX2JoKCZqci0+aW5iX2xvY2spOw0KKw0KKwlqci0+dGltZXIuZGF0YSA9ICh1bnNp
Z25lZCBsb25nKXR4LT5jaGFuOw0KKwljb29raWUgPSBqci0+Y2hhbi5jb29raWUgKyAxOw0KKwlp
ZiAoY29va2llIDwgMCkNCisJCWNvb2tpZSA9IDE7DQorDQorCWRlc2MtPmFzeW5jX3R4LmNvb2tp
ZSA9IGNvb2tpZTsNCisJanItPmNoYW4uY29va2llID0gZGVzYy0+YXN5bmNfdHguY29va2llOw0K
Kwlqci0+cGVuZF9jb3VudCsrOw0KKw0KKwlpZiAoIXRpbWVyX3BlbmRpbmcoJmpyLT50aW1lcikp
DQorCQlhZGRfdGltZXIoJmpyLT50aW1lcik7DQorDQorCXNwaW5fdW5sb2NrX2JoKCZqci0+aW5i
X2xvY2spOw0KKw0KKwlyZXR1cm4gY29va2llOw0KK30NCisNCitzdGF0aWMgdm9pZCByZV9qcl91
bm1hcF9kZXN0X3NyYyhzdHJ1Y3QgZnNsX3JlX2RtYV9hc3luY190eF9kZXNjICpkZXNjKSANCit7
DQorCWludCBpLCBqOw0KKwlzdHJ1Y3QgY21wbmRfZnJhbWUgKmNmOw0KKwlkbWFfYWRkcl90IGRl
c3QxID0gMCwgZGVzdDIgPSAwLCBzcmM7DQorCXN0cnVjdCBkZXZpY2UgKmRldjsNCisJZW51bSBk
bWFfY3RybF9mbGFncyBmbGFnczsNCisJZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGlyOw0KKw0K
KwlCVUdfT04oIWRlc2MpOw0KKwljZiA9IGRlc2MtPmNmX2FkZHI7DQorCWRlc3QxID0gY2ZbMV0u
YWRkcmVzczsNCisJaiA9IDI7DQorCWlmIChkZXNjLT5kZXN0X2NudCA9PSAyKSB7DQorCQlkZXN0
MiA9IGNmWzJdLmFkZHJlc3M7DQorCQlqID0gMzsNCisJfQ0KKwlkZXYgPSBkZXNjLT5qci0+Y2hh
bi5kZXZpY2UtPmRldjsNCisJZmxhZ3MgPSBkZXNjLT5hc3luY190eC5mbGFnczsNCisJaWYgKCEo
ZmxhZ3MgJiBETUFfQ09NUExfU0tJUF9ERVNUX1VOTUFQKSkgew0KKwkJaWYgKGRlc2MtPmNkYl9v
cGNvZGUgPT0gUkVfTU9WRV9PUENPREUpDQorCQkJZGlyID0gRE1BX0ZST01fREVWSUNFOw0KKwkJ
ZWxzZQ0KKwkJCWRpciA9IERNQV9CSURJUkVDVElPTkFMOw0KKw0KKwkJZG1hX3VubWFwX3BhZ2Uo
ZGV2LCBkZXN0MSwgZGVzYy0+ZG1hX2xlbiwgZGlyKTsNCisNCisJCWlmIChkZXN0MikNCisJCQlk
bWFfdW5tYXBfcGFnZShkZXYsIGRlc3QyLCBkZXNjLT5kbWFfbGVuLCBkaXIpOw0KKwl9DQorDQor
CWlmICghKGZsYWdzICYgRE1BX0NPTVBMX1NLSVBfU1JDX1VOTUFQKSkgew0KKwkJZGlyID0gRE1B
X1RPX0RFVklDRTsNCisJCWZvciAoaSA9IGo7IGkgPCBkZXNjLT5zcmNfY250K2o7IGkrKykgew0K
KwkJCXNyYyA9IGNmW2ldLmFkZHJlc3M7DQorCQkJaWYgKHNyYyA9PSBkZXN0MSB8fCBzcmMgPT0g
ZGVzdDIpDQorCQkJCWNvbnRpbnVlOw0KKwkJCWRtYV91bm1hcF9wYWdlKGRldiwgc3JjLCBkZXNj
LT5kbWFfbGVuLCBkaXIpOw0KKwkJfQ0KKwl9DQorfQ0KKw0KK3N0YXRpYyB2b2lkIHJlX2pyX2Rl
c2NfZG9uZShzdHJ1Y3QgZnNsX3JlX2RtYV9hc3luY190eF9kZXNjICpkZXNjKSB7DQorCXN0cnVj
dCByZV9qciAqZG1hX2pyID0gZGVzYy0+anI7DQorCWRtYV9hc3luY190eF9jYWxsYmFjayBjYWxs
YmFjazsNCisJdm9pZCAqY2FsbGJhY2tfcGFyYW07DQorDQorCWNhbGxiYWNrID0gZGVzYy0+YXN5
bmNfdHguY2FsbGJhY2s7DQorCWNhbGxiYWNrX3BhcmFtID0gZGVzYy0+YXN5bmNfdHguY2FsbGJh
Y2tfcGFyYW07DQorDQorCWRtYV9ydW5fZGVwZW5kZW5jaWVzKCZkZXNjLT5hc3luY190eCk7DQor
DQorCWlmIChkbWFfanItPmNvbXBsZXRlZF9jb29raWUgPCBkZXNjLT5hc3luY190eC5jb29raWUp
IHsNCisJCWRtYV9qci0+Y29tcGxldGVkX2Nvb2tpZSA9IGRlc2MtPmFzeW5jX3R4LmNvb2tpZTsN
CisJCWlmIChkbWFfanItPmNvbXBsZXRlZF9jb29raWUgPT0gRE1BX01BWF9DT09LSUUpDQorCQkJ
ZG1hX2pyLT5jb21wbGV0ZWRfY29va2llID0gRE1BX01JTl9DT09LSUU7DQorCX0NCisNCisJcmVf
anJfdW5tYXBfZGVzdF9zcmMoZGVzYyk7DQorDQorCWlmIChjYWxsYmFjaykNCisJCWNhbGxiYWNr
KGNhbGxiYWNrX3BhcmFtKTsNCisNCit9DQorDQorLyoNCisgKiBHZXQgdGhlIHZpcnR1YWwgYWRk
cmVzcyBvZiBzb2Z0d2FyZSBkZXNjIGZyb20gdmlydF9hZGRyLg0KKyAqIFN0b3JpbmcgdGhlIGFk
ZHJlc3Mgb2Ygc29mdHdhcmUgZGVzYyBsaWtlIHRoaXMgbWFrZXMgdGhlDQorICogb3JkZXIgb2Yg
YWxvZ29yaXRobSBhcyBPKDEpDQorICovDQorc3RhdGljIHZvaWQgcmVfanJfZGVxdWV1ZSh1bnNp
Z25lZCBsb25nIGRhdGEpIHsNCisJc3RydWN0IGRldmljZSAqZGV2Ow0KKwlzdHJ1Y3QgcmVfanIg
KmpyOw0KKwlzdHJ1Y3QgZnNsX3JlX2RtYV9hc3luY190eF9kZXNjICpkZXNjOw0KKwl1bnNpZ25l
ZCBpbnQgY291bnQ7DQorCXN0cnVjdCBmc2xfcmVfZG1hX2FzeW5jX3R4X2Rlc2MgKmFja19kZXNj
ID0gTlVMTCwgKl9hY2tfZGVzYyA9IE5VTEw7DQorDQorCWRldiA9IChzdHJ1Y3QgZGV2aWNlICop
ZGF0YTsNCisJanIgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsNCisNCisJd2hpbGUgKChjb3VudCA9
DQorCQlSRV9KUl9PVUJfU0xPVF9GVUxMKGluX2JlMzIoJmpyLT5qcnJlZ3MtPm91YnJpbmdfc2xv
dF9mdWxsKSkpKSB7DQorCQl3aGlsZSAoY291bnQtLSkgew0KKwkJCXNwaW5fbG9ja19iaCgmanIt
Pm91Yl9sb2NrKTsNCisJCQlqci0+b3ViX2NvdW50ICY9IFJJTkdfU0laRSAtIDE7DQorCQkJZGVz
YyA9ICZqci0+ZGVzY3NbanItPm91Yl9jb3VudCsrXTsNCisNCisJCQkvKiBPbmUgam9iIHByb2Nl
c3NlZCAqLw0KKwkJCW91dF9iZTMyKCZqci0+anJyZWdzLT5vdWJyaW5nX2pvYl9ybXZkLA0KKwkJ
CQlSRV9KUl9PVUJfSk9CX1JFTU9WRSgxKSk7DQorCQkJc3Bpbl91bmxvY2tfYmgoJmpyLT5vdWJf
bG9jayk7DQorDQorCQkJc3Bpbl9sb2NrX2JoKCZqci0+ZGVzY19sb2NrKTsNCisJCQlsaXN0X2Fk
ZF90YWlsKCZkZXNjLT5ub2RlLCAmanItPmFja19xKTsNCisJCQlyZV9qcl9kZXNjX2RvbmUoZGVz
Yyk7DQorCQkJc3Bpbl91bmxvY2tfYmgoJmpyLT5kZXNjX2xvY2spOw0KKwkJfQ0KKwl9DQorDQor
CS8qIFRvIHNhdmUgbWVtb3J5LCBwYXJzZSB0aGUgYWNrX3EgYW5kIGZyZWUgdXAgZGVzY3MgKi8N
CisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGFja19kZXNjLCBfYWNrX2Rlc2MsICZqci0+YWNr
X3EsIG5vZGUpIHsNCisJCWlmIChhc3luY190eF90ZXN0X2FjaygmYWNrX2Rlc2MtPmFzeW5jX3R4
KSkgew0KKwkJCXNwaW5fbG9ja19iaCgmanItPmRlc2NfbG9jayk7DQorCQkJbGlzdF9kZWwoJmFj
a19kZXNjLT5ub2RlKTsNCisJCQlhY2tfZGVzYy0+c3RhdGUgPSBSRV9ERVNDX0VNUFRZOw0KKwkJ
CWFja19kZXNjLT5hc3luY190eC5mbGFncyA9IDA7DQorCQkJc3Bpbl91bmxvY2tfYmgoJmpyLT5k
ZXNjX2xvY2spOw0KKwkJfQ0KKwl9DQorfQ0KKw0KKy8qIFBlciBKb2IgUmluZyBpbnRlcnJ1cHQg
aGFuZGxlciAqLw0KK3N0YXRpYyBpcnFyZXR1cm5fdCByZV9qcl9pbnRlcnJ1cHQoaW50IGlycSwg
dm9pZCAqZGF0YSkgew0KKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBkYXRhOw0KKwlzdHJ1Y3QgcmVf
anIgKmpyID0gZGV2X2dldF9kcnZkYXRhKGRldik7DQorCXUzMiBpcnFzdGF0ZSwgc3RhdHVzOw0K
Kw0KKwlpcnFzdGF0ZSA9IGluX2JlMzIoJmpyLT5qcnJlZ3MtPmpyX2ludGVycnVwdF9zdGF0dXMp
Ow0KKwlpZiAoIWlycXN0YXRlKQ0KKwkJcmV0dXJuIElSUV9OT05FOw0KKw0KKwkvKg0KKwkgKiBU
aGVyZSdzIG5vIHdheSBpbiB1cHBlciBsYXllciAocmVhZCBNRCBsYXllcikgdG8gcmVjb3ZlciBm
cm9tDQorCSAqIGVycm9yIGNvbmRpdGlvbnMgZXhjZXB0IHJlc3RhcnQgZXZlcnl0aGluZy4gSW4g
bG9uZyB0ZXJtIHdlDQorCSAqIG5lZWQgdG8gZG8gc29tZXRoaW5nIG1vcmUgdGhhbiBqdXN0IGNy
YXNoaW5nDQorCSAqLw0KKwlpZiAoaXJxc3RhdGUgJiBSRV9KUl9FUlJPUikgew0KKwkJc3RhdHVz
ID0gaW5fYmUzMigmanItPmpycmVncy0+anJfc3RhdHVzKTsNCisJCWRldl9lcnIoZGV2LCAiJXM6
IGpyIGVycm9yIGlycXN0YXRlOiAleCwgc3RhdHVzOiAleFxuIiwNCisJCQkJCV9fZnVuY19fLCBp
cnFzdGF0ZSwgc3RhdHVzKTsNCisNCisJCUJVRygpOw0KKwl9DQorDQorCS8qIENsZWFyIGludGVy
cnVwdCAqLw0KKwlvdXRfYmUzMigmanItPmpycmVncy0+anJfaW50ZXJydXB0X3N0YXR1cywgUkVf
SlJfQ0xFQVJfSU5UKTsNCisNCisJdGFza2xldF9zY2hlZHVsZSgmanItPmlycXRhc2spOw0KKw0K
KwlyZXR1cm4gSVJRX0hBTkRMRUQ7DQorfQ0KKw0KK3N0YXRpYyBlbnVtIGRtYV9zdGF0dXMgcmVf
anJfdHhfc3RhdHVzKHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwNCisJCWRtYV9jb29raWVfdCBjb29r
aWUsIHN0cnVjdCBkbWFfdHhfc3RhdGUgKnR4c3RhdGUpIHsNCisJc3RydWN0IHJlX2pyICpqciA9
IE5VTEw7DQorCWRtYV9jb29raWVfdCBsYXN0X3VzZWQ7DQorCWRtYV9jb29raWVfdCBsYXN0X2Nv
bXBsZXRlOw0KKw0KKwlqciA9IGNvbnRhaW5lcl9vZihjaGFuLCBzdHJ1Y3QgcmVfanIsIGNoYW4p
Ow0KKwlsYXN0X3VzZWQgPSBjaGFuLT5jb29raWU7DQorCXNtcF9tYigpOw0KKwlsYXN0X2NvbXBs
ZXRlID0ganItPmNvbXBsZXRlZF9jb29raWU7DQorDQorCWRtYV9zZXRfdHhfc3RhdGUodHhzdGF0
ZSwgbGFzdF9jb21wbGV0ZSwgbGFzdF91c2VkLCAwKTsNCisNCisJcmV0dXJuIGRtYV9hc3luY19p
c19jb21wbGV0ZShjb29raWUsIGxhc3RfY29tcGxldGUsIGxhc3RfdXNlZCk7IH0NCisNCisNCisv
KiBDb3B5IGRlc2NyaXB0b3IgZnJvbSBwZXIganIgc29mdHdhcmUgcXVldWUgaW50byBoYXJkd2Fy
ZSBqb2IgcmluZyAqLyANCit2b2lkIHJlX2pyX2lzc3VlX3BlbmRpbmcoc3RydWN0IGRtYV9jaGFu
ICpjaGFuKSB7DQorCXN0cnVjdCByZV9qciAqanIgPSBOVUxMOw0KKwlpbnQgYXZhaWwgPSAwOw0K
Kw0KKwlqciA9IGNvbnRhaW5lcl9vZihjaGFuLCBzdHJ1Y3QgcmVfanIsIGNoYW4pOw0KKwlpZiAo
dGltZXJfcGVuZGluZygmanItPnRpbWVyKSkNCisJCWRlbF90aW1lcl9zeW5jKCZqci0+dGltZXIp
Ow0KKw0KKwlzcGluX2xvY2tfYmgoJmpyLT5pbmJfbG9jayk7DQorDQorCWF2YWlsID0gDQorUkVf
SlJfSU5CX1NMT1RfQVZBSUwoaW5fYmUzMigmanItPmpycmVncy0+aW5icmluZ19zbG90X2F2YWls
KSk7DQorDQorCWlmICghKGF2YWlsICYmIGpyLT5wZW5kX2NvdW50KSkNCisJCWdvdG8gb3V0X3Vu
bG9jazsNCisNCisJaWYgKGF2YWlsID4ganItPnBlbmRfY291bnQpDQorCQlhdmFpbCA9IGpyLT5w
ZW5kX2NvdW50Ow0KKw0KKwlqci0+cGVuZF9jb3VudCAtPSBhdmFpbDsNCisJanItPmluYl9jb3Vu
dCA9IChqci0+aW5iX2NvdW50ICsgYXZhaWwpICYgKFJJTkdfU0laRSAtIDEpOw0KKw0KKwkvKiBh
ZGQgam9icyBpbnRvIGpvYiByaW5nICovDQorCW91dF9iZTMyKCZqci0+anJyZWdzLT5pbmJyaW5n
X2FkZF9qb2IsIFJFX0pSX0lOQl9KT0JfQUREKGF2YWlsKSk7DQorDQorb3V0X3VubG9jazoNCisJ
c3Bpbl91bmxvY2tfYmgoJmpyLT5pbmJfbG9jayk7DQorfQ0KKw0KKy8qIFBlciBKb2IgUmluZyB0
aW1lciBoYW5kbGVyICovDQorc3RhdGljIHZvaWQgcmFpZGVfdGltZXJfaGFuZGxlcih1bnNpZ25l
ZCBsb25nIGRhdGEpIHsNCisJc3RydWN0IGRtYV9jaGFuICpjaGFuID0gTlVMTDsNCisJY2hhbiA9
IChzdHJ1Y3QgZG1hX2NoYW4gKilkYXRhOw0KKw0KKwlyZV9qcl9pc3N1ZV9wZW5kaW5nKGNoYW4p
Ow0KKw0KKwlyZXR1cm47DQorfQ0KKw0KK2lubGluZSB2b2lkIGZpbGxfY2ZkX2ZyYW1lKHN0cnVj
dCBjbXBuZF9mcmFtZSAqY2YsIHU4IGluZGV4LA0KKwkJc2l6ZV90IGxlbmd0aCwgZG1hX2FkZHJf
dCBhZGRyLCBib29sIGZpbmFsKSB7DQorCWNmW2luZGV4XS5maW5hbCA9IGZpbmFsOw0KKwljZltp
bmRleF0ubGVuZ3RoID0gbGVuZ3RoOw0KKwljZltpbmRleF0uYWRkcmVzcyA9IGFkZHI7DQorfQ0K
Kw0KK3N0YXRpYyBzdHJ1Y3QgZnNsX3JlX2RtYV9hc3luY190eF9kZXNjICpyZV9qcl9pbml0X2Rl
c2Moc3RydWN0IHJlX2pyICpqciwNCisJc3RydWN0IGZzbF9yZV9kbWFfYXN5bmNfdHhfZGVzYyAq
ZGVzYywgdm9pZCAqY2YsIGRtYV9hZGRyX3QgcGFkZHIpIHsNCisJZGVzYy0+anIgPSBqcjsNCisJ
ZGVzYy0+YXN5bmNfdHgudHhfc3VibWl0ID0gcmVfanJfdHhfc3VibWl0Ow0KKwlkbWFfYXN5bmNf
dHhfZGVzY3JpcHRvcl9pbml0KCZkZXNjLT5hc3luY190eCwgJmpyLT5jaGFuKTsNCisJSU5JVF9M
SVNUX0hFQUQoJmRlc2MtPm5vZGUpOw0KKw0KKwlkZXNjLT5od2Rlc2MtPmZvcm1hdCA9IEZSQU1F
X0ZPUk1BVDsNCisJZGVzYy0+aHdkZXNjLT5hZGRyZXNzID0gcGFkZHI7DQorCWRlc2MtPmNmX2Fk
ZHIgPSBjZjsNCisNCisJZGVzYy0+Y2RiX2FkZHIgPSAodm9pZCAqKShjZiArIFJFX0NGX0RFU0Nf
U0laRSk7DQorCWRlc2MtPmNkYl9wYWRkciA9IHBhZGRyICsgUkVfQ0ZfREVTQ19TSVpFOw0KKw0K
KwlyZXR1cm4gZGVzYzsNCit9DQorDQorc3RhdGljIHN0cnVjdCBmc2xfcmVfZG1hX2FzeW5jX3R4
X2Rlc2MgKnJlX2pyX2FsbG9jX2Rlc2Moc3RydWN0IHJlX2pyICpqciwNCisJCXVuc2lnbmVkIGxv
bmcgZmxhZ3MpDQorew0KKwlzdHJ1Y3QgZnNsX3JlX2RtYV9hc3luY190eF9kZXNjICpkZXNjOw0K
Kw0KKwlzcGluX2xvY2tfYmgoJmpyLT5pbmJfbG9jayk7DQorDQorCWpyLT5pbmJfY291bnQgJj0g
UklOR19TSVpFIC0gMTsNCisJZGVzYyA9ICZqci0+ZGVzY3NbanItPmluYl9jb3VudF07DQorDQor
CWlmIChkZXNjLT5zdGF0ZSAhPSBSRV9ERVNDX0VNUFRZKSB7DQorCQlzcGluX3VubG9ja19iaCgm
anItPmluYl9sb2NrKTsNCisJCXJlX2pyX2lzc3VlX3BlbmRpbmcoJmpyLT5jaGFuKTsNCisJCXJl
dHVybiBOVUxMOw0KKwl9DQorCXNwaW5fdW5sb2NrX2JoKCZqci0+aW5iX2xvY2spOw0KKw0KKwlk
ZXNjLT5zdGF0ZSA9IFJFX0RFU0NfQUxMT0M7DQorCWRlc2MtPmFzeW5jX3R4LmZsYWdzID0gZmxh
Z3M7DQorCXJldHVybiBkZXNjOw0KK30NCisNCitzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9k
ZXNjcmlwdG9yICpyZV9qcl9wcmVwX2dlbnEoDQorCQlzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4sIGRt
YV9hZGRyX3QgZGVzdCwgZG1hX2FkZHJfdCAqc3JjLA0KKwkJdW5zaWduZWQgaW50IHNyY19jbnQs
IGNvbnN0IHVuc2lnbmVkIGNoYXIgKnNjZiwgc2l6ZV90IGxlbiwNCisJCXVuc2lnbmVkIGxvbmcg
ZmxhZ3MpDQorew0KKwlzdHJ1Y3QgcmVfanIgKmpyID0gTlVMTDsNCisJc3RydWN0IGZzbF9yZV9k
bWFfYXN5bmNfdHhfZGVzYyAqZGVzYyA9IE5VTEw7DQorCXN0cnVjdCB4b3JfY2RiICp4b3IgPSBO
VUxMOw0KKwlzdHJ1Y3QgY21wbmRfZnJhbWUgKmNmOw0KKwl1bnNpZ25lZCBpbnQgaSA9IDA7DQor
CXVuc2lnbmVkIGludCBqID0gMDsNCisNCisJaWYgKGxlbiA+IE1BWF9EQVRBX0xFTkdUSCkgew0K
KwkJcHJfZXJyKCIlczogTGVuZ3RoIGdyZWF0ZXIgdGhhbiAlZCBub3Qgc3VwcG9ydGVkXG4iLA0K
KwkJCQlfX2Z1bmNfXywgTUFYX0RBVEFfTEVOR1RIKTsNCisJCXJldHVybiBOVUxMOw0KKwl9DQor
CWpyID0gY29udGFpbmVyX29mKGNoYW4sIHN0cnVjdCByZV9qciwgY2hhbik7DQorCWRlc2MgPSBy
ZV9qcl9hbGxvY19kZXNjKGpyLCBmbGFncyk7DQorCWlmICghZGVzYyB8fCBkZXNjIDwgMCkNCisJ
CXJldHVybiBOVUxMOw0KKw0KKwlkZXNjLT5kbWFfbGVuID0gbGVuOw0KKwlkZXNjLT5kZXN0X2Nu
dCA9IDE7DQorCWRlc2MtPnNyY19jbnQgPSBzcmNfY250Ow0KKw0KKwlkZXNjLT5jZGJfb3Bjb2Rl
ID0gUkVfWE9SX09QQ09ERTsNCisJZGVzYy0+Y2RiX2xlbiA9IHNpemVvZihzdHJ1Y3QgeG9yX2Nk
Yik7DQorDQorCS8qIEZpbGxpbmcgeG9yIENEQiAqLw0KKwl4b3IgPSBkZXNjLT5jZGJfYWRkcjsN
CisJeG9yLT5vcGNvZGUgPSBSRV9YT1JfT1BDT0RFOw0KKwl4b3ItPm5yY3MgPSAoc3JjX2NudCAt
IDEpOw0KKwl4b3ItPmJsa19zaXplID0gUkVfQkxPQ0tfU0laRTsNCisJeG9yLT5lcnJvcl9hdHRy
aWIgPSBJTlRFUlJVUFRfT05fRVJST1I7DQorCXhvci0+ZGF0YV9kZXBlbmQgPSBEQVRBX0RFUEVO
REVOQ1k7DQorDQorCWlmIChzY2YgIT0gTlVMTCkgew0KKwkJLyogY29tcHV0ZSBxID0gc3JjMCpj
b2VmMF5zcmMxKmNvZWYxXi4uLiwgKiBpcyBHRig4KSBtdWx0ICovDQorCQlmb3IgKGkgPSAwOyBp
IDwgc3JjX2NudDsgaSsrKQ0KKwkJCXhvci0+Z2ZtW2ldID0gc2NmW2ldOw0KKwl9IGVsc2Ugew0K
KwkJLyogY29tcHV0ZSBQLCB0aGF0IGlzIFhPUiBhbGwgc3JjcyAqLw0KKwkJZm9yIChpID0gMDsg
aSA8IHNyY19jbnQ7IGkrKykNCisJCQl4b3ItPmdmbVtpXSA9IDE7DQorCX0NCisNCisJLyogRmls
bGluZyBmcmFtZSAwIG9mIGNvbXBvdW5kIGZyYW1lIGRlc2NyaXB0b3Igd2l0aCBDREIgKi8NCisJ
Y2YgPSBkZXNjLT5jZl9hZGRyOw0KKwlmaWxsX2NmZF9mcmFtZShjZiwgMCwgZGVzYy0+Y2RiX2xl
biwgZGVzYy0+Y2RiX3BhZGRyLCAwKTsNCisNCisJLyogRmlsbCBDRkQncyAxc3QgZnJhbWUgd2l0
aCBkZXN0IGJ1ZmZlciAqLw0KKwlmaWxsX2NmZF9mcmFtZShjZiwgMSwgbGVuLCBkZXN0LCAwKTsN
CisNCisJLyogRmlsbCBDRkQncyByZXN0IG9mIHRoZSBmcmFtZXMgd2l0aCBzb3VyY2UgYnVmZmVy
cyAqLw0KKwlmb3IgKGkgPSAyLCBqID0gMDsgaiA8IHNyY19jbnQ7IGkrKywgaisrKQ0KKwkJZmls
bF9jZmRfZnJhbWUoY2YsIGksIGxlbiwgc3JjW2pdLCAwKTsNCisNCisJLyogU2V0dGluZyB0aGUg
ZmluYWwgYml0IGluIHRoZSBsYXN0IHNvdXJjZSBidWZmZXIgZnJhbWUgaW4gQ0ZEICovDQorCWNm
W2kgLSAxXS5maW5hbCA9IDE7DQorDQorCXJldHVybiAmZGVzYy0+YXN5bmNfdHg7DQorfQ0KKw0K
Ky8qDQorICogUHJlcCBmdW5jdGlvbiBmb3IgUCBwYXJpdHkgY2FsY3VsYXRpb24uSW4gUkFJRCBF
bmdpbmUgdGVybWlub2xvZ3ksDQorICogWE9SIGNhbGN1bGF0aW9uIGlzIGNhbGxlZCBHZW5RIGNh
bGN1bGF0aW9uIGRvbmUgdGhyb3VnaCBHZW5RIGNvbW1hbmQgIA0KKyovIHN0YXRpYyBzdHJ1Y3Qg
ZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnJlX2pyX3ByZXBfZG1hX3hvcigNCisJCXN0cnVjdCBk
bWFfY2hhbiAqY2hhbiwgZG1hX2FkZHJfdCBkZXN0LCBkbWFfYWRkcl90ICpzcmMsDQorCQl1bnNp
Z25lZCBpbnQgc3JjX2NudCwgc2l6ZV90IGxlbiwgdW5zaWduZWQgbG9uZyBmbGFncykgew0KKwkv
KiBOVUxMIGxldCBnZW5xIHRha2UgYWxsIGNvZWYgYXMgMSAqLw0KKwlyZXR1cm4gcmVfanJfcHJl
cF9nZW5xKGNoYW4sIGRlc3QsIHNyYywgc3JjX2NudCwgTlVMTCwgbGVuLCBmbGFncyk7IH0NCisN
CisvKg0KKyAqIFByZXAgZnVuY3Rpb24gZm9yIFAvUSBwYXJpdHkgY2FsY3VsYXRpb24uSW4gUkFJ
RCBFbmdpbmUgdGVybWlub2xvZ3ksDQorICogUC9RIGNhbGN1bGF0aW9uIGlzIGNhbGxlZCBHZW5R
USBkb25lIHRocm91Z2ggR2VuUVEgY29tbWFuZCAgKi8gDQorc3RhdGljIHN0cnVjdCBkbWFfYXN5
bmNfdHhfZGVzY3JpcHRvciAqcmVfanJfcHJlcF9wcSgNCisJCXN0cnVjdCBkbWFfY2hhbiAqY2hh
biwgZG1hX2FkZHJfdCAqZGVzdCwgZG1hX2FkZHJfdCAqc3JjLA0KKwkJdW5zaWduZWQgaW50IHNy
Y19jbnQsIGNvbnN0IHVuc2lnbmVkIGNoYXIgKnNjZiwgc2l6ZV90IGxlbiwNCisJCXVuc2lnbmVk
IGxvbmcgZmxhZ3MpDQorew0KKwlzdHJ1Y3QgcmVfanIgKmpyID0gTlVMTDsNCisJc3RydWN0IGZz
bF9yZV9kbWFfYXN5bmNfdHhfZGVzYyAqZGVzYyA9IE5VTEw7DQorCXN0cnVjdCBwcV9jZGIgKnBx
ID0gTlVMTDsNCisJc3RydWN0IGNtcG5kX2ZyYW1lICpjZjsNCisJdTggKnA7DQorCWludCBnZm1x
X2xlbiwgaSwgajsNCisNCisJaWYgKGxlbiA+IE1BWF9EQVRBX0xFTkdUSCkgew0KKwkJcHJfZXJy
KCIlczogTGVuZ3RoIGdyZWF0ZXIgdGhhbiAlZCBub3Qgc3VwcG9ydGVkXG4iLA0KKwkJCQlfX2Z1
bmNfXywgTUFYX0RBVEFfTEVOR1RIKTsNCisJCXJldHVybiBOVUxMOw0KKwl9DQorDQorCS8qDQor
CSAqIFJFIHJlcXVpcmVzIGF0IGxlYXN0IDIgc291cmNlcywgaWYgZ2l2ZW4gb25seSBvbmUgc291
cmNlLCB3ZSBwYXNzIHRoZQ0KKwkgKiBzZWNvbmQgc291cmNlIHNhbWUgYXMgdGhlIGZpcnN0IG9u
ZS4NCisJICogV2l0aCBvbmx5IG9uZSBzb3VyY2UsIGdlbmVyYXRlIFAgaXMgbWVhbmluZ2xlc3Ms
IG9ubHkgY2FyZSBRLg0KKwkgKi8NCisJaWYgKHNyY19jbnQgPT0gMSkgew0KKwkJc3RydWN0IGRt
YV9hc3luY190eF9kZXNjcmlwdG9yICp0eCA9IE5VTEw7DQorCQlkbWFfYWRkcl90IGRtYV9zcmNb
Ml07DQorCQl1bnNpZ25lZCBjaGFyIGNvZWZbMl07DQorCQlkbWFfc3JjWzBdID0gKnNyYzsNCisJ
CWNvZWZbMF0gPSAqc2NmOw0KKwkJZG1hX3NyY1sxXSA9ICpzcmM7DQorCQljb2VmWzFdID0gMDsN
CisJCXR4ID0gcmVfanJfcHJlcF9nZW5xKGNoYW4sIGRlc3RbMV0sIGRtYV9zcmMsIDIsIGNvZWYs
IGxlbiwNCisJCQkJZmxhZ3MpOw0KKwkJaWYgKHR4KSB7DQorCQkJZGVzYyA9IHRvX2ZzbF9yZV9k
bWFfZGVzYyh0eCk7DQorCQkJZGVzYy0+c3JjX2NudCA9IDE7DQorCQl9DQorCQlyZXR1cm4gdHg7
DQorCX0NCisNCisJLyoNCisJICogRHVyaW5nIFJBSUQ2IGFycmF5IGNyZWF0aW9uLCBMaW51eCdz
IE1EIGxheWVyIGdldHMgUCBhbmQgUQ0KKwkgKiBjYWxjdWxhdGVkIHNlcGFyYXRlbHkgaW4gdHdv
IHN0ZXBzLiBCdXQgb3VyIFJBSUQgRW5naW5lIGhhcw0KKwkgKiB0aGUgY2FwYWJpbGl0eSB0byBj
YWxjdWxhdGUgYm90aCBQIGFuZCBRIHdpdGggYSBzaW5nbGUgY29tbWFuZA0KKwkgKiBIZW5jZSB0
byBtZXJnZSB3ZWxsIHdpdGggTUQgbGF5ZXIsIHdlIG5lZWQgdG8gcHJvdmlkZSBhIGhvb2sNCisJ
ICogaGVyZSBhbmQgY2FsbCByZV9qcV9wcmVwX2dlbnEoKSBmdW5jdGlvbg0KKwkgKi8NCisNCisJ
aWYgKGZsYWdzICYgRE1BX1BSRVBfUFFfRElTQUJMRV9QKQ0KKwkJcmV0dXJuIHJlX2pyX3ByZXBf
Z2VucShjaGFuLCBkZXN0WzFdLCBzcmMsIHNyY19jbnQsDQorCQkJCXNjZiwgbGVuLCBmbGFncyk7
DQorDQorCWpyID0gY29udGFpbmVyX29mKGNoYW4sIHN0cnVjdCByZV9qciwgY2hhbik7DQorCWRl
c2MgPSByZV9qcl9hbGxvY19kZXNjKGpyLCBmbGFncyk7DQorCWlmICghZGVzYyB8fCBkZXNjIDwg
MCkNCisJCXJldHVybiBOVUxMOw0KKw0KKwlkZXNjLT5kbWFfbGVuID0gbGVuOw0KKwlkZXNjLT5k
ZXN0X2NudCA9IDI7DQorCWRlc2MtPnNyY19jbnQgPSBzcmNfY250Ow0KKw0KKwlkZXNjLT5jZGJf
b3Bjb2RlID0gUkVfUFFfT1BDT0RFOw0KKwlkZXNjLT5jZGJfbGVuID0gc2l6ZW9mKHN0cnVjdCBw
cV9jZGIpOw0KKw0KKwkvKiBGaWxsaW5nIEdlblFRIENEQiAqLw0KKwlwcSA9IGRlc2MtPmNkYl9h
ZGRyOw0KKwlwcS0+b3Bjb2RlID0gUkVfUFFfT1BDT0RFOw0KKwlwcS0+YmxrX3NpemUgPSBSRV9C
TE9DS19TSVpFOw0KKwlwcS0+YnVmZmVyX2F0dHJpYiA9IEJVRkZFUkFCTEVfT1VUUFVUOw0KKwlw
cS0+ZGF0YV9kZXBlbmQgPSBEQVRBX0RFUEVOREVOQ1k7DQorCXBxLT5ucmNzID0gKHNyY19jbnQg
LSAxKTsNCisNCisJcCA9IHBxLT5nZm1fcTE7DQorCS8qIEluaXQgZ2ZtX3ExW10gKi8NCisJZm9y
IChpID0gMDsgaSA8IHNyY19jbnQ7IGkrKykNCisJCXBbaV0gPSAxOw0KKw0KKwkvKiBBbGlnbiBn
Zm1bXSB0byAzMmJpdCAqLw0KKwlnZm1xX2xlbiA9ICgoc3JjX2NudCszKS80KSo0Ow0KKw0KKwkv
KiBJbml0IGdmbV9xMltdICovDQorCXAgKz0gZ2ZtcV9sZW47DQorCWZvciAoaSA9IDA7IGkgPCBz
cmNfY250OyBpKyspDQorCQlwW2ldID0gc2NmW2ldOw0KKw0KKwkvKiBGaWxsaW5nIGZyYW1lIDAg
b2YgY29tcG91bmQgZnJhbWUgZGVzY3JpcHRvciB3aXRoIENEQiAqLw0KKwljZiA9IGRlc2MtPmNm
X2FkZHI7DQorCWZpbGxfY2ZkX2ZyYW1lKGNmLCAwLCBkZXNjLT5jZGJfbGVuLCBkZXNjLT5jZGJf
cGFkZHIsIDApOw0KKw0KKwkvKiBGaWxsIENGRCdzIDFzdCAmIDJuZCBmcmFtZSB3aXRoIGRlc3Qg
YnVmZmVycyAqLw0KKwlmb3IgKGkgPSAxLCBqID0gMDsgaSA8IDM7IGkrKywgaisrKQ0KKwkJZmls
bF9jZmRfZnJhbWUoY2YsIGksIGxlbiwgZGVzdFtqXSwgMCk7DQorDQorCS8qIEZpbGwgQ0ZEJ3Mg
cmVzdCBvZiB0aGUgZnJhbWVzIHdpdGggc291cmNlIGJ1ZmZlcnMgKi8NCisJZm9yIChpID0gMywg
aiA9IDA7IGogPCBzcmNfY250OyBpKyssIGorKykNCisJCWZpbGxfY2ZkX2ZyYW1lKGNmLCBpLCBs
ZW4sIHNyY1tqXSwgMCk7DQorDQorCS8qIFNldHRpbmcgdGhlIGZpbmFsIGJpdCBpbiB0aGUgbGFz
dCBzb3VyY2UgYnVmZmVyIGZyYW1lIGluIENGRCAqLw0KKwljZltpIC0gMV0uZmluYWwgPSAxOw0K
Kw0KKwlyZXR1cm4gJmRlc2MtPmFzeW5jX3R4Ow0KK30NCisNCisvKg0KKyAqIFByZXAgZnVuY3Rp
b24gZm9yIG1lbWNweS4gSW4gUkFJRCBFbmdpbmUsIG1lbWNweSBpcyBkb25lIHRocm91Z2ggDQor
TU9WRQ0KKyAqIGNvbW1hbmQuIExvZ2ljIG9mIHRoaXMgZnVuY3Rpb24gd2lsbCBuZWVkIHRvIGJl
IG1vZGlmaWVkIG9uY2UgDQorbXVsdGlwYWdlDQorICogc3VwcG9ydCBpcyBhZGRlZCBpbiBMaW51
eCdzIE1EL0FTWU5DIExheWVyICAqLyBzdGF0aWMgc3RydWN0IA0KK2RtYV9hc3luY190eF9kZXNj
cmlwdG9yICpyZV9qcl9wcmVwX21lbWNweSgNCisJCXN0cnVjdCBkbWFfY2hhbiAqY2hhbiwgZG1h
X2FkZHJfdCBkZXN0LCBkbWFfYWRkcl90IHNyYywNCisJCXNpemVfdCBsZW4sIHVuc2lnbmVkIGxv
bmcgZmxhZ3MpDQorew0KKwlzdHJ1Y3QgcmVfanIgKmpyID0gTlVMTDsNCisJc3RydWN0IGZzbF9y
ZV9kbWFfYXN5bmNfdHhfZGVzYyAqZGVzYyA9IE5VTEw7DQorCXNpemVfdCBsZW5ndGggPSAwOw0K
KwlzdHJ1Y3QgY21wbmRfZnJhbWUgKmNmID0gTlVMTDsNCisJc3RydWN0IG1vdmVfY2RiICptb3Zl
ID0gTlVMTDsNCisNCisJanIgPSBjb250YWluZXJfb2YoY2hhbiwgc3RydWN0IHJlX2pyLCBjaGFu
KTsNCisNCisJaWYgKGxlbiA+IE1BWF9EQVRBX0xFTkdUSCkgew0KKwkJcHJfZXJyKCIlczogTGVu
Z3RoIGdyZWF0ZXIgdGhhbiAlZCBub3Qgc3VwcG9ydGVkXG4iLA0KKwkJCQlfX2Z1bmNfXywgTUFY
X0RBVEFfTEVOR1RIKTsNCisJCXJldHVybiBOVUxMOw0KKwl9DQorDQorCWRlc2MgPSByZV9qcl9h
bGxvY19kZXNjKGpyLCBmbGFncyk7DQorCWlmICghZGVzYyB8fCBkZXNjIDwgMCkNCisJCXJldHVy
biBOVUxMOw0KKw0KKwlkZXNjLT5kbWFfbGVuID0gbGVuOw0KKwlkZXNjLT5zcmNfY250ID0gMTsN
CisJZGVzYy0+ZGVzdF9jbnQgPSAxOw0KKw0KKwlkZXNjLT5jZGJfb3Bjb2RlID0gUkVfTU9WRV9P
UENPREU7DQorCWRlc2MtPmNkYl9sZW4gPSBzaXplb2Yoc3RydWN0IG1vdmVfY2RiKTsNCisNCisJ
LyogRmlsbGluZyBtb3ZlIENEQiAqLw0KKwltb3ZlID0gZGVzYy0+Y2RiX2FkZHI7DQorCW1vdmUt
Pm9wY29kZSA9IFJFX01PVkVfT1BDT0RFOyAvKiBVbmljYXN0IG1vdmUgKi8NCisJbW92ZS0+Ymxr
X3NpemUgPSBSRV9CTE9DS19TSVpFOw0KKwltb3ZlLT5lcnJvcl9hdHRyaWIgPSBJTlRFUlJVUFRf
T05fRVJST1I7DQorCW1vdmUtPmRhdGFfZGVwZW5kID0gREFUQV9ERVBFTkRFTkNZOw0KKw0KKwkv
KiBGaWxsaW5nIGZyYW1lIDAgb2YgQ0ZEIHdpdGggbW92ZSBDREIgKi8NCisJY2YgPSBkZXNjLT5j
Zl9hZGRyOw0KKwlmaWxsX2NmZF9mcmFtZShjZiwgMCwgZGVzYy0+Y2RiX2xlbiwgZGVzYy0+Y2Ri
X3BhZGRyLCAwKTsNCisNCisJbGVuZ3RoID0gbWluX3Qoc2l6ZV90LCBsZW4sIE1BWF9EQVRBX0xF
TkdUSCk7DQorDQorCS8qIEZpbGwgQ0ZEJ3MgMXN0IGZyYW1lIHdpdGggZGVzdCBidWZmZXIgKi8N
CisJZmlsbF9jZmRfZnJhbWUoY2YsIDEsIGxlbmd0aCwgZGVzdCwgMCk7DQorDQorCS8qIEZpbGwg
Q0ZEJ3MgMm5kIGZyYW1lIHdpdGggc3JjIGJ1ZmZlciAqLw0KKwlmaWxsX2NmZF9mcmFtZShjZiwg
MiwgbGVuZ3RoLCBzcmMsIDEpOw0KKw0KKwlyZXR1cm4gJmRlc2MtPmFzeW5jX3R4Ow0KK30NCisN
CitzdGF0aWMgaW50IHJlX2pyX2FsbG9jX2NoYW5fcmVzb3VyY2VzKHN0cnVjdCBkbWFfY2hhbiAq
Y2hhbikgew0KKwlpbnQgaTsNCisJc3RydWN0IGZzbF9yZV9kbWFfYXN5bmNfdHhfZGVzYyAqZGVz
YzsNCisJc3RydWN0IHJlX2pyICpqciA9IGNvbnRhaW5lcl9vZihjaGFuLCBzdHJ1Y3QgcmVfanIs
IGNoYW4pOw0KKwl2b2lkICpjZiA9IE5VTEw7DQorCWRtYV9hZGRyX3QgcGFkZHI7DQorDQorCWpy
LT5kZXNjcyA9IGt6YWxsb2Moc2l6ZW9mKCpkZXNjKSAqIFJJTkdfU0laRSwgR0ZQX0tFUk5FTCk7
DQorCWlmICghanItPmRlc2NzKSB7DQorCQlkZXZfZXJyKGpyLT5kZXYsICIlczogTm8gbWVtb3J5
IGZvciBzdyBkZXNjcmlwdG9yIHJpbmdcbiIsDQorCQkJX19mdW5jX18pOw0KKwkJZ290byBlcnJf
ZnJlZTsNCisJfQ0KKw0KKwljZiA9IGRtYV9wb29sX2FsbG9jKGpyLT5yZV9kZXYtPmRlc2NfcG9v
bCwgR0ZQX0FUT01JQywgJnBhZGRyKTsNCisJaWYgKCFjZikgew0KKwkJZGV2X2Vycihqci0+ZGV2
LCAiJXM6IE5vIG1lbW9yeSBmb3IgZG1hIGRlc2NyaXB0b3IgcmluZ1xuIiwNCisJCQlfX2Z1bmNf
Xyk7DQorCQlnb3RvIGVycl9mcmVlOw0KKwl9DQorCW1lbXNldChjZiwgMCwgUkVfQ0ZfQ0RCX1NJ
WkUgKiBSSU5HX1NJWkUpOw0KKwlqci0+Y2ZzID0gY2Y7DQorCWpyLT5waHlzID0gcGFkZHI7DQor
DQorCWZvciAoaSA9IDA7IGkgPCBSSU5HX1NJWkU7IGkrKykgew0KKwkJdTMyIG9mZnNldCA9IGkg
KiBSRV9DRl9DREJfU0laRTsNCisJCWRlc2MgPSAmanItPmRlc2NzW2ldOw0KKwkJZGVzYy0+aHdk
ZXNjID0gJmpyLT5pbmJfcmluZ192aXJ0X2FkZHJbaV07DQorCQlyZV9qcl9pbml0X2Rlc2MoanIs
IGRlc2MsIGNmICsgb2Zmc2V0LCBwYWRkciArIG9mZnNldCk7DQorCQlkZXNjLT5zdGF0ZSA9IFJF
X0RFU0NfRU1QVFk7DQorCX0NCisJcmV0dXJuIDA7DQorDQorZXJyX2ZyZWU6DQorCWtmcmVlKGpy
LT5kZXNjcyk7DQorCXJldHVybiAtRU5PTUVNOw0KK30NCisNCitzdGF0aWMgdm9pZCByZV9qcl9m
cmVlX2NoYW5fcmVzb3VyY2VzKHN0cnVjdCBkbWFfY2hhbiAqY2hhbikgew0KKwlzdHJ1Y3QgcmVf
anIgKmpyID0gY29udGFpbmVyX29mKGNoYW4sIHN0cnVjdCByZV9qciwgY2hhbik7DQorCWRtYV9w
b29sX2ZyZWUoanItPnJlX2Rldi0+ZGVzY19wb29sLCBqci0+Y2ZzLCBqci0+cGh5cyk7DQorCWtm
cmVlKGpyLT5kZXNjcyk7DQorCXJldHVybjsNCit9DQorDQoraW50IHJlX2pyX3Byb2JlKHN0cnVj
dCBwbGF0Zm9ybV9kZXZpY2UgKm9mZGV2LA0KKwkJc3RydWN0IGRldmljZV9ub2RlICpucCwgdTgg
cSwgdTMyICpvZmYpIHsNCisJc3RydWN0IGRldmljZSAqZGV2ID0gTlVMTDsNCisJc3RydWN0IHJl
X2Rydl9wcml2YXRlICpyZXByaXYgPSBOVUxMOw0KKwlzdHJ1Y3QgcmVfanIgKmpyID0gTlVMTDsN
CisJc3RydWN0IGRtYV9kZXZpY2UgKmRtYV9kZXYgPSBOVUxMOw0KKwl1MzIgKnB0ciA9IE5VTEw7
DQorCXUzMiBzdGF0dXM7DQorCWludCByZXQgPSAwOw0KKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl
ICpqcl9vZmRldiA9IE5VTEw7DQorDQorCWRldiA9ICZvZmRldi0+ZGV2Ow0KKwlyZXByaXYgPSBk
ZXZfZ2V0X2RydmRhdGEoZGV2KTsNCisJZG1hX2RldiA9ICZyZXByaXYtPmRtYV9kZXY7DQorDQor
CWpyID0ga3phbGxvYyhzaXplb2Yoc3RydWN0IHJlX2pyKSwgR0ZQX0tFUk5FTCk7DQorCWlmICgh
anIpIHsNCisJCWRldl9lcnIoZGV2LCAiJXM6IE5vIGZyZWUgbWVtb3J5IGZvciBhbGxvY2F0aW5n
IEpSIHN0cnVjdFxuIiwNCisJCQlfX2Z1bmNfXyk7DQorCQlyZXR1cm4gLUVOT01FTTsNCisJfQ0K
Kw0KKwlqcl9vZmRldiA9IG9mX3BsYXRmb3JtX2RldmljZV9jcmVhdGUobnAsIE5VTEwsIGRldik7
DQorCWlmIChqcl9vZmRldiA9PSBOVUxMKSB7DQorCQlkZXZfZXJyKGRldiwgIiVzOiBOb3QgYWJs
ZSB0byBjcmVhdGUgb2ZkZXYgZm9yIGpyICVkXG4iLA0KKwkJCV9fZnVuY19fLCBxKTsNCisJCXJl
dCA9IC1FSU5WQUw7DQorCQlnb3RvIGVycl9mcmVlOw0KKwl9DQorCWRldl9zZXRfZHJ2ZGF0YSgm
anJfb2ZkZXYtPmRldiwganIpOw0KKw0KKwlwdHIgPSAodTMyICopb2ZfZ2V0X3Byb3BlcnR5KG5w
LCAicmVnIiwgTlVMTCk7DQorCWlmICghcHRyKSB7DQorCQlkZXZfZXJyKGRldiwgIiVzOiBSZWcg
cHJvcGVydHkgbm90IGZvdW5kIGluIEpSIG51bWJlciAlZFxuIiwNCisJCQlfX2Z1bmNfXywgcSk7
DQorCQlyZXQgPSAtRU5PREVWOw0KKwkJZ290byBlcnJfZnJlZTsNCisJfQ0KKw0KKwlqci0+anJy
ZWdzID0gKHN0cnVjdCBqcl9jb25maWdfcmVncyAqKSgodTggKilyZXByaXYtPnJlX3JlZ3MgKw0K
KwkJCSpvZmYgKyAqcHRyKTsNCisNCisJanItPmlycSA9IGlycV9vZl9wYXJzZV9hbmRfbWFwKG5w
LCAwKTsNCisJaWYgKGpyLT5pcnEgPT0gTk9fSVJRKSB7DQorCQlkZXZfZXJyKGRldiwgIiVzOiBO
byBJUlEgZGVmaW5lZCBmb3IgSlIgJWRcbiIsIF9fZnVuY19fLCBxKTsNCisJCXJldCA9IC1FTk9E
RVY7DQorCQlnb3RvIGVycl9mcmVlOw0KKwl9DQorDQorCXRhc2tsZXRfaW5pdCgmanItPmlycXRh
c2ssIHJlX2pyX2RlcXVldWUsDQorCQkJKHVuc2lnbmVkIGxvbmcpJmpyX29mZGV2LT5kZXYpOw0K
Kw0KKwlyZXQgPSByZXF1ZXN0X2lycShqci0+aXJxLCByZV9qcl9pbnRlcnJ1cHQsIDAsICJyZS1q
ciIsICZqcl9vZmRldi0+ZGV2KTsNCisJaWYgKHJldCkgew0KKwkJZGV2X2VycihkZXYsICIlczog
VW5hYmxlIHRvIHJlZ2lzdGVyIEpSIGludGVycnVwdCBmb3IgSlIgJWRcbiIsDQorCQkJX19mdW5j
X18sIHEpOw0KKwkJcmV0ID0gLUVJTlZBTDsNCisJCWdvdG8gZXJyX2ZyZWU7DQorCX0NCisNCisJ
cmVwcml2LT5yZV9qcnNbcV0gPSBqcjsNCisJanItPmNoYW4uZGV2aWNlID0gZG1hX2RldjsNCisJ
anItPmNoYW4ucHJpdmF0ZSA9IGpyOw0KKwlqci0+ZGV2ID0gJmpyX29mZGV2LT5kZXY7DQorCWpy
LT5yZV9kZXYgPSByZXByaXY7DQorCWpyLT5wZW5kX2NvdW50ID0gMDsNCisJSU5JVF9MSVNUX0hF
QUQoJmpyLT5hY2tfcSk7DQorCXNwaW5fbG9ja19pbml0KCZqci0+ZGVzY19sb2NrKTsNCisJc3Bp
bl9sb2NrX2luaXQoJmpyLT5pbmJfbG9jayk7DQorCXNwaW5fbG9ja19pbml0KCZqci0+b3ViX2xv
Y2spOw0KKw0KKwlpbml0X3RpbWVyKCZqci0+dGltZXIpOw0KKwlqci0+dGltZXIuZXhwaXJlcyA9
IGppZmZpZXMgKyAxMCpIWjsNCisJanItPnRpbWVyLmZ1bmN0aW9uID0gcmFpZGVfdGltZXJfaGFu
ZGxlcjsNCisNCisJbGlzdF9hZGRfdGFpbCgmanItPmNoYW4uZGV2aWNlX25vZGUsICZkbWFfZGV2
LT5jaGFubmVscyk7DQorCWRtYV9kZXYtPmNoYW5jbnQrKzsNCisNCisJanItPmluYl9yaW5nX3Zp
cnRfYWRkciA9IGRtYV9wb29sX2FsbG9jKGpyLT5yZV9kZXYtPmh3X2Rlc2NfcG9vbCwNCisJCUdG
UF9BVE9NSUMsICZqci0+aW5iX3BoeXNfYWRkcik7DQorDQorCWlmICghanItPmluYl9yaW5nX3Zp
cnRfYWRkcikgew0KKwkJZGV2X2VycihkZXYsICIlczpObyBkbWEgbWVtb3J5IGZvciBpbmJfcmlu
Z192aXJ0X2FkZHJcbiIsDQorCQkJX19mdW5jX18pOw0KKwkJcmV0ID0gLUVOT01FTTsNCisJCWdv
dG8gZXJyX2ZyZWU7DQorCX0NCisNCisJanItPm91Yl9yaW5nX3ZpcnRfYWRkciA9IGRtYV9wb29s
X2FsbG9jKGpyLT5yZV9kZXYtPmh3X2Rlc2NfcG9vbCwNCisJCUdGUF9BVE9NSUMsICZqci0+b3Vi
X3BoeXNfYWRkcik7DQorDQorCWlmICghanItPm91Yl9yaW5nX3ZpcnRfYWRkcikgew0KKwkJZGV2
X2VycihkZXYsICIlczpObyBkbWEgbWVtb3J5IGZvciBvdWJfcmluZ192aXJ0X2FkZHJcbiIsDQor
CQkJX19mdW5jX18pOw0KKwkJcmV0ID0gLUVOT01FTTsNCisJCWdvdG8gZXJyX2ZyZWU7DQorCX0N
CisNCisJanItPmluYl9jb3VudCA9IDA7DQorCWpyLT5wZW5kX2NvdW50ID0gMDsNCisJanItPm91
Yl9jb3VudCA9IDA7DQorDQorCXN0YXR1cyA9IGluX2JlMzIoJmpyLT5qcnJlZ3MtPmpyX3N0YXR1
cyk7DQorDQorCWlmIChzdGF0dXMgJiBSRV9KUl9QQVVTRSkgew0KKwkJZGV2X2luZm8oZGV2LCAi
JXM6IEpSIGlzIGluIHBhdXNlZCBzdGF0ZS4uLmVuYWJsZSBpdFxuIiwNCisJCQlfX2Z1bmNfXyk7
DQorCX0gZWxzZSB7DQorCQlkZXZfZXJyKGRldiwgIiVzOiBFcnJvcjotIEpSIHNodWQgYmUgaW4g
cGF1c2VkIHN0YXRlXG4iLA0KKwkJCV9fZnVuY19fKTsNCisJCXJldCA9IC1FSU5WQUw7DQorCQln
b3RvIHBvb2xfZnJlZTsNCisJfQ0KKw0KKwkvKiBQcm9ncmFtIHRoZSBJbmJvdW5kL091dGJvdW5k
IHJpbmcgYmFzZSBhZGRyZXNzZXMgYW5kIHNpemUgKi8NCisJb3V0X2JlMzIoJmpyLT5qcnJlZ3Mt
PmluYnJpbmdfYmFzZV9oLA0KKwkJCWpyLT5pbmJfcGh5c19hZGRyICYgUkVfSlJfQUREUkVTU19C
SVRfTUFTSyk7DQorCW91dF9iZTMyKCZqci0+anJyZWdzLT5vdWJyaW5nX2Jhc2VfaCwNCisJCQlq
ci0+b3ViX3BoeXNfYWRkciAmIFJFX0pSX0FERFJFU1NfQklUX01BU0spOw0KKwlvdXRfYmUzMigm
anItPmpycmVncy0+aW5icmluZ19iYXNlX2wsDQorCQkJanItPmluYl9waHlzX2FkZHIgPj4gUkVf
SlJfQUREUkVTU19CSVRfU0hJRlQpOw0KKwlvdXRfYmUzMigmanItPmpycmVncy0+b3VicmluZ19i
YXNlX2wsDQorCQkJanItPm91Yl9waHlzX2FkZHIgPj4gUkVfSlJfQUREUkVTU19CSVRfU0hJRlQp
Ow0KKwlvdXRfYmUzMigmanItPmpycmVncy0+aW5icmluZ19zaXplLCBSSU5HX1NJWkUgPDwgUklO
R19TSVpFX1NISUZUKTsNCisJb3V0X2JlMzIoJmpyLT5qcnJlZ3MtPm91YnJpbmdfc2l6ZSwgUklO
R19TSVpFIDw8IFJJTkdfU0laRV9TSElGVCk7DQorDQorCS8qIFJlYWQgTElPRE4gdmFsdWUgZnJv
bSB1LWJvb3QgKi8NCisJc3RhdHVzID0gaW5fYmUzMigmanItPmpycmVncy0+anJfY29uZmlnXzEp
ICYgUkVfSlJfUkVHX0xJT0ROX01BU0s7DQorDQorCS8qIFByb2dyYW0gdGhlIENGRyByZWcgKi8N
CisJb3V0X2JlMzIoJmpyLT5qcnJlZ3MtPmpyX2NvbmZpZ18xLA0KKwkJCVJFX0pSX0NGRzFfQ0JT
SSB8IFJFX0pSX0NGRzFfQ0JTMCB8IHN0YXR1cyk7DQorDQorCS8qIEVuYWJsZSBSRS9KUiAqLw0K
KwlvdXRfYmUzMigmanItPmpycmVncy0+anJfY29tbWFuZCwgUkVfSlJfRU5BQkxFKTsNCisNCisJ
cmV0dXJuIDA7DQorDQorcG9vbF9mcmVlOg0KKwlkbWFfcG9vbF9mcmVlKGpyLT5yZV9kZXYtPmh3
X2Rlc2NfcG9vbCwganItPmluYl9yaW5nX3ZpcnRfYWRkciwNCisJCQlqci0+aW5iX3BoeXNfYWRk
cik7DQorZXJyX2ZyZWU6DQorCWtmcmVlKGpyKTsNCisJcmV0dXJuIHJldDsNCit9DQorDQorLyog
UHJvYmUgZnVuY3Rpb24gZm9yIFJBSUQgRW5naW5lICovDQorc3RhdGljIGludCBfX2RldmluaXQg
cmFpZGVfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqb2ZkZXYpIHsNCisJc3RydWN0IHJl
X2Rydl9wcml2YXRlICpyZXByaXYgPSBOVUxMOw0KKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBOVUxM
Ow0KKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wID0gTlVMTDsNCisJc3RydWN0IGRldmljZV9ub2Rl
ICpjaGlsZCA9IE5VTEw7DQorCXUzMiAqb2ZmID0gTlVMTDsNCisJdTggcmlkeCA9IDA7DQorCXN0
cnVjdCBkbWFfZGV2aWNlICpkbWFfZGV2ID0gTlVMTDsNCisJaW50IHJldCA9IDA7DQorDQorCWRl
dl9pbmZvKCZvZmRldi0+ZGV2LCAiRnJlZXNjYWxlIFJBSUQgRW5naW5lIGRyaXZlclxuIik7DQor
DQorCXJlcHJpdiA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCByZV9kcnZfcHJpdmF0ZSksIEdGUF9L
RVJORUwpOw0KKwlpZiAoIXJlcHJpdikgew0KKwkJZGV2X2VycihkZXYsICIlczogTm8gbWVtb3J5
IGZvciByZXByaXZcbiIsIF9fZnVuY19fKTsNCisJCXJldHVybiAtRU5PTUVNOw0KKwl9DQorDQor
CWRldiA9ICZvZmRldi0+ZGV2Ow0KKwlkZXZfc2V0X2RydmRhdGEoZGV2LCByZXByaXYpOw0KKw0K
KwkvKiBJT01BUCB0aGUgZW50aXJlIFJBSUQgRW5naW5lIHJlZ2lvbiAqLw0KKwlyZXByaXYtPnJl
X3JlZ3MgPSBvZl9pb21hcChvZmRldi0+ZGV2Lm9mX25vZGUsIDApOw0KKwlpZiAocmVwcml2LT5y
ZV9yZWdzID09IE5VTEwpIHsNCisJCWRldl9lcnIoZGV2LCAiJXM6IG9mX2lvbWFwIGZhaWxlZFxu
IiwgX19mdW5jX18pOw0KKwkJa2ZyZWUocmVwcml2KTsNCisJCXJldCA9IC1FTk9NRU07DQorCQln
b3RvIGVycl9mcmVlXzQ7DQorCX0NCisNCisJLyogUHJpbnQgdGhlIFJFIHZlcnNpb24gdG8gbWFr
ZSBzdXJlIFJFIGlzIGFsaXZlICovDQorCWRldl9pbmZvKGRldiwgIlZlciA9ICV4XG4iLCBpbl9i
ZTMyKCZyZXByaXYtPnJlX3JlZ3MtPnJlX3ZlcnNpb25faWQpKTsNCisNCisJLyogUHJvZ3JhbSB0
aGUgUkUgbW9kZSAqLw0KKwlvdXRfYmUzMigmcmVwcml2LT5yZV9yZWdzLT5nbG9iYWxfY29uZmln
LCBSRV9OT05fRFBBQV9NT0RFKTsNCisJZGV2X2luZm8oZGV2LCAiJXM6UkUgbW9kZSBpcyAleFxu
IiwgX19mdW5jX18sDQorCQkJaW5fYmUzMigmcmVwcml2LT5yZV9yZWdzLT5nbG9iYWxfY29uZmln
KSk7DQorDQorCS8qIFByb2dyYW0gR2Fsb2lzIEZpZWxkIHBvbHlub21pYWwgKi8NCisJb3V0X2Jl
MzIoJnJlcHJpdi0+cmVfcmVncy0+Z2Fsb2lzX2ZpZWxkX2NvbmZpZywgUkVfR0ZNX1BPTFkpOw0K
KwlkZXZfaW5mbyhkZXYsICIlczpHYWxvaXMgRmllbGQgUG9seW5vbWlhbCBpcyAleFxuIiwgX19m
dW5jX18sDQorCQkJaW5fYmUzMigmcmVwcml2LT5yZV9yZWdzLT5nYWxvaXNfZmllbGRfY29uZmln
KSk7DQorDQorCWRtYV9kZXYgPSAmcmVwcml2LT5kbWFfZGV2Ow0KKwlkbWFfZGV2LT5kZXYgPSBk
ZXY7DQorCUlOSVRfTElTVF9IRUFEKCZkbWFfZGV2LT5jaGFubmVscyk7DQorCWRtYV9zZXRfbWFz
ayhkZXYsIERNQV9CSVRfTUFTSyg0MCkpOw0KKw0KKwlkbWFfZGV2LT5kZXZpY2VfYWxsb2NfY2hh
bl9yZXNvdXJjZXMgPSByZV9qcl9hbGxvY19jaGFuX3Jlc291cmNlczsNCisJZG1hX2Rldi0+ZGV2
aWNlX3R4X3N0YXR1cyA9IHJlX2pyX3R4X3N0YXR1czsNCisJZG1hX2Rldi0+ZGV2aWNlX2lzc3Vl
X3BlbmRpbmcgPSByZV9qcl9pc3N1ZV9wZW5kaW5nOw0KKw0KKwlkbWFfZGV2LT5tYXhfeG9yID0g
TUFYX1hPUl9TUkNTOw0KKwlkbWFfZGV2LT5kZXZpY2VfcHJlcF9kbWFfeG9yID0gcmVfanJfcHJl
cF9kbWFfeG9yOw0KKwlkbWFfY2FwX3NldChETUFfWE9SLCBkbWFfZGV2LT5jYXBfbWFzayk7DQor
DQorCWRtYV9kZXYtPm1heF9wcSA9IE1BWF9QUV9TUkNTOw0KKwlkbWFfZGV2LT5kZXZpY2VfcHJl
cF9kbWFfcHEgPSByZV9qcl9wcmVwX3BxOw0KKwlkbWFfY2FwX3NldChETUFfUFEsIGRtYV9kZXYt
PmNhcF9tYXNrKTsNCisNCisJZG1hX2Rldi0+ZGV2aWNlX3ByZXBfZG1hX21lbWNweSA9IHJlX2py
X3ByZXBfbWVtY3B5Ow0KKwlkbWFfY2FwX3NldChETUFfTUVNQ1BZLCBkbWFfZGV2LT5jYXBfbWFz
ayk7DQorDQorCWRtYV9kZXYtPmRldmljZV9mcmVlX2NoYW5fcmVzb3VyY2VzID0gcmVfanJfZnJl
ZV9jaGFuX3Jlc291cmNlczsNCisNCisJcmVwcml2LT50b3RhbF9qcnMgPSAwOw0KKw0KKwlyZXBy
aXYtPmRlc2NfcG9vbCA9IGRtYV9wb29sX2NyZWF0ZSgicmVfZG1hX2Rlc2NfcG9vbCIsIGRldiwN
CisJCQkJCVJFX0NGX0NEQl9TSVpFICogUklOR19TSVpFLA0KKwkJCQkJUkVfQ0ZfQ0RCX0FMSUdO
LCAwKTsNCisNCisJaWYgKCFyZXByaXYtPmRlc2NfcG9vbCkgew0KKwkJcHJfZXJyKCIlczpObyBt
ZW1vcnkgZm9yIGRtYSBkZXNjIHBvb2xcbiIsIF9fZnVuY19fKTsNCisJCXJldCA9IC1FTk9NRU07
DQorCQlnb3RvIGVycl9mcmVlXzM7DQorCX0NCisNCisJcmVwcml2LT5od19kZXNjX3Bvb2wgPSBk
bWFfcG9vbF9jcmVhdGUoInJlX2h3X2Rlc2NfcG9vbCIsIGRldiwNCisJCQkJc2l6ZW9mKHN0cnVj
dCBqcl9od19kZXNjKSAqIFJJTkdfU0laRSwNCisJCQkJRlJBTUVfREVTQ19BTElHTk1FTlQsIDAp
Ow0KKwlpZiAoIXJlcHJpdi0+aHdfZGVzY19wb29sKSB7DQorCQlwcl9lcnIoIiVzOk5vIG1lbW9y
eSBmb3IgaHcgZGVzYyBwb29sXG4iLCBfX2Z1bmNfXyk7DQorCQlyZXQgPSAtRU5PTUVNOw0KKwkJ
Z290byBlcnJfZnJlZV8yOw0KKwl9DQorDQorCS8qIFBhcnNlIERldmljZSB0cmVlIHRvIGZpbmQg
b3V0IHRoZSB0b3RhbCBudW1iZXIgb2YgSlFzIHByZXNlbnQgKi8NCisJZm9yX2VhY2hfY29tcGF0
aWJsZV9ub2RlKG5wLCBOVUxMLCAiZnNsLHJhaWRlbmctdjEuMC1qb2ItcXVldWUiKSB7DQorCQlv
ZmYgPSAodTMyICopb2ZfZ2V0X3Byb3BlcnR5KG5wLCAicmVnIiwgTlVMTCk7DQorCQlpZiAoIW9m
Zikgew0KKwkJCWRldl9lcnIoZGV2LCAiJXM6IFJlZyBwcm9wZXJ0eSBub3QgZm91bmQgaW4gSlEg
bm9kZVxuIiwNCisJCQkJX19mdW5jX18pOw0KKwkJCXJldHVybiAtRU5PREVWOw0KKwkJfQ0KKw0K
KwkJLyogRmluZCBvdXQgdGhlIEpvYiBSaW5ncyBwcmVzZW50IHVuZGVyIGVhY2ggSlEgKi8NCisJ
CWZvcl9lYWNoX2NoaWxkX29mX25vZGUobnAsIGNoaWxkKSB7DQorCQkJaWYgKG9mX2RldmljZV9p
c19jb21wYXRpYmxlKGNoaWxkLA0KKwkJCQkiZnNsLHJhaWRlbmctdjEuMC1qb2ItcmluZyIpKSB7
DQorCQkJCXJlX2pyX3Byb2JlKG9mZGV2LCBjaGlsZCwgcmlkeCsrLCBvZmYpOw0KKwkJCQlyZXBy
aXYtPnRvdGFsX2pycysrOw0KKwkJCX0NCisJCX0NCisJfQ0KKw0KKwlkbWFfYXN5bmNfZGV2aWNl
X3JlZ2lzdGVyKGRtYV9kZXYpOw0KKwlyZXR1cm4gMDsNCisNCitlcnJfZnJlZV8yOg0KKwlkbWFf
cG9vbF9kZXN0cm95KHJlcHJpdi0+ZGVzY19wb29sKTsNCitlcnJfZnJlZV8zOg0KKwlpb3VubWFw
KHJlcHJpdi0+cmVfcmVncyk7DQorZXJyX2ZyZWVfNDoNCisJa2ZyZWUocmVwcml2KTsNCisNCisJ
cmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIHZvaWQgcmVsZWFzZV9qcihzdHJ1Y3QgcmVfanIg
KmpyKSB7DQorCS8qIEZyZWUgdGhlIG1lbW9yeSBhbGxvY2F0ZWQgZnJvbSBETUEgcG9vbHMgYW5k
IGRlc3Ryb3kgdGhlbSAqLw0KKwlkbWFfcG9vbF9mcmVlKGpyLT5yZV9kZXYtPmh3X2Rlc2NfcG9v
bCwganItPmluYl9yaW5nX3ZpcnRfYWRkciwNCisJCWpyLT5pbmJfcGh5c19hZGRyKTsNCisJa2Zy
ZWUoanIpOw0KK30NCisNCitzdGF0aWMgaW50IHJhaWRlX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1f
ZGV2aWNlICpvZmRldikgew0KKwlzdHJ1Y3QgcmVfZHJ2X3ByaXZhdGUgKnJlcHJpdiA9IE5VTEw7
DQorCXN0cnVjdCBkZXZpY2UgKmRldiA9IE5VTEw7DQorCWludCBpOw0KKw0KKwlkZXYgPSAmb2Zk
ZXYtPmRldjsNCisJcmVwcml2ID0gZGV2X2dldF9kcnZkYXRhKGRldik7DQorDQorCS8qIENsZWFu
dXAgSlIgcmVsYXRlZCBtZW1vcnkgYXJlYXMgKi8NCisJZm9yIChpID0gMDsgaSA8IHJlcHJpdi0+
dG90YWxfanJzOyBpKyspDQorCQlyZWxlYXNlX2pyKHJlcHJpdi0+cmVfanJzW2ldKTsNCisNCisJ
ZG1hX3Bvb2xfZGVzdHJveShyZXByaXYtPmh3X2Rlc2NfcG9vbCk7DQorCWRtYV9wb29sX2Rlc3Ry
b3kocmVwcml2LT5kZXNjX3Bvb2wpOw0KKw0KKwkvKiBVbnJlZ2lzdGVyIHRoZSBkcml2ZXIgKi8N
CisJZG1hX2FzeW5jX2RldmljZV91bnJlZ2lzdGVyKCZyZXByaXYtPmRtYV9kZXYpOw0KKw0KKwkv
KiBVbm1hcCB0aGUgUkFJRCBFbmdpbmUgcmVnaW9uICovDQorCWlvdW5tYXAocmVwcml2LT5yZV9y
ZWdzKTsNCisNCisJa2ZyZWUocmVwcml2KTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRp
YyBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIHJhaWRlX2lkc1tdID0gew0KKwl7IC5jb21wYXRpYmxlID0g
ImZzbCxyYWlkZW5nLXYxLjAiLCB9LA0KKwl7fQ0KK307DQorDQorc3RhdGljIHN0cnVjdCBwbGF0
Zm9ybV9kcml2ZXIgcmFpZGVfZHJpdmVyID0gew0KKwkuZHJpdmVyID0gew0KKwkJLm5hbWUgPSAi
ZnNsLXJhaWRlbmciLA0KKwkJLm93bmVyID0gVEhJU19NT0RVTEUsDQorCQkub2ZfbWF0Y2hfdGFi
bGUgPSByYWlkZV9pZHMsDQorCX0sDQorCS5wcm9iZSA9IHJhaWRlX3Byb2JlLA0KKwkucmVtb3Zl
ID0gcmFpZGVfcmVtb3ZlLA0KK307DQorDQorc3RhdGljIF9faW5pdCBpbnQgcmFpZGVfaW5pdCh2
b2lkKQ0KK3sNCisJaW50IHJldCA9IDA7DQorDQorCXJldCA9IHBsYXRmb3JtX2RyaXZlcl9yZWdp
c3RlcigmcmFpZGVfZHJpdmVyKTsNCisJaWYgKHJldCkNCisJCXByX2VycigiZnNsLXJhaWQ6IEZh
aWxlZCB0byByZWdpc3RlciBwbGF0Zm9ybSBkcml2ZXJcbiIpOw0KKw0KKwlyZXR1cm4gcmV0Ow0K
K30NCisNCitzdGF0aWMgdm9pZCBfX2V4aXQgcmFpZGVfZXhpdCh2b2lkKQ0KK3sNCisJcGxhdGZv
cm1fZHJpdmVyX3VucmVnaXN0ZXIoJnJhaWRlX2RyaXZlcik7DQorfQ0KKw0KK3N1YnN5c19pbml0
Y2FsbChyYWlkZV9pbml0KTsNCittb2R1bGVfZXhpdChyYWlkZV9leGl0KTsNCisNCitNT0RVTEVf
QVVUSE9SKCJIYXJuaW5kZXIgUmFpIDxoYXJuaW5kZXIucmFpQGZyZWVzY2FsZS5jb20+Iik7IA0K
K01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsgTU9EVUxFX0RFU0NSSVBUSU9OKCJGcmVlc2NhbGUg
UkFJRCBFbmdpbmUgDQorRGV2aWNlIERyaXZlciIpOw0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1h
L2ZzbF9yYWlkLmggYi9kcml2ZXJzL2RtYS9mc2xfcmFpZC5oIG5ldyBmaWxlIG1vZGUgMTAwNjQ0
IGluZGV4IDAwMDAwMDAuLjNjYjg0NTQNCi0tLSAvZGV2L251bGwNCisrKyBiL2RyaXZlcnMvZG1h
L2ZzbF9yYWlkLmgNCkBAIC0wLDAgKzEsMzE3IEBADQorLyoNCisgKiBkcml2ZXJzL2RtYS9mc2xf
cmFpZC5oDQorICoNCisgKiBGcmVlc2NhbGUgUkFJRCBFbmdpbmUgZGV2aWNlIGRyaXZlcg0KKyAq
DQorICogQXV0aG9yOg0KKyAqCUhhcm5pbmRlciBSYWkgPGhhcm5pbmRlci5yYWlAZnJlZXNjYWxl
LmNvbT4NCisgKglOYXZlZW4gQnVybWkgPG5hdmVlbmJ1cm1pQGZyZWVzY2FsZS5jb20+DQorICoN
CisgKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMiBGcmVlc2NhbGUgU2VtaWNvbmR1Y3RvciwgSW5j
Lg0KKyAqDQorICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBm
b3Jtcywgd2l0aCBvciB3aXRob3V0DQorICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHBy
b3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6DQorICogICAgICog
UmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5
cmlnaHQNCisgKiAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUg
Zm9sbG93aW5nIGRpc2NsYWltZXIuDQorICogICAgICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFy
eSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQNCisgKiAgICAgICBub3Rp
Y2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIg
aW4gdGhlDQorICogICAgICAgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4NCisgKiAgICAgKiBOZWl0aGVyIHRoZSBuYW1l
IG9mIEZyZWVzY2FsZSBTZW1pY29uZHVjdG9yIG5vciB0aGUNCisgKiAgICAgICBuYW1lcyBvZiBp
dHMgY29udHJpYnV0b3JzIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0
cw0KKyAqICAgICAgIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMg
cHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLg0KKyAqDQorICogQUxURVJOQVRJVkVMWSwgdGhpcyBz
b2Z0d2FyZSBtYXkgYmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIA0KK3RoZQ0KKyAq
IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlICgiR1BMIikgYXMgcHVibGlzaGVkIGJ5IHRoZSBG
cmVlIFNvZnR3YXJlDQorICogRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGF0IExp
Y2Vuc2Ugb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkNCisgKiBsYXRlciB2ZXJzaW9uLg0KKyAqDQor
ICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBGcmVlc2NhbGUgU2VtaWNvbmR1Y3RvciBg
YEFTIElTJycgQU5EIA0KK0FOWQ0KKyAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJ
TkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIA0KK0lNUExJRUQNCisgKiBXQVJSQU5U
SUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBP
U0UgDQorQVJFDQorICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRnJlZXNjYWxlIFNl
bWljb25kdWN0b3IgQkUgTElBQkxFIEZPUiANCitBTlkNCisgKiBESVJFQ1QsIElORElSRUNULCBJ
TkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgDQorREFNQUdF
Uw0KKyAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VC
U1RJVFVURSBHT09EUyBPUiANCitTRVJWSUNFUzsNCisgKiBMT1NTIE9GIFVTRSwgREFUQSwgT1Ig
UFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIA0KK0NBVVNFRCBBTkQN
CisgKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RS
SUNUIExJQUJJTElUWSwgDQorT1IgVE9SVA0KKyAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBP
VEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIA0KK1VTRSBPRiBUSElTDQor
ICogU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBE
QU1BR0UuDQorICoNCisgKi8NCisNCisjZGVmaW5lIFJFX0RQQUFfTU9ERQkJKDEgPDwgMzApDQor
I2RlZmluZSBSRV9OT05fRFBBQV9NT0RFCSgxIDw8IDMxKQ0KKyNkZWZpbmUgUkVfR0ZNX1BPTFkJ
CSgweDFkMDAwMDAwKQ0KKyNkZWZpbmUgUkVfSlJfSU5CX0pPQl9BREQoeCkJKCh4KSA8PCAxNikN
CisjZGVmaW5lIFJFX0pSX09VQl9KT0JfUkVNT1ZFKHgpCSgoeCkgPDwgMTYpDQorI2RlZmluZSBS
RV9KUl9DRkcxX0NCU0kJCTB4MDgwMDAwMDANCisjZGVmaW5lIFJFX0pSX0NGRzFfQ0JTMAkJMHgw
MDA4MDAwMA0KKyNkZWZpbmUgUkVfSlJfT1VCX1NMT1RfRlVMTF9TSElGVAk4DQorI2RlZmluZSBS
RV9KUl9PVUJfU0xPVF9GVUxMKHgpCSgoeCkgPj4gUkVfSlJfT1VCX1NMT1RfRlVMTF9TSElGVCkN
CisjZGVmaW5lIFJFX0pSX0lOQl9TTE9UX0FWQUlMX1NISUZUCTgNCisjZGVmaW5lIFJFX0pSX0lO
Ql9TTE9UX0FWQUlMKHgpCSgoeCkgPj4gUkVfSlJfSU5CX1NMT1RfQVZBSUxfU0hJRlQpDQorI2Rl
ZmluZSBSRV9QUV9PUENPREUJCTB4MUINCisjZGVmaW5lIFJFX1hPUl9PUENPREUJCTB4MUENCisj
ZGVmaW5lIFJFX01PVkVfT1BDT0RFCQkweDgNCisjZGVmaW5lIEZSQU1FX0RFU0NfQUxJR05NRU5U
CTE2DQorI2RlZmluZSBSRV9CTE9DS19TSVpFCQkweDMgLyogNDA5NiBieXRlcyAqLw0KKyNkZWZp
bmUgQ0FDSEVBQkxFX0lOUFVUX09VVFBVVAkweDANCisjZGVmaW5lIEJVRkZFUkFCTEVfT1VUUFVU
CTB4MA0KKyNkZWZpbmUgSU5URVJSVVBUX09OX0VSUk9SCTB4MQ0KKyNkZWZpbmUgREFUQV9ERVBF
TkRFTkNZCQkweDENCisjZGVmaW5lIEVOQUJMRV9EUEkJCTB4MA0KKyNkZWZpbmUgUklOR19TSVpF
CQkweDEwMDANCisjZGVmaW5lIFJJTkdfU0laRV9TSElGVAkJOA0KKyNkZWZpbmUgUkVfSlJfQURE
UkVTU19CSVRfU0hJRlQJNA0KKyNkZWZpbmUgUkVfSlJfQUREUkVTU19CSVRfTUFTSwkoKDEgPDwg
UkVfSlJfQUREUkVTU19CSVRfU0hJRlQpIC0gMSkNCisjZGVmaW5lIFJFX0pSX0VSUk9SCQkweDQw
MDAwMDAwDQorI2RlZmluZSBSRV9KUl9JTlRFUlJVUFQJCTB4ODAwMDAwMDANCisjZGVmaW5lIFJF
X0pSX0NMRUFSX0lOVAkJMHg4MDAwMDAwMA0KKyNkZWZpbmUgUkVfSlJfUEFVU0UJCTB4ODAwMDAw
MDANCisjZGVmaW5lIFJFX0pSX0VOQUJMRQkJMHg4MDAwMDAwMA0KKw0KKyNkZWZpbmUgUkVfSlJf
UkVHX0xJT0ROX01BU0sJMHgwMDAwMGZmZg0KKyNkZWZpbmUgUkVfQ0ZfQ0RCX0FMSUdOCQk2NA0K
Ky8qDQorICogdGhlIGxhcmdlc3QgY2YgYmxvY2sgaXMgMTkqc2l6ZW9mKHN0cnVjdCBjbXBuZF9m
cmFtZSksIHdoaWNoIGlzIDMwNCBieXRlcy4NCisgKiBoZXJlIDE5ID0gMShjZGIpKzIoZGVzdCkr
MTYoc3JjKSwgYWxpZ24gdG8gNjRieXRlcywgdGhhdCBpcyAzMjAgYnl0ZXMuDQorICogdGhlIGxh
cmdlc3QgY2RiIGJsb2NrOiBzdHJ1Y3QgcHFfY2RiIHdoaWNoIGlzIDE4MCBieXRlcywgYWRkaW5n
IHRvIA0KK2NmIGJsb2NrDQorICogMzIwKzE4MD01MDAsIGFsaWduIHRvIDY0Ynl0ZXMsIHRoYXQg
aXMgNTEyIGJ5dGVzLg0KKyAqLw0KKyNkZWZpbmUgUkVfQ0ZfREVTQ19TSVpFCQkzMjANCisjZGVm
aW5lIFJFX0NGX0NEQl9TSVpFCQk1MTINCisNCitzdHJ1Y3QgcmVfY3RybCB7DQorCS8qIEdlbmVy
YWwgQ29uZmlndXJhdGlvbiBSZWdpc3RlcnMgKi8NCisJX19iZTMyIGdsb2JhbF9jb25maWc7CS8q
IEdsb2JhbCBDb25maWd1cmF0aW9uIFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkMVs0XTsNCisJ
X19iZTMyIGdhbG9pc19maWVsZF9jb25maWc7IC8qIEdhbG9pcyBGaWVsZCBDb25maWd1cmF0aW9u
IFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkMls0XTsNCisJX19iZTMyIGpxX3dycl9jb25maWc7
ICAgLyogV1JSIENvbmZpZ3VyYXRpb24gcmVnaXN0ZXIgKi8NCisJdTggICAgIHJzdmQzWzRdOw0K
KwlfX2JlMzIgY3JjX2NvbmZpZzsJLyogQ1JDIENvbmZpZ3VyYXRpb24gcmVnaXN0ZXIgKi8NCisJ
dTggICAgIHJzdmQ0WzIyOF07DQorCV9fYmUzMiBzeXN0ZW1fcmVzZXQ7CS8qIFN5c3RlbSBSZXNl
dCBSZWdpc3RlciAqLw0KKwl1OCAgICAgcnN2ZDVbMjUyXTsNCisJX19iZTMyIGdsb2JhbF9zdGF0
dXM7CS8qIEdsb2JhbCBTdGF0dXMgUmVnaXN0ZXIgKi8NCisJdTggICAgIHJzdmQ2WzgzMl07DQor
CV9fYmUzMiByZV9saW9kbl9iYXNlOwkvKiBMSU9ETiBCYXNlIFJlZ2lzdGVyICovDQorCXU4ICAg
ICByc3ZkN1sxNzEyXTsNCisJX19iZTMyIHJlX3ZlcnNpb25faWQ7CS8qIFZlcnNpb24gSUQgcmVn
aXN0ZXIgb2YgUkUgKi8NCisJX19iZTMyIHJlX3ZlcnNpb25faWRfMjsgLyogVmVyc2lvbiBJRCAy
IHJlZ2lzdGVyIG9mIFJFICovDQorCXU4ICAgICByc3ZkOFs1MTJdOw0KKwlfX2JlMzIgaG9zdF9j
b25maWc7CS8qIEhvc3QgSS9GIENvbmZpZ3VyYXRpb24gUmVnaXN0ZXIgKi8NCit9Ow0KKw0KK3N0
cnVjdCBqcl9jb25maWdfcmVncyB7DQorCS8qIFJlZ2lzdGVycyBmb3IgSlIgaW50ZXJmYWNlICov
DQorCV9fYmUzMiBqcl9jb25maWdfMDsJLyogSm9iIFF1ZXVlIENvbmZpZ3VyYXRpb24gMCBSZWdp
c3RlciAqLw0KKwlfX2JlMzIganJfY29uZmlnXzE7CS8qIEpvYiBRdWV1ZSBDb25maWd1cmF0aW9u
IDEgUmVnaXN0ZXIgKi8NCisJX19iZTMyIGpyX2ludGVycnVwdF9zdGF0dXM7IC8qIEpvYiBRdWV1
ZSBJbnRlcnJ1cHQgU3RhdHVzIFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkMVs0XTsNCisJX19i
ZTMyIGpyX2NvbW1hbmQ7CS8qIEpvYiBRdWV1ZSBDb21tYW5kIFJlZ2lzdGVyICovDQorCXU4ICAg
ICByc3ZkMls0XTsNCisJX19iZTMyIGpyX3N0YXR1czsJLyogSm9iIFF1ZXVlIFN0YXR1cyBSZWdp
c3RlciAqLw0KKwl1OCAgICAgcnN2ZDNbMjI4XTsNCisNCisJLyogSW5wdXQgUmluZyAqLw0KKwlf
X2JlMzIgaW5icmluZ19iYXNlX2g7CS8qIEluYm91bmQgUmluZyBCYXNlIEFkZHJlc3MgUmVnaXN0
ZXIgLSBIaWdoICovDQorCV9fYmUzMiBpbmJyaW5nX2Jhc2VfbDsJLyogSW5ib3VuZCBSaW5nIEJh
c2UgQWRkcmVzcyBSZWdpc3RlciAtIExvdyAqLw0KKwlfX2JlMzIgaW5icmluZ19zaXplOwkvKiBJ
bmJvdW5kIFJpbmcgU2l6ZSBSZWdpc3RlciAqLw0KKwl1OCAgICAgcnN2ZDRbNF07DQorCV9fYmUz
MiBpbmJyaW5nX3Nsb3RfYXZhaWw7IC8qIEluYm91bmQgUmluZyBTbG90IEF2YWlsYWJsZSBSZWdp
c3RlciAqLw0KKwl1OCAgICAgcnN2ZDVbNF07DQorCV9fYmUzMiBpbmJyaW5nX2FkZF9qb2I7CS8q
IEluYm91bmQgUmluZyBBZGQgSm9iIFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkNls0XTsNCisJ
X19iZTMyIGluYnJpbmdfY25zbXJfaW5keDsgLyogSW5ib3VuZCBSaW5nIENvbnN1bWVyIEluZGV4
IFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkN1syMjBdOw0KKw0KKwkvKiBPdXRwdXQgUmluZyAq
Lw0KKwlfX2JlMzIgb3VicmluZ19iYXNlX2g7CS8qIE91dGJvdW5kIFJpbmcgQmFzZSBBZGRyZXNz
IFJlZ2lzdGVyIC0gSGlnaCAqLw0KKwlfX2JlMzIgb3VicmluZ19iYXNlX2w7CS8qIE91dGJvdW5k
IFJpbmcgQmFzZSBBZGRyZXNzIFJlZ2lzdGVyIC0gTG93ICovDQorCV9fYmUzMiBvdWJyaW5nX3Np
emU7CS8qIE91dGJvdW5kIFJpbmcgU2l6ZSBSZWdpc3RlciAqLw0KKwl1OCAgICAgcnN2ZDhbNF07
DQorCV9fYmUzMiBvdWJyaW5nX2pvYl9ybXZkOyAvKiBPdXRib3VuZCBSaW5nIEpvYiBSZW1vdmVk
IFJlZ2lzdGVyICovDQorCXU4ICAgICByc3ZkOVs0XTsNCisJX19iZTMyIG91YnJpbmdfc2xvdF9m
dWxsOyAvKiBPdXRib3VuZCBSaW5nIFNsb3QgRnVsbCBSZWdpc3RlciAqLw0KKwl1OCAgICAgcnN2
ZDEwWzRdOw0KKwlfX2JlMzIgb3VicmluZ19wcmRjcl9pbmR4OyAvKiBPdXRib3VuZCBSaW5nIFBy
b2R1Y2VyIEluZGV4ICovIH07DQorDQorLyoNCisgKiBDb21tYW5kIERlc2NyaXB0b3IgQmxvY2sg
KENEQikgZm9yIHVuaWNhc3QgbW92ZSBjb21tYW5kLg0KKyAqIEluIFJBSUQgRW5naW5lIHRlcm1z
LCBtZW1jcHkgaXMgZG9uZSB0aHJvdWdoIG1vdmUgY29tbWFuZCAgKi8gc3RydWN0IA0KK21vdmVf
Y2RiIHsNCisJdTMyIG9wY29kZTo1Ow0KKwl1MzIgcnN2ZDE6MTE7DQorCXUzMiBibGtfc2l6ZToy
Ow0KKwl1MzIgY2FjaGVfYXR0cmliOjI7DQorCXUzMiBidWZmZXJfYXR0cmliOjE7DQorCXUzMiBl
cnJvcl9hdHRyaWI6MTsNCisJdTMyIHJzdmQyOjY7DQorCXUzMiBkYXRhX2RlcGVuZDoxOw0KKwl1
MzIgZHBpOjE7DQorCXUzMiByc3ZkMzoyOw0KK30gX19wYWNrZWQ7DQorDQorLyogRGF0YSBwcm90
ZWN0aW9uL2ludGVncml0eSByZWxhdGVkIGZpZWxkcyAqLyBzdHJ1Y3QgZHBpX3JlbGF0ZWQgew0K
Kwl1MzIgYXBwc19tdGhkOjI7DQorCXUzMiByZWZfbXRoZDoyOw0KKwl1MzIgZ3VhcmRfbXRoZDoy
Ow0KKwl1MzIgZHBpX2F0dHI6MjsNCisJdTMyIHJzdmQxOjg7DQorCXUzMiBtZXRhX3RhZzoxNjsN
CisJdTMyIHJlZl90YWc6MzI7DQorfSBfX3BhY2tlZDsNCisNCisvKg0KKyAqIENEQiBmb3IgR2Vu
USBjb21tYW5kLiBJbiBSQUlEIEVuZ2luZSB0ZXJtaW5vbG9neSwgWE9SIGlzDQorICogZG9uZSB0
aHJvdWdoIHRoaXMgY29tbWFuZA0KKyAqLw0KK3N0cnVjdCB4b3JfY2RiIHsNCisJdTMyIG9wY29k
ZTo1Ow0KKwl1MzIgcnN2ZDE6MTE7DQorCXUzMiBibGtfc2l6ZToyOw0KKwl1MzIgY2FjaGVfYXR0
cmliOjI7DQorCXUzMiBidWZmZXJfYXR0cmliOjE7DQorCXUzMiBlcnJvcl9hdHRyaWI6MTsNCisJ
dTMyIG5yY3M6NDsNCisJdTMyIHJzdmQyOjI7DQorCXUzMiBkYXRhX2RlcGVuZDoxOw0KKwl1MzIg
ZHBpOjE7DQorCXUzMiByc3ZkMzoyOw0KKwl1OCBnZm1bMTZdOw0KKwlzdHJ1Y3QgZHBpX3JlbGF0
ZWQgZHBpX2Rlc3Rfc3BlYzsNCisJc3RydWN0IGRwaV9yZWxhdGVkIGRwaV9zcmNfc3BlY1sxNl07
DQorfSBfX3BhY2tlZDsNCisNCisvKiBDREIgZm9yIG5vLW9wIGNvbW1hbmQgKi8NCitzdHJ1Y3Qg
bm9vcF9jZGIgew0KKwl1MzIgb3Bjb2RlOjU7DQorCXUzMiByc3ZkMToyMzsNCisJdTMyIGRlcGVu
ZGVuY3k6MTsNCisJdTMyIHJzdmQyOjM7DQorfSBfX3BhY2tlZDsNCisNCisvKg0KKyAqIENEQiBm
b3IgR2VuUVEgY29tbWFuZC4gSW4gUkFJRCBFbmdpbmUgdGVybWlub2xvZ3ksIFAvUSBpcw0KKyAq
IGRvbmUgdGhyb3VnaCB0aGlzIGNvbW1hbmQNCisgKi8NCitzdHJ1Y3QgcHFfY2RiIHsNCisJdTMy
IG9wY29kZTo1Ow0KKwl1MzIgcnN2ZDE6MTsNCisJdTMyIGV4Y2xfZW5hYmxlOjI7DQorCXUzMiBl
eGNsX3ExOjQ7DQorCXUzMiBleGNsX3EyOjQ7DQorCXUzMiBibGtfc2l6ZToyOw0KKwl1MzIgY2Fj
aGVfYXR0cmliOjI7DQorCXUzMiBidWZmZXJfYXR0cmliOjE7DQorCXUzMiBlcnJvcl9hdHRyaWI6
MTsNCisJdTMyIG5yY3M6NDsNCisJdTMyIHJzdmQyOjI7DQorCXUzMiBkYXRhX2RlcGVuZDoxOw0K
Kwl1MzIgZHBpOjE7DQorCXUzMiByc3ZkMzoyOw0KKwl1OCBnZm1fcTFbMTZdOw0KKwl1OCBnZm1f
cTJbMTZdOw0KKwlzdHJ1Y3QgZHBpX3JlbGF0ZWQgZHBpX2Rlc3Rfc3BlY1syXTsNCisJc3RydWN0
IGRwaV9yZWxhdGVkIGRwaV9zcmNfc3BlY1sxNl07DQorfSBfX3BhY2tlZDsNCisNCisvKiBDb21w
b3VuZCBmcmFtZSAqLw0KK3N0cnVjdCBjbXBuZF9mcmFtZSB7DQorCXU2NCByc3ZkMToyNDsNCisJ
dTY0IGFkZHJlc3M6NDA7DQorCXUzMiBleHRlbnNpb246MTsNCisJdTMyIGZpbmFsOjE7DQorCXUz
MiByc3ZkMzoxMDsNCisJdTMyIGxlbmd0aDoyMDsNCisJdTMyIHJzdmQ0Ojg7DQorCXUzMiBicGlk
Ojg7DQorCXUzMiByc3ZkNTozOw0KKwl1MzIgb2Zmc2V0OjEzOw0KK30gX19wYWNrZWQ7DQorDQor
LyogRnJhbWUgZGVzY3JpcHRvciAqLw0KK3N0cnVjdCBqcl9od19kZXNjIHsNCisJdTY0IGRlYnVn
OjI7DQorCXU2NCBsaW9kbl9vZmY6NjsNCisJdTY0IGJwaWQ6ODsNCisJdTY0IGVsaW9kbl9vZmY6
NDsNCisJdTY0IHJzdmQxOjQ7DQorCXU2NCBhZGRyZXNzOjQwOw0KKwl1NjQgZm9ybWF0OjM7DQor
CXU2NCByc3ZkMjoyOTsNCisJdTY0IHN0YXR1czozMjsNCit9IF9fcGFja2VkOw0KKw0KKyNkZWZp
bmUgTUFYX1JFX0pSUwkJNA0KKw0KKy8qIFJhaWQgRW5naW5lIGRldmljZSBwcml2YXRlIGRhdGEg
Ki8NCitzdHJ1Y3QgcmVfZHJ2X3ByaXZhdGUgew0KKwl1OCB0b3RhbF9qcnM7DQorCXN0cnVjdCBk
bWFfZGV2aWNlIGRtYV9kZXY7DQorCXN0cnVjdCByZV9jdHJsICpyZV9yZWdzOw0KKwlzdHJ1Y3Qg
cmVfanIgKnJlX2pyc1tNQVhfUkVfSlJTXTsNCisJc3RydWN0IGRtYV9wb29sICpkZXNjX3Bvb2w7
DQorCXN0cnVjdCBkbWFfcG9vbCAqaHdfZGVzY19wb29sOw0KK307DQorDQorLyogUGVyIGpvYiBy
aW5nIGRhdGEgc3RydWN0dXJlICovDQorc3RydWN0IHJlX2pyIHsNCisJZG1hX2Nvb2tpZV90IGNv
bXBsZXRlZF9jb29raWU7DQorCXNwaW5sb2NrX3QgZGVzY19sb2NrOw0KKwlzdHJ1Y3QgbGlzdF9o
ZWFkIGFja19xOw0KKwlzdHJ1Y3QgZGV2aWNlICpkZXY7DQorCXN0cnVjdCByZV9kcnZfcHJpdmF0
ZSAqcmVfZGV2Ow0KKwlzdHJ1Y3QgZG1hX2NoYW4gY2hhbjsNCisJc3RydWN0IGpyX2NvbmZpZ19y
ZWdzICpqcnJlZ3M7DQorCWludCBpcnE7DQorCXN0cnVjdCB0YXNrbGV0X3N0cnVjdCBpcnF0YXNr
Ow0KKw0KKwkvKiBodyBkZXNjcmlwdG9yIHJpbmcgZm9yIGluYm91bmQgcXVldWUqLw0KKwlkbWFf
YWRkcl90IGluYl9waHlzX2FkZHI7DQorCXN0cnVjdCBqcl9od19kZXNjICppbmJfcmluZ192aXJ0
X2FkZHI7DQorCXUzMiBpbmJfY291bnQ7DQorCXUzMiBwZW5kX2NvdW50Ow0KKwlzcGlubG9ja190
IGluYl9sb2NrOw0KKw0KKwkvKiBodyBkZXNjcmlwdG9yIHJpbmcgZm9yIG91dGJvdW5kIHF1ZXVl
ICovDQorCWRtYV9hZGRyX3Qgb3ViX3BoeXNfYWRkcjsNCisJc3RydWN0IGpyX2h3X2Rlc2MgKm91
Yl9yaW5nX3ZpcnRfYWRkcjsNCisJdTMyIG91Yl9jb3VudDsNCisJc3BpbmxvY2tfdCBvdWJfbG9j
azsNCisNCisJc3RydWN0IGZzbF9yZV9kbWFfYXN5bmNfdHhfZGVzYyAqZGVzY3M7IC8qIHN3IGRl
c2NyaXB0b3IgcmluZyAqLw0KKwl2b2lkICpjZnM7CQkJCS8qIGRtYSBkZXNjcmlwdG9yIHJpbmcg
Ki8NCisJZG1hX2FkZHJfdCBwaHlzOyAgICAgICAgICAvKiBwaHlzIGFkZHIgZm9yIGRtYSBkZXNj
cmlwdG9yIHJpbmcgKi8NCisNCisJc3RydWN0IHRpbWVyX2xpc3QgdGltZXI7DQorfTsNCisNCitl
bnVtIGRlc2Nfc3RhdGUgew0KKwlSRV9ERVNDX0VNUFRZLA0KKwlSRV9ERVNDX0FMTE9DLA0KK307
DQorDQorLyogQXN5bmMgdHJhbnNhY3Rpb24gZGVzY3JpcHRvciAqLw0KK3N0cnVjdCBmc2xfcmVf
ZG1hX2FzeW5jX3R4X2Rlc2Mgew0KKwlzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgYXN5
bmNfdHg7DQorCXN0cnVjdCBsaXN0X2hlYWQgbm9kZTsNCisJc3RydWN0IGxpc3RfaGVhZCB0eF9s
aXN0Ow0KKwlzdHJ1Y3QganJfaHdfZGVzYyAqaHdkZXNjOw0KKwlzdHJ1Y3QgcmVfanIgKmpyOw0K
Kw0KKwl2b2lkICpjZl9hZGRyOw0KKwlpbnQgZG1hX2xlbjsNCisJdTggZGVzdF9jbnQ7DQorCXU4
IHNyY19jbnQ7DQorDQorCXUxNiBjZGJfb3Bjb2RlOw0KKwl2b2lkICpjZGJfYWRkcjsNCisJZG1h
X2FkZHJfdCBjZGJfcGFkZHI7DQorCWludCBjZGJfbGVuOw0KKw0KKwllbnVtIGRlc2Nfc3RhdGUg
c3RhdGU7DQorfTsNCi0tDQoxLjcuOS41DQoNCg==
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-04-10 5:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-21 9:01 [PATCH 1/2] powerpc/dma/raidengine: add raidengine device b29237
2012-11-21 9:01 ` [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device b29237
2013-04-10 5:07 ` Shi Xuelin-B29237
2012-11-25 13:21 ` [PATCH 1/2] powerpc/dma/raidengine: add raidengine device Kumar Gala
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).