mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King:
"The major updates included in this update are:
- Clang compatible stack pointer accesses by Behan Webster.
- SA11x0 updates from Dmitry Eremin-Solenikov.
- kgdb handling of breakpoints with read-only text/modules
- Support for Privileged-no-execute feature on ARMv7 to prevent
userspace code execution by the kernel.
- AMBA primecell bus handling of irq-safe runtime PM
- Unwinding support for memset/memzero/memmove/memcpy functions
- VFP fixes for Krait CPUs and improvements in detecting the VFP
architecture
- A number of code cleanups (using pr_*, removing or reducing the
severity of a couple of kernel messages, splitting ftrace asm code
out to a separate file, etc.)
- Add machine name to stack dump output"
* 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: (62 commits)
ARM: 8247/2: pcmcia: sa1100: make use of device clock
ARM: 8246/2: pcmcia: sa1111: provide device clock
ARM: 8245/1: pcmcia: soc-common: enable/disable socket clocks
ARM: 8244/1: fbdev: sa1100fb: make use of device clock
ARM: 8243/1: sa1100: add a clock alias for sa1111 pcmcia device
ARM: 8242/1: sa1100: add cpu clock
ARM: 8221/1: PJ4: allow building in Thumb-2 mode
ARM: 8234/1: sa1100: reorder IRQ handling code
ARM: 8233/1: sa1100: switch to hwirq usage
ARM: 8232/1: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain
ARM: 8231/1: sa1100: introduce irqdomains support
ARM: 8230/1: sa1100: shift IRQs by one
ARM: 8229/1: sa1100: replace irq numbers with names in irq driver
ARM: 8228/1: sa1100: drop entry-macro.S
ARM: 8227/1: sa1100: switch to MULTI_IRQ_HANDLER
ARM: 8241/1: Update processor_modes for hyp and monitor mode
ARM: 8240/1: MCPM: document mcpm_sync_init()
ARM: 8239/1: Introduce {set,clear}_pte_bit
ARM: 8238/1: mm: Refine set_memory_* functions
ARM: 8237/1: fix flush_pfn_alias
...
This commit is contained in:
commit
26ceb127f7
92 changed files with 1592 additions and 850 deletions
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "dmaengine.h"
|
||||
#define PL330_MAX_CHAN 8
|
||||
|
|
@ -265,6 +266,9 @@ static unsigned cmd_line;
|
|||
|
||||
#define NR_DEFAULT_DESC 16
|
||||
|
||||
/* Delay for runtime PM autosuspend, ms */
|
||||
#define PL330_AUTOSUSPEND_DELAY 20
|
||||
|
||||
/* Populated by the PL330 core driver for DMA API driver's info */
|
||||
struct pl330_config {
|
||||
u32 periph_id;
|
||||
|
|
@ -1958,6 +1962,7 @@ static void pl330_tasklet(unsigned long data)
|
|||
struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
|
||||
struct dma_pl330_desc *desc, *_dt;
|
||||
unsigned long flags;
|
||||
bool power_down = false;
|
||||
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
|
|
@ -1972,10 +1977,17 @@ static void pl330_tasklet(unsigned long data)
|
|||
/* Try to submit a req imm. next to the last completed cookie */
|
||||
fill_queue(pch);
|
||||
|
||||
/* Make sure the PL330 Channel thread is active */
|
||||
spin_lock(&pch->thread->dmac->lock);
|
||||
_start(pch->thread);
|
||||
spin_unlock(&pch->thread->dmac->lock);
|
||||
if (list_empty(&pch->work_list)) {
|
||||
spin_lock(&pch->thread->dmac->lock);
|
||||
_stop(pch->thread);
|
||||
spin_unlock(&pch->thread->dmac->lock);
|
||||
power_down = true;
|
||||
} else {
|
||||
/* Make sure the PL330 Channel thread is active */
|
||||
spin_lock(&pch->thread->dmac->lock);
|
||||
_start(pch->thread);
|
||||
spin_unlock(&pch->thread->dmac->lock);
|
||||
}
|
||||
|
||||
while (!list_empty(&pch->completed_list)) {
|
||||
dma_async_tx_callback callback;
|
||||
|
|
@ -1990,6 +2002,12 @@ static void pl330_tasklet(unsigned long data)
|
|||
if (pch->cyclic) {
|
||||
desc->status = PREP;
|
||||
list_move_tail(&desc->node, &pch->work_list);
|
||||
if (power_down) {
|
||||
spin_lock(&pch->thread->dmac->lock);
|
||||
_start(pch->thread);
|
||||
spin_unlock(&pch->thread->dmac->lock);
|
||||
power_down = false;
|
||||
}
|
||||
} else {
|
||||
desc->status = FREE;
|
||||
list_move_tail(&desc->node, &pch->dmac->desc_pool);
|
||||
|
|
@ -2004,6 +2022,12 @@ static void pl330_tasklet(unsigned long data)
|
|||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
|
||||
/* If work list empty, power down */
|
||||
if (power_down) {
|
||||
pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
|
||||
pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
|
||||
}
|
||||
}
|
||||
|
||||
bool pl330_filter(struct dma_chan *chan, void *param)
|
||||
|
|
@ -2073,6 +2097,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
|
|||
|
||||
switch (cmd) {
|
||||
case DMA_TERMINATE_ALL:
|
||||
pm_runtime_get_sync(pl330->ddma.dev);
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
spin_lock(&pl330->lock);
|
||||
|
|
@ -2099,10 +2124,15 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
|
|||
dma_cookie_complete(&desc->txd);
|
||||
}
|
||||
|
||||
if (!list_empty(&pch->work_list))
|
||||
pm_runtime_put(pl330->ddma.dev);
|
||||
|
||||
list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool);
|
||||
list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
|
||||
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
||||
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||
break;
|
||||
case DMA_SLAVE_CONFIG:
|
||||
slave_config = (struct dma_slave_config *)arg;
|
||||
|
|
@ -2138,6 +2168,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
|
|||
|
||||
tasklet_kill(&pch->task);
|
||||
|
||||
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
pl330_release_channel(pch->thread);
|
||||
|
|
@ -2147,6 +2178,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
|
|||
list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
|
||||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
|
||||
pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
|
||||
}
|
||||
|
||||
static enum dma_status
|
||||
|
|
@ -2162,6 +2195,15 @@ static void pl330_issue_pending(struct dma_chan *chan)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
if (list_empty(&pch->work_list)) {
|
||||
/*
|
||||
* Warn on nothing pending. Empty submitted_list may
|
||||
* break our pm_runtime usage counter as it is
|
||||
* updated on work_list emptiness status.
|
||||
*/
|
||||
WARN_ON(list_empty(&pch->submitted_list));
|
||||
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
||||
}
|
||||
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
|
||||
|
|
@ -2594,6 +2636,46 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runtime PM callbacks are provided by amba/bus.c driver.
|
||||
*
|
||||
* It is assumed here that IRQ safe runtime PM is chosen in probe and amba
|
||||
* bus driver will only disable/enable the clock in runtime PM callbacks.
|
||||
*/
|
||||
static int __maybe_unused pl330_suspend(struct device *dev)
|
||||
{
|
||||
struct amba_device *pcdev = to_amba_device(dev);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
if (!pm_runtime_status_suspended(dev)) {
|
||||
/* amba did not disable the clock */
|
||||
amba_pclk_disable(pcdev);
|
||||
}
|
||||
amba_pclk_unprepare(pcdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused pl330_resume(struct device *dev)
|
||||
{
|
||||
struct amba_device *pcdev = to_amba_device(dev);
|
||||
int ret;
|
||||
|
||||
ret = amba_pclk_prepare(pcdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
ret = amba_pclk_enable(pcdev);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
|
||||
|
||||
static int
|
||||
pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
|
|
@ -2748,6 +2830,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
|
||||
pcfg->num_peri, pcfg->num_events);
|
||||
|
||||
pm_runtime_irq_safe(&adev->dev);
|
||||
pm_runtime_use_autosuspend(&adev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY);
|
||||
pm_runtime_mark_last_busy(&adev->dev);
|
||||
pm_runtime_put_autosuspend(&adev->dev);
|
||||
|
||||
return 0;
|
||||
probe_err3:
|
||||
/* Idle the DMAC */
|
||||
|
|
@ -2774,6 +2862,8 @@ static int pl330_remove(struct amba_device *adev)
|
|||
struct pl330_dmac *pl330 = amba_get_drvdata(adev);
|
||||
struct dma_pl330_chan *pch, *_p;
|
||||
|
||||
pm_runtime_get_noresume(pl330->ddma.dev);
|
||||
|
||||
if (adev->dev.of_node)
|
||||
of_dma_controller_free(adev->dev.of_node);
|
||||
|
||||
|
|
@ -2812,6 +2902,7 @@ static struct amba_driver pl330_driver = {
|
|||
.drv = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "dma-pl330",
|
||||
.pm = &pl330_pm,
|
||||
},
|
||||
.id_table = pl330_ids,
|
||||
.probe = pl330_probe,
|
||||
|
|
|
|||
Loading…
Reference in a new issue