diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2010-06-20 17:26:38 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2010-06-22 21:01:56 -0400 |
commit | d181b3a8cb2fc1732ad1826a5e6fdccab03e6a51 (patch) | |
tree | 421df4b6411a9b3acea2467237ad3b0e2fc20b4c /drivers/dma/ste_dma40.c | |
parent | 8bc68fa51d7ed520cd4c69f74fb37add60b6ea47 (diff) |
DMAENGINE: ste_dma40: fix suspend bug
This fixes a bug when suspending channels: first make the checks,
then suspend the channel, not the other way around.
Signed-off-by: Jonas Aaberg <jonas.aberg@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/ste_dma40.c')
-rw-r--r-- | drivers/dma/ste_dma40.c | 33 |
1 files changed, 13 insertions, 20 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 5748e96f00de..e14c39526255 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -1220,7 +1220,7 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1220 | { | 1220 | { |
1221 | 1221 | ||
1222 | int res = 0; | 1222 | int res = 0; |
1223 | u32 event, dir; | 1223 | u32 event; |
1224 | struct d40_phy_res *phy = d40c->phy_chan; | 1224 | struct d40_phy_res *phy = d40c->phy_chan; |
1225 | bool is_src; | 1225 | bool is_src; |
1226 | struct d40_desc *d; | 1226 | struct d40_desc *d; |
@@ -1252,21 +1252,12 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1252 | return -EINVAL; | 1252 | return -EINVAL; |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | ||
1256 | if (res) { | ||
1257 | dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n", | ||
1258 | __func__); | ||
1259 | return res; | ||
1260 | } | ||
1261 | |||
1262 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 1255 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
1263 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 1256 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { |
1264 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | 1257 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); |
1265 | dir = D40_CHAN_REG_SDLNK; | ||
1266 | is_src = false; | 1258 | is_src = false; |
1267 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 1259 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { |
1268 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); | 1260 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); |
1269 | dir = D40_CHAN_REG_SSLNK; | ||
1270 | is_src = true; | 1261 | is_src = true; |
1271 | } else { | 1262 | } else { |
1272 | dev_err(&d40c->chan.dev->device, | 1263 | dev_err(&d40c->chan.dev->device, |
@@ -1274,16 +1265,17 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1274 | return -EINVAL; | 1265 | return -EINVAL; |
1275 | } | 1266 | } |
1276 | 1267 | ||
1268 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | ||
1269 | if (res) { | ||
1270 | dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n", | ||
1271 | __func__); | ||
1272 | return res; | ||
1273 | } | ||
1274 | |||
1277 | if (d40c->log_num != D40_PHY_CHAN) { | 1275 | if (d40c->log_num != D40_PHY_CHAN) { |
1278 | /* | 1276 | /* Release logical channel, deactivate the event line */ |
1279 | * Release logical channel, deactivate the event line during | ||
1280 | * the time physical res is suspended. | ||
1281 | */ | ||
1282 | writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event)) & | ||
1283 | D40_EVENTLINE_MASK(event), | ||
1284 | d40c->base->virtbase + D40_DREG_PCBASE + | ||
1285 | phy->num * D40_DREG_PCDELTA + dir); | ||
1286 | 1277 | ||
1278 | d40_config_set_event(d40c, false); | ||
1287 | d40c->base->lookup_log_chans[d40c->log_num] = NULL; | 1279 | d40c->base->lookup_log_chans[d40c->log_num] = NULL; |
1288 | 1280 | ||
1289 | /* | 1281 | /* |
@@ -1304,8 +1296,9 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1304 | } | 1296 | } |
1305 | return 0; | 1297 | return 0; |
1306 | } | 1298 | } |
1307 | } else | 1299 | } else { |
1308 | d40_alloc_mask_free(phy, is_src, 0); | 1300 | (void) d40_alloc_mask_free(phy, is_src, 0); |
1301 | } | ||
1309 | 1302 | ||
1310 | /* Release physical channel */ | 1303 | /* Release physical channel */ |
1311 | res = d40_channel_execute_command(d40c, D40_DMA_STOP); | 1304 | res = d40_channel_execute_command(d40c, D40_DMA_STOP); |