diff options
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index ed3ef22e68a4..c2b0172a7589 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -189,7 +189,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) | |||
189 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, | 189 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, |
190 | struct sh_dmae_device, common); | 190 | struct sh_dmae_device, common); |
191 | struct sh_dmae_pdata *pdata = shdev->pdata; | 191 | struct sh_dmae_pdata *pdata = shdev->pdata; |
192 | struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; | 192 | const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; |
193 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); | 193 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); |
194 | int shift = chan_pdata->dmars_bit; | 194 | int shift = chan_pdata->dmars_bit; |
195 | 195 | ||
@@ -265,7 +265,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) | |||
265 | return NULL; | 265 | return NULL; |
266 | } | 266 | } |
267 | 267 | ||
268 | static struct sh_dmae_slave_config *sh_dmae_find_slave( | 268 | static const struct sh_dmae_slave_config *sh_dmae_find_slave( |
269 | struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) | 269 | struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) |
270 | { | 270 | { |
271 | struct dma_device *dma_dev = sh_chan->common.device; | 271 | struct dma_device *dma_dev = sh_chan->common.device; |
@@ -289,6 +289,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
289 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); | 289 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); |
290 | struct sh_desc *desc; | 290 | struct sh_desc *desc; |
291 | struct sh_dmae_slave *param = chan->private; | 291 | struct sh_dmae_slave *param = chan->private; |
292 | int ret; | ||
292 | 293 | ||
293 | pm_runtime_get_sync(sh_chan->dev); | 294 | pm_runtime_get_sync(sh_chan->dev); |
294 | 295 | ||
@@ -297,14 +298,18 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
297 | * never runs concurrently with itself or free_chan_resources. | 298 | * never runs concurrently with itself or free_chan_resources. |
298 | */ | 299 | */ |
299 | if (param) { | 300 | if (param) { |
300 | struct sh_dmae_slave_config *cfg; | 301 | const struct sh_dmae_slave_config *cfg; |
301 | 302 | ||
302 | cfg = sh_dmae_find_slave(sh_chan, param); | 303 | cfg = sh_dmae_find_slave(sh_chan, param); |
303 | if (!cfg) | 304 | if (!cfg) { |
304 | return -EINVAL; | 305 | ret = -EINVAL; |
306 | goto efindslave; | ||
307 | } | ||
305 | 308 | ||
306 | if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) | 309 | if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) { |
307 | return -EBUSY; | 310 | ret = -EBUSY; |
311 | goto etestused; | ||
312 | } | ||
308 | 313 | ||
309 | param->config = cfg; | 314 | param->config = cfg; |
310 | 315 | ||
@@ -333,10 +338,20 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
333 | } | 338 | } |
334 | spin_unlock_bh(&sh_chan->desc_lock); | 339 | spin_unlock_bh(&sh_chan->desc_lock); |
335 | 340 | ||
336 | if (!sh_chan->descs_allocated) | 341 | if (!sh_chan->descs_allocated) { |
337 | pm_runtime_put(sh_chan->dev); | 342 | ret = -ENOMEM; |
343 | goto edescalloc; | ||
344 | } | ||
338 | 345 | ||
339 | return sh_chan->descs_allocated; | 346 | return sh_chan->descs_allocated; |
347 | |||
348 | edescalloc: | ||
349 | if (param) | ||
350 | clear_bit(param->slave_id, sh_dmae_slave_used); | ||
351 | etestused: | ||
352 | efindslave: | ||
353 | pm_runtime_put(sh_chan->dev); | ||
354 | return ret; | ||
340 | } | 355 | } |
341 | 356 | ||
342 | /* | 357 | /* |
@@ -558,12 +573,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
558 | { | 573 | { |
559 | struct sh_dmae_slave *param; | 574 | struct sh_dmae_slave *param; |
560 | struct sh_dmae_chan *sh_chan; | 575 | struct sh_dmae_chan *sh_chan; |
576 | dma_addr_t slave_addr; | ||
561 | 577 | ||
562 | if (!chan) | 578 | if (!chan) |
563 | return NULL; | 579 | return NULL; |
564 | 580 | ||
565 | sh_chan = to_sh_chan(chan); | 581 | sh_chan = to_sh_chan(chan); |
566 | param = chan->private; | 582 | param = chan->private; |
583 | slave_addr = param->config->addr; | ||
567 | 584 | ||
568 | /* Someone calling slave DMA on a public channel? */ | 585 | /* Someone calling slave DMA on a public channel? */ |
569 | if (!param || !sg_len) { | 586 | if (!param || !sg_len) { |
@@ -576,7 +593,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
576 | * if (param != NULL), this is a successfully requested slave channel, | 593 | * if (param != NULL), this is a successfully requested slave channel, |
577 | * therefore param->config != NULL too. | 594 | * therefore param->config != NULL too. |
578 | */ | 595 | */ |
579 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, ¶m->config->addr, | 596 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr, |
580 | direction, flags); | 597 | direction, flags); |
581 | } | 598 | } |
582 | 599 | ||
@@ -857,7 +874,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
857 | int irq, unsigned long flags) | 874 | int irq, unsigned long flags) |
858 | { | 875 | { |
859 | int err; | 876 | int err; |
860 | struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; | 877 | const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; |
861 | struct platform_device *pdev = to_platform_device(shdev->common.dev); | 878 | struct platform_device *pdev = to_platform_device(shdev->common.dev); |
862 | struct sh_dmae_chan *new_sh_chan; | 879 | struct sh_dmae_chan *new_sh_chan; |
863 | 880 | ||