From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eugeniy.Paltsev@synopsys.com (Eugeniy Paltsev) Date: Fri, 21 Apr 2017 14:29:38 +0000 Subject: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver In-Reply-To: <1492518695.24567.56.camel@linux.intel.com> References: <1491573855-1039-1-git-send-email-Eugeniy.Paltsev@synopsys.com> <1491573855-1039-3-git-send-email-Eugeniy.Paltsev@synopsys.com> <1492518695.24567.56.camel@linux.intel.com> List-ID: Message-ID: <1492784977.16657.6.camel@synopsys.com> To: linux-snps-arc@lists.infradead.org Hi Andy, thanks for respond. My comments are inlined below. On Tue, 2017-04-18@15:31 +0300, Andy Shevchenko wrote: > On Fri, 2017-04-07@17:04 +0300, Eugeniy Paltsev wrote: > > This patch adds support for the DW AXI DMAC controller. > > > > DW AXI DMAC is a part of upcoming development board from Synopsys. > > > > In this driver implementation only DMA_MEMCPY and DMA_SG transfers > > are supported. > > > > +++ b/drivers/dma/axi_dma_platform.c > > @@ -0,0 +1,1044 @@ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > Are you sure you still need of.h along with depends OF ? "of_match_ptr" used from of.h > > +#include > > +#include > > +#include > > +#include > > + > > +#include "axi_dma_platform.h" > > +#include "axi_dma_platform_reg.h" > > Can't you have this in one header? Sure. > > +#include "dmaengine.h" > > +#include "virt-dma.h" > > +#define AXI_DMA_BUSWIDTHS ??\ > > + (DMA_SLAVE_BUSWIDTH_1_BYTE | \ > > + DMA_SLAVE_BUSWIDTH_2_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_4_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_8_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_16_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_32_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_64_BYTES) > > +/* TODO: check: do we need to use BIT() macro here? */ > > Still TODO? I remember I answered to this on the first round. Yes, I remember it. I left this TODO as a reminder because src_addr_widths and dst_addr_widths are not used anywhere and they are set differently in different drivers (with or without BIT macro). > > + > > +static inline void > > +axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val) > > +{ > > + iowrite32(val, chip->regs + reg); > > Are you going to use IO ports for this IP? I don't think so. > Wouldn't be better to call readl()/writel() instead? As I understand, it's better to use ioread/iowrite as more universal IO access way. Am I wrong? > > +} > > +static inline void > > +axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val) > > +{ > > + iowrite32(val & 0xFFFFFFFF, chan->chan_regs + reg); > Useless conjunction. > > > + iowrite32(val >> 32, chan->chan_regs + reg + 4); > > +} > > Can your hardware get 8 bytes at once? > For such cases we have iowrite64() for 64-bit kernels > > But with readq()/writeq() we have specific helpers to make this > pretty, > i.e. lo_hi_readq() / lo_hi_writeq() (or hi_lo_*() variants). Ok, I possibly can use lo_hi_writeq here. > > +static inline void axi_chan_irq_disable(struct axi_dma_chan *chan, > > u32 irq_mask) > > +{ > > + u32 val; > > + > > + if (likely(irq_mask == DWAXIDMAC_IRQ_ALL)) { > > + axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, > > DWAXIDMAC_IRQ_NONE); > > + } else { > > I don't see the benefit. (Yes, I see one read-less path, I think it > makes perplexity for nothing here) This function is called mostly with irq_mask = DWAXIDMAC_IRQ_ALL. Actually it is called only with irq_mask = DWAXIDMAC_IRQ_ALL until I add DMA_SLAVE support. But I can cut off this 'if' statment, if it is necessery. > > + val = axi_chan_ioread32(chan, CH_INTSTATUS_ENA); > > + val &= ~irq_mask; > > + axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, val); > > + } > > +} > > +static inline void axi_chan_disable(struct axi_dma_chan *chan) > > +{ > > +} > > + > > +static inline void axi_chan_enable(struct axi_dma_chan *chan) > > +{ > > +} > > +static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, > > dma_addr_t src, > > + ???dma_addr_t dst, size_t len) > > +{ > > + u32 max_width = chan->chip->dw->hdata->m_data_width; > > + size_t sdl = (src | dst | len); > > Redundant parens, redundant temporary variable (you may do this in > place). Ok. > > + > > + return min_t(size_t, __ffs(sdl), max_width); > > +} > > +static void axi_desc_put(struct axi_dma_desc *desc) > > +{ > > + struct axi_dma_chan *chan = desc->chan; > > + struct dw_axi_dma *dw = chan->chip->dw; > > + struct axi_dma_desc *child, *_next; > > + unsigned int descs_put = 0; > > + list_for_each_entry_safe(child, _next, &desc->xfer_list, > > xfer_list) { > > xfer_list looks redundant. > Can you elaborate why virtual channel management is not working for > you? Each virtual descriptor encapsulates several hardware descriptors, which belong to same transfer. This list (xfer_list) is used only for allocating/freeing these descriptors and it doesn't affect on virtual dma work logic. I can see this approach in several drivers with VirtDMA (but they mostly use array instead of list) > > + list_del(&child->xfer_list); > > + dma_pool_free(dw->desc_pool, child, child- > > > vd.tx.phys); > > > > + descs_put++; > > + } > > +} > > +/* Called in chan locked context */ > > +static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, > > + ??????struct axi_dma_desc *first) > > +{ > > + u32 reg, irq_mask; > > + u8 lms = 0; > > Does it make any sense? It looks like lms is always 0. > Or I miss the source of its value? lms variable uset to determine axi bus for reading lli descriptors. It is equal to 0 for mem-to-mem transfers. Perhaps it is better to use define instead of this variable. > > + u32 priority = chan->chip->dw->hdata->priority[chan->id]; > > Reversed xmas tree, please. > > Btw, are you planning to use priority at all? For now on I didn't see > a single driver (from the set I have checked, like 4-5 of them) that > uses priority anyhow. It makes driver more complex for nothing. Only for dma slave operations. > > > + > > + if (unlikely(axi_chan_is_hw_enable(chan))) { > > + dev_err(chan2dev(chan), "%s is non-idle!\n", > > + axi_chan_name(chan)); > > + > > + return; > > + } > > +} > > +static void dma_chan_free_chan_resources(struct dma_chan *dchan) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + > > + /* ASSERT: channel hw is idle */ > > + if (axi_chan_is_hw_enable(chan)) > > + dev_err(dchan2dev(dchan), "%s is non-idle!\n", > > + axi_chan_name(chan)); > > + > > + axi_chan_disable(chan); > > + axi_chan_irq_disable(chan, DWAXIDMAC_IRQ_ALL); > > + > > + vchan_free_chan_resources(&chan->vc); > > + > > + dev_vdbg(dchan2dev(dchan), "%s: %s: descriptor still > > allocated: %u\n", > > + __func__, axi_chan_name(chan), > > Redundant __func__ parameter for debug prints. > > > + atomic_read(&chan->descs_allocated)); > > + > > + pm_runtime_put(chan->chip->dev); > > +} > > +static struct dma_async_tx_descriptor * > > +dma_chan_prep_dma_sg(struct dma_chan *dchan, > > + ?????struct scatterlist *dst_sg, unsigned int > > dst_nents, > > + ?????struct scatterlist *src_sg, unsigned int > > src_nents, > > + ?????unsigned long flags) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + struct axi_dma_desc *first = NULL, *desc = NULL, *prev = > > NULL; > > + size_t dst_len = 0, src_len = 0, xfer_len = 0; > > + dma_addr_t dst_adr = 0, src_adr = 0; > > + u32 src_width, dst_width; > > + size_t block_ts, max_block_ts; > > + u32 reg; > > + u8 lms = 0; > > Same about lms. > > > + > > + dev_dbg(chan2dev(chan), "%s: %s: sn: %d dn: %d flags: > > 0x%lx", > > + __func__, axi_chan_name(chan), src_nents, > > dst_nents, > > flags); > > Ditto for __func__. > > > + > > > > + if (unlikely(dst_nents == 0 || src_nents == 0)) > > + return NULL; > > + > > + if (unlikely(dst_sg == NULL || src_sg == NULL)) > > + return NULL; > > If we need those checks they should go to dmaengine.h/dmaengine.c. I checked several drivers, which implements device_prep_dma_sg and they implements this checkers. Should I add something like "dma_sg_desc_invalid" function to dmaengine.h ? > > +static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, > > + ???struct axi_dma_desc *desc_head) > > +{ > > + struct axi_dma_desc *desc; > > + > > + axi_chan_dump_lli(chan, desc_head); > > + list_for_each_entry(desc, &desc_head->xfer_list, > > xfer_list) > > + axi_chan_dump_lli(chan, desc); > > +} > > + > > +static void axi_chan_handle_err(struct axi_dma_chan *chan, u32 > > status) > > +{ > > + /* WARN about bad descriptor */ > > > > + dev_err(chan2dev(chan), > > + "Bad descriptor submitted for %s, cookie: %d, irq: > > 0x%08x\n", > > + axi_chan_name(chan), vd->tx.cookie, status); > > + axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd)); > > As I said earlier dw_dmac is *bad* example of the (virtual channel > based) DMA driver. > > I guess you may just fail the descriptor and don't pretend it has > been processed successfully. What do you mean by saying "fail the descriptor"? After I get error I cancel current transfer and free all descriptors from it (by calling vchan_cookie_complete). I can't store error status in descriptor structure because it will be freed by vchan_cookie_complete. I can't store error status in channel structure because it will be overwritten by next transfer. > > +static int dma_chan_pause(struct dma_chan *dchan) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + unsigned long flags; > > + unsigned int timeout = 20; /* timeout iterations */ > > + int ret = -EAGAIN; > > + u32 val; > > + > > + spin_lock_irqsave(&chan->vc.lock, flags); > > + > > + val = axi_dma_ioread32(chan->chip, DMAC_CHEN); > > + val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT | > > + ???????BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT; > > + axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); > > You have helpers which you don't use. Why? Ok, will use. > > + > > + while (timeout--) { > > In such cases I prefer do {} while (); to explicitly show that body > goes at least once. Good idea. Will change to do {} while () here. > > + if (axi_chan_irq_read(chan) & > > DWAXIDMAC_IRQ_SUSPENDED) { > > + ret = 0; > > + break; > > + } > > + udelay(2); > > + } > > + > > + axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED); > > + > > + chan->is_paused = true; > > + > > + spin_unlock_irqrestore(&chan->vc.lock, flags); > > + > > + return ret; > > +} > > + > > +/* Called in chan locked context */ > > +static inline void axi_chan_resume(struct axi_dma_chan *chan) > > +{ > > + u32 val; > > + > > + val = axi_dma_ioread32(chan->chip, DMAC_CHEN); > > + val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT); > > + val |=??(BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT); > > + axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); > > + > > + chan->is_paused = false; > > +} > > +static int axi_dma_runtime_suspend(struct device *dev) > > +{ > > + struct axi_dma_chip *chip = dev_get_drvdata(dev); > > + > > + dev_info(dev, "PAL: %s\n", __func__); > > Noisy and useless. > We have functional tracer in kernel. Use it. Ok. > > + > > + axi_dma_irq_disable(chip); > > + axi_dma_disable(chip); > > + > > + clk_disable_unprepare(chip->clk); > > + > > + return 0; > > +} [snip] > > + > > +static const struct dev_pm_ops dw_axi_dma_pm_ops = { > > + SET_RUNTIME_PM_OPS(axi_dma_runtime_suspend, > > axi_dma_runtime_resume, NULL) > > +}; > > Have you tried to build with CONFIG_PM disabled? Yes. > I'm pretty sure you need __maybe_unused applied to your PM ops. I call axi_dma_runtime_suspend / axi_dma_runtime_resume even I dont't use PM. (I call them in probe / remove function.) So I don't need to declare them with __maybe_unused. > > +struct axi_dma_chan { > > + struct axi_dma_chip *chip; > > + void __iomem *chan_regs; > > + u8 id; > > + atomic_t descs_allocated; > > + > > + struct virt_dma_chan vc; > > + > > + /* these other elements are all protected by vc.lock */ > > + bool is_paused; > > I still didn't get (already forgot) why you can't use dma_status > instead for the active descriptor? As I said before, I checked several driver, which have status variable in their channel structure - it is used *only* for determinating is channel paused or not. So there is no much sense in replacing "is_paused" to "status" and I left "is_paused" variable untouched. (I described above why we can't use status in channel structure for error handling) > > +}; > > +/* LLI == Linked List Item */ > > +struct __attribute__ ((__packed__)) axi_dma_lli { > > ... > > > + __le64 sar; > > + __le64 dar; > > + __le32 block_ts_lo; > > + __le32 block_ts_hi; > > + __le64 llp; > > + __le32 ctl_lo; > > + __le32 ctl_hi; > > + __le32 sstat; > > + __le32 dstat; > > + __le32 status_lo; > > + __le32 ststus_hi; > > + __le32 reserved_lo; > > + __le32 reserved_hi; > > +}; > > Just __packed here. > Ok. > > + > > +struct axi_dma_desc { > > + struct axi_dma_lli lli; > > + > > + struct virt_dma_desc vd; > > + struct axi_dma_chan *chan; > > + struct list_head xfer_list; > > This looks redundant. Already asked above about it. Answered above. > > +}; > > + > > +/* Common registers offset */ > > +#define DMAC_ID 0x000 /* R DMAC ID */ > > +#define DMAC_COMPVER 0x008 /* R DMAC Component > > Version > > */ > > +#define DMAC_CFG 0x010 /* R/W DMAC Configuration */ > > +#define DMAC_CHEN 0x018 /* R/W DMAC Channel Enable > > */ > > +#define DMAC_CHEN_L 0x018 /* R/W DMAC Channel > > Enable > > 00-31 */ > > +#define DMAC_CHEN_H 0x01C /* R/W DMAC Channel > > Enable > > 32-63 */ > > +#define DMAC_INTSTATUS 0x030 /* R DMAC Interrupt > > Status */ > > +#define DMAC_COMMON_INTCLEAR 0x038 /* W DMAC Interrupt > > Clear > > */ > > +#define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status > > Enable */ > > +#define DMAC_COMMON_INTSIGNAL_ENA 0x048 /* R/W DMAC Interrupt > > Signal > > Enable */ > > +#define DMAC_COMMON_INTSTATUS 0x050 /* R DMAC Interrupt > > Status > > */ > > +#define DMAC_RESET 0x058 /* R DMAC Reset Register1 > > */ > > + > > +/* DMA channel registers offset */ > > +#define CH_SAR 0x000 /* R/W Chan Source > > Address */ > > +#define CH_DAR 0x008 /* R/W Chan > > Destination > > Address */ > > +#define CH_BLOCK_TS 0x010 /* R/W Chan Block > > Transfer > > Size */ > > +#define CH_CTL 0x018 /* R/W Chan Control */ > > +#define CH_CTL_L 0x018 /* R/W Chan Control 00-31 */ > > +#define CH_CTL_H 0x01C /* R/W Chan Control 32-63 */ > > +#define CH_CFG 0x020 /* R/W Chan > > Configuration > > */ > > +#define CH_CFG_L 0x020 /* R/W Chan Configuration > > 00-31 > > */ > > +#define CH_CFG_H 0x024 /* R/W Chan Configuration > > 32-63 > > */ > > +#define CH_LLP 0x028 /* R/W Chan Linked > > List > > Pointer */ > > +#define CH_STATUS 0x030 /* R Chan Status */ > > +#define CH_SWHSSRC 0x038 /* R/W Chan SW Handshake > > Source */ > > +#define CH_SWHSDST 0x040 /* R/W Chan SW Handshake > > Destination */ > > +#define CH_BLK_TFR_RESUMEREQ 0x048 /* W Chan Block Transfer > > Resume Req */ > > +#define CH_AXI_ID 0x050 /* R/W Chan AXI ID */ > > +#define CH_AXI_QOS 0x058 /* R/W Chan AXI QOS */ > > +#define CH_SSTAT 0x060 /* R Chan Source Status */ > > +#define CH_DSTAT 0x068 /* R Chan Destination Status > > */ > > +#define CH_SSTATAR 0x070 /* R/W Chan Source Status > > Fetch Addr */ > > +#define CH_DSTATAR 0x078 /* R/W Chan Destination > > Status Fetch Addr */ > > +#define CH_INTSTATUS_ENA 0x080 /* R/W Chan Interrupt Status > > Enable */ > > +#define CH_INTSTATUS 0x088 /* R/W Chan Interrupt > > Status */ > > +#define CH_INTSIGNAL_ENA 0x090 /* R/W Chan Interrupt Signal > > Enable */ > > +#define CH_INTCLEAR 0x098 /* W Chan Interrupt Clear > > */ > > I'm wondering if you can use regmap API instead. Is it really necessary? It'll make driver more complex for nothing. > > > +/* DMAC_CFG */ > > +#define DMAC_EN_MASK 0x00000001U > > GENMASK() Ok. > > +#define DMAC_EN_POS 0 > > Usually _SHIFT, but it's up to you. > > > +enum { > > + DWAXIDMAC_BURST_TRANS_LEN_1 = 0x0, > > + DWAXIDMAC_BURST_TRANS_LEN_4, > > + DWAXIDMAC_BURST_TRANS_LEN_8, > > + DWAXIDMAC_BURST_TRANS_LEN_16, > > + DWAXIDMAC_BURST_TRANS_LEN_32, > > + DWAXIDMAC_BURST_TRANS_LEN_64, > > + DWAXIDMAC_BURST_TRANS_LEN_128, > > + DWAXIDMAC_BURST_TRANS_LEN_256, > > + DWAXIDMAC_BURST_TRANS_LEN_512, > > + DWAXIDMAC_BURST_TRANS_LEN_1024 > > ..._1024, ? What exactly you are asking about? > > +}; > > Hmm... do you need them in the header? I use some of these definitions in my code so I guess yes. /* Maybe I misunderstood your question... */ > > +#define CH_CFG_H_TT_FC_POS 0 > > +enum { > > + DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0x0, > > + DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_PER_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_MEM_SRC, > > + DWAXIDMAC_TT_FC_PER_TO_PER_SRC, > > + DWAXIDMAC_TT_FC_MEM_TO_PER_DST, > > + DWAXIDMAC_TT_FC_PER_TO_PER_DST > > +}; > > Some of definitions are the same as for dw_dmac, right? We might > split them to a common header, though I have no strong opinion about it. > Vinod? APB DMAC and AXI DMAC have completely different regmap. So there is no much sense to do that. -- ?Eugeniy Paltsev From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eugeniy Paltsev Subject: Re: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver Date: Fri, 21 Apr 2017 14:29:38 +0000 Message-ID: <1492784977.16657.6.camel@synopsys.com> References: <1491573855-1039-1-git-send-email-Eugeniy.Paltsev@synopsys.com> <1491573855-1039-3-git-send-email-Eugeniy.Paltsev@synopsys.com> <1492518695.24567.56.camel@linux.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1492518695.24567.56.camel-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> Content-Language: en-US Content-ID: <025345809586DF49A1C2E405A43F3F95-z7JfP6tgrtVBCHUSTMH8dZqQE7yCjDx5@public.gmane.org> Sender: devicetree-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: "andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org" Cc: "vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org" , "linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , "robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org" , "Alexey.Brodkin-HKixBCOQz3hWk0Htik3J/w@public.gmane.org" , "devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , "Eugeniy.Paltsev-HKixBCOQz3hWk0Htik3J/w@public.gmane.org" , "linux-snps-arc-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org" , "dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org" , "dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" List-Id: devicetree@vger.kernel.org SGkgQW5keSwNCnRoYW5rcyBmb3IgcmVzcG9uZC4NCk15IGNvbW1lbnRzIGFyZSBpbmxpbmVkIGJl bG93Lg0KDQpPbiBUdWUsIDIwMTctMDQtMTggYXQgMTU6MzEgKzAzMDAsIEFuZHkgU2hldmNoZW5r byB3cm90ZToNCj4gT24gRnJpLCAyMDE3LTA0LTA3IGF0IDE3OjA0ICswMzAwLCBFdWdlbml5IFBh bHRzZXYgd3JvdGU6DQo+ID4gVGhpcyBwYXRjaCBhZGRzIHN1cHBvcnQgZm9yIHRoZSBEVyBBWEkg RE1BQyBjb250cm9sbGVyLg0KPiA+DQo+ID4gRFcgQVhJIERNQUMgaXMgYSBwYXJ0IG9mIHVwY29t aW5nIGRldmVsb3BtZW50IGJvYXJkIGZyb20gU3lub3BzeXMuDQo+ID4NCj4gPiBJbiB0aGlzIGRy aXZlciBpbXBsZW1lbnRhdGlvbiBvbmx5IERNQV9NRU1DUFkgYW5kIERNQV9TRyB0cmFuc2ZlcnMN Cj4gPiBhcmUgc3VwcG9ydGVkLg0KPiA+DQo+ID4gKysrIGIvZHJpdmVycy9kbWEvYXhpX2RtYV9w bGF0Zm9ybS5jDQo+ID4gQEAgLTAsMCArMSwxMDQ0IEBADQo+ID4gKyNpbmNsdWRlIDxsaW51eC9i aXRvcHMuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+DQo+ID4gKyNpbmNsdWRlIDxs aW51eC9kZXZpY2UuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPg0KPiA+ICsj aW5jbHVkZSA8bGludXgvZG1hcG9vbC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvZXJyLmg+DQo+ ID4gKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2lv Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4 L21vZHVsZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4NCj4NCj4gQXJlIHlvdSBzdXJl IHlvdSBzdGlsbCBuZWVkIG9mLmggYWxvbmcgd2l0aCBkZXBlbmRzIE9GID8NCiJvZl9tYXRjaF9w dHIiIHVzZWQgZnJvbSBvZi5oDQoNCj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2Rldmlj ZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcG1fcnVudGltZS5oPg0KPiA+ICsjaW5jbHVkZSA8 bGludXgvcHJvcGVydHkuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+DQo+ID4gKw0K PiA+ICsjaW5jbHVkZSAiYXhpX2RtYV9wbGF0Zm9ybS5oIg0KPiA+ICsjaW5jbHVkZSAiYXhpX2Rt YV9wbGF0Zm9ybV9yZWcuaCINCj4NCj4gQ2FuJ3QgeW91IGhhdmUgdGhpcyBpbiBvbmUgaGVhZGVy Pw0KU3VyZS4NCg0KPiA+ICsjaW5jbHVkZSAiZG1hZW5naW5lLmgiDQo+ID4gKyNpbmNsdWRlICJ2 aXJ0LWRtYS5oIg0KPiA+ICsjZGVmaW5lIEFYSV9ETUFfQlVTV0lEVEhTCQnCoMKgXA0KPiA+ICsJ KERNQV9TTEFWRV9CVVNXSURUSF8xX0JZVEUJfCBcDQo+ID4gKwlETUFfU0xBVkVfQlVTV0lEVEhf Ml9CWVRFUwl8IFwNCj4gPiArCURNQV9TTEFWRV9CVVNXSURUSF80X0JZVEVTCXwgXA0KPiA+ICsJ RE1BX1NMQVZFX0JVU1dJRFRIXzhfQllURVMJfCBcDQo+ID4gKwlETUFfU0xBVkVfQlVTV0lEVEhf MTZfQllURVMJfCBcDQo+ID4gKwlETUFfU0xBVkVfQlVTV0lEVEhfMzJfQllURVMJfCBcDQo+ID4g KwlETUFfU0xBVkVfQlVTV0lEVEhfNjRfQllURVMpDQo+ID4gKy8qIFRPRE86IGNoZWNrOiBkbyB3 ZSBuZWVkIHRvIHVzZSBCSVQoKSBtYWNybyBoZXJlPyAqLw0KPg0KPiBTdGlsbCBUT0RPPyBJIHJl bWVtYmVyIEkgYW5zd2VyZWQgdG8gdGhpcyBvbiB0aGUgZmlyc3Qgcm91bmQuDQpZZXMsIEkgcmVt ZW1iZXIgaXQuDQpJIGxlZnQgdGhpcyBUT0RPIGFzIGEgcmVtaW5kZXIgYmVjYXVzZSBzcmNfYWRk cl93aWR0aHMgYW5kDQpkc3RfYWRkcl93aWR0aHMgYXJlDQpub3QgdXNlZCBhbnl3aGVyZSBhbmQg dGhleSBhcmUgc2V0IGRpZmZlcmVudGx5IGluIGRpZmZlcmVudCBkcml2ZXJzDQood2l0aCBvciB3 aXRob3V0IEJJVCBtYWNybykuDQoNCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgdm9pZA0KPiA+ ICtheGlfZG1hX2lvd3JpdGUzMihzdHJ1Y3QgYXhpX2RtYV9jaGlwICpjaGlwLCB1MzIgcmVnLCB1 MzIgdmFsKQ0KPiA+ICt7DQo+ID4gKwlpb3dyaXRlMzIodmFsLCBjaGlwLT5yZWdzICsgcmVnKTsN Cj4NCj4gQXJlIHlvdSBnb2luZyB0byB1c2UgSU8gcG9ydHMgZm9yIHRoaXMgSVA/IEkgZG9uJ3Qg dGhpbmsgc28uDQo+IFdvdWxkbid0IGJlIGJldHRlciB0byBjYWxsIHJlYWRsKCkvd3JpdGVsKCkg aW5zdGVhZD8NCkFzIEkgdW5kZXJzdGFuZCwgaXQncyBiZXR0ZXIgdG8gdXNlIGlvcmVhZC9pb3dy aXRlIGFzIG1vcmUgdW5pdmVyc2FsIElPDQphY2Nlc3Mgd2F5LiBBbSBJIHdyb25nPw0KDQo+ID4g K30NCj4gPiArc3RhdGljIGlubGluZSB2b2lkDQo+ID4gK2F4aV9jaGFuX2lvd3JpdGU2NChzdHJ1 Y3QgYXhpX2RtYV9jaGFuICpjaGFuLCB1MzIgcmVnLCB1NjQgdmFsKQ0KPiA+ICt7DQo+ID4gKwlp b3dyaXRlMzIodmFsICYgMHhGRkZGRkZGRiwgY2hhbi0+Y2hhbl9yZWdzICsgcmVnKTsNCj4gVXNl bGVzcyBjb25qdW5jdGlvbi4NCj4NCj4gPiArCWlvd3JpdGUzMih2YWwgPj4gMzIsIGNoYW4tPmNo YW5fcmVncyArIHJlZyArIDQpOw0KPiA+ICt9DQo+DQo+IENhbiB5b3VyIGhhcmR3YXJlIGdldCA4 IGJ5dGVzIGF0IG9uY2U/DQo+IEZvciBzdWNoIGNhc2VzIHdlIGhhdmUgaW93cml0ZTY0KCkgZm9y IDY0LWJpdCBrZXJuZWxzDQo+DQo+IEJ1dCB3aXRoIHJlYWRxKCkvd3JpdGVxKCkgd2UgaGF2ZSBz cGVjaWZpYyBoZWxwZXJzIHRvIG1ha2UgdGhpcw0KPiBwcmV0dHksDQo+IGkuZS4gbG9faGlfcmVh ZHEoKSAvIGxvX2hpX3dyaXRlcSgpIChvciBoaV9sb18qKCkgdmFyaWFudHMpLg0KT2ssIEkgcG9z c2libHkgY2FuIHVzZSBsb19oaV93cml0ZXEgaGVyZS4NCg0KPiA+ICtzdGF0aWMgaW5saW5lIHZv aWQgYXhpX2NoYW5faXJxX2Rpc2FibGUoc3RydWN0IGF4aV9kbWFfY2hhbiAqY2hhbiwNCj4gPiB1 MzIgaXJxX21hc2spDQo+ID4gK3sNCj4gPiArCXUzMiB2YWw7DQo+ID4gKw0KPiA+ICsJaWYgKGxp a2VseShpcnFfbWFzayA9PSBEV0FYSURNQUNfSVJRX0FMTCkpIHsNCj4gPiArCQlheGlfY2hhbl9p b3dyaXRlMzIoY2hhbiwgQ0hfSU5UU1RBVFVTX0VOQSwNCj4gPiBEV0FYSURNQUNfSVJRX05PTkUp Ow0KPiA+ICsJfSBlbHNlIHsNCj4NCj4gSSBkb24ndCBzZWUgdGhlIGJlbmVmaXQuIChZZXMsIEkg c2VlIG9uZSByZWFkLWxlc3MgcGF0aCwgSSB0aGluayBpdA0KPiBtYWtlcyBwZXJwbGV4aXR5IGZv ciBub3RoaW5nIGhlcmUpDQpUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBtb3N0bHkgd2l0aCBpcnFf bWFzayA9IERXQVhJRE1BQ19JUlFfQUxMLg0KQWN0dWFsbHkgaXQgaXMgY2FsbGVkIG9ubHkgd2l0 aCBpcnFfbWFzayA9IERXQVhJRE1BQ19JUlFfQUxMIHVudGlsIEkNCmFkZCBETUFfU0xBVkUgc3Vw cG9ydC4NCkJ1dCBJIGNhbiBjdXQgb2ZmIHRoaXMgJ2lmJyBzdGF0bWVudCwgaWYgaXQgaXMgbmVj ZXNzZXJ5Lg0KDQo+ID4gKwkJdmFsID0gYXhpX2NoYW5faW9yZWFkMzIoY2hhbiwgQ0hfSU5UU1RB VFVTX0VOQSk7DQo+ID4gKwkJdmFsICY9IH5pcnFfbWFzazsNCj4gPiArCQlheGlfY2hhbl9pb3dy aXRlMzIoY2hhbiwgQ0hfSU5UU1RBVFVTX0VOQSwgdmFsKTsNCj4gPiArCX0NCj4gPiArfQ0KPiA+ ICtzdGF0aWMgaW5saW5lIHZvaWQgYXhpX2NoYW5fZGlzYWJsZShzdHJ1Y3QgYXhpX2RtYV9jaGFu ICpjaGFuKQ0KPiA+ICt7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgdm9pZCBh eGlfY2hhbl9lbmFibGUoc3RydWN0IGF4aV9kbWFfY2hhbiAqY2hhbikNCj4gPiArew0KPiA+ICt9 DQo+ID4gK3N0YXRpYyB1MzIgYXhpX2NoYW5fZ2V0X3hmZXJfd2lkdGgoc3RydWN0IGF4aV9kbWFf Y2hhbiAqY2hhbiwNCj4gPiBkbWFfYWRkcl90IHNyYywNCj4gPiArCQkJCcKgwqDCoGRtYV9hZGRy X3QgZHN0LCBzaXplX3QgbGVuKQ0KPiA+ICt7DQo+ID4gKwl1MzIgbWF4X3dpZHRoID0gY2hhbi0+ Y2hpcC0+ZHctPmhkYXRhLT5tX2RhdGFfd2lkdGg7DQo+ID4gKwlzaXplX3Qgc2RsID0gKHNyYyB8 IGRzdCB8IGxlbik7DQo+DQo+IFJlZHVuZGFudCBwYXJlbnMsIHJlZHVuZGFudCB0ZW1wb3Jhcnkg dmFyaWFibGUgKHlvdSBtYXkgZG8gdGhpcyBpbg0KPiBwbGFjZSkuDQpPay4NCg0KPiA+ICsNCj4g PiArCXJldHVybiBtaW5fdChzaXplX3QsIF9fZmZzKHNkbCksIG1heF93aWR0aCk7DQo+ID4gK30N Cj4gPiArc3RhdGljIHZvaWQgYXhpX2Rlc2NfcHV0KHN0cnVjdCBheGlfZG1hX2Rlc2MgKmRlc2Mp DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBheGlfZG1hX2NoYW4gKmNoYW4gPSBkZXNjLT5jaGFuOw0K PiA+ICsJc3RydWN0IGR3X2F4aV9kbWEgKmR3ID0gY2hhbi0+Y2hpcC0+ZHc7DQo+ID4gKwlzdHJ1 Y3QgYXhpX2RtYV9kZXNjICpjaGlsZCwgKl9uZXh0Ow0KPiA+ICsJdW5zaWduZWQgaW50IGRlc2Nz X3B1dCA9IDA7DQo+ID4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY2hpbGQsIF9uZXh0LCAm ZGVzYy0+eGZlcl9saXN0LA0KPiA+IHhmZXJfbGlzdCkgew0KPg0KPiB4ZmVyX2xpc3QgbG9va3Mg cmVkdW5kYW50Lg0KPiBDYW4geW91IGVsYWJvcmF0ZSB3aHkgdmlydHVhbCBjaGFubmVsIG1hbmFn ZW1lbnQgaXMgbm90IHdvcmtpbmcgZm9yDQo+IHlvdT8NCkVhY2ggdmlydHVhbCBkZXNjcmlwdG9y IGVuY2Fwc3VsYXRlcyBzZXZlcmFsIGhhcmR3YXJlIGRlc2NyaXB0b3JzLA0Kd2hpY2ggYmVsb25n IHRvIHNhbWUgdHJhbnNmZXIuDQpUaGlzIGxpc3QgKHhmZXJfbGlzdCkgaXMgdXNlZCBvbmx5IGZv ciBhbGxvY2F0aW5nL2ZyZWVpbmcgdGhlc2UNCmRlc2NyaXB0b3JzIGFuZCBpdCBkb2Vzbid0IGFm ZmVjdCBvbiB2aXJ0dWFsIGRtYSB3b3JrIGxvZ2ljLg0KSSBjYW4gc2VlIHRoaXMgYXBwcm9hY2gg aW4gc2V2ZXJhbCBkcml2ZXJzIHdpdGggVmlydERNQSAoYnV0IHRoZXkNCm1vc3RseSB1c2UgYXJy YXkgaW5zdGVhZCBvZiBsaXN0KQ0KDQo+ID4gKwkJbGlzdF9kZWwoJmNoaWxkLT54ZmVyX2xpc3Qp Ow0KPiA+ICsJCWRtYV9wb29sX2ZyZWUoZHctPmRlc2NfcG9vbCwgY2hpbGQsIGNoaWxkLQ0KPiA+ ID4gdmQudHgucGh5cyk7DQo+ID4NCj4gPiArCQlkZXNjc19wdXQrKzsNCj4gPiArCX0NCj4gPiAr fQ0KPiA+ICsvKiBDYWxsZWQgaW4gY2hhbiBsb2NrZWQgY29udGV4dCAqLw0KPiA+ICtzdGF0aWMg dm9pZCBheGlfY2hhbl9ibG9ja194ZmVyX3N0YXJ0KHN0cnVjdCBheGlfZG1hX2NoYW4gKmNoYW4s DQo+ID4gKwkJCQnCoMKgwqDCoMKgwqBzdHJ1Y3QgYXhpX2RtYV9kZXNjICpmaXJzdCkNCj4gPiAr ew0KPiA+ICsJdTMyIHJlZywgaXJxX21hc2s7DQo+ID4gKwl1OCBsbXMgPSAwOw0KPg0KPiBEb2Vz IGl0IG1ha2UgYW55IHNlbnNlPyBJdCBsb29rcyBsaWtlIGxtcyBpcyBhbHdheXMgMC4NCj4gT3Ig SSBtaXNzIHRoZSBzb3VyY2Ugb2YgaXRzIHZhbHVlPw0KbG1zIHZhcmlhYmxlIHVzZXQgdG8gZGV0 ZXJtaW5lIGF4aSBidXMgZm9yIHJlYWRpbmcgbGxpIGRlc2NyaXB0b3JzLiBJdA0KaXMgZXF1YWwg dG8gMCBmb3IgbWVtLXRvLW1lbSB0cmFuc2ZlcnMuIFBlcmhhcHMgaXQgaXMgYmV0dGVyIHRvIHVz ZQ0KZGVmaW5lIGluc3RlYWQgb2YgdGhpcyB2YXJpYWJsZS4NCg0KPiA+ICsJdTMyIHByaW9yaXR5 ID0gY2hhbi0+Y2hpcC0+ZHctPmhkYXRhLT5wcmlvcml0eVtjaGFuLT5pZF07DQo+DQo+IFJldmVy c2VkIHhtYXMgdHJlZSwgcGxlYXNlLg0KPg0KPiBCdHcsIGFyZSB5b3UgcGxhbm5pbmcgdG8gdXNl IHByaW9yaXR5IGF0IGFsbD8gRm9yIG5vdyBvbiBJIGRpZG4ndCBzZWUNCj4gYSBzaW5nbGUgZHJp dmVyIChmcm9tIHRoZSBzZXQgSSBoYXZlIGNoZWNrZWQsIGxpa2UgNC01IG9mIHRoZW0pIHRoYXQN Cj4gdXNlcyBwcmlvcml0eSBhbnlob3cuIEl0IG1ha2VzIGRyaXZlciBtb3JlIGNvbXBsZXggZm9y IG5vdGhpbmcuDQpPbmx5IGZvciBkbWEgc2xhdmUgb3BlcmF0aW9ucy4NCg0KPg0KPiA+ICsNCj4g PiArCWlmICh1bmxpa2VseShheGlfY2hhbl9pc19od19lbmFibGUoY2hhbikpKSB7DQo+ID4gKwkJ ZGV2X2VycihjaGFuMmRldihjaGFuKSwgIiVzIGlzIG5vbi1pZGxlIVxuIiwNCj4gPiArCQkJYXhp X2NoYW5fbmFtZShjaGFuKSk7DQo+ID4gKw0KPiA+ICsJCXJldHVybjsNCj4gPiArCX0NCj4gPiAr fQ0KPiA+ICtzdGF0aWMgdm9pZCBkbWFfY2hhbl9mcmVlX2NoYW5fcmVzb3VyY2VzKHN0cnVjdCBk bWFfY2hhbiAqZGNoYW4pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBheGlfZG1hX2NoYW4gKmNoYW4g PSBkY2hhbl90b19heGlfZG1hX2NoYW4oZGNoYW4pOw0KPiA+ICsNCj4gPiArCS8qIEFTU0VSVDog Y2hhbm5lbCBodyBpcyBpZGxlICovDQo+ID4gKwlpZiAoYXhpX2NoYW5faXNfaHdfZW5hYmxlKGNo YW4pKQ0KPiA+ICsJCWRldl9lcnIoZGNoYW4yZGV2KGRjaGFuKSwgIiVzIGlzIG5vbi1pZGxlIVxu IiwNCj4gPiArCQkJYXhpX2NoYW5fbmFtZShjaGFuKSk7DQo+ID4gKw0KPiA+ICsJYXhpX2NoYW5f ZGlzYWJsZShjaGFuKTsNCj4gPiArCWF4aV9jaGFuX2lycV9kaXNhYmxlKGNoYW4sIERXQVhJRE1B Q19JUlFfQUxMKTsNCj4gPiArDQo+ID4gKwl2Y2hhbl9mcmVlX2NoYW5fcmVzb3VyY2VzKCZjaGFu LT52Yyk7DQo+ID4gKw0KPiA+ICsJZGV2X3ZkYmcoZGNoYW4yZGV2KGRjaGFuKSwgIiVzOiAlczog ZGVzY3JpcHRvciBzdGlsbA0KPiA+IGFsbG9jYXRlZDogJXVcbiIsDQo+ID4gKwkJX19mdW5jX18s IGF4aV9jaGFuX25hbWUoY2hhbiksDQo+DQo+IFJlZHVuZGFudCBfX2Z1bmNfXyBwYXJhbWV0ZXIg Zm9yIGRlYnVnIHByaW50cy4NCj4NCj4gPiArCQlhdG9taWNfcmVhZCgmY2hhbi0+ZGVzY3NfYWxs b2NhdGVkKSk7DQo+ID4gKw0KPiA+ICsJcG1fcnVudGltZV9wdXQoY2hhbi0+Y2hpcC0+ZGV2KTsN Cj4gPiArfQ0KPiA+ICtzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICoNCj4g PiArZG1hX2NoYW5fcHJlcF9kbWFfc2coc3RydWN0IGRtYV9jaGFuICpkY2hhbiwNCj4gPiArCQnC oMKgwqDCoMKgc3RydWN0IHNjYXR0ZXJsaXN0ICpkc3Rfc2csIHVuc2lnbmVkIGludA0KPiA+IGRz dF9uZW50cywNCj4gPiArCQnCoMKgwqDCoMKgc3RydWN0IHNjYXR0ZXJsaXN0ICpzcmNfc2csIHVu c2lnbmVkIGludA0KPiA+IHNyY19uZW50cywNCj4gPiArCQnCoMKgwqDCoMKgdW5zaWduZWQgbG9u ZyBmbGFncykNCj4gPiArew0KPiA+ICsJc3RydWN0IGF4aV9kbWFfY2hhbiAqY2hhbiA9IGRjaGFu X3RvX2F4aV9kbWFfY2hhbihkY2hhbik7DQo+ID4gKwlzdHJ1Y3QgYXhpX2RtYV9kZXNjICpmaXJz dCA9IE5VTEwsICpkZXNjID0gTlVMTCwgKnByZXYgPQ0KPiA+IE5VTEw7DQo+ID4gKwlzaXplX3Qg ZHN0X2xlbiA9IDAsIHNyY19sZW4gPSAwLCB4ZmVyX2xlbiA9IDA7DQo+ID4gKwlkbWFfYWRkcl90 IGRzdF9hZHIgPSAwLCBzcmNfYWRyID0gMDsNCj4gPiArCXUzMiBzcmNfd2lkdGgsIGRzdF93aWR0 aDsNCj4gPiArCXNpemVfdCBibG9ja190cywgbWF4X2Jsb2NrX3RzOw0KPiA+ICsJdTMyIHJlZzsN Cj4gPiArCXU4IGxtcyA9IDA7DQo+DQo+IFNhbWUgYWJvdXQgbG1zLg0KPg0KPiA+ICsNCj4gPiAr CWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICIlczogJXM6IHNuOiAlZCBkbjogJWQgZmxhZ3M6DQo+ ID4gMHglbHgiLA0KPiA+ICsJCV9fZnVuY19fLCBheGlfY2hhbl9uYW1lKGNoYW4pLCBzcmNfbmVu dHMsDQo+ID4gZHN0X25lbnRzLA0KPiA+IGZsYWdzKTsNCj4NCj4gRGl0dG8gZm9yIF9fZnVuY19f Lg0KPg0KPiA+ICsNCj4gPg0KPiA+ICsJaWYgKHVubGlrZWx5KGRzdF9uZW50cyA9PSAwIHx8IHNy Y19uZW50cyA9PSAwKSkNCj4gPiArCQlyZXR1cm4gTlVMTDsNCj4gPiArDQo+ID4gKwlpZiAodW5s aWtlbHkoZHN0X3NnID09IE5VTEwgfHwgc3JjX3NnID09IE5VTEwpKQ0KPiA+ICsJCXJldHVybiBO VUxMOw0KPg0KPiBJZiB3ZSBuZWVkIHRob3NlIGNoZWNrcyB0aGV5IHNob3VsZCBnbyB0byBkbWFl bmdpbmUuaC9kbWFlbmdpbmUuYy4NCkkgY2hlY2tlZCBzZXZlcmFsIGRyaXZlcnMsIHdoaWNoIGlt cGxlbWVudHMgZGV2aWNlX3ByZXBfZG1hX3NnIGFuZCB0aGV5DQppbXBsZW1lbnRzIHRoaXMgY2hl Y2tlcnMuDQpTaG91bGQgSSBhZGQgc29tZXRoaW5nIGxpa2UgImRtYV9zZ19kZXNjX2ludmFsaWQi IGZ1bmN0aW9uIHRvDQpkbWFlbmdpbmUuaCA/DQoNCj4gPiArc3RhdGljIHZvaWQgYXhpX2NoYW5f bGlzdF9kdW1wX2xsaShzdHJ1Y3QgYXhpX2RtYV9jaGFuICpjaGFuLA0KPiA+ICsJCQkJwqDCoMKg c3RydWN0IGF4aV9kbWFfZGVzYyAqZGVzY19oZWFkKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgYXhp X2RtYV9kZXNjICpkZXNjOw0KPiA+ICsNCj4gPiArCWF4aV9jaGFuX2R1bXBfbGxpKGNoYW4sIGRl c2NfaGVhZCk7DQo+ID4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGRlc2MsICZkZXNjX2hlYWQtPnhm ZXJfbGlzdCwNCj4gPiB4ZmVyX2xpc3QpDQo+ID4gKwkJYXhpX2NoYW5fZHVtcF9sbGkoY2hhbiwg ZGVzYyk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIGF4aV9jaGFuX2hhbmRsZV9l cnIoc3RydWN0IGF4aV9kbWFfY2hhbiAqY2hhbiwgdTMyDQo+ID4gc3RhdHVzKQ0KPiA+ICt7DQo+ ID4gKwkvKiBXQVJOIGFib3V0IGJhZCBkZXNjcmlwdG9yICovDQo+ID4NCj4gPiArCWRldl9lcnIo Y2hhbjJkZXYoY2hhbiksDQo+ID4gKwkJIkJhZCBkZXNjcmlwdG9yIHN1Ym1pdHRlZCBmb3IgJXMs IGNvb2tpZTogJWQsIGlycToNCj4gPiAweCUwOHhcbiIsDQo+ID4gKwkJYXhpX2NoYW5fbmFtZShj aGFuKSwgdmQtPnR4LmNvb2tpZSwgc3RhdHVzKTsNCj4gPiArCWF4aV9jaGFuX2xpc3RfZHVtcF9s bGkoY2hhbiwgdmRfdG9fYXhpX2Rlc2ModmQpKTsNCj4NCj4gQXMgSSBzYWlkIGVhcmxpZXIgZHdf ZG1hYyBpcyAqYmFkKiBleGFtcGxlIG9mIHRoZSAodmlydHVhbCBjaGFubmVsDQo+IGJhc2VkKSBE TUEgZHJpdmVyLg0KPg0KPiBJIGd1ZXNzIHlvdSBtYXkganVzdCBmYWlsIHRoZSBkZXNjcmlwdG9y IGFuZCBkb24ndCBwcmV0ZW5kIGl0IGhhcw0KPiBiZWVuIHByb2Nlc3NlZCBzdWNjZXNzZnVsbHku DQpXaGF0IGRvIHlvdSBtZWFuIGJ5IHNheWluZyAiZmFpbCB0aGUgZGVzY3JpcHRvciI/DQpBZnRl ciBJIGdldCBlcnJvciBJIGNhbmNlbCBjdXJyZW50IHRyYW5zZmVyIGFuZCBmcmVlIGFsbCBkZXNj cmlwdG9ycw0KZnJvbSBpdCAoYnkgY2FsbGluZyB2Y2hhbl9jb29raWVfY29tcGxldGUpLg0KSSBj YW4ndCBzdG9yZSBlcnJvciBzdGF0dXMgaW4gZGVzY3JpcHRvciBzdHJ1Y3R1cmUgYmVjYXVzZSBp dCB3aWxsIGJlDQpmcmVlZCBieSB2Y2hhbl9jb29raWVfY29tcGxldGUuDQpJIGNhbid0IHN0b3Jl IGVycm9yIHN0YXR1cyBpbiBjaGFubmVsIHN0cnVjdHVyZSBiZWNhdXNlIGl0IHdpbGwgYmUNCm92 ZXJ3cml0dGVuIGJ5IG5leHQgdHJhbnNmZXIuDQoNCg0KPiA+ICtzdGF0aWMgaW50IGRtYV9jaGFu X3BhdXNlKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBheGlf ZG1hX2NoYW4gKmNoYW4gPSBkY2hhbl90b19heGlfZG1hX2NoYW4oZGNoYW4pOw0KPiA+ICsJdW5z aWduZWQgbG9uZyBmbGFnczsNCj4gPiArCXVuc2lnbmVkIGludCB0aW1lb3V0ID0gMjA7IC8qIHRp bWVvdXQgaXRlcmF0aW9ucyAqLw0KPiA+ICsJaW50IHJldCA9IC1FQUdBSU47DQo+ID4gKwl1MzIg dmFsOw0KPiA+ICsNCj4gPiArCXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFn cyk7DQo+ID4gKw0KPiA+ICsJdmFsID0gYXhpX2RtYV9pb3JlYWQzMihjaGFuLT5jaGlwLCBETUFD X0NIRU4pOw0KPiA+ICsJdmFsIHw9IEJJVChjaGFuLT5pZCkgPDwgRE1BQ19DSEFOX1NVU1BfU0hJ RlQgfA0KPiA+ICsJwqDCoMKgwqDCoMKgwqBCSVQoY2hhbi0+aWQpIDw8IERNQUNfQ0hBTl9TVVNQ X1dFX1NISUZUOw0KPiA+ICsJYXhpX2RtYV9pb3dyaXRlMzIoY2hhbi0+Y2hpcCwgRE1BQ19DSEVO LCB2YWwpOw0KPg0KPiBZb3UgaGF2ZSBoZWxwZXJzIHdoaWNoIHlvdSBkb24ndCB1c2UuIFdoeT8N Ck9rLCB3aWxsIHVzZS4NCg0KPiA+ICsNCj4gPiArCXdoaWxlICh0aW1lb3V0LS0pIHsNCj4NCj4g SW4gc3VjaCBjYXNlcyBJIHByZWZlciBkbyB7fSB3aGlsZSAoKTsgdG8gZXhwbGljaXRseSBzaG93 IHRoYXQgYm9keQ0KPiBnb2VzIGF0IGxlYXN0IG9uY2UuDQpHb29kIGlkZWEuIFdpbGwgY2hhbmdl IHRvIGRvIHt9IHdoaWxlICgpIGhlcmUuDQoNCj4gPiArCQlpZiAoYXhpX2NoYW5faXJxX3JlYWQo Y2hhbikgJg0KPiA+IERXQVhJRE1BQ19JUlFfU1VTUEVOREVEKSB7DQo+ID4gKwkJCXJldCA9IDA7 DQo+ID4gKwkJCWJyZWFrOw0KPiA+ICsJCX0NCj4gPiArCQl1ZGVsYXkoMik7DQo+ID4gKwl9DQo+ ID4gKw0KPiA+ICsJYXhpX2NoYW5faXJxX2NsZWFyKGNoYW4sIERXQVhJRE1BQ19JUlFfU1VTUEVO REVEKTsNCj4gPiArDQo+ID4gKwljaGFuLT5pc19wYXVzZWQgPSB0cnVlOw0KPiA+ICsNCj4gPiAr CXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsNCj4gPiArDQo+ ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICsvKiBDYWxsZWQgaW4gY2hhbiBs b2NrZWQgY29udGV4dCAqLw0KPiA+ICtzdGF0aWMgaW5saW5lIHZvaWQgYXhpX2NoYW5fcmVzdW1l KHN0cnVjdCBheGlfZG1hX2NoYW4gKmNoYW4pDQo+ID4gK3sNCj4gPiArCXUzMiB2YWw7DQo+ID4g Kw0KPiA+ICsJdmFsID0gYXhpX2RtYV9pb3JlYWQzMihjaGFuLT5jaGlwLCBETUFDX0NIRU4pOw0K PiA+ICsJdmFsICY9IH4oQklUKGNoYW4tPmlkKSA8PCBETUFDX0NIQU5fU1VTUF9TSElGVCk7DQo+ ID4gKwl2YWwgfD3CoMKgKEJJVChjaGFuLT5pZCkgPDwgRE1BQ19DSEFOX1NVU1BfV0VfU0hJRlQp Ow0KPiA+ICsJYXhpX2RtYV9pb3dyaXRlMzIoY2hhbi0+Y2hpcCwgRE1BQ19DSEVOLCB2YWwpOw0K PiA+ICsNCj4gPiArCWNoYW4tPmlzX3BhdXNlZCA9IGZhbHNlOw0KPiA+ICt9DQo+ID4gK3N0YXRp YyBpbnQgYXhpX2RtYV9ydW50aW1lX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQ0KPiA+ICt7 DQo+ID4gKwlzdHJ1Y3QgYXhpX2RtYV9jaGlwICpjaGlwID0gZGV2X2dldF9kcnZkYXRhKGRldik7 DQo+ID4gKw0KPiA+ICsJZGV2X2luZm8oZGV2LCAiUEFMOiAlc1xuIiwgX19mdW5jX18pOw0KPg0K PiBOb2lzeSBhbmQgdXNlbGVzcy4NCj4gV2UgaGF2ZSBmdW5jdGlvbmFsIHRyYWNlciBpbiBrZXJu ZWwuIFVzZSBpdC4NCk9rLg0KDQo+ID4gKw0KPiA+ICsJYXhpX2RtYV9pcnFfZGlzYWJsZShjaGlw KTsNCj4gPiArCWF4aV9kbWFfZGlzYWJsZShjaGlwKTsNCj4gPiArDQo+ID4gKwljbGtfZGlzYWJs ZV91bnByZXBhcmUoY2hpcC0+Y2xrKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0K DQpbc25pcF0NCg0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBkZXZfcG1fb3BzIGR3 X2F4aV9kbWFfcG1fb3BzID0gew0KPiA+ICsJU0VUX1JVTlRJTUVfUE1fT1BTKGF4aV9kbWFfcnVu dGltZV9zdXNwZW5kLA0KPiA+IGF4aV9kbWFfcnVudGltZV9yZXN1bWUsIE5VTEwpDQo+ID4gK307 DQo+DQo+IEhhdmUgeW91IHRyaWVkIHRvIGJ1aWxkIHdpdGggQ09ORklHX1BNIGRpc2FibGVkPw0K WWVzLg0KDQo+IEknbSBwcmV0dHkgc3VyZSB5b3UgbmVlZCBfX21heWJlX3VudXNlZCBhcHBsaWVk IHRvIHlvdXIgUE0gb3BzLg0KSSBjYWxsIGF4aV9kbWFfcnVudGltZV9zdXNwZW5kIC8gYXhpX2Rt YV9ydW50aW1lX3Jlc3VtZSBldmVuIEkgZG9udCd0DQp1c2UgUE0uDQooSSBjYWxsIHRoZW0gaW4g cHJvYmUgLyByZW1vdmUgZnVuY3Rpb24uKQ0KU28gSSBkb24ndCBuZWVkIHRvIGRlY2xhcmUgdGhl bSB3aXRoIF9fbWF5YmVfdW51c2VkLg0KDQo+ID4gK3N0cnVjdCBheGlfZG1hX2NoYW4gew0KPiA+ ICsJc3RydWN0IGF4aV9kbWFfY2hpcAkJKmNoaXA7DQo+ID4gKwl2b2lkIF9faW9tZW0JCQkqY2hh bl9yZWdzOw0KPiA+ICsJdTgJCQkJaWQ7DQo+ID4gKwlhdG9taWNfdAkJCWRlc2NzX2FsbG9jYXRl ZDsNCj4gPiArDQo+ID4gKwlzdHJ1Y3QgdmlydF9kbWFfY2hhbgkJdmM7DQo+ID4gKw0KPiA+ICsJ LyogdGhlc2Ugb3RoZXIgZWxlbWVudHMgYXJlIGFsbCBwcm90ZWN0ZWQgYnkgdmMubG9jayAqLw0K PiA+ICsJYm9vbAkJCQlpc19wYXVzZWQ7DQo+DQo+IEkgc3RpbGwgZGlkbid0IGdldCAoYWxyZWFk eSBmb3Jnb3QpIHdoeSB5b3UgY2FuJ3QgdXNlIGRtYV9zdGF0dXMNCj4gaW5zdGVhZCBmb3IgdGhl IGFjdGl2ZSBkZXNjcmlwdG9yPw0KQXMgSSBzYWlkIGJlZm9yZSwgSSBjaGVja2VkIHNldmVyYWwg ZHJpdmVyLCB3aGljaCBoYXZlIHN0YXR1cyB2YXJpYWJsZQ0KaW4gdGhlaXIgY2hhbm5lbCBzdHJ1 Y3R1cmUgLSBpdCBpcyB1c2VkICpvbmx5KiBmb3IgZGV0ZXJtaW5hdGluZyBpcw0KY2hhbm5lbCBw YXVzZWQgb3Igbm90LiBTbyB0aGVyZSBpcyBubyBtdWNoIHNlbnNlIGluIHJlcGxhY2luZw0KImlz X3BhdXNlZCIgdG8gInN0YXR1cyIgYW5kIEkgbGVmdCAiaXNfcGF1c2VkIiB2YXJpYWJsZSB1bnRv dWNoZWQuDQoNCihJIGRlc2NyaWJlZCBhYm92ZSB3aHkgd2UgY2FuJ3QgdXNlIHN0YXR1cyBpbiBj aGFubmVsIHN0cnVjdHVyZSBmb3INCmVycm9yIGhhbmRsaW5nKQ0KDQo+ID4gK307DQo+ID4gKy8q IExMSSA9PSBMaW5rZWQgTGlzdCBJdGVtICovDQo+ID4gK3N0cnVjdCBfX2F0dHJpYnV0ZV9fICgo X19wYWNrZWRfXykpIGF4aV9kbWFfbGxpIHsNCj4NCj4gLi4uDQo+DQo+ID4gKwlfX2xlNjQJCXNh cjsNCj4gPiArCV9fbGU2NAkJZGFyOw0KPiA+ICsJX19sZTMyCQlibG9ja190c19sbzsNCj4gPiAr CV9fbGUzMgkJYmxvY2tfdHNfaGk7DQo+ID4gKwlfX2xlNjQJCWxscDsNCj4gPiArCV9fbGUzMgkJ Y3RsX2xvOw0KPiA+ICsJX19sZTMyCQljdGxfaGk7DQo+ID4gKwlfX2xlMzIJCXNzdGF0Ow0KPiA+ ICsJX19sZTMyCQlkc3RhdDsNCj4gPiArCV9fbGUzMgkJc3RhdHVzX2xvOw0KPiA+ICsJX19sZTMy CQlzdHN0dXNfaGk7DQo+ID4gKwlfX2xlMzIJCXJlc2VydmVkX2xvOw0KPiA+ICsJX19sZTMyCQly ZXNlcnZlZF9oaTsNCj4gPiArfTsNCj4NCj4gSnVzdCBfX3BhY2tlZCBoZXJlLg0KPg0KT2suDQoN Cj4gPiArDQo+ID4gK3N0cnVjdCBheGlfZG1hX2Rlc2Mgew0KPiA+ICsJc3RydWN0IGF4aV9kbWFf bGxpCQlsbGk7DQo+ID4gKw0KPiA+ICsJc3RydWN0IHZpcnRfZG1hX2Rlc2MJCXZkOw0KPiA+ICsJ c3RydWN0IGF4aV9kbWFfY2hhbgkJKmNoYW47DQo+ID4gKwlzdHJ1Y3QgbGlzdF9oZWFkCQl4ZmVy X2xpc3Q7DQo+DQo+IFRoaXMgbG9va3MgcmVkdW5kYW50LiBBbHJlYWR5IGFza2VkIGFib3ZlIGFi b3V0IGl0Lg0KQW5zd2VyZWQgYWJvdmUuDQoNCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIENvbW1v biByZWdpc3RlcnMgb2Zmc2V0ICovDQo+ID4gKyNkZWZpbmUgRE1BQ19JRAkJCTB4MDAwIC8qIFIg RE1BQyBJRCAqLw0KPiA+ICsjZGVmaW5lIERNQUNfQ09NUFZFUgkJMHgwMDggLyogUiBETUFDIENv bXBvbmVudA0KPiA+IFZlcnNpb24NCj4gPiAqLw0KPiA+ICsjZGVmaW5lIERNQUNfQ0ZHCQkweDAx MCAvKiBSL1cgRE1BQyBDb25maWd1cmF0aW9uICovDQo+ID4gKyNkZWZpbmUgRE1BQ19DSEVOCQkw eDAxOCAvKiBSL1cgRE1BQyBDaGFubmVsIEVuYWJsZQ0KPiA+ICovDQo+ID4gKyNkZWZpbmUgRE1B Q19DSEVOX0wJCTB4MDE4IC8qIFIvVyBETUFDIENoYW5uZWwNCj4gPiBFbmFibGUNCj4gPiAwMC0z MSAqLw0KPiA+ICsjZGVmaW5lIERNQUNfQ0hFTl9ICQkweDAxQyAvKiBSL1cgRE1BQyBDaGFubmVs DQo+ID4gRW5hYmxlDQo+ID4gMzItNjMgKi8NCj4gPiArI2RlZmluZSBETUFDX0lOVFNUQVRVUwkJ MHgwMzAgLyogUiBETUFDIEludGVycnVwdA0KPiA+IFN0YXR1cyAqLw0KPiA+ICsjZGVmaW5lIERN QUNfQ09NTU9OX0lOVENMRUFSCTB4MDM4IC8qIFcgRE1BQyBJbnRlcnJ1cHQNCj4gPiBDbGVhcg0K PiA+ICovDQo+ID4gKyNkZWZpbmUgRE1BQ19DT01NT05fSU5UU1RBVFVTX0VOQSAweDA0MCAvKiBS IERNQUMgSW50ZXJydXB0IFN0YXR1cw0KPiA+IEVuYWJsZSAqLw0KPiA+ICsjZGVmaW5lIERNQUNf Q09NTU9OX0lOVFNJR05BTF9FTkEgMHgwNDggLyogUi9XIERNQUMgSW50ZXJydXB0DQo+ID4gU2ln bmFsDQo+ID4gRW5hYmxlICovDQo+ID4gKyNkZWZpbmUgRE1BQ19DT01NT05fSU5UU1RBVFVTCTB4 MDUwIC8qIFIgRE1BQyBJbnRlcnJ1cHQNCj4gPiBTdGF0dXMNCj4gPiAqLw0KPiA+ICsjZGVmaW5l IERNQUNfUkVTRVQJCTB4MDU4IC8qIFIgRE1BQyBSZXNldCBSZWdpc3RlcjENCj4gPiAqLw0KPiA+ ICsNCj4gPiArLyogRE1BIGNoYW5uZWwgcmVnaXN0ZXJzIG9mZnNldCAqLw0KPiA+ICsjZGVmaW5l IENIX1NBUgkJCTB4MDAwIC8qIFIvVyBDaGFuIFNvdXJjZQ0KPiA+IEFkZHJlc3MgKi8NCj4gPiAr I2RlZmluZSBDSF9EQVIJCQkweDAwOCAvKiBSL1cgQ2hhbg0KPiA+IERlc3RpbmF0aW9uDQo+ID4g QWRkcmVzcyAqLw0KPiA+ICsjZGVmaW5lIENIX0JMT0NLX1RTCQkweDAxMCAvKiBSL1cgQ2hhbiBC bG9jaw0KPiA+IFRyYW5zZmVyDQo+ID4gU2l6ZSAqLw0KPiA+ICsjZGVmaW5lIENIX0NUTAkJCTB4 MDE4IC8qIFIvVyBDaGFuIENvbnRyb2wgKi8NCj4gPiArI2RlZmluZSBDSF9DVExfTAkJMHgwMTgg LyogUi9XIENoYW4gQ29udHJvbCAwMC0zMSAqLw0KPiA+ICsjZGVmaW5lIENIX0NUTF9ICQkweDAx QyAvKiBSL1cgQ2hhbiBDb250cm9sIDMyLTYzICovDQo+ID4gKyNkZWZpbmUgQ0hfQ0ZHCQkJMHgw MjAgLyogUi9XIENoYW4NCj4gPiBDb25maWd1cmF0aW9uDQo+ID4gKi8NCj4gPiArI2RlZmluZSBD SF9DRkdfTAkJMHgwMjAgLyogUi9XIENoYW4gQ29uZmlndXJhdGlvbg0KPiA+IDAwLTMxDQo+ID4g Ki8NCj4gPiArI2RlZmluZSBDSF9DRkdfSAkJMHgwMjQgLyogUi9XIENoYW4gQ29uZmlndXJhdGlv bg0KPiA+IDMyLTYzDQo+ID4gKi8NCj4gPiArI2RlZmluZSBDSF9MTFAJCQkweDAyOCAvKiBSL1cg Q2hhbiBMaW5rZWQNCj4gPiBMaXN0DQo+ID4gUG9pbnRlciAqLw0KPiA+ICsjZGVmaW5lIENIX1NU QVRVUwkJMHgwMzAgLyogUiBDaGFuIFN0YXR1cyAqLw0KPiA+ICsjZGVmaW5lIENIX1NXSFNTUkMJ CTB4MDM4IC8qIFIvVyBDaGFuIFNXIEhhbmRzaGFrZQ0KPiA+IFNvdXJjZSAqLw0KPiA+ICsjZGVm aW5lIENIX1NXSFNEU1QJCTB4MDQwIC8qIFIvVyBDaGFuIFNXIEhhbmRzaGFrZQ0KPiA+IERlc3Rp bmF0aW9uICovDQo+ID4gKyNkZWZpbmUgQ0hfQkxLX1RGUl9SRVNVTUVSRVEJMHgwNDggLyogVyBD aGFuIEJsb2NrIFRyYW5zZmVyDQo+ID4gUmVzdW1lIFJlcSAqLw0KPiA+ICsjZGVmaW5lIENIX0FY SV9JRAkJMHgwNTAgLyogUi9XIENoYW4gQVhJIElEICovDQo+ID4gKyNkZWZpbmUgQ0hfQVhJX1FP UwkJMHgwNTggLyogUi9XIENoYW4gQVhJIFFPUyAqLw0KPiA+ICsjZGVmaW5lIENIX1NTVEFUCQkw eDA2MCAvKiBSIENoYW4gU291cmNlIFN0YXR1cyAqLw0KPiA+ICsjZGVmaW5lIENIX0RTVEFUCQkw eDA2OCAvKiBSIENoYW4gRGVzdGluYXRpb24gU3RhdHVzDQo+ID4gKi8NCj4gPiArI2RlZmluZSBD SF9TU1RBVEFSCQkweDA3MCAvKiBSL1cgQ2hhbiBTb3VyY2UgU3RhdHVzDQo+ID4gRmV0Y2ggQWRk ciAqLw0KPiA+ICsjZGVmaW5lIENIX0RTVEFUQVIJCTB4MDc4IC8qIFIvVyBDaGFuIERlc3RpbmF0 aW9uDQo+ID4gU3RhdHVzIEZldGNoIEFkZHIgKi8NCj4gPiArI2RlZmluZSBDSF9JTlRTVEFUVVNf RU5BCTB4MDgwIC8qIFIvVyBDaGFuIEludGVycnVwdCBTdGF0dXMNCj4gPiBFbmFibGUgKi8NCj4g PiArI2RlZmluZSBDSF9JTlRTVEFUVVMJCTB4MDg4IC8qIFIvVyBDaGFuIEludGVycnVwdA0KPiA+ IFN0YXR1cyAqLw0KPiA+ICsjZGVmaW5lIENIX0lOVFNJR05BTF9FTkEJMHgwOTAgLyogUi9XIENo YW4gSW50ZXJydXB0IFNpZ25hbA0KPiA+IEVuYWJsZSAqLw0KPiA+ICsjZGVmaW5lIENIX0lOVENM RUFSCQkweDA5OCAvKiBXIENoYW4gSW50ZXJydXB0IENsZWFyDQo+ID4gKi8NCj4NCj4gSSdtIHdv bmRlcmluZyBpZiB5b3UgY2FuIHVzZSByZWdtYXAgQVBJIGluc3RlYWQuDQpJcyBpdCByZWFsbHkg bmVjZXNzYXJ5PyBJdCdsbCBtYWtlIGRyaXZlciBtb3JlIGNvbXBsZXggZm9yIG5vdGhpbmcuDQo+ DQo+ID4gKy8qIERNQUNfQ0ZHICovDQo+ID4gKyNkZWZpbmUgRE1BQ19FTl9NQVNLCQkweDAwMDAw MDAxVQ0KPg0KPiBHRU5NQVNLKCkNCk9rLg0KDQo+ID4gKyNkZWZpbmUgRE1BQ19FTl9QT1MJCTAN Cj4NCj4gVXN1YWxseSBfU0hJRlQsIGJ1dCBpdCdzIHVwIHRvIHlvdS4NCj4NCj4gPiArZW51bSB7 DQo+ID4gKwlEV0FYSURNQUNfQlVSU1RfVFJBTlNfTEVOXzEJPSAweDAsDQo+ID4gKwlEV0FYSURN QUNfQlVSU1RfVFJBTlNfTEVOXzQsDQo+ID4gKwlEV0FYSURNQUNfQlVSU1RfVFJBTlNfTEVOXzgs DQo+ID4gKwlEV0FYSURNQUNfQlVSU1RfVFJBTlNfTEVOXzE2LA0KPiA+ICsJRFdBWElETUFDX0JV UlNUX1RSQU5TX0xFTl8zMiwNCj4gPiArCURXQVhJRE1BQ19CVVJTVF9UUkFOU19MRU5fNjQsDQo+ ID4gKwlEV0FYSURNQUNfQlVSU1RfVFJBTlNfTEVOXzEyOCwNCj4gPiArCURXQVhJRE1BQ19CVVJT VF9UUkFOU19MRU5fMjU2LA0KPiA+ICsJRFdBWElETUFDX0JVUlNUX1RSQU5TX0xFTl81MTIsDQo+ ID4gKwlEV0FYSURNQUNfQlVSU1RfVFJBTlNfTEVOXzEwMjQNCj4NCj4gLi4uXzEwMjQsID8NCldo YXQgZXhhY3RseSB5b3UgYXJlIGFza2luZyBhYm91dD8NCg0KPiA+ICt9Ow0KPg0KPiBIbW0uLi4g ZG8geW91IG5lZWQgdGhlbSBpbiB0aGUgaGVhZGVyPw0KSSB1c2Ugc29tZSBvZiB0aGVzZSBkZWZp bml0aW9ucyBpbiBteSBjb2RlIHNvIEkgZ3Vlc3MgeWVzLg0KLyogTWF5YmUgSSBtaXN1bmRlcnN0 b29kIHlvdXIgcXVlc3Rpb24uLi4gKi8NCg0KPiA+ICsjZGVmaW5lIENIX0NGR19IX1RUX0ZDX1BP UwkwDQo+ID4gK2VudW0gew0KPiA+ICsJRFdBWElETUFDX1RUX0ZDX01FTV9UT19NRU1fRE1BQwk9 IDB4MCwNCj4gPiArCURXQVhJRE1BQ19UVF9GQ19NRU1fVE9fUEVSX0RNQUMsDQo+ID4gKwlEV0FY SURNQUNfVFRfRkNfUEVSX1RPX01FTV9ETUFDLA0KPiA+ICsJRFdBWElETUFDX1RUX0ZDX1BFUl9U T19QRVJfRE1BQywNCj4gPiArCURXQVhJRE1BQ19UVF9GQ19QRVJfVE9fTUVNX1NSQywNCj4gPiAr CURXQVhJRE1BQ19UVF9GQ19QRVJfVE9fUEVSX1NSQywNCj4gPiArCURXQVhJRE1BQ19UVF9GQ19N RU1fVE9fUEVSX0RTVCwNCj4gPiArCURXQVhJRE1BQ19UVF9GQ19QRVJfVE9fUEVSX0RTVA0KPiA+ ICt9Ow0KPg0KPiBTb21lIG9mIGRlZmluaXRpb25zIGFyZSB0aGUgc2FtZSBhcyBmb3IgZHdfZG1h YywgcmlnaHQ/IFdlIG1pZ2h0DQo+IHNwbGl0IHRoZW0gdG8gYSBjb21tb24gaGVhZGVyLCB0aG91 Z2ggSSBoYXZlIG5vIHN0cm9uZyBvcGluaW9uIGFib3V0DQppdC4NCj4gVmlub2Q/DQpBUEIgRE1B QyBhbmQgQVhJIERNQUMgaGF2ZSBjb21wbGV0ZWx5IGRpZmZlcmVudCByZWdtYXAuIFNvIHRoZXJl IGlzIG5vDQptdWNoIHNlbnNlIHRvIGRvIHRoYXQuDQoNCi0tDQrCoEV1Z2VuaXkgUGFsdHNldg== -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1041053AbdDUO3q (ORCPT ); Fri, 21 Apr 2017 10:29:46 -0400 Received: from smtprelay2.synopsys.com ([198.182.60.111]:58667 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1041018AbdDUO3n (ORCPT ); Fri, 21 Apr 2017 10:29:43 -0400 From: Eugeniy Paltsev To: "andriy.shevchenko@linux.intel.com" CC: "vinod.koul@intel.com" , "linux-kernel@vger.kernel.org" , "robh+dt@kernel.org" , "Alexey.Brodkin@synopsys.com" , "devicetree@vger.kernel.org" , "Eugeniy.Paltsev@synopsys.com" , "linux-snps-arc@lists.infradead.org" , "dan.j.williams@intel.com" , "dmaengine@vger.kernel.org" Subject: Re: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver Thread-Topic: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver Thread-Index: AQHSr6fifaPEtWYJzkyOcLiQLbUIqKHK/piAgATX+YA= Date: Fri, 21 Apr 2017 14:29:38 +0000 Message-ID: <1492784977.16657.6.camel@synopsys.com> References: <1491573855-1039-1-git-send-email-Eugeniy.Paltsev@synopsys.com> <1491573855-1039-3-git-send-email-Eugeniy.Paltsev@synopsys.com> <1492518695.24567.56.camel@linux.intel.com> In-Reply-To: <1492518695.24567.56.camel@linux.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.121.8.113] Content-Type: text/plain; charset="utf-8" Content-ID: <025345809586DF49A1C2E405A43F3F95@internal.synopsys.com> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by mail.home.local id v3LETqAT015650 Hi Andy, thanks for respond. My comments are inlined below. On Tue, 2017-04-18 at 15:31 +0300, Andy Shevchenko wrote: > On Fri, 2017-04-07 at 17:04 +0300, Eugeniy Paltsev wrote: > > This patch adds support for the DW AXI DMAC controller. > > > > DW AXI DMAC is a part of upcoming development board from Synopsys. > > > > In this driver implementation only DMA_MEMCPY and DMA_SG transfers > > are supported. > > > > +++ b/drivers/dma/axi_dma_platform.c > > @@ -0,0 +1,1044 @@ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > Are you sure you still need of.h along with depends OF ? "of_match_ptr" used from of.h > > +#include > > +#include > > +#include > > +#include > > + > > +#include "axi_dma_platform.h" > > +#include "axi_dma_platform_reg.h" > > Can't you have this in one header? Sure. > > +#include "dmaengine.h" > > +#include "virt-dma.h" > > +#define AXI_DMA_BUSWIDTHS   \ > > + (DMA_SLAVE_BUSWIDTH_1_BYTE | \ > > + DMA_SLAVE_BUSWIDTH_2_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_4_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_8_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_16_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_32_BYTES | \ > > + DMA_SLAVE_BUSWIDTH_64_BYTES) > > +/* TODO: check: do we need to use BIT() macro here? */ > > Still TODO? I remember I answered to this on the first round. Yes, I remember it. I left this TODO as a reminder because src_addr_widths and dst_addr_widths are not used anywhere and they are set differently in different drivers (with or without BIT macro). > > + > > +static inline void > > +axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val) > > +{ > > + iowrite32(val, chip->regs + reg); > > Are you going to use IO ports for this IP? I don't think so. > Wouldn't be better to call readl()/writel() instead? As I understand, it's better to use ioread/iowrite as more universal IO access way. Am I wrong? > > +} > > +static inline void > > +axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val) > > +{ > > + iowrite32(val & 0xFFFFFFFF, chan->chan_regs + reg); > Useless conjunction. > > > + iowrite32(val >> 32, chan->chan_regs + reg + 4); > > +} > > Can your hardware get 8 bytes at once? > For such cases we have iowrite64() for 64-bit kernels > > But with readq()/writeq() we have specific helpers to make this > pretty, > i.e. lo_hi_readq() / lo_hi_writeq() (or hi_lo_*() variants). Ok, I possibly can use lo_hi_writeq here. > > +static inline void axi_chan_irq_disable(struct axi_dma_chan *chan, > > u32 irq_mask) > > +{ > > + u32 val; > > + > > + if (likely(irq_mask == DWAXIDMAC_IRQ_ALL)) { > > + axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, > > DWAXIDMAC_IRQ_NONE); > > + } else { > > I don't see the benefit. (Yes, I see one read-less path, I think it > makes perplexity for nothing here) This function is called mostly with irq_mask = DWAXIDMAC_IRQ_ALL. Actually it is called only with irq_mask = DWAXIDMAC_IRQ_ALL until I add DMA_SLAVE support. But I can cut off this 'if' statment, if it is necessery. > > + val = axi_chan_ioread32(chan, CH_INTSTATUS_ENA); > > + val &= ~irq_mask; > > + axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, val); > > + } > > +} > > +static inline void axi_chan_disable(struct axi_dma_chan *chan) > > +{ > > +} > > + > > +static inline void axi_chan_enable(struct axi_dma_chan *chan) > > +{ > > +} > > +static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, > > dma_addr_t src, > > +    dma_addr_t dst, size_t len) > > +{ > > + u32 max_width = chan->chip->dw->hdata->m_data_width; > > + size_t sdl = (src | dst | len); > > Redundant parens, redundant temporary variable (you may do this in > place). Ok. > > + > > + return min_t(size_t, __ffs(sdl), max_width); > > +} > > +static void axi_desc_put(struct axi_dma_desc *desc) > > +{ > > + struct axi_dma_chan *chan = desc->chan; > > + struct dw_axi_dma *dw = chan->chip->dw; > > + struct axi_dma_desc *child, *_next; > > + unsigned int descs_put = 0; > > + list_for_each_entry_safe(child, _next, &desc->xfer_list, > > xfer_list) { > > xfer_list looks redundant. > Can you elaborate why virtual channel management is not working for > you? Each virtual descriptor encapsulates several hardware descriptors, which belong to same transfer. This list (xfer_list) is used only for allocating/freeing these descriptors and it doesn't affect on virtual dma work logic. I can see this approach in several drivers with VirtDMA (but they mostly use array instead of list) > > + list_del(&child->xfer_list); > > + dma_pool_free(dw->desc_pool, child, child- > > > vd.tx.phys); > > > > + descs_put++; > > + } > > +} > > +/* Called in chan locked context */ > > +static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, > > +       struct axi_dma_desc *first) > > +{ > > + u32 reg, irq_mask; > > + u8 lms = 0; > > Does it make any sense? It looks like lms is always 0. > Or I miss the source of its value? lms variable uset to determine axi bus for reading lli descriptors. It is equal to 0 for mem-to-mem transfers. Perhaps it is better to use define instead of this variable. > > + u32 priority = chan->chip->dw->hdata->priority[chan->id]; > > Reversed xmas tree, please. > > Btw, are you planning to use priority at all? For now on I didn't see > a single driver (from the set I have checked, like 4-5 of them) that > uses priority anyhow. It makes driver more complex for nothing. Only for dma slave operations. > > > + > > + if (unlikely(axi_chan_is_hw_enable(chan))) { > > + dev_err(chan2dev(chan), "%s is non-idle!\n", > > + axi_chan_name(chan)); > > + > > + return; > > + } > > +} > > +static void dma_chan_free_chan_resources(struct dma_chan *dchan) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + > > + /* ASSERT: channel hw is idle */ > > + if (axi_chan_is_hw_enable(chan)) > > + dev_err(dchan2dev(dchan), "%s is non-idle!\n", > > + axi_chan_name(chan)); > > + > > + axi_chan_disable(chan); > > + axi_chan_irq_disable(chan, DWAXIDMAC_IRQ_ALL); > > + > > + vchan_free_chan_resources(&chan->vc); > > + > > + dev_vdbg(dchan2dev(dchan), "%s: %s: descriptor still > > allocated: %u\n", > > + __func__, axi_chan_name(chan), > > Redundant __func__ parameter for debug prints. > > > + atomic_read(&chan->descs_allocated)); > > + > > + pm_runtime_put(chan->chip->dev); > > +} > > +static struct dma_async_tx_descriptor * > > +dma_chan_prep_dma_sg(struct dma_chan *dchan, > > +      struct scatterlist *dst_sg, unsigned int > > dst_nents, > > +      struct scatterlist *src_sg, unsigned int > > src_nents, > > +      unsigned long flags) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + struct axi_dma_desc *first = NULL, *desc = NULL, *prev = > > NULL; > > + size_t dst_len = 0, src_len = 0, xfer_len = 0; > > + dma_addr_t dst_adr = 0, src_adr = 0; > > + u32 src_width, dst_width; > > + size_t block_ts, max_block_ts; > > + u32 reg; > > + u8 lms = 0; > > Same about lms. > > > + > > + dev_dbg(chan2dev(chan), "%s: %s: sn: %d dn: %d flags: > > 0x%lx", > > + __func__, axi_chan_name(chan), src_nents, > > dst_nents, > > flags); > > Ditto for __func__. > > > + > > > > + if (unlikely(dst_nents == 0 || src_nents == 0)) > > + return NULL; > > + > > + if (unlikely(dst_sg == NULL || src_sg == NULL)) > > + return NULL; > > If we need those checks they should go to dmaengine.h/dmaengine.c. I checked several drivers, which implements device_prep_dma_sg and they implements this checkers. Should I add something like "dma_sg_desc_invalid" function to dmaengine.h ? > > +static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, > > +    struct axi_dma_desc *desc_head) > > +{ > > + struct axi_dma_desc *desc; > > + > > + axi_chan_dump_lli(chan, desc_head); > > + list_for_each_entry(desc, &desc_head->xfer_list, > > xfer_list) > > + axi_chan_dump_lli(chan, desc); > > +} > > + > > +static void axi_chan_handle_err(struct axi_dma_chan *chan, u32 > > status) > > +{ > > + /* WARN about bad descriptor */ > > > > + dev_err(chan2dev(chan), > > + "Bad descriptor submitted for %s, cookie: %d, irq: > > 0x%08x\n", > > + axi_chan_name(chan), vd->tx.cookie, status); > > + axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd)); > > As I said earlier dw_dmac is *bad* example of the (virtual channel > based) DMA driver. > > I guess you may just fail the descriptor and don't pretend it has > been processed successfully. What do you mean by saying "fail the descriptor"? After I get error I cancel current transfer and free all descriptors from it (by calling vchan_cookie_complete). I can't store error status in descriptor structure because it will be freed by vchan_cookie_complete. I can't store error status in channel structure because it will be overwritten by next transfer. > > +static int dma_chan_pause(struct dma_chan *dchan) > > +{ > > + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); > > + unsigned long flags; > > + unsigned int timeout = 20; /* timeout iterations */ > > + int ret = -EAGAIN; > > + u32 val; > > + > > + spin_lock_irqsave(&chan->vc.lock, flags); > > + > > + val = axi_dma_ioread32(chan->chip, DMAC_CHEN); > > + val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT | > > +        BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT; > > + axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); > > You have helpers which you don't use. Why? Ok, will use. > > + > > + while (timeout--) { > > In such cases I prefer do {} while (); to explicitly show that body > goes at least once. Good idea. Will change to do {} while () here. > > + if (axi_chan_irq_read(chan) & > > DWAXIDMAC_IRQ_SUSPENDED) { > > + ret = 0; > > + break; > > + } > > + udelay(2); > > + } > > + > > + axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED); > > + > > + chan->is_paused = true; > > + > > + spin_unlock_irqrestore(&chan->vc.lock, flags); > > + > > + return ret; > > +} > > + > > +/* Called in chan locked context */ > > +static inline void axi_chan_resume(struct axi_dma_chan *chan) > > +{ > > + u32 val; > > + > > + val = axi_dma_ioread32(chan->chip, DMAC_CHEN); > > + val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT); > > + val |=  (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT); > > + axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); > > + > > + chan->is_paused = false; > > +} > > +static int axi_dma_runtime_suspend(struct device *dev) > > +{ > > + struct axi_dma_chip *chip = dev_get_drvdata(dev); > > + > > + dev_info(dev, "PAL: %s\n", __func__); > > Noisy and useless. > We have functional tracer in kernel. Use it. Ok. > > + > > + axi_dma_irq_disable(chip); > > + axi_dma_disable(chip); > > + > > + clk_disable_unprepare(chip->clk); > > + > > + return 0; > > +} [snip] > > + > > +static const struct dev_pm_ops dw_axi_dma_pm_ops = { > > + SET_RUNTIME_PM_OPS(axi_dma_runtime_suspend, > > axi_dma_runtime_resume, NULL) > > +}; > > Have you tried to build with CONFIG_PM disabled? Yes. > I'm pretty sure you need __maybe_unused applied to your PM ops. I call axi_dma_runtime_suspend / axi_dma_runtime_resume even I dont't use PM. (I call them in probe / remove function.) So I don't need to declare them with __maybe_unused. > > +struct axi_dma_chan { > > + struct axi_dma_chip *chip; > > + void __iomem *chan_regs; > > + u8 id; > > + atomic_t descs_allocated; > > + > > + struct virt_dma_chan vc; > > + > > + /* these other elements are all protected by vc.lock */ > > + bool is_paused; > > I still didn't get (already forgot) why you can't use dma_status > instead for the active descriptor? As I said before, I checked several driver, which have status variable in their channel structure - it is used *only* for determinating is channel paused or not. So there is no much sense in replacing "is_paused" to "status" and I left "is_paused" variable untouched. (I described above why we can't use status in channel structure for error handling) > > +}; > > +/* LLI == Linked List Item */ > > +struct __attribute__ ((__packed__)) axi_dma_lli { > > ... > > > + __le64 sar; > > + __le64 dar; > > + __le32 block_ts_lo; > > + __le32 block_ts_hi; > > + __le64 llp; > > + __le32 ctl_lo; > > + __le32 ctl_hi; > > + __le32 sstat; > > + __le32 dstat; > > + __le32 status_lo; > > + __le32 ststus_hi; > > + __le32 reserved_lo; > > + __le32 reserved_hi; > > +}; > > Just __packed here. > Ok. > > + > > +struct axi_dma_desc { > > + struct axi_dma_lli lli; > > + > > + struct virt_dma_desc vd; > > + struct axi_dma_chan *chan; > > + struct list_head xfer_list; > > This looks redundant. Already asked above about it. Answered above. > > +}; > > + > > +/* Common registers offset */ > > +#define DMAC_ID 0x000 /* R DMAC ID */ > > +#define DMAC_COMPVER 0x008 /* R DMAC Component > > Version > > */ > > +#define DMAC_CFG 0x010 /* R/W DMAC Configuration */ > > +#define DMAC_CHEN 0x018 /* R/W DMAC Channel Enable > > */ > > +#define DMAC_CHEN_L 0x018 /* R/W DMAC Channel > > Enable > > 00-31 */ > > +#define DMAC_CHEN_H 0x01C /* R/W DMAC Channel > > Enable > > 32-63 */ > > +#define DMAC_INTSTATUS 0x030 /* R DMAC Interrupt > > Status */ > > +#define DMAC_COMMON_INTCLEAR 0x038 /* W DMAC Interrupt > > Clear > > */ > > +#define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status > > Enable */ > > +#define DMAC_COMMON_INTSIGNAL_ENA 0x048 /* R/W DMAC Interrupt > > Signal > > Enable */ > > +#define DMAC_COMMON_INTSTATUS 0x050 /* R DMAC Interrupt > > Status > > */ > > +#define DMAC_RESET 0x058 /* R DMAC Reset Register1 > > */ > > + > > +/* DMA channel registers offset */ > > +#define CH_SAR 0x000 /* R/W Chan Source > > Address */ > > +#define CH_DAR 0x008 /* R/W Chan > > Destination > > Address */ > > +#define CH_BLOCK_TS 0x010 /* R/W Chan Block > > Transfer > > Size */ > > +#define CH_CTL 0x018 /* R/W Chan Control */ > > +#define CH_CTL_L 0x018 /* R/W Chan Control 00-31 */ > > +#define CH_CTL_H 0x01C /* R/W Chan Control 32-63 */ > > +#define CH_CFG 0x020 /* R/W Chan > > Configuration > > */ > > +#define CH_CFG_L 0x020 /* R/W Chan Configuration > > 00-31 > > */ > > +#define CH_CFG_H 0x024 /* R/W Chan Configuration > > 32-63 > > */ > > +#define CH_LLP 0x028 /* R/W Chan Linked > > List > > Pointer */ > > +#define CH_STATUS 0x030 /* R Chan Status */ > > +#define CH_SWHSSRC 0x038 /* R/W Chan SW Handshake > > Source */ > > +#define CH_SWHSDST 0x040 /* R/W Chan SW Handshake > > Destination */ > > +#define CH_BLK_TFR_RESUMEREQ 0x048 /* W Chan Block Transfer > > Resume Req */ > > +#define CH_AXI_ID 0x050 /* R/W Chan AXI ID */ > > +#define CH_AXI_QOS 0x058 /* R/W Chan AXI QOS */ > > +#define CH_SSTAT 0x060 /* R Chan Source Status */ > > +#define CH_DSTAT 0x068 /* R Chan Destination Status > > */ > > +#define CH_SSTATAR 0x070 /* R/W Chan Source Status > > Fetch Addr */ > > +#define CH_DSTATAR 0x078 /* R/W Chan Destination > > Status Fetch Addr */ > > +#define CH_INTSTATUS_ENA 0x080 /* R/W Chan Interrupt Status > > Enable */ > > +#define CH_INTSTATUS 0x088 /* R/W Chan Interrupt > > Status */ > > +#define CH_INTSIGNAL_ENA 0x090 /* R/W Chan Interrupt Signal > > Enable */ > > +#define CH_INTCLEAR 0x098 /* W Chan Interrupt Clear > > */ > > I'm wondering if you can use regmap API instead. Is it really necessary? It'll make driver more complex for nothing. > > > +/* DMAC_CFG */ > > +#define DMAC_EN_MASK 0x00000001U > > GENMASK() Ok. > > +#define DMAC_EN_POS 0 > > Usually _SHIFT, but it's up to you. > > > +enum { > > + DWAXIDMAC_BURST_TRANS_LEN_1 = 0x0, > > + DWAXIDMAC_BURST_TRANS_LEN_4, > > + DWAXIDMAC_BURST_TRANS_LEN_8, > > + DWAXIDMAC_BURST_TRANS_LEN_16, > > + DWAXIDMAC_BURST_TRANS_LEN_32, > > + DWAXIDMAC_BURST_TRANS_LEN_64, > > + DWAXIDMAC_BURST_TRANS_LEN_128, > > + DWAXIDMAC_BURST_TRANS_LEN_256, > > + DWAXIDMAC_BURST_TRANS_LEN_512, > > + DWAXIDMAC_BURST_TRANS_LEN_1024 > > ..._1024, ? What exactly you are asking about? > > +}; > > Hmm... do you need them in the header? I use some of these definitions in my code so I guess yes. /* Maybe I misunderstood your question... */ > > +#define CH_CFG_H_TT_FC_POS 0 > > +enum { > > + DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0x0, > > + DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_PER_DMAC, > > + DWAXIDMAC_TT_FC_PER_TO_MEM_SRC, > > + DWAXIDMAC_TT_FC_PER_TO_PER_SRC, > > + DWAXIDMAC_TT_FC_MEM_TO_PER_DST, > > + DWAXIDMAC_TT_FC_PER_TO_PER_DST > > +}; > > Some of definitions are the same as for dw_dmac, right? We might > split them to a common header, though I have no strong opinion about it. > Vinod? APB DMAC and AXI DMAC have completely different regmap. So there is no much sense to do that. --  Eugeniy Paltsev