serial: pl011: Don't enable RX DMA if residue processing not supported
authorAndrew Jackson <Andrew.Jackson@arm.com>
Fri, 31 Oct 2014 08:10:29 +0000 (08:10 +0000)
committerLiviu Dudau <Liviu.Dudau@arm.com>
Fri, 31 Oct 2014 12:22:16 +0000 (12:22 +0000)
If the DMA engine doesn't support residue processing then the RX DMA
handling won't work terribly well if polling is enabled.  So, disable
RX DMA if residue handling isn't available.

Signed-off-by: Andrew Jackson <Andrew.Jackson@arm.com>
drivers/tty/serial/amba-pl011.c

index 9c738c83fb8a6b767bf6cc5e7daa691c4ce8e6fd..9a94b3d0ddf61aeea811a5b601a8aa3e2efd7ae3 100644 (file)
@@ -304,7 +304,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
 
        /* Optionally make use of an RX channel as well */
        chan = dma_request_slave_channel(dev, "rx");
-       
+
        if (!chan && plat->dma_rx_param) {
                chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
 
@@ -322,7 +322,22 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
                        .src_maxburst = uap->fifosize >> 2,
                        .device_fc = false,
                };
+               struct dma_slave_caps caps;
 
+               /*
+                * Some DMA controllers provide information on their capabilities.
+                * If the controller does, check for suitable residue processing
+                * otherwise assime all is well.
+                */
+               if (0 == dma_get_slave_caps(chan, &caps)) {
+                       if (caps.residue_granularity ==
+                                       DMA_RESIDUE_GRANULARITY_DESCRIPTOR) {
+                               dma_release_channel(chan);
+                               dev_info(uap->port.dev,
+                                       "RX DMA disabled - no residue processing\n");
+                               return;
+                       }
+               }
                dmaengine_slave_config(chan, &rx_conf);
                uap->dmarx.chan = chan;