1 From 535bf1097beb4279ac4895a61199078672ffc63a Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Mon, 7 Mar 2016 16:46:39 +0000
4 Subject: [PATCH] bcm2835-sdhost: Only claim one DMA channel
6 With both MMC controllers enabled there are few DMA channels left. The
7 bcm2835-sdhost driver only uses DMA in one direction at a time, so it
8 doesn't need to claim two channels.
10 See: https://github.com/raspberrypi/linux/issues/1327
12 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
14 arch/arm/boot/dts/bcm2708_common.dtsi | 5 +--
15 drivers/mmc/host/bcm2835-sdhost.c | 70 ++++++++++++++++++++++++-----------
16 2 files changed, 50 insertions(+), 25 deletions(-)
18 --- a/arch/arm/boot/dts/bcm2708_common.dtsi
19 +++ b/arch/arm/boot/dts/bcm2708_common.dtsi
21 reg = <0x7e202000 0x100>;
26 - dma-names = "tx", "rx";
28 + dma-names = "rx-tx";
29 brcm,overclock-50 = <0>;
32 --- a/drivers/mmc/host/bcm2835-sdhost.c
33 +++ b/drivers/mmc/host/bcm2835-sdhost.c
34 @@ -185,9 +185,10 @@ struct bcm2835_host {
35 unsigned int debug:1; /* Enable debug output */
38 - struct dma_chan *dma_chan_rx; /* DMA channel for reads */
39 - struct dma_chan *dma_chan_tx; /* DMA channel for writes */
40 - struct dma_chan *dma_chan; /* Channel in used */
41 + struct dma_chan *dma_chan_rxtx; /* DMA channel for reads and writes */
42 + struct dma_chan *dma_chan; /* Channel in use */
43 + struct dma_slave_config dma_cfg_rx;
44 + struct dma_slave_config dma_cfg_tx;
45 struct dma_async_tx_descriptor *dma_desc;
48 @@ -771,12 +772,11 @@ static void bcm2835_sdhost_prepare_dma(s
49 log_event("PRD<", (u32)data, 0);
50 pr_debug("bcm2835_sdhost_prepare_dma()\n");
52 + dma_chan = host->dma_chan_rxtx;
53 if (data->flags & MMC_DATA_READ) {
54 - dma_chan = host->dma_chan_rx;
55 dir_data = DMA_FROM_DEVICE;
56 dir_slave = DMA_DEV_TO_MEM;
58 - dma_chan = host->dma_chan_tx;
59 dir_data = DMA_TO_DEVICE;
60 dir_slave = DMA_MEM_TO_DEV;
62 @@ -813,6 +813,12 @@ static void bcm2835_sdhost_prepare_dma(s
63 host->drain_words = len/4;
66 + /* The parameters have already been validated, so this will not fail */
67 + (void)dmaengine_slave_config(dma_chan,
68 + (dir_data == DMA_FROM_DEVICE) ?
72 len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len,
75 @@ -1805,28 +1811,46 @@ int bcm2835_sdhost_add_host(struct bcm28
76 spin_lock_init(&host->lock);
78 if (host->allow_dma) {
79 - if (IS_ERR_OR_NULL(host->dma_chan_tx) ||
80 - IS_ERR_OR_NULL(host->dma_chan_rx)) {
81 - pr_err("%s: unable to initialise DMA channels. "
82 + if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) {
83 + pr_err("%s: unable to initialise DMA channel. "
84 "Falling back to PIO\n",
86 host->use_dma = false;
88 - host->use_dma = true;
90 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
91 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
92 cfg.slave_id = 13; /* DREQ channel */
94 + /* Validate the slave configurations */
96 cfg.direction = DMA_MEM_TO_DEV;
98 cfg.dst_addr = host->bus_addr + SDDATA;
99 - ret = dmaengine_slave_config(host->dma_chan_tx, &cfg);
101 - cfg.direction = DMA_DEV_TO_MEM;
102 - cfg.src_addr = host->bus_addr + SDDATA;
104 - ret = dmaengine_slave_config(host->dma_chan_rx, &cfg);
105 + ret = dmaengine_slave_config(host->dma_chan_rxtx, &cfg);
108 + host->dma_cfg_tx = cfg;
110 + cfg.direction = DMA_DEV_TO_MEM;
111 + cfg.src_addr = host->bus_addr + SDDATA;
114 + ret = dmaengine_slave_config(host->dma_chan_rxtx, &cfg);
118 + host->dma_cfg_rx = cfg;
120 + host->use_dma = true;
122 + pr_err("%s: unable to configure DMA channel. "
123 + "Falling back to PIO\n",
124 + mmc_hostname(mmc));
125 + dma_release_channel(host->dma_chan_rxtx);
126 + host->dma_chan_rxtx = NULL;
127 + host->use_dma = false;
131 host->use_dma = false;
132 @@ -1948,19 +1972,21 @@ static int bcm2835_sdhost_probe(struct p
134 if (host->allow_dma) {
136 - host->dma_chan_tx =
137 - dma_request_slave_channel(dev, "tx");
138 - host->dma_chan_rx =
139 - dma_request_slave_channel(dev, "rx");
140 + host->dma_chan_rxtx =
141 + dma_request_slave_channel(dev, "rx-tx");
142 + if (!host->dma_chan_rxtx)
143 + host->dma_chan_rxtx =
144 + dma_request_slave_channel(dev, "tx");
145 + if (!host->dma_chan_rxtx)
146 + host->dma_chan_rxtx =
147 + dma_request_slave_channel(dev, "rx");
152 /* we don't care about the channel, any would work */
153 dma_cap_set(DMA_SLAVE, mask);
154 - host->dma_chan_tx =
155 - dma_request_channel(mask, NULL, NULL);
156 - host->dma_chan_rx =
157 + host->dma_chan_rxtx =
158 dma_request_channel(mask, NULL, NULL);