* [PATCH] ARM: dts: sun8i-q8-common: enable bluetooth on SDIO Wi-Fi
From: Maxime Ripard @ 2016-12-16 12:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161213233658.atGuNCNY@smtp1h.mail.yandex.net>
On Fri, Dec 09, 2016 at 07:49:00PM +0800, Icenowy Zheng wrote:
>
> 2016?12?9? ??4:07? Maxime Ripard <maxime.ripard@free-electrons.com>???
> >
> > On Tue, Dec 06, 2016 at 04:08:38PM +0800, Icenowy Zheng wrote:
> > > Some SDIO Wi-Fi chips (such as RTL8703AS) have a UART bluetooth, which
> > > has a dedicated enable pin (PL8 in the reference design).
> > >
> > > Enable the pin in the same way as the WLAN enable pins.
> > >
> > > Tested on an A33 Q8 tablet with RTL8703AS.
> > >
> > > Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> > > ---
> > >
> > > This patch should be coupled with the uart1 node patch I send before:
> > > http://lists.infradead.org/pipermail/linux-arm-kernel/2016-December/471997.html
> > >
> > > For RTL8703AS, the rtl8723bs bluetooth code is used, which can be retrieve from:
> > > https://github.com/lwfinger/rtl8723bs_bt
> > >
> > >? arch/arm/boot/dts/sun8i-q8-common.dtsi | 2 +-
> > >? 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi
> > > index c676940..4aeb5bb 100644
> > > --- a/arch/arm/boot/dts/sun8i-q8-common.dtsi
> > > +++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi
> > > @@ -88,7 +88,7 @@
> > >?
> > >? &r_pio {
> > >? wifi_pwrseq_pin_q8: wifi_pwrseq_pin at 0 {
> > > - pins = "PL6", "PL7", "PL11";
> > > + pins = "PL6", "PL7", "PL8", "PL11";
> > >? function = "gpio_in";
> > >? bias-pull-up;
> > >? };
> >
> > There's several things wrong here. The first one is that you rely
> > solely on the pinctrl state to maintain a reset line. This is very
> > fragile (especially since the GPIO pinctrl state are likely to go away
> > at some point), but it also means that if your driver wants to recover
> > from that situation at some point, it won't work.
> >
> > The other one is that the bluetooth and wifi chips are two devices in
> > linux, and you assign that pin to the wrong device (wifi).
> >
> > rfkill-gpio is made just for that, so please use it.
>
> The GPIO is not for the radio, but for the full Bluetooth part.
I know.
> If it's set to 0, then the bluetooth part will reset, and the
> hciattach will fail.
Both rfkill-gpio and rfkill-regulator will shutdown when called
(either by poking the reset pin or shutting down the regulator), so
that definitely seems like an expected behavior to put the device in
reset.
> The BSP uses this as a rfkill, and the result is that the bluetooth
> on/off switch do not work properly.
Then rfkill needs fixing, but working around it by hoping that the
core will probe an entirely different device, and enforcing a default
that the rest of the kernel might or might not change is both fragile
and wrong.
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/20161216/7af246ff/attachment.sig>
^ permalink raw reply
* [PATCH v10 7/8] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl
From: Peter Maydell @ 2016-12-16 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4272e489-7aa4-b77d-ec09-22b58af78336@redhat.com>
On 16 December 2016 at 12:07, Auger Eric <eric.auger@redhat.com> wrote:
> Hi Vijaya,
>
> On 01/12/2016 08:09, vijay.kilari at gmail.com wrote:
>> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
>> + const u64 val)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < 32; i++) {
>> + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
> same as above.
>> + spin_lock(&irq->irq_lock);
>> + if (val & (1U << i)) {
>> + if (irq->config == VGIC_CONFIG_LEVEL) {
>> + irq->line_level = true;
>> + irq->pending = true;
>> + vgic_queue_irq_unlock(vcpu->kvm, irq);
>> + } else {
>> + spin_unlock(&irq->irq_lock);
>> + }
>> + } else {
>> + if (irq->config == VGIC_CONFIG_EDGE ||
> can't we just ignore VGIC_CONFIG_EDGE case for which line_level is not
> modeled?
>> + (irq->config == VGIC_CONFIG_LEVEL &&
>> + !irq->soft_pending))
>> + irq->line_level = false;
> To me the line level does not depend on the soft_pending bit. The
> pending state depends on both.
Without having looked at the details, it seems surprising to
me that the implementation of "set line level to X" is not
"set irq->line_level to X; figure out consequences and update
other state as necessary"...
thanks
-- PMM
^ permalink raw reply
* [PATCH v9 01/11] arm/arm64: vgic: Implement support for userspace access
From: Auger Eric @ 2016-12-16 12:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CALicx6vgdVFMM7fACsGO6UKsXYA-oE__-e0pxvUyJsExKczoSQ@mail.gmail.com>
Hi Vijaya,
On 15/12/2016 08:36, Vijay Kilari wrote:
> On Tue, Dec 6, 2016 at 5:12 PM, Auger Eric <eric.auger@redhat.com> wrote:
>> Hi,
>>
>> On 28/11/2016 14:05, Christoffer Dall wrote:
>>> On Wed, Nov 23, 2016 at 06:31:48PM +0530, vijay.kilari at gmail.com wrote:
>>>> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>>>>
>>>> Read and write of some registers like ISPENDR and ICPENDR
>>>> from userspace requires special handling when compared to
>>>> guest access for these registers.
>>>>
>>>> Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
>>>> for handling of ISPENDR, ICPENDR registers handling.
>>>>
>>>> Add infrastructure to support guest and userspace read
>>>> and write for the required registers
>>>> Also moved vgic_uaccess from vgic-mmio-v2.c to vgic-mmio.c
>>>>
>>>> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>>>> ---
>>>> virt/kvm/arm/vgic/vgic-mmio-v2.c | 25 ----------
>>>> virt/kvm/arm/vgic/vgic-mmio-v3.c | 102 ++++++++++++++++++++++++++++++++-------
>>>> virt/kvm/arm/vgic/vgic-mmio.c | 78 +++++++++++++++++++++++++++---
>>>> virt/kvm/arm/vgic/vgic-mmio.h | 19 ++++++++
>>>> 4 files changed, 175 insertions(+), 49 deletions(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index b44b359..0b32f40 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -406,31 +406,6 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>>>> return -ENXIO;
>>>> }
>>>>
>>>> -/*
>>>> - * When userland tries to access the VGIC register handlers, we need to
>>>> - * create a usable struct vgic_io_device to be passed to the handlers and we
>>>> - * have to set up a buffer similar to what would have happened if a guest MMIO
>>>> - * access occurred, including doing endian conversions on BE systems.
>>>> - */
>>>> -static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
>>>> - bool is_write, int offset, u32 *val)
>>>> -{
>>>> - unsigned int len = 4;
>>>> - u8 buf[4];
>>>> - int ret;
>>>> -
>>>> - if (is_write) {
>>>> - vgic_data_host_to_mmio_bus(buf, len, *val);
>>>> - ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
>>>> - } else {
>>>> - ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
>>>> - if (!ret)
>>>> - *val = vgic_data_mmio_bus_to_host(buf, len);
>>>> - }
>>>> -
>>>> - return ret;
>>>> -}
>>>> -
>>>> int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>>> int offset, u32 *val)
>>>> {
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> index 50f42f0..8e76d04 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> @@ -207,6 +207,66 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
>>>> return 0;
>>>> }
>>>>
>>>> +static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
>>>> + gpa_t addr, unsigned int len)
>>>> +{
>>>> + u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>>>> + u32 value = 0;
>>>> + int i;
>>>> +
>>>> + /*
>>>> + * A level triggerred interrupt pending state is latched in both
>>>> + * "soft_pending" and "line_level" variables. Userspace will save
>>>> + * and restore soft_pending and line_level separately.
>>>> + * Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
>>>> + * handling of ISPENDR and ICPENDR.
>>>> + */
>>>> + for (i = 0; i < len * 8; i++) {
>>>> + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>>>> +
>>>> + if (irq->config == VGIC_CONFIG_LEVEL && irq->soft_pending)
>>>> + value |= (1U << i);
>>>> + if (irq->config == VGIC_CONFIG_EDGE && irq->pending)
>>>> + value |= (1U << i);
>>>> +
>>>> + vgic_put_irq(vcpu->kvm, irq);
>>>> + }
>>>> +
>>>> + return value;
>>>> +}
>>>> +
>>>> +static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
>>>> + gpa_t addr, unsigned int len,
>>>> + unsigned long val)
>>>> +{
>>>> + u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>>>> + int i;
>>>> +
>>>> + for (i = 0; i < len * 8; i++) {
>>>> + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>>>> +
>>>> + spin_lock(&irq->irq_lock);
>>>> + if (test_bit(i, &val)) {
>>>> + /* soft_pending is set irrespective of irq type
>>>> + * (level or edge) to avoid dependency that VM should
>>>> + * restore irq config before pending info.
>>>> + */
>>>
>>> nit: kernel commenting style
>>>
>>>> + irq->pending = true;
>>>> + irq->soft_pending = true;
>>>> + vgic_queue_irq_unlock(vcpu->kvm, irq);
>>>> + } else {
>>>> + irq->soft_pending = false;
>>>> + if (irq->config == VGIC_CONFIG_EDGE ||
>>>> + (irq->config == VGIC_CONFIG_LEVEL &&
>>>> + !irq->line_level))
>>>> + irq->pending = false;
>> I am confused by the comment above. Since we test the irq config here
>> don't we assume the config was restored before the pending state?
>>>> + spin_unlock(&irq->irq_lock);
>>>> + }
>>>> +
>>>> + vgic_put_irq(vcpu->kvm, irq);
>>>> + }
>>>> +}
>>>> +
>>>> /* We want to avoid outer shareable. */
>>>> u64 vgic_sanitise_shareability(u64 field)
>>>> {
>>>> @@ -356,7 +416,7 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
>>>> * We take some special care here to fix the calculation of the register
>>>> * offset.
>>>> */
>>>> -#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc) \
>>>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, ur, uw, bpi, acc) \
>>>> { \
>>>> .reg_offset = off, \
>>>> .bits_per_irq = bpi, \
>>>> @@ -371,6 +431,8 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
>>>> .access_flags = acc, \
>>>> .read = rd, \
>>>> .write = wr, \
>>>> + .uaccess_read = ur, \
>>>> + .uaccess_write = uw, \
>>>> }
>>>>
>>>> static const struct vgic_register_region vgic_v3_dist_registers[] = {
>>>> @@ -378,40 +440,42 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
>>>> vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>>>> - vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
>>>> + vgic_mmio_read_rao, vgic_mmio_write_wi, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>>>> - vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
>>>> + vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
>>>> - vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
>>>> + vgic_mmio_read_enable, vgic_mmio_write_cenable, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
>>>> - vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
>>>> + vgic_mmio_read_pending, vgic_mmio_write_spending,
>>>> + vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
>>>> - vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
>>>> + vgic_mmio_read_pending, vgic_mmio_write_cpending,
>>>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
>>>> - vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
>>>> + vgic_mmio_read_active, vgic_mmio_write_sactive, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
>>>> - vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
>>>> + vgic_mmio_read_active, vgic_mmio_write_cactive, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
>>>> - vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
>>>> - VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>>>> + vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
>>>> + 8, VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
>>>> - vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
>>>> + vgic_mmio_read_raz, vgic_mmio_write_wi, NULL, NULL, 8,
>>>> VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
>>>> - vgic_mmio_read_config, vgic_mmio_write_config, 2,
>>>> + vgic_mmio_read_config, vgic_mmio_write_config, NULL, NULL, 2,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>>>> - vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
>>>> + vgic_mmio_read_raz, vgic_mmio_write_wi, NULL, NULL, 1,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>>>> - vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
>>>> + vgic_mmio_read_irouter, vgic_mmio_write_irouter, NULL, NULL, 64,
>>>> VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>>>> vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
>>>> @@ -449,11 +513,13 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
>>>> REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
>>>> vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
>>>> VGIC_ACCESS_32bit),
>>>> - REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
>>>> - vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
>>>> + REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISPENDR0,
>>>> + vgic_mmio_read_pending, vgic_mmio_write_spending,
>>>> + vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4,
>>>> VGIC_ACCESS_32bit),
>>>> - REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
>>>> - vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
>>>> + REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICPENDR0,
>>>> + vgic_mmio_read_pending, vgic_mmio_write_cpending,
>>>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
>>>> VGIC_ACCESS_32bit),
>>>> REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
>>>> vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> index ebe1b9f..d5f3ee2 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> @@ -484,6 +484,74 @@ static bool check_region(const struct kvm *kvm,
>>>> return false;
>>>> }
>>>>
>>>> +static const struct vgic_register_region *
>>>> +vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev,
>>>> + gpa_t addr, int len)
>>>> +{
>>>> + const struct vgic_register_region *region;
>>>> +
>>>> + region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
>>>> + addr - iodev->base_addr);
>>>> + if (!region || !check_region(vcpu->kvm, region, addr, len))
>>>> + return NULL;
>>>> +
>>>> + return region;
>>>> +}
>>>> +
>>>> +static int vgic_uaccess_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
>>>> + gpa_t addr, u32 *val)
>>>> +{
>>>> + struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
>>>> + const struct vgic_register_region *region;
>>>> + struct kvm_vcpu *r_vcpu;
>>>> +
>>>> + region = vgic_get_mmio_region(vcpu, iodev, addr, sizeof(u32));
>>>> + if (!region) {
>>>> + *val = 0;
>>>> + return 0;
>> do we really want to return 0 here? -ENXIO?
>> I see that dispatch_mmio_read/write return 0 in that case but I don't
>> see any reason either? Other kvm_io_device_ops seem to return
>> -EOPNOTSUPP in such a case.
>
> Yes, This was discussed and decided to fix it outside of this series.
>
> https://www.spinics.net/lists/arm-kernel/msg533695.html
OK. Sorry I missed that. Other comments I sent on v9 remain applicable
on v10 I think.
Thanks
Eric
>
> _______________________________________________
> 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] arm: dt: Initialize boot_command_line from CONFIG_CMDLINE in case DT does not provide /chosen/bootargs
From: Javier Martinez Canillas @ 2016-12-16 12:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201612161332.36406@pali>
Hello Pali,
On 12/16/2016 09:32 AM, Pali Roh?r wrote:
> Hi!
>
> On Friday 16 December 2016 13:13:34 Javier Martinez Canillas wrote:
>> Hello Pali,
>>
>> On 12/16/2016 08:46 AM, Pali Roh?r wrote:
>>> On Thursday 15 December 2016 01:09:20 Pali Roh?r wrote:
>>>> On Thursday 15 December 2016 00:52:24 Russell King - ARM Linux
>>>> wrote:
>>>>> On Wed, Dec 14, 2016 at 10:12:43PM +0100, Pali Roh?r wrote:
>>>>>> Commit 008a2ebcd677 ("ARM: dts: omap3: Remove skeleton.dtsi
>>>>>> usage") broke support for setting cmdline on Nokia N900 via
>>>>>> CONFIG_CMDLINE.
>>>>>>
>>>>>> It is because arm code booted in DT mode parse cmdline only via
>>>>>> function early_init_dt_scan_chosen() and that function does not
>>>>>> fill variable boot_command_line when DTB does not contain
>>>>>> /chosen entry. It is called from function
>>>>>> early_init_dt_scan_nodes() in setup_machine_fdt().
>>>>>>
>>>>>> This patch fixes it by explicitly filling boot_command_line in
>>>>>> function setup_machine_fdt() after calling
>>>>>> early_init_dt_scan_nodes() in case boot_command_line still
>>>>>> remains empty.
>>>>>
>>>>> This looks like a hack.
>>>>>
>>>>> First, the matter of the ATAGs compatibility. The decompressor
>>>>> relies on there being a pre-existing /chosen node to insert the
>>>>> command line and other parameters into. If we've dropped it (by
>>>>> dropping skeleton.dtsi) then we've just regressed more than just
>>>>> N900 - the decompressor won't be able to merge the ATAGs into the
>>>>> concatenated FDT.
>>>>
>>>> Hm... I did not think about it. But right this can be broken
>>>> too...
>>>
>>> Tony, Javier: are you aware of above ??? problem?
>>>
>>> It looks like commit 008a2ebcd677 ("ARM: dts: omap3: Remove
>>> skeleton.dtsi usage") should be really reverted.
>>
>> I don't think reverting the mentioned commit is the correct fix for
>> your problem. We are trying to get rid of skeleton.dtsi for many
>> reasons, see commit commit ("3ebee5a2e141 arm64: dts: kill
>> skeleton.dtsi").
>
> $ git show 3ebee5a2e141
>
> * The default empty /chosen and /aliases are somewhat useless...
>
> That is not truth, they are not useless as Russell King wrote --
> removing them break ATAG support.
>
> (But that commit is for arm64 which probably is not using ATAGs... But I
> do not know. At least it is not truth for 32bit arm.)
>
>> Also, the chosen node is mentioned to be optional in the ePAPR
>> document and u-boot creates a chosen node if isn't found [0] so this
>> issue is only present in boards that don't use u-boot like the
>> N900/N950/N9 phones.
>
> Linux arm decompressor does not propagate ATAGs when /chosen is missing.
> Sorry, but if for Linux /chosen is required (and without it is broken!)
> then some ePARP document does not apply there. Either Linux code needs
> to be fixed (so /chosen will be really only optional) or /chosen stay in
> Linux required. There is no other option.
>
> And I hope that U-boot is not the only one bootloader which Linux kernel
> supports. I thought that I can use *any* bootloader to boot Linux kernel
> not just U-Boot which is doing some magic...
>
> With this step you are basically going to break booting Linux kernel
> with all others bootloaders... And personally I really dislike this
> idea.
>
>> So if NOLO doesn't do the same than u-boot and the kernel expects a
>> chosen node, I suggest to add an empty chosen node in the
>> omap3-n900.dts and omap3-n950-n9.dtsi device tree source files.
>
> That would fix a problem for N900, N950 and N9. But not for all other
> ARM devices which bootloader pass some ATAGs.
>
> IIRC rule of kernel is not to break compatibility and that commit
> 008a2ebcd677 really did it.
>
> Note: I'm not saying if 008a2ebcd677 is good or bad. I'm just saying
> that it cause problems which need to be properly fixed. And if fixing
> them is harder and will take more time, then correct option is to revert
> 008a2ebcd677 due to breaking support for more devices.
>
If you think that others boards may have the same issue, then you could
add an empty chosen node to omap3.dtsi. As I said I think that in practice
this will only be needed for the machines using NOLO but you are right
that in theory you could boot them using other bootloaders and having an
empty node doesn't cause any harm anyway.
>> [0]:
>> http://git.denx.de/?p=u-boot.git;a=blob;f=common/fdt_support.c;h=c9f
>> 7019e38e8de1469f506cdd57353fd27d8e134;hb=HEAD#l226
>>
>> Best regards,
>
Best regards,
--
Javier Martinez Canillas
Open Source Group
Samsung Research America
^ permalink raw reply
* [PATCH] pinctrl: stm32: activate strict mux mode
From: Patrice Chotard @ 2016-12-16 12:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481725456-1030-1-git-send-email-gabriel.fernandez@st.com>
On 12/14/2016 03:24 PM, gabriel.fernandez at st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>
> This activates strict mode muxing for the STM32 pin controllers,
> as these do not allow GPIO and functions to use the same pin
> simultaneously.
>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> ---
> drivers/pinctrl/stm32/pinctrl-stm32.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
> index efc4371..c983a1e 100644
> --- a/drivers/pinctrl/stm32/pinctrl-stm32.c
> +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
> @@ -631,6 +631,7 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
> .get_function_groups = stm32_pmx_get_func_groups,
> .set_mux = stm32_pmx_set_mux,
> .gpio_set_direction = stm32_pmx_gpio_set_direction,
> + .strict = true,
> };
>
> /* Pinconf functions */
>
Hi Gaby
Acked-by: Patrice Chotard <patrice.chotard@st.com>
regards
^ permalink raw reply
* [RESEND PATCH 2/2] arm64: make WANT_HUGE_PMD_SHARE depends on HUGETLB_PAGE
From: Will Deacon @ 2016-12-16 12:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5853AF6D.20305@huawei.com>
On Fri, Dec 16, 2016 at 05:10:05PM +0800, zhong jiang wrote:
> On 2016/12/14 22:19, zhongjiang wrote:
> > From: zhong jiang <zhongjiang@huawei.com>
> >
> > when HUGETLB_PAGE is disable, WANT_HUGE_PMD_SHARE contains the
> > fuctions should not be use. therefore, we add the dependency.
> >
> > Signed-off-by: zhong jiang <zhongjiang@huawei.com>
> > ---
> > arch/arm64/Kconfig | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 969ef88..694ca73 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -640,6 +640,7 @@ config SYS_SUPPORTS_HUGETLBFS
> >
> > config ARCH_WANT_HUGE_PMD_SHARE
> > def_bool y if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
> > + depends on HUGETLB_PAGE
> >
> > config ARCH_HAS_CACHE_LINE_SIZE
> > def_bool y
> Hi,
> I still think it is a issue. Perhaps above changelog is unclear. Further explain is as follows.
> when hugetlb_pages is disable and arch_want_huge_pmd_share is enable, we maybe call
> huge_pmd_sahre in hugetlbpage.c, but the function actually is not definition as it is not
> exported. is it right ??
The only users of ARCH_WANT_HUGE_PMD_SHARE on arm64 are:
arch/arm64/mm/hugetlbpage.c: if (IS_ENABLED(CONFIG_ARCH_WANT_HUGE_PMD_SHARE) &&
mm/hugetlb.c:#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
mm/hugetlb.c:#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
mm/hugetlb.c:#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
and neither of those files are compiled if !HUGETLB_PAGE.
Are you actually seeing a problem here?
Will
^ permalink raw reply
* [PATCH] arm: dt: Initialize boot_command_line from CONFIG_CMDLINE in case DT does not provide /chosen/bootargs
From: Pali Rohár @ 2016-12-16 12:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <029ec718-89c0-b08e-de7e-279946c1a9bd@osg.samsung.com>
Hi!
On Friday 16 December 2016 13:13:34 Javier Martinez Canillas wrote:
> Hello Pali,
>
> On 12/16/2016 08:46 AM, Pali Roh?r wrote:
> > On Thursday 15 December 2016 01:09:20 Pali Roh?r wrote:
> >> On Thursday 15 December 2016 00:52:24 Russell King - ARM Linux
> >> wrote:
> >>> On Wed, Dec 14, 2016 at 10:12:43PM +0100, Pali Roh?r wrote:
> >>>> Commit 008a2ebcd677 ("ARM: dts: omap3: Remove skeleton.dtsi
> >>>> usage") broke support for setting cmdline on Nokia N900 via
> >>>> CONFIG_CMDLINE.
> >>>>
> >>>> It is because arm code booted in DT mode parse cmdline only via
> >>>> function early_init_dt_scan_chosen() and that function does not
> >>>> fill variable boot_command_line when DTB does not contain
> >>>> /chosen entry. It is called from function
> >>>> early_init_dt_scan_nodes() in setup_machine_fdt().
> >>>>
> >>>> This patch fixes it by explicitly filling boot_command_line in
> >>>> function setup_machine_fdt() after calling
> >>>> early_init_dt_scan_nodes() in case boot_command_line still
> >>>> remains empty.
> >>>
> >>> This looks like a hack.
> >>>
> >>> First, the matter of the ATAGs compatibility. The decompressor
> >>> relies on there being a pre-existing /chosen node to insert the
> >>> command line and other parameters into. If we've dropped it (by
> >>> dropping skeleton.dtsi) then we've just regressed more than just
> >>> N900 - the decompressor won't be able to merge the ATAGs into the
> >>> concatenated FDT.
> >>
> >> Hm... I did not think about it. But right this can be broken
> >> too...
> >
> > Tony, Javier: are you aware of above ??? problem?
> >
> > It looks like commit 008a2ebcd677 ("ARM: dts: omap3: Remove
> > skeleton.dtsi usage") should be really reverted.
>
> I don't think reverting the mentioned commit is the correct fix for
> your problem. We are trying to get rid of skeleton.dtsi for many
> reasons, see commit commit ("3ebee5a2e141 arm64: dts: kill
> skeleton.dtsi").
$ git show 3ebee5a2e141
* The default empty /chosen and /aliases are somewhat useless...
That is not truth, they are not useless as Russell King wrote --
removing them break ATAG support.
(But that commit is for arm64 which probably is not using ATAGs... But I
do not know. At least it is not truth for 32bit arm.)
> Also, the chosen node is mentioned to be optional in the ePAPR
> document and u-boot creates a chosen node if isn't found [0] so this
> issue is only present in boards that don't use u-boot like the
> N900/N950/N9 phones.
Linux arm decompressor does not propagate ATAGs when /chosen is missing.
Sorry, but if for Linux /chosen is required (and without it is broken!)
then some ePARP document does not apply there. Either Linux code needs
to be fixed (so /chosen will be really only optional) or /chosen stay in
Linux required. There is no other option.
And I hope that U-boot is not the only one bootloader which Linux kernel
supports. I thought that I can use *any* bootloader to boot Linux kernel
not just U-Boot which is doing some magic...
With this step you are basically going to break booting Linux kernel
with all others bootloaders... And personally I really dislike this
idea.
> So if NOLO doesn't do the same than u-boot and the kernel expects a
> chosen node, I suggest to add an empty chosen node in the
> omap3-n900.dts and omap3-n950-n9.dtsi device tree source files.
That would fix a problem for N900, N950 and N9. But not for all other
ARM devices which bootloader pass some ATAGs.
IIRC rule of kernel is not to break compatibility and that commit
008a2ebcd677 really did it.
Note: I'm not saying if 008a2ebcd677 is good or bad. I'm just saying
that it cause problems which need to be properly fixed. And if fixing
them is harder and will take more time, then correct option is to revert
008a2ebcd677 due to breaking support for more devices.
> [0]:
> http://git.denx.de/?p=u-boot.git;a=blob;f=common/fdt_support.c;h=c9f
> 7019e38e8de1469f506cdd57353fd27d8e134;hb=HEAD#l226
>
> Best regards,
--
Pali Roh?r
pali.rohar at gmail.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161216/e81662a3/attachment-0001.sig>
^ permalink raw reply
* [PATCH v10 6/8] arm/arm64: vgic: Implement VGICv3 CPU interface access
From: Auger Eric @ 2016-12-16 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480576187-5012-7-git-send-email-vijay.kilari@gmail.com>
Hi Vijaya,
On 01/12/2016 08:09, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> VGICv3 CPU interface registers are accessed using
> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
> as 64-bit. The cpu MPIDR value is passed along with register id.
> is used to identify the cpu for registers access.
s/is/It is
>
> The VM that supports SEIs expect it on destination machine to handle
> guest aborts and hence checked for ICC_CTLR_EL1.SEIS compatibility.
> Similarly, VM that supports Affinity Level 3 that is required for AArch64
> mode, is required to be supported on destination machine. Hence checked
> for ICC_CTLR_EL1.A3V compatibility.
We make sure ICC_CTLR_EL1 SEIS and A3V are compatible on source and target?
>
> The arch/arm64/kvm/vgic-sys-reg-v3.c handles read and write of VGIC
> CPU registers for AArch64.
>
> For AArch32 mode, arch/arm/kvm/vgic-v3-coproc.c file is created but
> APIs are not implemented.
>
> Updated arch/arm/include/uapi/asm/kvm.h with new definitions
> required to compile for AArch32.
>
> The version of VGIC v3 specification is define here
s/define/defined
> Documentation/virtual/kvm/devices/arm-vgic-v3.txt
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> arch/arm/include/uapi/asm/kvm.h | 2 +
> arch/arm/kvm/Makefile | 4 +-
> arch/arm/kvm/vgic-v3-coproc.c | 35 ++++
> arch/arm64/include/uapi/asm/kvm.h | 3 +
> arch/arm64/kvm/Makefile | 3 +-
> arch/arm64/kvm/vgic-sys-reg-v3.c | 338 ++++++++++++++++++++++++++++++++++++
> include/kvm/arm_vgic.h | 9 +
> virt/kvm/arm/vgic/vgic-kvm-device.c | 28 +++
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 18 ++
> virt/kvm/arm/vgic/vgic-v3.c | 8 +
> virt/kvm/arm/vgic/vgic.h | 4 +
> 11 files changed, 449 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index 0ae6035..98658d9d 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -186,9 +186,11 @@ struct kvm_arch_memory_slot {
> (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
> #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
> +#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
> #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> /* KVM_IRQ_LINE irq field index values */
> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> index d571243..68fb023 100644
> --- a/arch/arm/kvm/Makefile
> +++ b/arch/arm/kvm/Makefile
> @@ -7,7 +7,7 @@ ifeq ($(plus_virt),+virt)
> plus_virt_def := -DREQUIRES_VIRT=1
> endif
>
> -ccflags-y += -Iarch/arm/kvm
> +ccflags-y += -Iarch/arm/kvm -Ivirt/kvm/arm/vgic
> CFLAGS_arm.o := -I. $(plus_virt_def)
> CFLAGS_mmu.o := -I.
>
> @@ -20,7 +20,7 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vf
> obj-$(CONFIG_KVM_ARM_HOST) += hyp/
> obj-y += kvm-arm.o init.o interrupts.o
> obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
> -obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
> +obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o vgic-v3-coproc.o
> obj-y += $(KVM)/arm/aarch32.o
>
> obj-y += $(KVM)/arm/vgic/vgic.o
> diff --git a/arch/arm/kvm/vgic-v3-coproc.c b/arch/arm/kvm/vgic-v3-coproc.c
> new file mode 100644
> index 0000000..f41abf7
> --- /dev/null
> +++ b/arch/arm/kvm/vgic-v3-coproc.c
> @@ -0,0 +1,35 @@
> +/*
> + * VGIC system registers handling functions for AArch32 mode
> + *
> + * 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 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.
> + */
> +
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <asm/kvm_emulate.h>
> +#include "vgic.h"
> +
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + /*
> + * TODO: Implement for AArch32
> + */
> + return -ENXIO;
> +}
> +
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + /*
> + * TODO: Implement for AArch32
> + */
> + return -ENXIO;
> +}
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 56dc08d..91c7137 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
> (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
> #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
> +#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
> #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> +
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> /* Device Control API on vcpu fd */
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index d50a82a..d89aa50 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -2,7 +2,7 @@
> # Makefile for Kernel-based Virtual Machine module
> #
>
> -ccflags-y += -Iarch/arm64/kvm
> +ccflags-y += -Iarch/arm64/kvm -Ivirt/kvm/arm/vgic
> CFLAGS_arm.o := -I.
> CFLAGS_mmu.o := -I.
>
> @@ -19,6 +19,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o
> kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o
> kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
> kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
>
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
> diff --git a/arch/arm64/kvm/vgic-sys-reg-v3.c b/arch/arm64/kvm/vgic-sys-reg-v3.c
> new file mode 100644
> index 0000000..76663f9
> --- /dev/null
> +++ b/arch/arm64/kvm/vgic-sys-reg-v3.c
> @@ -0,0 +1,338 @@
> +/*
> + * VGIC system registers handling functions for AArch64 mode
> + *
> + * 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 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.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <asm/kvm_emulate.h>
> +#include "vgic.h"
> +#include "sys_regs.h"
> +
> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + u32 host_pri_bits, host_id_bits, host_seis, host_a3v, seis, a3v;
> + struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
> + struct vgic_vmcr vmcr;
> + u64 val;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + val = p->regval;
> +
> + /*
> + * Disallow restoring VM state if not supported by this
> + * hardware.
> + */
> + host_pri_bits = ((val & ICC_CTLR_EL1_PRI_BITS_MASK) >>
> + ICC_CTLR_EL1_PRI_BITS_SHIFT) + 1;
I am confused by the "host" terminology. Those are the "source" values
we want to restore and we compare with the destination current value, right?
> + if (host_pri_bits > vgic_v3_cpu->num_pri_bits)
> + return false;
I am lost. Who did set num_pri_bits and num_id_bits we compare with?
Seis and a3v I get this is computed on probe
> +
> + vgic_v3_cpu->num_pri_bits = host_pri_bits;
> +
> + host_id_bits = (val & ICC_CTLR_EL1_ID_BITS_MASK) >>
> + ICC_CTLR_EL1_ID_BITS_SHIFT;
> + if (host_id_bits > vgic_v3_cpu->num_id_bits)
> + return false;
> +
> + vgic_v3_cpu->num_id_bits = host_id_bits;
> +
> + host_seis = ((kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_SEIS_MASK) >> ICH_VTR_SEIS_SHIFT);
> + seis = (val & ICC_CTLR_EL1_SEIS_MASK) >>
> + ICC_CTLR_EL1_SEIS_SHIFT;
> + if (host_seis != seis)
> + return false;
> +
> + host_a3v = ((kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT);
> + a3v = (val & ICC_CTLR_EL1_A3V_MASK) >> ICC_CTLR_EL1_A3V_SHIFT;
> + if (host_a3v != a3v)
> + return false;
> +
> + vmcr.ctlr = val & ICC_CTLR_EL1_CBPR_MASK;
> + vmcr.ctlr |= val & ICC_CTLR_EL1_EOImode_MASK;
nit: I still don't get why the vmcr has CPBR and EOImode set with the
ICC_CTLR_EL1 layout and then this gets transformed in the proper vmcr
format by vgic_set_vmcr. This is confusing to me and would at least
deserve a comment attached to struct vgic_vmcr definition.
Why don't we set the vmcr.ctlr directly in its ICH_VMCR format? In
set/get_vmcr all the other struct vgic_vmcr fields are handled in
ICH_VMCR native layout except the ctrl field.
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + val = 0;
> + val |= (vgic_v3_cpu->num_pri_bits - 1) <<
> + ICC_CTLR_EL1_PRI_BITS_SHIFT;
> + val |= vgic_v3_cpu->num_id_bits << ICC_CTLR_EL1_ID_BITS_SHIFT;
> + val |= ((kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_SEIS_MASK) >> ICH_VTR_SEIS_SHIFT) <<
> + ICC_CTLR_EL1_SEIS_SHIFT;
> + val |= ((kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT) <<
> + ICC_CTLR_EL1_A3V_SHIFT;
> + val |= vmcr.ctlr & ICC_CTLR_EL1_CBPR_MASK;
> + val |= vmcr.ctlr & ICC_CTLR_EL1_EOImode_MASK;
> +
> + p->regval = val;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.pmr = (p->regval & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.pmr << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.bpr = (p->regval & ICC_BPR0_EL1_MASK) >>
> + ICC_BPR0_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.bpr << ICC_BPR0_EL1_SHIFT) &
> + ICC_BPR0_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + if (!p->is_write)
> + p->regval = 0;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) {
> + if (p->is_write) {
> + vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >>
> + ICC_BPR1_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.abpr << ICC_BPR1_EL1_SHIFT) &
> + ICC_BPR1_EL1_MASK;
> + }
> + } else {
> + if (!p->is_write)
> + p->regval = min((vmcr.bpr + 1), 7U);
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen0 = (p->regval & ICC_IGRPEN0_EL1_MASK) >>
> + ICC_IGRPEN0_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen0 << ICC_IGRPEN0_EL1_SHIFT) &
> + ICC_IGRPEN0_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen1 = (p->regval & ICC_IGRPEN1_EL1_MASK) >>
> + ICC_IGRPEN1_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen1 << ICC_IGRPEN1_EL1_SHIFT) &
> + ICC_IGRPEN1_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static void vgic_v3_access_apr_reg(struct kvm_vcpu *vcpu,
> + struct sys_reg_params *p, u8 apr, u8 idx)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> + uint32_t *ap_reg;
> +
> + if (apr)
> + ap_reg = &vgicv3->vgic_ap1r[idx];
> + else
> + ap_reg = &vgicv3->vgic_ap0r[idx];
> +
> + if (p->is_write)
> + *ap_reg = p->regval;
> + else
> + p->regval = *ap_reg;
> +}
> +
> +static bool access_gic_aprn(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r, u8 apr)
> +{
> + struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
> + u8 idx = r->Op2 & 3;
> +
> + /*
> + * num_pri_bits are initialized with HW supported values.
> + * We can rely safely on num_pri_bits even if VM has not
> + * restored ICC_CTLR_EL1 before restoring APnR registers.
> + */
> + switch (vgic_v3_cpu->num_pri_bits) {
> + case 7:
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + break;
> + case 6:
> + if (idx > 1)
> + goto err;
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + break;
> + default:
> + if (idx > 0)
> + goto err;
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + }
> +
> + return true;
> +err:
> + if (!p->is_write)
> + p->regval = 0;
> +
> + return false;
> +}
> +
> +static bool access_gic_ap0r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +
> +{
> + return access_gic_aprn(vcpu, p, r, 0);
> +}
> +
> +static bool access_gic_ap1r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + return access_gic_aprn(vcpu, p, r, 1);
> +}
> +
> +static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> + /* Validate SRE bit */
> + if (p->is_write) {
> + if (!(p->regval & ICC_SRE_EL1_SRE))
> + return false;
> + } else {
> + p->regval = vgicv3->vgic_sre;
> + }
> +
> + return true;
> +}
> +static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
> + /* ICC_PMR_EL1 */
> + { Op0(3), Op1(0), CRn(4), CRm(6), Op2(0), access_gic_pmr },
> + /* ICC_BPR0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(3), access_gic_bpr0 },
> + /* ICC_AP0R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(4), access_gic_ap0r },
> + /* ICC_AP0R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(5), access_gic_ap0r },
> + /* ICC_AP0R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(6), access_gic_ap0r },
> + /* ICC_AP0R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(7), access_gic_ap0r },
> + /* ICC_AP1R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(0), access_gic_ap1r },
> + /* ICC_AP1R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(1), access_gic_ap1r },
> + /* ICC_AP1R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(2), access_gic_ap1r },
> + /* ICC_AP1R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(3), access_gic_ap1r },
> + /* ICC_BPR1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(3), access_gic_bpr1 },
> + /* ICC_CTLR_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(4), access_gic_ctlr },
> + /* ICC_SRE_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(5), access_gic_sre },
> + /* ICC_IGRPEN0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(6), access_gic_grpen0 },
> + /* ICC_GRPEN1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(7), access_gic_grpen1 },
> +};
> +
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
At the beginning I asked myself why we did not OR with KVM_REG_ARM64 as
stated in include/uapi/linux/kvm.h but then looking at
index_to_params() implementation it looks it is not used.
> +
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + if (find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs)))
> + return 0;
> +
> + return -ENXIO;
> +}
> +
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + const struct sys_reg_desc *r;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> +
> + if (is_write)
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + r = find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs));
> + if (!r)
> + return -ENXIO;
> +
> + if (!r->access(vcpu, ¶ms, r))
> + return -EINVAL;
> +
> + if (!is_write)
> + *reg = params.regval;
> +
> + return 0;
> +}
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 002f092..730a18a 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -71,6 +71,9 @@ struct vgic_global {
>
> /* GIC system register CPU interface */
> struct static_key_false gicv3_cpuif;
> +
> + /* Cache ICH_VTR_EL2 reg value */
nit: comment does not bring much value I think
> + u32 ich_vtr_el2;
> };
>
> extern struct vgic_global kvm_vgic_global_state;
> @@ -269,6 +272,12 @@ struct vgic_cpu {
> u64 pendbaser;
>
> bool lpis_enabled;
> +
> + /* Cache guest priority bits */
> + u32 num_pri_bits;
> +
> + /* Cache guest interrupt ID bits */
> + u32 num_id_bits;
> };
>
> extern struct static_key_false vgic_v2_cpuif_trap;
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index bc7de95..b6266fe 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -16,6 +16,7 @@
> #include <linux/kvm_host.h>
> #include <kvm/arm_vgic.h>
> #include <linux/uaccess.h>
> +#include <asm/kvm_emulate.h>
not needed I think
Thanks
Eric
> #include <asm/kvm_mmu.h>
> #include "vgic.h"
>
> @@ -501,6 +502,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
> if (!is_write)
> *reg = tmp32;
> break;
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 regid;
> +
> + regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
> + regid, reg);
> + break;
> + }
> default:
> ret = -EINVAL;
> break;
> @@ -534,6 +543,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
> reg = tmp32;
> return vgic_v3_attr_regs_access(dev, attr, ®, true);
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + if (get_user(reg, uaddr))
> + return -EFAULT;
> +
> + return vgic_v3_attr_regs_access(dev, attr, ®, true);
> + }
> }
> return -ENXIO;
> }
> @@ -560,6 +578,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
> tmp32 = reg;
> return put_user(tmp32, uaddr);
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + ret = vgic_v3_attr_regs_access(dev, attr, ®, false);
> + if (ret)
> + return ret;
> + return put_user(reg, uaddr);
> + }
> }
>
> return -ENXIO;
> @@ -578,6 +605,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> break;
> case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS:
> return vgic_v3_has_attr_regs(dev, attr);
> case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> return 0;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index e4799ae..51439c9 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -642,6 +642,24 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> break;
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 reg, id;
> + unsigned long vgic_mpidr, mpidr_reg;
> + struct kvm_vcpu *vcpu;
> +
> + vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
> + KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
> +
> + /* Convert plain mpidr value to MPIDR reg format */
> + mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
> +
> + vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
> + if (!vcpu)
> + return -EINVAL;
> +
> + id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, ®);
> + }
> default:
> return -ENXIO;
> }
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index c21968b..c98a1c5 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -238,6 +238,13 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
> vgic_v3->vgic_sre = 0;
> }
>
> + vcpu->arch.vgic_cpu.num_id_bits = (kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_ID_BITS_MASK) >>
> + ICH_VTR_ID_BITS_SHIFT;
> + vcpu->arch.vgic_cpu.num_pri_bits = ((kvm_vgic_global_state.ich_vtr_el2 &
> + ICH_VTR_PRI_BITS_MASK) >>
> + ICH_VTR_PRI_BITS_SHIFT) + 1;
> +
> /* Get the show on the road... */
> vgic_v3->vgic_hcr = ICH_HCR_EN;
> }
> @@ -338,6 +345,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> */
> kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
> kvm_vgic_global_state.can_emulate_gicv2 = false;
> + kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>
> if (!info->vcpu.start) {
> kvm_info("GICv3: no GICV resource entry\n");
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 9232791..eac272c 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -140,6 +140,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> + u64 id, u64 *val);
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg);
> int kvm_register_vgic_device(unsigned long type);
> void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>
^ permalink raw reply
* [PATCH v10 8/8] arm/arm64: Documentation: Update arm-vgic-v3.txt
From: Auger Eric @ 2016-12-16 12:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480576187-5012-9-git-send-email-vijay.kilari@gmail.com>
Hi Vijaya,
On 01/12/2016 08:09, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> Update error code returned for Invalid CPU interface register
> value and access in AArch32 mode.
>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> index 9348b3c..0f29850 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> @@ -142,10 +142,12 @@ Groups:
> KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
> CPU specified by the mpidr field.
>
> + CPU interface registers access is not implemented for AArch32 mode.
> + Error -ENXIO is returned when accessed in AArch32 mode.
> Errors:
> -ENXIO: Getting or setting this register is not yet supported
> -EBUSY: VCPU is running
> - -EINVAL: Invalid mpidr supplied
> + -EINVAL: Invalid mpidr or register value supplied
>
>
> KVM_DEV_ARM_VGIC_GRP_NR_IRQS
> @@ -193,6 +195,11 @@ Groups:
>
> Bit[n] indicates the status for interrupt vINTID + n.
>
> + Getting or setting the level info for an edge-triggered interrupt is
> + not guaranteed to work.
I don't get this statement. is the API applicable to edge triggered IRQs?
Thanks
Eric
To restore the complete state of the VGIC, the
> + configuration (edge/level) of interrupts must be restored before
> + restoring the level.
> +
> SGIs and any interrupt with a higher ID than the number of interrupts
> supported, will be RAZ/WI. LPIs are always edge-triggered and are
> therefore not supported by this interface.
>
^ permalink raw reply
* [PATCH] arm: dt: Initialize boot_command_line from CONFIG_CMDLINE in case DT does not provide /chosen/bootargs
From: Javier Martinez Canillas @ 2016-12-16 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201612161246.12155@pali>
Hello Pali,
On 12/16/2016 08:46 AM, Pali Roh?r wrote:
> On Thursday 15 December 2016 01:09:20 Pali Roh?r wrote:
>> On Thursday 15 December 2016 00:52:24 Russell King - ARM Linux wrote:
>>> On Wed, Dec 14, 2016 at 10:12:43PM +0100, Pali Roh?r wrote:
>>>> Commit 008a2ebcd677 ("ARM: dts: omap3: Remove skeleton.dtsi
>>>> usage") broke support for setting cmdline on Nokia N900 via
>>>> CONFIG_CMDLINE.
>>>>
>>>> It is because arm code booted in DT mode parse cmdline only via
>>>> function early_init_dt_scan_chosen() and that function does not
>>>> fill variable boot_command_line when DTB does not contain /chosen
>>>> entry. It is called from function early_init_dt_scan_nodes() in
>>>> setup_machine_fdt().
>>>>
>>>> This patch fixes it by explicitly filling boot_command_line in
>>>> function setup_machine_fdt() after calling
>>>> early_init_dt_scan_nodes() in case boot_command_line still
>>>> remains empty.
>>>
>>> This looks like a hack.
>>>
>>> First, the matter of the ATAGs compatibility. The decompressor
>>> relies on there being a pre-existing /chosen node to insert the
>>> command line and other parameters into. If we've dropped it (by
>>> dropping skeleton.dtsi) then we've just regressed more than just
>>> N900 - the decompressor won't be able to merge the ATAGs into the
>>> concatenated FDT.
>>
>> Hm... I did not think about it. But right this can be broken too...
>
> Tony, Javier: are you aware of above ??? problem?
>
> It looks like commit 008a2ebcd677 ("ARM: dts: omap3: Remove
> skeleton.dtsi usage") should be really reverted.
>
I don't think reverting the mentioned commit is the correct fix for your
problem. We are trying to get rid of skeleton.dtsi for many reasons, see
commit commit ("3ebee5a2e141 arm64: dts: kill skeleton.dtsi").
Also, the chosen node is mentioned to be optional in the ePAPR document
and u-boot creates a chosen node if isn't found [0] so this issue is only
present in boards that don't use u-boot like the N900/N950/N9 phones.
So if NOLO doesn't do the same than u-boot and the kernel expects a chosen
node, I suggest to add an empty chosen node in the omap3-n900.dts and
omap3-n950-n9.dtsi device tree source files.
[0]: http://git.denx.de/?p=u-boot.git;a=blob;f=common/fdt_support.c;h=c9f7019e38e8de1469f506cdd57353fd27d8e134;hb=HEAD#l226
Best regards,
--
Javier Martinez Canillas
Open Source Group
Samsung Research America
^ permalink raw reply
* [PATCH v10 7/8] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl
From: Auger Eric @ 2016-12-16 12:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480576187-5012-8-git-send-email-vijay.kilari@gmail.com>
Hi Vijaya,
On 01/12/2016 08:09, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> Userspace requires to store and restore of line_level for
> level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.
>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> arch/arm/include/uapi/asm/kvm.h | 7 ++++++
> arch/arm64/include/uapi/asm/kvm.h | 6 +++++
> virt/kvm/arm/vgic/vgic-kvm-device.c | 45 +++++++++++++++++++++++++++++++++++-
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 11 +++++++++
> virt/kvm/arm/vgic/vgic-mmio.c | 46 +++++++++++++++++++++++++++++++++++++
> virt/kvm/arm/vgic/vgic-mmio.h | 5 ++++
> virt/kvm/arm/vgic/vgic.h | 2 ++
> 7 files changed, 121 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index 98658d9d..f347779 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -191,6 +191,13 @@ struct kvm_arch_memory_slot {
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> #define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
> +#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)
> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
> +#define VGIC_LEVEL_INFO_LINE_LEVEL 0
> +
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> /* KVM_IRQ_LINE irq field index values */
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 91c7137..4100f8c 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -211,6 +211,12 @@ struct kvm_arch_memory_slot {
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> #define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
> +#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)
> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
> +#define VGIC_LEVEL_INFO_LINE_LEVEL 0
>
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index b6266fe..d5f7197 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -510,6 +510,21 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
> regid, reg);
> break;
> }
> + case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
> + unsigned int info, intid;
> +
> + info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
> + KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;
> + if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {
> + intid = attr->attr &
> + KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;
> + ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,
> + intid, reg);
> + } else {
> + ret = -EINVAL;
> + }
> + break;
> + }
> default:
> ret = -EINVAL;
> break;
> @@ -552,6 +567,17 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
>
> return vgic_v3_attr_regs_access(dev, attr, ®, true);
> }
> + case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
> + u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> + u64 reg;
> + u32 tmp32;
> +
> + if (get_user(tmp32, uaddr))
> + return -EFAULT;
> +
> + reg = tmp32;
> + return vgic_v3_attr_regs_access(dev, attr, ®, true);
> + }
> }
> return -ENXIO;
> }
> @@ -587,8 +613,18 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
> return ret;
> return put_user(reg, uaddr);
> }
> - }
> + case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
> + u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> + u64 reg;
> + u32 tmp32;
>
> + ret = vgic_v3_attr_regs_access(dev, attr, ®, false);
> + if (ret)
> + return ret;
> + tmp32 = reg;
> + return put_user(tmp32, uaddr);
> + }
> + }
> return -ENXIO;
> }
>
> @@ -609,6 +645,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> return vgic_v3_has_attr_regs(dev, attr);
> case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> return 0;
> + case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
> + if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
> + KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==
> + VGIC_LEVEL_INFO_LINE_LEVEL)
> + return 0;
> + break;
> + }
> case KVM_DEV_ARM_VGIC_GRP_CTRL:
> switch (attr->attr) {
> case KVM_DEV_ARM_VGIC_CTRL_INIT:
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 51439c9..9491d72 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -809,3 +809,14 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> return vgic_uaccess(vcpu, &rd_dev, is_write,
> offset, val);
> }
> +
> +int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> + u32 intid, u64 *val)
> +{
I don't see anyone checking vINTID is multiple of 32 as emphasized in
Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> + if (is_write)
> + vgic_write_irq_line_level_info(vcpu, intid, *val);
> + else
> + *val = vgic_read_irq_line_level_info(vcpu, intid);
> +
> + return 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index f81e0e5..28fef92b 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -371,6 +371,52 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
> }
> }
>
> +u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)
> +{
> + int i;
> + u64 val = 0;
> +
> + for (i = 0; i < 32; i++) {
> + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> + if (irq->line_level)
> + val |= (1U << i);
what about SGIs and higher ID than the number of interrupts supported.
Spec says RAZ/WI.
> +
> + vgic_put_irq(vcpu->kvm, irq);
> + }
> +
> + return val;
> +}
> +
> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
> + const u64 val)
> +{
> + int i;
> +
> + for (i = 0; i < 32; i++) {
> + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
same as above.
> + spin_lock(&irq->irq_lock);
> + if (val & (1U << i)) {
> + if (irq->config == VGIC_CONFIG_LEVEL) {
> + irq->line_level = true;
> + irq->pending = true;
> + vgic_queue_irq_unlock(vcpu->kvm, irq);
> + } else {
> + spin_unlock(&irq->irq_lock);
> + }
> + } else {
> + if (irq->config == VGIC_CONFIG_EDGE ||
can't we just ignore VGIC_CONFIG_EDGE case for which line_level is not
modeled?
> + (irq->config == VGIC_CONFIG_LEVEL &&
> + !irq->soft_pending))
> + irq->line_level = false;
To me the line level does not depend on the soft_pending bit. The
pending state depends on both.
Thanks
Eric
> + spin_unlock(&irq->irq_lock);
> + }
> +
> + vgic_put_irq(vcpu->kvm, irq);
> + }
> +}
> +
> static int match_region(const void *key, const void *elt)
> {
> const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 1cc7faf..b9423b4 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -181,6 +181,11 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
> const struct vgic_register_region *regions,
> int nr_regions, gpa_t addr);
>
> +u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid);
> +
> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
> + const u64 val);
> +
> unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>
> unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index eac272c..60d4350 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -144,6 +144,8 @@ int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> u64 id, u64 *val);
> int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> u64 *reg);
> +int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> + u32 intid, u64 *val);
> int kvm_register_vgic_device(unsigned long type);
> void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>
^ permalink raw reply
* [PATCH 3/4] iommu/arm-smmu: Disable stalling faults for all endpoints
From: Will Deacon @ 2016-12-16 11:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAF6AEGujUb37qagBZK1T13eAh=50zy0z5HpFF9FsuvkZZ7c5qw@mail.gmail.com>
Hi Rob,
On Tue, Dec 06, 2016 at 06:30:21PM -0500, Rob Clark wrote:
> On Thu, Aug 18, 2016 at 9:05 AM, Will Deacon <will.deacon@arm.com> wrote:
> > Enabling stalling faults can result in hardware deadlock on poorly
> > designed systems, particularly those with a PCI root complex upstream of
> > the SMMU.
> >
> > Although it's not really Linux's job to save hardware integrators from
> > their own misfortune, it *is* our job to stop userspace (e.g. VFIO
> > clients) from hosing the system for everybody else, even if they might
> > already be required to have elevated privileges.
> >
> > Given that the fault handling code currently executes entirely in IRQ
> > context, there is nothing that can sensibly be done to recover from
> > things like page faults anyway, so let's rip this code out for now and
> > avoid the potential for deadlock.
>
> so, I'd like to re-introduce this feature, I *guess* as some sort of
> opt-in quirk (ie. disabled by default unless something in DT tells you
> otherwise?? But I'm open to suggestions. I'm not entirely sure what
> hw was having problems due to this feature.)
>
> On newer snapdragon devices we are using arm-smmu for the GPU, and
> halting the GPU so the driver's fault handler can dump some GPU state
> on faults is enormously helpful for debugging and tracking down where
> in the gpu cmdstream the fault was triggered. In addition, we will
> eventually want the ability to update pagetables from fault handler
> and resuming the faulting transition.
I'm not against reintroducing this, but it would certainly need to be
opt-in, as you suggest. If we want to try to use stall faults to enable
demand paging for DMA, then that means running core mm code to resolve
the fault and we can't do that in irq context. Consequently, we have to
hand this off to a thread, which means the hardware must allow the SS
bit to remain set without immediately reasserting the interrupt line.
Furthermore, we can't handle multiple faults on a context-bank, so we'd
need to restrict ourselves to one device (i.e. faulting stream) per
domain (CB).
I think that means we want both specific compatible strings to identify
the SS bit behaviour, but also a way to opt-in for the stall model as a
separate property to indicate that the SoC integration can support this
without e.g. deadlocking.
Will
^ permalink raw reply
* [PATCH 2/2] media: s5p-mfc: fix MMAP of mfc buffer during reqbufs
From: Pankaj Dubey @ 2016-12-16 11:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481888915-19624-1-git-send-email-pankaj.dubey@samsung.com>
From: Smitha T Murthy <smitha.t@samsung.com>
It has been observed on ARM64 based Exynos SoC, if IOMMU is not enabled
and we try to use reserved memory for MFC, reqbufs fails with below
mentioned error
---------------------------------------------------------------------------
V4L2 Codec decoding example application
Kamil Debski <k.debski@samsung.com>
Copyright 2012 Samsung Electronics Co., Ltd.
Opening MFC.
(mfc.c:mfc_open:58): MFC Info (/dev/video0): driver="s5p-mfc" \
bus_info="platform:12c30000.mfc0" card="s5p-mfc-dec" fd=0x4[
42.339165] Remapping memory failed, error: -6
MFC Open Success.
(main.c:main:711): Successfully opened all necessary files and devices
(mfc.c:mfc_dec_setup_output:103): Setup MFC decoding OUTPUT buffer \
size=4194304 (requested=4194304)
(mfc.c:mfc_dec_setup_output:120): Number of MFC OUTPUT buffers is 2 \
(requested 2)
[App] Out buf phy : 0x00000000, virt : 0xffffffff
Output Length is = 0x300000
Error (mfc.c:mfc_dec_setup_output:145): Failed to MMAP MFC OUTPUT buffer
-------------------------------------------------------------------------
This is because the device requesting for memory is mfc0.left not the parent mfc0.
Hence setting of alloc_devs need to be done only if IOMMU is enabled
and in that case both the left and right device is treated as mfc0 only.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
[pankaj.dubey: debugging issue and formatting commit message]
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 17 ++++++++++-------
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 18 +++++++++++-------
2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 52081dd..9cfca5d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -30,6 +30,7 @@
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
#include "s5p_mfc_pm.h"
+#include "s5p_mfc_iommu.h"
static struct s5p_mfc_fmt formats[] = {
{
@@ -930,16 +931,18 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
psize[0] = ctx->luma_size;
psize[1] = ctx->chroma_size;
-
- if (IS_MFCV6_PLUS(dev))
- alloc_devs[0] = ctx->dev->mem_dev_l;
- else
- alloc_devs[0] = ctx->dev->mem_dev_r;
- alloc_devs[1] = ctx->dev->mem_dev_l;
+ if (exynos_is_iommu_available(&dev->plat_dev->dev)) {
+ if (IS_MFCV6_PLUS(dev))
+ alloc_devs[0] = ctx->dev->mem_dev_l;
+ else
+ alloc_devs[0] = ctx->dev->mem_dev_r;
+ alloc_devs[1] = ctx->dev->mem_dev_l;
+ }
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
ctx->state == MFCINST_INIT) {
psize[0] = ctx->dec_src_buf_size;
- alloc_devs[0] = ctx->dev->mem_dev_l;
+ if (exynos_is_iommu_available(&dev->plat_dev->dev))
+ alloc_devs[0] = ctx->dev->mem_dev_l;
} else {
mfc_err("This video node is dedicated to decoding. Decoding not initialized\n");
return -EINVAL;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index fcc2e05..eb8f06d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -30,6 +30,7 @@
#include "s5p_mfc_enc.h"
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
+#include "s5p_mfc_iommu.h"
#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12M
#define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264
@@ -1832,7 +1833,8 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
if (*buf_count > MFC_MAX_BUFFERS)
*buf_count = MFC_MAX_BUFFERS;
psize[0] = ctx->enc_dst_buf_size;
- alloc_devs[0] = ctx->dev->mem_dev_l;
+ if (exynos_is_iommu_available(&dev->plat_dev->dev))
+ alloc_devs[0] = ctx->dev->mem_dev_l;
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (ctx->src_fmt)
*plane_count = ctx->src_fmt->num_planes;
@@ -1847,12 +1849,14 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
psize[0] = ctx->luma_size;
psize[1] = ctx->chroma_size;
- if (IS_MFCV6_PLUS(dev)) {
- alloc_devs[0] = ctx->dev->mem_dev_l;
- alloc_devs[1] = ctx->dev->mem_dev_l;
- } else {
- alloc_devs[0] = ctx->dev->mem_dev_r;
- alloc_devs[1] = ctx->dev->mem_dev_r;
+ if (exynos_is_iommu_available(&dev->plat_dev->dev)) {
+ if (IS_MFCV6_PLUS(dev)) {
+ alloc_devs[0] = ctx->dev->mem_dev_l;
+ alloc_devs[1] = ctx->dev->mem_dev_l;
+ } else {
+ alloc_devs[0] = ctx->dev->mem_dev_r;
+ alloc_devs[1] = ctx->dev->mem_dev_r;
+ }
}
} else {
mfc_err("invalid queue type: %d\n", vq->type);
--
2.7.4
^ permalink raw reply related
* [PATCH 1/2] media: s5p-mfc: convert drivers to use the new vb2_queue dev field
From: Pankaj Dubey @ 2016-12-16 11:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481888915-19624-1-git-send-email-pankaj.dubey@samsung.com>
From: Smitha T Murthy <smitha.t@samsung.com>
commit 2548fee63d9e ("[media] media/platform: convert drivers to use the new
vb2_queue dev field") has missed to set dev pointer of vb2_queue which will be
used in reqbufs of mfc driver. Without this change following error is observed:
---------------------------------------------------------------
V4L2 Codec decoding example application
Kamil Debski <k.debski@samsung.com>
Copyright 2012 Samsung Electronics Co., Ltd.
Opening MFC.
(mfc.c:mfc_open:58): MFC Info (/dev/video0): driver="s5p-mfc" \
bus_info="platform:12c30000.mfc0" card="s5p-mfc-dec" fd=0x4[
42.339165] Remapping memory failed, error: -6
MFC Open Success.
(main.c:main:711): Successfully opened all necessary files and devices
(mfc.c:mfc_dec_setup_output:103): Setup MFC decoding OUTPUT buffer \
size=4194304 (requested=4194304)
(mfc.c:mfc_dec_setup_output:120): Number of MFC OUTPUT buffers is 2 \
(requested 2)
[App] Out buf phy : 0x00000000, virt : 0xffffffff
Output Length is = 0x300000
Error (mfc.c:mfc_dec_setup_output:145): Failed to MMAP MFC OUTPUT buffer
-------------------------------------------------------
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
[pankaj.dubey: debugging issue and formatting commit message]
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
drivers/media/platform/s5p-mfc/s5p_mfc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 0a5b8f5..6ea8246 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -838,6 +838,7 @@ static int s5p_mfc_open(struct file *file)
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
+ q->dev = &dev->plat_dev->dev;
if (vdev == dev->vfd_dec) {
q->io_modes = VB2_MMAP;
q->ops = get_dec_queue_ops();
@@ -861,6 +862,7 @@ static int s5p_mfc_open(struct file *file)
q->io_modes = VB2_MMAP;
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
+ q->dev = &dev->plat_dev->dev;
if (vdev == dev->vfd_dec) {
q->io_modes = VB2_MMAP;
q->ops = get_dec_queue_ops();
--
2.7.4
^ permalink raw reply related
* [PATCH 0/2] s5p-mfc fix for using reserved memory
From: Pankaj Dubey @ 2016-12-16 11:48 UTC (permalink / raw)
To: linux-arm-kernel
It has been observed on ARM64 based Exynos SoC, if IOMMU is not enabled
and we try to use reserved memory for MFC, reqbufs fails with below
mentioned error
---------------------------------------------------------------------------
V4L2 Codec decoding example application
Kamil Debski <k.debski@samsung.com>
Copyright 2012 Samsung Electronics Co., Ltd.
Opening MFC.
(mfc.c:mfc_open:58): MFC Info (/dev/video0): driver="s5p-mfc" \
bus_info="platform:12c30000.mfc0" card="s5p-mfc-dec" fd=0x4[
42.339165] Remapping memory failed, error: -6
MFC Open Success.
(main.c:main:711): Successfully opened all necessary files and devices
(mfc.c:mfc_dec_setup_output:103): Setup MFC decoding OUTPUT buffer \
size=4194304 (requested=4194304)
(mfc.c:mfc_dec_setup_output:120): Number of MFC OUTPUT buffers is 2 \
(requested 2)
[App] Out buf phy : 0x00000000, virt : 0xffffffff
Output Length is = 0x300000
Error (mfc.c:mfc_dec_setup_output:145): Failed to MMAP MFC OUTPUT buffer
-------------------------------------------------------------------------
This is because the device requesting for memory is mfc0.left not the parent mfc0.
Hence setting of alloc_devs need to be done only if IOMMU is enabled
and in that case both the left and right device is treated as mfc0 only.
Also we need to populate vb2_queue's dev pointer with mfc dev pointer.
Smitha T Murthy (2):
media: s5p-mfc: convert drivers to use the new vb2_queue dev field
media: s5p-mfc: fix MMAP of mfc buffer during reqbufs
drivers/media/platform/s5p-mfc/s5p_mfc.c | 2 ++
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 17 ++++++++++-------
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 18 +++++++++++-------
3 files changed, 23 insertions(+), 14 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH] arm: dt: Initialize boot_command_line from CONFIG_CMDLINE in case DT does not provide /chosen/bootargs
From: Pali Rohár @ 2016-12-16 11:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201612150109.20868@pali>
On Thursday 15 December 2016 01:09:20 Pali Roh?r wrote:
> On Thursday 15 December 2016 00:52:24 Russell King - ARM Linux wrote:
> > On Wed, Dec 14, 2016 at 10:12:43PM +0100, Pali Roh?r wrote:
> > > Commit 008a2ebcd677 ("ARM: dts: omap3: Remove skeleton.dtsi
> > > usage") broke support for setting cmdline on Nokia N900 via
> > > CONFIG_CMDLINE.
> > >
> > > It is because arm code booted in DT mode parse cmdline only via
> > > function early_init_dt_scan_chosen() and that function does not
> > > fill variable boot_command_line when DTB does not contain /chosen
> > > entry. It is called from function early_init_dt_scan_nodes() in
> > > setup_machine_fdt().
> > >
> > > This patch fixes it by explicitly filling boot_command_line in
> > > function setup_machine_fdt() after calling
> > > early_init_dt_scan_nodes() in case boot_command_line still
> > > remains empty.
> >
> > This looks like a hack.
> >
> > First, the matter of the ATAGs compatibility. The decompressor
> > relies on there being a pre-existing /chosen node to insert the
> > command line and other parameters into. If we've dropped it (by
> > dropping skeleton.dtsi) then we've just regressed more than just
> > N900 - the decompressor won't be able to merge the ATAGs into the
> > concatenated FDT.
>
> Hm... I did not think about it. But right this can be broken too...
Tony, Javier: are you aware of above ??? problem?
It looks like commit 008a2ebcd677 ("ARM: dts: omap3: Remove
skeleton.dtsi usage") should be really reverted.
--
Pali Roh?r
pali.rohar at gmail.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161216/cf408722/attachment.sig>
^ permalink raw reply
* [PATCH] arm: dt: Initialize boot_command_line from CONFIG_CMDLINE in case DT does not provide /chosen/bootargs
From: Pali Rohár @ 2016-12-16 11:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161215100931.GJ14217@n2100.armlinux.org.uk>
On Thursday 15 December 2016 11:09:32 Russell King - ARM Linux wrote:
> On Thu, Dec 15, 2016 at 01:09:20AM +0100, Pali Roh?r wrote:
> > If cmdline is not in DT, but /chosen exists, then function
> > early_init_dt_scan_chosen() use cmdline from CONFIG_CMDLINE.
>
> Ah, yes. Looks to me then as if the bug exists there, and not in
> arch code then. early_init_dt_scan_chosen() completely ignores the
> CMDLINE options if the chosen node is not found.
Yes... but question is: shoud function named early_init_dt_scan_chosen()
use CONFIG_CMDLINE if there is DT entry? From name dt_scan_chosen I
would expect that it scan /chosen and set some fields from /chosen...
At least name of that function is confusing.
> > What is reason that CONFIG_CMDLINE is not supported for DT?
>
> Sorry, that's my mistake - as you've pointed out above, it is
> supported but via generic code. I was only looking at arch code
> when I made the statement.
>
> This patch (untested) should solve it:
>
> drivers/of/fdt.c | 40 ++++++++++++++++++++--------------------
> 1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index c89d5d231a0e..fb89157332c6 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -1073,26 +1073,6 @@ int __init early_init_dt_scan_chosen(unsigned
> long node, const char *uname, if (p != NULL && l > 0)
> strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
>
> - /*
> - * CONFIG_CMDLINE is meant to be a default in case nothing else
> - * managed to set the command line, unless CONFIG_CMDLINE_FORCE
> - * is set in which case we override whatever was found earlier.
> - */
> -#ifdef CONFIG_CMDLINE
> -#if defined(CONFIG_CMDLINE_EXTEND)
> - strlcat(data, " ", COMMAND_LINE_SIZE);
> - strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> -#elif defined(CONFIG_CMDLINE_FORCE)
> - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> -#else
> - /* No arguments from boot loader, use kernel's cmdl*/
> - if (!((char *)data)[0])
> - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> -#endif
> -#endif /* CONFIG_CMDLINE */
> -
> - pr_debug("Command line is: %s\n", (char*)data);
> -
> /* break now */
> return 1;
> }
> @@ -1205,6 +1185,26 @@ void __init early_init_dt_scan_nodes(void)
> /* Retrieve various information from the /chosen node */
> of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
>
> + /*
> + * CONFIG_CMDLINE is meant to be a default in case nothing else
> + * managed to set the command line, unless CONFIG_CMDLINE_FORCE
> + * is set in which case we override whatever was found earlier.
> + */
> +#ifdef CONFIG_CMDLINE
> +#if defined(CONFIG_CMDLINE_EXTEND)
> + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
> + strlcat(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> +#elif defined(CONFIG_CMDLINE_FORCE)
> + strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> +#else
> + /* No arguments from boot loader, use kernel's cmdline */
> + if (!boot_command_line[0])
> + strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> +#endif
> +#endif /* CONFIG_CMDLINE */
> +
> + pr_debug("Command line is: %s\n", boot_command_line);
> +
> /* Initialize {size,address}-cells info */
> of_scan_flat_dt(early_init_dt_scan_root, NULL);
Patch is working fine and fixes my problem. You can add my Tested-by.
--
Pali Roh?r
pali.rohar at gmail.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161216/bfd7ea52/attachment.sig>
^ permalink raw reply
* [RFC] minimum gcc version for kernel: raise to gcc-4.3 or 4.6?
From: Arnd Bergmann @ 2016-12-16 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161216105634.235457-1-arnd@arndb.de>
[Fixed linux-arm-kernel mailing list address, sorry for the duplicate,
I'm not reposting all the ugly patches though, unless someone really
wants them, https://lkml.org/lkml/2016/12/16/174 has a copy]
On Friday, December 16, 2016 11:56:21 AM CET Arnd Bergmann wrote:
> I had some fun doing build testing with older gcc versions, building
> every release from 4.0 through 7.0 and running that on my randconfig
> setup to see what comes out.
>
> First of all, gcc-4.9 and higher is basically warning-free everywhere,
> although gcc-7 introduces some interesting new warnings (I have started
> doing patches for those as well). gcc-4.8 is probably good, too, and
> gcc-4.6 and 4.7 at least don't produce build failures in general, though
> the level of false-positive warnings increases (we could decide to turn
> those off for older compilers for build test purposes).
>
> In gcc-4.5 and below, dead code elimination is not as good as later,
> causing a couple of link errors, and some of them have no good workaround
> (see patch 1). It would be nice to declare that version too old, but
> several older distros that are still in wide use ship with compilers
> earlier than 4.6:
>
> RHEL6: gcc-4.4
> Debian 6: gcc-4.4
> Ubuntu 10.04: gcc-4.4
> SLES11: gcc-4.3
>
> With gcc-4.3, we need a couple of workaround patches beyond the problem
> mentioned above, more configuration options are unavailable and we get
> a significant number of false-positive warnings, but it's not much worse
> than gcc-4.5 otherwise.
>
> These are the options I had to disable to get gcc-4.3 randconfig builds
> working:
>
> CONFIG_HAVE_GCC_PLUGINS
> CONFIG_CC_STACKPROTECTOR_STRONG
> CONFIG_ARM_SINGLE_ARMV7M
> CONFIG_THUMB2_KERNEL
> CONFIG_KERNEL_MODE_NEON
> CONFIG_VDSO
> CONFIG_FUNCTION_TRACER (with CONFIG_FRAME_POINTER=n)
>
> I have not checked in detail which version is required for
> each of the above.
>
> Specifically on ARM, going further makes things rather useless especially
> for build testing: with gcc-4.2, we lose support for ARMv7, EABI, and
> effectively ARMv6 (as it relies on EABI for building reliably). Also,
> the number of false-positive build warnings is so high that it is useless
> for finding actual bugs from the warnings.
>
> See the replies to this mail for 13 patches I needed to work around
> issues for each of the releases before 4.6. I have also submitted
> some separate patches for issues that I considered actual bugs
> uncovered by the older compilers and that should be applied regardless.
>
> The original gcc-4.3 release was in early 2008. If we decide to still
> support that, we probably want the first 10 quirks in this series,
> while gcc-4.6 (released in 2011) requires none of them.
>
> Arnd
>
> Arnd Bergmann (13):
> [HACK] gcc-4.5: avoid link errors for unused function pointers
> KVM: arm: fix gcc-4.5 build
> ARM: div64: fix building with gcc-4.5 and lower
> vfio-pci: use 32-bit comparisons for register address for gcc-4.5
> clk: pxa: fix gcc-4.4 build
> ARM: atomic: fix gcc-4.4 build
> watchdog: kempld: fix gcc-4.3 build
> arm/arm64: xen: avoid gcc-4.4 warning
> ARM: mark cmpxchg and xchg __always_inline for gcc-4.3
> asm-generic: mark cmpxchg as __always_inline for gcc-4.3
> fs: fix unsigned enum warning with gcc-4.2
> KVM: arm: avoid binary number literals for gcc-4.2
> ARM: avoid 'Q' asm constraint for gcc-4.1 and earlier
>
> arch/arm/include/asm/atomic.h | 10 ++++++++--
> arch/arm/include/asm/cmpxchg.h | 12 ++++++------
> arch/arm/include/asm/div64.h | 17 +++--------------
> arch/arm/include/asm/io.h | 8 ++++++++
> arch/arm/include/asm/kvm_mmu.h | 2 +-
> arch/arm/include/asm/percpu.h | 5 ++++-
> arch/arm/mach-imx/pm-imx5.c | 20 ++++++++++++++++----
> arch/arm/mach-sa1100/pm.c | 2 ++
> arch/arm/plat-samsung/pm.c | 4 ++++
> drivers/clk/pxa/clk-pxa.c | 3 +--
> drivers/dma/ti-dma-crossbar.c | 4 ++++
> drivers/firmware/psci_checker.c | 3 +++
> drivers/iio/adc/exynos_adc.c | 3 +++
> drivers/net/ethernet/via/via-rhine.c | 6 ++++++
> drivers/vfio/pci/vfio_pci_rdwr.c | 5 ++++-
> drivers/watchdog/kempld_wdt.c | 9 ++++++++-
> include/asm-generic/cmpxchg-local.h | 7 ++++---
> include/linux/fs.h | 2 +-
> include/xen/arm/page.h | 1 +
> virt/kvm/arm/vgic/vgic-its.c | 4 ++--
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 8 ++++----
> virt/kvm/arm/vgic/vgic-mmio.c | 16 ++++++++--------
> virt/kvm/arm/vgic/vgic-mmio.h | 12 ++++++------
> 23 files changed, 107 insertions(+), 56 deletions(-)
>
>
^ permalink raw reply
* [PATCH 3/3] mm: make pagoff_t type 64-bit
From: Arnd Bergmann @ 2016-12-16 11:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161216105514.GA466@yury-N73SV>
On Friday, December 16, 2016 4:25:14 PM CET Yury Norov wrote:
> On Sun, Dec 11, 2016 at 03:59:01PM +0100, Arnd Bergmann wrote:
> > On Sunday, December 11, 2016 6:26:42 PM CET Yury Norov wrote:
> > > Also fix related interfaces
> > >
> > > Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
> >
> > Thanks Yury for the demonstration. I think this would put the nail
> > in the coffin of the idea of mmap64 even for Pavel, who didn't
> > seem convinced already.
> >
> > Changing all those interfaces and structure, struct page in particular,
> > is clearly too costly for any advantage we might have otherwise
> > gained.
> >
> > Arnd
>
> To be complete, we have 3 options:
> 1 leave things as is. 32-bit architectures will have no option to
> mmap big offsets, and no one cares - as usual.
> 2 add mmap64() for compat arches only. This way we don't need patch
> 3, and arches like aarch32 or aarch64/ilp32 will enjoy true 64-bit
> offsets.
> 3 introduce CONFIG_64_BIT_PGOFF_T, and let Pavel enable it if he has
> to work with big files on 32-bit arches.
>
> The most realistic approach for me is 1 because I never heard about
> 64-bit pgoff_t requests, except Pavel's one. Thinking about
> aarch64/ilp32, we probably need second approach. This is only 2 simple
> patches that are already there, and one patch in glibc. It will let
> 32-bit software work in 64-bit environment more smoothly. Cavium
> people should be completely satisfied with 2.
Agreed: If there is a serious request from Cavium or Huawei (which
are also very interested in this feature) and a specific use case,
we can still do 2 easily.
> Third is more looking like research exercise than something we need
> in practice.
Right.
> The only thing that makes me sad is that we proudly declare 64-bit
> off_t in new 32-bit ABIs but in fact we lie, at least in this
> specific case. We should add corresponding checks on glibc side at
> least. It's also simple.
Well, the only thing we are really saying there is that we support
more than 32-bit, and that the ABI uses 64-bit. Actually doing 64-bit
offsets within (very sparse) files probably also fails on 64-bit
architectures, at least on some file systems.
Arnd
^ permalink raw reply
* [PATCH 3/3] mm: make pagoff_t type 64-bit
From: Yury Norov @ 2016-12-16 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2636242.RWRJivuddj@wuerfel>
On Sun, Dec 11, 2016 at 03:59:01PM +0100, Arnd Bergmann wrote:
> On Sunday, December 11, 2016 6:26:42 PM CET Yury Norov wrote:
> > Also fix related interfaces
> >
> > Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
>
> Thanks Yury for the demonstration. I think this would put the nail
> in the coffin of the idea of mmap64 even for Pavel, who didn't
> seem convinced already.
>
> Changing all those interfaces and structure, struct page in particular,
> is clearly too costly for any advantage we might have otherwise
> gained.
>
> Arnd
To be complete, we have 3 options:
1 leave things as is. 32-bit architectures will have no option to
mmap big offsets, and no one cares - as usual.
2 add mmap64() for compat arches only. This way we don't need patch
3, and arches like aarch32 or aarch64/ilp32 will enjoy true 64-bit
offsets.
3 introduce CONFIG_64_BIT_PGOFF_T, and let Pavel enable it if he has
to work with big files on 32-bit arches.
The most realistic approach for me is 1 because I never heard about
64-bit pgoff_t requests, except Pavel's one. Thinking about
aarch64/ilp32, we probably need second approach. This is only 2 simple
patches that are already there, and one patch in glibc. It will let
32-bit software work in 64-bit environment more smoothly. Cavium
people should be completely satisfied with 2.
Third is more looking like research exercise than something we need
in practice.
The only thing that makes me sad is that we proudly declare 64-bit
off_t in new 32-bit ABIs but in fact we lie, at least in this
specific case. We should add corresponding checks on glibc side at
least. It's also simple.
Yury.
^ permalink raw reply
* [PATCH] dmaengine: pl330: Fix runtime PM support for terminated transfers
From: Marek Szyprowski @ 2016-12-16 10:39 UTC (permalink / raw)
To: linux-arm-kernel
PL330 DMA engine driver is leaking a runtime reference after any terminated
DMA transactions. This patch fixes this issue by tracking runtime PM state
of the device and making additional call to pm_runtime_put() in terminate_all
callback if needed.
Fixes: ae43b3289186 ("ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12")
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/dma/pl330.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 030fe05ed43b..9f3dbc8c63d2 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -448,6 +448,9 @@ struct dma_pl330_chan {
/* for cyclic capability */
bool cyclic;
+
+ /* for runtime pm tracking */
+ bool active;
};
struct pl330_dmac {
@@ -2031,6 +2034,7 @@ static void pl330_tasklet(unsigned long data)
_stop(pch->thread);
spin_unlock(&pch->thread->dmac->lock);
power_down = true;
+ pch->active = false;
} else {
/* Make sure the PL330 Channel thread is active */
spin_lock(&pch->thread->dmac->lock);
@@ -2050,6 +2054,7 @@ static void pl330_tasklet(unsigned long data)
desc->status = PREP;
list_move_tail(&desc->node, &pch->work_list);
if (power_down) {
+ pch->active = true;
spin_lock(&pch->thread->dmac->lock);
_start(pch->thread);
spin_unlock(&pch->thread->dmac->lock);
@@ -2164,6 +2169,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
unsigned long flags;
struct pl330_dmac *pl330 = pch->dmac;
LIST_HEAD(list);
+ bool power_down = false;
pm_runtime_get_sync(pl330->ddma.dev);
spin_lock_irqsave(&pch->lock, flags);
@@ -2174,6 +2180,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
pch->thread->req[0].desc = NULL;
pch->thread->req[1].desc = NULL;
pch->thread->req_running = -1;
+ power_down = pch->active;
+ pch->active = false;
/* Mark all desc done */
list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2191,6 +2199,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
spin_unlock_irqrestore(&pch->lock, flags);
pm_runtime_mark_last_busy(pl330->ddma.dev);
+ if (power_down)
+ pm_runtime_put_autosuspend(pl330->ddma.dev);
pm_runtime_put_autosuspend(pl330->ddma.dev);
return 0;
@@ -2350,6 +2360,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
* updated on work_list emptiness status.
*/
WARN_ON(list_empty(&pch->submitted_list));
+ pch->active = true;
pm_runtime_get_sync(pch->dmac->ddma.dev);
}
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in vdma
From: Jose Abreu @ 2016-12-16 10:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <C246CAC1457055469EF09E3A7AC4E11A4A65C9D3@XAP-PVEXMBX01.xlnx.xilinx.com>
Hi Kedar,
On 15-12-2016 19:09, Appana Durga Kedareswara Rao wrote:
> Hi Jose Miguel Abreu,
>
> Thanks for the review....
>
>>> - last = segment;
>>> + for (j = 0; j < chan->num_frms; ) {
>>> + list_for_each_entry(segment, &desc->segments, node)
>> {
>>> + if (chan->ext_addr)
>>> + vdma_desc_write_64(chan,
>>> +
>> XILINX_VDMA_REG_START_ADDRESS_64(i++),
>>> + segment->hw.buf_addr,
>>> + segment->hw.buf_addr_msb);
>>> + else
>>> + vdma_desc_write(chan,
>>> +
>> XILINX_VDMA_REG_START_ADDRESS(i++),
>>> + segment->hw.buf_addr);
>>> +
>>> + last = segment;
>> Hmm, is it possible to submit more than one segment? If so, then i and j will get
>> out of sync.
> If h/w is configured for more than 1 frame buffer and user submits more than one frame buffer
> We can submit more than one frame/ segment to hw right??
I'm not sure. When I used VDMA driver I always submitted only one
segment and multiple descriptors. But the problem is, for example:
If you have:
descriptor1 (2 segments)
descriptor2 (2 segments)
And you have 3 frame buffers in the HW.
Then:
1st frame buffer will have: descriptor1 -> segment1
2nd frame buffer will have: descriptor1 -> segment2
3rd frame buffer will have: descriptor2 -> segment1
but, 4th frame buffer will have: descriptor2 -> segment2 <----
INVALID because there is only 3 frame buffers
So, maybe a check inside the loop "list_for_each_entry(segment,
&desc->segments, node)" could be a nice to have.
>
>>> + }
>>> + list_del(&desc->node);
>>> + list_add_tail(&desc->node, &chan->active_list);
>>> + j++;
>> But if i is non zero and pending_list has more than num_frms then i will not
>> wrap-around as it should and will write to invalid framebuffer location, right?
> Yep will fix in v2...
>
> If (if (list_empty(&chan->pending_list)) || (i == chan->num_frms)
> break;
>
> Above condition is sufficient right???
Looks ok.
>
>>> + if (list_empty(&chan->pending_list))
>>> + break;
>>> + desc = list_first_entry(&chan->pending_list,
>>> + struct
>> xilinx_dma_tx_descriptor,
>>> + node);
>>> }
>>>
>>> if (!last)
>>> @@ -1114,14 +1124,13 @@ static void xilinx_vdma_start_transfer(struct
>> xilinx_dma_chan *chan)
>>> vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE,
>>> last->hw.stride);
>>> vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last-
>>> hw.vsize);
>> Maybe a check that all framebuffers contain valid addresses should be done
>> before programming vsize so that VDMA does not try to write to invalid
>> addresses.
> Do we really need to check for valid address???
> I didn't get you what to do you mean by invalid address could you please explain???
> In the driver we are reading form the pending_list which will be updated by pep_interleaved_dma
> Call so we are under assumption that user sends the proper address right???
What I mean by valid address is to check that i variable has
already been incremented by num_frms at least once since a VDMA
reset. This way you know that you have programmed all the
addresses of the frame buffers with an address and they are non-zero.
Best regards,
Jose Miguel Abreu
>
>>> +
>>> + chan->desc_submitcount += j;
>>> + chan->desc_pendingcount -= j;
>>> }
>>>
>>> chan->idle = false;
>>> if (!chan->has_sg) {
>>> - list_del(&desc->node);
>>> - list_add_tail(&desc->node, &chan->active_list);
>>> - chan->desc_submitcount++;
>>> - chan->desc_pendingcount--;
>>> if (chan->desc_submitcount == chan->num_frms)
>>> chan->desc_submitcount = 0;
>> "desc_submitcount >= chan->num_frms would be safer here.
> Sure will fix in v2...
>
> Regards,
> Kedar.
>
>>> } else {
>> Best regards,
>> Jose Miguel Abreu
>> --
>> To unsubscribe from this list: send the line "unsubscribe dmaengine" 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 3/3 v2] iio: adc: add a driver for Qualcomm PM8xxx HK/XOADC
From: Peter Meerwald-Stadler @ 2016-12-16 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481842118-14095-1-git-send-email-linus.walleij@linaro.org>
On Thu, 15 Dec 2016, Linus Walleij wrote:
> The Qualcomm PM8xxx PMICs contain a simpler ADC than its
> successors (already in the kernel as qcom-spmi-adc.c):
> the HK/XO ADC (Housekeeping/Chrystal oscillator ADC).
crystal
some minor comments below
>
> As far as I can understand this is equal to the PMICs
> using SSBI transport and encompass PM8018, PM8038,
> PM8058, PM8917 and PM8921, so this is shortly named
> PM8xxx.
>
> This ADC monitors a bunch of on-board voltages and the die
> temperature of the PMIC itself, but it can also be routed
> to convert a few external MPPs (multi-purpose pins). On
> the APQ8060 DragonBoard this feature is used to let this
> ADC convert an analog ALS (Ambient Light Sensor) voltage
> signal from a Capella CM3605 ALS into a LUX value.
>
> Developed and tested with APQ8060 DragonBoard based on
> Ivan's driver. The SPMI VADC driver is quite different,
> but share enough minor functionality that I have split
> out to the common file in a previous patch.
>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-arm-msm at vger.kernel.org
> Cc: Ivan T. Ivanov <iivanov.xz@gmail.com>
> Cc: Andy Gross <andy.gross@linaro.org>
> Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - Introduce a mutex to avoid different clients stepping on each others'
> toes
> - Add an of_xlate function to be sure to match the right ADC
> - Add all compatible strings, not just PM8058
> ---
> drivers/iio/adc/Kconfig | 10 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/qcom-pm8xxx-xoadc.c | 786 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 797 insertions(+)
> create mode 100644 drivers/iio/adc/qcom-pm8xxx-xoadc.c
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 7edcf3238620..f0b0cbdb9519 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -380,6 +380,16 @@ config PALMAS_GPADC
> is used in smartphones and tablets and supports a 16 channel
> general purpose ADC.
>
> +config QCOM_PM8XXX_XOADC
> + tristate "Qualcomm SSBI PM8xxx PMIC XOADCs"
> + depends on MFD_PM8XXX
> + help
> + ADC driver for the XOADC portions of the Qualcomm PM8xxx PMICs
> + using SSBI transport: PM8018, PM8038, PM8058, PM8917, PM8921.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called qcom-pm8xxx-xoadc.
> +
> config QCOM_SPMI_IADC
> tristate "Qualcomm SPMI PMIC current ADC"
> depends on SPMI
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index f9468d228b1e..234d45c805f9 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
> obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
> qcom-vadc-y := qcom-vadc-common.o
> obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-vadc.o qcom-spmi-vadc.o
> +obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-vadc.o qcom-pm8xxx-xoadc.o
> obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
> obj-$(CONFIG_STX104) += stx104.o
> obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
> diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
> new file mode 100644
> index 000000000000..32500d5d2989
> --- /dev/null
> +++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
> @@ -0,0 +1,786 @@
> +/*
> + * Qualcomm PM8xxx PMIC XOADC driver
> + *
> + * These ADCs are known as HK/XO (house keeping / chrystal oscillator)
> + * "XO" in "XOADC" means Chrystal Oscillator. It's a bunch of
2x crystal
> + * specific-purpose and general purpose ADC converters and channels.
> + *
> + * Copyright (C) 2016 Linaro Ltd.
> + * Author: Linus Walleij <linus.walleij@linaro.org>
> + */
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "qcom-vadc-common.h"
common prefix for all #define and declarations would be nice
> +
> +/*
> + * Definitions for the "user processor" registers lifted from the v3.4
> + * Qualcomm tree. Their kernel has two out-of-tree drivers for the ADC:
> + * drivers/misc/pmic8058-xoadc.c
> + * drivers/hwmon/pm8xxx-adc.c
> + * None of them contain any complete register specification, so this is
> + * a best effort of combining the information.
> + */
> +
> +/* These appear to be "battery monitor" registers */
> +#define ADC_ARB_BTM_CNTRL1 0x17e
> +#define ADC_ARB_BTM_CNTRL1_EN_BTM BIT(0)
> +#define ADC_ARB_BTM_CNTRL1_SEL_OP_MODE BIT(1)
> +#define ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL1 BIT(2)
> +#define ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL2 BIT(3)
> +#define ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL3 BIT(4)
> +#define ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL4 BIT(5)
> +#define ADC_ARB_BTM_CNTRL1_EOC BIT(6)
> +#define ADC_ARB_BTM_CNTRL1_REQ BIT(7)
> +
> +#define ADC_ARB_BTM_AMUX_CNTRL 0x17f
> +#define ADC_ARB_BTM_ANA_PARAM 0x180
> +#define ADC_ARB_BTM_DIG_PARAM 0x181
> +#define ADC_ARB_BTM_RSV 0x182
> +#define ADC_ARB_BTM_DATA1 0x183
> +#define ADC_ARB_BTM_DATA0 0x184
> +#define ADC_ARB_BTM_BAT_COOL_THR1 0x185
> +#define ADC_ARB_BTM_BAT_COOL_THR0 0x186
> +#define ADC_ARB_BTM_BAT_WARM_THR1 0x187
> +#define ADC_ARB_BTM_BAT_WARM_THR0 0x188
> +#define ADC_ARB_BTM_CNTRL2 0x18c
> +
> +/* Proper ADC registers */
> +
> +#define ADC_ARB_USRP_CNTRL 0x197
> +#define ADC_ARB_USRP_CNTRL_EN_ARB BIT(0)
> +#define ADC_ARB_USRP_CNTRL_RSV1 BIT(1)
> +#define ADC_ARB_USRP_CNTRL_RSV2 BIT(2)
> +#define ADC_ARB_USRP_CNTRL_RSV3 BIT(3)
> +#define ADC_ARB_USRP_CNTRL_RSV4 BIT(4)
> +#define ADC_ARB_USRP_CNTRL_RSV5 BIT(5)
> +#define ADC_ARB_USRP_CNTRL_EOC BIT(6)
> +#define ADC_ARB_USRP_CNTRL_REQ BIT(7)
> +
> +#define ADC_ARB_USRP_AMUX_CNTRL 0x198
> +#define ADC_ARB_USRP_AMUX_CNTRL_RSV0 BIT(0)
> +#define ADC_ARB_USRP_AMUX_CNTRL_RSV1 BIT(1)
> +#define ADC_ARB_USRP_AMUX_CNTRL_PREMUX0 BIT(2)
> +#define ADC_ARB_USRP_AMUX_CNTRL_PREMUX1 BIT(3)
> +#define ADC_ARB_USRP_AMUX_CNTRL_SEL0 BIT(4)
> +#define ADC_ARB_USRP_AMUX_CNTRL_SEL1 BIT(5)
> +#define ADC_ARB_USRP_AMUX_CNTRL_SEL2 BIT(6)
> +#define ADC_ARB_USRP_AMUX_CNTRL_SEL3 BIT(7)
> +#define ADC_AMUX_PREMUX_SHIFT 2
> +#define ADC_AMUX_SEL_SHIFT 4
> +
> +/* We know very little about the bits in this register */
> +#define ADC_ARB_USRP_ANA_PARAM 0x199
> +#define ADC_ARB_USRP_ANA_PARAM_DIS 0xFE
> +#define ADC_ARB_USRP_ANA_PARAM_EN 0xFF
> +
> +#define ADC_ARB_USRP_DIG_PARAM 0x19A
> +#define ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT0 BIT(0)
> +#define ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT1 BIT(1)
> +#define ADC_ARB_USRP_DIG_PARAM_CLK_RATE0 BIT(2)
> +#define ADC_ARB_USRP_DIG_PARAM_CLK_RATE1 BIT(3)
> +#define ADC_ARB_USRP_DIG_PARAM_EOC BIT(4)
> +/*
> + * On a later ADC the decimation factors are defined as
> + * 00 = 512, 01 = 1024, 10 = 2048, 11 = 4096 so assume this
> + * holds also for this older XOADC.
> + */
> +#define ADC_ARB_USRP_DIG_PARAM_DEC_RATE0 BIT(5)
> +#define ADC_ARB_USRP_DIG_PARAM_DEC_RATE1 BIT(6)
> +#define ADC_ARB_USRP_DIG_PARAM_EN BIT(7)
> +#define ADC_DIG_PARAM_DEC_SHIFT 5
> +
> +#define ADC_ARB_USRP_RSV 0x19B
> +#define ADC_ARB_USRP_RSV_RST BIT(0)
> +#define ADC_ARB_USRP_RSV_DTEST0 BIT(1)
> +#define ADC_ARB_USRP_RSV_DTEST1 BIT(2)
> +#define ADC_ARB_USRP_RSV_OP BIT(3)
> +#define ADC_ARB_USRP_RSV_IP_SEL0 BIT(4)
> +#define ADC_ARB_USRP_RSV_IP_SEL1 BIT(5)
> +#define ADC_ARB_USRP_RSV_IP_SEL2 BIT(6)
> +#define ADC_ARB_USRP_RSV_TRM BIT(7)
> +#define ADC_RSV_IP_SEL_SHIFT 4
> +
> +#define ADC_ARB_USRP_DATA0 0x19D
> +#define ADC_ARB_USRP_DATA1 0x19C
> +
> +/* Physical channels. MPP = Multi-Purpose Pin */
> +#define CHANNEL_VCOIN 0x0 /* Coincell */
> +#define CHANNEL_VBAT 0x1 /* Battery voltage */
> +#define CHANNEL_VCHG 0x2 /* Charger voltage */
> +#define CHANNEL_CHG_MONITOR 0x3 /* Charger current monitor */
> +#define CHANNEL_VPH_PWR 0x4 /* Main system power VPH */
> +#define CHANNEL_MPP5 0x5 /* "Battery charge current" */
> +#define CHANNEL_MPP6 0x6 /* "MPP1" */
> +#define CHANNEL_MPP7 0x7 /* "MPP2" */
> +#define CHANNEL_MPP8 0x8 /* Battery temperature */
> +#define CHANNEL_MPP9 0x9 /* Battery detection */
> +#define CHANNEL_USB_VBUS 0xa /* USB charger voltage */
> +#define CHANNEL_DIE_TEMP 0xb /* PMIC die temperature */
> +#define CHANNEL_INTERNAL 0xc /* 625mV reference channel */
> +#define CHANNEL_125V 0xd /* 1.25V reference channel */
> +#define CHANNEL_INTERNAL_2 0xe /* Charger temperature */
> +#define CHANNEL_MUXOFF 0xf /* Channel to reduce input load on mux */
> +
> +#define XOADC_CHAN_MAX 15 /* 4 bits */
> +
> +/* MPP = Multi-Purpose Pins */
> +#define PREMUX_MPP_SCALE_0 0x0 /* No scaling on the signal */
> +#define PREMUX_MPP_SCALE_1 0x1 /* Unity scaling selected by the user */
> +#define PREMUX_MPP_SCALE_1_DIV3 0x2 /* 1/3 prescaler on the input from MPP */
> +
> +/* Defines reference voltage for the XOADC */
> +#define AMUX_RSV0 0x0 /* XO_IN/XOADC_GND */
> +#define AMUX_RSV1 0x1 /* PMIC_IN/XOADC_GND */
> +#define AMUX_RSV2 0x2 /* PMIC_IN/BMS_CSP */
> +#define AMUX_RSV3 0x3 /* not used */
> +#define AMUX_RSV4 0x4 /* XOADC_GND/XOADC_GND */
> +#define AMUX_RSV5 0x5 /* XOADC_VREF/XOADC_GND */
> +#define XOADC_RSV_MAX 5 /* 3 bits 0..7, 3 and 6,7 are invalid */
> +
> +/*
> + * The different channels have hard-coded prescale ratios defined
> + * by the hardware.
> + */
> +static const struct vadc_prescale_ratio adc_prescale_ratios[] = {
> + { .num = 1, .den = 2 }, /* CHANNEL_VCOIN */
> + { .num = 1, .den = 3 }, /* CHANNEL_VBAT */
> + { .num = 1, .den = 10 }, /* CHANNEL_VCHG */
> + { .num = 1, .den = 1 }, /* CHANNEL_CHG_MONITOR */
> + { .num = 1, .den = 3 }, /* CHANNEL_VPH_PWR */
> + { .num = 1, .den = 1 }, /* CHANNEL_MPP5 */
> + { .num = 1, .den = 1 }, /* CHANNEL_MPP6 */
> + { .num = 1, .den = 2 }, /* CHANNEL_MPP7 */
> + { .num = 1, .den = 2 }, /* CHANNEL_MPP8 */
> + { .num = 1, .den = 3 }, /* CHANNEL_MPP9 */
> + { .num = 1, .den = 3 }, /* CHANNEL_USB_VBUS */
> + { .num = 1, .den = 1 }, /* CHANNEL_DIE_TEMP */
> + { .num = 1, .den = 1 }, /* CHANNEL_INTERNAL */
> + { .num = 1, .den = 1 }, /* CHANNEL_125V */
> + { .num = 1, .den = 1 }, /* CHANNEL_INTERNAL_2 */
> + { .num = 1, .den = 1 }, /* CHANNEL_MUXOFF */
> +};
> +
> +/**
> + * struct pm8xxx_chan_info - ADC channel information
> + * @name: name of this channel
> + * @calibration: whether to use absolute or ratiometric calibration
> + * @amux_channel: channel 0..15
> + * @decimation: 0,1,2,3
> + * @amux_mpp_channel: MPP channel 0..3
> + * @amux_ip_rsv: ratiometric scale value if using ratiometric
> + * calibration: 0, 1, 2, 4, 5.
> + */
> +struct pm8xxx_chan_info {
> + const char *name;
> + enum vadc_calibration calibration;
> + u8 amux_channel:4;
> + u8 decimation:2;
> + u8 amux_mpp_channel:2;
> + u8 amux_ip_rsv:3;
> +};
> +
> +/**
> + * struct pm8xxx_xoadc - state container for the XOADC
> + * @dev: pointer to device
> + * @map: regmap to access registers
> + * @vref: reference voltage regulator
> + * @nchans: number of channels
> + * @chans: the channel information per-channel
> + * @iio_chans: IIO channel specifiers
> + * @graph: linear calibration parameters for absolute and
> + * ratiometric measurements
> + * @complete: completion to indicate end of conversion
> + * @lock: lock to restrict access to the hardware to one client at the time
> + */
> +struct pm8xxx_xoadc {
> + struct device *dev;
> + struct regmap *map;
> + struct regulator *vref;
> + unsigned int nchans;
> + struct pm8xxx_chan_info *chans;
> + struct iio_chan_spec *iio_chans;
> + struct vadc_linear_graph graph[2];
> + struct completion complete;
> + struct mutex lock;
> +};
> +
> +static irqreturn_t pm8xxx_eoc_irq(int irq, void *d)
> +{
> + struct iio_dev *indio_dev = d;
> + struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
> +
> + complete(&adc->complete);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static struct pm8xxx_chan_info *
> +pm8xxx_get_channel(struct pm8xxx_xoadc *adc, u8 chan)
> +{
> + struct pm8xxx_chan_info *ch;
> + int i;
> +
> + for (i = 0; i < adc->nchans; i++) {
> + ch = &adc->chans[i];
> + if (ch->amux_channel == chan)
> + break;
return ch;
directly here
> + }
just
return NULL;
> + if (i == adc->nchans)
> + return NULL;
> +
> + return ch;
> +}
> +
> +static int pm8xxx_read_channel_rsv(struct pm8xxx_xoadc *adc,
> + const struct pm8xxx_chan_info *ch,
> + u8 rsv, u16 *adc_code)
> +{
> + int ret;
> + unsigned int val;
> + u8 rsvmask, rsvval;
> + u8 lsb, msb;
> +
> + dev_dbg(adc->dev, "read channel \"%s\", amux %d, mpp %d, rsv %d\n",
> + ch->name, ch->amux_channel, ch->amux_mpp_channel, rsv);
> +
> + mutex_lock(&adc->lock);
> +
> + /* Mux in this channel */
> + ret = regmap_write(adc->map, ADC_ARB_USRP_AMUX_CNTRL,
> + ch->amux_channel << ADC_AMUX_SEL_SHIFT |
> + ch->amux_mpp_channel << ADC_AMUX_PREMUX_SHIFT);
> + if (ret)
> + goto unlock;
> +
> + /* Set up ratiometric scale value */
> + rsvmask = (ADC_ARB_USRP_RSV_RST | ADC_ARB_USRP_RSV_DTEST0 |
> + ADC_ARB_USRP_RSV_DTEST1 | ADC_ARB_USRP_RSV_OP);
> + if (ch->calibration == VADC_CALIB_RATIOMETRIC) {
> + if (rsv == 0xff)
> + rsvval = (ch->amux_ip_rsv << ADC_RSV_IP_SEL_SHIFT) |
> + ADC_ARB_USRP_RSV_TRM;
> + else
> + rsvval = (rsv << ADC_RSV_IP_SEL_SHIFT) |
> + ADC_ARB_USRP_RSV_TRM;
> + } else {
> + /* We are not ratiometric so turn this off */
> + rsvval = ADC_ARB_USRP_RSV_IP_SEL1;
> + }
> +
> + ret = regmap_update_bits(adc->map,
> + ADC_ARB_USRP_RSV,
> + ~rsvmask,
> + rsvval);
> + if (ret)
> + goto unlock;
> +
> + ret = regmap_write(adc->map, ADC_ARB_USRP_ANA_PARAM,
> + ADC_ARB_USRP_ANA_PARAM_DIS);
> + if (ret)
> + goto unlock;
> +
> + /* Decimation factor */
> + ret = regmap_write(adc->map, ADC_ARB_USRP_DIG_PARAM,
> + ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT0 |
> + ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT1 |
> + ch->decimation << ADC_DIG_PARAM_DEC_SHIFT);
> + if (ret)
> + goto unlock;
> +
> + ret = regmap_write(adc->map, ADC_ARB_USRP_ANA_PARAM,
> + ADC_ARB_USRP_ANA_PARAM_EN);
> + if (ret)
> + goto unlock;
> +
> + /* Enable the arbiter, the Qualcomm code does it twice like this */
> + ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
> + ADC_ARB_USRP_CNTRL_EN_ARB);
> + if (ret)
> + goto unlock;
> + ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
> + ADC_ARB_USRP_CNTRL_EN_ARB);
> + if (ret)
> + goto unlock;
> +
> +
> + /* Fire a request! */
> + reinit_completion(&adc->complete);
> + ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
> + ADC_ARB_USRP_CNTRL_EN_ARB |
> + ADC_ARB_USRP_CNTRL_REQ);
> + if (ret)
> + goto unlock;
> +
> + /* Next the interrupt occurs */
> + ret = wait_for_completion_timeout(&adc->complete,
> + VADC_CONV_TIME_MAX_US);
> + if (!ret) {
> + dev_err(adc->dev, "conversion timed out\n");
> + ret = -ETIMEDOUT;
> + goto unlock;
> + }
> +
> + ret = regmap_read(adc->map, ADC_ARB_USRP_DATA0, &val);
> + if (ret)
> + goto unlock;
> + lsb = val;
> + ret = regmap_read(adc->map, ADC_ARB_USRP_DATA1, &val);
> + if (ret)
> + goto unlock;
> + msb = val;
> + *adc_code = (msb << 8) | lsb;
> +
> + /* Turn off the ADC by setting the arbiter to 0 twice */
> + ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL, 0);
> + if (ret)
> + goto unlock;
> + ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL, 0);
> + if (ret)
> + goto unlock;
> +
> +unlock:
> + mutex_unlock(&adc->lock);
> + return ret;
> +}
> +
> +static int pm8xxx_read_channel(struct pm8xxx_xoadc *adc,
> + const struct pm8xxx_chan_info *ch,
> + u16 *adc_code)
> +{
> + /*
> + * Normally we just use the ratiometric scale value (RSV) predefined
> + * for the channel, but during calibration we need to modify this
> + * so this wrapper is a helper hiding the more complex version.
> + */
> + return pm8xxx_read_channel_rsv(adc, ch, 0xff, adc_code);
> +}
> +
> +static s32 pm8xxx_calibrate(struct pm8xxx_xoadc *adc,
> + const struct pm8xxx_chan_info *ch,
> + u16 adc_code)
> +{
> + return qcom_vadc_calibrate(&adc_prescale_ratios[ch->amux_channel],
> + &adc->graph[ch->calibration],
> + (ch->calibration == VADC_CALIB_ABSOLUTE),
> + adc_code);
> +}
> +
> +static int pm8xxx_calibrate_device(struct pm8xxx_xoadc *adc)
> +{
> + const struct pm8xxx_chan_info *ch;
> + u16 read_1250v;
> + u16 read_0625v;
> + u16 read_nomux_rsv5;
> + u16 read_nomux_rsv4;
> + int ret;
> +
> +
> + adc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV;
> + adc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE_UV;
> +
> + /* Common reference channel calibration */
> + ch = pm8xxx_get_channel(adc, CHANNEL_125V);
> + if (!ch)
> + return -ENODEV;
> + ret = pm8xxx_read_channel(adc, ch, &read_1250v);
> + if (ret) {
> + dev_err(adc->dev, "could not read 1.25V reference channel\n");
> + return -ENODEV;
> + }
> + ch = pm8xxx_get_channel(adc, CHANNEL_INTERNAL);
> + if (!ch)
> + return -ENODEV;
> + ret = pm8xxx_read_channel(adc, ch, &read_0625v);
> + if (ret) {
> + dev_err(adc->dev, "could not read 0.625V reference channel\n");
> + return -ENODEV;
> + }
> + if (read_1250v == read_0625v) {
> + dev_err(adc->dev, "read same ADC code for 1.25V and 0.625V\n");
> + return -ENODEV;
> + }
> +
> + adc->graph[VADC_CALIB_ABSOLUTE].dy = read_1250v - read_0625v;
> + adc->graph[VADC_CALIB_ABSOLUTE].gnd = read_0625v;
> +
> + dev_info(adc->dev, "absolute calibration dx = %d uV, dy = %d units\n",
> + VADC_ABSOLUTE_RANGE_UV, adc->graph[VADC_CALIB_ABSOLUTE].dy);
> +
> + /* Ratiometric calibration */
> + ch = pm8xxx_get_channel(adc, CHANNEL_MUXOFF);
> + if (!ch)
> + return -ENODEV;
> + ret = pm8xxx_read_channel_rsv(adc, ch, AMUX_RSV5, &read_nomux_rsv5);
> + if (ret) {
> + dev_err(adc->dev, "could not read MUXOFF reference channel\n");
> + return -ENODEV;
> + }
> + ret = pm8xxx_read_channel_rsv(adc, ch, AMUX_RSV4, &read_nomux_rsv4);
> + if (ret) {
> + dev_err(adc->dev, "could not read MUXOFF reference channel\n");
> + return -ENODEV;
> + }
> + adc->graph[VADC_CALIB_RATIOMETRIC].dy =
> + read_nomux_rsv5 - read_nomux_rsv4;
> + adc->graph[VADC_CALIB_RATIOMETRIC].gnd = read_nomux_rsv4;
> +
> + dev_info(adc->dev, "ratiometric calibration dx = %d uV, dy = %d units\n",
> + VADC_RATIOMETRIC_RANGE_UV,
> + adc->graph[VADC_CALIB_RATIOMETRIC].dy);
> +
> + return 0;
> +}
> +
> +static int pm8xxx_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
> + const struct pm8xxx_chan_info *ch;
> + u16 adc_code;
> + int ret;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_PROCESSED:
> + /* Only die temperature ends up here */
> + ch = pm8xxx_get_channel(adc, chan->address);
> + if (!ch) {
> + dev_err(adc->dev, "no such channel %lu\n",
> + chan->address);
> + return -EINVAL;
> + }
> + ret = pm8xxx_read_channel(adc, ch, &adc_code);
> + if (ret)
> + return ret;
> + *val = pm8xxx_calibrate(adc, ch, adc_code);
> + /* 2mV/K, return milli Celsius */
> + *val /= 2;
> + *val -= KELVINMIL_CELSIUSMIL;
> + return IIO_VAL_INT;
> + case IIO_CHAN_INFO_RAW:
> + switch (chan->type) {
> + case IIO_VOLTAGE:
any global state involved here?
locking might be needed
> + ch = pm8xxx_get_channel(adc, chan->address);
> + if (!ch) {
> + dev_err(adc->dev, "no such channel %lu\n",
> + chan->address);
> + return -EINVAL;
> + }
> + ret = pm8xxx_read_channel(adc, ch, &adc_code);
> + if (ret)
> + return ret;
> + *val = pm8xxx_calibrate(adc, ch, adc_code);
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> + case IIO_CHAN_INFO_SCALE:
> + /*
> + * Applies to all voltage channels: we scale the microvolts
> + * to millivolts as required by the userspace ABI.
> + */
> + *val = 0;
> + *val2 = 1000;
> + return IIO_VAL_INT_PLUS_MICRO;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int pm8xxx_of_xlate(struct iio_dev *indio_dev,
> + const struct of_phandle_args *iiospec)
> +{
> + struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
> + unsigned int i;
> +
> + for (i = 0; i < adc->nchans; i++)
> + if (adc->iio_chans[i].channel == iiospec->args[0])
> + return i;
> +
> + return -EINVAL;
> +}
> +
> +static const struct iio_info pm8xxx_xoadc_info = {
> + .driver_module = THIS_MODULE,
> + .of_xlate = pm8xxx_of_xlate,
> + .read_raw = pm8xxx_read_raw,
> +};
> +
> +static int pm8xxx_xoadc_parse_channel(struct device *dev,
> + struct device_node *np,
> + struct pm8xxx_chan_info *ch)
> +{
> + const char *name = np->name;
> + u32 chan, rsv, dec;
> + int ret;
> +
> + ret = of_property_read_u32(np, "reg", &chan);
> + if (ret) {
> + dev_err(dev, "invalid channel number %s\n", name);
> + return ret;
> + }
> + if (chan > XOADC_CHAN_MAX) {
> + dev_err(dev, "%s too big channel number %d\n", name, chan);
> + return -EINVAL;
> + }
> +
> + if (of_property_read_bool(np, "qcom,ratiometric")) {
> + ch->calibration = VADC_CALIB_RATIOMETRIC;
> + ret = of_property_read_u32(np, "qcom,ratiometric-ref", &rsv);
> + if (ret) {
> + dev_err(dev, "invalid RSV %s\n", name);
> + return ret;
> + }
> + if (rsv > XOADC_RSV_MAX) {
> + dev_err(dev, "%s too large RSV value %d\n", name, rsv);
> + return -EINVAL;
> + }
> + if (rsv == AMUX_RSV3) {
> + dev_err(dev, "%s invalid RSV value %d\n", name, rsv);
> + return -EINVAL;
> + }
> + } else {
> + ch->calibration = VADC_CALIB_ABSOLUTE;
> + rsv = 0;
> + }
> +
> + ret = of_property_read_u32(np, "qcom,decimation", &dec);
> + if (!ret) {
> + /* It's OK to skip this ... */
> + ret = qcom_vadc_decimation_from_dt(dec);
> + if (ret < 0) {
> + dev_err(dev, "%s invalid decimation %d\n",
> + name, dec);
> + return ret;
> + }
> + ch->decimation = ret;
> + } else {
> + ch->decimation = VADC_DEF_DECIMATION;
> + }
> +
> + ch->amux_channel = chan;
> + ch->name = name;
> + ch->amux_ip_rsv = rsv;
> + ch->amux_mpp_channel = PREMUX_MPP_SCALE_0; /* FIXME: get from DT */
> +
> + dev_dbg(dev, "channel %d \"%s\" ref voltage: %d, decimation %d\n",
> + ch->amux_channel,
> + ch->name,
> + ch->amux_ip_rsv,
> + ch->decimation);
> + return 0;
> +}
> +
> +static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc,
> + struct device_node *np)
> +{
> + struct device_node *child;
> + struct pm8xxx_chan_info *ch;
> + int ret;
> + int i;
> +
> + adc->nchans = of_get_available_child_count(np);
> + if (!adc->nchans) {
> + dev_err(adc->dev, "no channel children\n");
> + return -ENODEV;
> + }
> + dev_dbg(adc->dev, "found %d ADC channels\n", adc->nchans);
> +
> + adc->iio_chans = devm_kcalloc(adc->dev, adc->nchans,
> + sizeof(*adc->iio_chans), GFP_KERNEL);
> + if (!adc->iio_chans)
> + return -ENOMEM;
> +
> + adc->chans = devm_kcalloc(adc->dev, adc->nchans,
> + sizeof(*adc->chans), GFP_KERNEL);
> + if (!adc->chans)
> + return -ENOMEM;
> +
> + i = 0;
> + for_each_available_child_of_node(np, child) {
> + struct iio_chan_spec *iio_chan;
> +
> + ch = &adc->chans[i];
> + ret = pm8xxx_xoadc_parse_channel(adc->dev, child, ch);
> + if (ret) {
> + of_node_put(child);
> + return ret;
> + }
> +
> + iio_chan = &adc->iio_chans[i];
> + iio_chan->channel = ch->amux_channel;
> + iio_chan->datasheet_name = ch->name;
> + /* A single temperature channel, the rest are voltages */
> + if (ch->amux_channel == CHANNEL_DIE_TEMP) {
> + iio_chan->type = IIO_TEMP;
> + iio_chan->info_mask_separate =
> + BIT(IIO_CHAN_INFO_PROCESSED);
> + } else {
> + iio_chan->type = IIO_VOLTAGE;
> + iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE);
> + }
> + iio_chan->indexed = 1;
> + iio_chan->address = ch->amux_channel;
> +
> + i++;
> + }
> +
> + /* Check for required channels */
> + ch = pm8xxx_get_channel(adc, CHANNEL_125V);
> + if (!ch) {
> + dev_err(adc->dev, "missing 1.25V reference channel\n");
> + return -ENODEV;
> + }
> + ch = pm8xxx_get_channel(adc, CHANNEL_INTERNAL);
> + if (!ch) {
> + dev_err(adc->dev, "missing 0.625V reference channel\n");
> + return -ENODEV;
> + }
> + ch = pm8xxx_get_channel(adc, CHANNEL_MUXOFF);
> + if (!ch) {
> + dev_err(adc->dev, "missing MUXOFF reference channel\n");
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +static int pm8xxx_xoadc_probe(struct platform_device *pdev)
> +{
> + struct pm8xxx_xoadc *adc;
> + struct iio_dev *indio_dev;
> + struct device_node *np = pdev->dev.of_node;
> + struct regmap *map;
> + struct device *dev = &pdev->dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
> + if (!indio_dev)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, indio_dev);
> +
> + adc = iio_priv(indio_dev);
> + adc->dev = dev;
> + init_completion(&adc->complete);
> + mutex_init(&adc->lock);
> +
> + ret = pm8xxx_xoadc_parse_channels(adc, np);
> + if (ret)
> + return ret;
> +
> + map = dev_get_regmap(dev->parent, NULL);
> + if (!map) {
> + dev_err(dev, "Parent regmap unavailable.\n");
most other strings start lowercase :)
> + return -ENXIO;
> + }
> + adc->map = map;
> +
> + /* Bring up regulator */
> + adc->vref = devm_regulator_get(dev, "xoadc-ref");
> + if (IS_ERR(adc->vref)) {
> + dev_err(dev, "failed to get XOADC VREF regulator\n");
> + return PTR_ERR(adc->vref);
> + }
> + /* We strictly require this voltage */
> + ret = regulator_set_voltage(adc->vref, 2200000, 2200000);
> + if (ret) {
> + dev_err(dev, "unable to set LDO18 voltage to 2.2V\n");
> + return ret;
> + }
> + ret = regulator_enable(adc->vref);
> + if (ret) {
> + dev_err(dev, "failed to enable XOADC VREF regulator\n");
> + return ret;
> + }
> +
> + ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
> + pm8xxx_eoc_irq, NULL, 0, "pm8xxx-adc", indio_dev);
> + if (ret) {
> + dev_err(dev, "unable to request IRQ\n");
> + goto out_disable_vref;
> + }
> +
> + indio_dev->dev.parent = dev;
> + indio_dev->dev.of_node = np;
> + indio_dev->name = "pm8xxx-xoadc";
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = &pm8xxx_xoadc_info;
> + indio_dev->channels = adc->iio_chans;
> + indio_dev->num_channels = adc->nchans;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto out_disable_vref;
> +
> + ret = pm8xxx_calibrate_device(adc);
shouldn't this be done before the device is registered?
> + if (ret)
> + goto out_unreg_device;
> +
> + dev_info(dev, "PM8xxx XOADC driver enabled\n");
message necessary?
> +
> + return 0;
> +
> +out_unreg_device:
> + iio_device_unregister(indio_dev);
> +out_disable_vref:
> + regulator_disable(adc->vref);
> +
> + return ret;
> +}
> +
> +static int pm8xxx_xoadc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + regulator_disable(adc->vref);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id pm8xxx_xoadc_id_table[] = {
> + {
> + .compatible = "qcom,pm8018-adc",
> + },
> + {
> + .compatible = "qcom,pm8038-adc",
> + },
> + {
> + .compatible = "qcom,pm8058-adc",
> + },
> + {
> + .compatible = "qcom,pm8917-adc",
> + },
> + {
> + .compatible = "qcom,pm8921-adc",
> + },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, pm8xxx_xoadc_id_table);
> +
> +static struct platform_driver pm8xxx_xoadc_driver = {
> + .driver = {
> + .name = "pm8xxx-adc",
> + .of_match_table = pm8xxx_xoadc_id_table,
> + },
> + .probe = pm8xxx_xoadc_probe,
> + .remove = pm8xxx_xoadc_remove,
> +};
> +module_platform_driver(pm8xxx_xoadc_driver);
> +
> +MODULE_DESCRIPTION("PM8xxx XOADC driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:pm8xxx-xoadc");
>
--
Peter Meerwald-Stadler
+43-664-2444418 (mobile)
^ permalink raw reply
* mmc: core: complete/wait_for_completion performance
From: Jörg Krause @ 2016-12-16 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <875319194.240552.1481827900469@email.1und1.de>
Hi Stefan,
On Thu, 2016-12-15 at 19:51 +0100, Stefan Wahren wrote:
> Hi J?rg,
>
> > J?rg Krause <joerg.krause@embedded.rocks> hat am 15. Dezember 2016
> > um 14:50 geschrieben:
> >
> >
> > Hi Stefan,
> >
> > On Wed, 2016-12-14 at 19:57 +0100, Stefan Wahren wrote:
> > > Hi J?rg,
> > >
> >
> > [snip]
> >
> > > > >
> > > > > did you try cyclictest [1]?
> > > >
> > > > Not yet. Not sure what to measure and which values to compare
> > > > here.
> > >
> > > i tought you have the vendor kernel and the mainline kernel
> > > available
> > > for your platform.
> > >
> > > So you could compare the both kernels.
> >
> > Yes, that's right. I will have a look at this tool.
> >
> > > >
> > > > >
> > > > > Beside the time for a request the amount of requests for the
> > > > > complete
> > > > > iperf test
> > > > > would we interesting. Maybe there are retries.
> > > > >
> > > > > I'm still interested in your PIO mode patches for mxs-mmc
> > > > > even
> > > > > without clean up.
> > > >
> > > > Actually, the patch does not implement a PIO mode, but drops
> > > > DMA
> > > > and
> > > > uses polling instead. I've attached the patch.
> > >
> > > Thanks. I applied it, but unfortunately this breaks SD card
> > > support
> > > for my Duckbill and the kernel isn't able to mount the rootfs:
> > >
> > > [????2.267073] mxs-mmc 80010000.ssp: initialized
> > > [????2.272624] mxs-mmc 80010000.ssp: AC command error 0xffffff92
> >
> > Sorry, I messed up the branches. I attached the correct patch which
> > is
> > working for me on Linux v4.9.
>
> i tested the second version but there isn't any performance gain with
> the patch.
In the vendor kernel the polling is used only for small chunks of <=
1024 bytes to save the context switches when using DMA. This patch does
not use DMA at all, but only polling.
As I said before, I guess the limitation in the mxs-mmc driver is the
time needed to return the mmc request to the mmc core driver.
I have a Cubietruck with the same wifi chipset as on my i.MX28 target
where I get ~20Mbps throughput. Furthermore, I've found a benchmark on
a NXP thread [1] measuring about 30Mbps for an i.MX6 target and a
similiar wifi chip.
Looking at the sunxi-mmc driver shows that it calls mmc_request_done()
in an interrupt context and does not use the dmaengine driver@all.
For now, I would drop the polling mode and look how to optimize the
control flow between the DMA controller and the MMC host.
Unfortunately, this will need some time...
> Duckbill with class 10 SD card
> Linux 4.8 without patch
>
> dd if=/dev/zero of=test bs=1k count=10000
> 10000+0 records in
> 10000+0 records out
> 10240000 bytes (10 MB) copied, 2.68934 s, 3.8 MB/s
>
> dd if=/dev/zero of=test bs=8k count=10000
> 10000+0 records in
> 10000+0 records out
> 81920000 bytes (82 MB) copied, 8.24305 s, 9.9 MB/s
>
>
> Duckbill with class 10 SD card
> Linux 4.8 with patch
>
> dd if=/dev/zero of=test bs=1k count=10000
> 10000+0 records in
> 10000+0 records out
> 10240000 bytes (10 MB) copied, 3.41193 s, 3.0 MB/s
>
> dd if=/dev/zero of=test bs=8k count=10000
> 10000+0 records in
> 10000+0 records out
> 81920000 bytes (82 MB) copied, 14.4564 s, 5.7 MB/s
>
> Additionally i get these warning during boot:
>
> [????2.278445] mxs-mmc 80010000.ssp: initialized
> [????2.283996] mxs-mmc 80010000.ssp: AC command error -110
> [????2.305158] mxs-mmc 80010000.ssp: AC command error -110
> [????2.322975] mxs-mmc 80010000.ssp: AC command error -110
> [????2.338660] mxs-mmc 80010000.ssp: AC command error -110
> [????2.344289] mxs-mmc 80010000.ssp: AC command error -110
> [????2.365653] mxs-mmc 80010000.ssp: AC command error -110
I get this errors, too. The MMC host is sending some commands and the
MMC client is not (yet) responding to those commands. I haven't looked
any closer at this.
[1] https://community.nxp.com/thread/317396
^ permalink raw reply
* [PATCH v6 0/5] davinci: VPIF: add DT support
From: Hans Verkuil @ 2016-12-16 9:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161207183025.20684-1-khilman@baylibre.com>
On 07/12/16 19:30, Kevin Hilman wrote:
> Prepare the groundwork for adding DT support for davinci VPIF drivers.
> This series does some fixups/cleanups and then adds the DT binding and
> DT compatible string matching for DT probing.
>
> The controversial part from previous versions around async subdev
> parsing, and specifically hard-coding the input/output routing of
> subdevs, has been left out of this series. That part can be done as a
> follow-on step after agreement has been reached on the path forward.
> With this version, platforms can still use the VPIF capture/display
> drivers, but must provide platform_data for the subdevs and subdev
> routing.
>
> Tested video capture to memory on da850-lcdk board using composite
> input.
Other than the comment for the first patch this series looks good.
So once that's addressed I'll queue it up for 4.11.
Regards,
Hans
>
> Changes since v5:
> - locking fix: updated comment around lock variable
> - binding doc: added example for
> - added reviewed-by tags from Laurent (thanks!)
>
> Changes since v4:
> - dropped controversial async subdev parsing support. That can be
> done as a follow-up step after the discussions have finalized on the
> right approach.
> - DT binding Acked by DT maintainer (Rob H.)
> - reworked locking fix (suggested by Laurent)
>
> Changes since v3:
> - move to a single VPIF node, DT binding updated accordingly
> - misc fixes/updates based on reviews from Sakari
>
> Changes since v2:
> - DT binding doc: fix example to use correct compatible
>
> Changes since v1:
> - more specific compatible strings, based on SoC: ti,da850-vpif*
> - fix locking bug when unlocking over subdev s_stream
>
>
> Kevin Hilman (5):
> [media] davinci: VPIF: fix module loading, init errors
> [media] davinci: vpif_capture: remove hard-coded I2C adapter id
> [media] davinci: vpif_capture: fix start/stop streaming locking
> [media] dt-bindings: add TI VPIF documentation
> [media] davinci: VPIF: add basic support for DT init
>
> .../devicetree/bindings/media/ti,da850-vpif.txt | 83 ++++++++++++++++++++++
> drivers/media/platform/davinci/vpif.c | 14 +++-
> drivers/media/platform/davinci/vpif_capture.c | 26 +++++--
> drivers/media/platform/davinci/vpif_capture.h | 2 +-
> drivers/media/platform/davinci/vpif_display.c | 6 ++
> include/media/davinci/vpif_types.h | 1 +
> 6 files changed, 125 insertions(+), 7 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/media/ti,da850-vpif.txt
>
^ 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