From 5302bcc299e0a64b2c62b45454a5d0ed5cf56e41 Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Wed, 30 Nov 2011 19:20:42 +0530 Subject: [PATCH] --- yaml --- r: 286127 b: refs/heads/master c: 5cd326fd27da347925019fcc041b79bad8dd55ed h: refs/heads/master i: 286125: 781a78602a1bcfa145d43bfc4730a5c7fd2c1527 286123: b277faf0f40c1652cddd6fb16d763d252dd8a542 286119: 562c78a05f86d95abdb26f81add458f921092d1e 286111: 7bd206c4c2253d27e7e13f33e9fc2d0f125587ff v: v3 --- [refs] | 2 +- .../arm/plat-nomadik/include/plat/ste_dma40.h | 6 ++- trunk/drivers/dma/ste_dma40.c | 51 +++++++++++++++---- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index 5393a9a2395e..a35b44dbd531 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8f0d30f9ee333f4fb3458a9a33f7ead5269ea8f3 +refs/heads/master: 5cd326fd27da347925019fcc041b79bad8dd55ed diff --git a/trunk/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/trunk/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 3177bed253df..fd0ee84c45d1 100644 --- a/trunk/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/trunk/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -113,7 +113,8 @@ struct stedma40_half_channel_info { * @dst_dev_type: Dst device type * @src_info: Parameters for dst half channel * @dst_info: Parameters for dst half channel - * + * @use_fixed_channel: if true, use physical channel specified by phy_channel + * @phy_channel: physical channel to use, only if use_fixed_channel is true * * This structure has to be filled by the client drivers. * It is recommended to do all dma configurations for clients in the machine. @@ -129,6 +130,9 @@ struct stedma40_chan_cfg { int dst_dev_type; struct stedma40_half_channel_info src_info; struct stedma40_half_channel_info dst_info; + + bool use_fixed_channel; + int phy_channel; }; /** diff --git a/trunk/drivers/dma/ste_dma40.c b/trunk/drivers/dma/ste_dma40.c index aff128a39a4b..972dc35770f9 100644 --- a/trunk/drivers/dma/ste_dma40.c +++ b/trunk/drivers/dma/ste_dma40.c @@ -1545,11 +1545,16 @@ static int d40_validate_conf(struct d40_chan *d40c, return res; } -static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src, - int log_event_line, bool is_log) +static bool d40_alloc_mask_set(struct d40_phy_res *phy, + bool is_src, int log_event_line, bool is_log, + bool *first_user) { unsigned long flags; spin_lock_irqsave(&phy->lock, flags); + + *first_user = ((phy->allocated_src | phy->allocated_dst) + == D40_ALLOC_FREE); + if (!is_log) { /* Physical interrupts are masked per physical full channel */ if (phy->allocated_src == D40_ALLOC_FREE && @@ -1630,7 +1635,7 @@ static bool d40_alloc_mask_free(struct d40_phy_res *phy, bool is_src, return is_free; } -static int d40_allocate_channel(struct d40_chan *d40c) +static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) { int dev_type; int event_group; @@ -1666,7 +1671,8 @@ static int d40_allocate_channel(struct d40_chan *d40c) for (i = 0; i < d40c->base->num_phy_chans; i++) { if (d40_alloc_mask_set(&phys[i], is_src, - 0, is_log)) + 0, is_log, + first_phy_user)) goto found_phy; } } else @@ -1676,7 +1682,8 @@ static int d40_allocate_channel(struct d40_chan *d40c) if (d40_alloc_mask_set(&phys[i], is_src, 0, - is_log)) + is_log, + first_phy_user)) goto found_phy; } } @@ -1692,6 +1699,25 @@ static int d40_allocate_channel(struct d40_chan *d40c) /* Find logical channel */ for (j = 0; j < d40c->base->num_phy_chans; j += 8) { int phy_num = j + event_group * 2; + + if (d40c->dma_cfg.use_fixed_channel) { + i = d40c->dma_cfg.phy_channel; + + if ((i != phy_num) && (i != phy_num + 1)) { + dev_err(chan2dev(d40c), + "invalid fixed phy channel %d\n", i); + return -EINVAL; + } + + if (d40_alloc_mask_set(&phys[i], is_src, event_line, + is_log, first_phy_user)) + goto found_log; + + dev_err(chan2dev(d40c), + "could not allocate fixed phy channel %d\n", i); + return -EINVAL; + } + /* * Spread logical channels across all available physical rather * than pack every logical channel at the first available phy @@ -1700,13 +1726,15 @@ static int d40_allocate_channel(struct d40_chan *d40c) if (is_src) { for (i = phy_num; i < phy_num + 2; i++) { if (d40_alloc_mask_set(&phys[i], is_src, - event_line, is_log)) + event_line, is_log, + first_phy_user)) goto found_log; } } else { for (i = phy_num + 1; i >= phy_num; i--) { if (d40_alloc_mask_set(&phys[i], is_src, - event_line, is_log)) + event_line, is_log, + first_phy_user)) goto found_log; } } @@ -2160,9 +2188,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) goto fail; } } - is_free_phy = (d40c->phy_chan == NULL); - err = d40_allocate_channel(d40c); + err = d40_allocate_channel(d40c, &is_free_phy); if (err) { chan_err(d40c, "Failed to allocate channel\n"); d40c->configured = false; @@ -2189,6 +2216,12 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; } + dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", + chan_is_logical(d40c) ? "logical" : "physical", + d40c->phy_chan->num, + d40c->dma_cfg.use_fixed_channel ? ", fixed" : ""); + + /* * Only write channel configuration to the DMA if the physical * resource is free. In case of multiple logical channels