diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 23:27:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 23:27:23 -0500 |
commit | ca2a650f3dfdc30d71d21bcbb04d2d057779f3f9 (patch) | |
tree | 12e5f7f4dea5ba17cc82f2c633bbe9dbf725fb11 /drivers/dma/pl330.c | |
parent | e9e352e9100b98aed1a5fb9e33355c29fb07d5b1 (diff) | |
parent | 15cec530e4bc7bed3f51cde8404f96fd28a8c7c5 (diff) |
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dma updates from Vinod Koul:
- new driver for BCM2835 used in R-pi
- new driver for MOXA ART
- dma_get_any_slave_channel API for DT based systems
- minor fixes and updates spread acrooss driver
[ The fsl-ssi dual fifo mode support addition clashed badly with the
other changes to fsl-ssi that came in through the sound merge. I did
a very rough cut at fixing up the conflict, but Nicolin Chen (author
of both sides) will need to verify and check things ]
* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (36 commits)
dmaengine: mmp_pdma: fix mismerge
dma: pl08x: Export pl08x_filter_id
acpi-dma: align documentation with kernel-doc format
dma: fix vchan_cookie_complete() debug print
DMA: dmatest: extend the "device" module parameter to 32 characters
drivers/dma: fix error return code
dma: omap: Set debug level to debugging messages
dmaengine: fix kernel-doc style typos for few comments
dma: tegra: add support for Tegra148/124
dma: dw: use %pad instead of casting dma_addr_t
dma: dw: join split up messages
dma: dw: fix style of multiline comment
dmaengine: k3dma: fix sparse warnings
dma: pl330: Use dma_get_slave_channel() in the of xlate callback
dma: pl330: Differentiate between submitted and issued descriptors
dmaengine: sirf: Add device_slave_caps interface
DMA: Freescale: change BWC from 256 bytes to 1024 bytes
dmaengine: Add MOXA ART DMA engine driver
dmaengine: Add DMA_PRIVATE to BCM2835 driver
dma: imx-sdma: Assign a default script number for ROM firmware cases
...
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r-- | drivers/dma/pl330.c | 65 |
1 files changed, 34 insertions, 31 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index c90edecee463..73fa9b7a10ab 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
@@ -543,7 +543,9 @@ struct dma_pl330_chan { | |||
543 | /* DMA-Engine Channel */ | 543 | /* DMA-Engine Channel */ |
544 | struct dma_chan chan; | 544 | struct dma_chan chan; |
545 | 545 | ||
546 | /* List of to be xfered descriptors */ | 546 | /* List of submitted descriptors */ |
547 | struct list_head submitted_list; | ||
548 | /* List of issued descriptors */ | ||
547 | struct list_head work_list; | 549 | struct list_head work_list; |
548 | /* List of completed descriptors */ | 550 | /* List of completed descriptors */ |
549 | struct list_head completed_list; | 551 | struct list_head completed_list; |
@@ -578,12 +580,16 @@ struct dma_pl330_dmac { | |||
578 | /* DMA-Engine Device */ | 580 | /* DMA-Engine Device */ |
579 | struct dma_device ddma; | 581 | struct dma_device ddma; |
580 | 582 | ||
583 | /* Holds info about sg limitations */ | ||
584 | struct device_dma_parameters dma_parms; | ||
585 | |||
581 | /* Pool of descriptors available for the DMAC's channels */ | 586 | /* Pool of descriptors available for the DMAC's channels */ |
582 | struct list_head desc_pool; | 587 | struct list_head desc_pool; |
583 | /* To protect desc_pool manipulation */ | 588 | /* To protect desc_pool manipulation */ |
584 | spinlock_t pool_lock; | 589 | spinlock_t pool_lock; |
585 | 590 | ||
586 | /* Peripheral channels connected to this DMAC */ | 591 | /* Peripheral channels connected to this DMAC */ |
592 | unsigned int num_peripherals; | ||
587 | struct dma_pl330_chan *peripherals; /* keep at end */ | 593 | struct dma_pl330_chan *peripherals; /* keep at end */ |
588 | }; | 594 | }; |
589 | 595 | ||
@@ -606,11 +612,6 @@ struct dma_pl330_desc { | |||
606 | struct dma_pl330_chan *pchan; | 612 | struct dma_pl330_chan *pchan; |
607 | }; | 613 | }; |
608 | 614 | ||
609 | struct dma_pl330_filter_args { | ||
610 | struct dma_pl330_dmac *pdmac; | ||
611 | unsigned int chan_id; | ||
612 | }; | ||
613 | |||
614 | static inline void _callback(struct pl330_req *r, enum pl330_op_err err) | 615 | static inline void _callback(struct pl330_req *r, enum pl330_op_err err) |
615 | { | 616 | { |
616 | if (r && r->xfer_cb) | 617 | if (r && r->xfer_cb) |
@@ -2298,16 +2299,6 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) | |||
2298 | tasklet_schedule(&pch->task); | 2299 | tasklet_schedule(&pch->task); |
2299 | } | 2300 | } |
2300 | 2301 | ||
2301 | static bool pl330_dt_filter(struct dma_chan *chan, void *param) | ||
2302 | { | ||
2303 | struct dma_pl330_filter_args *fargs = param; | ||
2304 | |||
2305 | if (chan->device != &fargs->pdmac->ddma) | ||
2306 | return false; | ||
2307 | |||
2308 | return (chan->chan_id == fargs->chan_id); | ||
2309 | } | ||
2310 | |||
2311 | bool pl330_filter(struct dma_chan *chan, void *param) | 2302 | bool pl330_filter(struct dma_chan *chan, void *param) |
2312 | { | 2303 | { |
2313 | u8 *peri_id; | 2304 | u8 *peri_id; |
@@ -2325,23 +2316,16 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec, | |||
2325 | { | 2316 | { |
2326 | int count = dma_spec->args_count; | 2317 | int count = dma_spec->args_count; |
2327 | struct dma_pl330_dmac *pdmac = ofdma->of_dma_data; | 2318 | struct dma_pl330_dmac *pdmac = ofdma->of_dma_data; |
2328 | struct dma_pl330_filter_args fargs; | 2319 | unsigned int chan_id; |
2329 | dma_cap_mask_t cap; | ||
2330 | |||
2331 | if (!pdmac) | ||
2332 | return NULL; | ||
2333 | 2320 | ||
2334 | if (count != 1) | 2321 | if (count != 1) |
2335 | return NULL; | 2322 | return NULL; |
2336 | 2323 | ||
2337 | fargs.pdmac = pdmac; | 2324 | chan_id = dma_spec->args[0]; |
2338 | fargs.chan_id = dma_spec->args[0]; | 2325 | if (chan_id >= pdmac->num_peripherals) |
2339 | 2326 | return NULL; | |
2340 | dma_cap_zero(cap); | ||
2341 | dma_cap_set(DMA_SLAVE, cap); | ||
2342 | dma_cap_set(DMA_CYCLIC, cap); | ||
2343 | 2327 | ||
2344 | return dma_request_channel(cap, pl330_dt_filter, &fargs); | 2328 | return dma_get_slave_channel(&pdmac->peripherals[chan_id].chan); |
2345 | } | 2329 | } |
2346 | 2330 | ||
2347 | static int pl330_alloc_chan_resources(struct dma_chan *chan) | 2331 | static int pl330_alloc_chan_resources(struct dma_chan *chan) |
@@ -2385,6 +2369,11 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned | |||
2385 | pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); | 2369 | pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); |
2386 | 2370 | ||
2387 | /* Mark all desc done */ | 2371 | /* Mark all desc done */ |
2372 | list_for_each_entry(desc, &pch->submitted_list, node) { | ||
2373 | desc->status = FREE; | ||
2374 | dma_cookie_complete(&desc->txd); | ||
2375 | } | ||
2376 | |||
2388 | list_for_each_entry(desc, &pch->work_list , node) { | 2377 | list_for_each_entry(desc, &pch->work_list , node) { |
2389 | desc->status = FREE; | 2378 | desc->status = FREE; |
2390 | dma_cookie_complete(&desc->txd); | 2379 | dma_cookie_complete(&desc->txd); |
@@ -2395,6 +2384,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned | |||
2395 | dma_cookie_complete(&desc->txd); | 2384 | dma_cookie_complete(&desc->txd); |
2396 | } | 2385 | } |
2397 | 2386 | ||
2387 | list_splice_tail_init(&pch->submitted_list, &pdmac->desc_pool); | ||
2398 | list_splice_tail_init(&pch->work_list, &pdmac->desc_pool); | 2388 | list_splice_tail_init(&pch->work_list, &pdmac->desc_pool); |
2399 | list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool); | 2389 | list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool); |
2400 | spin_unlock_irqrestore(&pch->lock, flags); | 2390 | spin_unlock_irqrestore(&pch->lock, flags); |
@@ -2453,7 +2443,14 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
2453 | 2443 | ||
2454 | static void pl330_issue_pending(struct dma_chan *chan) | 2444 | static void pl330_issue_pending(struct dma_chan *chan) |
2455 | { | 2445 | { |
2456 | pl330_tasklet((unsigned long) to_pchan(chan)); | 2446 | struct dma_pl330_chan *pch = to_pchan(chan); |
2447 | unsigned long flags; | ||
2448 | |||
2449 | spin_lock_irqsave(&pch->lock, flags); | ||
2450 | list_splice_tail_init(&pch->submitted_list, &pch->work_list); | ||
2451 | spin_unlock_irqrestore(&pch->lock, flags); | ||
2452 | |||
2453 | pl330_tasklet((unsigned long)pch); | ||
2457 | } | 2454 | } |
2458 | 2455 | ||
2459 | /* | 2456 | /* |
@@ -2480,11 +2477,11 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) | |||
2480 | 2477 | ||
2481 | dma_cookie_assign(&desc->txd); | 2478 | dma_cookie_assign(&desc->txd); |
2482 | 2479 | ||
2483 | list_move_tail(&desc->node, &pch->work_list); | 2480 | list_move_tail(&desc->node, &pch->submitted_list); |
2484 | } | 2481 | } |
2485 | 2482 | ||
2486 | cookie = dma_cookie_assign(&last->txd); | 2483 | cookie = dma_cookie_assign(&last->txd); |
2487 | list_add_tail(&last->node, &pch->work_list); | 2484 | list_add_tail(&last->node, &pch->submitted_list); |
2488 | spin_unlock_irqrestore(&pch->lock, flags); | 2485 | spin_unlock_irqrestore(&pch->lock, flags); |
2489 | 2486 | ||
2490 | return cookie; | 2487 | return cookie; |
@@ -2960,6 +2957,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
2960 | else | 2957 | else |
2961 | num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); | 2958 | num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); |
2962 | 2959 | ||
2960 | pdmac->num_peripherals = num_chan; | ||
2961 | |||
2963 | pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); | 2962 | pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); |
2964 | if (!pdmac->peripherals) { | 2963 | if (!pdmac->peripherals) { |
2965 | ret = -ENOMEM; | 2964 | ret = -ENOMEM; |
@@ -2974,6 +2973,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
2974 | else | 2973 | else |
2975 | pch->chan.private = adev->dev.of_node; | 2974 | pch->chan.private = adev->dev.of_node; |
2976 | 2975 | ||
2976 | INIT_LIST_HEAD(&pch->submitted_list); | ||
2977 | INIT_LIST_HEAD(&pch->work_list); | 2977 | INIT_LIST_HEAD(&pch->work_list); |
2978 | INIT_LIST_HEAD(&pch->completed_list); | 2978 | INIT_LIST_HEAD(&pch->completed_list); |
2979 | spin_lock_init(&pch->lock); | 2979 | spin_lock_init(&pch->lock); |
@@ -3021,6 +3021,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
3021 | "unable to register DMA to the generic DT DMA helpers\n"); | 3021 | "unable to register DMA to the generic DT DMA helpers\n"); |
3022 | } | 3022 | } |
3023 | } | 3023 | } |
3024 | |||
3025 | adev->dev.dma_parms = &pdmac->dma_parms; | ||
3026 | |||
3024 | /* | 3027 | /* |
3025 | * This is the limit for transfers with a buswidth of 1, larger | 3028 | * This is the limit for transfers with a buswidth of 1, larger |
3026 | * buswidths will have larger limits. | 3029 | * buswidths will have larger limits. |