forked from Minki/linux
tty: serial: 8250_dma: keep own book keeping about RX transfers
After dmaengine_terminate_all() has been invoked then both DMA drivers (edma and omap-dma) do not invoke dma_cookie_complete() to mark the transfer as complete. This dma_cookie_complete() is performed by the Synopsys DesignWare driver which is probably the only one that is used by omap8250-dma and hence don't see following problem… …which is that once a RX transfer has been terminated then following query of channel status reports DMA_IN_PROGRESS (again: the actual transfer has been canceled, there is nothing going on anymore). This means that serial8250_rx_dma() never enqueues another DMA transfer because it (wrongly) assumes that there is a transer already pending. Vinod Koul refuses to accept a patch which adds this dma_cookie_complete() to both drivers and so dmaengine_tx_status() would report DMA_COMPLETE instead (and behave like the Synopsys DesignWare driver already does). He argues that I am not allowed to use the cookie to query the status and that the driver already cleaned everything up after the invokation of dmaengine_terminate_all(). To end this I add a bookkeeping whether or not a RX-transfer has been started to the 8250-dma code. It has already been done for the TX side. *Now* we learn about the RX status based on our bookkeeping and don't need dmaengine_tx_status() for this anymore. Cc: vinod.koul@intel.com Reviewed-by: Tony Lindgren <tony@atomide.com> Tested-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Reviewed-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b220282156
commit
0fcb7901f9
@ -42,6 +42,7 @@ struct uart_8250_dma {
|
||||
|
||||
unsigned char tx_running:1;
|
||||
unsigned char tx_err: 1;
|
||||
unsigned char rx_running:1;
|
||||
};
|
||||
|
||||
struct old_serial_port {
|
||||
|
@ -61,6 +61,7 @@ static void __dma_rx_complete(void *param)
|
||||
dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
|
||||
dma->rx_running = 0;
|
||||
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
dmaengine_terminate_all(dma->rxchan);
|
||||
|
||||
@ -123,10 +124,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
||||
{
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_tx_state state;
|
||||
int dma_status;
|
||||
|
||||
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
|
||||
|
||||
switch (iir & 0x3f) {
|
||||
case UART_IIR_RLSI:
|
||||
@ -137,7 +134,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
||||
* If RCVR FIFO trigger level was not reached, complete the
|
||||
* transfer and let 8250_core copy the remaining data.
|
||||
*/
|
||||
if (dma_status == DMA_IN_PROGRESS) {
|
||||
if (dma->rx_running) {
|
||||
dmaengine_pause(dma->rxchan);
|
||||
__dma_rx_complete(p);
|
||||
}
|
||||
@ -146,7 +143,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dma_status)
|
||||
if (dma->rx_running)
|
||||
return 0;
|
||||
|
||||
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
|
||||
@ -155,6 +152,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
|
||||
if (!desc)
|
||||
return -EBUSY;
|
||||
|
||||
dma->rx_running = 1;
|
||||
desc->callback = __dma_rx_complete;
|
||||
desc->callback_param = p;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user