aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40.c
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2010-06-20 17:26:38 -0400
committerDan Williams <dan.j.williams@intel.com>2010-06-22 21:01:56 -0400
commitd181b3a8cb2fc1732ad1826a5e6fdccab03e6a51 (patch)
tree421df4b6411a9b3acea2467237ad3b0e2fc20b4c /drivers/dma/ste_dma40.c
parent8bc68fa51d7ed520cd4c69f74fb37add60b6ea47 (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.c33
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);