lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 17 Sep 2012 10:39:36 +0300 From: Andy Shevchenko <andriy.shevchenko@...ux.intel.com> To: Viresh Kumar <viresh.linux@...il.com>, Vinod Koul <vinod.koul@...el.com>, spear-devel@...t.st.com, linux-kernel@...r.kernel.org, Hein Tibosch <hein_tibosch@...oo.es> Cc: Andy Shevchenko <andriy.shevchenko@...ux.intel.com> Subject: [PATCH 6/7] dw_dmac: check if controller supports LLP Some controllers have the reduced functionality where the LLP multi block transfers are not supported. This patch introduces a check and refuses to deal with such devices. Signed-off-by: Andy Shevchenko <andriy.shevchenko@...ux.intel.com> --- drivers/dma/dw_dmac.c | 35 ++++++++++++++++++++++++++++++++++- drivers/dma/dw_dmac_regs.h | 4 ++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index fdb7d5a..00958ad 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -647,6 +647,12 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, unsigned int dst_width; u32 ctllo; + if (dwc->nollp) { + dev_dbg(chan2dev(&dwc->chan), + "channel doesn't support LLP transfers\n"); + return NULL; + } + dev_vdbg(chan2dev(chan), "%s: d0x%llx s0x%llx l0x%zx f0x%lx\n", __func__, (unsigned long long)dest, (unsigned long long)src, @@ -741,6 +747,12 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (unlikely(!dws || !sg_len)) return NULL; + if (dwc->nollp) { + dev_dbg(chan2dev(&dwc->chan), + "channel doesn't support LLP transfers\n"); + return NULL; + } + prev = first = NULL; switch (direction) { @@ -1202,6 +1214,13 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); + if (dwc->nollp) { + spin_unlock_irqrestore(&dwc->lock, flags); + dev_dbg(chan2dev(&dwc->chan), + "channel doesn't support LLP transfers\n"); + return ERR_PTR(-EINVAL); + } + if (!list_empty(&dwc->queue) || !list_empty(&dwc->active_list)) { spin_unlock_irqrestore(&dwc->lock, flags); dev_dbg(chan2dev(&dwc->chan), @@ -1469,6 +1488,7 @@ static int __devinit dw_probe(struct platform_device *pdev) INIT_LIST_HEAD(&dw->dma.channels); for (i = 0; i < nr_channels; i++) { struct dw_dma_chan *dwc = &dw->chan[i]; + int r = nr_channels - i - 1; dwc->chan.device = &dw->dma; dma_cookie_init(&dwc->chan); @@ -1480,7 +1500,7 @@ static int __devinit dw_probe(struct platform_device *pdev) /* 7 is highest priority & 0 is lowest. */ if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) - dwc->priority = nr_channels - i - 1; + dwc->priority = r; else dwc->priority = i; @@ -1498,10 +1518,23 @@ static int __devinit dw_probe(struct platform_device *pdev) /* hardware configuration */ if (autocfg) { + unsigned int dwc_params; + + dwc_params = dma_raw_readl(regs + r * sizeof(u32), + DWC_PARAMS); + dwc->block_size = (4 << ((max_blk_size >> 4 * i) & 0xf)) - 1; + dwc->nollp = + (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0; } else { dwc->block_size = pdata->block_size; + + /* Check if channel supports multi block transfer */ + channel_writel(dwc, LLP, 0xfffffffc); + dwc->nollp = + (channel_readl(dwc, LLP) & 0xfffffffc) == 0; + channel_writel(dwc, LLP, 0); } } diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index 9beaef0..b66a716 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -114,6 +114,9 @@ struct dw_dma_regs { #define DW_PARAMS_DATA_WIDTH4 21 /* master 4 data width */ #define DW_PARAMS_EN 28 /* encoded parameters */ +/* Bitfields in DWC_PARAMS */ +#define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */ + /* Bitfields in CTL_LO */ #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ @@ -194,6 +197,7 @@ struct dw_dma_chan { /* hardware configuration */ unsigned short block_size; + bool nollp; /* configuration passed via DMA_SLAVE_CONFIG */ struct dma_slave_config dma_sconfig; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists