diff options
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 544340d7a464..a1727522343e 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | 29 | #include <linux/sh_dma.h> | |
30 | #include <asm/dmaengine.h> | ||
31 | 30 | ||
32 | #include "shdma.h" | 31 | #include "shdma.h" |
33 | 32 | ||
@@ -45,7 +44,7 @@ enum sh_dmae_desc_status { | |||
45 | #define LOG2_DEFAULT_XFER_SIZE 2 | 44 | #define LOG2_DEFAULT_XFER_SIZE 2 |
46 | 45 | ||
47 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ | 46 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ |
48 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; | 47 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; |
49 | 48 | ||
50 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); | 49 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); |
51 | 50 | ||
@@ -190,7 +189,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) | |||
190 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, | 189 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, |
191 | struct sh_dmae_device, common); | 190 | struct sh_dmae_device, common); |
192 | struct sh_dmae_pdata *pdata = shdev->pdata; | 191 | struct sh_dmae_pdata *pdata = shdev->pdata; |
193 | struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; | 192 | const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; |
194 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); | 193 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); |
195 | int shift = chan_pdata->dmars_bit; | 194 | int shift = chan_pdata->dmars_bit; |
196 | 195 | ||
@@ -266,8 +265,8 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) | |||
266 | return NULL; | 265 | return NULL; |
267 | } | 266 | } |
268 | 267 | ||
269 | static struct sh_dmae_slave_config *sh_dmae_find_slave( | 268 | static const struct sh_dmae_slave_config *sh_dmae_find_slave( |
270 | struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id) | 269 | struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) |
271 | { | 270 | { |
272 | struct dma_device *dma_dev = sh_chan->common.device; | 271 | struct dma_device *dma_dev = sh_chan->common.device; |
273 | struct sh_dmae_device *shdev = container_of(dma_dev, | 272 | struct sh_dmae_device *shdev = container_of(dma_dev, |
@@ -275,11 +274,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( | |||
275 | struct sh_dmae_pdata *pdata = shdev->pdata; | 274 | struct sh_dmae_pdata *pdata = shdev->pdata; |
276 | int i; | 275 | int i; |
277 | 276 | ||
278 | if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER) | 277 | if (param->slave_id >= SH_DMA_SLAVE_NUMBER) |
279 | return NULL; | 278 | return NULL; |
280 | 279 | ||
281 | for (i = 0; i < pdata->slave_num; i++) | 280 | for (i = 0; i < pdata->slave_num; i++) |
282 | if (pdata->slave[i].slave_id == slave_id) | 281 | if (pdata->slave[i].slave_id == param->slave_id) |
283 | return pdata->slave + i; | 282 | return pdata->slave + i; |
284 | 283 | ||
285 | return NULL; | 284 | return NULL; |
@@ -290,6 +289,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
290 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); | 289 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); |
291 | struct sh_desc *desc; | 290 | struct sh_desc *desc; |
292 | struct sh_dmae_slave *param = chan->private; | 291 | struct sh_dmae_slave *param = chan->private; |
292 | int ret; | ||
293 | 293 | ||
294 | pm_runtime_get_sync(sh_chan->dev); | 294 | pm_runtime_get_sync(sh_chan->dev); |
295 | 295 | ||
@@ -298,14 +298,18 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
298 | * never runs concurrently with itself or free_chan_resources. | 298 | * never runs concurrently with itself or free_chan_resources. |
299 | */ | 299 | */ |
300 | if (param) { | 300 | if (param) { |
301 | struct sh_dmae_slave_config *cfg; | 301 | const struct sh_dmae_slave_config *cfg; |
302 | 302 | ||
303 | cfg = sh_dmae_find_slave(sh_chan, param->slave_id); | 303 | cfg = sh_dmae_find_slave(sh_chan, param); |
304 | if (!cfg) | 304 | if (!cfg) { |
305 | return -EINVAL; | 305 | ret = -EINVAL; |
306 | goto efindslave; | ||
307 | } | ||
306 | 308 | ||
307 | 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)) { |
308 | return -EBUSY; | 310 | ret = -EBUSY; |
311 | goto etestused; | ||
312 | } | ||
309 | 313 | ||
310 | param->config = cfg; | 314 | param->config = cfg; |
311 | 315 | ||
@@ -334,10 +338,20 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
334 | } | 338 | } |
335 | spin_unlock_bh(&sh_chan->desc_lock); | 339 | spin_unlock_bh(&sh_chan->desc_lock); |
336 | 340 | ||
337 | if (!sh_chan->descs_allocated) | 341 | if (!sh_chan->descs_allocated) { |
338 | pm_runtime_put(sh_chan->dev); | 342 | ret = -ENOMEM; |
343 | goto edescalloc; | ||
344 | } | ||
339 | 345 | ||
340 | 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; | ||
341 | } | 355 | } |
342 | 356 | ||
343 | /* | 357 | /* |
@@ -559,12 +573,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
559 | { | 573 | { |
560 | struct sh_dmae_slave *param; | 574 | struct sh_dmae_slave *param; |
561 | struct sh_dmae_chan *sh_chan; | 575 | struct sh_dmae_chan *sh_chan; |
576 | dma_addr_t slave_addr; | ||
562 | 577 | ||
563 | if (!chan) | 578 | if (!chan) |
564 | return NULL; | 579 | return NULL; |
565 | 580 | ||
566 | sh_chan = to_sh_chan(chan); | 581 | sh_chan = to_sh_chan(chan); |
567 | param = chan->private; | 582 | param = chan->private; |
583 | slave_addr = param->config->addr; | ||
568 | 584 | ||
569 | /* Someone calling slave DMA on a public channel? */ | 585 | /* Someone calling slave DMA on a public channel? */ |
570 | if (!param || !sg_len) { | 586 | if (!param || !sg_len) { |
@@ -577,7 +593,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
577 | * if (param != NULL), this is a successfully requested slave channel, | 593 | * if (param != NULL), this is a successfully requested slave channel, |
578 | * therefore param->config != NULL too. | 594 | * therefore param->config != NULL too. |
579 | */ | 595 | */ |
580 | 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, |
581 | direction, flags); | 597 | direction, flags); |
582 | } | 598 | } |
583 | 599 | ||
@@ -859,7 +875,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
859 | int irq, unsigned long flags) | 875 | int irq, unsigned long flags) |
860 | { | 876 | { |
861 | int err; | 877 | int err; |
862 | struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; | 878 | const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; |
863 | struct platform_device *pdev = to_platform_device(shdev->common.dev); | 879 | struct platform_device *pdev = to_platform_device(shdev->common.dev); |
864 | struct sh_dmae_chan *new_sh_chan; | 880 | struct sh_dmae_chan *new_sh_chan; |
865 | 881 | ||