aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-01-25 05:18:34 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-31 01:27:21 -0500
commit86eb5fb61125e4646c9447a1f2ce130817dab34e (patch)
tree98722f05c9a3eaab60608f665755b331306325f4
parent7ad74a7cf6f6355fd3f4c15afe63460fc4ec3f57 (diff)
dma40: stop ongoing transfers in DMA_TERMINATE_ALL
The current implementation of DMA_TERMINATE_ALL leaves ongoing transfers running. Fix it. Acked-by: Per Forlin <per.forlin@stericsson.com> Acked-by: Jonas Aaberg <jonas.aberg@stericsson.com> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/dma/ste_dma40.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 929fd8f45a2d..8fd0bb94e777 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -918,10 +918,8 @@ static bool d40_tx_is_linked(struct d40_chan *d40c)
918 return is_link; 918 return is_link;
919} 919}
920 920
921static int d40_pause(struct dma_chan *chan) 921static int d40_pause(struct d40_chan *d40c)
922{ 922{
923 struct d40_chan *d40c =
924 container_of(chan, struct d40_chan, chan);
925 int res = 0; 923 int res = 0;
926 unsigned long flags; 924 unsigned long flags;
927 925
@@ -945,10 +943,8 @@ static int d40_pause(struct dma_chan *chan)
945 return res; 943 return res;
946} 944}
947 945
948static int d40_resume(struct dma_chan *chan) 946static int d40_resume(struct d40_chan *d40c)
949{ 947{
950 struct d40_chan *d40c =
951 container_of(chan, struct d40_chan, chan);
952 int res = 0; 948 int res = 0;
953 unsigned long flags; 949 unsigned long flags;
954 950
@@ -978,6 +974,22 @@ no_suspend:
978 return res; 974 return res;
979} 975}
980 976
977static int d40_terminate_all(struct d40_chan *chan)
978{
979 unsigned long flags;
980 int ret = 0;
981
982 ret = d40_pause(chan);
983 if (!ret && chan_is_physical(chan))
984 ret = d40_channel_execute_command(chan, D40_DMA_STOP);
985
986 spin_lock_irqsave(&chan->lock, flags);
987 d40_term_all(chan);
988 spin_unlock_irqrestore(&chan->lock, flags);
989
990 return ret;
991}
992
981static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) 993static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
982{ 994{
983 struct d40_chan *d40c = container_of(tx->chan, 995 struct d40_chan *d40c = container_of(tx->chan,
@@ -2176,7 +2188,6 @@ static void d40_set_runtime_config(struct dma_chan *chan,
2176static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 2188static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
2177 unsigned long arg) 2189 unsigned long arg)
2178{ 2190{
2179 unsigned long flags;
2180 struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); 2191 struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
2181 2192
2182 if (d40c->phy_chan == NULL) { 2193 if (d40c->phy_chan == NULL) {
@@ -2186,14 +2197,11 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
2186 2197
2187 switch (cmd) { 2198 switch (cmd) {
2188 case DMA_TERMINATE_ALL: 2199 case DMA_TERMINATE_ALL:
2189 spin_lock_irqsave(&d40c->lock, flags); 2200 return d40_terminate_all(d40c);
2190 d40_term_all(d40c);
2191 spin_unlock_irqrestore(&d40c->lock, flags);
2192 return 0;
2193 case DMA_PAUSE: 2201 case DMA_PAUSE:
2194 return d40_pause(chan); 2202 return d40_pause(d40c);
2195 case DMA_RESUME: 2203 case DMA_RESUME:
2196 return d40_resume(chan); 2204 return d40_resume(d40c);
2197 case DMA_SLAVE_CONFIG: 2205 case DMA_SLAVE_CONFIG:
2198 d40_set_runtime_config(chan, 2206 d40_set_runtime_config(chan,
2199 (struct dma_slave_config *) arg); 2207 (struct dma_slave_config *) arg);