* [PATCH v5 06/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
From: Christoffer Dall @ 2017-04-27 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492164934-988-7-git-send-email-eric.auger@redhat.com>
On Fri, Apr 14, 2017 at 12:15:18PM +0200, Eric Auger wrote:
> We need to use those helpers in vgic-its.c so let's
> expose them in the private vgic header.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Christoffer Dall <cdall@linaro.org>
>
> ---
>
> v4 -> v5:
> - Add Marc's A-b
> ---
> virt/kvm/arm/vgic/vgic-kvm-device.c | 4 ++--
> virt/kvm/arm/vgic/vgic.h | 3 +++
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index d181d2b..859bfa8 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -259,13 +259,13 @@ static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx)
> }
> }
>
> -static void unlock_all_vcpus(struct kvm *kvm)
> +void unlock_all_vcpus(struct kvm *kvm)
> {
> unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1);
> }
>
> /* Returns true if all vcpus were locked, false otherwise */
> -static bool lock_all_vcpus(struct kvm *kvm)
> +bool lock_all_vcpus(struct kvm *kvm)
> {
> struct kvm_vcpu *tmp_vcpu;
> int c;
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 6cf557e..b87f1c6 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -184,4 +184,7 @@ int vgic_init(struct kvm *kvm);
> int vgic_debug_init(struct kvm *kvm);
> int vgic_debug_destroy(struct kvm *kvm);
>
> +bool lock_all_vcpus(struct kvm *kvm);
> +void unlock_all_vcpus(struct kvm *kvm);
> +
> #endif
> --
> 2.5.5
>
^ permalink raw reply
* [PATCH v5 05/22] KVM: arm64: vgic-its: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
From: Christoffer Dall @ 2017-04-27 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492164934-988-6-git-send-email-eric.auger@redhat.com>
On Fri, Apr 14, 2017 at 12:15:17PM +0200, Eric Auger wrote:
> The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group which allows the userspace to save/restore ITS registers.
>
> At this stage the get/set/has operations are not yet implemented.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
>
> ---
> v4 -> v5:
> - Add Marc's A-b
>
> v3 -> v4:
> - added Andre's R-b
> ---
> arch/arm/include/uapi/asm/kvm.h | 1 +
> arch/arm64/include/uapi/asm/kvm.h | 1 +
> virt/kvm/arm/vgic/vgic-its.c | 36 +++++++++++++++++++++++++++++++++++-
> 3 files changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index 6ebd3e6..4beb83b 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -192,6 +192,7 @@ struct kvm_arch_memory_slot {
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
> #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
> +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
> #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
> #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
> (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index c286035..7e8dd69 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -212,6 +212,7 @@ struct kvm_arch_memory_slot {
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
> #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
> +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
> #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
> #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
> (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 3ffcbbe..f687e91 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1466,6 +1466,19 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
> kfree(its);
> }
>
> +int vgic_its_has_attr_regs(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +
> +int vgic_its_attr_regs_access(struct kvm_device *dev,
> + struct kvm_device_attr *attr,
> + u64 *reg, bool is_write)
> +{
> + return -ENXIO;
> +}
> +
> static int vgic_its_has_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> @@ -1482,6 +1495,8 @@ static int vgic_its_has_attr(struct kvm_device *dev,
> return 0;
> }
> break;
> + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
> + return vgic_its_has_attr_regs(dev, attr);
> }
> return -ENXIO;
> }
> @@ -1521,6 +1536,15 @@ static int vgic_its_set_attr(struct kvm_device *dev,
> return 0;
> }
> break;
> + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + if (get_user(reg, uaddr))
> + return -EFAULT;
> +
> + return vgic_its_attr_regs_access(dev, attr, ®, true);
> + }
> }
> return -ENXIO;
> }
> @@ -1541,10 +1565,20 @@ static int vgic_its_get_attr(struct kvm_device *dev,
> if (copy_to_user(uaddr, &addr, sizeof(addr)))
> return -EFAULT;
> break;
> + }
> + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> + int ret;
> +
> + ret = vgic_its_attr_regs_access(dev, attr, ®, false);
> + if (ret)
> + return ret;
> + return put_user(reg, uaddr);
> + }
> default:
> return -ENXIO;
> }
> - }
>
> return 0;
> }
> --
> 2.5.5
>
^ permalink raw reply
* [PATCH v5 04/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
From: Christoffer Dall @ 2017-04-27 9:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492164934-988-5-git-send-email-eric.auger@redhat.com>
On Fri, Apr 14, 2017 at 12:15:16PM +0200, Eric Auger wrote:
> We plan to use vgic_find_mmio_region in vgic-its.c so let's
> turn it into a public function.
>
> Also let's take the opportunity to rename the region parameter
> into regions to emphasize this latter is an array of regions.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
>
> ---
> v4 -> v5:
> - add Marc's A-b
>
> v3 -> v4:
> - rename region parameter into regions
> - add Andre's R-b
> ---
> virt/kvm/arm/vgic/vgic-mmio.c | 11 +++++------
> virt/kvm/arm/vgic/vgic-mmio.h | 5 +++++
> 2 files changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 2a5db13..1c17b2a 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -446,13 +446,12 @@ static int match_region(const void *key, const void *elt)
> return 0;
> }
>
> -/* Find the proper register handler entry given a certain address offset. */
> -static const struct vgic_register_region *
> -vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> - unsigned int offset)
> +const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *regions,
> + int nr_regions, unsigned int offset)
> {
> - return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> - sizeof(region[0]), match_region);
> + return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
> + sizeof(regions[0]), match_region);
> }
>
> void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 98bb566..6eec91b 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -192,4 +192,9 @@ u64 vgic_sanitise_shareability(u64 reg);
> u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
> u64 (*sanitise_fn)(u64));
>
> +/* Find the proper register handler entry given a certain address offset */
nit: we don't usually comment the functions in the prototype in the
header files but keep comments with the function implementation.
But I don't care deeply about this.
Acked-by: Christoffer Dall <cdall@linaro.org>
> +const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *regions,
> + int nr_regions, unsigned int offset);
> +
> #endif
> --
> 2.5.5
>
^ permalink raw reply
* [PATCH v5 03/22] KVM: arm/arm64: vgic-its: rename itte into ite
From: Christoffer Dall @ 2017-04-27 9:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492164934-988-4-git-send-email-eric.auger@redhat.com>
On Fri, Apr 14, 2017 at 12:15:15PM +0200, Eric Auger wrote:
> The actual abbreviation for the interrupt translation table entry
> is ITE. Let's rename all itte instances by ite.
Is there really any confusion or problems with using itte? This is a
lot of churn...
Thanks,
-Christoffer
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
>
> ---
>
> v5: Add Marc's A-b
> ---
> virt/kvm/arm/vgic/vgic-its.c | 148 +++++++++++++++++++++----------------------
> 1 file changed, 74 insertions(+), 74 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 8d1da1a..3ffcbbe 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -114,8 +114,8 @@ struct its_collection {
> #define its_is_collection_mapped(coll) ((coll) && \
> ((coll)->target_addr != COLLECTION_NOT_MAPPED))
>
> -struct its_itte {
> - struct list_head itte_list;
> +struct its_ite {
> + struct list_head ite_list;
>
> struct vgic_irq *irq;
> struct its_collection *collection;
> @@ -143,27 +143,27 @@ static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
> * Device ID/Event ID pair on an ITS.
> * Must be called with the its_lock mutex held.
> */
> -static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
> +static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
> u32 event_id)
> {
> struct its_device *device;
> - struct its_itte *itte;
> + struct its_ite *ite;
>
> device = find_its_device(its, device_id);
> if (device == NULL)
> return NULL;
>
> - list_for_each_entry(itte, &device->itt_head, itte_list)
> - if (itte->event_id == event_id)
> - return itte;
> + list_for_each_entry(ite, &device->itt_head, ite_list)
> + if (ite->event_id == event_id)
> + return ite;
>
> return NULL;
> }
>
> /* To be used as an iterator this macro misses the enclosing parentheses */
> -#define for_each_lpi_its(dev, itte, its) \
> +#define for_each_lpi_its(dev, ite, its) \
> list_for_each_entry(dev, &(its)->device_list, dev_list) \
> - list_for_each_entry(itte, &(dev)->itt_head, itte_list)
> + list_for_each_entry(ite, &(dev)->itt_head, ite_list)
>
> /*
> * We only implement 48 bits of PA at the moment, although the ITS
> @@ -270,18 +270,18 @@ static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
> * Needs to be called whenever either the collection for a LPIs has
> * changed or the collection itself got retargeted.
> */
> -static void update_affinity_itte(struct kvm *kvm, struct its_itte *itte)
> +static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
> {
> struct kvm_vcpu *vcpu;
>
> - if (!its_is_collection_mapped(itte->collection))
> + if (!its_is_collection_mapped(ite->collection))
> return;
>
> - vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
> + vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
>
> - spin_lock(&itte->irq->irq_lock);
> - itte->irq->target_vcpu = vcpu;
> - spin_unlock(&itte->irq->irq_lock);
> + spin_lock(&ite->irq->irq_lock);
> + ite->irq->target_vcpu = vcpu;
> + spin_unlock(&ite->irq->irq_lock);
> }
>
> /*
> @@ -292,13 +292,13 @@ static void update_affinity_collection(struct kvm *kvm, struct vgic_its *its,
> struct its_collection *coll)
> {
> struct its_device *device;
> - struct its_itte *itte;
> + struct its_ite *ite;
>
> - for_each_lpi_its(device, itte, its) {
> - if (!itte->collection || coll != itte->collection)
> + for_each_lpi_its(device, ite, its) {
> + if (!ite->collection || coll != ite->collection)
> continue;
>
> - update_affinity_itte(kvm, itte);
> + update_affinity_ite(kvm, ite);
> }
> }
>
> @@ -425,25 +425,25 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
> u32 devid, u32 eventid)
> {
> struct kvm_vcpu *vcpu;
> - struct its_itte *itte;
> + struct its_ite *ite;
>
> if (!its->enabled)
> return -EBUSY;
>
> - itte = find_itte(its, devid, eventid);
> - if (!itte || !its_is_collection_mapped(itte->collection))
> + ite = find_ite(its, devid, eventid);
> + if (!ite || !its_is_collection_mapped(ite->collection))
> return E_ITS_INT_UNMAPPED_INTERRUPT;
>
> - vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
> + vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
> if (!vcpu)
> return E_ITS_INT_UNMAPPED_INTERRUPT;
>
> if (!vcpu->arch.vgic_cpu.lpis_enabled)
> return -EBUSY;
>
> - spin_lock(&itte->irq->irq_lock);
> - itte->irq->pending_latch = true;
> - vgic_queue_irq_unlock(kvm, itte->irq);
> + spin_lock(&ite->irq->irq_lock);
> + ite->irq->pending_latch = true;
> + vgic_queue_irq_unlock(kvm, ite->irq);
>
> return 0;
> }
> @@ -511,15 +511,15 @@ int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
> }
>
> /* Requires the its_lock to be held. */
> -static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
> +static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
> {
> - list_del(&itte->itte_list);
> + list_del(&ite->ite_list);
>
> /* This put matches the get in vgic_add_lpi. */
> - if (itte->irq)
> - vgic_put_irq(kvm, itte->irq);
> + if (ite->irq)
> + vgic_put_irq(kvm, ite->irq);
>
> - kfree(itte);
> + kfree(ite);
> }
>
> static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
> @@ -544,17 +544,17 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
> {
> u32 device_id = its_cmd_get_deviceid(its_cmd);
> u32 event_id = its_cmd_get_id(its_cmd);
> - struct its_itte *itte;
> + struct its_ite *ite;
>
>
> - itte = find_itte(its, device_id, event_id);
> - if (itte && itte->collection) {
> + ite = find_ite(its, device_id, event_id);
> + if (ite && ite->collection) {
> /*
> * Though the spec talks about removing the pending state, we
> * don't bother here since we clear the ITTE anyway and the
> * pending state is a property of the ITTE struct.
> */
> - its_free_itte(kvm, itte);
> + its_free_ite(kvm, ite);
> return 0;
> }
>
> @@ -572,26 +572,26 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
> u32 event_id = its_cmd_get_id(its_cmd);
> u32 coll_id = its_cmd_get_collection(its_cmd);
> struct kvm_vcpu *vcpu;
> - struct its_itte *itte;
> + struct its_ite *ite;
> struct its_collection *collection;
>
> - itte = find_itte(its, device_id, event_id);
> - if (!itte)
> + ite = find_ite(its, device_id, event_id);
> + if (!ite)
> return E_ITS_MOVI_UNMAPPED_INTERRUPT;
>
> - if (!its_is_collection_mapped(itte->collection))
> + if (!its_is_collection_mapped(ite->collection))
> return E_ITS_MOVI_UNMAPPED_COLLECTION;
>
> collection = find_collection(its, coll_id);
> if (!its_is_collection_mapped(collection))
> return E_ITS_MOVI_UNMAPPED_COLLECTION;
>
> - itte->collection = collection;
> + ite->collection = collection;
> vcpu = kvm_get_vcpu(kvm, collection->target_addr);
>
> - spin_lock(&itte->irq->irq_lock);
> - itte->irq->target_vcpu = vcpu;
> - spin_unlock(&itte->irq->irq_lock);
> + spin_lock(&ite->irq->irq_lock);
> + ite->irq->target_vcpu = vcpu;
> + spin_unlock(&ite->irq->irq_lock);
>
> return 0;
> }
> @@ -679,7 +679,7 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
> {
> struct its_collection *collection;
> struct its_device *device;
> - struct its_itte *itte;
> + struct its_ite *ite;
>
> /*
> * Clearing the mapping for that collection ID removes the
> @@ -690,10 +690,10 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
> if (!collection)
> return;
>
> - for_each_lpi_its(device, itte, its)
> - if (itte->collection &&
> - itte->collection->collection_id == coll_id)
> - itte->collection = NULL;
> + for_each_lpi_its(device, ite, its)
> + if (ite->collection &&
> + ite->collection->collection_id == coll_id)
> + ite->collection = NULL;
>
> list_del(&collection->coll_list);
> kfree(collection);
> @@ -709,7 +709,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
> u32 device_id = its_cmd_get_deviceid(its_cmd);
> u32 event_id = its_cmd_get_id(its_cmd);
> u32 coll_id = its_cmd_get_collection(its_cmd);
> - struct its_itte *itte;
> + struct its_ite *ite;
> struct its_device *device;
> struct its_collection *collection, *new_coll = NULL;
> int lpi_nr;
> @@ -728,7 +728,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
> return E_ITS_MAPTI_PHYSICALID_OOR;
>
> /* If there is an existing mapping, behavior is UNPREDICTABLE. */
> - if (find_itte(its, device_id, event_id))
> + if (find_ite(its, device_id, event_id))
> return 0;
>
> collection = find_collection(its, coll_id);
> @@ -739,36 +739,36 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
> new_coll = collection;
> }
>
> - itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
> - if (!itte) {
> + ite = kzalloc(sizeof(struct its_ite), GFP_KERNEL);
> + if (!ite) {
> if (new_coll)
> vgic_its_free_collection(its, coll_id);
> return -ENOMEM;
> }
>
> - itte->event_id = event_id;
> - list_add_tail(&itte->itte_list, &device->itt_head);
> + ite->event_id = event_id;
> + list_add_tail(&ite->ite_list, &device->itt_head);
>
> - itte->collection = collection;
> - itte->lpi = lpi_nr;
> + ite->collection = collection;
> + ite->lpi = lpi_nr;
>
> irq = vgic_add_lpi(kvm, lpi_nr);
> if (IS_ERR(irq)) {
> if (new_coll)
> vgic_its_free_collection(its, coll_id);
> - its_free_itte(kvm, itte);
> + its_free_ite(kvm, ite);
> return PTR_ERR(irq);
> }
> - itte->irq = irq;
> + ite->irq = irq;
>
> - update_affinity_itte(kvm, itte);
> + update_affinity_ite(kvm, ite);
>
> /*
> * We "cache" the configuration table entries in out struct vgic_irq's.
> * However we only have those structs for mapped IRQs, so we read in
> * the respective config data from memory here upon mapping the LPI.
> */
> - update_lpi_config(kvm, itte->irq, NULL);
> + update_lpi_config(kvm, ite->irq, NULL);
>
> return 0;
> }
> @@ -776,15 +776,15 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
> /* Requires the its_lock to be held. */
> static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
> {
> - struct its_itte *itte, *temp;
> + struct its_ite *ite, *temp;
>
> /*
> * The spec says that unmapping a device with still valid
> * ITTEs associated is UNPREDICTABLE. We remove all ITTEs,
> * since we cannot leave the memory unreferenced.
> */
> - list_for_each_entry_safe(itte, temp, &device->itt_head, itte_list)
> - its_free_itte(kvm, itte);
> + list_for_each_entry_safe(ite, temp, &device->itt_head, ite_list)
> + its_free_ite(kvm, ite);
>
> list_del(&device->dev_list);
> kfree(device);
> @@ -883,14 +883,14 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
> {
> u32 device_id = its_cmd_get_deviceid(its_cmd);
> u32 event_id = its_cmd_get_id(its_cmd);
> - struct its_itte *itte;
> + struct its_ite *ite;
>
>
> - itte = find_itte(its, device_id, event_id);
> - if (!itte)
> + ite = find_ite(its, device_id, event_id);
> + if (!ite)
> return E_ITS_CLEAR_UNMAPPED_INTERRUPT;
>
> - itte->irq->pending_latch = false;
> + ite->irq->pending_latch = false;
>
> return 0;
> }
> @@ -904,14 +904,14 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
> {
> u32 device_id = its_cmd_get_deviceid(its_cmd);
> u32 event_id = its_cmd_get_id(its_cmd);
> - struct its_itte *itte;
> + struct its_ite *ite;
>
>
> - itte = find_itte(its, device_id, event_id);
> - if (!itte)
> + ite = find_ite(its, device_id, event_id);
> + if (!ite)
> return E_ITS_INV_UNMAPPED_INTERRUPT;
>
> - return update_lpi_config(kvm, itte->irq, NULL);
> + return update_lpi_config(kvm, ite->irq, NULL);
> }
>
> /*
> @@ -1435,7 +1435,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
> struct kvm *kvm = kvm_dev->kvm;
> struct vgic_its *its = kvm_dev->private;
> struct its_device *dev;
> - struct its_itte *itte;
> + struct its_ite *ite;
> struct list_head *dev_cur, *dev_temp;
> struct list_head *cur, *temp;
>
> @@ -1450,8 +1450,8 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
> list_for_each_safe(dev_cur, dev_temp, &its->device_list) {
> dev = container_of(dev_cur, struct its_device, dev_list);
> list_for_each_safe(cur, temp, &dev->itt_head) {
> - itte = (container_of(cur, struct its_itte, itte_list));
> - its_free_itte(kvm, itte);
> + ite = (container_of(cur, struct its_ite, ite_list));
> + its_free_ite(kvm, ite);
> }
> list_del(dev_cur);
> kfree(dev);
> --
> 2.5.5
>
^ permalink raw reply
* [PATCH v5 01/22] KVM: arm/arm64: Add ITS save/restore API documentation
From: Christoffer Dall @ 2017-04-27 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <88a194fa-9143-960e-e0a6-6b5c388cef82@redhat.com>
On Wed, Apr 26, 2017 at 05:48:32PM +0200, Auger Eric wrote:
> Hi Christoffer,
>
> On 26/04/2017 14:31, Christoffer Dall wrote:
> > On Fri, Apr 14, 2017 at 12:15:13PM +0200, Eric Auger wrote:
> >> Add description for how to access ITS registers and how to save/restore
> >> ITS tables into/from memory.
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >>
> >> ---
> >> v4 -> v5:
> >> - take into account Christoffer's comments
> >> - pending table save on GICV3 side now
> >>
> >> v3 -> v4:
> >> - take into account Peter's comments:
> >> - typos
> >> - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
> >> - add a validity bit in DTE
> >> - document all fields in CTE and ITE
> >> - document ABI revision
> >> - take into account Andre's comments:
> >> - document restrictions about GITS_CREADR writing and GITS_IIDR
> >> - document -EBUSY error if one or more VCPUS are runnning
> >> - document 64b registers only can be accessed with 64b access
> >> - itt_addr field matches bits [51:8] of the itt_addr
> >>
> >> v1 -> v2:
> >> - DTE and ITE now are 8 bytes
> >> - DTE and ITE now indexed by deviceid/eventid
> >> - use ITE name instead of ITTE
> >> - mentions ITT_addr matches bits [51:8] of the actual address
> >> - mentions LE layout
> >> ---
> >> Documentation/virtual/kvm/devices/arm-vgic-its.txt | 99 ++++++++++++++++++++++
> >> 1 file changed, 99 insertions(+)
> >>
> >> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> index 6081a5b..b5f010d 100644
> >> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> @@ -32,7 +32,106 @@ Groups:
> >> KVM_DEV_ARM_VGIC_CTRL_INIT
> >> request the initialization of the ITS, no additional parameter in
> >> kvm_device_attr.addr.
> >> +
> >> + KVM_DEV_ARM_ITS_SAVE_TABLES
> >> + save the ITS table data into guest RAM, at the location provisioned
> >> + by the guest in corresponding registers/table entries.
> >> +
> >> + The layout of the tables in guest memory defines an ABI. The entries
> >> + are laid out in little endian format as described in the last paragraph.
> >> +
> >> + KVM_DEV_ARM_ITS_RESTORE_TABLES
> >> + restore the ITS tables from guest RAM to ITS internal structures.
> >> +
> >> + The GICV3 must be restored before the ITS and all ITS registers but
> >> + the GITS_CTLR must be restored before restoring the ITS tables.
> >> +
> >> + The GITS_IIDR read-only register must also be restored before
> >> + the table restore as the IIDR revision field encodes the ABI revision.
> >> +
> >
> > what is the expected sequence of operations. For example, to restore
> > the ITS, do I call KVM_DEV_ARM_VGIC_CTRL_INIT first, then restore all
> > the memory and registers, and finally call KVM_DEV_ARM_ITS_RESTORE_TABLES?
> Yes KVM_DEV_ARM_VGIC_CTRL_INIT comes first, then restore all registers
> except GITS_CTLR, then table restore, then GITS_CTLR
> >
> > Is there any interaction between when you call KVM_DEV_ARM_ITS_RESTORE_TABLES
> > and restore GITS_CTLR (which enables the ITS)?
>
> Yep, when GITS_CTLR is set, LPIs may be enabled and this on that event
> that the pending table is read. But the whole pending table is not read
> as we only iterate on registered LPIs. So the ITT must have been
> restored previously.
>
> I became aware that the pending table sync is done twice, once in the
> pending table restore, and once in the GITS_CTLR restore. So if we
> leave this order specification, I should be able to remove the sync on
> table restore. This was the original reason why GITS_CTLR restore has
> been done at the very end.
I'm sorry, I'm a bit confused. Do we not need
KVM_DEV_ARM_ITS_RESTORE_TABLES at all then?
> >
> >> Errors:
> >> -ENXIO: ITS not properly configured as required prior to setting
> >> this attribute
> >> -ENOMEM: Memory shortage when allocating ITS internal data
> >> + -EINVAL: Inconsistent restored data
> >> + -EFAULT: Invalid guest ram access
> >> + -EBUSY: One or more VCPUS are running
> >> +
> >> + KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> >> + Attributes:
> >> + The attr field of kvm_device_attr encodes the offset of the
> >> + ITS register, relative to the ITS control frame base address
> >> + (ITS_base).
> >> +
> >> + kvm_device_attr.addr points to a __u64 value whatever the width
> >> + of the addressed register (32/64 bits). 64 bit registers can only
> >> + be accessed with full length.
> >> +
> >> + Writes to read-only registers are ignored by the kernel except for:
> >> + - GITS_READR. It needs to be restored otherwise commands in the queue
> >> + will be re-executed after restoring CWRITER. GITS_READR must be restored
> >> + before restoring the GITS_CTLR which is likely to enable the ITS.
> >> + Also it needs to be restored after GITS_CBASER since a write to
> >> + GITS_CBASER resets GITS_CREADR.
> >> + - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> >> + In the future we might implement direct injection of virtual LPIS.
> >> + This will require an upgrade of the table layout and an evolution of
> >> + the ABI. GITS_IIDR must be restored before the table restoration.
> >> +
> >> + For other registers, getting or setting a register has the same
> >> + effect as reading/writing the register on real hardware.
> >> + Errors:
> >> + -ENXIO: Offset does not correspond to any supported register
> >> + -EFAULT: Invalid user pointer for attr->addr
> >> + -EINVAL: Offset is not 64-bit aligned
> >> + -EBUSY: one or more VCPUS are running
> >
> >
> > It may be helpful to state the ordering requirements somewhere:
> >
> > Restoring the ITS:
> > ------------------
> > Restoring the ITS requires certain things to happen in order.
> > Specifically:
> > 1. Initialize the ITS (KVM_DEV_ARM_VGIC_CTRL_INIT)
> > 2. Restore GITS_IIDR
> > 3. Restore GITS_CBASER
> > 4. Restore GITS_READR
> > 5. Restore remainin registers except GITS_CTLR
> > 6. Make sure all guest memory is restored
> > 7. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
>
> OK I will try to fit that description somewhere.
>
Thanks,
-Christoffer
^ permalink raw reply
* [patch V2 00/24] cpu/hotplug: Convert get_online_cpus() to a percpu_rwsem
From: Sebastian Siewior @ 2017-04-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170426103236.GI27156@leverpostej>
On 2017-04-26 11:32:36 [+0100], Mark Rutland wrote:
> > So we could end up calling static_branch_enable_cpuslocked()
> > without actually holding the lock. Should we do a cpu_hotplug_begin/done in
> > setup_cpu_feature_capabilities ? I agree it doesn't look that nice. Thoughts ?
>
> I agree that's hideous, but it looks like the only choice given the
> hotplug rwsem cahnges. :/
would work for you to provide a locked and unlocked version?
> I can spin a v2 with that and the typo fixes.
>
> Thanks,
> Mark.
Sebastian
^ permalink raw reply
* [PATCH 1/2] wcn36xx: Pass used skb to ieee80211_tx_status()
From: Johannes Berg @ 2017-04-27 8:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170426220444.10539-1-bjorn.andersson@linaro.org>
> @@ -371,7 +371,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn,
> struct wcn36xx_dxe_ch *ch)
> ? info = IEEE80211_SKB_CB(ctl->skb);
> ? if (!(info->flags &
> IEEE80211_TX_CTL_REQ_TX_STATUS)) {
> ? /* Keep frame until TX status comes
> */
> - ieee80211_free_txskb(wcn->hw, ctl-
> >skb);
> + ieee80211_tx_status(wcn->hw, ctl-
> >skb);
>
I don't think this is a good idea. This code intentionally checked if
TX status was requested, and if not then it doesn't go to the effort of
building it.
As it is with your patch, it'll go and report the TX status without any
TX status information - which is handled in wcn36xx_dxe_tx_ack_ind()
for those frames needing it.
johannes
^ permalink raw reply
* [PATCH v2] clk: sunxi-ng: Fix dependency on SUNXI_CCU_GATE
From: Corentin Labbe @ 2017-04-27 8:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170427070436.3qu4mzepq4gmmymi@lukather>
On Thu, Apr 27, 2017 at 09:04:36AM +0200, Maxime Ripard wrote:
> On Wed, Apr 26, 2017 at 01:53:19PM +0200, Corentin Labbe wrote:
> > When CONFIG_SUNXI_CCU is set but no other SUNXI_CCU is selected i got
> > the following build error:
> > drivers/built-in.o: In function `ccu_pll_notifier_cb':
> > drivers/clk/sunxi-ng/ccu_common.c:71: undefined reference to `ccu_gate_helper_disable'
> > drivers/clk/sunxi-ng/ccu_common.c:73: undefined reference to `ccu_gate_helper_enable'
> >
> > The problem is the function ccu_pll_notifier_cb in ccu_common.c need
> > some function from ccu_gate.c which is not compiled since SUNXI_CCU_GATE
> > is not selected.
> >
> > This patch remove SUNXI_CCU_GATE and compile ccu_gate.c unconditionnaly
> > since all other combination of options select SUNXI_CCU_GATE finally.
> >
> > Fixes: 02ae2bc6febd ("clk: sunxi-ng: Add clk notifier to gate then ungate PLL clocks")
> > Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
>
> I think Chen-Yu had some comments that you didn't address.
>
I have changed subject as requested
^ permalink raw reply
* [linux-sunxi] Re: [PATCH v5 02/11] clk: sunxi-ng: add support for DE2 CCU
From: Maxime Ripard @ 2017-04-27 7:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9def8a6b635880095e6b75e3a53af1f4@aosc.io>
On Mon, Apr 24, 2017 at 06:26:51PM +0800, icenowy at aosc.io wrote:
> ? 2017-04-24 16:51?Maxime Ripard ???
> > Hi,
> >
> > On Sun, Apr 23, 2017 at 06:37:45PM +0800, Icenowy Zheng wrote:
> > > +static const struct of_device_id sunxi_de2_clk_ids[] = {
> > > + {
> > > + .compatible = "allwinner,sun8i-a83t-de2-clk",
> > > + .data = &sun8i_a83t_de2_clk_desc,
> > > + },
> > > + {
> > > + .compatible = "allwinner,sun50i-h5-de2-clk",
> > > + .data = &sun50i_a64_de2_clk_desc,
> > > + },
> > > + /*
> > > + * The Allwinner A64 SoC needs some bit to be poke in syscon to make
> > > + * DE2 really working.
> > > + * So there's currently no A64 compatible here.
> > > + * H5 shares the same reset line with A64, so here H5 is using the
> > > + * clock description of A64.
> > > + */
> > > + { }
> > > +};
> >
> > So that A64 driver would require more than just what you defined in
> > the binding in order to operate?
>
> Yes. When trying to do A64 driver, I will send out first a patch to
> add the needed binding bit.
Then remove the A64 compatible from the binding document.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170427/07055f3a/attachment.sig>
^ permalink raw reply
* [PATCH v2] clk: sunxi-ng: Fix dependency on SUNXI_CCU_GATE
From: Maxime Ripard @ 2017-04-27 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170426115319.30951-1-clabbe.montjoie@gmail.com>
On Wed, Apr 26, 2017 at 01:53:19PM +0200, Corentin Labbe wrote:
> When CONFIG_SUNXI_CCU is set but no other SUNXI_CCU is selected i got
> the following build error:
> drivers/built-in.o: In function `ccu_pll_notifier_cb':
> drivers/clk/sunxi-ng/ccu_common.c:71: undefined reference to `ccu_gate_helper_disable'
> drivers/clk/sunxi-ng/ccu_common.c:73: undefined reference to `ccu_gate_helper_enable'
>
> The problem is the function ccu_pll_notifier_cb in ccu_common.c need
> some function from ccu_gate.c which is not compiled since SUNXI_CCU_GATE
> is not selected.
>
> This patch remove SUNXI_CCU_GATE and compile ccu_gate.c unconditionnaly
> since all other combination of options select SUNXI_CCU_GATE finally.
>
> Fixes: 02ae2bc6febd ("clk: sunxi-ng: Add clk notifier to gate then ungate PLL clocks")
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
I think Chen-Yu had some comments that you didn't address.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170427/ca785aac/attachment.sig>
^ permalink raw reply
* [PATCH] drm/rockchip: Set line flag config register in vop_crtc_enable
From: Mark yao @ 2017-04-27 7:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1493276057-4516-1-git-send-email-jeffy.chen@rock-chips.com>
On 2017?04?27? 14:54, Jeffy Chen wrote:
> We need to set vop config done after update line flag config, it's a
> new requirement for chips newer than rk3368.
>
> Since we would only use line flag irq for vact_end, let's move it to
> vop_crtc_enable.
>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
looks good for me:
Acked-by: Mark Yao <mark.yao@rock-chips.com>
>
> ---
>
> drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 ++--
> drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 +--
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +++++++++-----------
> 3 files changed, 12 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> index d8fa7a9..9bfdbc6 100644
> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> @@ -115,8 +115,8 @@ static void analogix_dp_psr_work(struct work_struct *work)
>
> vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
>
> - ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
> - PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
> + ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
> + PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
> if (ret) {
> dev_err(dp->dev, "line flag interrupt did not arrive\n");
> return;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index a48fcce..47905fa 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
> struct device *dev);
> void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
> struct device *dev);
> -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
> - unsigned int mstimeout);
> +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
>
> extern struct platform_driver cdn_dp_driver;
> extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 3f7a82d..40a5e6e 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop)
> return !!line_flag_irq;
> }
>
> -static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
> +static void vop_line_flag_irq_enable(struct vop *vop)
> {
> unsigned long flags;
>
> @@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
>
> spin_lock_irqsave(&vop->irq_lock, flags);
>
> - VOP_CTRL_SET(vop, line_flag_num[0], line_num);
> VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
> VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
>
> @@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
> VOP_CTRL_SET(vop, vact_st_end, val);
> VOP_CTRL_SET(vop, vpost_st_end, val);
>
> + VOP_CTRL_SET(vop, line_flag_num[0], vact_end);
> +
> clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
>
> VOP_CTRL_SET(vop, standby, 0);
> @@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop)
> }
>
> /**
> - * rockchip_drm_wait_line_flag - acqiure the give line flag event
> + * rockchip_drm_wait_vact_end
> * @crtc: CRTC to enable line flag
> - * @line_num: interested line number
> * @mstimeout: millisecond for timeout
> *
> - * Driver would hold here until the interested line flag interrupt have
> - * happened or timeout to wait.
> + * Wait for vact_end line flag irq or timeout.
> *
> * Returns:
> * Zero on success, negative errno on failure.
> */
> -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
> - unsigned int mstimeout)
> +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
> {
> struct vop *vop = to_vop(crtc);
> unsigned long jiffies_left;
> @@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
> if (!crtc || !vop->is_enabled)
> return -ENODEV;
>
> - if (line_num > crtc->mode.vtotal || mstimeout <= 0)
> + if (mstimeout <= 0)
> return -EINVAL;
>
> if (vop_line_flag_irq_is_enabled(vop))
> return -EBUSY;
>
> reinit_completion(&vop->line_flag_completion);
> - vop_line_flag_irq_enable(vop, line_num);
> + vop_line_flag_irq_enable(vop);
>
> jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
> msecs_to_jiffies(mstimeout));
> @@ -1547,7 +1545,7 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
>
> return 0;
> }
> -EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
> +EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
>
> static int vop_bind(struct device *dev, struct device *master, void *data)
> {
--
?ark Yao
^ permalink raw reply
* [PATCH v5 00/22] vITS save/restore
From: Auger Eric @ 2017-04-27 6:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACJhumdaHDX2oAuJ2PQCqhmJV0u7Eu9SF7a8xsga6sAwJHyrCQ@mail.gmail.com>
Hi Brahmajyosyula,
On 26/04/2017 13:38, Prakash B wrote:
> Verified on Cavium ThunderX platform
> Continousily migrated Guest more than 500 times b/w different hosts.
> Please feel free to add Tested-by: Prakash, Brahmajyosyula
> <Brahmajyosyula.Prakash@cavium.com>
I really appreciate. Many thanks!
Best Regards
Eric
* note you are not obliged to bother to send individual T-b on each
patch. You can just send T-b on the cover letter and if requested
exclude patches or features you could not test.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* [PATCH] drm/rockchip: Set line flag config register in vop_crtc_enable
From: Jeffy Chen @ 2017-04-27 6:54 UTC (permalink / raw)
To: linux-arm-kernel
We need to set vop config done after update line flag config, it's a
new requirement for chips newer than rk3368.
Since we would only use line flag irq for vact_end, let's move it to
vop_crtc_enable.
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 ++--
drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 +--
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +++++++++-----------
3 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d8fa7a9..9bfdbc6 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -115,8 +115,8 @@ static void analogix_dp_psr_work(struct work_struct *work)
vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
- ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
- PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+ ret = rockchip_drm_wait_vact_end(dp->encoder.crtc,
+ PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
dev_err(dp->dev, "line flag interrupt did not arrive\n");
return;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index a48fcce..47905fa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
struct device *dev);
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
- unsigned int mstimeout);
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
extern struct platform_driver cdn_dp_driver;
extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3f7a82d..40a5e6e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop)
return !!line_flag_irq;
}
-static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+static void vop_line_flag_irq_enable(struct vop *vop)
{
unsigned long flags;
@@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
spin_lock_irqsave(&vop->irq_lock, flags);
- VOP_CTRL_SET(vop, line_flag_num[0], line_num);
VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
@@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
VOP_CTRL_SET(vop, vact_st_end, val);
VOP_CTRL_SET(vop, vpost_st_end, val);
+ VOP_CTRL_SET(vop, line_flag_num[0], vact_end);
+
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
VOP_CTRL_SET(vop, standby, 0);
@@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop)
}
/**
- * rockchip_drm_wait_line_flag - acqiure the give line flag event
+ * rockchip_drm_wait_vact_end
* @crtc: CRTC to enable line flag
- * @line_num: interested line number
* @mstimeout: millisecond for timeout
*
- * Driver would hold here until the interested line flag interrupt have
- * happened or timeout to wait.
+ * Wait for vact_end line flag irq or timeout.
*
* Returns:
* Zero on success, negative errno on failure.
*/
-int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
- unsigned int mstimeout)
+int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
{
struct vop *vop = to_vop(crtc);
unsigned long jiffies_left;
@@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
if (!crtc || !vop->is_enabled)
return -ENODEV;
- if (line_num > crtc->mode.vtotal || mstimeout <= 0)
+ if (mstimeout <= 0)
return -EINVAL;
if (vop_line_flag_irq_is_enabled(vop))
return -EBUSY;
reinit_completion(&vop->line_flag_completion);
- vop_line_flag_irq_enable(vop, line_num);
+ vop_line_flag_irq_enable(vop);
jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
msecs_to_jiffies(mstimeout));
@@ -1547,7 +1545,7 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
return 0;
}
-EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
+EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
static int vop_bind(struct device *dev, struct device *master, void *data)
{
--
2.1.4
^ permalink raw reply related
* [PATCH v8 1/4] syscalls: Verify address limit before returning to user-mode
From: Ingo Molnar @ 2017-04-27 6:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170426183425.32158-1-thgarnie@google.com>
* Thomas Garnier <thgarnie@google.com> wrote:
> +
> +/*
> + * Called before coming back to user-mode. Returning to user-mode with an
> + * address limit different than USER_DS can allow to overwrite kernel memory.
> + */
> +static inline void addr_limit_check_syscall(void)
> +{
> + BUG_ON(!segment_eq(get_fs(), USER_DS));
> +}
> +
> +#ifndef CONFIG_ADDR_LIMIT_CHECK
> +#define __CHECK_USERMODE_SYSCALL() \
> + bool user_caller = segment_eq(get_fs(), USER_DS)
> +#define __VERIFY_ADDR_LIMIT() \
> + if (user_caller) addr_limit_check_syscall()
> +#else
> +#define __CHECK_USERMODE_SYSCALL()
> +#define __VERIFY_ADDR_LIMIT()
> +asmlinkage void addr_limit_check_failed(void) __noreturn;
> +#endif
_Please_ harmonize all the externally exposed names and symbols.
There's no reason for this mismash of names:
CONFIG_ADDR_LIMIT_CHECK
__CHECK_USERMODE_SYSCALL
__VERIFY_ADDR_LIMIT
When we could just as easily name them consistently, along the existing pattern:
CONFIG_ADDR_LIMIT_CHECK
__SYSCALL_ADDR_LIMIT_CHECK
__ADDR_LIMIT_CHECK
which should fit into existing nomenclature:
> #define __SYSCALL_DEFINEx(x, name, ...) \
But even with that fixed, the whole construct still looks pretty weird:
> { \
> - long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
> + long ret; \
> + __CHECK_USERMODE_SYSCALL(); \
> + ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
> + __ADDR_LIMIT_CHECK(); \
> __MAP(x,__SC_TEST,__VA_ARGS__); \
> __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
> return ret; \
I think something like this would be more natural to read:
> + ADDR_LIMIT_CHECK_PRE(); \
> + ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
> + ADDR_LIMIT_CHECK_POST(); \
it's a clear pre/post construct. Also note the lack of double underscores.
BTW., a further simplification would be:
#ifndef ADDR_LIMIT_CHECK_PRE
# define ADDR_LIMIT_CHECK_PRE ...
#endif
This way architectures could override this generic functionality simply by
defining the helpers. Architectures that don't do that get the generic version.
Thanks,
Ingo
^ permalink raw reply
* [PATCH RFC 0/5] *** SPI Slave mode support ***
From: Jiada Wang @ 2017-04-27 6:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170425103113.lxpwoq6sbxvg3ihl@sirena.org.uk>
Hello Geert and Mark
On 04/25/2017 03:31 AM, Mark Brown wrote:
> On Mon, Apr 24, 2017 at 12:55:21PM +0200, Geert Uytterhoeven wrote:
>> On Fri, Apr 14, 2017 at 7:39 AM, Jiada Wang<jiada_wang@mentor.com> wrote:
>>> Our use case is to use spidev as an interface to communicate with external
>>> SPI master devices.
>>> meanwhile the SPI bus controller can also act as master device to send data
>>> to other
>>> SPI slave devices on the board.
>> That sounds a bit hackish to me. SPI was never meant to be a multi-master bus.
>> While it can be done, you will need external synchronization (signals) to
>> avoid conflicts between the SPI masters.
>>> I found in your implementation, SPI bus controller is limited to either work
>>> in master mode or
>>> slave mode, is there any reasoning to not configure SPI mode based on SPI
>>> devices use case?
>> If you really need both master and slave support, you can use 2 subnodes
>> in DT, the first representing the master, the second the slave.
>> Mark, what's your opinion about this?
> That sounds like a mess... we *could* put the slave flag on the device
> rather than the controller I guess but there's also going to need to be
> something representing whatever avoids collisions on the bus somewhere.
The reason I gave the example use case is want to point out that
with Geert's patch set, a SPI device (with only one controller) can no
longer
act as master and slave at the same time. because IMO as a SPI core
function,
it needs to cover all the use cases, and to be as generic as possible.
BUT if you think the use case don't need to be supported from SPI core,
then I don't have objection either, I will only submit imx SPI slave
support patch,
after your SPI slave support patch set been applied
Thanks,
Jiada
^ permalink raw reply
* [PATCH] [media] mtk-mdp: Fix g_/s_selection capture/compose logic
From: houlong wei @ 2017-04-27 6:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMLVLiLkZsBfezx6b9Xq=kyPjUZOXwHC4LfHh1=wy6Ynt=zSQ@mail.gmail.com>
On Thu, 2017-04-13 at 14:50 +0800, Wu-Cheng Li (???) wrote:
> Reviewed-by: Wu-Cheng Li <wuchengli@chromium.org>
>
> On Thu, Apr 13, 2017 at 12:18 PM, Minghsiu Tsai
> <minghsiu.tsai@mediatek.com> wrote:
> > From: Daniel Kurtz <djkurtz@chromium.org>
> >
> > Experiments show that the:
> > (1) mtk-mdp uses the _MPLANE form of CAPTURE/OUTPUT
> > (2) CAPTURE types use CROP targets, and OUTPUT types use COMPOSE targets
> >
> > Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> > Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>
Acked-by:Houlong Wei <houlong.wei@mediatek.com>
> >
> > ---
> > drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 18 +++++++++---------
> > 1 file changed, 9 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> > index 13afe48..8ab7ca0 100644
> > --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> > +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> > @@ -837,12 +837,12 @@ static int mtk_mdp_m2m_g_selection(struct file *file, void *fh,
> > struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
> > bool valid = false;
> >
> > - if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > - if (mtk_mdp_is_target_compose(s->target))
> > - valid = true;
> > - } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> > if (mtk_mdp_is_target_crop(s->target))
> > valid = true;
> > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> > + if (mtk_mdp_is_target_compose(s->target))
> > + valid = true;
> > }
> > if (!valid) {
> > mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
> > @@ -907,12 +907,12 @@ static int mtk_mdp_m2m_s_selection(struct file *file, void *fh,
> > int ret;
> > bool valid = false;
> >
> > - if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > - if (s->target == V4L2_SEL_TGT_COMPOSE)
> > - valid = true;
> > - } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> > if (s->target == V4L2_SEL_TGT_CROP)
> > valid = true;
> > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> > + if (s->target == V4L2_SEL_TGT_COMPOSE)
> > + valid = true;
> > }
> > if (!valid) {
> > mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
> > @@ -925,7 +925,7 @@ static int mtk_mdp_m2m_s_selection(struct file *file, void *fh,
> > if (ret)
> > return ret;
> >
> > - if (mtk_mdp_is_target_crop(s->target))
> > + if (mtk_mdp_is_target_compose(s->target))
> > frame = &ctx->s_frame;
> > else
> > frame = &ctx->d_frame;
> > --
> > 1.9.1
> >
^ permalink raw reply
* [patch] autogain support for bayer10 format (was Re: [patch] propagating controls in libv4l2)
From: Ivaylo Dimitrov @ 2017-04-27 5:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170426225150.GA4188@amd>
On 27.04.2017 01:51, Pavel Machek wrote:
> Hi!
>
>>>> There are two separate things here:
>>>>
>>>> 1) Autofoucs for a device that doesn't use subdev API
>>>> 2) libv4l2 support for devices that require MC and subdev API
>>>
>>> Actually there are three: 0) autogain. Unfortunately, I need autogain
>>> first before autofocus has a chance...
>>>
>>> And that means... bayer10 support for autogain.
>>>
>>> Plus, I changed avg_lum to long long. Quick calculation tells me int
>>> could overflow with few megapixel sensor.
>>>
>>> Oh, btw http://ytse.tricolour.net/docs/LowLightOptimization.html no
>>> longer works.
>>>
>>> Regards,
>>> Pavel
>>>
>>> diff --git a/lib/libv4lconvert/processing/autogain.c b/lib/libv4lconvert/processing/autogain.c
>>> index c6866d6..0b52d0f 100644
>>> --- a/lib/libv4lconvert/processing/autogain.c
>>> +++ b/lib/libv4lconvert/processing/autogain.c
>>> @@ -68,6 +71,41 @@ static void autogain_adjust(struct v4l2_queryctrl *ctrl, int *value,
>>> }
>>> }
>>>
>>> +static int get_luminosity_bayer10(uint16_t *buf, const struct v4l2_format *fmt)
>>> +{
>>> + long long avg_lum = 0;
>>> + int x, y;
>>> +
>>> + buf += fmt->fmt.pix.height * fmt->fmt.pix.bytesperline / 4 +
>>> + fmt->fmt.pix.width / 4;
>>> +
>>> + for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
>>> + for (x = 0; x < fmt->fmt.pix.width / 2; x++)
>>
>> That would take some time :). AIUI, we have NEON support in ARM kernels
>> (CONFIG_KERNEL_MODE_NEON), I wonder if it makes sense (me) to convert the
>> above loop to NEON-optimized when it comes to it? Are there any drawbacks in
>> using NEON code in kernel?
>
> Well, thanks for offer. This is actualy libv4l2.
>
Oh, somehow I got confused that this is kernel code :)
> But I'd say NEON conversion is not neccessary anytime soon. First,
> this is just trying to get average luminosity. We can easily skip
> quite a lot of pixels, and still get reasonable answer.
>
> Second, omap3isp actually has a hardware block computing statistics
> for us. We just don't use it for simplicity.
>
Right, I forgot about that.
> (But if you want to play with camera, I'll get you patches; there's
> ton of work to be done, both kernel and userspace :-).
Well, I saw a low hanging fruit I thought I can convert to NEON in a day
or two, while having some rest from the huge "project" I am devoting all
my spare time recently (rebasing hildon/maemo 5 on top of devuan
Jessie). Still, if there is something relatively small to be done, just
email me and I'll have a look.
Regards,
Ivo
^ permalink raw reply
* [PATCH] iio: stm32 trigger: Add support for TRGO2 triggers
From: Jonathan Cameron @ 2017-04-27 5:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CA+M3ks69FLm+2+t-QQNuGyi+gc-nyUw8rXUAM6WxzC9DurPPCw@mail.gmail.com>
On 26/04/17 09:55, Benjamin Gaignard wrote:
> 2017-04-26 10:17 GMT+02:00 Fabrice Gasnier <fabrice.gasnier@st.com>:
>> Add support for TRGO2 trigger that can be found on STM32F7.
>> Add additional master modes supported by TRGO2.
These additional modes would benefit from more information in the
ABI docs. Otherwise patch seems fine, though this may win
the award for hardest hardware to come up with a generic
interface for...
>> Register additional "tim[1/8]_trgo2" triggers for timer1 & timer8.
>> Detect TRGO2 timer capability (master mode selection 2).
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>> .../ABI/testing/sysfs-bus-iio-timer-stm32 | 15 +++
>> drivers/iio/trigger/stm32-timer-trigger.c | 113 ++++++++++++++++++---
>> include/linux/iio/timer/stm32-timer-trigger.h | 2 +
>> include/linux/mfd/stm32-timers.h | 2 +
>> 4 files changed, 118 insertions(+), 14 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>> index 230020e..47647b4 100644
>> --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>> +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>> @@ -16,6 +16,21 @@ Description:
>> - "OC2REF" : OC2REF signal is used as trigger output.
>> - "OC3REF" : OC3REF signal is used as trigger output.
>> - "OC4REF" : OC4REF signal is used as trigger output.
>> + Additional modes (on TRGO2 only):
>> + - "OC5REF" : OC5REF signal is used as trigger output.
>> + - "OC6REF" : OC6REF signal is used as trigger output.
>> + - "compare_pulse_OC4REF":
>> + OC4REF rising or falling edges generate pulses.
I'd like this to be fairly understandable without resorting to reading the
datasheet. As I understand it you get a fixed term pulse on both edges
of the waveform? Perhaps this calls for some ascii art :)
>> + - "compare_pulse_OC6REF":
>> + OC6REF rising or falling edges generate pulses.
>> + - "compare_pulse_OC4REF_r_or_OC6REF_r":
>> + OC4REF or OC6REF rising edges generate pulses.
>> + - "compare_pulse_OC4REF_r_or_OC6REF_f":
>> + OC4REF rising or OC6REF falling edges generate pulses.
>> + - "compare_pulse_OC5REF_r_or_OC6REF_r":
>> + OC5REF or OC6REF rising edges generate pulses.
>> + - "compare_pulse_OC5REF_r_or_OC6REF_f":
>> + OC5REF rising or OC6REF falling edges generate pulses.
>>
>> What: /sys/bus/iio/devices/triggerX/master_mode
>> KernelVersion: 4.11
>> diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
>> index 0f1a2cf..a0031b7 100644
>> --- a/drivers/iio/trigger/stm32-timer-trigger.c
>> +++ b/drivers/iio/trigger/stm32-timer-trigger.c
>> @@ -14,19 +14,19 @@
>> #include <linux/module.h>
>> #include <linux/platform_device.h>
>>
>> -#define MAX_TRIGGERS 6
>> +#define MAX_TRIGGERS 7
>> #define MAX_VALIDS 5
>>
>> /* List the triggers created by each timer */
>> static const void *triggers_table[][MAX_TRIGGERS] = {
>> - { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
>> + { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
>> { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,},
>> { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,},
>> { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,},
>> { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,},
>> { TIM6_TRGO,},
>> { TIM7_TRGO,},
>> - { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
>> + { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
>> { TIM9_TRGO, TIM9_CH1, TIM9_CH2,},
>> { }, /* timer 10 */
>> { }, /* timer 11 */
>> @@ -56,9 +56,16 @@ struct stm32_timer_trigger {
>> u32 max_arr;
>> const void *triggers;
>> const void *valids;
>> + bool has_trgo2;
>> };
>>
>> +static bool stm32_timer_is_trgo2_name(const char *name)
>> +{
>> + return !!strstr(name, "trgo2");
>> +}
>> +
>> static int stm32_timer_start(struct stm32_timer_trigger *priv,
>> + struct iio_trigger *trig,
>> unsigned int frequency)
>> {
>> unsigned long long prd, div;
>> @@ -102,7 +109,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
>> regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
>>
>> /* Force master mode to update mode */
>> - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20);
>> + if (stm32_timer_is_trgo2_name(trig->name))
>> + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2,
>> + 0x2 << TIM_CR2_MMS2_SHIFT);
>> + else
>> + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS,
>> + 0x2 << TIM_CR2_MMS_SHIFT);
>>
>> /* Make sure that registers are updated */
>> regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
>> @@ -150,7 +162,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev,
>> if (freq == 0) {
>> stm32_timer_stop(priv);
>> } else {
>> - ret = stm32_timer_start(priv, freq);
>> + ret = stm32_timer_start(priv, trig, freq);
>> if (ret)
>> return ret;
>> }
>> @@ -183,6 +195,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660,
>> stm32_tt_read_frequency,
>> stm32_tt_store_frequency);
>>
>> +#define MASTER_MODE_MAX 7
>> +#define MASTER_MODE2_MAX 15
>> +
>> static char *master_mode_table[] = {
>> "reset",
>> "enable",
>> @@ -191,7 +206,16 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660,
>> "OC1REF",
>> "OC2REF",
>> "OC3REF",
>> - "OC4REF"
>> + "OC4REF",
>> + /* Master mode selection 2 only */
>> + "OC5REF",
>> + "OC6REF",
>> + "compare_pulse_OC4REF",
>> + "compare_pulse_OC6REF",
>> + "compare_pulse_OC4REF_r_or_OC6REF_r",
>> + "compare_pulse_OC4REF_r_or_OC6REF_f",
>> + "compare_pulse_OC5REF_r_or_OC6REF_r",
>> + "compare_pulse_OC5REF_r_or_OC6REF_f",
>> };
>>
>> static ssize_t stm32_tt_show_master_mode(struct device *dev,
>> @@ -199,10 +223,15 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev,
>> char *buf)
>> {
>> struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
>> + struct iio_trigger *trig = to_iio_trigger(dev);
>> u32 cr2;
>>
>> regmap_read(priv->regmap, TIM_CR2, &cr2);
>> - cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
>> +
>> + if (stm32_timer_is_trgo2_name(trig->name))
>> + cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT;
>> + else
>> + cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
>>
>> return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]);
>> }
>> @@ -212,13 +241,25 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
>> const char *buf, size_t len)
>> {
>> struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
>> + struct iio_trigger *trig = to_iio_trigger(dev);
>> + u32 mask, shift, master_mode_max;
>> int i;
>>
>> - for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) {
>> + if (stm32_timer_is_trgo2_name(trig->name)) {
>> + mask = TIM_CR2_MMS2;
>> + shift = TIM_CR2_MMS2_SHIFT;
>> + master_mode_max = MASTER_MODE2_MAX;
>> + } else {
>> + mask = TIM_CR2_MMS;
>> + shift = TIM_CR2_MMS_SHIFT;
>> + master_mode_max = MASTER_MODE_MAX;
>> + }
>> +
>> + for (i = 0; i <= master_mode_max; i++) {
>> if (!strncmp(master_mode_table[i], buf,
>> strlen(master_mode_table[i]))) {
>> - regmap_update_bits(priv->regmap, TIM_CR2,
>> - TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT);
>> + regmap_update_bits(priv->regmap, TIM_CR2, mask,
>> + i << shift);
>> /* Make sure that registers are updated */
>> regmap_update_bits(priv->regmap, TIM_EGR,
>> TIM_EGR_UG, TIM_EGR_UG);
>> @@ -229,8 +270,31 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
>> return -EINVAL;
>> }
>>
>> -static IIO_CONST_ATTR(master_mode_available,
>> - "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF");
>> +static ssize_t stm32_tt_show_master_mode_avail(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct iio_trigger *trig = to_iio_trigger(dev);
>> + unsigned int i, master_mode_max;
>> + size_t len = 0;
>> +
>> + if (stm32_timer_is_trgo2_name(trig->name))
>> + master_mode_max = MASTER_MODE2_MAX;
>> + else
>> + master_mode_max = MASTER_MODE_MAX;
>> +
>> + for (i = 0; i <= master_mode_max; i++)
>> + len += scnprintf(buf + len, PAGE_SIZE - len,
>> + "%s ", master_mode_table[i]);
>> +
>> + /* replace trailing space by newline */
>> + buf[len - 1] = '\n';
>> +
>> + return len;
>> +}
>> +
>> +static IIO_DEVICE_ATTR(master_mode_available, 0444,
>> + stm32_tt_show_master_mode_avail, NULL, 0);
>>
>> static IIO_DEVICE_ATTR(master_mode, 0660,
>> stm32_tt_show_master_mode,
>> @@ -240,7 +304,7 @@ static IIO_DEVICE_ATTR(master_mode, 0660,
>> static struct attribute *stm32_trigger_attrs[] = {
>> &iio_dev_attr_sampling_frequency.dev_attr.attr,
>> &iio_dev_attr_master_mode.dev_attr.attr,
>> - &iio_const_attr_master_mode_available.dev_attr.attr,
>> + &iio_dev_attr_master_mode_available.dev_attr.attr,
>> NULL,
>> };
>>
>> @@ -264,6 +328,12 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv)
>>
>> while (cur && *cur) {
>> struct iio_trigger *trig;
>> + bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur);
>> +
>> + if (cur_is_trgo2 && !priv->has_trgo2) {
>> + cur++;
>> + continue;
>> + }
>>
>> trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
>> if (!trig)
>> @@ -277,7 +347,7 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv)
>> * should only be available on trgo trigger which
>> * is always the first in the list.
>> */
>> - if (cur == priv->triggers)
>> + if (cur == priv->triggers || cur_is_trgo2)
>> trig->dev.groups = stm32_trigger_attr_groups;
>>
>> iio_trigger_set_drvdata(trig, priv);
>> @@ -584,6 +654,20 @@ bool is_stm32_timer_trigger(struct iio_trigger *trig)
>> }
>> EXPORT_SYMBOL(is_stm32_timer_trigger);
>>
>> +static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv)
>> +{
>> + u32 val;
>> +
>> + /*
>> + * Master mode selection 2 bits can only be written and read back when
>> + * timer supports it.
>> + */
>> + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2);
>> + regmap_read(priv->regmap, TIM_CR2, &val);
>> + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0);
>> + priv->has_trgo2 = !!val;
>> +}
>> +
>> static int stm32_timer_trigger_probe(struct platform_device *pdev)
>> {
>> struct device *dev = &pdev->dev;
>> @@ -614,6 +698,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev)
>> priv->max_arr = ddata->max_arr;
>> priv->triggers = triggers_table[index];
>> priv->valids = valids_table[index];
>> + stm32_timer_detect_trgo2(priv);
>>
>> ret = stm32_setup_iio_triggers(priv);
>> if (ret)
>> diff --git a/include/linux/iio/timer/stm32-timer-trigger.h b/include/linux/iio/timer/stm32-timer-trigger.h
>> index 55535ae..fa7d786 100644
>> --- a/include/linux/iio/timer/stm32-timer-trigger.h
>> +++ b/include/linux/iio/timer/stm32-timer-trigger.h
>> @@ -10,6 +10,7 @@
>> #define _STM32_TIMER_TRIGGER_H_
>>
>> #define TIM1_TRGO "tim1_trgo"
>> +#define TIM1_TRGO2 "tim1_trgo2"
>> #define TIM1_CH1 "tim1_ch1"
>> #define TIM1_CH2 "tim1_ch2"
>> #define TIM1_CH3 "tim1_ch3"
>> @@ -44,6 +45,7 @@
>> #define TIM7_TRGO "tim7_trgo"
>>
>> #define TIM8_TRGO "tim8_trgo"
>> +#define TIM8_TRGO2 "tim8_trgo2"
>> #define TIM8_CH1 "tim8_ch1"
>> #define TIM8_CH2 "tim8_ch2"
>> #define TIM8_CH3 "tim8_ch3"
>> diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h
>> index 4a0abbc..ce7346e 100644
>> --- a/include/linux/mfd/stm32-timers.h
>> +++ b/include/linux/mfd/stm32-timers.h
>> @@ -34,6 +34,7 @@
>> #define TIM_CR1_DIR BIT(4) /* Counter Direction */
>> #define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */
>> #define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */
>> +#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */
>> #define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */
>> #define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
>> #define TIM_DIER_UIE BIT(0) /* Update interrupt */
>> @@ -60,6 +61,7 @@
>>
>> #define MAX_TIM_PSC 0xFFFF
>> #define TIM_CR2_MMS_SHIFT 4
>> +#define TIM_CR2_MMS2_SHIFT 20
>> #define TIM_SMCR_TS_SHIFT 4
>> #define TIM_BDTR_BKF_MASK 0xF
>> #define TIM_BDTR_BKF_SHIFT 16
>> --
>> 1.9.1
>>
>
> Acked-by: Benjamin Gaiganrd <benjamin.gaignard@linaro.org>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH] arm64: dts: ls1088a: add esdhc node
From: Yangbo Lu @ 2017-04-27 5:31 UTC (permalink / raw)
To: linux-arm-kernel
Add esdhc node for ls1088a and enable it on both RDB and QDS boards.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 12 ++++++++++++
3 files changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 8c3cae5..466c91b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -121,3 +121,7 @@
&sata {
status = "okay";
};
+
+&esdhc {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
index 8a04fbb..130cc3b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
@@ -105,3 +105,7 @@
&sata {
status = "okay";
};
+
+&esdhc {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 2946fd7..ef62aca 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -223,6 +223,18 @@
status = "disabled";
};
+ esdhc: esdhc at 2140000 {
+ compatible = "fsl,ls1088a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x2140000 0x0 0x10000>;
+ interrupts = <0 28 0x4>; /* Level high type */
+ clock-frequency = <0>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ little-endian;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
i2c0: i2c at 2000000 {
compatible = "fsl,vf610-i2c";
#address-cells = <1>;
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCH 3/3] iio: tools: generic_buffer: increase trigger length
From: Jonathan Cameron @ 2017-04-27 5:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492590045-17329-4-git-send-email-eugen.hristev@microchip.com>
On 19/04/17 09:20, Eugen Hristev wrote:
> Increased trigger length to 50 in order to cope with trigger names like
> fc030000.adc-dev0-external-rising
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
This is fine (though I'd go bigger as Daniel suggested)
I'll pick it up with the revised series.
thanks,
Jonathan
> ---
> tools/iio/iio_utils.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
> index 780f201..9d59771 100644
> --- a/tools/iio/iio_utils.h
> +++ b/tools/iio/iio_utils.h
> @@ -13,7 +13,7 @@
> #include <stdint.h>
>
> /* Made up value to limit allocation sizes */
> -#define IIO_MAX_NAME_LENGTH 30
> +#define IIO_MAX_NAME_LENGTH 50
>
> #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
> #define FORMAT_TYPE_FILE "%s_type"
>
^ permalink raw reply
* [PATCH 2/3] iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
From: Jonathan Cameron @ 2017-04-27 5:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492590045-17329-3-git-send-email-eugen.hristev@microchip.com>
On 19/04/17 09:20, Eugen Hristev wrote:
> Added support for the external hardware trigger on pin ADTRG,
> integrated the three possible edge triggers into the subsystem
> and created buffer management for data retrieval
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> ---
> drivers/iio/adc/at91-sama5d2_adc.c | 207 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 204 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
> index e10dca3..09a8c3d 100644
> --- a/drivers/iio/adc/at91-sama5d2_adc.c
> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
> @@ -23,8 +23,15 @@
> #include <linux/platform_device.h>
> #include <linux/sched.h>
> #include <linux/wait.h>
> +#include <linux/slab.h>
> +
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +
> #include <linux/regulator/consumer.h>
>
> /* Control Register */
> @@ -132,6 +139,17 @@
> #define AT91_SAMA5D2_PRESSR 0xbc
> /* Trigger Register */
> #define AT91_SAMA5D2_TRGR 0xc0
> +/* Mask for TRGMOD field of TRGR register */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
> +/* No trigger, only software trigger can start conversions */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
> +/* Trigger Mode external trigger rising edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
> +/* Trigger Mode external trigger falling edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
> +/* Trigger Mode external trigger any edge */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
> +
> /* Correction Select Register */
> #define AT91_SAMA5D2_COSR 0xd0
> /* Correction Value Register */
> @@ -145,14 +163,20 @@
> /* Version Register */
> #define AT91_SAMA5D2_VERSION 0xfc
>
> +#define AT91_SAMA5D2_HW_TRIG_CNT 3
> +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
> +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
> +
> #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
> { \
> .type = IIO_VOLTAGE, \
> .channel = num, \
> .address = addr, \
> + .scan_index = num, \
> .scan_type = { \
> .sign = 'u', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -168,9 +192,11 @@
> .channel = num, \
> .channel2 = num2, \
> .address = addr, \
> + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
> .scan_type = { \
> .sign = 's', \
> .realbits = 12, \
> + .storagebits = 16, \
> }, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> @@ -188,18 +214,26 @@ struct at91_adc_soc_info {
> unsigned max_sample_rate;
> };
>
> +struct at91_adc_trigger {
> + char *name;
> + unsigned int trgmod_value;
> +};
> +
> struct at91_adc_state {
> void __iomem *base;
> int irq;
> struct clk *per_clk;
> struct regulator *reg;
> struct regulator *vref;
> + u16 *buffer;
> int vref_uv;
> const struct iio_chan_spec *chan;
> bool conversion_done;
> u32 conversion_value;
> struct at91_adc_soc_info soc_info;
> wait_queue_head_t wq_data_available;
> + struct iio_trigger **trig;
> + const struct at91_adc_trigger *trigger_list;
> /*
> * lock to prevent concurrent 'single conversion' requests through
> * sysfs.
> @@ -207,6 +241,21 @@ struct at91_adc_state {
> struct mutex lock;
> };
>
> +static const struct at91_adc_trigger at91_adc_trigger_list[] = {
> + {
> + .name = "external-rising",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
> + },
> + {
> + .name = "external-falling",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
> + },
> + {
> + .name = "external-any",
> + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
> + },
> +};
> +
> static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
> AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
> @@ -226,8 +275,141 @@ static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
> AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
> AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
> + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
> + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
> };
>
> +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
> +{
> + struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> + struct at91_adc_state *st = iio_priv(indio);
> + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
> + u8 bit;
> + int i;
> +
> + /* clear TRGMOD */
> + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
> +
> + /* if we are disabling the trigger, it's enough to clear TRGMOD */
> + if (!state) {
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
> + kfree(st->buffer);
Would normally expect to see elements related to the buffer in the
preenable callback for the buffer. In this case it might not make
much difference, but that's conceptually where it belongs.
> + return 0;
> + }
> +
> + st->buffer = kmalloc(indio->scan_bytes, GFP_KERNEL);
How big does this get? I'd be tempted to just use a fixed size big
enough to take the maximum possible. Will probably end up more
efficient than allocating it separately. Not to mention slightly
simplified code.
> + if (!st->buffer)
> + return -ENOMEM;
> +
> + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++) {
> + if (!strstr(trig->name, st->trigger_list[i].name)) {
> + status |= st->trigger_list[i].trgmod_value;
> + break;
> + }
> + }
> +
> + /* setup hw trigger */
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
> + }
> +
> + return 0;
> +}
> +
> +static const struct iio_trigger_ops at91_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> + .set_trigger_state = &at91_adc_configure_trigger,
> +};
> +
> +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
> + char *trigger_name)
> +{
> + struct iio_trigger *trig;
> + int ret;
> +
> + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
> + indio->id, trigger_name);
> + if (!trig)
> + return NULL;
> +
> + trig->dev.parent = indio->dev.parent;
> + iio_trigger_set_drvdata(trig, indio);
> + trig->ops = &at91_adc_trigger_ops;
> +
> + ret = devm_iio_trigger_register(&indio->dev, trig);
> +
> + if (ret)
> + return NULL;
> +
> + return trig;
> +}
> +
> +static int at91_adc_trigger_init(struct iio_dev *indio)
> +{
> + struct at91_adc_state *st = iio_priv(indio);
> + int i;
> +
> + st->trig = devm_kzalloc(&indio->dev,
> + AT91_SAMA5D2_HW_TRIG_CNT * sizeof(*st->trig),
> + GFP_KERNEL);
Given it's a fixed sized allocation, why not just make the resulting array
part of st directly?
> +
> + if (!st->trig) {
> + dev_err(&indio->dev, "could not allocate trig list memory\n");
> + return -ENOMEM;
> + }
> +
> + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++) {
> + st->trig[i] = at91_adc_allocate_trigger(indio,
> + st->trigger_list[i].name);
> + if (!st->trig[i]) {
> + dev_err(&indio->dev,
> + "could not allocate trigger %d\n", i);
> + return -ENOMEM;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio = pf->indio_dev;
> + struct at91_adc_state *st = iio_priv(indio);
> + int i = 0;
> + u8 bit;
> +
> + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
> + struct iio_chan_spec const *chan = indio->channels + bit;
> +
> + st->buffer[i] = at91_adc_readl(st, chan->address);
> + i++;
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
> +
> + iio_trigger_notify_done(indio->trig);
> +
> + /* Needed to ACK the DRDY interruption */
> + at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> +
> + enable_irq(st->irq);
Unusual to have to disable the irq until this point. Firstly
if you did need to do this, it should be in the tryreeenable callback.
You haven't restricted this trigger to just this device, so other
drivers could be hanging of it.
Secondly this irq is always defined to be a threaded oneshot irq
so it should be nicely masked anyway.
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int at91_adc_buffer_init(struct iio_dev *indio)
> +{
> + return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> + &iio_pollfunc_store_time,
> + &at91_adc_trigger_handler, NULL);
This particular wrapper doesn't seem to add much over having it
inline. I'd be tempted to drop it but unimportant if you'd rather
keep it.
> +}
> +
> static unsigned at91_adc_startup_time(unsigned startup_time_min,
> unsigned adc_clk_khz)
> {
> @@ -293,14 +475,19 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
> u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
>
> - if (status & imr) {
> + if (!(status & imr))
> + return IRQ_NONE;
> +
> + if (iio_buffer_enabled(indio)) {
> + disable_irq_nosync(irq);
> + iio_trigger_poll(indio->trig);
> + } else {
> st->conversion_value = at91_adc_readl(st, st->chan->address);
> st->conversion_done = true;
> wake_up_interruptible(&st->wq_data_available);
> - return IRQ_HANDLED;
> }
>
> - return IRQ_NONE;
> + return IRQ_HANDLED;
> }
>
> static int at91_adc_read_raw(struct iio_dev *indio_dev,
> @@ -406,6 +593,8 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> st = iio_priv(indio_dev);
>
> + st->trigger_list = at91_adc_trigger_list;Given it's const, why not just use it directly?
> +
> ret = of_property_read_u32(pdev->dev.of_node,
> "atmel,min-sample-rate-hz",
> &st->soc_info.min_sample_rate);
> @@ -499,6 +688,18 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> + ret = at91_adc_buffer_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> + ret = at91_adc_trigger_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't setup the triggers.\n");
> + goto per_clk_disable_unprepare;
> + }
> +
> ret = iio_device_register(indio_dev);
> if (ret < 0)
> goto per_clk_disable_unprepare;
>
^ permalink raw reply
* [PATCH 1/1] rtc: gemini: add return value validation
From: Hans Ulli Kroll @ 2017-04-27 4:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492951687-16777-1-git-send-email-bianpan201602@163.com>
HI Pan,
On Sun, 23 Apr 2017, Pan Bian wrote:
> From: Pan Bian <bianpan2016@163.com>
>
> Function devm_ioremap() will return a NULL pointer if it fails to remap
> IO address, and its return value should be validated before it is used.
> However, in function gemini_rtc_probe(), its return value is not
> checked. This may result in bad memory access bugs on future access,
> e.g. calling the function gemini_rtc_read_time().
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
> ---
> drivers/rtc/rtc-gemini.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/rtc/rtc-gemini.c b/drivers/rtc/rtc-gemini.c
> index ccf0dba..5279390 100644
> --- a/drivers/rtc/rtc-gemini.c
> +++ b/drivers/rtc/rtc-gemini.c
> @@ -139,6 +139,8 @@ static int gemini_rtc_probe(struct platform_device *pdev)
>
> rtc->rtc_base = devm_ioremap(dev, res->start,
> resource_size(res));
> + if (!rtc->rtc_base)
> + return -ENOMEM;
>
> ret = devm_request_irq(dev, rtc->rtc_irq, gemini_rtc_interrupt,
> IRQF_SHARED, pdev->name, dev);
> --
> 1.9.1
>
>
>
Acked-by: Hans Ulli Kroll <ulli.kroll@googlemail.com>
^ permalink raw reply
* [PATCH net-next 1/9] drivers: net: xgene: Protect indirect MAC access
From: Iyappan Subramanian @ 2017-04-27 4:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d23578a5-fedd-accd-c49b-12200440b9ca@gmail.com>
On Wed, Apr 26, 2017 at 5:06 PM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> On 04/26/2017 04:38 PM, Iyappan Subramanian wrote:
>> From: Quan Nguyen <qnguyen@apm.com>
>>
>> This patch adds lock to protect indirect mac access sequence.
>>
>> Signed-off-by: Quan Nguyen <qnguyen@apm.com>
>> Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
>> ---
>> drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 2 ++
>> drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 1 +
>> drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 +
>> drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 7 ++++++-
>> drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 ++
>> 5 files changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> index 2a835e0..3697ba7 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> @@ -365,9 +365,11 @@ static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
>> cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
>> cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
>>
>> + spin_lock(&pdata->mac_lock);
>> if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
>> netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
>> rd_addr);
>> + spin_unlock(&pdata->mac_lock);
>
> Why not fold the spinlock manipulation within xgenet_enet_rd_indirect()?
> That way the caller does not have to know that acquiring the spinlock is
> required and you avoid potential bugs in the future where you are
> missing the spinlock on indirect accesses?
Thanks. We'll do that and post the next version.
> --
> Florian
^ permalink raw reply
* Touchscreen failure with CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
From: Fabio Estevam @ 2017-04-27 2:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHCN7xJ70S49E9w+jEzBUhgiyakLvVyMkRzPaULxRLVwjN3+cg@mail.gmail.com>
On Wed, Apr 26, 2017 at 11:01 PM, Adam Ford <aford173@gmail.com> wrote:
> I held it for nearly six minutes while checking out facebook (I am not
> sure why I did that part). After 6 minutes it was still operational.
>
> I should note that I am running 4.9.23
Thanks for testing. I will keep investigating.
^ permalink raw reply
* Touchscreen failure with CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
From: Adam Ford @ 2017-04-27 2:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5B95OEhUgBtV+S3q5rMVJ89zDYB5wMJs=vUaZF28Wivjg@mail.gmail.com>
On Wed, Apr 26, 2017 at 8:50 PM, Fabio Estevam <festevam@gmail.com> wrote:
> On Wed, Apr 26, 2017 at 9:57 PM, Adam Ford <aford173@gmail.com> wrote:
>
>> Using my board set to ondemand (and I verified frequency)
>> # cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq
>> 396000
>>
>> I ran it for 3 hours and it and continued to show results.
>
> Thanks for testing.
>
> Does evtest still work if you keep constantly touching the screen
> after one or two minutes?
I held it for nearly six minutes while checking out facebook (I am not
sure why I did that part). After 6 minutes it was still operational.
I should note that I am running 4.9.23
# evtest /dev/input/event0
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x0 product 0x7d4 version 0x0
Input device name: "TSC200X touchscreen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 2331
Min 0
Max 4095
Fuzz 4
Event code 1 (ABS_Y)
Value 1540
Min 0
Max 4095
Fuzz 7
Event code 24 (ABS_PRESSURE)
Value 0
Min 0
Max 2048
Fuzz 2
^ permalink raw reply
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