The unmap_range function did not properly cover the case when the start
address was not aligned to PMD_SIZE or PUD_SIZE and an entire pte table
or pmd table was cleared, causing us to leak memory when incrementing
the addr.
The fix is to always move onto the next page table entry boundary
instead of adding the full size of the VA range covered by the
corresponding table level entry.
Acked-by: Marc Zyngier <marc.zyngier(a)arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall(a)linaro.org>
---
arch/arm/kvm/mmu.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index ca6bea4..80a83ec 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -132,37 +132,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
pmd_t *pmd;
pte_t *pte;
unsigned long long addr = start, end = start + size;
- u64 range;
+ u64 next;
while (addr < end) {
pgd = pgdp + pgd_index(addr);
pud = pud_offset(pgd, addr);
if (pud_none(*pud)) {
- addr += PUD_SIZE;
+ addr = pud_addr_end(addr, end);
continue;
}
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
- addr += PMD_SIZE;
+ addr = pmd_addr_end(addr, end);
continue;
}
pte = pte_offset_kernel(pmd, addr);
clear_pte_entry(kvm, pte, addr);
- range = PAGE_SIZE;
+ next = addr + PAGE_SIZE;
/* If we emptied the pte, walk back up the ladder */
if (pte_empty(pte)) {
clear_pmd_entry(kvm, pmd, addr);
- range = PMD_SIZE;
+ next = pmd_addr_end(addr, end);
if (pmd_empty(pmd)) {
clear_pud_entry(kvm, pud, addr);
- range = PUD_SIZE;
+ next = pud_addr_end(addr, end);
}
}
- addr += range;
+ addr = next;
}
}
--
1.7.10.4
THe kvm_set_pte function was actually assigning the entire struct to the
structure member, which should work because the structure only has that
one member, but it is still not very nice.
Signed-off-by: Christoffer Dall <christoffer.dall(a)linaro.org>
---
arch/arm/include/asm/kvm_mmu.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 472ac70..9b28c41 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -64,7 +64,7 @@ void kvm_clear_hyp_idmap(void);
static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
{
- pte_val(*pte) = new_pte;
+ *pte = new_pte;
/*
* flush_pmd_entry just takes a void pointer and cleans the necessary
* cache entries, so we can reuse the function for ptes.
--
1.7.10.4
Hi Stephen,
This is the first attempt to get rid of tegra-cpufreq driver. This patchset
tries to add supporting infrastructure for tegra to use cpufreq-cpu0 driver.
I don't have hardware to test it and so is compiled tested only.. Few bits may
be missing as I couldn't think of all aspects and so may need your help getting
them fixed.
Once this is tested by you, I would like to take it through my ARM cpufreq tree
if nobody else has a problem with it.
Thanks
--
Viresh.
Viresh Kumar (6):
clk: Tegra: Add CPU0 clock driver
ARM: Tegra: Add CPU's OPPs for using cpufreq-cpu0 driver
ARM: Tegra: Enable OPP library
ARM: Tegra: defconfig: select cpufreq-cpu0 driver
ARM: Tegra: start using cpufreq-cpu0 driver
cpufreq: Tegra: Remove tegra-cpufreq driver
arch/arm/boot/dts/tegra114.dtsi | 12 ++
arch/arm/boot/dts/tegra20.dtsi | 12 ++
arch/arm/boot/dts/tegra30.dtsi | 12 ++
arch/arm/configs/tegra_defconfig | 1 +
arch/arm/mach-tegra/Kconfig | 2 +
arch/arm/mach-tegra/tegra.c | 2 +
drivers/clk/tegra/Makefile | 1 +
drivers/clk/tegra/clk-cpu.c | 164 ++++++++++++++++++++++
drivers/clk/tegra/clk-tegra30.c | 4 +
drivers/cpufreq/Kconfig.arm | 8 --
drivers/cpufreq/Makefile | 1 -
drivers/cpufreq/tegra-cpufreq.c | 291 ---------------------------------------
include/linux/clk/tegra.h | 1 +
13 files changed, 211 insertions(+), 300 deletions(-)
create mode 100644 drivers/clk/tegra/clk-cpu.c
delete mode 100644 drivers/cpufreq/tegra-cpufreq.c
--
1.7.12.rc2.18.g61b472e
From: Mark Brown <broonie(a)linaro.org>
Commit 28ec711 (drm/agp: move AGP cleanup paths to drm_agpsupport.c)
broke the build for platforms which do not have AGP since it moved the
AGP cleanup code inside an #ifdef __OS_HAS_AGP which are referenced
unconditionally in drm_drv.c. This causes build failures for embedded
SoCs which use DRM but do not have AGP.
Fix this by providing stub static inlines in the header.
Signed-off-by: Mark Brown <broonie(a)linaro.org>
---
include/drm/drmP.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index fba5473..e7f7da0 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1453,6 +1453,7 @@ extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/* AGP/GART support (drm_agpsupport.h) */
+#if __OS_HAS_AGP
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
extern void drm_agp_destroy(struct drm_agp_head *agp);
extern void drm_agp_clear(struct drm_device *dev);
@@ -1480,6 +1481,10 @@ extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+#else
+static inline void drm_agp_destroy(struct drm_agp_head *agp) { }
+static inline void drm_agp_clear(struct drm_device *dev) { }
+#endif
/* Stub support (drm_stub.h) */
extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
--
1.8.4.rc1
Bridge and TUN/TAP support are needed for enabling networking with
a guest OS.
Signed-off-by: Kim Phillips <kim.phillips(a)linaro.org>
---
ultimately targeted for the LNG kernel, but seeking acceptance in
the upstream linaro kernel
linaro/configs/kvm-host.conf | 2 ++
1 file changed, 2 insertions(+)
diff --git a/linaro/configs/kvm-host.conf b/linaro/configs/kvm-host.conf
index 21a40e0..0e4c21a 100644
--- a/linaro/configs/kvm-host.conf
+++ b/linaro/configs/kvm-host.conf
@@ -9,3 +9,5 @@ CONFIG_KVM_ARM_VGIC=y
CONFIG_KVM_MMIO=y
CONFIG_KVM=y
CONFIG_BLK_DEV_NBD=m
+CONFIG_BRIDGE=y
+CONFIG_TUN=y
--
1.8.3.3
Export opp_add() so that modules can use it.
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
drivers/base/power/opp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index c8ec186..ef89897 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -460,6 +460,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
return 0;
}
+EXPORT_SYMBOL_GPL(opp_add);
/**
* opp_set_availability() - helper to set the availability of an opp
--
1.7.12.rc2.18.g61b472e
On Wed, 2013-08-07 at 18:52 +0530, Viresh Kumar wrote:
> While getting support for In-Kernel-Switcher in big LITTLE cpufreq driver we
> introduced cpu_last_req_freq per-cpu variable that stores the last frequency
> requested for a cpu. It was important for IKS as CPUs in the same cluster can
> have separate struct cpufreq_policy associated with them and so cpufreq core may
> try to set different frequencies on both CPUs of same cluster.
>
> But for non-IKS solution or MP we don't need to cache last requested frequency.
> Currently there is a bug in code where if cpufreq_driver->get() is called for
> any cpu other than policy->cpu, we are returning 0, because we set
> cpu_last_req_freq only for policy->cpu and not for others.
Do you know what the observable symptoms of this are?
As this is a fix which needs to get into LSK I've added the
linaro-kernel list to the cc so it has more public visibility.
Tixy
> This problem could have been fixed by setting cpu_last_req_freq for all CPUs in
> policy->cpus, but that wouldn't be the best solution. Purpose of
> cpufreq_driver->get() is to get exact frequency from the hardware instead of
> returning cached frequency that was last requested as that is already present
> with the core.
>
> Hence, this patch forces only IKS to use cpu_last_req_freq and not MP. We will
> get the frequency from hardware when ->get() is called for MP.
>
> Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
> ---
> drivers/cpufreq/arm_big_little.c | 27 ++++++++++++++++++---------
> 1 file changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
> index f589b6c..c8de71f 100644
> --- a/drivers/cpufreq/arm_big_little.c
> +++ b/drivers/cpufreq/arm_big_little.c
> @@ -91,9 +91,14 @@ static unsigned int clk_get_cpu_rate(unsigned int cpu)
>
> static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
> {
> - pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq, cpu));
> + if (is_bL_switching_enabled()) {
> + pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq,
> + cpu));
>
> - return per_cpu(cpu_last_req_freq, cpu);
> + return per_cpu(cpu_last_req_freq, cpu);
> + } else {
> + return clk_get_cpu_rate(cpu);
> + }
> }
>
> static unsigned int
> @@ -104,11 +109,11 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
>
> mutex_lock(&cluster_lock[new_cluster]);
>
> - prev_rate = per_cpu(cpu_last_req_freq, cpu);
> - per_cpu(cpu_last_req_freq, cpu) = rate;
> - per_cpu(physical_cluster, cpu) = new_cluster;
> -
> if (is_bL_switching_enabled()) {
> + prev_rate = per_cpu(cpu_last_req_freq, cpu);
> + per_cpu(cpu_last_req_freq, cpu) = rate;
> + per_cpu(physical_cluster, cpu) = new_cluster;
> +
> new_rate = find_cluster_maxfreq(new_cluster);
> new_rate = ACTUAL_FREQ(new_cluster, new_rate);
> } else {
> @@ -122,8 +127,10 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> if (WARN_ON(ret)) {
> pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
> new_cluster);
> - per_cpu(cpu_last_req_freq, cpu) = prev_rate;
> - per_cpu(physical_cluster, cpu) = old_cluster;
> + if (is_bL_switching_enabled()) {
> + per_cpu(cpu_last_req_freq, cpu) = prev_rate;
> + per_cpu(physical_cluster, cpu) = old_cluster;
> + }
>
> mutex_unlock(&cluster_lock[new_cluster]);
>
> @@ -461,7 +468,9 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
> policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
>
> policy->cur = clk_get_cpu_rate(policy->cpu);
> - per_cpu(cpu_last_req_freq, policy->cpu) = policy->cur;
> +
> + if (is_bL_switching_enabled())
> + per_cpu(cpu_last_req_freq, policy->cpu) = policy->cur;
>
> dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
> return 0;
From: Mark Brown <broonie(a)linaro.org>
The pin list is the same for any board using the CODEC.
Signed-off-by: Mark Brown <broonie(a)linaro.org>
---
.../bindings/sound/nvidia,tegra-audio-wm8903.txt | 24 ++--------------------
Documentation/devicetree/bindings/sound/wm8903.txt | 19 +++++++++++++++++
2 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
index 3bf722d..4b44dfb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
@@ -11,28 +11,8 @@ Required properties:
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
- sinks are the WM8903's pins, and the jacks on the board:
-
- WM8903 pins:
-
- * IN1L
- * IN1R
- * IN2L
- * IN2R
- * IN3L
- * IN3R
- * DMICDAT
- * HPOUTL
- * HPOUTR
- * LINEOUTL
- * LINEOUTR
- * LOP
- * LON
- * ROP
- * RON
- * MICBIAS
-
- Board connectors:
+ sinks are the WM8903's pins (documented in the WM8903 binding document),
+ and the jacks on the board:
* Headphone Jack
* Int Spk
diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt
index f102cbc..94ec32c 100644
--- a/Documentation/devicetree/bindings/sound/wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/wm8903.txt
@@ -28,6 +28,25 @@ Optional properties:
performed. If any entry has the value 0xffffffff, that GPIO's
configuration will not be modified.
+Pins on the device (for linking into audio routes):
+
+ * IN1L
+ * IN1R
+ * IN2L
+ * IN2R
+ * IN3L
+ * IN3R
+ * DMICDAT
+ * HPOUTL
+ * HPOUTR
+ * LINEOUTL
+ * LINEOUTR
+ * LOP
+ * LON
+ * ROP
+ * RON
+ * MICBIAS
+
Example:
codec: wm8903@1a {
--
1.8.4.rc1
The PAR was exported as CRn == 7 and CRm == 0, but in fact the primary
coprocessor register number was determined by CRm for 64-bit coprocessor
registers as the user space API was modeled after the coprocessor
access instructions (see the ARM ARM rev. C - B3-1445).
However, just changing the CRn to CRm breaks the sorting check when
booting the kernel, because the internal kernel logic always treats CRn
as the primary register number, and it makes the table sorting
impossible to understand for humans.
Alternatively we could change the logic to always have CRn == CRm, but
that becomes unclear in the number of ways we do look up of a coprocessor
register. We could also have a separate 64-bit table but that feels
somewhat over-engineered. Instead, keep CRn the primary representation
of the primary coproc. register number in-kernel and always export the
primary number as CRm as per the existing user space ABI.
Note: The TTBR registers just magically worked because they happened to
follow the CRn(0) regs and were considered CRn(0) in the in-kernel
representation.
Cc: Marc Zyngier <marc.zyngier(a)arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall(a)linaro.org>
---
[Changes v1 -> v2]:
- Use CRm64 macro as suggested by Marc Zyngier
- Fix spelling issues
arch/arm/kvm/coproc.c | 26 +++++++++++++++++++-------
arch/arm/kvm/coproc.h | 3 +++
arch/arm/kvm/coproc_a15.c | 6 +++++-
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 4a51990..db9cf69 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
#define access_pmintenclr pm_fake
/* Architected CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ * registers preceding 32-bit ones.
*/
static const struct coproc_reg cp15_regs[] = {
/* CSSELR: swapped by interrupt.S. */
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
NULL, reset_unknown, c0_CSSELR },
/* TTBR0/TTBR1: swapped by interrupt.S. */
- { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
- { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+ { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+ { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
/* TTBCR: swapped by interrupt.S. */
{ CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
@@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = {
NULL, reset_unknown, c6_IFAR },
/* PAR swapped by interrupt.S */
- { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+ { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
/*
* DC{C,I,CI}SW operations:
@@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
| KVM_REG_ARM_OPC1_MASK))
return false;
params->is_64bit = true;
- params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+ /* CRm to CRn: see cp15_to_index for details */
+ params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
>> KVM_REG_ARM_CRM_SHIFT);
params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
>> KVM_REG_ARM_OPC1_SHIFT);
params->Op2 = 0;
- params->CRn = 0;
+ params->CRm = 0;
return true;
default:
return false;
@@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
if (reg->is_64) {
val |= KVM_REG_SIZE_U64;
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
- val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+ /*
+ * CRn always denotes the primary coproc. reg. nr. for the
+ * in-kernel representation, but the user space API uses the
+ * CRm for the encoding, because it is modelled after the
+ * MRRC/MCRR instructions: see the ARM ARM rev. c page
+ * B3-1445
+ */
+ val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
} else {
val |= KVM_REG_SIZE_U32;
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h
index b7301d3..0461d5c 100644
--- a/arch/arm/kvm/coproc.h
+++ b/arch/arm/kvm/coproc.h
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
return -1;
if (i1->CRn != i2->CRn)
return i1->CRn - i2->CRn;
+ if (i1->is_64 != i2->is_64)
+ return i2->is_64 - i1->is_64;
if (i1->CRm != i2->CRm)
return i1->CRm - i2->CRm;
if (i1->Op1 != i2->Op1)
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
#define CRn(_x) .CRn = _x
#define CRm(_x) .CRm = _x
+#define CRm64(_x) .CRn = _x, .CRm = 0
#define Op1(_x) .Op1 = _x
#define Op2(_x) .Op2 = _x
#define is64 .is_64 = true
diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c
index 685063a..cf93472 100644
--- a/arch/arm/kvm/coproc_a15.c
+++ b/arch/arm/kvm/coproc_a15.c
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
/*
* A15-specific CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ * registers preceding 32-bit ones.
*/
static const struct coproc_reg a15_regs[] = {
/* MPIDR: we use VMPIDR for guest access. */
--
1.7.10.4