Skip to content

Commit e8ee6c8

Browse files
fancervinodkoul
authored andcommitted
dmaengine: dw: Add DMA-channels mask cell support
DW DMA IP-core provides a way to synthesize the DMA controller with channels having different parameters like maximum burst-length, multi-block support, maximum data width, etc. Those parameters both explicitly and implicitly affect the channels performance. Since DMA slave devices might be very demanding to the DMA performance, let's provide a functionality for the slaves to be assigned with DW DMA channels, which performance according to the platform engineer fulfill their requirements. After this patch is applied it can be done by passing the mask of suitable DMA-channels either directly in the dw_dma_slave structure instance or as a fifth cell of the DMA DT-property. If mask is zero or not provided, then there is no limitation on the channels allocation. For instance Baikal-T1 SoC is equipped with a DW DMAC engine, which first two channels are synthesized with max burst length of 16, while the rest of the channels have been created with max-burst-len=4. It would seem that the first two channels must be faster than the others and should be more preferable for the time-critical DMA slave devices. In practice it turned out that the situation is quite the opposite. The channels with max-burst-len=4 demonstrated a better performance than the channels with max-burst-len=16 even when they both had been initialized with the same settings. The performance drop of the first two DMA-channels made them unsuitable for the DW APB SSI slave device. No matter what settings they are configured with, full-duplex SPI transfers occasionally experience the Rx FIFO overflow. It means that the DMA-engine doesn't keep up with incoming data pace even though the SPI-bus is enabled with speed of 25MHz while the DW DMA controller is clocked with 50MHz signal. There is no such problem has been noticed for the channels synthesized with max-burst-len=4. Signed-off-by: Serge Semin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 8d2f59d commit e8ee6c8

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

drivers/dma/dw/core.c

+4
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,10 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
772772
if (dws->dma_dev != chan->device->dev)
773773
return false;
774774

775+
/* permit channels in accordance with the channels mask */
776+
if (dws->channels && !(dws->channels & dwc->mask))
777+
return false;
778+
775779
/* We have to copy data since dws can be temporary storage */
776780
memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave));
777781

drivers/dma/dw/of.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,21 @@ static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
2222
};
2323
dma_cap_mask_t cap;
2424

25-
if (dma_spec->args_count != 3)
25+
if (dma_spec->args_count < 3 || dma_spec->args_count > 4)
2626
return NULL;
2727

2828
slave.src_id = dma_spec->args[0];
2929
slave.dst_id = dma_spec->args[0];
3030
slave.m_master = dma_spec->args[1];
3131
slave.p_master = dma_spec->args[2];
32+
if (dma_spec->args_count >= 4)
33+
slave.channels = dma_spec->args[3];
3234

3335
if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
3436
slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
3537
slave.m_master >= dw->pdata->nr_masters ||
36-
slave.p_master >= dw->pdata->nr_masters))
38+
slave.p_master >= dw->pdata->nr_masters ||
39+
slave.channels >= BIT(dw->pdata->nr_channels)))
3740
return NULL;
3841

3942
dma_cap_zero(cap);

include/linux/platform_data/dma-dw.h

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct device;
2626
* @dst_id: dst request line
2727
* @m_master: memory master for transfers on allocated channel
2828
* @p_master: peripheral master for transfers on allocated channel
29+
* @channels: mask of the channels permitted for allocation (zero value means any)
2930
* @hs_polarity:set active low polarity of handshake interface
3031
*/
3132
struct dw_dma_slave {
@@ -34,6 +35,7 @@ struct dw_dma_slave {
3435
u8 dst_id;
3536
u8 m_master;
3637
u8 p_master;
38+
u8 channels;
3739
bool hs_polarity;
3840
};
3941

0 commit comments

Comments
 (0)