* [RFC PATCH 7/8] KVM: arm64: vgic-its: fix compatability with 32-bit
From: Vladimir Murzin @ 2016-10-21 11:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5ea0ecc0-edb1-f770-16f3-7c48dbdb5c29@arm.com>
On 21/10/16 10:49, Andre Przywara wrote:
> Hi,
>
> On 21/10/16 10:36, Vladimir Murzin wrote:
>> Evaluate GITS_BASER_ENTRY_SIZE once as an int data (GITS_BASER<n>'s
>> Entry Size is 5-bit wide only), so when used as divider no reference
>> to __aeabi_uldivmod is generated when build for AArch32.
>>
>> Use unsigned long long for GITS_BASER_PAGE_SIZE_* since they are
>> used in conjunction with 64-bit data.
>>
>> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
>
> Looks good to me, thanks for fixing this!
>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Thanks!
Vladimir
>
> Cheers,
> Andre.
>
>> ---
>> include/linux/irqchip/arm-gic-v3.h | 8 ++++----
>> virt/kvm/arm/vgic/vgic-its.c | 11 ++++++-----
>> 2 files changed, 10 insertions(+), 9 deletions(-)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 5118d3a..e808f8a 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -295,10 +295,10 @@
>> #define GITS_BASER_InnerShareable \
>> GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
>> #define GITS_BASER_PAGE_SIZE_SHIFT (8)
>> -#define GITS_BASER_PAGE_SIZE_4K (0UL << GITS_BASER_PAGE_SIZE_SHIFT)
>> -#define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT)
>> -#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
>> -#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
>> +#define GITS_BASER_PAGE_SIZE_4K (0ULL << GITS_BASER_PAGE_SIZE_SHIFT)
>> +#define GITS_BASER_PAGE_SIZE_16K (1ULL << GITS_BASER_PAGE_SIZE_SHIFT)
>> +#define GITS_BASER_PAGE_SIZE_64K (2ULL << GITS_BASER_PAGE_SIZE_SHIFT)
>> +#define GITS_BASER_PAGE_SIZE_MASK (3ULL << GITS_BASER_PAGE_SIZE_SHIFT)
>> #define GITS_BASER_PAGES_MAX 256
>> #define GITS_BASER_PAGES_SHIFT (0)
>> #define GITS_BASER_NR_PAGES(r) (((r) & 0xff) + 1)
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index 4660a7d..8c2b3cd 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -632,21 +632,22 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
>> int index;
>> u64 indirect_ptr;
>> gfn_t gfn;
>> + int esz = GITS_BASER_ENTRY_SIZE(baser);
>>
>> if (!(baser & GITS_BASER_INDIRECT)) {
>> phys_addr_t addr;
>>
>> - if (id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(baser)))
>> + if (id >= (l1_tbl_size / esz))
>> return false;
>>
>> - addr = BASER_ADDRESS(baser) + id * GITS_BASER_ENTRY_SIZE(baser);
>> + addr = BASER_ADDRESS(baser) + id * esz;
>> gfn = addr >> PAGE_SHIFT;
>>
>> return kvm_is_visible_gfn(its->dev->kvm, gfn);
>> }
>>
>> /* calculate and check the index into the 1st level */
>> - index = id / (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
>> + index = id / (SZ_64K / esz);
>> if (index >= (l1_tbl_size / sizeof(u64)))
>> return false;
>>
>> @@ -670,8 +671,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
>> indirect_ptr &= GENMASK_ULL(51, 16);
>>
>> /* Find the address of the actual entry */
>> - index = id % (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
>> - indirect_ptr += index * GITS_BASER_ENTRY_SIZE(baser);
>> + index = id % (SZ_64K / esz);
>> + indirect_ptr += index * esz;
>> gfn = indirect_ptr >> PAGE_SHIFT;
>>
>> return kvm_is_visible_gfn(its->dev->kvm, gfn);
>>
>
^ permalink raw reply
* [RFC PATCH 8/8] ARM: KVM: Support vGICv3 ITS
From: Vladimir Murzin @ 2016-10-21 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <857fb7fd-b8eb-7a44-2a6c-be2ec41927ec@arm.com>
On 21/10/16 12:02, Andre Przywara wrote:
> Hi,
>
> On 21/10/16 10:36, Vladimir Murzin wrote:
>> This patch allows to build and use vGICv3 ITS in 32-bit mode.
>
> Ah, what a relief to see that config option go. Thanks for that!
>
> I quickly booted an ITS guest on a (64-bit) model and couldn't spot any
> regressions.
Awesome!
>
>> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Thanks for your time!
Cheers
Vladimir
>
> Cheers,
> Andre.
>
>> ---
>> Documentation/virtual/kvm/api.txt | 2 +-
>> arch/arm/include/uapi/asm/kvm.h | 2 ++
>> arch/arm/kvm/Kconfig | 1 +
>> arch/arm/kvm/Makefile | 1 +
>> arch/arm/kvm/arm.c | 6 ++++++
>> arch/arm64/kvm/Kconfig | 4 ----
>> arch/arm64/kvm/reset.c | 6 ------
>> virt/kvm/arm/vgic/vgic-kvm-device.c | 2 --
>> virt/kvm/arm/vgic/vgic-mmio-v3.c | 2 --
>> virt/kvm/arm/vgic/vgic.h | 26 --------------------------
>> 10 files changed, 11 insertions(+), 41 deletions(-)
>>
>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>> index 739db9a..2feeae6 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -2198,7 +2198,7 @@ after pausing the vcpu, but before it is resumed.
>> 4.71 KVM_SIGNAL_MSI
>>
>> Capability: KVM_CAP_SIGNAL_MSI
>> -Architectures: x86 arm64
>> +Architectures: x86 arm arm64
>> Type: vm ioctl
>> Parameters: struct kvm_msi (in)
>> Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
>> index b38c10c..af05f8e 100644
>> --- a/arch/arm/include/uapi/asm/kvm.h
>> +++ b/arch/arm/include/uapi/asm/kvm.h
>> @@ -87,9 +87,11 @@ struct kvm_regs {
>> /* Supported VGICv3 address types */
>> #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
>> #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
>> +#define KVM_VGIC_ITS_ADDR_TYPE 4
>>
>> #define KVM_VGIC_V3_DIST_SIZE SZ_64K
>> #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
>> +#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
>>
>> #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
>> #define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
>> diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
>> index 3e1cd04..90d0176 100644
>> --- a/arch/arm/kvm/Kconfig
>> +++ b/arch/arm/kvm/Kconfig
>> @@ -34,6 +34,7 @@ config KVM
>> select HAVE_KVM_IRQFD
>> select HAVE_KVM_IRQCHIP
>> select HAVE_KVM_IRQ_ROUTING
>> + select HAVE_KVM_MSI
>> depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
>> ---help---
>> Support hosting virtualized guest machines.
>> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
>> index f19842e..d571243 100644
>> --- a/arch/arm/kvm/Makefile
>> +++ b/arch/arm/kvm/Makefile
>> @@ -32,5 +32,6 @@ obj-y += $(KVM)/arm/vgic/vgic-mmio.o
>> obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
>> obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
>> obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
>> +obj-y += $(KVM)/arm/vgic/vgic-its.o
>> obj-y += $(KVM)/irqchip.o
>> obj-y += $(KVM)/arm/arch_timer.o
>> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
>> index 03e9273..8b13448 100644
>> --- a/arch/arm/kvm/arm.c
>> +++ b/arch/arm/kvm/arm.c
>> @@ -209,6 +209,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>> case KVM_CAP_MAX_VCPUS:
>> r = KVM_MAX_VCPUS;
>> break;
>> + case KVM_CAP_MSI_DEVID:
>> + if (!kvm)
>> + r = -EINVAL;
>> + else
>> + r = kvm->arch.vgic.msis_require_devid;
>> + break;
>> default:
>> r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
>> break;
>> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
>> index 6eaf12c..52cb7ad 100644
>> --- a/arch/arm64/kvm/Kconfig
>> +++ b/arch/arm64/kvm/Kconfig
>> @@ -16,9 +16,6 @@ menuconfig VIRTUALIZATION
>>
>> if VIRTUALIZATION
>>
>> -config KVM_ARM_VGIC_V3_ITS
>> - bool
>> -
>> config KVM
>> bool "Kernel-based Virtual Machine (KVM) support"
>> depends on OF
>> @@ -34,7 +31,6 @@ config KVM
>> select KVM_VFIO
>> select HAVE_KVM_EVENTFD
>> select HAVE_KVM_IRQFD
>> - select KVM_ARM_VGIC_V3_ITS
>> select KVM_ARM_PMU if HW_PERF_EVENTS
>> select HAVE_KVM_MSI
>> select HAVE_KVM_IRQCHIP
>> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
>> index 5bc4608..e95d4f6 100644
>> --- a/arch/arm64/kvm/reset.c
>> +++ b/arch/arm64/kvm/reset.c
>> @@ -86,12 +86,6 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
>> case KVM_CAP_VCPU_ATTRIBUTES:
>> r = 1;
>> break;
>> - case KVM_CAP_MSI_DEVID:
>> - if (!kvm)
>> - r = -EINVAL;
>> - else
>> - r = kvm->arch.vgic.msis_require_devid;
>> - break;
>> default:
>> r = 0;
>> }
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index ce1f4ed..fbe87a6 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -221,11 +221,9 @@ int kvm_register_vgic_device(unsigned long type)
>> ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
>> KVM_DEV_TYPE_ARM_VGIC_V3);
>>
>> -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
>> if (ret)
>> break;
>> ret = kvm_vgic_register_its_device();
>> -#endif
>> break;
>> }
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> index 0d3c76a..50f42f0 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -42,7 +42,6 @@ u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
>> return reg | ((u64)val << lower);
>> }
>>
>> -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
>> bool vgic_has_its(struct kvm *kvm)
>> {
>> struct vgic_dist *dist = &kvm->arch.vgic;
>> @@ -52,7 +51,6 @@ bool vgic_has_its(struct kvm *kvm)
>>
>> return dist->has_its;
>> }
>> -#endif
>>
>> static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
>> gpa_t addr, unsigned int len)
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index 9d9e014..859f65c 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -84,37 +84,11 @@ static inline void vgic_get_irq_kref(struct vgic_irq *irq)
>> int vgic_v3_map_resources(struct kvm *kvm);
>> int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>>
>> -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
>> int vgic_register_its_iodevs(struct kvm *kvm);
>> bool vgic_has_its(struct kvm *kvm);
>> int kvm_vgic_register_its_device(void);
>> void vgic_enable_lpis(struct kvm_vcpu *vcpu);
>> int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
>> -#else
>> -static inline int vgic_register_its_iodevs(struct kvm *kvm)
>> -{
>> - return -ENODEV;
>> -}
>> -
>> -static inline bool vgic_has_its(struct kvm *kvm)
>> -{
>> - return false;
>> -}
>> -
>> -static inline int kvm_vgic_register_its_device(void)
>> -{
>> - return -ENODEV;
>> -}
>> -
>> -static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
>> -{
>> -}
>> -
>> -static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
>> -{
>> - return -ENODEV;
>> -}
>> -#endif
>>
>> int kvm_register_vgic_device(unsigned long type);
>> int vgic_lazy_init(struct kvm *kvm);
>>
>
^ permalink raw reply
* [PATCH v14 5/9] clocksource/drivers/arm_arch_timer: Simplify ACPI support code.
From: Mark Rutland @ 2016-10-21 11:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021111352.GA16630@leverpostej>
On Fri, Oct 21, 2016 at 12:14:01PM +0100, Mark Rutland wrote:
> On Thu, Oct 20, 2016 at 05:58:17PM +0100, Mark Rutland wrote:
> > On Thu, Sep 29, 2016 at 02:17:13AM +0800, fu.wei at linaro.org wrote:
> > > + arch_timer_ppi[PHYS_NONSECURE_PPI] = acpi_gtdt_map_ppi(PHYS_NONSECURE_PPI);
> > > + arch_timer_ppi[VIRT_PPI] = acpi_gtdt_map_ppi(VIRT_PPI);
> > > + arch_timer_ppi[HYP_PPI] = acpi_gtdt_map_ppi(HYP_PPI);
> > > + /* Always-on capability */
> > > + arch_timer_c3stop = acpi_gtdt_c3stop();
> >
> > ... I think we should check the flag on the relevant interrupt, though
> > that's worth clarifying.
>
> I see I misread the spec; this is part of the common flags.
>
> Please ignore this point; sorry for the noise.
Actually, I misread the spec this time around; the flag *can* differ per
interrupt for the sysreg/cp15 timer, but not for the MMIO timers where
the flag is in a common field.
So please *do* consider the above.
Thanks,
Mark.
^ permalink raw reply
* [PATCH v4 0/3] arm64/mm: use the contiguous attribute for kernel mappings
From: Ard Biesheuvel @ 2016-10-21 11:22 UTC (permalink / raw)
To: linux-arm-kernel
Back to a 3-piece series.
Changes in v4:
- dropped handling of contiguous PUDs and folded PMDs, given that the hardware
is likely to ignore the contiguous bit at this level anyway
- factor out the pte/pmd/pgd attribute BUG check (#1)
Changes in v3 [0]:
- add support for contiguous PMDs for all granule sizes (not just 16k)
- add a separate patch to deal with contiguous PUDs (4k granule only), and
contiguous PMDs for 2 levels of translation (which requires special handling)
- avoid pmd_none/pud_none in the BUG() statements in patch #1, since they
may resolve in unexpected ways with folded PMDs/PUDs
Version v2 [1] addressed the following issues:
- the contiguous attribute is also useful for contigous PMD mappings on 16k
granule kernels (i.e., 1 GB blocks)
- the function parameter 'block_mappings_allowed' does not clearly convey
whether contiguous page mappings should be used, so it is renamed to
'page_mappings_only', and its meaning inverted
- instead of BUGging on changes in the PTE_CONT attribute in PMD or PTE entries
that have been populated already, BUG on any modification except for
permission attributes, which don't require break-before-make when changed.
[0] http://marc.info/?l=linux-arm-kernel&m=147627155206982
[1] http://marc.info/?l=linux-arm-kernel&m=147618975314593
Ard Biesheuvel (3):
arm64: mm: BUG on unsupported manipulations of live kernel mappings
arm64: mm: replace 'block_mappings_allowed' with 'page_mappings_only'
arm64: mm: set the contiguous bit for kernel mappings where
appropriate
arch/arm64/include/asm/mmu.h | 2 +-
arch/arm64/kernel/efi.c | 8 +-
arch/arm64/mm/mmu.c | 134 +++++++++++++-------
3 files changed, 93 insertions(+), 51 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v4 1/3] arm64: mm: BUG on unsupported manipulations of live kernel mappings
From: Ard Biesheuvel @ 2016-10-21 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477048978-4140-1-git-send-email-ard.biesheuvel@linaro.org>
Now that we take care not manipulate the live kernel page tables in a
way that may lead to TLB conflicts, the case where a table mapping is
replaced by a block mapping can no longer occur. So remove the handling
of this at the PUD and PMD levels, and instead, BUG() on any occurrence
of live kernel page table manipulations that modify anything other than
the permission bits.
Since mark_rodata_ro() is the only caller where the kernel mappings that
are being manipulated are actually live, drop the various conditional
flush_tlb_all() invocations, and add a single call to mark_rodata_ro()
instead.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/mm/mmu.c | 70 ++++++++++++--------
1 file changed, 43 insertions(+), 27 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 05615a3fdc6f..27dc0e5012a8 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -28,8 +28,6 @@
#include <linux/memblock.h>
#include <linux/fs.h>
#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/stop_machine.h>
#include <asm/barrier.h>
#include <asm/cputype.h>
@@ -95,6 +93,17 @@ static phys_addr_t __init early_pgtable_alloc(void)
return phys;
}
+static bool pgattr_change_is_safe(u64 old, u64 new)
+{
+ /*
+ * The following mapping attributes may be updated in live
+ * kernel mappings without the need for break-before-make.
+ */
+ static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE;
+
+ return old == 0 || new == 0 || ((old ^ new) & ~mask) == 0;
+}
+
static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
unsigned long end, unsigned long pfn,
pgprot_t prot,
@@ -115,8 +124,17 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
pte = pte_set_fixmap_offset(pmd, addr);
do {
+ pte_t old_pte = *pte;
+
set_pte(pte, pfn_pte(pfn, prot));
pfn++;
+
+ /*
+ * After the PTE entry has been populated once, we
+ * only allow updates to the permission attributes.
+ */
+ BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte)));
+
} while (pte++, addr += PAGE_SIZE, addr != end);
pte_clear_fixmap();
@@ -146,27 +164,27 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
pmd = pmd_set_fixmap_offset(pud, addr);
do {
+ pmd_t old_pmd = *pmd;
+
next = pmd_addr_end(addr, end);
+
/* try section mapping first */
if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
allow_block_mappings) {
- pmd_t old_pmd =*pmd;
pmd_set_huge(pmd, phys, prot);
+
/*
- * Check for previous table entries created during
- * boot (__create_page_tables) and flush them.
+ * After the PMD entry has been populated once, we
+ * only allow updates to the permission attributes.
*/
- if (!pmd_none(old_pmd)) {
- flush_tlb_all();
- if (pmd_table(old_pmd)) {
- phys_addr_t table = pmd_page_paddr(old_pmd);
- if (!WARN_ON_ONCE(slab_is_available()))
- memblock_free(table, PAGE_SIZE);
- }
- }
+ BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd),
+ pmd_val(*pmd)));
} else {
alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
prot, pgtable_alloc);
+
+ BUG_ON(pmd_val(old_pmd) != 0 &&
+ pmd_val(old_pmd) != pmd_val(*pmd));
}
phys += next - addr;
} while (pmd++, addr = next, addr != end);
@@ -204,33 +222,28 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
pud = pud_set_fixmap_offset(pgd, addr);
do {
+ pud_t old_pud = *pud;
+
next = pud_addr_end(addr, end);
/*
* For 4K granule only, attempt to put down a 1GB block
*/
if (use_1G_block(addr, next, phys) && allow_block_mappings) {
- pud_t old_pud = *pud;
pud_set_huge(pud, phys, prot);
/*
- * If we have an old value for a pud, it will
- * be pointing to a pmd table that we no longer
- * need (from swapper_pg_dir).
- *
- * Look up the old pmd table and free it.
+ * After the PUD entry has been populated once, we
+ * only allow updates to the permission attributes.
*/
- if (!pud_none(old_pud)) {
- flush_tlb_all();
- if (pud_table(old_pud)) {
- phys_addr_t table = pud_page_paddr(old_pud);
- if (!WARN_ON_ONCE(slab_is_available()))
- memblock_free(table, PAGE_SIZE);
- }
- }
+ BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
+ pud_val(*pud)));
} else {
alloc_init_pmd(pud, addr, next, phys, prot,
pgtable_alloc, allow_block_mappings);
+
+ BUG_ON(pud_val(old_pud) != 0 &&
+ pud_val(old_pud) != pud_val(*pud));
}
phys += next - addr;
} while (pud++, addr = next, addr != end);
@@ -396,6 +409,9 @@ void mark_rodata_ro(void)
section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
section_size, PAGE_KERNEL_RO);
+
+ /* flush the TLBs after updating live kernel mappings */
+ flush_tlb_all();
}
static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
--
2.7.4
^ permalink raw reply related
* [PATCH v4 2/3] arm64: mm: replace 'block_mappings_allowed' with 'page_mappings_only'
From: Ard Biesheuvel @ 2016-10-21 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477048978-4140-1-git-send-email-ard.biesheuvel@linaro.org>
In preparation of adding support for contiguous PTE and PMD mappings,
let's replace 'block_mappings_allowed' with 'page_mappings_only', which
will be a more accurate description of the nature of the setting once we
add such contiguous mappings into the mix.
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/include/asm/mmu.h | 2 +-
arch/arm64/kernel/efi.c | 8 ++---
arch/arm64/mm/mmu.c | 32 ++++++++++----------
3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 8d9fce037b2f..a81454ad5455 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -34,7 +34,7 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
extern void init_mem_pgprot(void);
extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
- pgprot_t prot, bool allow_block_mappings);
+ pgprot_t prot, bool page_mappings_only);
extern void *fixmap_remap_fdt(phys_addr_t dt_phys);
#endif
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index ba9bee389fd5..5d17f377d905 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -62,8 +62,8 @@ struct screen_info screen_info __section(.data);
int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
pteval_t prot_val = create_mapping_protection(md);
- bool allow_block_mappings = (md->type != EFI_RUNTIME_SERVICES_CODE &&
- md->type != EFI_RUNTIME_SERVICES_DATA);
+ bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE ||
+ md->type == EFI_RUNTIME_SERVICES_DATA);
if (!PAGE_ALIGNED(md->phys_addr) ||
!PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT)) {
@@ -76,12 +76,12 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
* from the MMU routines. So avoid block mappings altogether in
* that case.
*/
- allow_block_mappings = false;
+ page_mappings_only = true;
}
create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
md->num_pages << EFI_PAGE_SHIFT,
- __pgprot(prot_val | PTE_NG), allow_block_mappings);
+ __pgprot(prot_val | PTE_NG), page_mappings_only);
return 0;
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 27dc0e5012a8..7b0dd07212ae 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -143,7 +143,7 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
phys_addr_t phys, pgprot_t prot,
phys_addr_t (*pgtable_alloc)(void),
- bool allow_block_mappings)
+ bool page_mappings_only)
{
pmd_t *pmd;
unsigned long next;
@@ -170,7 +170,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
/* try section mapping first */
if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
- allow_block_mappings) {
+ !page_mappings_only) {
pmd_set_huge(pmd, phys, prot);
/*
@@ -207,7 +207,7 @@ static inline bool use_1G_block(unsigned long addr, unsigned long next,
static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
phys_addr_t phys, pgprot_t prot,
phys_addr_t (*pgtable_alloc)(void),
- bool allow_block_mappings)
+ bool page_mappings_only)
{
pud_t *pud;
unsigned long next;
@@ -229,7 +229,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
/*
* For 4K granule only, attempt to put down a 1GB block
*/
- if (use_1G_block(addr, next, phys) && allow_block_mappings) {
+ if (use_1G_block(addr, next, phys) && !page_mappings_only) {
pud_set_huge(pud, phys, prot);
/*
@@ -240,7 +240,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
pud_val(*pud)));
} else {
alloc_init_pmd(pud, addr, next, phys, prot,
- pgtable_alloc, allow_block_mappings);
+ pgtable_alloc, page_mappings_only);
BUG_ON(pud_val(old_pud) != 0 &&
pud_val(old_pud) != pud_val(*pud));
@@ -255,7 +255,7 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot,
phys_addr_t (*pgtable_alloc)(void),
- bool allow_block_mappings)
+ bool page_mappings_only)
{
unsigned long addr, length, end, next;
pgd_t *pgd = pgd_offset_raw(pgdir, virt);
@@ -275,7 +275,7 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
do {
next = pgd_addr_end(addr, end);
alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc,
- allow_block_mappings);
+ page_mappings_only);
phys += next - addr;
} while (pgd++, addr = next, addr != end);
}
@@ -304,17 +304,17 @@ static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
&phys, virt);
return;
}
- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, true);
+ __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, false);
}
void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
- pgprot_t prot, bool allow_block_mappings)
+ pgprot_t prot, bool page_mappings_only)
{
BUG_ON(mm == &init_mm);
__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
- pgd_pgtable_alloc, allow_block_mappings);
+ pgd_pgtable_alloc, page_mappings_only);
}
static void create_mapping_late(phys_addr_t phys, unsigned long virt,
@@ -327,7 +327,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
}
__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
- NULL, !debug_pagealloc_enabled());
+ NULL, debug_pagealloc_enabled());
}
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
@@ -345,7 +345,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
__create_pgd_mapping(pgd, start, __phys_to_virt(start),
end - start, PAGE_KERNEL,
early_pgtable_alloc,
- !debug_pagealloc_enabled());
+ debug_pagealloc_enabled());
return;
}
@@ -358,13 +358,13 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
__phys_to_virt(start),
kernel_start - start, PAGE_KERNEL,
early_pgtable_alloc,
- !debug_pagealloc_enabled());
+ debug_pagealloc_enabled());
if (kernel_end < end)
__create_pgd_mapping(pgd, kernel_end,
__phys_to_virt(kernel_end),
end - kernel_end, PAGE_KERNEL,
early_pgtable_alloc,
- !debug_pagealloc_enabled());
+ debug_pagealloc_enabled());
/*
* Map the linear alias of the [_text, __init_begin) interval as
@@ -374,7 +374,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
*/
__create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start),
kernel_end - kernel_start, PAGE_KERNEL_RO,
- early_pgtable_alloc, !debug_pagealloc_enabled());
+ early_pgtable_alloc, debug_pagealloc_enabled());
}
static void __init map_mem(pgd_t *pgd)
@@ -424,7 +424,7 @@ static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
BUG_ON(!PAGE_ALIGNED(size));
__create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot,
- early_pgtable_alloc, !debug_pagealloc_enabled());
+ early_pgtable_alloc, debug_pagealloc_enabled());
vma->addr = va_start;
vma->phys_addr = pa_start;
--
2.7.4
^ permalink raw reply related
* [PATCH v4 3/3] arm64: mm: set the contiguous bit for kernel mappings where appropriate
From: Ard Biesheuvel @ 2016-10-21 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477048978-4140-1-git-send-email-ard.biesheuvel@linaro.org>
Now that we no longer allow live kernel PMDs to be split, it is safe to
start using the contiguous bit for kernel mappings. So set the contiguous
bit in the kernel page mappings for regions whose size and alignment are
suitable for this.
This enables the following contiguous range sizes for the virtual mapping
of the kernel image, and for the linear mapping:
granule size | cont PTE | cont PMD |
-------------+------------+------------+
4 KB | 64 KB | 32 MB |
16 KB | 2 MB | 1 GB* |
64 KB | 2 MB | 16 GB* |
* Only when built for 3 or more levels of translation. This is due to the
fact that a 2 level configuration only consists of PGDs and PTEs, and the
added complexity of dealing with folded PMDs is not justified considering
that 16 GB contiguous ranges are likely to be ignored by the hardware (and
16k/2 levels is a niche configuration)
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/mm/mmu.c | 34 +++++++++++++++++---
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 7b0dd07212ae..dd5f12d0959e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -107,8 +107,10 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
unsigned long end, unsigned long pfn,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(void))
+ phys_addr_t (*pgtable_alloc)(void),
+ bool page_mappings_only)
{
+ pgprot_t __prot = prot;
pte_t *pte;
BUG_ON(pmd_sect(*pmd));
@@ -126,7 +128,18 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
do {
pte_t old_pte = *pte;
- set_pte(pte, pfn_pte(pfn, prot));
+ /*
+ * Set the contiguous bit for the subsequent group of PTEs if
+ * its size and alignment are appropriate.
+ */
+ if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) {
+ if (end - addr >= CONT_PTE_SIZE && !page_mappings_only)
+ __prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+ else
+ __prot = prot;
+ }
+
+ set_pte(pte, pfn_pte(pfn, __prot));
pfn++;
/*
@@ -145,6 +158,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
phys_addr_t (*pgtable_alloc)(void),
bool page_mappings_only)
{
+ pgprot_t __prot = prot;
pmd_t *pmd;
unsigned long next;
@@ -171,7 +185,18 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
/* try section mapping first */
if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
!page_mappings_only) {
- pmd_set_huge(pmd, phys, prot);
+ /*
+ * Set the contiguous bit for the subsequent group of
+ * PMDs if its size and alignment are appropriate.
+ */
+ if (((addr | phys) & ~CONT_PMD_MASK) == 0) {
+ if (end - addr >= CONT_PMD_SIZE)
+ __prot = __pgprot(pgprot_val(prot) |
+ PTE_CONT);
+ else
+ __prot = prot;
+ }
+ pmd_set_huge(pmd, phys, __prot);
/*
* After the PMD entry has been populated once, we
@@ -181,7 +206,8 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
pmd_val(*pmd)));
} else {
alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
- prot, pgtable_alloc);
+ prot, pgtable_alloc,
+ page_mappings_only);
BUG_ON(pmd_val(old_pmd) != 0 &&
pmd_val(old_pmd) != pmd_val(*pmd));
--
2.7.4
^ permalink raw reply related
* [PATCH v14 7/9] clocksource/drivers/arm_arch_timer: Refactor the timer init code to prepare for GTDT
From: Mark Rutland @ 2016-10-21 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475086637-1914-8-git-send-email-fu.wei@linaro.org>
On Thu, Sep 29, 2016 at 02:17:15AM +0800, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> The patch refactor original memory-mapped timer init code:
> (1) extract some subfunction for reusing some common code
> a. get_cnttidr
> b. is_best_frame
> (2) move base address and irq code for arch_timer_mem to
> arch_timer_mem_register
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
> drivers/clocksource/arm_arch_timer.c | 159 +++++++++++++++++++++--------------
> 1 file changed, 96 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index c7b0040..e78095f 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -57,6 +57,7 @@
> static unsigned arch_timers_present __initdata;
>
> static void __iomem *arch_counter_base;
> +static void __iomem *cntctlbase __initdata;
>
> struct arch_timer {
> void __iomem *base;
> @@ -656,15 +657,49 @@ out:
> return err;
> }
>
> -static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq)
> +static int __init arch_timer_mem_register(struct device_node *np, void *frame)
> {
> - int ret;
> - irq_handler_t func;
> + struct device_node *frame_node = NULL;
> struct arch_timer *t;
> + void __iomem *base;
> + irq_handler_t func;
> + unsigned int irq;
> + int ret;
> +
> + if (!frame)
> + return -EINVAL;
Why would we call this without a frame?
> +
> + if (np) {
... or without a node?
> + frame_node = (struct device_node *)frame;
> + base = of_iomap(frame_node, 0);
> + arch_timer_detect_rate(base, np);
... BANG! (we check base too late, below).
Please as Marc requested several versions ago: split the FW parsing
(ACPI and DT) so that happens first, *then* once we have the data in a
common format, use that to drive poking the HW, requesting IRQs, etc,
completely independent of the source.
In patches, do this by:
(1) adding the data structures
(2) splitting the existing DT probing to use them
(3) Adding ACPI functionality atop
> -static int __init arch_timer_mem_init(struct device_node *np)
> +static int __init get_cnttidr(struct device_node *np, u32 *cnttidr)
> {
> - struct device_node *frame, *best_frame = NULL;
> - void __iomem *cntctlbase, *base;
> - unsigned int irq, ret = -EINVAL;
> - u32 cnttidr;
> + if (!cnttidr)
> + return -EINVAL;
> +
> + if (np)
> + cntctlbase = of_iomap(np, 0);
> + else
> + return -EINVAL;
We want to check this for ACPI too, no?
Thanks,
Mark.
^ permalink raw reply
* [PATCH] arm64: fix show_regs fallout from KERN_CONT changes
From: Robin Murphy @ 2016-10-21 11:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476962596-21046-1-git-send-email-mark.rutland@arm.com>
Hi Mark,
On 20/10/16 12:23, Mark Rutland wrote:
> Recently in commit 4bcc595ccd80decb ("printk: reinstate KERN_CONT for
> printing continuation lines"), the behaviour of printk changed w.r.t.
> KERN_CONT. Now, KERN_CONT is mandatory to continue existing lines.
> Without this, prefixes are inserted, making output illegible, e.g.
>
> [ 1007.069010] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
> [ 1007.076329] sp : ffff000008d53ec0
> [ 1007.079606] x29: ffff000008d53ec0 [ 1007.082797] x28: 0000000080c50018
> [ 1007.086160]
> [ 1007.087630] x27: ffff000008e0c7f8 [ 1007.090820] x26: ffff80097631ca00
> [ 1007.094183]
> [ 1007.095653] x25: 0000000000000001 [ 1007.098843] x24: 000000ea68b61cac
> [ 1007.102206]
>
> ... or when dumped with the userpace dmesg tool, which has slightly
> different implicit newline behaviour. e.g.
>
> [ 1007.069010] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
> [ 1007.076329] sp : ffff000008d53ec0
> [ 1007.079606] x29: ffff000008d53ec0
> [ 1007.082797] x28: 0000000080c50018
> [ 1007.086160]
> [ 1007.087630] x27: ffff000008e0c7f8
> [ 1007.090820] x26: ffff80097631ca00
> [ 1007.094183]
> [ 1007.095653] x25: 0000000000000001
> [ 1007.098843] x24: 000000ea68b61cac
> [ 1007.102206]
>
> We can't simply always use KERN_CONT for lines which may or may not be
> continuations. That causes line prefixes (e.g. timestamps) to be
> supressed, and the alignment of all but the first line will be broken.
>
> For even more fun, we can't simply insert some dummy empty-string printk
> calls, as GCC warns for an empty printk string, and even if we pass
> KERN_DEFAULT explcitly to silence the warning, the prefix gets swallowed
> unless there is an additional part to the string.
>
> Instead, we must manually iterate over pairs of registers, which gives
> us the legible output we want in either case, e.g.
>
> [ 169.771790] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
> [ 169.779109] sp : ffff000008d53ec0
> [ 169.782386] x29: ffff000008d53ec0 x28: 0000000080c50018
> [ 169.787650] x27: ffff000008e0c7f8 x26: ffff80097631de00
> [ 169.792913] x25: 0000000000000001 x24: 00000027827b2cf4
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
> arch/arm64/kernel/process.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index ddce61b..3f31cf93 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -187,10 +187,19 @@ void __show_regs(struct pt_regs *regs)
> printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
> regs->pc, lr, regs->pstate);
> printk("sp : %016llx\n", sp);
> - for (i = top_reg; i >= 0; i--) {
> +
> + i = top_reg;
> +
> + while (i >= 0) {
> printk("x%-2d: %016llx ", i, regs->regs[i]);
> - if (i % 2 == 0)
> - printk("\n");
> + i--;
> +
> + if (i % 2 == 0) {
> + pr_cont("x%-2d: %016llx ", i, regs->regs[i]);
> + i--;
> + }
> +
> + pr_cont("\n");
> }
Might it be nicer to simply do this (or thereabouts)?
for (i = top_reg; i > 1; i -= 2)
printk("x%-2d: %016llx x%-2d: %016llx\n", i-1,
regs->regs[i-1], i, regs->regs[i]);
if (i > 0)
printk("x%-2d: %016llx\n", i-1, regs->regs[i-1]);
Robin.
> printk("\n");
> }
>
^ permalink raw reply
* [PATCH] PM / Domains: Restrict "samsung, power-domain" checks to ARCH_EXYNOS
From: Geert Uytterhoeven @ 2016-10-21 11:34 UTC (permalink / raw)
To: linux-arm-kernel
Currently the generic PM Domain code code checks for the presence of
both (generic) "power-domains" and (Samsung Exynos legacy)
"samsung,power-domain" properties in all device tree nodes representing
devices.
There are two issues with this:
1. This imposes a small boot-time penalty on all platforms using DT,
2. Platform-specific checks do not really belong in core framework
code.
While moving the check from platform-agnostic code to Samsung-specific
code is non-trivial, the runtime overhead can be restricted to kernels
including support for 32-bit Samsung Exynos platforms.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
"samsung,power-domain" was only ever used in:
- arch/arm/boot/dts/exynos4415.dtsi: Unused?
- arch/arm/boot/dts/exynos3250.dtsi: CONFIG_ARCH_EXYNOS3
- arch/arm/boot/dts/exynos4.dtsi: CONFIG_ARCH_EXYNOS4
- arch/arm/boot/dts/exynos4x12.dtsi: CONFIG_ARCH_EXYNOS4
exynos4212.dtsi is unused?
- arch/arm/boot/dts/exynos5250.dtsi: CONFIG_ARCH_EXYNOS5
- arch/arm/boot/dts/exynos5420.dtsi: CONFIG_ARCH_EXYNOS5
---
drivers/base/power/domain.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e023066e421547c5..d94d6a4b9b527108 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1853,7 +1853,8 @@ int genpd_dev_pm_attach(struct device *dev)
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
"#power-domain-cells", 0, &pd_args);
if (ret < 0) {
- if (ret != -ENOENT)
+ if (ret != -ENOENT || !IS_ENABLED(CONFIG_ARCH_EXYNOS) ||
+ IS_ENABLED(CONFIG_64BIT))
return ret;
/*
--
1.9.1
^ permalink raw reply related
* [STLinux Kernel] [PATCH v2 1/6] ARM: dts: STiH407: DT fix s/interrupts-names/interrupt-names/
From: Patrice Chotard @ 2016-10-21 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021101156.GA32234@griffinp-ThinkPad-X1-Carbon-2nd>
On 10/21/2016 12:11 PM, Peter Griffin wrote:
> On Fri, 21 Oct 2016, Geert Uytterhoeven wrote:
>
>> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
>> Acked-by: Rob Herring <robh@kernel.org>
>> ---
>> v2:
>> - Add Acked-by.
>> ---
>
> Acked-by: Peter Griffin <peter.griffin@linaro.org>
>
applied with Peter Acked-by
Thanks Geert
^ permalink raw reply
* [PATCH] net: stmmac: Add OXNAS Glue Driver
From: Giuseppe CAVALLARO @ 2016-10-21 11:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGhQ9Vxe8fe8kfF_WY40xdh6YX9TuxQ3-Dd6pBG=AHpLtrHnMA@mail.gmail.com>
Hello
some my minor cents below
On 10/21/2016 12:20 PM, Joachim Eastwood wrote:
> Hi Neil,
>
> On 21 October 2016 at 10:44, Neil Armstrong <narmstrong@baylibre.com> wrote:
>> Add Synopsys Designware MAC Glue layer for the Oxford Semiconductor OX820.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>> .../devicetree/bindings/net/oxnas-dwmac.txt | 44 +++++
>> drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
>> drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
>> drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 219 +++++++++++++++++++++
>> 4 files changed, 275 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/net/oxnas-dwmac.txt
>> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
>>
>> Changes since RFC at https://patchwork.kernel.org/patch/9387257 :
>> - Drop init/exit callbacks
>> - Implement proper remove and PM callback
>> - Call init from probe
>> - Disable/Unprepare clock if stmmac probe fails
>
> <snip>
>
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
>> @@ -0,0 +1,219 @@
>> +/*
>> + * Oxford Semiconductor OXNAS DWMAC glue layer
>> + *
>> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
>> + * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
>> + * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
>> + * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/stmmac.h>
>> +
>> +#include "stmmac_platform.h"
>> +
>> +/* System Control regmap offsets */
>> +#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78
>> +#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100
>> +
>> +/* Control Register */
>> +#define DWMAC_CKEN_RX_IN 14
>> +#define DWMAC_CKEN_RXN_OUT 13
>> +#define DWMAC_CKEN_RX_OUT 12
>> +#define DWMAC_CKEN_TX_IN 10
>> +#define DWMAC_CKEN_TXN_OUT 9
>> +#define DWMAC_CKEN_TX_OUT 8
>> +#define DWMAC_RX_SOURCE 7
>> +#define DWMAC_TX_SOURCE 6
>> +#define DWMAC_LOW_TX_SOURCE 4
>> +#define DWMAC_AUTO_TX_SOURCE 3
>> +#define DWMAC_RGMII 2
>> +#define DWMAC_SIMPLE_MUX 1
>> +#define DWMAC_CKEN_GTX 0
>> +
>> +/* Delay register */
>> +#define DWMAC_TX_VARDELAY_SHIFT 0
>> +#define DWMAC_TXN_VARDELAY_SHIFT 8
>> +#define DWMAC_RX_VARDELAY_SHIFT 16
>> +#define DWMAC_RXN_VARDELAY_SHIFT 24
>> +#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT)
>> +#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT)
>> +#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT)
>> +#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT)
>> +
>> +struct oxnas_dwmac {
>> + struct device *dev;
>> + struct clk *clk;
>> + struct regmap *regmap;
>> +};
>> +
>> +static int oxnas_dwmac_init(struct oxnas_dwmac *dwmac)
>> +{
>> + unsigned int value;
>> + int ret;
>> +
>> + /* Reset HW here before changing the glue configuration */
>> + ret = device_reset(dwmac->dev);
>> + if (ret)
>> + return ret;
>> +
>> + clk_prepare_enable(dwmac->clk);
>
> You might want to check the return value from clk_prepare_enable() as well.
>
>> +
>> + ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
>> + value |= BIT(DWMAC_CKEN_GTX);
>> + /* Use simple mux for 25/125 Mhz clock switching */
>> + value |= BIT(DWMAC_SIMPLE_MUX);
>> + /* set auto switch tx clock source */
>> + value |= BIT(DWMAC_AUTO_TX_SOURCE);
>> + /* enable tx & rx vardelay */
>> + value |= BIT(DWMAC_CKEN_TX_OUT);
>> + value |= BIT(DWMAC_CKEN_TXN_OUT);
>> + value |= BIT(DWMAC_CKEN_TX_IN);
>> + value |= BIT(DWMAC_CKEN_RX_OUT);
>> + value |= BIT(DWMAC_CKEN_RXN_OUT);
>> + value |= BIT(DWMAC_CKEN_RX_IN);
>> + regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
>> +
>> + /* set tx & rx vardelay */
>> + value = DWMAC_TX_VARDELAY(4);
>> + value |= DWMAC_TXN_VARDELAY(2);
>> + value |= DWMAC_RX_VARDELAY(10);
>> + value |= DWMAC_RXN_VARDELAY(8);
>> + regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value);
there is no if condition so, I can suggest you, to hardwire
value with macros instead of computing at runtime:
e.g.
var = DWMAC_VARDELAY where
#define DWMAC_VARDELAY (DWMAC_TX_VARDELAY(4) | ...)
... same for OXNAS_DWMAC_CTRL_REGOFFSET where
BIT(DWMAC_CKEN_ ... ) should be re-organized as macros,
I mean:
#define DWMAC_CKEN_.. BIT(xxx)
>> +
>> + return 0;
>> +}
>> +
>> +static int oxnas_dwmac_probe(struct platform_device *pdev)
>> +{
>> + struct plat_stmmacenet_data *plat_dat;
>> + struct stmmac_resources stmmac_res;
>> + struct device_node *sysctrl;
>> + struct oxnas_dwmac *dwmac;
>> + int ret;
>> +
>> + sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0);
>> + if (!sysctrl) {
>> + dev_err(&pdev->dev, "failed to get sys-ctrl node\n");
>> + return -EINVAL;
>> + }
>> +
>> + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
>> + if (ret)
>> + return ret;
>> +
>> + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
>> + if (IS_ERR(plat_dat))
>> + return PTR_ERR(plat_dat);
>> +
>> + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
>> + if (!dwmac)
>> + return -ENOMEM;
>> +
>> + dwmac->dev = &pdev->dev;
>> + plat_dat->bsp_priv = dwmac;
>> +
>> + dwmac->regmap = syscon_node_to_regmap(sysctrl);
>> + if (IS_ERR(dwmac->regmap)) {
>> + dev_err(&pdev->dev, "failed to have sysctrl regmap\n");
>> + return PTR_ERR(dwmac->regmap);
>> + }
>> +
>> + dwmac->clk = devm_clk_get(&pdev->dev, "gmac");
>> + if (IS_ERR(dwmac->clk))
>> + return PTR_ERR(dwmac->clk);
>> +
>> + ret = oxnas_dwmac_init(dwmac);
>> + if (ret)
>> + return ret;
>> +
>> + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
>> + if (ret)
>> + clk_disable_unprepare(dwmac->clk);
>> +
>> + return ret;
>> +}
>> +
>> +static int oxnas_dwmac_remove(struct platform_device *pdev)
>> +{
>> + struct net_device *ndev = platform_get_drvdata(pdev);
>> + struct stmmac_priv *priv = netdev_priv(ndev);
>> + struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
>
> Instead of this long dance of variables use the get_stmmac_bsp_priv()-helper.
>
> You can take a look at dwmac-meson8b.c for reference.
>
>
>> + int ret = stmmac_dvr_remove(&pdev->dev);
>> +
>> + clk_disable_unprepare(dwmac->clk);
>> +
>> + return ret;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int oxnas_dwmac_suspend(struct device *dev)
>> +{
>> + struct net_device *ndev = dev_get_drvdata(dev);
>> + struct stmmac_priv *priv = netdev_priv(ndev);
>> + struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
>
> get_stmmac_bsp_priv()
>
>
>> + int ret;
>> +
>> + ret = stmmac_suspend(dev);
>> + clk_disable_unprepare(dwmac->clk);
>> +
>> + return ret;
>> +}
>> +
>> +static int oxnas_dwmac_resume(struct device *dev)
>> +{
>> + struct net_device *ndev = dev_get_drvdata(dev);
>> + struct stmmac_priv *priv = netdev_priv(ndev);
>> + struct oxnas_dwmac *dwmac = priv->plat->bsp_priv;
>
> get_stmmac_bsp_priv()
>
>
>> + int ret;
>> +
>> + ret = oxnas_dwmac_init(dwmac);
>> + if (ret)
>> + return ret;
>> +
>> + ret = stmmac_resume(dev);
>> +
>> + return ret;
>> +}
>> +#endif /* CONFIG_PM_SLEEP */
>
> With these changes:
> Acked-by: Joachim Eastwood <manabian@gmail.com>
>
>
> best regards,
> Joachim Eastwood
>
^ permalink raw reply
* [PATCH V7 1/3] tracing: add a possibility of exporting function trace to other places instead of ring buffer only
From: Chunyan Zhang @ 2016-10-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018114418.3445c390@gandalf.local.home>
On 18 October 2016 at 23:44, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Tue, 18 Oct 2016 16:08:58 +0800
> Chunyan Zhang <zhang.chunyan@linaro.org> wrote:
>
>> Currently Function traces can be only exported to ring buffer, this
>> patch added trace_export concept which can process traces and export
>> them to a registered destination as an addition to the current only
>> one output of Ftrace - i.e. ring buffer.
>>
>> In this way, if we want Function traces to be sent to other destination
>> rather than ring buffer only, we just need to register a new trace_export
>> and implement its own .write() function for writing traces to storage.
>>
>> With this patch, only Function trace (trace type is TRACE_FN)
>> is supported.
>
> This is getting better, but I still have some nits.
>
Thanks.
>>
>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>
>> ---
>> include/linux/trace.h | 28 +++++++++++
>> kernel/trace/trace.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 159 insertions(+), 1 deletion(-)
>> create mode 100644 include/linux/trace.h
>>
>> diff --git a/include/linux/trace.h b/include/linux/trace.h
>> new file mode 100644
>> index 0000000..eb1c5b8
>> --- /dev/null
>> +++ b/include/linux/trace.h
>> @@ -0,0 +1,28 @@
>> +#ifndef _LINUX_TRACE_H
>> +#define _LINUX_TRACE_H
>> +
>> +#ifdef CONFIG_TRACING
>> +/*
>> + * The trace export - an export of Ftrace output. The trace_export
>> + * can process traces and export them to a registered destination as
>> + * an addition to the current only output of Ftrace - i.e. ring buffer.
>> + *
>> + * If you want traces to be sent to some other place rather than ring
>> + * buffer only, just need to register a new trace_export and implement
>> + * its own .write() function for writing traces to the storage.
>> + *
>> + * next - pointer to the next trace_export
>> + * write - copy traces which have been delt with ->commit() to
>> + * the destination
>> + */
>> +struct trace_export {
>> + struct trace_export __rcu *next;
>> + void (*write)(const char *, unsigned int);
>
> Why const char*? Why not const void *? This will never be a string.
>
Will revise this.
>
>> +};
>> +
>> +int register_ftrace_export(struct trace_export *export);
>> +int unregister_ftrace_export(struct trace_export *export);
>> +
>> +#endif /* CONFIG_TRACING */
>> +
>> +#endif /* _LINUX_TRACE_H */
>> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
>> index 8696ce6..db94ec1 100644
>> --- a/kernel/trace/trace.c
>> +++ b/kernel/trace/trace.c
>> @@ -40,6 +40,7 @@
>> #include <linux/poll.h>
>> #include <linux/nmi.h>
>> #include <linux/fs.h>
>> +#include <linux/trace.h>
>> #include <linux/sched/rt.h>
>>
>> #include "trace.h"
>> @@ -2128,6 +2129,132 @@ void trace_buffer_unlock_commit_regs(struct trace_array *tr,
>> ftrace_trace_userstack(buffer, flags, pc);
>> }
>>
>> +static void
>> +trace_process_export(struct trace_export *export,
>> + struct ring_buffer_event *event)
>> +{
>> + struct trace_entry *entry;
>> + unsigned int size = 0;
>> +
>> + entry = ring_buffer_event_data(event);
>> +
>> + size = ring_buffer_event_length(event);
>> +
>> + if (export->write)
>> + export->write((char *)entry, size);
>
> Is there ever going to be a time where export->write wont be set?
There hasn't been since only one trace_export (i.e. stm_ftrace) was
added in this patch-set , I just wanted to make sure the write() has
been set before registering trace_export like what I added in 2/3 of
this series.
>
> And if there is, this can be racy. As in
>
>
> CPU 0: CPU 1:
> ------ ------
> if (export->write)
>
> export->write = NULL;
Is there going to be this kind of use case? Why some one needs to
change export->write() rather than register a new trace_export?
I probably haven't understood your point thoroughly, please correct me
if my guess was wrong.
Thanks for the review,
Chunyan
>
> export->write(entry, size);
>
> BOOM!
>
>
> -- Steve
>
>> +}
>> +
>> +static DEFINE_MUTEX(ftrace_export_lock);
>> +
>> +static struct trace_export __rcu *ftrace_exports_list __read_mostly;
>> +
>> +static DEFINE_STATIC_KEY_FALSE(ftrace_exports_enabled);
>> +
>> +static inline void ftrace_exports_enable(void)
>> +{
>> + static_branch_enable(&ftrace_exports_enabled);
>> +}
>> +
>> +static inline void ftrace_exports_disable(void)
>> +{
>> + static_branch_disable(&ftrace_exports_enabled);
>> +}
>> +
>> +void ftrace_exports(struct ring_buffer_event *event)
>> +{
>> + struct trace_export *export;
>> +
>> + preempt_disable_notrace();
>> +
>> + export = rcu_dereference_raw_notrace(ftrace_exports_list);
>> + while (export) {
>> + trace_process_export(export, event);
>> + export = rcu_dereference_raw_notrace(export->next);
>> + }
>> +
>> + preempt_enable_notrace();
>> +}
>> +
>> +static inline void
>> +add_trace_export(struct trace_export **list, struct trace_export *export)
>> +{
>> + rcu_assign_pointer(export->next, *list);
>> + /*
>> + * We are entering export into the list but another
>> + * CPU might be walking that list. We need to make sure
>> + * the export->next pointer is valid before another CPU sees
>> + * the export pointer included into the list.
>> + */
>> + rcu_assign_pointer(*list, export);
>> +}
>> +
>> +static inline int
>> +rm_trace_export(struct trace_export **list, struct trace_export *export)
>> +{
>> + struct trace_export **p;
>> +
>> + for (p = list; *p != NULL; p = &(*p)->next)
>> + if (*p == export)
>> + break;
>> +
>> + if (*p != export)
>> + return -1;
>> +
>> + rcu_assign_pointer(*p, (*p)->next);
>> +
>> + return 0;
>> +}
>> +
>> +static inline void
>> +add_ftrace_export(struct trace_export **list, struct trace_export *export)
>> +{
>> + if (*list == NULL)
>> + ftrace_exports_enable();
>> +
>> + add_trace_export(list, export);
>> +}
>> +
>> +static inline int
>> +rm_ftrace_export(struct trace_export **list, struct trace_export *export)
>> +{
>> + int ret;
>> +
>> + ret = rm_trace_export(list, export);
>> + if (*list == NULL)
>> + ftrace_exports_disable();
>> +
>> + return ret;
>> +}
>> +
>> +int register_ftrace_export(struct trace_export *export)
>> +{
>> + if (WARN_ON_ONCE(!export->write))
>> + return -1;
>> +
>> + mutex_lock(&ftrace_export_lock);
>> +
>> + add_ftrace_export(&ftrace_exports_list, export);
>> +
>> + mutex_unlock(&ftrace_export_lock);
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(register_ftrace_export);
>> +
>> +int unregister_ftrace_export(struct trace_export *export)
>> +{
>> + int ret;
>> +
>> + mutex_lock(&ftrace_export_lock);
>> +
>> + ret = rm_ftrace_export(&ftrace_exports_list, export);
>> +
>> + mutex_unlock(&ftrace_export_lock);
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(unregister_ftrace_export);
>> +
>> void
>> trace_function(struct trace_array *tr,
>> unsigned long ip, unsigned long parent_ip, unsigned long flags,
>> @@ -2146,8 +2273,11 @@ trace_function(struct trace_array *tr,
>> entry->ip = ip;
>> entry->parent_ip = parent_ip;
>>
>> - if (!call_filter_check_discard(call, entry, buffer, event))
>> + if (!call_filter_check_discard(call, entry, buffer, event)) {
>> + if (static_branch_unlikely(&ftrace_exports_enabled))
>> + ftrace_exports(event);
>> __buffer_unlock_commit(buffer, event);
>> + }
>> }
>>
>> #ifdef CONFIG_STACKTRACE
>
^ permalink raw reply
* [PATCH V7 2/3] stm class: ftrace: Add ftrace-export-over-stm driver
From: Chunyan Zhang @ 2016-10-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018122928.0c9449a4@gandalf.local.home>
On 19 October 2016 at 00:29, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Tue, 18 Oct 2016 16:08:59 +0800
> Chunyan Zhang <zhang.chunyan@linaro.org> wrote:
>
>> This patch adds a driver that models itself as an stm_source called
>> stm_ftrace. Once the stm device and stm_ftrace have been linked via
>> sysfs, the driver registers itself as a trace_export and everything
>> passed to the interface from Ftrace subsystem will end up in the STM
>> trace engine.
>>
>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>
>> ---
>> drivers/hwtracing/stm/Kconfig | 11 ++++++
>> drivers/hwtracing/stm/Makefile | 2 +
>> drivers/hwtracing/stm/ftrace.c | 88 ++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 101 insertions(+)
>> create mode 100644 drivers/hwtracing/stm/ftrace.c
>>
>> diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
>> index 847a39b..b34ea96 100644
>> --- a/drivers/hwtracing/stm/Kconfig
>> +++ b/drivers/hwtracing/stm/Kconfig
>> @@ -39,4 +39,15 @@ config STM_SOURCE_HEARTBEAT
>> If you want to send heartbeat messages over STM devices,
>> say Y.
>>
>> +config STM_SOURCE_FTRACE
>> + tristate "Copy the output from kernel Ftrace to STM engine"
>> + depends on TRACING
>
> I think it should depend on FUNCTION_TRACER
I think we should support other type of tracer in the future, but
you're right it only should depend on FUNCTION_TRACER for now, I will
revise this.
>
>> + help
>> + This option can be used to copy the output from kernel Ftrace
>> + to STM engine. Enabling this option will introduce a slight
>> + timing effect.
>> +
>> + If you want to send kernel Ftrace messages over STM devices,
>> + say Y.
>> +
>> endif
>> diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
>> index a9ce3d4..3abd84c 100644
>> --- a/drivers/hwtracing/stm/Makefile
>> +++ b/drivers/hwtracing/stm/Makefile
>> @@ -6,6 +6,8 @@ obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
>>
>> obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o
>> obj-$(CONFIG_STM_SOURCE_HEARTBEAT) += stm_heartbeat.o
>> +obj-$(CONFIG_STM_SOURCE_FTRACE) += stm_ftrace.o
>>
>> stm_console-y := console.o
>> stm_heartbeat-y := heartbeat.o
>> +stm_ftrace-y := ftrace.o
>> diff --git a/drivers/hwtracing/stm/ftrace.c b/drivers/hwtracing/stm/ftrace.c
>> new file mode 100644
>> index 0000000..1a114c8f
>> --- /dev/null
>> +++ b/drivers/hwtracing/stm/ftrace.c
>> @@ -0,0 +1,88 @@
>> +/*
>> + * Simple kernel driver to link kernel Ftrace and an STM device
>> + * Copyright (c) 2016, Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + *
>> + * STM Ftrace will be registered as a trace_export.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/stm.h>
>> +#include <linux/trace.h>
>> +
>> +#define STM_FTRACE_NR_CHANNELS 1
>> +#define STM_FTRACE_CHAN 0
>> +
>> +static int stm_ftrace_link(struct stm_source_data *data);
>> +static void stm_ftrace_unlink(struct stm_source_data *data);
>> +
>> +static struct stm_ftrace {
>> + struct stm_source_data data;
>> + struct trace_export ftrace;
>> +} stm_ftrace = {
>> + .data = {
>> + .name = "ftrace",
>> + .nr_chans = STM_FTRACE_NR_CHANNELS,
>> + .link = stm_ftrace_link,
>> + .unlink = stm_ftrace_unlink,
>> + },
>> +};
>> +
>> +/**
>> + * stm_ftrace_write() - write data to STM via 'stm_ftrace' source
>> + * @buf: buffer containing the data packet
>> + * @len: length of the data packet
>> + */
>> +static void notrace
>> +stm_ftrace_write(const char *buf, unsigned int len)
>> +{
>> + stm_source_write(&stm_ftrace.data, STM_FTRACE_CHAN, buf, len);
>> +}
>> +
>> +static int stm_ftrace_link(struct stm_source_data *data)
>> +{
>> + struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
>> +
>> + sf->ftrace.write = stm_ftrace_write;
>> + sf->ftrace.next = NULL;
>
> Why setting this to NULL? register_ftrace_export() should not require
> nor depend on that.
Right, it's not required indeed, will remove it.
Thanks,
Chunyan
>
> -- Steve
>
>> +
>> + return register_ftrace_export(&sf->ftrace);
>> +}
>> +
>> +static void stm_ftrace_unlink(struct stm_source_data *data)
>> +{
>> + struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
>> +
>> + unregister_ftrace_export(&sf->ftrace);
>> +}
>> +
>> +static int __init stm_ftrace_init(void)
>> +{
>> + int ret;
>> +
>> + ret = stm_source_register_device(NULL, &stm_ftrace.data);
>> + if (ret)
>> + pr_err("Failed to register stm_source - ftrace.\n");
>> +
>> + return ret;
>> +}
>> +
>> +static void __exit stm_ftrace_exit(void)
>> +{
>> + stm_source_unregister_device(&stm_ftrace.data);
>> +}
>> +
>> +module_init(stm_ftrace_init);
>> +module_exit(stm_ftrace_exit);
>> +
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_DESCRIPTION("stm_ftrace driver");
>> +MODULE_AUTHOR("Chunyan Zhang <zhang.chunyan@linaro.org>");
>
^ permalink raw reply
* [PATCH] ARM: sti: stih407-clocks: Identify critical clocks
From: Patrice Chotard @ 2016-10-21 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477040891-31611-1-git-send-email-peter.griffin@linaro.org>
On 10/21/2016 11:08 AM, Peter Griffin wrote:
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover is to restart the board(s). This driver takes
> references to clocks which are required to be always-on. The Common
> Clk Framework will then take references to them. This way they will
> not be turned off during the clk_disabled_unused() procedure.
>
> In this patch we are identifying clocks, which if gated would render
> the STiH407 development board unserviceable.
>
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
> arch/arm/boot/dts/stih407-clock.dtsi | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/stih407-clock.dtsi
> index 13029c0..34c119a 100644
> --- a/arch/arm/boot/dts/stih407-clock.dtsi
> +++ b/arch/arm/boot/dts/stih407-clock.dtsi
> @@ -101,6 +101,7 @@
> clocks = <&clk_sysin>;
>
> clock-output-names = "clk-s-a0-pll-ofd-0";
> + clock-critical = <0>; /* clk-s-a0-pll-ofd-0 */
> };
>
> clk_s_a0_flexgen: clk-s-a0-flexgen {
> @@ -112,6 +113,7 @@
> <&clk_sysin>;
>
> clock-output-names = "clk-ic-lmi0";
> + clock-critical = <CLK_IC_LMI0>;
> };
> };
>
> @@ -126,6 +128,7 @@
> "clk-s-c0-fs0-ch1",
> "clk-s-c0-fs0-ch2",
> "clk-s-c0-fs0-ch3";
> + clock-critical = <0>; /* clk-s-c0-fs0-ch0 */
> };
>
> clk_s_c0: clockgen-c at 09103000 {
> @@ -139,6 +142,7 @@
> clocks = <&clk_sysin>;
>
> clock-output-names = "clk-s-c0-pll0-odf-0";
> + clock-critical = <0>; /* clk-s-c0-pll0-odf-0 */
> };
>
> clk_s_c0_pll1: clk-s-c0-pll1 {
> @@ -194,6 +198,12 @@
> "clk-main-disp",
> "clk-aux-disp",
> "clk-compo-dvp";
> + clock-critical = <CLK_PROC_STFE>,
> + <CLK_ICN_CPU>,
> + <CLK_TX_ICN_DMU>,
> + <CLK_EXT2F_A9>,
> + <CLK_ICN_LMI>,
> + <CLK_ICN_SBC>;
> };
> };
>
>
Acked-by: Patrice Chotard <patrice.chotard@st.com>
And applied !
Effectively, the job was done for STiH410 but i forgot to apply the same for STiH407
Thanks Peter ;-)
^ permalink raw reply
* [PATCH] [media] c8sectpfe: Remove clk_disable_unprepare hacks
From: Patrice Chotard @ 2016-10-21 12:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477040132-31442-1-git-send-email-peter.griffin@linaro.org>
On 10/21/2016 10:55 AM, Peter Griffin wrote:
> Now that CLK_PROC_STFE is defined as a critical clock in
> DT, we can remove the commented clk_disable_unprepare from
> the c8sectpfe driver. This means we now have balanced
> clk*enable/disable calls in the driver, but on STiH407
> family the clock in reality will never actually be disabled.
>
> This is due to a HW bug where once the IP has been configured
> and the SLIM core is running, disabling the clock causes a
> unrecoverable bus lockup.
>
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
> drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 6 +-----
> 1 file changed, 1 insertion(+), 5 deletions(-)
>
> diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
> index 30c148b..79d793b 100644
> --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
> +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
> @@ -888,8 +888,7 @@ static int c8sectpfe_probe(struct platform_device *pdev)
> return 0;
>
> err_clk_disable:
> - /* TODO uncomment when upstream has taken a reference on this clk */
> - /*clk_disable_unprepare(fei->c8sectpfeclk);*/
> + clk_disable_unprepare(fei->c8sectpfeclk);
> return ret;
> }
>
> @@ -924,11 +923,8 @@ static int c8sectpfe_remove(struct platform_device *pdev)
> if (readl(fei->io + SYS_OTHER_CLKEN))
> writel(0, fei->io + SYS_OTHER_CLKEN);
>
> - /* TODO uncomment when upstream has taken a reference on this clk */
> - /*
> if (fei->c8sectpfeclk)
> clk_disable_unprepare(fei->c8sectpfeclk);
> - */
>
> return 0;
> }
>
Acked-by: Patrice Chotard <patrice.chotard@st.com>
^ permalink raw reply
* [PATCH] PM / Domains: Restrict "samsung, power-domain" checks to ARCH_EXYNOS
From: Rafael J. Wysocki @ 2016-10-21 12:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477049656-27535-1-git-send-email-geert+renesas@glider.be>
On Fri, Oct 21, 2016 at 1:34 PM, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> Currently the generic PM Domain code code checks for the presence of
> both (generic) "power-domains" and (Samsung Exynos legacy)
> "samsung,power-domain" properties in all device tree nodes representing
> devices.
>
> There are two issues with this:
> 1. This imposes a small boot-time penalty on all platforms using DT,
> 2. Platform-specific checks do not really belong in core framework
> code.
>
> While moving the check from platform-agnostic code to Samsung-specific
> code is non-trivial, the runtime overhead can be restricted to kernels
> including support for 32-bit Samsung Exynos platforms.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> "samsung,power-domain" was only ever used in:
> - arch/arm/boot/dts/exynos4415.dtsi: Unused?
> - arch/arm/boot/dts/exynos3250.dtsi: CONFIG_ARCH_EXYNOS3
> - arch/arm/boot/dts/exynos4.dtsi: CONFIG_ARCH_EXYNOS4
> - arch/arm/boot/dts/exynos4x12.dtsi: CONFIG_ARCH_EXYNOS4
> exynos4212.dtsi is unused?
> - arch/arm/boot/dts/exynos5250.dtsi: CONFIG_ARCH_EXYNOS5
> - arch/arm/boot/dts/exynos5420.dtsi: CONFIG_ARCH_EXYNOS5
> ---
> drivers/base/power/domain.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index e023066e421547c5..d94d6a4b9b527108 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -1853,7 +1853,8 @@ int genpd_dev_pm_attach(struct device *dev)
> ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
> "#power-domain-cells", 0, &pd_args);
> if (ret < 0) {
> - if (ret != -ENOENT)
> + if (ret != -ENOENT || !IS_ENABLED(CONFIG_ARCH_EXYNOS) ||
Please don't check things like CONFIG_ARCH_EXYNOS in the core.
If you need to put checks like that here, there is a design problem somewhere.
And imagine someone 5 years ahead from now looking at this code and
wondering why on Earth the check is here.
> + IS_ENABLED(CONFIG_64BIT))
> return ret;
>
> /*
> --
Thanks,
Rafael
^ permalink raw reply
* [PATCH 0/3] clk: keystone: add sci clock support
From: Tero Kristo @ 2016-10-21 12:45 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
Version 3 has following changes compared to v2 [1]:
- rebased on top of 4.9-rc1
- dropped some of the controversial DT properties like ti,ssc-clocks etc.
- driver now registers all the SCI clocks during probe time, for this,
there is an array built-in to the driver with knowledge of valid clocks
for the device
- xlate only picks up the clocks registered during probe
This series depends on the base SCI protocol support series [2]
and the TI-SCI generic PM domain support series for the device
ID include file [3].
Quick boot test seems to be fine.
-Tero
[1] http://www.spinics.net/lists/devicetree/msg141319.html
[2] http://www.spinics.net/lists/devicetree/msg146621.html
[3] http://www.spinics.net/lists/arm-kernel/msg536851.html
Tero Kristo (3):
Documentation: dt: Add TI SCI clock driver
dt-binding: clock: Add k2g clock definitions
clk: keystone: Add sci-clk driver support
.../devicetree/bindings/clock/ti,sci-clk.txt | 37 ++
MAINTAINERS | 3 +
drivers/clk/Kconfig | 9 +
drivers/clk/keystone/Makefile | 1 +
drivers/clk/keystone/sci-clk.c | 589 +++++++++++++++++++++
include/dt-bindings/clock/k2g.h | 234 ++++++++
6 files changed, 873 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti,sci-clk.txt
create mode 100644 drivers/clk/keystone/sci-clk.c
create mode 100644 include/dt-bindings/clock/k2g.h
--
1.9.1
^ permalink raw reply
* [PATCH 1/3] Documentation: dt: Add TI SCI clock driver
From: Tero Kristo @ 2016-10-21 12:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477053961-27128-1-git-send-email-t-kristo@ti.com>
Add a clock implementation, TI SCI clock, that will hook to the common
clock framework, and allow each clock to be controlled via TI SCI
protocol.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
.../devicetree/bindings/clock/ti,sci-clk.txt | 37 ++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti,sci-clk.txt
diff --git a/Documentation/devicetree/bindings/clock/ti,sci-clk.txt b/Documentation/devicetree/bindings/clock/ti,sci-clk.txt
new file mode 100644
index 0000000..bfc3ca4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,sci-clk.txt
@@ -0,0 +1,37 @@
+Texas Instruments TI-SCI Clocks
+===============================
+
+All clocks on Texas Instruments' SoCs that contain a System Controller,
+are only controlled by this entity. Communication between a host processor
+running an OS and the System Controller happens through a protocol known
+as TI-SCI[1]. This clock implementation plugs into the common clock
+framework and makes use of the TI-SCI protocol on clock API requests.
+
+[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+
+Required properties:
+-------------------
+- compatible: Must be "ti,k2g-sci-clk"
+- #clock-cells: Shall be 2.
+ In clock consumers, this cell represents the device ID and clock ID
+ exposed by the PM firmware. The assignments can be found in the header
+ files <dt-bindings/genpd/<soc>.h> (which covers the device IDs) and
+ <dt-bindings/clock/<soc>.h> (which covers the clock IDs), where <soc>
+ is the SoC involved, for example 'k2g'.
+
+Examples:
+--------
+
+pmmc: pmmc {
+ compatible = "ti,k2g-sci";
+
+ k2g_clks: k2g_clks {
+ compatible = "ti,k2g-sci-clk";
+ #clock-cells = <2>;
+ };
+};
+
+uart0: serial at 2530c00 {
+ compatible = "ns16550a";
+ clocks = <&k2g_clks K2G_DEV_UART0 0>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 3eaac5ed..3ee7c7a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11895,6 +11895,7 @@ F: include/linux/soc/ti/ti_sci_protocol.h
F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
F: include/dt-bindings/genpd/k2g.h
F: drivers/soc/ti/ti_sci_pm_domains.c
+F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] dt-binding: clock: Add k2g clock definitions
From: Tero Kristo @ 2016-10-21 12:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477053961-27128-1-git-send-email-t-kristo@ti.com>
Add identifiers for the K2G clocks managed by the PMMC.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Tested-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
---
MAINTAINERS | 1 +
include/dt-bindings/clock/k2g.h | 234 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 235 insertions(+)
create mode 100644 include/dt-bindings/clock/k2g.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3ee7c7a..960deb6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11896,6 +11896,7 @@ F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
F: include/dt-bindings/genpd/k2g.h
F: drivers/soc/ti/ti_sci_pm_domains.c
F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
+F: include/dt-bindings/clock/k2g.h
THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/include/dt-bindings/clock/k2g.h b/include/dt-bindings/clock/k2g.h
new file mode 100644
index 0000000..cddffc3
--- /dev/null
+++ b/include/dt-bindings/clock/k2g.h
@@ -0,0 +1,234 @@
+/*
+ * TI K2G SoC clock definitions
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DT_BINDINGS_CLOCK_K2G_H__
+#define __DT_BINDINGS_CLOCK_K2G_H__
+
+/*
+ * The clock IDs listed in this file are describing the clocks at IP's
+ * boundaries. The firmware is not exposing any of the generic clocks
+ * from the system, those are handled internally by the firmware.
+ */
+#define K2G_DEV_PMMC_MPM_VBUS_CLK 0
+#define K2G_DEV_PMMC_MPM_FUNC_32K_CLK 1
+#define K2G_DEV_PMMC_MPM_FUNC_OSC_CLK 2
+#define K2G_DEV_PMMC_MPM_DAP_CLK 3
+
+#define K2G_DEV_MLB_MLB_SYS_CLK 0
+#define K2G_DEV_MLB_MLB_SHB_OCP_CLK 1
+#define K2G_DEV_MLB_MLB_SPB_OCP_CLK 2
+#define K2G_DEV_MLB_MLB_IO_CLK 3
+#define K2G_DEV_MLB_MLBP_IO_CLK 4
+
+#define K2G_DEV_DSS_PI_DSS_OCP_CLK 0
+#define K2G_DEV_DSS_PI_DSS_VP_CLK 1
+
+#define K2G_DEV_MCBSP_VBUS_CLK 0
+#define K2G_DEV_MCBSP_CLKS 1
+#define K2G_DEV_MCBSP_CLKS_PARENT_AUDIO_OSC 2
+#define K2G_DEV_MCBSP_CLKS_PARENT_MLB_IO_CLK 3
+#define K2G_DEV_MCBSP_CLKS_PARENT_MLBP_IO_CLK 4
+#define K2G_DEV_MCBSP_CLKS_PARENT_SYS_OSCCLK 5
+#define K2G_DEV_MCBSP_CLKS_PARENT_XREFCLK 6
+#define K2G_DEV_MCBSP_CLKS_PARENT_UART_PLL 7
+
+#define K2G_DEV_MCASP_VBUS_CLK 0
+#define K2G_DEV_MCASP_AUX_CLK 1
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_AUDIO_OSC 2
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_MLB_IO_CLK 3
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_MLBP_IO_CLK 4
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_SYS_OSCCLK 5
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_XREFCLK 6
+#define K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL 7
+
+#define K2G_DEV_DCAN_VBUS_CLK 0
+#define K2G_DEV_DCAN_CAN_CLK 1
+
+#define K2G_DEV_EMIF_V_CLK 0
+#define K2G_DEV_EMIF_M_CLK 1
+#define K2G_DEV_EMIF_DFT_LOCAL_CLK 2
+#define K2G_DEV_EMIF_PUB_CTL_CLK 3
+#define K2G_DEV_EMIF_PHY_CTL_CLK 4
+#define K2G_DEV_EMIF_VBUSP_CLK 5
+
+#define K2G_DEV_MMCHS_VBUS_CLK 0
+#define K2G_DEV_MMCHS_CLK_ADPI 1
+#define K2G_DEV_MMCHS_CLK32K 2
+
+#define K2G_DEV_GPMC_GPMC_FCLK 0
+
+#define K2G_DEV_ELM_CLK 0
+
+#define K2G_DEV_SPI_VBUSP_CLK 0
+
+#define K2G_DEV_ICSS_VCLK_CLK 0
+#define K2G_DEV_ICSS_CORE_CLK 1
+#define K2G_DEV_ICSS_CORE_CLK_PARENT_ICSS_PLL 2
+#define K2G_DEV_ICSS_CORE_CLK_PARENT_NSS_PLL 3
+#define K2G_DEV_ICSS_UCLK_CLK 4
+#define K2G_DEV_ICSS_IEPCLK_CLK 5
+
+#define K2G_DEV_USB_BUS_CLK 0
+#define K2G_DEV_USB_PHYMMR_CLK 1
+#define K2G_DEV_USB_SUSP_CLK 2
+#define K2G_DEV_USB_REF_CLK 3
+#define K2G_DEV_USB_DFT_ULPI_CLK 4
+#define K2G_DEV_USB_DFT_UTMI_CLK 5
+#define K2G_DEV_USB_CLKCORE 6
+
+#define K2G_DEV_NSS_VCLK 0
+#define K2G_DEV_NSS_SA_UL_CLK 1
+#define K2G_DEV_NSS_SA_UL_X1_CLK 2
+#define K2G_DEV_NSS_ESW_CLK 3
+/*
+ * Mux register is internal to the CPTS, so we must allow NSS to control it.
+ * CPTS_REFCLK_P/N is a direct input to this mux, so ignore it is ignored
+ * in the SoC clock tree.
+ */
+#define K2G_DEV_NSS_CPTS_CHIP_CLK1_2 4
+#define K2G_DEV_NSS_CPTS_CHIP_CLK1_3 5
+#define K2G_DEV_NSS_CPTS_TIMI0 6
+#define K2G_DEV_NSS_CPTS_TIMI1 7
+#define K2G_DEV_NSS_CPTS_NSS_PLL 8
+#define K2G_DEV_NSS_GMII_RFTCLK 9
+#define K2G_DEV_NSS_RGMII_MHZ_5_CLK 10
+#define K2G_DEV_NSS_RGMII_MHZ_50_CLK 11
+#define K2G_DEV_NSS_RGMII_MHZ_250_CLK 12
+#define K2G_DEV_NSS_RMII_MHZ_50_CLK 13
+
+#define K2G_DEV_PCIE_VBUS_CLK 0
+
+#define K2G_DEV_OTP_VBUS_CLK 0
+
+#define K2G_DEV_GPIO_VBUS_CLK 0
+
+#define K2G_DEV_TIMER64_VBUS_CLK 0
+#define K2G_DEV_TIMER64_TINL 1
+#define K2G_DEV_TIMER64_TINL_PARENT_TIMI0 2
+#define K2G_DEV_TIMER64_TINL_PARENT_TIMI1 3
+#define K2G_DEV_TIMER64_TINH 4
+#define K2G_DEV_TIMER64_TINH_PARENT_TIMI0 5
+#define K2G_DEV_TIMER64_TINH_PARENT_TIMI1 6
+#define K2G_DEV_TIMER64_TOUTL 7
+#define K2G_DEV_TIMER64_TOUTH 8
+
+#define K2G_DEV_SEC_MGR_SEC_CLK_PI 0
+
+#define K2G_DEV_MSGMGR_VBUS_CLK 0
+
+#define K2G_DEV_BOOTCFG_VBUS_CLK 0
+
+#define K2G_DEV_ARM_BOOTROM_VBUS_CLK 0
+
+#define K2G_DEV_DSP_BOOTROM_VBUS_CLK 0
+
+#define K2G_DEV_DEBUGSS_VBUSP_CTTBRCLK_CLK 0
+#define K2G_DEV_DEBUGSS_VBUSP_STMD0_CLK 1
+#define K2G_DEV_DEBUGSS_VBUSP_SLAVE_CLK 2
+#define K2G_DEV_DEBUGSS_VBUSP_MASTER_CLK 3
+#define K2G_DEV_DEBUGSS_TCK 4
+#define K2G_DEV_DEBUGSS_CS_TRCEXPT_CLK 5
+#define K2G_DEV_DEBUGSS_DSP_TRACECLK 6
+#define K2G_DEV_DEBUGSS_STMXPT_CLK 7
+
+#define K2G_DEV_UART_CBA_CLK_PI 0
+
+#define K2G_DEV_EHRPWM_VBUS_CLK 0
+
+#define K2G_DEV_EQEP_VBUS_CLK 0
+
+#define K2G_DEV_ECAP_VBUS_CLK 0
+
+#define K2G_DEV_I2C_VBUS_CLK 0
+
+#define K2G_DEV_CP_TRACER_CP_TRACER_CLK 0
+
+#define K2G_DEV_EDMA_TPTC_CLK 0
+#define K2G_DEV_EDMA_TPCC_CLK 1
+
+#define K2G_DEV_SEMAPHORE_VBUS_CLK 0
+
+#define K2G_DEV_INTC_VBUS_CLK 0
+
+#define K2G_DEV_GIC_VBUS_CLK 0
+
+#define K2G_DEV_QSPI_QSPI_CLK 0
+#define K2G_DEV_QSPI_DATA_BUS_CLK 1
+#define K2G_DEV_QSPI_CFG_BUS_CLK 2
+#define K2G_DEV_QSPI_QSPI_CLK_O 3
+#define K2G_DEV_QSPI_QSPI_CLK_I 4
+
+#define K2G_DEV_ARM_64B_COUNTER_CLK_INPUT 0
+#define K2G_DEV_ARM_64B_COUNTER_VBUSP_CLK 1
+
+#define K2G_DEV_TETRIS_CORE_CLK 0
+#define K2G_DEV_TETRIS_SUBSYS_CLK 1
+
+#define K2G_DEV_CGEM_CORE_CLK 0
+#define K2G_DEV_CGEM_TRACE_CLK 1
+
+#define K2G_DEV_MSMC_VBUS_CLK 0
+
+#define K2G_DEV_DFT_SS_VBUS_CLK 0
+#define K2G_DEV_DFT_SS_TCK 1
+
+#define K2G_DEV_CBASS_VBUS_CLK 0
+
+#define K2G_DEV_SMARTREFLEX_SCLK_CLK 0
+#define K2G_DEV_SMARTREFLEX_REFCLK1_CLK 1
+#define K2G_DEV_SMARTREFLEX_TEMPMCLK_CLK 2
+
+#define K2G_DEV_EFUSE_VBUS_CLK 0
+
+/* Outputs from board (inputs to SoC) */
+#define K2G_DEV_BOARD_SYS_OSCIN 0
+#define K2G_DEV_BOARD_SYS_CLK 1
+#define K2G_DEV_BOARD_AUDIO_OSCIN 2
+#define K2G_DEV_BOARD_DDR 3
+#define K2G_DEV_BOARD_MLBCLK 4
+#define K2G_DEV_BOARD_MLBPCLK 5
+#define K2G_DEV_BOARD_XREFCLK 6
+#define K2G_DEV_BOARD_TIMI0 7
+#define K2G_DEV_BOARD_TIMI1 8
+
+/* Inputs to board (outputs from SoC) */
+#define K2G_DEV_BOARD_SYSCLKOUT 10
+#define K2G_DEV_BOARD_OBSCLK 11
+#define K2G_DEV_BOARD_OBSCLK_PARENT_MAIN_PLL 12
+#define K2G_DEV_BOARD_OBSCLK_PARENT_DSS_PLL 13
+#define K2G_DEV_BOARD_OBSCLK_PARENT_ARM_PLL 14
+#define K2G_DEV_BOARD_OBSCLK_PARENT_UART_PLL 15
+#define K2G_DEV_BOARD_OBSCLK_PARENT_ICSS_PLL 16
+#define K2G_DEV_BOARD_OBSCLK_PARENT_DDR_PLL 17
+#define K2G_DEV_BOARD_OBSCLK_PARENT_PLL_CTRL 18
+#define K2G_DEV_BOARD_OBSCLK_PARENT_NSS_PLL 19
+#define K2G_DEV_BOARD_OBSCLK_PARENT_SYSOSC 20
+#define K2G_DEV_BOARD_MII_CLKOUT 21
+#define K2G_DEV_BOARD_TIMO0 22
+#define K2G_DEV_BOARD_TIMO1 23
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_0L 24
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_0H 25
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_1L 26
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_1H 27
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_2L 28
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_2H 29
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_3L 30
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_3H 31
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_4L 32
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_4H 33
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_5L 34
+#define K2G_DEV_BOARD_TIMO_PARENT_TIMER64_5H 35
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH 3/3] clk: keystone: Add sci-clk driver support
From: Tero Kristo @ 2016-10-21 12:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477053961-27128-1-git-send-email-t-kristo@ti.com>
In K2G, the clock handling is done through firmware executing on a
separate core. Linux kernel needs to communicate to the firmware
through TI system control interface to access any power management
related resources, including clocks.
The keystone sci-clk driver does this, by communicating to the
firmware through the TI SCI driver. The driver adds support for
registering clocks through DT, and basic required clock operations
like prepare/get_rate, etc.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
MAINTAINERS | 1 +
drivers/clk/Kconfig | 9 +
drivers/clk/keystone/Makefile | 1 +
drivers/clk/keystone/sci-clk.c | 589 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 600 insertions(+)
create mode 100644 drivers/clk/keystone/sci-clk.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 960deb6..3f51df6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11897,6 +11897,7 @@ F: include/dt-bindings/genpd/k2g.h
F: drivers/soc/ti/ti_sci_pm_domains.c
F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
F: include/dt-bindings/clock/k2g.h
+F: drivers/clk/keystone/sci-clk.c
THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6a8ac04..dce08a7 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -169,6 +169,15 @@ config COMMON_CLK_NXP
---help---
Support for clock providers on NXP platforms.
+config TI_SCI_CLK
+ tristate "TI System Control Interface clock drivers"
+ depends on (TI_SCI_PROTOCOL && COMMON_CLK_KEYSTONE) || COMPILE_TEST
+ default TI_SCI_PROTOCOL
+ ---help---
+ This adds the clock driver support over TI System Control Interface.
+ If you wish to use clock resources from the PMMC firmware, say Y.
+ Otherwise, say N.
+
config COMMON_CLK_PALMAS
tristate "Clock driver for TI Palmas devices"
depends on MFD_PALMAS
diff --git a/drivers/clk/keystone/Makefile b/drivers/clk/keystone/Makefile
index 0477cf6..0e7993d 100644
--- a/drivers/clk/keystone/Makefile
+++ b/drivers/clk/keystone/Makefile
@@ -1 +1,2 @@
obj-y += pll.o gate.o
+obj-$(CONFIG_TI_SCI_CLK) += sci-clk.o
diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c
new file mode 100644
index 0000000..f6af5bd
--- /dev/null
+++ b/drivers/clk/keystone/sci-clk.c
@@ -0,0 +1,589 @@
+/*
+ * SCI Clock driver for keystone based devices
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <dt-bindings/clock/k2g.h>
+#include <dt-bindings/genpd/k2g.h>
+
+#define SCI_CLK_SSC_ENABLE BIT(0)
+#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
+#define SCI_CLK_INPUT_TERMINATION BIT(2)
+
+/**
+ * struct sci_clk_data - TI SCI clock data
+ * @dev: device index
+ * @num_clks: number of clocks for this device
+ * @clocks: clocks array for this device
+ */
+struct sci_clk_data {
+ u16 dev;
+ u16 num_clks;
+ struct clk_hw **clocks;
+};
+
+/**
+ * struct sci_clk_provider - TI SCI clock provider representation
+ * @sci: Handle to the System Control Interface protocol handler
+ * @ops: Pointer to the SCI ops to be used by the clocks
+ * @dev: Device pointer for the clock provider
+ * @clocks: Clock data
+ */
+struct sci_clk_provider {
+ const struct ti_sci_handle *sci;
+ const struct ti_sci_clk_ops *ops;
+ struct device *dev;
+ struct sci_clk_data *clocks;
+};
+
+/**
+ * struct sci_clk - TI SCI clock representation
+ * @hw: Hardware clock cookie for common clock framework
+ * @dev_id: Device index
+ * @clk_id: Clock index
+ * @node: Clocks list link
+ * @provider: Master clock provider
+ * @flags: Flags for the clock
+ */
+struct sci_clk {
+ struct clk_hw hw;
+ u16 dev_id;
+ u8 clk_id;
+ struct list_head node;
+ struct sci_clk_provider *provider;
+ u8 flags;
+};
+
+#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
+
+/**
+ * sci_clk_prepare - Prepare (enable) a TI SCI clock
+ * @hw: clock to prepare
+ *
+ * Prepares a clock to be actively used. Returns the SCI protocol status.
+ */
+static int sci_clk_prepare(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
+ bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
+ bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
+
+ return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
+ clk->clk_id, enable_ssc,
+ allow_freq_change,
+ input_termination);
+}
+
+/**
+ * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
+ * @hw: clock to unprepare
+ *
+ * Un-prepares a clock from active state.
+ */
+static void sci_clk_unprepare(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ int ret;
+
+ ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
+ clk->clk_id);
+ if (ret)
+ dev_err(clk->provider->dev,
+ "unprepare failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+}
+
+/**
+ * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
+ * @hw: clock to check status for
+ *
+ * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
+ * value if clock is enabled, zero otherwise.
+ */
+static int sci_clk_is_prepared(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ bool req_state, current_state;
+ int ret;
+
+ ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
+ clk->clk_id, &req_state,
+ ¤t_state);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ return req_state;
+}
+
+/**
+ * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
+ * @hw: clock to get rate for
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a TI SCI clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ u64 freq;
+ int ret;
+
+ ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
+ clk->clk_id, &freq);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ return (u32)freq;
+}
+
+/**
+ * sci_clk_determine_rate - Determines a clock rate a clock can be set to
+ * @hw: clock to change rate for
+ * @req: requested rate configuration for the clock
+ *
+ * Determines a suitable clock rate and parent for a TI SCI clock.
+ * The parent handling is un-used, as generally the parent clock rates
+ * are not known by the kernel; instead these are internally handled
+ * by the firmware. Returns 0 on success, negative error value on failure.
+ */
+static int sci_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ int ret;
+ u64 new_rate;
+
+ ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
+ clk->dev_id,
+ clk->clk_id,
+ req->min_rate,
+ req->rate,
+ req->max_rate,
+ &new_rate);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "determine-rate failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return ret;
+ }
+
+ req->rate = new_rate;
+
+ return 0;
+}
+
+/**
+ * sci_clk_set_rate - Set rate for a TI SCI clock
+ * @hw: clock to change rate for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the clock parent, not used for TI SCI clocks
+ *
+ * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
+ * protocol status.
+ */
+static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+
+ return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
+ clk->clk_id, rate, rate, rate);
+}
+
+/**
+ * sci_clk_get_parent - Get the current parent of a TI SCI clock
+ * @hw: clock to get parent for
+ *
+ * Returns the index of the currently selected parent for a TI SCI clock.
+ */
+static u8 sci_clk_get_parent(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ u8 parent_id;
+ int ret;
+
+ ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
+ clk->clk_id, &parent_id);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "get-parent failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ return parent_id - clk->clk_id - 1;
+}
+
+/**
+ * sci_clk_set_parent - Set the parent of a TI SCI clock
+ * @hw: clock to set parent for
+ * @index: new parent index for the clock
+ *
+ * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
+ */
+static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+
+ return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
+ clk->clk_id,
+ index + 1 + clk->clk_id);
+}
+
+static const struct clk_ops sci_clk_ops = {
+ .prepare = sci_clk_prepare,
+ .unprepare = sci_clk_unprepare,
+ .is_prepared = sci_clk_is_prepared,
+ .recalc_rate = sci_clk_recalc_rate,
+ .determine_rate = sci_clk_determine_rate,
+ .set_rate = sci_clk_set_rate,
+ .get_parent = sci_clk_get_parent,
+ .set_parent = sci_clk_set_parent,
+};
+
+/**
+ * _sci_clk_get - Gets a handle for an SCI clock
+ * @provider: Handle to SCI clock provider
+ * @dev_id: device ID for the clock to register
+ * @clk_id: clock ID for the clock to register
+ *
+ * Gets a handle to an existing TI SCI hw clock, or builds a new clock
+ * entry and registers it with the common clock framework. Called from
+ * the common clock framework, when a corresponding of_clk_get call is
+ * executed, or recursively from itself when parsing parent clocks.
+ * Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
+ */
+static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
+ u16 dev_id, u8 clk_id)
+{
+ struct clk_init_data init = { NULL };
+ struct sci_clk *sci_clk = NULL;
+ char *name = NULL;
+ char **parent_names = NULL;
+ int i;
+ int ret;
+
+ sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
+ if (!sci_clk)
+ return ERR_PTR(-ENOMEM);
+
+ sci_clk->dev_id = dev_id;
+ sci_clk->clk_id = clk_id;
+ sci_clk->provider = provider;
+
+ ret = provider->ops->get_num_parents(provider->sci, dev_id,
+ clk_id,
+ &init.num_parents);
+ if (ret)
+ goto err;
+
+ name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
+ sci_clk->dev_id, sci_clk->clk_id);
+
+ init.name = name;
+
+ if (init.num_parents < 2)
+ init.num_parents = 0;
+
+ if (init.num_parents) {
+ parent_names = devm_kcalloc(provider->dev, init.num_parents,
+ sizeof(char *), GFP_KERNEL);
+
+ if (!parent_names) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < init.num_parents; i++) {
+ char *parent_name;
+
+ parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
+ dev_name(provider->dev),
+ sci_clk->dev_id,
+ sci_clk->clk_id + 1 + i);
+ if (!parent_name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ parent_names[i] = parent_name;
+ }
+ init.parent_names = (const char * const *)parent_names;
+ }
+
+ init.ops = &sci_clk_ops;
+ sci_clk->hw.init = &init;
+
+ ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
+ if (ret) {
+ dev_err(provider->dev, "failed clk register with %d\n", ret);
+ goto err;
+ }
+ kfree(name);
+
+ return &sci_clk->hw;
+
+err:
+ if (parent_names) {
+ for (i = 0; i < init.num_parents; i++)
+ devm_kfree(provider->dev, parent_names[i]);
+
+ devm_kfree(provider->dev, parent_names);
+ }
+
+ devm_kfree(provider->dev, sci_clk);
+
+ kfree(name);
+
+ return ERR_PTR(ret);
+}
+
+/**
+ * sci_clk_get - Xlate function for getting clock handles
+ * @clkspec: device tree clock specifier
+ * @data: pointer to the clock provider
+ *
+ * Xlate function for retrieving clock TI SCI hw clock handles based on
+ * device tree clock specifier. Called from the common clock framework,
+ * when a corresponding of_clk_get call is executed. Returns a pointer
+ * to the TI SCI hw clock struct, or ERR_PTR value in failure.
+ */
+static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct sci_clk_provider *provider = data;
+ u16 dev_id;
+ u8 clk_id;
+ struct sci_clk_data *clks = provider->clocks;
+
+ if (clkspec->args_count != 2)
+ return ERR_PTR(-EINVAL);
+
+ dev_id = clkspec->args[0];
+ clk_id = clkspec->args[1];
+
+ while (clks->num_clks) {
+ if (clks->dev == dev_id) {
+ if (clk_id >= clks->num_clks)
+ return ERR_PTR(-EINVAL);
+
+ return clks->clocks[clk_id];
+ }
+
+ clks++;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+static int ti_sci_init_clocks(struct sci_clk_provider *p)
+{
+ struct sci_clk_data *data = p->clocks;
+ struct clk_hw *hw;
+ int i;
+
+ while (data->num_clks) {
+ data->clocks = devm_kcalloc(p->dev, data->num_clks,
+ sizeof(struct sci_clk),
+ GFP_KERNEL);
+ if (!data->clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < data->num_clks; i++) {
+ hw = _sci_clk_build(p, data->dev, i);
+ if (!IS_ERR(hw)) {
+ data->clocks[i] = hw;
+ continue;
+ }
+
+ /* Skip any holes in the clock lists */
+ if (PTR_ERR(hw) == -ENODEV)
+ continue;
+
+ return PTR_ERR(hw);
+ }
+ data++;
+ }
+
+ return 0;
+}
+
+static const struct sci_clk_data k2g_clk_data[] = {
+ { .dev = K2G_DEV_PMMC0, .num_clks = K2G_DEV_PMMC_MPM_DAP_CLK + 1 },
+ { .dev = K2G_DEV_MLB0, .num_clks = K2G_DEV_MLB_MLBP_IO_CLK + 1 },
+ { .dev = K2G_DEV_DSS0, .num_clks = K2G_DEV_DSS_PI_DSS_VP_CLK + 1 },
+ { .dev = K2G_DEV_MCBSP0, .num_clks = K2G_DEV_MCBSP_CLKS_PARENT_UART_PLL + 1 },
+ { .dev = K2G_DEV_MCASP0, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
+ { .dev = K2G_DEV_MCASP1, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
+ { .dev = K2G_DEV_MCASP2, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
+ { .dev = K2G_DEV_DCAN0, .num_clks = K2G_DEV_DCAN_CAN_CLK + 1 },
+ { .dev = K2G_DEV_DCAN1, .num_clks = K2G_DEV_DCAN_CAN_CLK + 1 },
+ { .dev = K2G_DEV_EMIF0, .num_clks = K2G_DEV_EMIF_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_MMCHS0, .num_clks = K2G_DEV_MMCHS_CLK32K + 1 },
+ { .dev = K2G_DEV_MMCHS1, .num_clks = K2G_DEV_MMCHS_CLK32K + 1 },
+ { .dev = K2G_DEV_GPMC0, .num_clks = K2G_DEV_GPMC_GPMC_FCLK + 1 },
+ { .dev = K2G_DEV_ELM0, .num_clks = K2G_DEV_ELM_CLK + 1 },
+ { .dev = K2G_DEV_SPI0, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_SPI1, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_SPI2, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_SPI3, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_ICSS0, .num_clks = K2G_DEV_ICSS_IEPCLK_CLK + 1 },
+ { .dev = K2G_DEV_ICSS1, .num_clks = K2G_DEV_ICSS_IEPCLK_CLK + 1 },
+ { .dev = K2G_DEV_USB0, .num_clks = K2G_DEV_USB_CLKCORE + 1 },
+ { .dev = K2G_DEV_USB1, .num_clks = K2G_DEV_USB_CLKCORE + 1 },
+ { .dev = K2G_DEV_NSS0, .num_clks = K2G_DEV_NSS_RMII_MHZ_50_CLK + 1 },
+ { .dev = K2G_DEV_PCIE0, .num_clks = K2G_DEV_PCIE_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_GPIO0, .num_clks = K2G_DEV_GPIO_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_GPIO1, .num_clks = K2G_DEV_GPIO_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_TIMER64_0, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_1, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_2, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_3, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_4, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_5, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_TIMER64_6, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
+ { .dev = K2G_DEV_MSGMGR0, .num_clks = K2G_DEV_MSGMGR_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_BOOTCFG0, .num_clks = K2G_DEV_BOOTCFG_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_ARM_BOOTROM0, .num_clks = K2G_DEV_ARM_BOOTROM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_DSP_BOOTROM0, .num_clks = K2G_DEV_DSP_BOOTROM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_DEBUGSS0, .num_clks = K2G_DEV_DEBUGSS_STMXPT_CLK + 1 },
+ { .dev = K2G_DEV_UART0, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
+ { .dev = K2G_DEV_UART1, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
+ { .dev = K2G_DEV_UART2, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
+ { .dev = K2G_DEV_EHRPWM0, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EHRPWM1, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EHRPWM2, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EHRPWM3, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EHRPWM4, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EHRPWM5, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EQEP0, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EQEP1, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EQEP2, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_ECAP0, .num_clks = K2G_DEV_ECAP_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_ECAP1, .num_clks = K2G_DEV_ECAP_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_I2C0, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_I2C1, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_I2C2, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_EDMA0, .num_clks = K2G_DEV_EDMA_TPCC_CLK + 1 },
+ { .dev = K2G_DEV_SEMAPHORE0, .num_clks = K2G_DEV_SEMAPHORE_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_INTC0, .num_clks = K2G_DEV_INTC_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_GIC0, .num_clks = K2G_DEV_GIC_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_QSPI0, .num_clks = K2G_DEV_QSPI_QSPI_CLK_I + 1 },
+ { .dev = K2G_DEV_ARM_64B_COUNTER0, .num_clks = K2G_DEV_ARM_64B_COUNTER_VBUSP_CLK + 1 },
+ { .dev = K2G_DEV_TETRIS0, .num_clks = K2G_DEV_TETRIS_SUBSYS_CLK + 1 },
+ { .dev = K2G_DEV_CGEM0, .num_clks = K2G_DEV_CGEM_TRACE_CLK + 1 },
+ { .dev = K2G_DEV_MSMC0, .num_clks = K2G_DEV_MSMC_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_CBASS0, .num_clks = K2G_DEV_CBASS_VBUS_CLK + 1 },
+ { .dev = K2G_DEV_BOARD0, .num_clks = K2G_DEV_BOARD_TIMO_PARENT_TIMER64_5H + 1 },
+ { .dev = K2G_DEV_EDMA1, .num_clks = K2G_DEV_EDMA_TPCC_CLK + 1 },
+ { .num_clks = 0 },
+};
+
+static const struct of_device_id ti_sci_clk_of_match[] = {
+ { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
+ { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
+
+/**
+ * ti_sci_clk_probe - Probe function for the TI SCI clock driver
+ * @pdev: platform device pointer to be probed
+ *
+ * Probes the TI SCI clock device. Allocates a new clock provider
+ * and registers this to the common clock framework. Also applies
+ * any required flags to the identified clocks via clock lists
+ * supplied from DT. Returns 0 for success, negative error value
+ * for failure.
+ */
+static int ti_sci_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct sci_clk_provider *provider;
+ const struct ti_sci_handle *handle;
+ struct sci_clk_data *data;
+ int ret;
+
+ data = (struct sci_clk_data *)
+ of_match_node(ti_sci_clk_of_match, np)->data;
+
+ handle = devm_ti_sci_get_handle(dev);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
+ if (!provider)
+ return -ENOMEM;
+
+ provider->clocks = data;
+
+ provider->sci = handle;
+ provider->ops = &handle->ops.clk_ops;
+ provider->dev = dev;
+
+ ti_sci_init_clocks(provider);
+
+ ret = of_clk_add_hw_provider(np, sci_clk_get, provider);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * ti_sci_clk_remove - Remove TI SCI clock device
+ * @pdev: platform device pointer for the device to be removed
+ *
+ * Removes the TI SCI device. Unregisters the clock provider registered
+ * via common clock framework. Any memory allocated for the device will
+ * be free'd silently via the devm framework. Returns 0 always.
+ */
+static int ti_sci_clk_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+
+ return 0;
+}
+
+static struct platform_driver ti_sci_clk_driver = {
+ .probe = ti_sci_clk_probe,
+ .remove = ti_sci_clk_remove,
+ .driver = {
+ .name = "ti-sci-clk",
+ .of_match_table = of_match_ptr(ti_sci_clk_of_match),
+ },
+};
+module_platform_driver(ti_sci_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
+MODULE_AUTHOR("Tero Kristo");
+MODULE_ALIAS("platform:ti-sci-clk");
--
1.9.1
^ permalink raw reply related
* [PATCH] arm64: fix show_regs fallout from KERN_CONT changes
From: Mark Rutland @ 2016-10-21 12:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3a8485da-3f7d-07f8-95db-281e0115494d@arm.com>
Hi,
On Fri, Oct 21, 2016 at 12:34:11PM +0100, Robin Murphy wrote:
> > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> > index ddce61b..3f31cf93 100644
> > --- a/arch/arm64/kernel/process.c
> > +++ b/arch/arm64/kernel/process.c
> > @@ -187,10 +187,19 @@ void __show_regs(struct pt_regs *regs)
> > printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
> > regs->pc, lr, regs->pstate);
> > printk("sp : %016llx\n", sp);
> > - for (i = top_reg; i >= 0; i--) {
> > +
> > + i = top_reg;
> > +
> > + while (i >= 0) {
> > printk("x%-2d: %016llx ", i, regs->regs[i]);
> > - if (i % 2 == 0)
> > - printk("\n");
> > + i--;
> > +
> > + if (i % 2 == 0) {
> > + pr_cont("x%-2d: %016llx ", i, regs->regs[i]);
> > + i--;
> > + }
> > +
> > + pr_cont("\n");
> > }
>
> Might it be nicer to simply do this (or thereabouts)?
I don't think so; top_reg is either 12 (for compat), or 29 (for native),
so for the compat case, with the existing code the first line should be
one register (r12), with r1; r0 on the final line.
> for (i = top_reg; i > 1; i -= 2)
> printk("x%-2d: %016llx x%-2d: %016llx\n", i-1,
> regs->regs[i-1], i, regs->regs[i]);
... whereas here the first line would be two (r12 and r11) ...
> if (i > 0)
> printk("x%-2d: %016llx\n", i-1, regs->regs[i-1]);
... and then r0 on its own.
Perhaps that's fine, but it would differ from the existing behaviour,
and make native and compat noticeably different.
We could try fixing up the first line prior to the loop, but that still
requires duplicating the format string thrice, manipulation of i, etc.
It looks like Will's taken my patch as-is, but if we can clean this up
further it would certainly be nice.
Thanks,
Mark.
^ permalink raw reply
* [PATCH] ahci: use pci_alloc_irq_vectors
From: Christoph Hellwig @ 2016-10-21 12:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020154722.GH22012@rric.localdomain>
Hi Robert,
can you try the latest fixed in the libata tree:
https://git.kernel.org/cgit/linux/kernel/git/tj/libata.git/log/?h=for-4.9-fixes
^ permalink raw reply
* [PATCH v5 3/9] vcodec: mediatek: Add Mediatek V4L2 Video Decoder Driver
From: Mauro Carvalho Chehab @ 2016-10-21 13:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1472818800-22558-4-git-send-email-tiffany.lin@mediatek.com>
Em Fri, 2 Sep 2016 20:19:54 +0800
Tiffany Lin <tiffany.lin@mediatek.com> escreveu:
> Add v4l2 layer decoder driver for MT8173
>
> Signed-off-by: Tiffany Lin <tiffany.lin@mediatek.com>
> +int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
> +{
> + int ret = 0;
> +
> + switch (fourcc) {
> + case V4L2_PIX_FMT_H264:
> + case V4L2_PIX_FMT_VP8:
> + default:
> + return -EINVAL;
> + }
Did you ever test this driver? The above code will *always* return
-EINVAL, with will cause vidioc_vdec_s_fmt() to always fail!
I suspect that what you wanted to do, instead, is:
switch (fourcc) {
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_VP8:
break;
default:
return -EINVAL;
Btw, this patch series has also several issues that were pointed by
checkpatch. Please *always* run checkpatch when submitting your work.
You should take a look at the Kernel documentation about how to
submit patches, at:
https://mchehab.fedorapeople.org/kernel_docs/process/index.html
PS.: this time, I fixed the checkpatch issues for you. So, let me know
if the patch below is OK, and I'll merge it at media upstream,
assuming that the other patches in this series are ok.
--
Thanks,
Mauro
[PATCH] mtk-vcodec: fix some smatch warnings
Fix this bug:
drivers/media/platform/mtk-vcodec/vdec_drv_if.c:38 vdec_if_init() info: ignoring unreachable code.
With is indeed a real problem that prevents the driver to work!
While here, also remove an used var, as reported by smatch:
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c: In function 'mtk_vcodec_init_dec_pm':
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c:29:17: warning: variable 'dev' set but not used [-Wunused-but-set-variable]
struct device *dev;
^~~
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 18182f5676d8..79ca03ac449c 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -26,14 +26,12 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
{
struct device_node *node;
struct platform_device *pdev;
- struct device *dev;
struct mtk_vcodec_pm *pm;
int ret = 0;
pdev = mtkdev->plat_dev;
pm = &mtkdev->pm;
pm->mtkdev = mtkdev;
- dev = &pdev->dev;
node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
if (!node) {
mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 3cb04ef45144..9813b2ffd5fa 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -31,6 +31,7 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
switch (fourcc) {
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_VP8:
+ break;
default:
return -EINVAL;
}
^ permalink raw reply related
* [PATCH 2/3] ARM: convert to generated system call tables
From: Arnd Bergmann @ 2016-10-21 13:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019155325.GR1041@n2100.armlinux.org.uk>
On Wednesday, October 19, 2016 4:53:25 PM CEST Russell King - ARM Linux wrote:
> On Wed, Oct 19, 2016 at 05:30:49PM +0200, Arnd Bergmann wrote:
> > On Tuesday, October 18, 2016 8:31:38 PM CEST Russell King wrote:
> > > Convert ARM to use a similar mechanism to x86 to generate the unistd.h
> > > system call numbers and the various kernel system call tables. This
> > > means that rather than having to edit three places (asm/unistd.h for
> > > the total number of system calls, uapi/asm/unistd.h for the system call
> > > numbers, and arch/arm/kernel/calls.S for the call table) we have only
> > > one place to edit, making the process much more simple.
> > >
> > > The scripts have knowledge of the table padding requirements, so there's
> > > no need to worry about __NR_syscalls not fitting within the immediate
> > > constant field of ALU instructions anymore.
> > >
> > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> >
> > Ah, very nice!
> >
> > I have some vague plans to do something like this for all architectures,
> > so having it done for one of the more complex examples (there are very
> > few architectures with more than one table) simplifies it a lot.
> >
> > The next step is probably to do it for asm-generic/unistd.h, which
> > covers a lot of architectures, and then we can introduce a shared
> > table for all future additions so we only have to add the new calls
> > in one place, and change the scripts so they can merge two input
> > files into one.
>
> Architecture maintainers like to verify that the system call works on
> their architecture before they push it out into the wild; your idea
> effectively bypasses architecture maintainer review and testing, so
> is bad. For something as critical as system call interfaces, that
> step is critical: introducing a new system call across all architectures
> that then fails to work correctly on a particular architecture invites
> userspace to work around the problem, and the brokenness then becomes
> user API which can't be fixed.
I see your point, but I think there are serious issues with the current
approach as well:
- a lot of the less common architectures just don't get updated
in time, out of 22 architectures that don't use asm-generic/unistd.h,
only 12 have pwritev2 in linux-next, and only three have pkey_mprotect
- some architectures that add all syscalls sometimes make a mistake
and forget one, e.g. alpha apparently never added __NR_bpf, but it
did add the later __NR_execveat.
- when glibc updates their minimum supported kernel version, they
would like to drop obsolete syscalls, but when each architecture
adds the calls at a different time, it's hard to tell when a
replacement syscall is guaranteed to be available
- linux-next produces warnings about missing syscalls on most
architectures half of the time since it's impossible for an
arch maintainer to hook up the number before the implementation
is merged
Regarding the review process, I'd really hope we've improved enough
that we can rely on the review on linux-arch/linux-api to catch
all serious issues like system call that cannot be defined the same
way on all architectures. If we fail at this, there is a more
serious issue with the review process.
Since all syscalls now go through SYSCALL_DEFINEx(), we have
covered the hardest part (sign/zero extending short arguments),
and a lot more people are aware of problems with struct alignment
since it differs between i386 and x86_64 and also affects all
ioctl interfaces. I think the last time a syscall made it in that
didn't just work on all architectures was sync_file_range, and
that was nine years ago.
> > > +# Where abi is:
> > > +# common - for system calls shared between oabi and eabi
> > > +# oabi - for oabi-only system calls (may have compat)
> > > +# eabi - for eabi-only system calls
> >
> > Why do we need all three? I would have guessed that these two are
> > sufficient to cover all cases:
> >
> > arm - one entry for eabi, optional second entry for oabi if different
> > oabi - only one entry for oabi, syscall is not used on eabi
>
> You haven't quite understood if you think the second entry gets used
> for OABI - but that's not surprising because the issues here are
> quite complex.
>
> For OABI-only, all the oabi and first entry in common gets used.
> For EABI-only, all the eabi and first entry in common gets used.
> For EABI with OABI compat, EABI uses eabi and the first entry in common,
> but the OABI compat table uses the oabi and common entries, prefering
> the second entry where present.
Got it, I missed the fact that we support native OABI kernels.
> Yes, for the cases where we list the oabi and eabi together like you
> quoted, currently there are no differences between the system calls,
> and in my latest version, they've already been modified down to just
> a single "common" entry, leaving us without any eabi entries.
>
> However, I want to retain the ability to have separate eabi entries
> if needs be. Such a case would be a system call which needs a helper
> for arguments passed in >4 registers on EABI but not OABI (eg, because
> of an non-naturally aligned 64-bit quantity passed in r1/r2 on OABI
> but r2/r3 in EABI.)
If we hit this case, why not just use the wrapper on both EABI
and OABI for simplicity? It's not like we care a lot about
micro-optimizing OABI any more.
> You'll find the latest version in the next linux-next, or my current
> for-next branch.
Ok. After rebasing my randconfig tree on today's linux-next, I needed
this hunk to avoid a warning:
<stdin>:1143:2: error: #warning syscall sync_file_range not implemented [-Werror=cpp]
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index 70558e4459fd..7da1bbe69e56 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -355,7 +355,8 @@
338 common set_robust_list sys_set_robust_list
339 common get_robust_list sys_get_robust_list
340 common splice sys_splice
-341 common arm_sync_file_range sys_sync_file_range2
+341 common sync_file_range2 sys_sync_file_range2
+341 common arm_sync_file_range
342 common tee sys_tee
343 common vmsplice sys_vmsplice
344 common move_pages sys_move_pages
(or alternatively, add "#define sync_file_range2 arm_sync_file_range"
to uapi/asm/unistd.h).
> > > diff --git a/arch/arm/tools/syscallhdr.sh b/arch/arm/tools/syscallhdr.sh
> > > new file mode 100644
> > > index 000000000000..72d4b2e3bdec
> > > --- /dev/null
> > > +++ b/arch/arm/tools/syscallhdr.sh
> >
> > The scripts are still very similar to the x86 version. Any chance
> > we can move them to a top-level scripts/syscall/ directory and make
> > them work for both architectures? It would be good to avoid duplicating
> > them for all the other architectures too, so starting out with a common
> > version could make that easier.
>
> The fileguard prefix would have to be specified as an additional
> argument to achieve that, but I don't see that as a big problem.
Agreed, I saw the same thing there.
> The syscalltbl.sh script is particularly architecture specific, as
> our "compat" isn't the same as x86's "compat" requirements.
That brings up an interesting issue: it would be nice to use the
same input file for arch/arm/ and the compat mode of arch/arm64,
like x86 does. If we handle both oabi and arm64-compat in the same
file, we end up with a superset of what x86 does, and we could
use a single script again, and generate all four tables for
ARM (native OABI, OABI-on-EABI, native EABI, EABI-on-arm64).
Another related case in asm-generic, which defines three tables:
native 32-bit, native 64-bit and compat 32-bit. This one not only
needs to have three different function pointers (e.g. sys_fcntl64,
sys_fcntl and compat_sys_fcntl64) but also different macros (e.g.
__NR_fcntl64 and __NR_fcntl).
Anything wrong with this approach:?
/* ARM */
221 oabi fcntl64 sys_fcntl64 sys_oabi_fcntl64
221 eabi fcntl64 sys_fcntl64 compat_sys_fcntl64
/* asm-generic */
25 32 fcntl64 sys_fcntl64 compat_sys_fcntl64
25 64 fcntl sys_fcntl
> The syscallnr.sh script kind-of looks like a candidate, but it has
> ARM arch specifics to it (knowing that the number of system calls
> needs to fit within the 8-bit value plus 4-bit shift constant
> representation of ARM ALU instructions.) Maybe a generic version
> without that knowledge would work, provided architectures can
> override it.
syscallnr.sh isn't used on x86, and probably won't be needed on
most (or all) others, right?
Generally speaking I'd think that having a check for the ${ARCH}
variable and doing this conditionally in that one script is fine
here, if we need other architecture specific versions, they we can
use case/esac.
Similar checks exist in scripts/recordmcount.pl,
scripts/package/builddeb, scripts/tags.sh etc.
Arnd
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox