diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 20:11:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 20:11:49 -0700 |
commit | e6dce825fba05f447bd22c865e27233182ab3d79 (patch) | |
tree | 266c22686f5b376f2e1d560baaf596e7fd5b9c98 /drivers/dma | |
parent | Merge tag 'driver-core-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core (diff) | |
parent | Revert "serial: pl011: add console matching function" (diff) | |
download | linux-dev-e6dce825fba05f447bd22c865e27233182ab3d79.tar.xz linux-dev-e6dce825fba05f447bd22c865e27233182ab3d79.zip |
Merge tag 'tty-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty and serial updates from Greg KH:
"Here is the big tty and serial patch set for 4.9-rc1.
It also includes some drivers/dma/ changes, as those were needed by
some serial drivers, and they were all acked by the DMA maintainer.
Also in here is the long-suffering ACPI SPCR patchset, which was
passed around from maintainer to maintainer like a hot-potato. Seems I
was the sucker^Wlucky one. All of those patches have been acked by the
various subsystem maintainers as well.
All of this has been in linux-next with no reported issues"
* tag 'tty-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (111 commits)
Revert "serial: pl011: add console matching function"
MAINTAINERS: update entry for atmel_serial driver
serial: pl011: add console matching function
ARM64: ACPI: enable ACPI_SPCR_TABLE
ACPI: parse SPCR and enable matching console
of/serial: move earlycon early_param handling to serial
Revert "drivers/tty: Explicitly pass current to show_stack"
tty: amba-pl011: Don't complain on -EPROBE_DEFER when no irq
nios2: dts: 10m50: Add tx-threshold parameter
serial: 8250: Set Altera 16550 TX FIFO Threshold
serial: 8250: of: Load TX FIFO Threshold from DT
Documentation: dt: serial: Add TX FIFO threshold parameter
drivers/tty: Explicitly pass current to show_stack
serial: imx: Fix DCD reading
serial: stm32: mark symbols static where possible
serial: xuartps: Add some register initialisation to cdns_early_console_setup()
serial: xuartps: Removed unwanted checks while reading the error conditions
serial: xuartps: Rewrite the interrupt handling logic
serial: stm32: use mapbase instead of membase for DMA
tty/serial: atmel: fix fractional baud rate computation
...
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/dw/core.c | 39 | ||||
-rw-r--r-- | drivers/dma/dw/regs.h | 5 | ||||
-rw-r--r-- | drivers/dma/hsu/hsu.c | 9 | ||||
-rw-r--r-- | drivers/dma/hsu/pci.c | 6 | ||||
-rw-r--r-- | drivers/dma/imx-sdma.c | 56 |
5 files changed, 57 insertions, 58 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index edf053f73a49..da18b18561c4 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -46,9 +46,9 @@ u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ DW_DMA_MSIZE_16; \ u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \ - _dwc->p_master : _dwc->m_master; \ + _dwc->dws.p_master : _dwc->dws.m_master; \ u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \ - _dwc->p_master : _dwc->m_master; \ + _dwc->dws.p_master : _dwc->dws.m_master; \ \ (DWC_CTLL_DST_MSIZE(_dmsize) \ | DWC_CTLL_SRC_MSIZE(_smsize) \ @@ -143,12 +143,16 @@ static void dwc_initialize(struct dw_dma_chan *dwc) struct dw_dma *dw = to_dw_dma(dwc->chan.device); u32 cfghi = DWC_CFGH_FIFO_MODE; u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); + bool hs_polarity = dwc->dws.hs_polarity; if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) return; - cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); - cfghi |= DWC_CFGH_SRC_PER(dwc->src_id); + cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id); + cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id); + + /* Set polarity of handshake interface */ + cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0; channel_writel(dwc, CFG_LO, cfglo); channel_writel(dwc, CFG_HI, cfghi); @@ -209,7 +213,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) { struct dw_dma *dw = to_dw_dma(dwc->chan.device); - u8 lms = DWC_LLP_LMS(dwc->m_master); + u8 lms = DWC_LLP_LMS(dwc->dws.m_master); unsigned long was_soft_llp; /* ASSERT: channel is idle */ @@ -662,7 +666,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, struct dw_desc *prev; size_t xfer_count; size_t offset; - u8 m_master = dwc->m_master; + u8 m_master = dwc->dws.m_master; unsigned int src_width; unsigned int dst_width; unsigned int data_width = dw->pdata->data_width[m_master]; @@ -740,7 +744,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct dw_desc *prev; struct dw_desc *first; u32 ctllo; - u8 m_master = dwc->m_master; + u8 m_master = dwc->dws.m_master; u8 lms = DWC_LLP_LMS(m_master); dma_addr_t reg; unsigned int reg_width; @@ -895,12 +899,7 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) return false; /* We have to copy data since dws can be temporary storage */ - - dwc->src_id = dws->src_id; - dwc->dst_id = dws->dst_id; - - dwc->m_master = dws->m_master; - dwc->p_master = dws->p_master; + memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave)); return true; } @@ -1167,11 +1166,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) spin_lock_irqsave(&dwc->lock, flags); /* Clear custom channel configuration */ - dwc->src_id = 0; - dwc->dst_id = 0; - - dwc->m_master = 0; - dwc->p_master = 0; + memset(&dwc->dws, 0, sizeof(struct dw_dma_slave)); clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags); @@ -1264,7 +1259,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, struct dw_cyclic_desc *retval = NULL; struct dw_desc *desc; struct dw_desc *last = NULL; - u8 lms = DWC_LLP_LMS(dwc->m_master); + u8 lms = DWC_LLP_LMS(dwc->dws.m_master); unsigned long was_cyclic; unsigned int reg_width; unsigned int periods; @@ -1576,11 +1571,7 @@ int dw_dma_probe(struct dw_dma_chip *chip) (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, DWC_LLP_LOC(0xffffffff)); - dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0; - channel_writel(dwc, LLP, 0); + dwc->nollp = pdata->is_nollp; } } diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 4b7bd7834046..f65dd104479f 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -245,10 +245,7 @@ struct dw_dma_chan { bool nollp; /* custom slave configuration */ - u8 src_id; - u8 dst_id; - u8 m_master; - u8 p_master; + struct dw_dma_slave dws; /* configuration passed via .device_config */ struct dma_slave_config dma_sconfig; diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index c5f21efd6090..29d04ca71d52 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -200,10 +200,9 @@ EXPORT_SYMBOL_GPL(hsu_dma_get_status); * is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0. * * Return: - * IRQ_NONE for invalid channel number, IRQ_HANDLED otherwise. + * 0 for invalid channel number, 1 otherwise. */ -irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, - u32 status) +int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) { struct hsu_dma_chan *hsuc; struct hsu_dma_desc *desc; @@ -211,7 +210,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, /* Sanity check */ if (nr >= chip->hsu->nr_channels) - return IRQ_NONE; + return 0; hsuc = &chip->hsu->chan[nr]; @@ -230,7 +229,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, } spin_unlock_irqrestore(&hsuc->vchan.lock, flags); - return IRQ_HANDLED; + return 1; } EXPORT_SYMBOL_GPL(hsu_dma_do_irq); diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c index 9916058531d9..b51639f045ed 100644 --- a/drivers/dma/hsu/pci.c +++ b/drivers/dma/hsu/pci.c @@ -29,7 +29,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) u32 dmaisr; u32 status; unsigned short i; - irqreturn_t ret = IRQ_NONE; + int ret = 0; int err; dmaisr = readl(chip->regs + HSU_PCI_DMAISR); @@ -37,14 +37,14 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) if (dmaisr & 0x1) { err = hsu_dma_get_status(chip, i, &status); if (err > 0) - ret |= IRQ_HANDLED; + ret |= 1; else if (err == 0) ret |= hsu_dma_do_irq(chip, i, status); } dmaisr >>= 1; } - return ret; + return IRQ_RETVAL(ret); } static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 03ec76fc22ff..3cb47386fbb9 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -648,15 +648,11 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event) writel_relaxed(val, sdma->regs + chnenbl); } -static void sdma_handle_channel_loop(struct sdma_channel *sdmac) -{ - if (sdmac->desc.callback) - sdmac->desc.callback(sdmac->desc.callback_param); -} - static void sdma_update_channel_loop(struct sdma_channel *sdmac) { struct sdma_buffer_descriptor *bd; + int error = 0; + enum dma_status old_status = sdmac->status; /* * loop mode. Iterate over descriptors, re-setup them and @@ -668,17 +664,42 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) if (bd->mode.status & BD_DONE) break; - if (bd->mode.status & BD_RROR) + if (bd->mode.status & BD_RROR) { + bd->mode.status &= ~BD_RROR; sdmac->status = DMA_ERROR; + error = -EIO; + } + + /* + * We use bd->mode.count to calculate the residue, since contains + * the number of bytes present in the current buffer descriptor. + */ + sdmac->chn_real_count = bd->mode.count; bd->mode.status |= BD_DONE; + bd->mode.count = sdmac->period_len; + + /* + * The callback is called from the interrupt context in order + * to reduce latency and to avoid the risk of altering the + * SDMA transaction status by the time the client tasklet is + * executed. + */ + + if (sdmac->desc.callback) + sdmac->desc.callback(sdmac->desc.callback_param); + sdmac->buf_tail++; sdmac->buf_tail %= sdmac->num_bd; + + if (error) + sdmac->status = old_status; } } -static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) +static void mxc_sdma_handle_channel_normal(unsigned long data) { + struct sdma_channel *sdmac = (struct sdma_channel *) data; struct sdma_buffer_descriptor *bd; int i, error = 0; @@ -705,16 +726,6 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) sdmac->desc.callback(sdmac->desc.callback_param); } -static void sdma_tasklet(unsigned long data) -{ - struct sdma_channel *sdmac = (struct sdma_channel *) data; - - if (sdmac->flags & IMX_DMA_SG_LOOP) - sdma_handle_channel_loop(sdmac); - else - mxc_sdma_handle_channel_normal(sdmac); -} - static irqreturn_t sdma_int_handler(int irq, void *dev_id) { struct sdma_engine *sdma = dev_id; @@ -731,8 +742,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) if (sdmac->flags & IMX_DMA_SG_LOOP) sdma_update_channel_loop(sdmac); - - tasklet_schedule(&sdmac->tasklet); + else + tasklet_schedule(&sdmac->tasklet); __clear_bit(channel, &stat); } @@ -1353,7 +1364,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, u32 residue; if (sdmac->flags & IMX_DMA_SG_LOOP) - residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len; + residue = (sdmac->num_bd - sdmac->buf_tail) * + sdmac->period_len - sdmac->chn_real_count; else residue = sdmac->chn_count - sdmac->chn_real_count; @@ -1732,7 +1744,7 @@ static int sdma_probe(struct platform_device *pdev) dma_cookie_init(&sdmac->chan); sdmac->channel = i; - tasklet_init(&sdmac->tasklet, sdma_tasklet, + tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal, (unsigned long) sdmac); /* * Add the channel to the DMAC list. Do not add channel 0 though |