diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-01-25 05:18:34 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-01-31 01:27:21 -0500 |
commit | 86eb5fb61125e4646c9447a1f2ce130817dab34e (patch) | |
tree | 98722f05c9a3eaab60608f665755b331306325f4 /drivers/dma | |
parent | 7ad74a7cf6f6355fd3f4c15afe63460fc4ec3f57 (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>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ste_dma40.c | 34 |
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 | ||
921 | static int d40_pause(struct dma_chan *chan) | 921 | static 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 | ||
948 | static int d40_resume(struct dma_chan *chan) | 946 | static 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 | ||
977 | static 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 | |||
981 | static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) | 993 | static 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, | |||
2176 | static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 2188 | static 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); |