Skip to content

Commit 6fd2901

Browse files
Phil Elwellpopcornmix
Phil Elwell
authored andcommitted
bcm2708-dmaengine: Use more DMA channels (but not 12)
1) Only the bcm2708_fb drivers uses the legacy DMA API, and it requires a BULK-capable channel, so all other types (FAST, NORMAL and LITE) can be made available to the regular DMA API. 2) DMA channels 11-14 share an interrupt. The driver can't handle this, so don't use channels 12-14 (12 was used, probably because it appears to have an interrupt, but in reality that interrupt is for activity on ANY channel). This may explain a lockup encountered when running out of DMA channels. The combined effect of this patch is to leave 7 DMA channels available + channel 0 for bcm2708_fb via the legacy API. See: #1110 #1108
1 parent ca899b2 commit 6fd2901

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

arch/arm/boot/dts/bcm2708_common.dtsi

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,10 @@
5959
<1 24>,
6060
<1 25>,
6161
<1 26>,
62-
<1 27>,
63-
<1 28>;
62+
<1 27>;
6463

6564
#dma-cells = <1>;
66-
brcm,dma-channel-mask = <0x7f35>;
65+
brcm,dma-channel-mask = <0x0f35>;
6766
};
6867

6968
intc: interrupt-controller {

drivers/dma/bcm2708-dmaengine.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base,
184184
}
185185

186186
static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,
187-
unsigned preferred_feature_set)
187+
unsigned required_feature_set)
188188
{
189189
u32 chans;
190190
int chan = 0;
@@ -193,10 +193,8 @@ static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,
193193
chans = dmaman->chan_available;
194194
for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++)
195195
/* select the subset of available channels with the desired
196-
feature so long as some of the candidate channels have that
197-
feature */
198-
if ((preferred_feature_set & (1 << feature)) &&
199-
(chans & dmaman->has_feature[feature]))
196+
features */
197+
if (required_feature_set & (1 << feature))
200198
chans &= dmaman->has_feature[feature];
201199

202200
if (!chans)
@@ -228,7 +226,7 @@ static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan)
228226

229227
/* DMA Manager Monitor */
230228

231-
extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
229+
extern int bcm_dma_chan_alloc(unsigned required_feature_set,
232230
void __iomem **out_dma_base, int *out_dma_irq)
233231
{
234232
struct vc_dmaman *dmaman = g_dmaman;
@@ -240,7 +238,7 @@ extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
240238
return -ENODEV;
241239

242240
mutex_lock(&dmaman->lock);
243-
chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set);
241+
chan = vc_dmaman_chan_alloc(dmaman, required_feature_set);
244242
if (chan < 0)
245243
goto out;
246244

@@ -442,6 +440,7 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc(
442440
return container_of(t, struct bcm2835_desc, vd.tx);
443441
}
444442

443+
#if 0
445444
static void dma_dumpregs(struct bcm2835_chan *c)
446445
{
447446
pr_debug("-------------DMA DUMPREGS-------------\n");
@@ -457,6 +456,7 @@ static void dma_dumpregs(struct bcm2835_chan *c)
457456
readl(c->chan_base + BCM2835_DMA_NEXTCB));
458457
pr_debug("--------------------------------------\n");
459458
}
459+
#endif
460460

461461
static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
462462
{
@@ -862,6 +862,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
862862
uint32_t len = sg_dma_len(sgent);
863863

864864
for (j = 0; j < len; j += max_size) {
865+
u32 waits;
865866
struct bcm2835_dma_cb *control_block =
866867
&d->control_block_base[i+splitct];
867868

@@ -879,7 +880,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
879880
}
880881

881882
/* Common part */
882-
u32 waits = SDHCI_BCM_DMA_WAITS;
883+
waits = SDHCI_BCM_DMA_WAITS;
883884
if ((dma_debug >> 0) & 0x1f)
884885
waits = (dma_debug >> 0) & 0x1f;
885886
control_block->info |= BCM2835_DMA_WAITS(waits);
@@ -1074,6 +1075,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
10741075
int rc;
10751076
int i;
10761077
int irq;
1078+
#ifdef CONFIG_DMA_BCM2708_LEGACY
1079+
static const u32 wanted_features[] = {
1080+
BCM_DMA_FEATURE_FAST,
1081+
BCM_DMA_FEATURE_NORMAL,
1082+
BCM_DMA_FEATURE_LITE
1083+
};
1084+
int j;
1085+
#endif
10771086

10781087

10791088
if (!pdev->dev.dma_mask)
@@ -1120,20 +1129,24 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
11201129

11211130
platform_set_drvdata(pdev, od);
11221131

1123-
for (i = 0; i < 5; i++) {
1132+
for (i = 0, j = 0; j < ARRAY_SIZE(wanted_features);) {
1133+
11241134
void __iomem *chan_base;
11251135
int chan_id;
11261136

1127-
chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_LITE,
1128-
&chan_base,
1129-
&irq);
1137+
chan_id = bcm_dma_chan_alloc(wanted_features[j],
1138+
&chan_base,
1139+
&irq);
11301140

1131-
if (chan_id < 0)
1132-
break;
1141+
if (chan_id < 0) {
1142+
j++;
1143+
continue;
1144+
}
11331145

11341146
rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq);
11351147
if (rc)
11361148
goto err_no_dma;
1149+
i++;
11371150
}
11381151

11391152
if (pdev->dev.of_node) {
@@ -1146,6 +1159,8 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
11461159
}
11471160
}
11481161

1162+
dev_info(&pdev->dev, "Initialized %i DMA channels (+ 1 legacy)\n", i);
1163+
11491164
#else
11501165
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
11511166
if (rc)

0 commit comments

Comments
 (0)