Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 01/10] arm64: KVM: Use static keys for selecting the GIC backend
From: Marc Zyngier @ 2016-09-22 10:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473691764-29424-2-git-send-email-vladimir.murzin@arm.com>

On 12/09/16 15:49, Vladimir Murzin wrote:
> Currently GIC backend is selected via alternative framework and this
> is fine. We are going to introduce vgic-v3 to 32-bit world and there
> we don't have patching framework in hand, so we can either check
> support for GICv3 every time we need to choose which backend to use or
> try to optimise it by using static keys. The later looks quite
> promising because we can share logic involved in selecting GIC backend
> between architectures if both uses static keys.
> 
> This patch moves arm64 from alternative to static keys framework for
> selecting GIC backend. For that we embed static key into vgic_global
> and enable the key during vgic initialisation based on what has
> already been exposed by the host GIC driver.
> 
> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
> ---
>  arch/arm64/kvm/hyp/switch.c   |   21 +++++++++++----------
>  include/kvm/arm_vgic.h        |    4 ++++
>  virt/kvm/arm/vgic/vgic-init.c |    4 ++++
>  virt/kvm/arm/vgic/vgic.c      |    2 +-
>  4 files changed, 20 insertions(+), 11 deletions(-)

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v4 05/10] KVM: arm: vgic: Fix compiler warnings when built for 32-bit
From: Marc Zyngier @ 2016-09-22 10:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473691764-29424-6-git-send-email-vladimir.murzin@arm.com>

On 12/09/16 15:49, Vladimir Murzin wrote:
> Well, this patch is looking ahead of time, but we'll get following
> compiler warnings as soon as we introduce vgic-v3 to 32-bit world
> 
>   CC      arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.o
> arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.c: In function 'vgic_mmio_read_v3r_typer':
> arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.c:184:35: warning: left shift count >= width of type [-Wshift-count-overflow]
>   value = (mpidr & GENMASK(23, 0)) << 32;
>                                    ^
> In file included from ./include/linux/kernel.h:10:0,
>                  from ./include/asm-generic/bug.h:13,
>                  from ./arch/arm/include/asm/bug.h:59,
>                  from ./include/linux/bug.h:4,
>                  from ./include/linux/io.h:23,
>                  from ./arch/arm/include/asm/arch_gicv3.h:23,
>                  from ./include/linux/irqchip/arm-gic-v3.h:411,
>                  from arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.c:14:
> arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.c: In function 'vgic_v3_dispatch_sgi':
> ./include/linux/bitops.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
>  #define BIT(nr)   (1UL << (nr))
>                         ^
> arch/arm/kvm/../../../virt/kvm/arm/vgic/vgic-mmio-v3.c:614:20: note: in expansion of macro 'BIT'
>   broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
>                     ^
> Let's fix them now.
> 
> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-mmio-v3.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v26 1/7] arm64: kdump: reserve memory for crash dump kernel
From: Matthias Bruger @ 2016-09-22 10:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160907042908.6232-2-takahiro.akashi@linaro.org>



On 09/07/2016 06:29 AM, AKASHI Takahiro wrote:
> On the startup of primary kernel, the memory region used by crash dump
> kernel must be specified by "crashkernel=" kernel parameter.
> reserve_crashkernel() will allocate and reserve the region for later use.
>
> User space tools, like kexec-tools, will be able to find that region as
> 	- "Crash kernel" in /proc/iomem, or
> 	- "linux,crashkernel-base" and "linux,crashkernel-size" under
> 	  /sys/firmware/devicetree/base/chosen
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Signed-off-by: Mark Salter <msalter@redhat.com>
> Signed-off-by: Pratyush Anand <panand@redhat.com>
> Reviewed-by: James Morse <james.morse@arm.com>
> ---
>  arch/arm64/kernel/setup.c |   7 ++-
>  arch/arm64/mm/init.c      | 113 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 119 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index 514b4e3..38589b5 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -31,7 +31,6 @@
>  #include <linux/screen_info.h>
>  #include <linux/init.h>
>  #include <linux/kexec.h>
> -#include <linux/crash_dump.h>
>  #include <linux/root_dev.h>
>  #include <linux/cpu.h>
>  #include <linux/interrupt.h>
> @@ -225,6 +224,12 @@ static void __init request_standard_resources(void)
>  		    kernel_data.end <= res->end)
>  			request_resource(res, &kernel_data);
>  	}
> +
> +#ifdef CONFIG_KEXEC_CORE
> +	/* User space tools will find "Crash kernel" region in /proc/iomem. */
> +	if (crashk_res.end)
> +		insert_resource(&iomem_resource, &crashk_res);
> +#endif
>  }
>
>  u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index bbb7ee7..dd273ec 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -29,11 +29,13 @@
>  #include <linux/gfp.h>
>  #include <linux/memblock.h>
>  #include <linux/sort.h>
> +#include <linux/of.h>
>  #include <linux/of_fdt.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/dma-contiguous.h>
>  #include <linux/efi.h>
>  #include <linux/swiotlb.h>
> +#include <linux/kexec.h>
>
>  #include <asm/boot.h>
>  #include <asm/fixmap.h>
> @@ -76,6 +78,114 @@ static int __init early_initrd(char *p)
>  early_param("initrd", early_initrd);
>  #endif
>
> +#ifdef CONFIG_KEXEC_CORE
> +static unsigned long long crash_size, crash_base;
> +static struct property crash_base_prop = {
> +	.name = "linux,crashkernel-base",
> +	.length = sizeof(u64),
> +	.value = &crash_base
> +};
> +static struct property crash_size_prop = {
> +	.name = "linux,crashkernel-size",
> +	.length = sizeof(u64),
> +	.value = &crash_size,
> +};
> +
> +static int __init export_crashkernel(void)
> +{
> +	struct device_node *node;
> +	int ret;
> +
> +	if (!crashk_res.end)
> +		return 0;
> +
> +	crash_base = cpu_to_be64(crashk_res.start);
> +	crash_size = cpu_to_be64(crashk_res.end - crashk_res.start + 1);
> +

Shouldn't that be the same values as in reserve_crashkernel()?
IMHO this does not need to be recalculated here.

Regards,
Matthias

> +	/* Add /chosen/linux,crashkernel-* properties */
> +	node = of_find_node_by_path("/chosen");
> +	if (!node)
> +		return -ENOENT;
> +
> +	/*
> +	 * There might be existing crash kernel properties, but we can't
> +	 * be sure what's in them, so remove them.
> +	 */
> +	of_remove_property(node, of_find_property(node,
> +				"linux,crashkernel-base", NULL));
> +	of_remove_property(node, of_find_property(node,
> +				"linux,crashkernel-size", NULL));
> +
> +	ret = of_add_property(node, &crash_base_prop);
> +	if (ret)
> +		goto ret_err;
> +
> +	ret = of_add_property(node, &crash_size_prop);
> +	if (ret)
> +		goto ret_err;
> +
> +	return 0;
> +
> +ret_err:
> +	pr_warn("Exporting crashkernel region to device tree failed\n");
> +	return ret;
> +}
> +late_initcall(export_crashkernel);
> +
> +/*
> + * reserve_crashkernel() - reserves memory for crash kernel
> + *
> + * This function reserves memory area given in "crashkernel=" kernel command
> + * line parameter. The memory reserved is used by dump capture kernel when
> + * primary kernel is crashing.
> + */
> +static void __init reserve_crashkernel(void)
> +{
> +	int ret;
> +
> +	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
> +				&crash_size, &crash_base);
> +	/* no crashkernel= or invalid value specified */
> +	if (ret || !crash_size)
> +		return;
> +
> +	if (crash_base == 0) {
> +		/* Current arm64 boot protocol requires 2MB alignment */
> +		crash_base = memblock_find_in_range(0, ARCH_LOW_ADDRESS_LIMIT,
> +				crash_size, SZ_2M);
> +		if (crash_base == 0) {
> +			pr_warn("Unable to allocate crashkernel (size:%llx)\n",
> +				crash_size);
> +			return;
> +		}
> +	} else {
> +		/* User specifies base address explicitly. */
> +		if (!memblock_is_region_memory(crash_base, crash_size) ||
> +			memblock_is_region_reserved(crash_base, crash_size)) {
> +			pr_warn("crashkernel has wrong address or size\n");
> +			return;
> +		}
> +
> +		if (!IS_ALIGNED(crash_base, SZ_2M)) {
> +			pr_warn("crashkernel base address is not 2MB aligned\n");
> +			return;
> +		}
> +	}
> +	memblock_reserve(crash_base, crash_size);
> +
> +	pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",
> +		crash_size >> 20, crash_base >> 20);
> +
> +	crashk_res.start = crash_base;
> +	crashk_res.end = crash_base + crash_size - 1;
> +}
> +#else
> +static void __init reserve_crashkernel(void)
> +{
> +	;
> +}
> +#endif /* CONFIG_KEXEC_CORE */
> +
>  /*
>   * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
>   * currently assumes that for memory starting above 4G, 32-bit devices will
> @@ -296,6 +406,9 @@ void __init arm64_memblock_init(void)
>  		arm64_dma_phys_limit = max_zone_dma_phys();
>  	else
>  		arm64_dma_phys_limit = PHYS_MASK + 1;
> +
> +	reserve_crashkernel();
> +
>  	dma_contiguous_reserve(arm64_dma_phys_limit);
>
>  	memblock_allow_resize();
>

^ permalink raw reply

* [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Mugunthan V N @ 2016-09-22 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1dbd7bbd-36ac-4433-79bf-8975a06dd07e@ti.com>

On Thursday 22 September 2016 11:48 AM, Vignesh R wrote:
> 
> 
> On Wednesday 21 September 2016 09:41 PM, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c      | 160 ++++++++++++++++++++++++++++++++++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include <linux/iio/buffer.h>
>>  #include <linux/iio/kfifo_buf.h>
>>  
>> +#include <linux/dmaengine.h>
>> +#include <linux/dma-mapping.h>
>> +
>> +#define DMA_BUFFER_SIZE		SZ_2K
>> +
>> +struct tiadc_dma {
>> +	/* Filter function */
>> +	dma_filter_fn		fn;
>> +	/* Parameter to the filter function */
>> +	void			*param;
> 
> These will not be needed with newer APIs (see below)
> 
>> +	struct dma_slave_config	conf;
>> +	struct dma_chan		*chan;
>> +	dma_addr_t		addr;
>> +	dma_cookie_t		cookie;
>> +	u8			*buf;
>> +	bool			valid_buf_seg;
>> +	int			buf_offset;
>> +	u8			fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  	struct ti_tscadc_dev *mfd_tscadc;
>> +	struct tiadc_dma dma;
>>  	struct mutex fifo1_lock; /* to protect fifo access */
>>  	int channels;
>> +	int total_ch_enabled;
>>  	u8 channel_line[8];
>>  	u8 channel_step[8];
>>  	int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  	u16 *data = adc_dev->data;
>>  
>>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  	for (k = 0; k < fifo1count; k = k + i) {
>>  		for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  			read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  	return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +	struct iio_dev *indio_dev = param;
>> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>> +	u8 *data;
>> +	int i;
>> +
>> +	data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
>> +	dma->valid_buf_seg = !dma->valid_buf_seg;
>> +
>> +	for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +		iio_push_to_buffers(indio_dev, data);
>> +		data += indio_dev->scan_bytes;
>> +	}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>> +	struct dma_async_tx_descriptor *desc;
>> +
>> +	dma->valid_buf_seg = false;
>> +	dma->fifo_thresh = FIFO1_THRESHOLD;
>> +	/*
>> +	 * Make the fifo thresh as the multiple of total number of
>> +	 * channels enabled, so make sure that that cyclic DMA period
>> +	 * length is also a multiple of total number of channels
>> +	 * enabled. This ensures that no invalid data is reported
>> +	 * to the stack via iio_push_to_buffers().
>> +	 */
>> +	dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
> 
> Can we use rounddown(FIFO1_THRESHOLD + 1, adc_dev->total_ch_enabled)?
> 
>> +	dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> +	/* Make sure that period length is multiple of fifo thresh level */
>> +	dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
>> +					      sizeof(u16));
>> +
> 
> Can we use rounddown()?

Will change this in next version.

> 
>> +	dma->conf.src_maxburst = dma->fifo_thresh + 1;
>> +	dmaengine_slave_config(dma->chan, &dma->conf);
>> +
>> +	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
>> +					 dma->buf_offset * 2,
>> +					 dma->buf_offset, DMA_DEV_TO_MEM,
>> +					 DMA_PREP_INTERRUPT);
>> +	if (!desc)
>> +		return -EBUSY;
>> +
>> +	desc->callback = tiadc_dma_rx_complete;
>> +	desc->callback_param = indio_dev;
>> +
>> +	dma->cookie = dmaengine_submit(desc);
>> +
>> +	dma_async_issue_pending(dma->chan);
>> +
>> +	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
>> +	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
>> +	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
>> +
>> +	return 0;
>> +}
>> +
>>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	unsigned int enb = 0;
>>  	u8 bit;
>> +	u32 irq_enable;
>>  
>>  	tiadc_step_config(indio_dev);
>> -	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
>> +	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
>>  		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
>> +		adc_dev->total_ch_enabled++;
>> +	}
>>  	adc_dev->buffer_en_ch_steps = enb;
>>  
>> +	if (dma->chan)
>> +		tiadc_start_dma(indio_dev);
>> +
>>  	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
>>  
>>  	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
>>  				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
>> -	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
>> -				| IRQENB_FIFO1OVRRUN);
>> +
>> +	irq_enable = IRQENB_FIFO1OVRRUN;
>> +	if (!dma->chan)
>> +		irq_enable |= IRQENB_FIFO1THRES;
>> +	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
>>  
>>  	return 0;
>>  }
>> @@ -239,12 +334,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	int fifo1count, i, read;
>>  
>>  	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
>>  				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
>>  	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
>>  	adc_dev->buffer_en_ch_steps = 0;
>> +	adc_dev->total_ch_enabled = 0;
>> +	if (dma->chan) {
>> +		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
>> +		dmaengine_terminate_async(dma->chan);
>> +	}
>>  
>>  	/* Flush FIFO of leftover data in the time it takes to disable adc */
>>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> @@ -430,6 +531,50 @@ static const struct iio_info tiadc_info = {
>>  	.driver_module = THIS_MODULE,
>>  };
>>  
>> +static bool the_no_dma_filter_fn(struct dma_chan *chan, void *param)
>> +{
>> +	return false;
>> +}
>> +
>> +static int tiadc_request_dma(struct platform_device *pdev,
>> +			     struct tiadc_device *adc_dev)
>> +{
>> +	struct tiadc_dma	*dma = &adc_dev->dma;
>> +	dma_cap_mask_t		mask;
>> +
>> +	dma->fn = the_no_dma_filter_fn;
>> +
>> +	/* Default slave configuration parameters */
>> +	dma->conf.direction = DMA_DEV_TO_MEM;
>> +	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
>> +	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
>> +
>> +	dma_cap_zero(mask);
>> +	dma_cap_set(DMA_CYCLIC, mask);
>> +
>> +	/* Get a channel for RX */
>> +	dma->chan = dma_request_slave_channel_compat(mask,
>> +						     dma->fn, dma->param,
>> +						     adc_dev->mfd_tscadc->dev,
>> +						     "fifo1");
> 
> Please use dma_request_chan() API instead, this does not need
> dma_filter_fn and probe defer can be handled.

Okay

> 
>> +	if (!dma->chan)
>> +		return -ENODEV;
>> +
>> +	/* RX buffer */
>> +	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>> +				      &dma->addr, GFP_KERNEL);
>> +	if (!dma->buf)
>> +		goto err;
>> +
>> +	dev_dbg_ratelimited(adc_dev->mfd_tscadc->dev, "got dma channel\n");
> 
> Do we need _ratelimited? AFAICS, this print is called only once.

True, will change to dev_dbg.

> 
>> +
>> +	return 0;
>> +err:
>> +	dma_release_channel(dma->chan);
>> +
>> +	return -ENOMEM;
>> +}
>> +
>>  static int tiadc_parse_dt(struct platform_device *pdev,
>>  			  struct tiadc_device *adc_dev)
>>  {
>> @@ -512,8 +657,14 @@ static int tiadc_probe(struct platform_device *pdev)
>>  
>>  	platform_set_drvdata(pdev, indio_dev);
>>  
>> +	err = tiadc_request_dma(pdev, adc_dev);
>> +	if (err && err != -ENODEV)
>> +		goto err_dma;
>> +
>>  	return 0;
>>  
>> +err_dma:
>> +	iio_device_unregister(indio_dev);
>>  err_buffer_unregister:
>>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>>  err_free_channels:
>> @@ -525,8 +676,11 @@ static int tiadc_remove(struct platform_device *pdev)
>>  {
>>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	u32 step_en;
>>  
>> +	if (dma->chan)
>> +		dma_release_channel(dma->chan);
> 
> dma_free_coherent() for dma->buf?

Oops missed, will fix in next version.

Regards
Mugunthan V N

> 
>>  	iio_device_unregister(indio_dev);
>>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>>  	tiadc_channels_remove(indio_dev);
>> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
>> index e45a208..fb9dc99 100644
>> --- a/include/linux/mfd/ti_am335x_tscadc.h
>> +++ b/include/linux/mfd/ti_am335x_tscadc.h
>> @@ -23,6 +23,8 @@
>>  #define REG_IRQENABLE		0x02C
>>  #define REG_IRQCLR		0x030
>>  #define REG_IRQWAKEUP		0x034
>> +#define REG_DMAENABLE_SET	0x038
>> +#define REG_DMAENABLE_CLEAR	0x038
>>  #define REG_CTRL		0x040
>>  #define REG_ADCFSM		0x044
>>  #define REG_CLKDIV		0x04C
>> @@ -36,6 +38,7 @@
>>  #define REG_FIFO0THR		0xE8
>>  #define REG_FIFO1CNT		0xF0
>>  #define REG_FIFO1THR		0xF4
>> +#define REG_DMA1REQ		0xF8
>>  #define REG_FIFO0		0x100
>>  #define REG_FIFO1		0x200
>>  
>> @@ -126,6 +129,10 @@
>>  #define FIFOREAD_DATA_MASK (0xfff << 0)
>>  #define FIFOREAD_CHNLID_MASK (0xf << 16)
>>  
>> +/* DMA ENABLE/CLEAR Register */
>> +#define DMA_FIFO0		BIT(0)
>> +#define DMA_FIFO1		BIT(1)
>> +
>>  /* Sequencer Status */
>>  #define SEQ_STATUS BIT(5)
>>  #define CHARGE_STEP		0x11
>>
> 

^ permalink raw reply

* [PATCH] crypto: sun4i-ss: mark sun4i_hash() static
From: Herbert Xu @ 2016-09-22 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474203164-14884-1-git-send-email-baoyou.xie@linaro.org>

On Sun, Sep 18, 2016 at 08:52:44PM +0800, Baoyou Xie wrote:
> We get 1 warning when building kernel with W=1:
> drivers/crypto/sunxi-ss/sun4i-ss-hash.c:168:5: warning: no previous prototype for 'sun4i_hash' [-Wmissing-prototypes]
> 
> In fact, this function is only used in the file in which it is
> declared and don't need a declaration, but can be made static.
> So this patch marks it 'static'.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH 0/8] crypto: omap-sham: convert to sg based data engine
From: Herbert Xu @ 2016-09-22 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474298539-23897-1-git-send-email-t-kristo@ti.com>

On Mon, Sep 19, 2016 at 06:22:11PM +0300, Tero Kristo wrote:
> Hi,
> 
> This series converts the omap-sham buffer handling towards a scatterlist
> approach. This avoids the need to have a huge internal buffer within the
> driver, and also allows us to properly implement export/import for the
> driver. I tried splitting up the changes to some sane patches, but this
> was rather difficult due to the fact that this is largely a complete
> rewrite of portions of the driver. Patch #6 is a prime example of this
> being pretty large, but splitting this up would break bisectability.
> Hopefully the patch is still understandable though.
> 
> Crypto manager tests work fine at least on omap3/am3/am4/dra7 SoC:s.
> (Something is broken with test farm again and could not try omap2/omap4.)
> 
> Also tested tcrypt SHA performance on DRA7 and it seems to be working
> fine with different buffer sizes.
> 
> My test branch is also available here for interested parties:
> tree: https://github.com/t-kristo/linux-pm.git
> breanch: 4.8-rc1-crypto

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] hwrng: omap - Only fail if pm_runtime_get_sync returns < 0
From: Herbert Xu @ 2016-09-22 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160920152540.3004-1-d-gerlach@ti.com>

On Tue, Sep 20, 2016 at 10:25:40AM -0500, Dave Gerlach wrote:
> Currently omap-rng checks the return value of pm_runtime_get_sync and
> reports failure if anything is returned, however it should be checking
> if ret < 0 as pm_runtime_get_sync return 0 on success but also can return
> 1 if the device was already active which is not a failure case. Only
> values < 0 are actual failures.
> 
> Fixes: 61dc0a446e5d ("hwrng: omap - Fix assumption that runtime_get_sync will always succeed")
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Mugunthan V N @ 2016-09-22 10:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <94b46406-577e-9cec-8e79-1134581932c5@ti.com>

On Thursday 22 September 2016 12:50 PM, Peter Ujfalusi wrote:
> On 09/21/16 19:11, Mugunthan V N wrote:
>> This patch adds the required pieces to ti_am335x_adc driver for
>> DMA support
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>>  drivers/iio/adc/ti_am335x_adc.c      | 160 ++++++++++++++++++++++++++++++++++-
>>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>>  2 files changed, 164 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>> index c3cfacca..89d0b07 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -30,10 +30,32 @@
>>  #include <linux/iio/buffer.h>
>>  #include <linux/iio/kfifo_buf.h>
>>  
>> +#include <linux/dmaengine.h>
>> +#include <linux/dma-mapping.h>
>> +
>> +#define DMA_BUFFER_SIZE		SZ_2K
>> +
>> +struct tiadc_dma {
>> +	/* Filter function */
>> +	dma_filter_fn		fn;
>> +	/* Parameter to the filter function */
>> +	void			*param;
>> +	struct dma_slave_config	conf;
>> +	struct dma_chan		*chan;
>> +	dma_addr_t		addr;
>> +	dma_cookie_t		cookie;
>> +	u8			*buf;
>> +	bool			valid_buf_seg;
>> +	int			buf_offset;
>> +	u8			fifo_thresh;
>> +};
>> +
>>  struct tiadc_device {
>>  	struct ti_tscadc_dev *mfd_tscadc;
>> +	struct tiadc_dma dma;
>>  	struct mutex fifo1_lock; /* to protect fifo access */
>>  	int channels;
>> +	int total_ch_enabled;
>>  	u8 channel_line[8];
>>  	u8 channel_step[8];
>>  	int buffer_en_ch_steps;
>> @@ -184,6 +206,7 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  	u16 *data = adc_dev->data;
>>  
>>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> +
>>  	for (k = 0; k < fifo1count; k = k + i) {
>>  		for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
>>  			read = tiadc_readl(adc_dev, REG_FIFO1);
>> @@ -198,6 +221,68 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>>  	return IRQ_HANDLED;
>>  }
>>  
>> +static void tiadc_dma_rx_complete(void *param)
>> +{
>> +	struct iio_dev *indio_dev = param;
>> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>> +	u8 *data;
>> +	int i;
>> +
>> +	data = dma->valid_buf_seg ? dma->buf + dma->buf_offset : dma->buf;
> 
> bool valid_buf_seg ? The buffer segment is valid or not valid? Which buffer
> segment is valid when valid_buf_seg is true?
> 
> I know what this is doing, but it is logically not correct.
> 
> Instead you could have:
> 
> int current_period; /* The period the DMA is working on */
> 
> When you start the DMA:
> dma->current_period = 0; /* We start to fill period 0 */
> 
> In here:
> 
> u8 *data = dma->buf + (dma->current_period * dma_period_size);
> 
>> +	dma->valid_buf_seg = !dma->valid_buf_seg;
> 
> /* Currently we have only two periods, so we can just */
> dma->current_period = !dma->current_period;
> /* or */
> dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
> 
> I think this would make it better to follow and if later you figure that you
> want three or more periods instead of the two, it is going to be easier to add
> that.

Okay, will change this in next version patch.

> 
>> +
>> +	for (i = 0; i < dma->buf_offset; i += indio_dev->scan_bytes) {
>> +		iio_push_to_buffers(indio_dev, data);
>> +		data += indio_dev->scan_bytes;
>> +	}
>> +}
>> +
>> +static int tiadc_start_dma(struct iio_dev *indio_dev)
>> +{
>> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>> +	struct dma_async_tx_descriptor *desc;
>> +
>> +	dma->valid_buf_seg = false;
>> +	dma->fifo_thresh = FIFO1_THRESHOLD;
> 
> FIFO1_THRESHOLD is defined as 19 in the global header file, so
> if you have 2 channels enabled the trigger comes when the FIFO have 10
> samples/ch, in case of all 8 channels enabled you will round it down the
> trigger comes when you have 2 samples/ch.
> 
> Would not be better to try to use high threshold for the FIFO to reduce the
> number of DMA requests needed runtime?
> 
> It is OK as it is at the moment, but I think it would make sense to try to
> maximize the FIFO usage.

I had already tried with higher values, It works fine. Just don't want
to change the non-DMA implementation as I am not aware of any
limitations why at the first place they have used fifo threshold as 19.

> 
>> +	/*
>> +	 * Make the fifo thresh as the multiple of total number of
>> +	 * channels enabled, so make sure that that cyclic DMA period
>> +	 * length is also a multiple of total number of channels
>> +	 * enabled. This ensures that no invalid data is reported
>> +	 * to the stack via iio_push_to_buffers().
>> +	 */
>> +	dma->fifo_thresh -= (dma->fifo_thresh + 1) % adc_dev->total_ch_enabled;
>> +	dma->buf_offset = DMA_BUFFER_SIZE / 2;
>> +	/* Make sure that period length is multiple of fifo thresh level */
>> +	dma->buf_offset -= dma->buf_offset % ((dma->fifo_thresh + 1) *
>> +					      sizeof(u16));
>> +
>> +	dma->conf.src_maxburst = dma->fifo_thresh + 1;
>> +	dmaengine_slave_config(dma->chan, &dma->conf);
>> +
>> +	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
>> +					 dma->buf_offset * 2,
>> +					 dma->buf_offset, DMA_DEV_TO_MEM,
> 
> I find the buf_offset name and it's use really confusing. It should be called
> period_size, really.

Yes, will fix this.

> 
>> +					 DMA_PREP_INTERRUPT);
>> +	if (!desc)
>> +		return -EBUSY;
>> +
>> +	desc->callback = tiadc_dma_rx_complete;
>> +	desc->callback_param = indio_dev;
>> +
>> +	dma->cookie = dmaengine_submit(desc);
>> +
>> +	dma_async_issue_pending(dma->chan);
>> +
>> +	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
>> +	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
>> +	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
>> +
>> +	return 0;
>> +}
>> +
>>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> @@ -218,20 +303,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	unsigned int enb = 0;
>>  	u8 bit;
>> +	u32 irq_enable;
>>  
>>  	tiadc_step_config(indio_dev);
>> -	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
>> +	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
>>  		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
>> +		adc_dev->total_ch_enabled++;
>> +	}
>>  	adc_dev->buffer_en_ch_steps = enb;
>>  
>> +	if (dma->chan)
>> +		tiadc_start_dma(indio_dev);
>> +
>>  	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
>>  
>>  	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
>>  				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
>> -	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
>> -				| IRQENB_FIFO1OVRRUN);
>> +
>> +	irq_enable = IRQENB_FIFO1OVRRUN;
>> +	if (!dma->chan)
>> +		irq_enable |= IRQENB_FIFO1THRES;
>> +	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
>>  
>>  	return 0;
>>  }
>> @@ -239,12 +334,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>>  static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
>>  {
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	int fifo1count, i, read;
>>  
>>  	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
>>  				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
>>  	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
>>  	adc_dev->buffer_en_ch_steps = 0;
>> +	adc_dev->total_ch_enabled = 0;
>> +	if (dma->chan) {
>> +		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
>> +		dmaengine_terminate_async(dma->chan);
>> +	}
>>  
>>  	/* Flush FIFO of leftover data in the time it takes to disable adc */
>>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> @@ -430,6 +531,50 @@ static const struct iio_info tiadc_info = {
>>  	.driver_module = THIS_MODULE,
>>  };
>>  
>> +static bool the_no_dma_filter_fn(struct dma_chan *chan, void *param)
>> +{
>> +	return false;
>> +}
>> +
>> +static int tiadc_request_dma(struct platform_device *pdev,
>> +			     struct tiadc_device *adc_dev)
>> +{
>> +	struct tiadc_dma	*dma = &adc_dev->dma;
>> +	dma_cap_mask_t		mask;
>> +
>> +	dma->fn = the_no_dma_filter_fn;
>> +
>> +	/* Default slave configuration parameters */
>> +	dma->conf.direction = DMA_DEV_TO_MEM;
>> +	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
>> +	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
>> +
>> +	dma_cap_zero(mask);
>> +	dma_cap_set(DMA_CYCLIC, mask);
>> +
>> +	/* Get a channel for RX */
>> +	dma->chan = dma_request_slave_channel_compat(mask,
>> +						     dma->fn, dma->param,
>> +						     adc_dev->mfd_tscadc->dev,
>> +						     "fifo1");
> 
> dma_request_chan()

Will fix this.

> 
>> +	if (!dma->chan)
>> +		return -ENODEV;
>> +
>> +	/* RX buffer */
>> +	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>> +				      &dma->addr, GFP_KERNEL);
>> +	if (!dma->buf)
>> +		goto err;
>> +
>> +	dev_dbg_ratelimited(adc_dev->mfd_tscadc->dev, "got dma channel\n");
>> +
>> +	return 0;
>> +err:
>> +	dma_release_channel(dma->chan);
>> +
>> +	return -ENOMEM;
>> +}
>> +
>>  static int tiadc_parse_dt(struct platform_device *pdev,
>>  			  struct tiadc_device *adc_dev)
>>  {
>> @@ -512,8 +657,14 @@ static int tiadc_probe(struct platform_device *pdev)
>>  
>>  	platform_set_drvdata(pdev, indio_dev);
>>  
>> +	err = tiadc_request_dma(pdev, adc_dev);
>> +	if (err && err != -ENODEV)
>> +		goto err_dma;
>> +
>>  	return 0;
>>  
>> +err_dma:
>> +	iio_device_unregister(indio_dev);
>>  err_buffer_unregister:
>>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>>  err_free_channels:
>> @@ -525,8 +676,11 @@ static int tiadc_remove(struct platform_device *pdev)
>>  {
>>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> +	struct tiadc_dma *dma = &adc_dev->dma;
>>  	u32 step_en;
>>  
>> +	if (dma->chan)
>> +		dma_release_channel(dma->chan);
>>  	iio_device_unregister(indio_dev);
>>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>>  	tiadc_channels_remove(indio_dev);
>> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
>> index e45a208..fb9dc99 100644
>> --- a/include/linux/mfd/ti_am335x_tscadc.h
>> +++ b/include/linux/mfd/ti_am335x_tscadc.h
>> @@ -23,6 +23,8 @@
>>  #define REG_IRQENABLE		0x02C
>>  #define REG_IRQCLR		0x030
>>  #define REG_IRQWAKEUP		0x034
>> +#define REG_DMAENABLE_SET	0x038
>> +#define REG_DMAENABLE_CLEAR	0x038
>>  #define REG_CTRL		0x040
>>  #define REG_ADCFSM		0x044
>>  #define REG_CLKDIV		0x04C
>> @@ -36,6 +38,7 @@
>>  #define REG_FIFO0THR		0xE8
>>  #define REG_FIFO1CNT		0xF0
>>  #define REG_FIFO1THR		0xF4
>> +#define REG_DMA1REQ		0xF8
>>  #define REG_FIFO0		0x100
>>  #define REG_FIFO1		0x200
>>  
>> @@ -126,6 +129,10 @@
>>  #define FIFOREAD_DATA_MASK (0xfff << 0)
>>  #define FIFOREAD_CHNLID_MASK (0xf << 16)
>>  
>> +/* DMA ENABLE/CLEAR Register */
>> +#define DMA_FIFO0		BIT(0)
>> +#define DMA_FIFO1		BIT(1)
>> +
>>  /* Sequencer Status */
>>  #define SEQ_STATUS BIT(5)
>>  #define CHARGE_STEP		0x11
>>
> 
> 

--
Regards
Mugunthan V N

^ permalink raw reply

* [PATCH V6 3/5] PCI: thunder-pem: Allow to probe PEM-specific register range for ACPI case
From: Gabriele Paoloni @ 2016-09-22 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160922094955.GB18637@red-moon>

Hi Lorenzo, Bjorn

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: 22 September 2016 10:50
> To: Bjorn Helgaas
> Cc: Ard Biesheuvel; Tomasz Nowicki; David Daney; Will Deacon; Catalin
> Marinas; Rafael Wysocki; Arnd Bergmann; Hanjun Guo; Sinan Kaya;
> Jayachandran C; Christopher Covington; Duc Dang; Robert Richter; Marcin
> Wojtas; Liviu Dudau; Wangyijing; Mark Salter; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Linaro ACPI
> Mailman List; Jon Masters; Andrea Gallo; Jeremy Linton; liudongdong
> (C); Gabriele Paoloni; Jeff Hugo; linux-acpi at vger.kernel.org; linux-
> kernel at vger.kernel.org; Rafael J. Wysocki
> Subject: Re: [PATCH V6 3/5] PCI: thunder-pem: Allow to probe PEM-
> specific register range for ACPI case
> 
> On Wed, Sep 21, 2016 at 01:04:57PM -0500, Bjorn Helgaas wrote:
> > On Wed, Sep 21, 2016 at 03:05:49PM +0100, Lorenzo Pieralisi wrote:
> > > On Tue, Sep 20, 2016 at 02:17:44PM -0500, Bjorn Helgaas wrote:
> > > > On Tue, Sep 20, 2016 at 04:09:25PM +0100, Ard Biesheuvel wrote:
> > >
> > > [...]
> > >
> > > > > None of these platforms can be fixed entirely in software, and
> given
> > > > > that we will not be adding quirks for new broken hardware, we
> should
> > > > > ask ourselves whether having two versions of a quirk, i.e., one
> for
> > > > > broken hardware + currently shipping firmware, and one for the
> same
> > > > > broken hardware with fixed firmware is really an improvement
> over what
> > > > > has been proposed here.
> > > >
> > > > We're talking about two completely different types of quirks:
> > > >
> > > >   1) MCFG quirks to use memory-mapped config space that doesn't
> quite
> > > >      conform to the ECAM model in the PCIe spec, and
> > > >
> > > >   2) Some yet-to-be-determined method to describe address space
> > > >      consumed by a bridge.
> > > >
> > > > The first two patches of this series are a nice implementation
> for 1).
> > > > The third patch (ThunderX-specific) is one possibility for 2),
> but I
> > > > don't like it because there's no way for generic software like
> the
> > > > ACPI core to discover these resources.
> > >
> > > Ok, so basically this means that to implement (2) we need to assign
> > > some sort of _HID to these quirky PCI bridges (so that we know what
> > > device they represent and we can retrieve their _CRS). I take from
> > > this discussion that the goal is to make sure that all non-config
> > > resources have to be declared through _CRS device objects, which is
> > > fine but that requires a FW update (unless we can fabricate ACPI
> > > devices and corresponding _CRS in the kernel whenever we match a
> > > given MCFG table signature).
> >
> > All resources consumed by ACPI devices should be declared through
> > _CRS.  If you want to fabricate ACPI devices or _CRS via kernel
> > quirks, that's fine with me.  This could be triggered via MCFG
> > signature, DMI info, host bridge _HID, etc.
> 
> I think the PNP quirk approach + PNP0c02 resource put forward by Gab
> is enough.

Great thanks as we take a final decision I will ask Dogndgong to submit
another RFC based on this approach

> 
> > > We discussed this already and I think we should make a decision:
> > >
> > > http://lists.infradead.org/pipermail/linux-arm-kernel/2016-
> March/414722.html
> > >
> > > > > > I'd like to step back and come up with some understanding of
> how
> > > > > > non-broken firmware *should* deal with this issue.  Then, if
> we *do*
> > > > > > work around this particular broken firmware in the kernel, it
> would be
> > > > > > nice to do it in a way that fits in with that understanding.
> > > > > >
> > > > > > For example, if a companion ACPI device is the preferred
> solution, an
> > > > > > ACPI quirk could fabricate a device with the required
> resources.  That
> > > > > > would address the problem closer to the source and make it
> more likely
> > > > > > that the rest of the system will work correctly: /proc/iomem
> could
> > > > > > make sense, things that look at _CRS generically would work
> (e.g,
> > > > > > /sys/, an admittedly hypothetical "lsacpi", etc.)
> > > > > >
> > > > > > Hard-coding stuff in drivers is a point solution that doesn't
> provide
> > > > > > any guidance for future platforms and makes it likely that
> the hack
> > > > > > will get copied into even more drivers.
> > > > > >
> > > > >
> > > > > OK, I see. But the guidance for future platforms should be 'do
> not
> > > > > rely on quirks', and what I am arguing here is that the more we
> polish
> > > > > up this code and make it clean and reusable, the more likely it
> is
> > > > > that will end up getting abused by new broken hardware that we
> set out
> > > > > to reject entirely in the first place.
> > > > >
> > > > > So of course, if the quirk involves claiming resources, let's
> make
> > > > > sure that this occurs in the cleanest and most compliant way
> possible.
> > > > > But any factoring/reuse concerns other than for the current
> crop of
> > > > > broken hardware should be avoided imo.
> > > >
> > > > If future hardware is completely ECAM-compliant and we don't need
> any
> > > > more MCFG quirks, that would be great.
> > >
> > > Yes.
> > >
> > > > But we'll still need to describe that memory-mapped config space
> > > > somewhere.  If that's done with PNP0C02 or similar devices (as is
> done
> > > > on my x86 laptop), we'd be all set.
> > >
> > > I am not sure I understand what you mean here. Are you referring
> > > to MCFG regions reported as PNP0c02 resources through its _CRS ?
> >
> > Yes.  PCI Firmware Spec r3.0, Table 4-2, note 2 says address ranges
> > reported via MCFG or _CBA should be reserved by _CRS of a PNP0C02
> > device.
> 
> Ok, that's agreed. It goes without saying that since you are quoting
> the PCI spec, if FW fails to report MCFG regions in a PNP0c02 device
> _CRS I will consider that a FW bug.
> 
> > > IIUC PNP0C02 is a reservation mechanism, but it does not help us
> > > associate its _CRS to a specific PCI host bridge instance, right ?
> >
> > Gab proposed a hierarchy that *would* associate a PNP0C02 device with
> > a PCI bridge:
> >
> >   Device (PCI1) {
> >     Name (_HID, "HISI0080") // PCI Express Root Bridge
> >     Name (_CID, "PNP0A03") // Compatible PCI Root Bridge
> >     Method (_CRS, 0, Serialized) { // Root complex resources
> (windows) }
> >     Device (RES0) {
> >       Name (_HID, "HISI0081") // HiSi PCIe RC config base address
> >       Name (_CID, "PNP0C02")  // Motherboard reserved resource
> >       Name (_CRS, ResourceTemplate () { ... }
> >     }
> >   }
> >
> > That's a possibility.  The PCI Firmware Spec suggests putting RES0 at
> > the root (under \_SB), but I don't know why.
> >
> > Putting it at the root means we couldn't generically associate it
> with
> > a bridge, although I could imagine something like this:
> >
> >   Device (RES1) {
> >     Name (_HID, "HISI0081") // HiSi PCIe RC config base address
> >     Name (_CID, "PNP0C02")  // Motherboard reserved resource
> >     Name (_CRS, ResourceTemplate () { ... }
> >     Method (BRDG) { "PCI1" }  // hand-wavy ASL
> >   }
> >   Device (PCI1) {
> >     Name (_HID, "HISI0080") // PCI Express Root Bridge
> >     Name (_CID, "PNP0A03") // Compatible PCI Root Bridge
> >     Method (_CRS, 0, Serialized) { // Root complex resources
> (windows) }
> >   }
> >
> > Where you could search PNP0C02 devices for a cookie that matched the
> > host bridge.o
> 
> Ok, I am fine with both and I think we are converging, but the way
> to solve this problem has to be uniform for all ARM partners (and
> not only ARM). Two points here:
> 
> 1) Adding a device/subdevice allows people to add a _CRS reporting the
>    non-window bridge resources. Fine. It also allows people to chuck in
>    there all sorts of _DSD properties to describe their PCI host bridge
>    as it is done with DT properties (those _DSD can contain eg clocks
>    etc.), this may be tempting (so that they can reuse the same DT
>    driver and do not have to update their firmware) but I want to be
>    clear here: that must not happen. So, a subdevice with a _CRS to
>    report resources, yes, but it will stop there.
> 2) It is unclear to me how to formalize the above. People should not
>    write FW by reading the PCI mailing list, so these guidelines have
> to
>    be written, somehow. I do not want to standardize quirks, I want
>    to prevent random ACPI table content, which is different.
>    Should I report this to the ACPI spec working group ? If we do
>    not do that everyone will go solve this problem as they deem fit.
> 

Do we really need to formalize this?

As we discussed in the Linaro call at the moment we have few vendors
that need quirks and we want to avoid promoting/accepting quirks for
the future.

At the time of the call I think we decided to informally accept a set
of quirks for the current platforms and reject any other quirk coming
after a certain date/kernel version (this to be decided).

I am not sure if there is a way to document/formalize a temporary
exception from the rule...

Thanks

Gab 


> [...]
> 
> > > For FW that is immutable I really do not see what we can do apart
> > > from hardcoding the non-config resources (consumed by a bridge),
> > > somehow.
> >
> > Right.  Well, I assume you mean we should hard-code "non-window
> > resources consumed directly by a bridge".  If firmware in the field
> is
> > broken, we should work around it, and that may mean hard-coding some
> > resources.
> >
> > My point is that the hard-coding should not be buried in a driver
> > where it's invisible to the rest of the kernel.  If we hard-code it
> in
> > a quirk that adds _CRS entries, then the kernel will work just like
> it
> > would if the firmware had been correct in the first place.  The
> > resource will appear in /sys/devices/pnp*/*/resources and
> /proc/iomem,
> > and if we ever used _SRS to assign or move ACPI devices, we would
> know
> > to avoid the bridge resource.
> 
> We are in complete agreement here.
> 
> Thanks,
> Lorenzo

^ permalink raw reply

* [PATCH V6 3/5] PCI: thunder-pem: Allow to probe PEM-specific register range for ACPI case
From: Gabriele Paoloni @ 2016-09-22 11:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160921185920.GC20006@localhost>

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas at kernel.org]
> Sent: 21 September 2016 19:59
> To: Gabriele Paoloni
> Cc: Ard Biesheuvel; Tomasz Nowicki; David Daney; Will Deacon; Catalin
> Marinas; Rafael Wysocki; Lorenzo Pieralisi; Arnd Bergmann; Hanjun Guo;
> Sinan Kaya; Jayachandran C; Christopher Covington; Duc Dang; Robert
> Richter; Marcin Wojtas; Liviu Dudau; Wangyijing; Mark Salter; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Linaro ACPI
> Mailman List; Jon Masters; Andrea Gallo; Jeremy Linton; liudongdong
> (C); Jeff Hugo; linux-acpi at vger.kernel.org; linux-
> kernel at vger.kernel.org; Rafael J. Wysocki
> Subject: Re: [PATCH V6 3/5] PCI: thunder-pem: Allow to probe PEM-
> specific register range for ACPI case
> 
> On Wed, Sep 21, 2016 at 02:10:55PM +0000, Gabriele Paoloni wrote:
> > Hi Bjorn
> >
> > [...]
> >
> >
> > >
> > > If future hardware is completely ECAM-compliant and we don't need
> any
> > > more MCFG quirks, that would be great.
> > >
> > > But we'll still need to describe that memory-mapped config space
> > > somewhere.  If that's done with PNP0C02 or similar devices (as is
> done
> > > on my x86 laptop), we'd be all set.
> > >
> > > If we need to work around firmware in the field that doesn't do
> that,
> > > one possibility is a PNP quirk along the lines of
> > > quirk_amd_mmconfig_area().
> >
> > So, if my understanding is correct, for platforms that have not been
> > shipped yet you propose to use PNP0C02 in the ACPI table in order to
> > declare a motherboard reserved resource whereas for shipped platforms
> > you propose to have a quirk along pnp_fixups in order to track the
> > resource usage even if values are hardcoded...correct?
> 
> Yes.  I'm open to alternate proposals, but x86 uses PNP0C02, and
> following existing practice seems reasonable.
> 
> > Before Tomasz came up with this patchset we had a call between the
> vendors
> > involved in this PCI quirks saga and other guys from Linaro and ARM.
> >
> > Lorenzo summarized the outcome as in the following link
> > http://lkml.iu.edu/hypermail/linux/kernel/1606.2/03344.html
> >
> > Since this quirks mechanism has been discussed for quite a long time
> now
> > IMHO it would be good to have a last call including also you (Bjorn)
> so
> > that we can all agree on what to do and we avoid changing our drivers
> again
> > and again...
> 
> I think we're converging pretty fast.  As far as I'm concerned, the
> v6 ECAM quirks implementation is perfect.  The only remaining issue is
> reporting the ECAM resources, and I haven't seen objections to using
> PNP0C02 + PNP quirks for broken firmware.
> 
> There is the question of how or whether to associate a PNP0A03 PCI
> bridge with resources from a different PNP0C02 device, but that's not
> super important.  If the hard-coded resources appear both in a quirk
> and in the PCI bridge driver, it's ugly but not the end of the world.
> We've still achieved the objective of avoiding landmines in the
> address space.

Ok got it many thanks

Gab

> 
> Bjorn

^ permalink raw reply

* [PATCH 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Peter Ujfalusi @ 2016-09-22 11:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0cd3dfcc-2525-c2fb-35ab-1b260c5973a8@ti.com>

On 09/22/16 13:45, Mugunthan V N wrote:
>>> +	if (!dma->chan)
>>> +		return -ENODEV;
>>> +
>>> +	/* RX buffer */
>>> +	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>>> +				      &dma->addr, GFP_KERNEL);
>>> +	if (!dma->buf)
>>> +		goto err;
>>> +
>>> +	dev_dbg_ratelimited(adc_dev->mfd_tscadc->dev, "got dma channel\n");
>>
>> Do we need _ratelimited? AFAICS, this print is called only once.
> 
> True, will change to dev_dbg.

It would be better to remove it. It gives no useful debuggin information apart
from the fact that the driver did not failed to probe.

-- 
P?ter

^ permalink raw reply

* [PATCH v4 2/2] KVM: arm/arm64: Route vtimer events to user space
From: Alexander Graf @ 2016-09-22 11:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57E166F9.8080109@arm.com>

On 09/20/2016 06:42 PM, Marc Zyngier wrote:
> On 20/09/16 15:31, Alexander Graf wrote:
>> On 09/20/2016 02:37 PM, Marc Zyngier wrote:
> [...]
>
>>>>>> We also need to know "timer line low + timer line masked", as otherwise
>>>>>> we might get spurious interrupts in the guest, no?
>>>>> Yes. Though you can't really know about this one, and you'll have to
>>>>> wait until the next natural exit to find out. As long as the spurious is
>>>> We can provoke a special exit for it, no?
>>> How? The guest decides to disable its timer. That doesn't trigger any
>>> exit whatsoever. You'll have to wait until the next exit from the guest
>>> to notice it.
>> Before we inject a timer interrupt, we can check whether the pending
>> semantics of user space / kernel space match. If they don't match, we
>> can exit before we inject the interrupt and allow user space to disable
>> the pending state again.
> Let's rewind a bit, because I've long lost track of what you're trying
> to do to handle what.
>
> You need two signals:
>
> (1) TIMER_LEVEL: the output of the timer line, having accounted for the
> IMASK bit. This is conveniently the value of timer->irq.level.
>
> (2) TIMER_IRQ_MASK: an indication from userspace that a timer interrupt
> is pending, and that the physical line should be masked.
>
> You need a number of rules:
>
> (a) On exit to userspace, the kernel always exposes the value of
> TIMER_LEVEL.
>
> (b) On kernel entry, userspace always exposes the required
> TIMER_IRQ_MASK, depending on what has been exposed to it by TIMER_LEVEL.
>
> (c) If on guest exit, TIMER_LEVEL==1 and TIMER_IRQ_MASK==0, perform a
> userspace exit, because the emulated GIC needs to make the interrupt
> pending.

This should be "before guest entry", because the timer might have 
expired in between.

> (d) If on guest exit, TIMER_LEVEL==0 and TIMER_IRQ_MASK==1, perform a
> userspace exit, because the guest has disabled its timer before taking
> the interrupt, and the emulated GIC needs to retire the pending state.
>
> and that's it. Nothing else. The kernel tells userspace the state of the
> timer, and userspace drives the masking of the physical interrupt.
> Conveniently, this matches what the current code does.

Yup. It seems to work. It also does feel slower than the previous code, 
but maybe that's just me. It definitely is way more correct.

I'll trace around a bit more to see whether I can spot any obviously low 
hanging performance fruits, then prettify the patches and send them out :).


Alex

^ permalink raw reply

* [PATCH v2 1/3] phy_sun4i_usb: set_mode: Allow using set_mode to force end the current session
From: Hans de Goede @ 2016-09-22 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

The sunxi musb has a bug where sometimes it will generate a babble
error on device disconnect instead of a disconnect irq. When this
happens the musb-controller switches from host mode to device mode
(it clears MUSB_DEVCTL_SESSION and sets MUSB_DEVCTL_BDEVICE) and
gets stuck in this state.

Clearing this requires reporting Vbus low for 200 or more ms, but
on some devices Vbus is simply always high (host-only mode, no Vbus
control).

This commit modifies sun4i_usb_phy_set_mode so that it will force
end the current session when called with the current mode, before this
commit calling set_mode with the current mode was a nop since id_det
would stay the same resulting in the detect_work not doing anything.

This allows the sunxi-musb glue to use sun4i_usb_phy_set_mode to force
end the current session without changing the mode, to fixup the stuck
state after a babble error.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-New patch in v2 of this series replacing the
 "phy-sun4i-usb: Add sun4i_usb_phy_force_session_end() function"
 from v1
---
 drivers/phy/phy-sun4i-usb.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 43c0d98..d76538c 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -437,25 +437,32 @@ static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode)
 {
 	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 	struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+	enum usb_dr_mode new_mode;
 
 	if (phy->index != 0)
 		return -EINVAL;
 
 	switch (mode) {
 	case PHY_MODE_USB_HOST:
-		data->dr_mode = USB_DR_MODE_HOST;
+		new_mode = USB_DR_MODE_HOST;
 		break;
 	case PHY_MODE_USB_DEVICE:
-		data->dr_mode = USB_DR_MODE_PERIPHERAL;
+		new_mode = USB_DR_MODE_PERIPHERAL;
 		break;
 	case PHY_MODE_USB_OTG:
-		data->dr_mode = USB_DR_MODE_OTG;
+		new_mode = USB_DR_MODE_OTG;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	dev_info(&_phy->dev, "Changing dr_mode to %d\n", (int)data->dr_mode);
+	if (new_mode != data->dr_mode) {
+		dev_info(&_phy->dev, "Changing dr_mode to %d\n",
+			 (int)data->dr_mode);
+		data->dr_mode = new_mode;
+	}
+
+	data->id_det = -1; /* Force reprocessing of id */
 	data->force_session_end = true;
 	queue_delayed_work(system_wq, &data->detect, 0);
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 2/3] musb: sunxi: Remove custom babble handling
From: Hans de Goede @ 2016-09-22 11:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160922111901.15337-1-hdegoede@redhat.com>

The musb-core now a days always treats babble errors in host mode
as disconnects, so there is no need for the sunxi specific handling
of this anymore.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-This is a new patch in v2 of this patch series
---
 drivers/usb/musb/sunxi.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 1408245..82eba92 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -186,16 +186,6 @@ static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
 	if (musb->int_usb)
 		writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
 
-	/*
-	 * sunxi musb often signals babble on low / full speed device
-	 * disconnect, without ever raising MUSB_INTR_DISCONNECT, since
-	 * normally babble never happens treat it as disconnect.
-	 */
-	if ((musb->int_usb & MUSB_INTR_BABBLE) && is_host_active(musb)) {
-		musb->int_usb &= ~MUSB_INTR_BABBLE;
-		musb->int_usb |= MUSB_INTR_DISCONNECT;
-	}
-
 	if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
 		/* ep0 FADDR must be 0 when (re)entering peripheral mode */
 		musb_ep_select(musb->mregs, 0);
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 3/3] musb: sunxi: Force session end on babble errors in host-mode
From: Hans de Goede @ 2016-09-22 11:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160922111901.15337-1-hdegoede@redhat.com>

The sunxi musb has a bug where sometimes it will generate a babble
error on device disconnect instead of a disconnect irq. When this
happens the musb-controller switches from host mode to device mode
(it clears MUSB_DEVCTL_SESSION and sets MUSB_DEVCTL_BDEVICE) and
gets stuck in this state.

Clearing this requires reporting Vbus low for 200 or more ms, but
on some devices Vbus is simply always high (host-only mode, no Vbus
control).

This commit adds a sunxi_musb_recover() callback which makes
sunxi_musb_work call phy_set_mode with the current mode, which
will force end the current session.

This fixes the musb controller getting stuck in this state on systems
without Vbus control; and also fixes the need to unplug the usb-b ->
usb-a cable to get out of this state on systems with Vbus control.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-Use musb_platform_recover callback instead of using DYI code in the
 interrupt handler
-Call phy_set_mode with the current mode instead of adding a new custom
 sunxi phy callback
---
 drivers/usb/musb/sunxi.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 82eba92..d0be0ea 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -380,6 +380,20 @@ static int sunxi_musb_set_mode(struct musb *musb, u8 mode)
 	return 0;
 }
 
+static int sunxi_musb_recover(struct musb *musb)
+{
+	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+	/*
+	 * Schedule a phy_set_mode with the current glue->phy_mode value,
+	 * this will force end the current session.
+	 */
+	set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
+	schedule_work(&glue->work);
+
+	return 0;
+}
+
 /*
  * sunxi musb register layout
  * 0x00 - 0x17	fifo regs, 1 long per fifo
@@ -608,6 +622,7 @@ static const struct musb_platform_ops sunxi_musb_ops = {
 	.dma_init	= sunxi_musb_dma_controller_create,
 	.dma_exit	= sunxi_musb_dma_controller_destroy,
 	.set_mode	= sunxi_musb_set_mode,
+	.recover	= sunxi_musb_recover,
 	.set_vbus	= sunxi_musb_set_vbus,
 	.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
 	.post_root_reset_end = sunxi_musb_post_root_reset_end,
-- 
2.9.3

^ permalink raw reply related

* [PATCH v3] devicetree: bindings: uart: Add new compatible string for ZynqMP
From: Nava kishore Manne @ 2016-09-22 11:20 UTC (permalink / raw)
  To: linux-arm-kernel

From: Nava kishore Manne <nava.manne@xilinx.com>

This patch Adds the new compatiable string for ZynqMP.

Signed-off-by: Nava kishore Manne <navam@xilinx.com>
---
Changes for v3:
		-Added changeLog comment.
Changes for v2:
                -None

 Documentation/devicetree/bindings/serial/cdns,uart.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.txt b/Documentation/devicetree/bindings/serial/cdns,uart.txt
index a3eb154..4fe7aae 100644
--- a/Documentation/devicetree/bindings/serial/cdns,uart.txt
+++ b/Documentation/devicetree/bindings/serial/cdns,uart.txt
@@ -1,7 +1,8 @@
 Binding for Cadence UART Controller
 
 Required properties:
-- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps" for Zynq and
+               "cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC uart controller.
 - reg: Should contain UART controller registers location and length.
 - interrupts: Should contain UART controller interrupts.
 - clocks: Must contain phandles to the UART clocks
-- 
2.1.2

^ permalink raw reply related

* [PATCH v4] devicetree: bindings: uart: Add new compatible string for ZynqMP
From: Nava kishore Manne @ 2016-09-22 11:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Nava kishore Manne <nava.manne@xilinx.com>

This patch Adds the new compatible string for ZynqMP.

Signed-off-by: Nava kishore Manne <navam@xilinx.com>
---
Changes for v4:
		-Modified the ChangeLog comment.
Changes for v3:
		-Added changeLog comment.
Changes for v2:
                -None

 Documentation/devicetree/bindings/serial/cdns,uart.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.txt b/Documentation/devicetree/bindings/serial/cdns,uart.txt
index a3eb154..4fe7aae 100644
--- a/Documentation/devicetree/bindings/serial/cdns,uart.txt
+++ b/Documentation/devicetree/bindings/serial/cdns,uart.txt
@@ -1,7 +1,8 @@
 Binding for Cadence UART Controller
 
 Required properties:
-- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps" for Zynq and
+               "cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC uart controller.
 - reg: Should contain UART controller registers location and length.
 - interrupts: Should contain UART controller interrupts.
 - clocks: Must contain phandles to the UART clocks
-- 
2.1.2

^ permalink raw reply related

* [PATCH 0/2] Fix warnings for i2c-rk3x.c
From: David Wu @ 2016-09-22 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

David Wu (2):
  i2c: rk3x: Fix sparse warning
  i2c: rk3x: fix variable 'min_total_ns' unused warning

 drivers/i2c/busses/i2c-rk3x.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH 1/2] i2c: rk3x: Fix sparse warning
From: David Wu @ 2016-09-22 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474543764-51135-1-git-send-email-david.wu@rock-chips.com>

This patch fixes the following sparse warning:
drivers/i2c/busses/i2c-rk3x.c:888:17: warning: cast truncates bits from constant value (ffffffffff00 becomes ffffff00)

Signed-off-by: David Wu <david.wu@rock-chips.com>
---
 drivers/i2c/busses/i2c-rk3x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index f2d0148..965477e 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -58,7 +58,7 @@ enum {
 #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
 #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
 
-#define REG_CON_TUNING_MASK GENMASK(15, 8)
+#define REG_CON_TUNING_MASK GENMASK_ULL(15, 8)
 
 #define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
 #define REG_CON_STA_CFG(cfg) ((cfg) << 12)
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/2] i2c: rk3x: Fix variable 'min_total_ns' unused warning
From: David Wu @ 2016-09-22 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474543764-51135-1-git-send-email-david.wu@rock-chips.com>

This patch fixs the following warning:
drivers/i2c/busses/i2c-rk3x.c: In function 'rk3x_i2c_v1_calc_timings':
drivers/i2c/busses/i2c-rk3x.c:745:41: warning: variable 'min_total_ns' set but not used [-Wunused-but-set-variable]

Signed-off-by: David Wu <david.wu@rock-chips.com>
---
 drivers/i2c/busses/i2c-rk3x.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 965477e..50702c7 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -742,7 +742,7 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 				    struct i2c_timings *t,
 				    struct rk3x_i2c_calced_timings *t_calc)
 {
-	unsigned long min_low_ns, min_high_ns, min_total_ns;
+	unsigned long min_low_ns, min_high_ns;
 	unsigned long min_setup_start_ns, min_setup_data_ns;
 	unsigned long min_setup_stop_ns, max_hold_data_ns;
 
@@ -793,7 +793,6 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 
 	/* These are the min dividers needed for min hold times. */
 	min_div_for_hold = (min_low_div + min_high_div);
-	min_total_ns = min_low_ns + min_high_ns;
 
 	/*
 	 * This is the maximum divider so we don't go over the maximum.
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 0/3] efi: MMC proxy support for the UEFI varstore
From: Ard Biesheuvel @ 2016-09-22 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

================================================================================
NOTE: this is a work in progress, and not fully functional yet. In particular,
the actual MMC host protocol methods are stubbed out at the moment, and need to
be wired up to the Linux device drivers.
================================================================================

On mobile and embedded systems, there is usually only a single MMC device for
non-volatile storage, which sits behind a controller that is owned by the OS at
runtime. This makes it difficult to host the UEFI variable store on MMC as well,
since the UEFI runtime services routines expect ownership of the underlying
device as well.

This series proposes an approach to work around this. It implements the UEFI
MMC host protocol in the kernel, in a way that makes it possible to expose it
to the firmware. At the same time, the firmware needs be set up for this, i.e.,
it needs to expose its MMC host protocol pointer via a UEFI configuration table,
so that the kernel can override it if it decides to expose this functionality
to the firmware.

Note that these patches are based on patches in the EFI tree that are queued
for v4.9, which replace the runtime wrappers spinlock with a semaphore. This
allows us to sleep in the firmware callbacks.

Prerequisites for using these patches:

* qemu-system-aarch64 built from this branch:
  https://git.linaro.org/people/ard.biesheuvel/qemu.git/shortlog/refs/heads/mach-virt-pl181
  which adds a PL181 SD/MMC controller to the mach-virt model, and exposes it
  via the device tree. It also sets the 'linux,uefi-varstore' property on this
  node.

* UEFI firmware built from this branch:
  https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/mmc-proxy
  
  Build using the following command
  build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuMmcVars.dsc

  Run using 
  qemu-system-aarch64 \
    -M virt -cpu cortex-a57 -m 2048 \
    -device virtio-blk-device,drive=boot \
    -drive if=none,id=boot,file=fat:<path-of-Image>,format=raw \
    -kernel <edk2-dir>/Build/ArmVirtQemuMmcVars-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd \
    -sd <edk2-dir>/build/edk2/Build/ArmVirtQemuMmcVars-AARCH64/DEBUG_GCC5/FV/QEMU_VARS.fd \
    -nographic $@

  This will give you an UEFI environment which keeps its UEFI variables in the
  emulated MMC volume, and exposes its MMC host protocol in a way that allows
  these patches to hook into it.

Patches #1 and #2 implement the arch specific hooks to preserve/restore the NEON
registers that the firmware may expect to be preserved across function calls.

Patch #3 implements the plumbing to call back into the kernel from the firmware.

Please comment on whether this approach seems feasible, and in particular, how
on earth I should wire this up to the actual MMC code.

Thanks,
Ard.

Ard Biesheuvel (3):
  efi/arm64: add SIMD stash/unstash operations
  efi/arm: add SIMD stash/unstash operations
  efi: implement MMC proxy support for the UEFI variable store

 arch/arm/include/asm/efi.h       |  11 +
 arch/arm64/include/asm/efi.h     |  33 +++
 drivers/firmware/efi/Kconfig     |   9 +
 drivers/firmware/efi/Makefile    |   1 +
 drivers/firmware/efi/arm-init.c  |   2 +
 drivers/firmware/efi/mmc-proxy.c | 222 ++++++++++++++++++++
 include/linux/efi.h              |   1 +
 7 files changed, 279 insertions(+)
 create mode 100644 drivers/firmware/efi/mmc-proxy.c

-- 
2.7.4

^ permalink raw reply

* [RFC PATCH 1/3] efi/arm64: add SIMD stash/unstash operations
From: Ard Biesheuvel @ 2016-09-22 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474543806-19210-1-git-send-email-ard.biesheuvel@linaro.org>

This adds the SIMD stash/unstash operations that we need to allow UEFI
runtime services calls to call back into the kernel.

The UEFI bindings for arm64 stipulate that the ordinary AAPCS rules apply,
which means that code may use FP/NEON registers, and may also expect that
the values of the callee saved registers q8 - q15 are preserved across
function calls.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/include/asm/efi.h | 33 ++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index a9e54aad15ef..d6bbbcba9820 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -81,4 +81,37 @@ static inline void efi_set_pgd(struct mm_struct *mm)
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
 
+struct efi_simd_reg_stash {
+	u8	q8[16];
+	u8	q9[16];
+	u8	q10[16];
+	u8	q11[16];
+	u8	q12[16];
+	u8	q13[16];
+	u8	q14[16];
+	u8	q15[16];
+};
+
+static inline void arch_efi_stash_simd_regs(struct efi_simd_reg_stash *stash)
+{
+	asm(	"stp	q8,  q9,  [%1];"
+		"stp	q10, q11, [%1, #32];"
+		"stp	q12, q13, [%1, #64];"
+		"stp	q14, q15, [%1, #96];"
+
+		: "=m"(*stash)
+		: "r"(stash));
+}
+
+static inline void arch_efi_unstash_simd_regs(struct efi_simd_reg_stash *stash)
+{
+	asm(	"ldp	q8,  q9,  [%1];"
+		"ldp	q10, q11, [%1, #32];"
+		"ldp	q12, q13, [%1, #64];"
+		"ldp	q14, q15, [%1, #96];"
+
+		:
+		: "m"(*stash), "r"(stash));
+}
+
 #endif /* _ASM_EFI_H */
-- 
2.7.4

^ permalink raw reply related

* [RFC PATCH 2/3] efi/arm: add SIMD stash/unstash operations
From: Ard Biesheuvel @ 2016-09-22 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474543806-19210-1-git-send-email-ard.biesheuvel@linaro.org>

This adds the SIMD stash/unstash operations that we need to allow UEFI
runtime services calls to call back into the kernel. In the ARM case,
these are actually NOPs, since UEFI on ARM is not allowed to use the
FP/NEON register file.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/include/asm/efi.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 766bf9b78160..c71ea8c21d0d 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -83,4 +83,15 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
 #define MIN_ZIMAGE_OFFSET	MAX_UNCOMP_KERNEL_SIZE
 #define MAX_FDT_OFFSET		ZIMAGE_OFFSET_LIMIT
 
+struct efi_simd_reg_stash {
+};
+
+static inline void arch_efi_stash_simd_regs(struct efi_simd_reg_stash *stash)
+{
+}
+
+static inline void arch_efi_unstash_simd_regs(struct efi_simd_reg_stash *stash)
+{
+}
+
 #endif /* _ASM_ARM_EFI_H */
-- 
2.7.4

^ permalink raw reply related

* [RFC PATCH 3/3] efi: implement MMC proxy support for the UEFI variable store
From: Ard Biesheuvel @ 2016-09-22 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474543806-19210-1-git-send-email-ard.biesheuvel@linaro.org>

---
 drivers/firmware/efi/Kconfig     |   9 +
 drivers/firmware/efi/Makefile    |   1 +
 drivers/firmware/efi/arm-init.c  |   2 +
 drivers/firmware/efi/mmc-proxy.c | 222 ++++++++++++++++++++
 include/linux/efi.h              |   1 +
 5 files changed, 235 insertions(+)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index c981be17d3c0..1933e186a9c2 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -129,6 +129,15 @@ config EFI_TEST
 	  Say Y here to enable the runtime services support via /dev/efi_test.
 	  If unsure, say N.
 
+config EFI_MMC_PROXY
+	bool "Expose Embedded MMC host protocol to the firmware"
+	depends on EFI && (ARM || ARM64)
+	help
+	  This driver exposes the MMC host whose DT node is annotated with the
+	  "linux,uefi-varstore" property to the firmware via a UEFI compatible
+	  protocol. This allows the EFI variable store to reside on an MMC
+	  volume that is owned by the OS at runtime.
+
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index c8a439f6d715..88fdf0e13d6b 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -26,3 +26,4 @@ arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
 obj-$(CONFIG_ARM)			+= $(arm-obj-y)
 obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
 obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
+obj-$(CONFIG_EFI_MMC_PROXY)		+= mmc-proxy.o
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 8efe13075c92..7a57253975a5 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -56,9 +56,11 @@ static phys_addr_t efi_to_phys(unsigned long addr)
 }
 
 static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
+unsigned long __initdata mmc_fv_emulation_table = EFI_INVALID_TABLE_ADDR;
 
 static __initdata efi_config_table_type_t arch_tables[] = {
 	{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table},
+	{LINUX_MMC_FV_EMULATION_TABLE_GUID, NULL, &mmc_fv_emulation_table},
 	{NULL_GUID, NULL, NULL}
 };
 
diff --git a/drivers/firmware/efi/mmc-proxy.c b/drivers/firmware/efi/mmc-proxy.c
new file mode 100644
index 000000000000..3702bb2a5af0
--- /dev/null
+++ b/drivers/firmware/efi/mmc-proxy.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <asm/efi.h>
+
+extern unsigned long mmc_fv_emulation_table;
+
+enum emmc_state {
+	mmc_invalid_state = 0,
+	mmc_hw_initialization_state,
+	mmc_idle_state,
+	mmc_ready_state,
+	mmc_identification_state,
+	mmc_standby_state,
+	mmc_transfer_state,
+	mmc_sending_data_state,
+	mmc_receive_data_state,
+	mmc_programming_state,
+	mmc_disconnect_state,
+};
+
+static char const emmc_state_string[][28] = {
+	"mmc_invalid_state",
+	"mmc_hw_initialization_state",
+	"mmc_idle_state",
+	"mmc_ready_state",
+	"mmc_identification_state",
+	"mmc_standby_state",
+	"mmc_transfer_state",
+	"mmc_sending_data_state",
+	"mmc_receive_data_state",
+	"mmc_programming_state",
+	"mmc_disconnect_state",
+};
+
+/*
+ * This MMC host protocol version is not in the UEFI spec, and lives under
+ * EmbeddedPkg/ in Tianocore/EDK2.
+ */
+struct emmc_host_protocol
+{
+	u32		revision;
+	bool		(*is_card_present)(struct emmc_host_protocol*);
+	bool		(*is_read_only)(struct emmc_host_protocol*);
+	efi_status_t	(*build_device_path)(struct emmc_host_protocol*,
+					     void*);
+	efi_status_t	(*notify_state)(struct emmc_host_protocol*,
+					enum emmc_state);
+	efi_status_t	(*send_command)(struct emmc_host_protocol*,
+					u32, u32);
+	efi_status_t	(*receive_response)(struct emmc_host_protocol*,
+					    u32, u32*);
+	efi_status_t	(*read_block_data)(struct emmc_host_protocol*,
+					   u64, unsigned long, u32*);
+	efi_status_t	(*write_block_data)(struct emmc_host_protocol*,
+					    u64, unsigned long, u32*);
+};
+
+static bool mmc_is_card_present(struct emmc_host_protocol *this)
+{
+	return true;
+}
+
+static bool mmc_is_read_only(struct emmc_host_protocol *this)
+{
+	return false;
+}
+
+static efi_status_t mmc_build_device_path(struct emmc_host_protocol *this,
+					  void *dpp)
+{
+	return EFI_UNSUPPORTED;
+}
+
+static efi_status_t mmc_notify_state(struct emmc_host_protocol *this,
+				     enum emmc_state state)
+{
+	struct efi_simd_reg_stash simd_stash;
+
+	arch_efi_stash_simd_regs(&simd_stash);
+	arch_efi_call_virt_teardown();
+
+	pr_warn("mmc-proxy: entered %s state\n", emmc_state_string[state]);
+	might_sleep();
+
+	arch_efi_call_virt_setup();
+	arch_efi_unstash_simd_regs(&simd_stash);
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t mmc_send_command(struct emmc_host_protocol *this, u32 cmd,
+				     u32 arg)
+{
+	struct efi_simd_reg_stash simd_stash;
+
+	arch_efi_stash_simd_regs(&simd_stash);
+	arch_efi_call_virt_teardown();
+
+	pr_warn("mmc-proxy: send command %d (0x%x)\n", cmd, arg);
+	might_sleep();
+
+	arch_efi_call_virt_setup();
+	arch_efi_unstash_simd_regs(&simd_stash);
+	return EFI_NOT_FOUND;
+}
+
+static efi_status_t mmc_receive_response(struct emmc_host_protocol *this,
+					 u32 mmc_response_type, u32 *buffer)
+{
+	struct efi_simd_reg_stash simd_stash;
+	u32 response[4] = {};
+
+	arch_efi_stash_simd_regs(&simd_stash);
+	arch_efi_call_virt_teardown();
+
+	pr_warn("mmc-proxy: receive response %d\n", mmc_response_type);
+	might_sleep();
+
+	arch_efi_call_virt_setup();
+	arch_efi_unstash_simd_regs(&simd_stash);
+	memcpy(buffer, response, sizeof(response));
+
+	return EFI_NOT_FOUND;
+}
+
+static efi_status_t mmc_read_block_data(struct emmc_host_protocol *this,
+					u64 lba, unsigned long len,
+					u32 *buffer)
+{
+	struct efi_simd_reg_stash simd_stash;
+	void *bounce;
+
+	arch_efi_stash_simd_regs(&simd_stash);
+	arch_efi_call_virt_teardown();
+
+	bounce = kmalloc(len, GFP_KERNEL);
+
+	pr_warn("mmc-proxy: read block data lba==%lld, len==%ld\n", lba, len);
+	might_sleep();
+
+	arch_efi_call_virt_setup();
+	arch_efi_unstash_simd_regs(&simd_stash);
+	memcpy(buffer, bounce, len);
+	kfree(bounce);
+
+	return EFI_NOT_FOUND;
+}
+
+static efi_status_t mmc_write_block_data(struct emmc_host_protocol *this,
+					 u64 lba, unsigned long len,
+					 u32 *buffer)
+{
+	struct efi_simd_reg_stash simd_stash;
+	void *bounce;
+
+	/*
+	 * 'buffer' may point to memory that is mapped via the EFI page tables,
+	 * so copy the data before switching back to the ordinary mappings.
+	 */
+	bounce = kmalloc(len, GFP_ATOMIC);
+	if (!bounce)
+		return EFI_OUT_OF_RESOURCES;
+	memcpy(bounce, buffer, len);
+
+	arch_efi_stash_simd_regs(&simd_stash);
+	arch_efi_call_virt_teardown();
+
+	pr_warn("mmc-proxy: write block data lba==%lld, len==%ld\n", lba, len);
+	might_sleep();
+
+	kfree(bounce);
+	arch_efi_call_virt_setup();
+	arch_efi_unstash_simd_regs(&simd_stash);
+	return EFI_NOT_FOUND;
+}
+
+static const struct emmc_host_protocol emmc_proxy =
+{
+	0x00010001,		// revision 1.1
+	mmc_is_card_present,
+	mmc_is_read_only,
+	mmc_build_device_path,
+	mmc_notify_state,
+	mmc_send_command,
+	mmc_receive_response,
+	mmc_read_block_data,
+	mmc_write_block_data
+};
+
+static int __init emmc_proxy_install(void)
+{
+	unsigned long *p;
+
+	if (mmc_fv_emulation_table == EFI_INVALID_TABLE_ADDR)
+		return 0;
+
+	p = memremap(mmc_fv_emulation_table, sizeof(*p), MEMREMAP_WB);
+	if (!p)
+		return -ENOMEM;
+
+	/*
+	 * We expect a NULL value here, since the firmware should have cleared
+	 * this value in its ExitBootServices() handler.
+	 */
+	if (!WARN_ON(*p != 0))
+		*p = (unsigned long)&emmc_proxy;
+
+	memunmap(p);
+	return 0;
+}
+late_initcall(emmc_proxy_install);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2d089487d2da..25a4ae648b6f 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -599,6 +599,7 @@ void efi_native_runtime_setup(void);
  */
 #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID	EFI_GUID(0xe03fc20a, 0x85dc, 0x406e,  0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
 #define LINUX_EFI_LOADER_ENTRY_GUID		EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
+#define LINUX_MMC_FV_EMULATION_TABLE_GUID	EFI_GUID(0x44cd9912, 0xfda8, 0x4b7d,  0xa6, 0x13, 0x1b, 0x61, 0x34, 0xfc, 0xdc, 0x4a)
 
 typedef struct {
 	efi_guid_t guid;
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
From: Gabriele Paoloni @ 2016-09-22 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3538381.vOsx75UXVU@wuerfel>

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 21 September 2016 21:18
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > From: zhichang [mailto:zhichang.yuan02 at gmail.com]
> > > On 2016?09?15? 20:24, Arnd Bergmann wrote:
> > > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > > wrote:
> > > >>> -----Original Message-----
> > > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele
> Paoloni
> > > wrote:
> > > >> I think that maybe having the 1:1 range mapping doesn't
> > > >> reflect well the reality but it is the less painful
> > > >> solution...
> > > >>
> > > >> What's your view?
> > > >
> > > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > > and that should be enough to translate the I/O port number.
> > > >
> > > > The only part we need to change here is to not go through
> > > > the crazy conversion all the way from PCI I/O space to a
> > > > physical address and back to a (logical) port number
> > > > that we do today with of_translate_address/pci_address_to_pio.
> > > >
> > > Sorry for the late response! Several days' leave....
> > > Do you want to bypass of_translate_address and pci_address_to_pio
> for
> > > the registered specific PIO?
> > > I think the bypass for of_translate_address is ok, but worry some
> new
> > > issues will emerge without the
> > > conversion between physical address and logical/linux port number.
> 
> The same function that handles the non-translated region would
> do that conversion.
> 
> > > When PCI host bridge which support IO operations is configured and
> > > enabled, the pci_address_to_pio will
> > > populate the logical IO range from ZERO for the first host bridge.
> Our
> > > LPC will also use part of the IO range
> > > started from ZERO. It will make in/out enter the wrong branch
> possibly.
> > >
> > > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use
> only.
> > > But it seems not so good. In this way,
> > > PCI has no chance to use low 4K IO range(logical).
> > >
> > > So, in V3, applying the conversion from physical/cpu address to
> > > logical/linux IO port for any IO ranges,
> > > including the LPC, but recorded the logical IO range for LPC. When
> > > calling in/out with a logical port address,
> > > we can check this port fall into LPC logical IO range and get back
> the
> > > real IO.
> 
> Right, and the same translation can be used in
> __of_address_to_resource()
> going the opposite way.
> 
> > > Do you have further comments about this??
> >
> > I think there are two separate issues to be discussed:
> >
> > The first issue is about having of_translate_address failing due to
> > "range" missing. About this Arnd suggested that it is not appropriate
> > to have a range describing a bridge 1:1 mapping and this was
> discussed
> > before in this thread. Arnd had a suggestion about this (see below)
> > however (looking twice at the code) it seems to me that such solution
> > would lead to quite some duplication from __of_translate_address()
> > in order to retrieve the actual addr from dt...
> 
> I don't think we need to duplicate much, we can probably safely
> assume that there are no nontrivial ranges in devices below the LPC
> node, so we just walk up the bus to see if the node is a child
> (or possibly grandchild etc) of the LPC bus, and treat any IO port
> number under there as a physical port number, which has a known
> offset from the Linux I/O port number.
> 
> > I think extending of_empty_ranges_quirk() may be a reasonable
> solution.
> > What do you think Arnd?
> 
> I don't really like that idea, that quirk is meant to work around
> broken DTs, but we can just make the DT valid and implement the
> code properly.

Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
As a quirk is used to work around broken HW or broken FW (as in this case)
rather than to fix code

What about the following? I think adding the check you suggested next to
of_empty_ranges_quirk() is adding the case we need in the right point (thus
avoiding any duplication)
 
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
        return NULL;
 }
 
+static inline int of_isa_indirect_io(struct device_node *np)
+{
+       /*
+        * check if the current node is an isa bus and if indirectio operation
+        * are registered
+        */
+       return (of_bus_isa_match(np) && arm64_extio_ops);
+}
+
 static int of_empty_ranges_quirk(struct device_node *np)
 {
        if (IS_ENABLED(CONFIG_PPC)) {
@@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * This code is only enabled on powerpc. --gcl
         */
        ranges = of_get_property(parent, rprop, &rlen);
-       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
                pr_debug("OF: no ranges; cannot translate\n");
                return 1;
        }


> 
> > The second issue is a conflict between cpu addresses used by the LPC
> > controller and i/o tokens from pci endpoints.
> >
> > About this what if we modify armn64_extio_ops to have a list of
> ranges
> > rather than only one range (now we have just start/end); then in the
> > LPC driver we can scan the LPC child devices and
> > 1) populate such list of ranges
> > 2) call pci_register_io_range for such ranges
> 
> Scanning the child devices sounds really wrong, please register just
> one range that covers the bus to keep the workaround as simple
> as possible.
> 
> > Then when calling __of_address_to_resource we retrieve I/O tokens
> > for the devices on top of the LPC driver and in the I/O accessors
> > we call pci_pio_to_address to figure out the cpu address and compare
> > it to the list of ranges in armn64_extio_ops.
> >
> > What about this?
> 
> That seems really complex for something that can be quite simple.
> The only thing we need to worry about is that the io_range_list
> contains an entry for the LPC bus so we don't conflict with the
> PCI buses.

Thanks

I discussed with Zhichang and we agreed to use only one LPC range
to be registered with pci_register_io_range.

We'll rework the accessors to check if the retrieved I/O tokens
belong to LPC or PCI IO range...

Cheers

Gab


> 
> 	Arnd
> 
> 	Arnd

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox