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:
Linus Torvalds 2014-12-12 15:26:48 -08:00
commit 26ceb127f7
92 changed files with 1592 additions and 850 deletions

View file

@ -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,