Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/6] arm_pmu: Change API to support 64bit counter values
From: Suzuki K Poulose @ 2018-05-22  9:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201805220546.ySDTMDEX%fengguang.wu@intel.com>

On 22/05/18 00:30, kbuild test robot wrote:
> Hi Suzuki,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on tip/perf/core]
> [also build test ERROR on v4.17-rc6 next-20180517]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Suzuki-K-Poulose/arm64-perf-Support-for-chaining-event-counters/20180521-102117
> config: arm-corgi_defconfig (attached as .config)
> compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
> reproduce:
>          wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>          chmod +x ~/bin/make.cross
>          # save the attached .config to linux build tree
>          make.cross ARCH=arm
> 
> All errors (new ones prefixed by >>):
> 
>     arch/arm/kernel/perf_event_xscale.c: In function 'xscale2pmu_init':
>>> arch/arm/kernel/perf_event_xscale.c:741:24: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
>       cpu_pmu->read_counter = xscale2pmu_read_counter;
>                             ^
>     arch/arm/kernel/perf_event_xscale.c:742:25: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
>       cpu_pmu->write_counter = xscale2pmu_write_counter;
>                              ^
>     cc1: some warnings being treated as errors


Thanks for the report, I have fixed this for the next version.

Suzuki

^ permalink raw reply

* [PATCH 1/2] drm/fourcc: add a 10bits fully packed variant of NV12
From: Randy Li @ 2018-05-22  9:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <303c89b8-e24f-cacb-c305-65d17c58c597@linux.intel.com>



On 05/22/2018 05:26 PM, Maarten Lankhorst wrote:
> Op 20-05-18 om 19:17 schreef Randy Li:
>> This pixel format is a fully packed and 10bits variant of NV12.
>> A luma pixel would take 10bits in memory, without any
>> filled bits between pixels in a stride. The color gamut
>> follows the BT.2020 standard.
>>
>> Signed-off-by: Randy Li <ayaka@soulik.info>
>> ---
>>   drivers/gpu/drm/drm_fourcc.c  | 1 +
>>   include/uapi/drm/drm_fourcc.h | 3 +++
>>   2 files changed, 4 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
>> index 5ca6395cd4d3..1f43967c4013 100644
>> --- a/drivers/gpu/drm/drm_fourcc.c
>> +++ b/drivers/gpu/drm/drm_fourcc.c
>> @@ -173,6 +173,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
>>   		{ .format = DRM_FORMAT_UYVY,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
>>   		{ .format = DRM_FORMAT_VYUY,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
>>   		{ .format = DRM_FORMAT_AYUV,		.depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
>> +		{ .format = DRM_FORMAT_NV12_10LE40,	.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
> Hm, the cpp value might give problems because it rounds down, not sure how we should handle that? Set to zero?
It is default behavior that using the filed "cpp"? to calculate the 
pixel in many drivers. I would suggest use a new filed called bits per 
pixel (bpp) instead of the old cpp.
The one used in the Gstreamer is more complex: 
https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-GstVideoAlignment.html#GstVideoFormatInfo
As the struct drm_format_info only a kernel internal data structure, it 
doesn't need to update the user-space interface like libdrm.
>>   	};
>>   
>>   	unsigned int i;
>> diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
>> index e04613d30a13..8eabf01e966f 100644
>> --- a/include/uapi/drm/drm_fourcc.h
>> +++ b/include/uapi/drm/drm_fourcc.h
>> @@ -140,6 +140,9 @@ extern "C" {
>>   #define DRM_FORMAT_NV61		fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
>>   #define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
>>   #define DRM_FORMAT_NV42		fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
>> +/* A fully packed variant of NV12_10LE32 */
>> +#define DRM_FORMAT_NV12_10LE40	fourcc_code('R', 'K', '2', '0') /* 2x2 subsampled Cr:Cb plane */
>> +
>>   
>>   /*
>>    * 3 plane YCbCr
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH] arm64: dts: renesas: r8a77980: add SMP support
From: Geert Uytterhoeven @ 2018-05-22  9:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522085430.eqhan4njajnp5hkk@verge.net.au>

On Tue, May 22, 2018 at 10:54 AM, Simon Horman <horms@verge.net.au> wrote:
> On Sat, May 19, 2018 at 08:38:13PM +0300, Sergei Shtylyov wrote:
>> On 05/17/2018 11:23 PM, Geert Uytterhoeven wrote:
>>
>> >> Add the device nodes for 3 more Cortex-A53 CPU cores; adjust the interrupt
>> >> delivery masks for the ARM GIC and Architectured Timer.
>> >>
>> >> Based on the original (and large) patch by Vladimir Barinov.
>> >>
>> >> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
>> >> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>> >
>> > Thanks for your patch!
>> >
>> >> --- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980.dtsi
>> >> +++ renesas/arch/arm64/boot/dts/renesas/r8a77980.dtsi
>> >> @@ -30,6 +30,36 @@
>> >>                         enable-method = "psci";
>> >>                 };
>> >>
>> >> +               a53_1: cpu at 1 {
>> >> +                       device_type = "cpu";
>> >> +                       compatible = "arm,cortex-a53","arm,armv8";
>> >
>> > Please stop copying spaceless lists ;-)
>>
>>    Oops! Simon, do I need to re-post?
>
> No, but Geert, are you otherwise ok with this patch?

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Leo Yan @ 2018-05-22  9:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522083920.GD31075@leoy-ThinkPad-X240s>

On Tue, May 22, 2018 at 04:39:20PM +0800, Leo Yan wrote:

[...]

Rather than the patch I posted in my previous email, I think below new
patch is more reasonable for me.

In the below change, 'etmq->prev_packet' is only used to store the
previous CS_ETM_RANGE packet, we don't need to save CS_ETM_TRACE_ON
packet into 'etmq->prev_packet'.

On the other hand, cs_etm__flush() can use 'etmq->period_instructions'
to indicate if need to generate instruction sample or not.  If it's
non-zero, then generate instruction sample and
'etmq->period_instructions' will be cleared; so next time if there
have more tracing CS_ETM_TRACE_ON packet, it can skip to generate
instruction sample due 'etmq->period_instructions' is zero.

How about you think for this?

Thanks,
Leo Yan


diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 822ba91..dd354ad 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -495,6 +495,13 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
 static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
 {
 	/*
+	 * The packet is the start tracing packet if the end_addr is zero,
+	 * returns 0 for this case.
+	 */
+	if (!packet->end_addr)
+		return 0;
+
+	/*
 	 * The packet records the execution range with an exclusive end address
 	 *
 	 * A64 instructions are constant size, so the last executed
@@ -897,13 +904,27 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 		etmq->period_instructions = instrs_over;
 	}
 
-	if (etm->sample_branches &&
-	    etmq->prev_packet &&
-	    etmq->prev_packet->sample_type == CS_ETM_RANGE &&
-	    etmq->prev_packet->last_instr_taken_branch) {
-		ret = cs_etm__synth_branch_sample(etmq);
-		if (ret)
-			return ret;
+	if (etm->sample_branches && etmq->prev_packet) {
+		bool generate_sample = false;
+
+		/* Generate sample for start tracing packet */
+		if (etmq->prev_packet->sample_type == 0)
+			generate_sample = true;
+
+		/* Generate sample for exception packet */
+		if (etmq->prev_packet->exc == true)
+			generate_sample = true;
+
+		/* Generate sample for normal branch packet */
+		if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
+		    etmq->prev_packet->last_instr_taken_branch)
+			generate_sample = true;
+
+		if (generate_sample) {
+			ret = cs_etm__synth_branch_sample(etmq);
+			if (ret)
+				return ret;
+		}
 	}
 
 	if (etm->sample_branches || etm->synth_opts.last_branch) {
@@ -922,11 +943,12 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 static int cs_etm__flush(struct cs_etm_queue *etmq)
 {
 	int err = 0;
-	struct cs_etm_packet *tmp;
 
 	if (etmq->etm->synth_opts.last_branch &&
 	    etmq->prev_packet &&
-	    etmq->prev_packet->sample_type == CS_ETM_RANGE) {
+	    etmq->prev_packet->sample_type == CS_ETM_RANGE &&
+	    etmq->period_instructions) {
+
 		/*
 		 * Generate a last branch event for the branches left in the
 		 * circular buffer at the end of the trace.
@@ -940,14 +962,6 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 			etmq, addr,
 			etmq->period_instructions);
 		etmq->period_instructions = 0;
-
-		/*
-		 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
-		 * the next incoming packet.
-		 */
-		tmp = etmq->packet;
-		etmq->packet = etmq->prev_packet;
-		etmq->prev_packet = tmp;
 	}
 
 	return err;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 06/14] ARM: spectre-v2: harden branch predictor on context switches
From: Russell King - ARM Linux @ 2018-05-22  9:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <61e24c59-9905-8524-92ba-98cdbadb3011@gmail.com>

On Mon, May 21, 2018 at 08:21:58PM -0700, Florian Fainelli wrote:
> 
> 
> On 05/21/2018 04:44 AM, Russell King wrote:
> > Harden the branch predictor against Spectre v2 attacks on context
> > switches for ARMv7 and later CPUs.  We do this by:
> > 
> > Cortex A9, A12, A17, A73, A75: invalidating the BTB.
> > Cortex A15, Brahma B15: invalidating the instruction cache.
> > 
> > Cortex A57 and Cortex A72 are not addressed in this patch.
> > 
> > Cortex R7 and Cortex R8 are also not addressed as we do not enforce
> > memory protection on these cores.
> > 
> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> 
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

It does need this additional patch to avoid some build errors - I'm
surprised that my autobuilder found it before the 0-day builder...

diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index 0c37e6a2830d..526d07ab6b7a 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -127,4 +127,8 @@ void cpu_v7_bugs_init(void)
 		pr_info("CPU: Spectre v2: using %s workaround\n",
 			spectre_v2_method);
 }
+#else
+void cpu_v7_bugs_init(void)
+{
+}
 #endif


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply related

* [PATCH v1] dma: imx-sdma: add virt-dma support
From: Sascha Hauer @ 2018-05-22 10:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1521735499-29138-1-git-send-email-yibin.gong@nxp.com>

Hi Robin,

Several comments inside.

Sascha

On Fri, Mar 23, 2018 at 12:18:19AM +0800, Robin Gong wrote:
> The legacy sdma driver has below limitations or drawbacks:
>   1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
>      one page size for one channel regardless of only few BDs needed
>      most time. But in few cases, the max PAGE_SIZE maybe not enough.
>   2. One SDMA channel can't stop immediatley once channel disabled which
>      means SDMA interrupt may come in after this channel terminated.There
>      are some patches for this corner case such as commit "2746e2c389f9",
>      but not cover non-cyclic.
> 
> The common virt-dma overcomes the above limitations. It can alloc bd
> dynamically and free bd once this tx transfer done. No memory wasted or
> maximum limititation here, only depends on how many memory can be requested
> from kernel. For No.2, such issue can be workaround by checking if there
> is available descript("sdmac->desc") now once the unwanted interrupt
> coming. At last the common virt-dma is easier for sdma driver maintain.
> 
> Signed-off-by: Robin Gong <yibin.gong@nxp.com>
> ---
>  drivers/dma/Kconfig    |   1 +
>  drivers/dma/imx-sdma.c | 395 +++++++++++++++++++++++++++++++------------------
>  2 files changed, 253 insertions(+), 143 deletions(-)
> 
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 27df3e2..c4ce43c 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -247,6 +247,7 @@ config IMX_SDMA
>  	tristate "i.MX SDMA support"
>  	depends on ARCH_MXC
>  	select DMA_ENGINE
> +	select DMA_VIRTUAL_CHANNELS
>  	help
>  	  Support the i.MX SDMA engine. This engine is integrated into
>  	  Freescale i.MX25/31/35/51/53/6 chips.
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index ccd03c3..df79e73 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -48,6 +48,7 @@
>  #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
>  
>  #include "dmaengine.h"
> +#include "virt-dma.h"
>  
>  /* SDMA registers */
>  #define SDMA_H_C0PTR		0x000
> @@ -291,10 +292,19 @@ struct sdma_context_data {
>  	u32  scratch7;
>  } __attribute__ ((packed));
>  
> -#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
> -
>  struct sdma_engine;
>  
> +struct sdma_desc {
> +	struct virt_dma_desc	vd;
> +	struct list_head	node;
> +	unsigned int		num_bd;
> +	dma_addr_t		bd_phys;
> +	unsigned int		buf_tail;
> +	unsigned int		buf_ptail;
> +	struct sdma_channel	*sdmac;
> +	struct sdma_buffer_descriptor *bd;
> +};
> +
>  /**
>   * struct sdma_channel - housekeeping for a SDMA channel
>   *
> @@ -310,19 +320,17 @@ struct sdma_engine;
>   * @num_bd		max NUM_BD. number of descriptors currently handling
>   */
>  struct sdma_channel {
> +	struct virt_dma_chan		vc;
> +	struct list_head		pending;
>  	struct sdma_engine		*sdma;
> +	struct sdma_desc		*desc;
>  	unsigned int			channel;
>  	enum dma_transfer_direction		direction;
>  	enum sdma_peripheral_type	peripheral_type;
>  	unsigned int			event_id0;
>  	unsigned int			event_id1;
>  	enum dma_slave_buswidth		word_size;
> -	unsigned int			buf_tail;
> -	unsigned int			buf_ptail;
> -	unsigned int			num_bd;
>  	unsigned int			period_len;
> -	struct sdma_buffer_descriptor	*bd;
> -	dma_addr_t			bd_phys;
>  	unsigned int			pc_from_device, pc_to_device;
>  	unsigned int			device_to_device;
>  	unsigned long			flags;
> @@ -330,15 +338,12 @@ struct sdma_channel {
>  	unsigned long			event_mask[2];
>  	unsigned long			watermark_level;
>  	u32				shp_addr, per_addr;
> -	struct dma_chan			chan;
> -	spinlock_t			lock;
> -	struct dma_async_tx_descriptor	desc;
>  	enum dma_status			status;
>  	unsigned int			chn_count;
>  	unsigned int			chn_real_count;
> -	struct tasklet_struct		tasklet;
>  	struct imx_dma_data		data;
>  	bool				enabled;

Usage of this variable is removed in this patch, but not the variable
itself.

> +	u32				bd_size_sum;

This variable is never used for anything.

>  };
>  
>  #define IMX_DMA_SG_LOOP		BIT(0)
> @@ -398,6 +403,9 @@ struct sdma_engine {
>  	u32				spba_start_addr;
>  	u32				spba_end_addr;
>  	unsigned int			irq;
> +	/* channel0 bd */
> +	dma_addr_t			bd0_phys;
> +	struct sdma_buffer_descriptor	*bd0;
>  };
>  
>  static struct sdma_driver_data sdma_imx31 = {
> @@ -553,6 +561,8 @@ MODULE_DEVICE_TABLE(of, sdma_dt_ids);
>  #define SDMA_H_CONFIG_ACR	BIT(4)  /* indicates if AHB freq /core freq = 2 or 1 */
>  #define SDMA_H_CONFIG_CSM	(3)       /* indicates which context switch mode is selected*/
>  
> +static void sdma_start_desc(struct sdma_channel *sdmac);
> +
>  static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
>  {
>  	u32 chnenbl0 = sdma->drvdata->chnenbl0;
> @@ -597,14 +607,7 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
>  
>  static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
>  {
> -	unsigned long flags;
> -	struct sdma_channel *sdmac = &sdma->channel[channel];
> -
>  	writel(BIT(channel), sdma->regs + SDMA_H_START);
> -
> -	spin_lock_irqsave(&sdmac->lock, flags);
> -	sdmac->enabled = true;
> -	spin_unlock_irqrestore(&sdmac->lock, flags);
>  }
>  
>  /*
> @@ -632,7 +635,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
>  static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
>  		u32 address)
>  {
> -	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
> +	struct sdma_buffer_descriptor *bd0 = sdma->bd0;

This change seems to be an orthogonal change. Please make this a
separate patch.

>  	void *buf_virt;
>  	dma_addr_t buf_phys;
>  	int ret;
> @@ -691,23 +694,16 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
>  static void sdma_update_channel_loop(struct sdma_channel *sdmac)
>  {
>  	struct sdma_buffer_descriptor *bd;
> +	struct sdma_desc *desc = sdmac->desc;
>  	int error = 0;
>  	enum dma_status	old_status = sdmac->status;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&sdmac->lock, flags);
> -	if (!sdmac->enabled) {
> -		spin_unlock_irqrestore(&sdmac->lock, flags);
> -		return;
> -	}
> -	spin_unlock_irqrestore(&sdmac->lock, flags);
>  
>  	/*
>  	 * loop mode. Iterate over descriptors, re-setup them and
>  	 * call callback function.
>  	 */
> -	while (1) {
> -		bd = &sdmac->bd[sdmac->buf_tail];
> +	while (desc) {

'desc' seems to be used as a loop counter here, but this variable is
never assigned another value, so I assume it's just another way to say
"skip the loop if desc is NULL". When 'desc' NULL you won't get into
this function at all though, so this check for desc seems rather pointless.

> +		bd = &desc->bd[desc->buf_tail];
>  
>  		if (bd->mode.status & BD_DONE)
>  			break;
> @@ -726,8 +722,8 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
>  		sdmac->chn_real_count = bd->mode.count;
>  		bd->mode.status |= BD_DONE;
>  		bd->mode.count = sdmac->period_len;
> -		sdmac->buf_ptail = sdmac->buf_tail;
> -		sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
> +		desc->buf_ptail = desc->buf_tail;
> +		desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
>  
>  		/*
>  		 * The callback is called from the interrupt context in order
> @@ -735,15 +731,16 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
>  		 * SDMA transaction status by the time the client tasklet is
>  		 * executed.
>  		 */
> -
> -		dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
> +		spin_unlock(&sdmac->vc.lock);
> +		dmaengine_desc_get_callback_invoke(&desc->vd.tx, NULL);
> +		spin_lock(&sdmac->vc.lock);
>  
>  		if (error)
>  			sdmac->status = old_status;
>  	}
>  }
>  
> -static void mxc_sdma_handle_channel_normal(unsigned long data)
> +static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)
>  {
>  	struct sdma_channel *sdmac = (struct sdma_channel *) data;
>  	struct sdma_buffer_descriptor *bd;
> @@ -754,8 +751,8 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
>  	 * non loop mode. Iterate over all descriptors, collect
>  	 * errors and call callback function
>  	 */
> -	for (i = 0; i < sdmac->num_bd; i++) {
> -		bd = &sdmac->bd[i];
> +	for (i = 0; i < sdmac->desc->num_bd; i++) {
> +		bd = &sdmac->desc->bd[i];
>  
>  		 if (bd->mode.status & (BD_DONE | BD_RROR))
>  			error = -EIO;
> @@ -766,10 +763,6 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
>  		sdmac->status = DMA_ERROR;
>  	else
>  		sdmac->status = DMA_COMPLETE;
> -
> -	dma_cookie_complete(&sdmac->desc);
> -
> -	dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
>  }
>  
>  static irqreturn_t sdma_int_handler(int irq, void *dev_id)
> @@ -785,13 +778,24 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
>  	while (stat) {
>  		int channel = fls(stat) - 1;
>  		struct sdma_channel *sdmac = &sdma->channel[channel];
> -
> -		if (sdmac->flags & IMX_DMA_SG_LOOP)
> -			sdma_update_channel_loop(sdmac);
> -		else
> -			tasklet_schedule(&sdmac->tasklet);
> +		struct sdma_desc *desc;
> +
> +		spin_lock(&sdmac->vc.lock);
> +		desc = sdmac->desc;
> +		if (desc) {
> +			if (sdmac->flags & IMX_DMA_SG_LOOP) {
> +				sdma_update_channel_loop(sdmac);
> +			} else {
> +				mxc_sdma_handle_channel_normal(sdmac);
> +				vchan_cookie_complete(&desc->vd);
> +				if (!list_empty(&sdmac->pending))
> +					list_del(&desc->node);

What does this list_empty check protect you from? It looks like when the
list really is empty then it's a bug in your internal driver logic.

> +				 sdma_start_desc(sdmac);

Whitespace damage here.

> +			}
> +		}
>  
>  		__clear_bit(channel, &stat);
> +		spin_unlock(&sdmac->vc.lock);
>  	}
>  
>  	return IRQ_HANDLED;
> @@ -897,7 +901,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
>  	int channel = sdmac->channel;
>  	int load_address;
>  	struct sdma_context_data *context = sdma->context;
> -	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
> +	struct sdma_buffer_descriptor *bd0 = sdma->bd0;
>  	int ret;
>  	unsigned long flags;
>  
> @@ -946,7 +950,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
>  
>  static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
>  {
> -	return container_of(chan, struct sdma_channel, chan);
> +	return container_of(chan, struct sdma_channel, vc.chan);
>  }
>  
>  static int sdma_disable_channel(struct dma_chan *chan)
> @@ -954,15 +958,10 @@ static int sdma_disable_channel(struct dma_chan *chan)
>  	struct sdma_channel *sdmac = to_sdma_chan(chan);
>  	struct sdma_engine *sdma = sdmac->sdma;
>  	int channel = sdmac->channel;
> -	unsigned long flags;
>  
>  	writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
>  	sdmac->status = DMA_ERROR;
>  
> -	spin_lock_irqsave(&sdmac->lock, flags);
> -	sdmac->enabled = false;
> -	spin_unlock_irqrestore(&sdmac->lock, flags);
> -
>  	return 0;
>  }
>  
> @@ -1097,42 +1096,101 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
>  	return 0;
>  }
>  
> -static int sdma_request_channel(struct sdma_channel *sdmac)
> +static int sdma_alloc_bd(struct sdma_desc *desc)
>  {
> -	struct sdma_engine *sdma = sdmac->sdma;
> -	int channel = sdmac->channel;
> -	int ret = -EBUSY;
> +	u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
> +	int ret = 0;
> +	unsigned long flags;
>  
> -	sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
> +	desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
>  					GFP_KERNEL);
> -	if (!sdmac->bd) {
> +	if (!desc->bd) {
>  		ret = -ENOMEM;
>  		goto out;
>  	}
>  
> -	sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
> -	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
> +	spin_lock_irqsave(&desc->sdmac->vc.lock, flags);
> +	desc->sdmac->bd_size_sum += bd_size;
> +	spin_unlock_irqrestore(&desc->sdmac->vc.lock, flags);
>  
> -	sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
> -	return 0;
>  out:
> -
>  	return ret;
>  }
>  
> -static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
> +static void sdma_free_bd(struct sdma_desc *desc)
>  {
> +	u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
>  	unsigned long flags;
> -	struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
> -	dma_cookie_t cookie;
>  
> -	spin_lock_irqsave(&sdmac->lock, flags);
> +	if (desc->bd) {
> +		dma_free_coherent(NULL, bd_size, desc->bd, desc->bd_phys);
> +
> +		spin_lock_irqsave(&desc->sdmac->vc.lock, flags);
> +		desc->sdmac->bd_size_sum -= bd_size;
> +		spin_unlock_irqrestore(&desc->sdmac->vc.lock, flags);
> +	}
> +}
> +
> +static int sdma_request_channel0(struct sdma_engine *sdma)
> +{
> +	int ret = 0;
> +
> +	sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
> +					GFP_KERNEL);
> +	if (!sdma->bd0) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
>  
> -	cookie = dma_cookie_assign(tx);
> +	sdma->channel_control[0].base_bd_ptr = sdma->bd0_phys;
> +	sdma->channel_control[0].current_bd_ptr = sdma->bd0_phys;
>  
> -	spin_unlock_irqrestore(&sdmac->lock, flags);
> +	sdma_set_channel_priority(&sdma->channel[0], MXC_SDMA_DEFAULT_PRIORITY);
> +out:
>  
> -	return cookie;
> +	return ret;
> +}
> +
> +static struct sdma_desc *to_sdma_desc(struct dma_async_tx_descriptor *t)
> +{
> +	return container_of(t, struct sdma_desc, vd.tx);
> +}
> +
> +static void sdma_desc_free(struct virt_dma_desc *vd)
> +{
> +	struct sdma_desc *desc = container_of(vd, struct sdma_desc, vd);
> +
> +	if (desc) {

Depending on the position of 'vd' in struct sdma_desc 'desc' will always
be non-NULL, even if 'vd' is NULL.

I think this test is unnecessary since this function should never be
called with an invalid pointer. If it is, then the caller really
deserved the resulting crash.

> +		sdma_free_bd(desc);
> +		kfree(desc);
> +	}
> +}
> +
> +static int sdma_terminate_all(struct dma_chan *chan)
> +{
> +	struct sdma_channel *sdmac = to_sdma_chan(chan);
> +	unsigned long flags;
> +	LIST_HEAD(head);
> +
> +	spin_lock_irqsave(&sdmac->vc.lock, flags);
> +	vchan_get_all_descriptors(&sdmac->vc, &head);
> +	while (!list_empty(&sdmac->pending)) {
> +		struct sdma_desc *desc = list_first_entry(&sdmac->pending,
> +			struct sdma_desc, node);
> +
> +		 list_del(&desc->node);
> +		 spin_unlock_irqrestore(&sdmac->vc.lock, flags);
> +		 sdmac->vc.desc_free(&desc->vd);
> +		 spin_lock_irqsave(&sdmac->vc.lock, flags);
> +	}

list_for_each_entry_safe?

> +
> +	if (sdmac->desc)
> +		sdmac->desc = NULL;

The test is unnecesary.

> +	spin_unlock_irqrestore(&sdmac->vc.lock, flags);
> +	vchan_dma_desc_free_list(&sdmac->vc, &head);
> +	sdma_disable_channel_with_delay(chan);
> +
> +	return 0;
>  }
>  
>  static int sdma_alloc_chan_resources(struct dma_chan *chan)
> @@ -1168,18 +1226,11 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
>  	if (ret)
>  		goto disable_clk_ipg;
>  
> -	ret = sdma_request_channel(sdmac);
> -	if (ret)
> -		goto disable_clk_ahb;
> -
>  	ret = sdma_set_channel_priority(sdmac, prio);
>  	if (ret)
>  		goto disable_clk_ahb;
>  
> -	dma_async_tx_descriptor_init(&sdmac->desc, chan);
> -	sdmac->desc.tx_submit = sdma_tx_submit;
> -	/* txd.flags will be overwritten in prep funcs */
> -	sdmac->desc.flags = DMA_CTRL_ACK;
> +	sdmac->bd_size_sum = 0;
>  
>  	return 0;
>  
> @@ -1195,7 +1246,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
>  	struct sdma_channel *sdmac = to_sdma_chan(chan);
>  	struct sdma_engine *sdma = sdmac->sdma;
>  
> -	sdma_disable_channel(chan);
> +	sdma_terminate_all(chan);
>  
>  	if (sdmac->event_id0)
>  		sdma_event_disable(sdmac, sdmac->event_id0);
> @@ -1207,12 +1258,43 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
>  
>  	sdma_set_channel_priority(sdmac, 0);
>  
> -	dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
> -
>  	clk_disable(sdma->clk_ipg);
>  	clk_disable(sdma->clk_ahb);
>  }
>  
> +static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
> +				enum dma_transfer_direction direction, u32 bds)
> +{
> +	struct sdma_desc *desc;
> +
> +	desc = kzalloc((sizeof(*desc)), GFP_KERNEL);
> +	if (!desc)
> +		goto err_out;
> +
> +	sdmac->status = DMA_IN_PROGRESS;
> +	sdmac->direction = direction;
> +	sdmac->flags = 0;
> +	sdmac->chn_count = 0;
> +	sdmac->chn_real_count = 0;
> +
> +	desc->sdmac = sdmac;
> +	desc->num_bd = bds;
> +	INIT_LIST_HEAD(&desc->node);
> +
> +	if (sdma_alloc_bd(desc))
> +		goto err_desc_out;
> +
> +	if (sdma_load_context(sdmac))
> +		goto err_desc_out;
> +
> +	return desc;
> +
> +err_desc_out:
> +	kfree(desc);
> +err_out:
> +	return NULL;
> +}
> +
>  static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
>  		struct dma_chan *chan, struct scatterlist *sgl,
>  		unsigned int sg_len, enum dma_transfer_direction direction,
> @@ -1223,35 +1305,24 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
>  	int ret, i, count;
>  	int channel = sdmac->channel;
>  	struct scatterlist *sg;
> +	struct sdma_desc *desc;
>  
> -	if (sdmac->status == DMA_IN_PROGRESS)
> +	if (!chan)
>  		return NULL;
> -	sdmac->status = DMA_IN_PROGRESS;
> -
> -	sdmac->flags = 0;
>  
> -	sdmac->buf_tail = 0;
> -	sdmac->buf_ptail = 0;
> -	sdmac->chn_real_count = 0;
> +	desc = sdma_transfer_init(sdmac, direction, sg_len);
> +	if (!desc)
> +		goto err_out;
>  
>  	dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
>  			sg_len, channel);
>  
> -	sdmac->direction = direction;
>  	ret = sdma_load_context(sdmac);
>  	if (ret)
>  		goto err_out;
>  
> -	if (sg_len > NUM_BD) {
> -		dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
> -				channel, sg_len, NUM_BD);
> -		ret = -EINVAL;
> -		goto err_out;
> -	}
> -
> -	sdmac->chn_count = 0;
>  	for_each_sg(sgl, sg, sg_len, i) {
> -		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
> +		struct sdma_buffer_descriptor *bd = &desc->bd[i];
>  		int param;
>  
>  		bd->buffer_addr = sg->dma_address;
> @@ -1262,7 +1333,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
>  			dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
>  					channel, count, 0xffff);
>  			ret = -EINVAL;
> -			goto err_out;
> +			goto err_bd_out;
>  		}
>  
>  		bd->mode.count = count;
> @@ -1307,10 +1378,11 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
>  		bd->mode.status = param;
>  	}
>  
> -	sdmac->num_bd = sg_len;
> -	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
> +	return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
>  
> -	return &sdmac->desc;
> +err_bd_out:
> +	sdma_free_bd(desc);
> +	kfree(desc);
>  err_out:
>  	sdmac->status = DMA_ERROR;
>  	return NULL;
> @@ -1326,39 +1398,32 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
>  	int num_periods = buf_len / period_len;
>  	int channel = sdmac->channel;
>  	int ret, i = 0, buf = 0;
> +	struct sdma_desc *desc;
>  
>  	dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
>  
> -	if (sdmac->status == DMA_IN_PROGRESS)
> -		return NULL;
> -
> -	sdmac->status = DMA_IN_PROGRESS;
> +	/* Now allocate and setup the descriptor. */
> +	desc = sdma_transfer_init(sdmac, direction, num_periods);
> +	if (!desc)
> +		goto err_out;
>  
> -	sdmac->buf_tail = 0;
> -	sdmac->buf_ptail = 0;
> -	sdmac->chn_real_count = 0;
> +	desc->buf_tail = 0;
> +	desc->buf_ptail = 0;
>  	sdmac->period_len = period_len;
> -
>  	sdmac->flags |= IMX_DMA_SG_LOOP;
> -	sdmac->direction = direction;
> +
>  	ret = sdma_load_context(sdmac);
>  	if (ret)
>  		goto err_out;
>  
> -	if (num_periods > NUM_BD) {
> -		dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
> -				channel, num_periods, NUM_BD);
> -		goto err_out;
> -	}
> -
>  	if (period_len > 0xffff) {
>  		dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
>  				channel, period_len, 0xffff);
> -		goto err_out;
> +		goto err_bd_out;
>  	}
>  
>  	while (buf < buf_len) {
> -		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
> +		struct sdma_buffer_descriptor *bd = &desc->bd[i];
>  		int param;
>  
>  		bd->buffer_addr = dma_addr;
> @@ -1366,7 +1431,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
>  		bd->mode.count = period_len;
>  
>  		if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
> -			goto err_out;
> +			goto err_bd_out;
>  		if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
>  			bd->mode.command = 0;
>  		else
> @@ -1389,10 +1454,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
>  		i++;
>  	}
>  
> -	sdmac->num_bd = num_periods;
> -	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
> -
> -	return &sdmac->desc;
> +	return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
> +err_bd_out:
> +	sdma_free_bd(desc);
> +	kfree(desc);
>  err_out:
>  	sdmac->status = DMA_ERROR;
>  	return NULL;
> @@ -1432,26 +1497,74 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
>  {
>  	struct sdma_channel *sdmac = to_sdma_chan(chan);
>  	u32 residue;
> +	struct virt_dma_desc *vd;
> +	struct sdma_desc *desc;
> +	enum dma_status ret;
> +	unsigned long flags;
>  
> -	if (sdmac->flags & IMX_DMA_SG_LOOP)
> -		residue = (sdmac->num_bd - sdmac->buf_ptail) *
> +	ret = dma_cookie_status(chan, cookie, txstate);
> +	if (ret == DMA_COMPLETE && txstate) {
> +		residue = sdmac->chn_count - sdmac->chn_real_count;
> +		return ret;
> +	}
> +
> +	spin_lock_irqsave(&sdmac->vc.lock, flags);
> +	vd = vchan_find_desc(&sdmac->vc, cookie);
> +	desc = to_sdma_desc(&vd->tx);

You should use 'vd' only after you have made sure it is valid (though I
see it causes no harm in this case, but let's be nice to the readers of
this code)

> +	if (vd) {
> +		if (sdmac->flags & IMX_DMA_SG_LOOP)
> +			residue = (desc->num_bd - desc->buf_ptail) *
>  			   sdmac->period_len - sdmac->chn_real_count;
> -	else
> +		else
> +			residue = sdmac->chn_count - sdmac->chn_real_count;
> +	} else if (sdmac->desc && sdmac->desc->vd.tx.cookie == cookie) {
>  		residue = sdmac->chn_count - sdmac->chn_real_count;
> +	} else {
> +		residue = 0;
> +	}
> +	ret = sdmac->status;
> +	spin_unlock_irqrestore(&sdmac->vc.lock, flags);
>  
>  	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
>  			 residue);
>  
> -	return sdmac->status;
> +	return ret;
> +}
> +
> +static void sdma_start_desc(struct sdma_channel *sdmac)
> +{
> +	struct virt_dma_desc *vd = vchan_next_desc(&sdmac->vc);
> +	struct sdma_desc *desc;
> +	struct sdma_engine *sdma = sdmac->sdma;
> +	int channel = sdmac->channel;
> +
> +	if (!vd) {
> +		sdmac->desc = NULL;
> +		return;
> +	}
> +	sdmac->desc = desc = to_sdma_desc(&vd->tx);
> +	/*
> +	 * Do not delete the node in desc_issued list in cyclic mode, otherwise
> +	 * the desc alloced will never be freed in vchan_dma_desc_free_list
> +	 */
> +	if (!(sdmac->flags & IMX_DMA_SG_LOOP)) {
> +		list_add_tail(&sdmac->desc->node, &sdmac->pending);
> +		list_del(&vd->node);
> +	}
> +	sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
> +	sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
> +	sdma_enable_channel(sdma, sdmac->channel);
>  }
>  
>  static void sdma_issue_pending(struct dma_chan *chan)
>  {
>  	struct sdma_channel *sdmac = to_sdma_chan(chan);
> -	struct sdma_engine *sdma = sdmac->sdma;
> +	unsigned long flags;
>  
> -	if (sdmac->status == DMA_IN_PROGRESS)
> -		sdma_enable_channel(sdma, sdmac->channel);
> +	spin_lock_irqsave(&sdmac->vc.lock, flags);
> +	if (vchan_issue_pending(&sdmac->vc) && !sdmac->desc)
> +		sdma_start_desc(sdmac);
> +	spin_unlock_irqrestore(&sdmac->vc.lock, flags);
>  }
>  
>  #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1	34
> @@ -1657,7 +1770,7 @@ static int sdma_init(struct sdma_engine *sdma)
>  	for (i = 0; i < MAX_DMA_CHANNELS; i++)
>  		writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
>  
> -	ret = sdma_request_channel(&sdma->channel[0]);
> +	ret = sdma_request_channel0(sdma);
>  	if (ret)
>  		goto err_dma_alloc;
>  
> @@ -1819,22 +1932,17 @@ static int sdma_probe(struct platform_device *pdev)
>  		struct sdma_channel *sdmac = &sdma->channel[i];
>  
>  		sdmac->sdma = sdma;
> -		spin_lock_init(&sdmac->lock);
> -
> -		sdmac->chan.device = &sdma->dma_device;
> -		dma_cookie_init(&sdmac->chan);
>  		sdmac->channel = i;
> -
> -		tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal,
> -			     (unsigned long) sdmac);
> +		sdmac->status = DMA_IN_PROGRESS;
> +		sdmac->vc.desc_free = sdma_desc_free;
> +		INIT_LIST_HEAD(&sdmac->pending);
>  		/*
>  		 * Add the channel to the DMAC list. Do not add channel 0 though
>  		 * because we need it internally in the SDMA driver. This also means
>  		 * that channel 0 in dmaengine counting matches sdma channel 1.
>  		 */
>  		if (i)
> -			list_add_tail(&sdmac->chan.device_node,
> -					&sdma->dma_device.channels);
> +			vchan_init(&sdmac->vc, &sdma->dma_device);
>  	}
>  
>  	ret = sdma_init(sdma);
> @@ -1879,7 +1987,7 @@ static int sdma_probe(struct platform_device *pdev)
>  	sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
>  	sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
>  	sdma->dma_device.device_config = sdma_config;
> -	sdma->dma_device.device_terminate_all = sdma_disable_channel_with_delay;
> +	sdma->dma_device.device_terminate_all = sdma_terminate_all;
>  	sdma->dma_device.src_addr_widths = SDMA_DMA_BUSWIDTHS;
>  	sdma->dma_device.dst_addr_widths = SDMA_DMA_BUSWIDTHS;
>  	sdma->dma_device.directions = SDMA_DMA_DIRECTIONS;
> @@ -1939,7 +2047,8 @@ static int sdma_remove(struct platform_device *pdev)
>  	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
>  		struct sdma_channel *sdmac = &sdma->channel[i];
>  
> -		tasklet_kill(&sdmac->tasklet);
> +		tasklet_kill(&sdmac->vc.task);
> +		sdma_free_chan_resources(&sdmac->vc.chan);
>  	}
>  
>  	platform_set_drvdata(pdev, NULL);
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH 07/14] ARM: spectre-v2: add Cortex A8 and A15 validation of the IBE bit
From: Geert Uytterhoeven @ 2018-05-22 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1fIuBF-0003q0-3d@rmk-PC.armlinux.org.uk>

Hi Russell,

On Wed, May 16, 2018 at 1:01 PM, Russell King
<rmk+kernel@armlinux.org.uk> wrote:
> When the branch predictor hardening is enabled, firmware must have set
> the IBE bit in the auxiliary control register.  If this bit has not
> been set, the Spectre workarounds will not be functional.
>
> Add validation that this bit is set, and print a warning at alert level
> if this is not the case.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Thanks for your patch!

> --- /dev/null
> +++ b/arch/arm/mm/proc-v7-bugs.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/kernel.h>
> +#include <linux/smp.h>
> +
> +static __maybe_unused void cpu_v7_check_auxcr_set(u32 mask, const char *msg)
> +{
> +       u32 aux_cr;
> +
> +       asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (aux_cr));
> +
> +       if ((aux_cr & mask) != mask)
> +               pr_err("CPU%u: %s", smp_processor_id(), msg);

pr_alert(), to match the patch description.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH v6 9/9] iio: counter: Remove IIO counter subdirectory
From: Jonathan Cameron @ 2018-05-22 10:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180521135828.GD5723@sophia>

On Mon, 21 May 2018 09:58:28 -0400
William Breathitt Gray <vilhelm.gray@gmail.com> wrote:

> On Sun, May 20, 2018 at 04:53:02PM +0100, Jonathan Cameron wrote:
> >On Wed, 16 May 2018 13:52:39 -0400
> >William Breathitt Gray <vilhelm.gray@gmail.com> wrote:
> >  
> >> This patch removes the IIO counter subdirectory which is now superceded
> >> by the Counter subsystem. Deprecation warnings are added to the
> >> documentation of the relevant IIO counter sysfs attributes.
> >> 
> >> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>  
> >
> >Please drop the directory when it becomes empty rather than in a later
> >patch.  IIRC there are some issues with empty Makefiles that will
> >make building inbetween tricky.
> >
> >For the deprecated markings.
> >
> >Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>  
> 
> I'll have the directory removal occur with the removal of the last
> module then when the directory becomes empty.
> 
> Regarding the deprecation markings, should I select a specific kernel
> version to date the removal of these attributes, or leave the future
> date open as this patch is now?

Leave it open.  The ultimate test is whether it is actually enough of a burden
to make us want to clean up the deprecated interface.

This burden may be that it is a pain to implement something new, or to test
or to maintain the code (or something I haven't thought of).

If it's not it may stay there for ever.

Jonathan
> 
> William Breathitt Gray
> 
> >  
> >> ---
> >>  Documentation/ABI/testing/sysfs-bus-iio          |  8 ++++++++
> >>  .../ABI/testing/sysfs-bus-iio-counter-104-quad-8 | 16 ++++++++++++++++
> >>  drivers/iio/Kconfig                              |  1 -
> >>  drivers/iio/Makefile                             |  1 -
> >>  drivers/iio/counter/Kconfig                      |  8 --------
> >>  drivers/iio/counter/Makefile                     |  5 -----
> >>  6 files changed, 24 insertions(+), 15 deletions(-)
> >>  delete mode 100644 drivers/iio/counter/Kconfig
> >>  delete mode 100644 drivers/iio/counter/Makefile
> >> 
> >> diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
> >> index 731146c3b138..6115d97b075e 100644
> >> --- a/Documentation/ABI/testing/sysfs-bus-iio
> >> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> >> @@ -1637,6 +1637,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_raw
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Raw counter device counts from channel Y. For quadrature
> >>  		counters, multiplication by an available [Y]_scale results in
> >>  		the counts of a single quadrature signal phase from channel Y.
> >> @@ -1645,6 +1647,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_raw
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Raw counter device index value from channel Y. This attribute
> >>  		provides an absolute positional reference (e.g. a pulse once per
> >>  		revolution) which may be used to home positional systems as
> >> @@ -1654,6 +1658,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
> >>  KernelVersion:	4.12
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		A list of possible counting directions which are:
> >>  		- "up"	: counter device is increasing.
> >>  		- "down": counter device is decreasing.
> >> @@ -1662,4 +1668,6 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
> >>  KernelVersion:	4.12
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Raw counter device counters direction for channel Y.
> >> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> >> index 7fac2c268d9a..bac3d0d48b7b 100644
> >> --- a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> >> +++ b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> >> @@ -6,6 +6,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Discrete set of available values for the respective counter
> >>  		configuration are listed in this file.
> >>  
> >> @@ -13,6 +15,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Count mode for channel Y. Four count modes are available:
> >>  		normal, range limit, non-recycle, and modulo-n. The preset value
> >>  		for channel Y is used by the count mode where required.
> >> @@ -47,6 +51,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Read-only attribute that indicates whether excessive noise is
> >>  		present at the channel Y count inputs in quadrature clock mode;
> >>  		irrelevant in non-quadrature clock mode.
> >> @@ -55,6 +61,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_preset
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		If the counter device supports preset registers, the preset
> >>  		count for channel Y is provided by this attribute.
> >>  
> >> @@ -62,6 +70,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Configure channel Y counter for non-quadrature or quadrature
> >>  		clock mode. Selecting non-quadrature clock mode will disable
> >>  		synchronous load mode. In quadrature clock mode, the channel Y
> >> @@ -83,6 +93,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Whether to set channel Y counter with channel Y preset value
> >>  		when channel Y index input is active, or continuously count.
> >>  		Valid attribute values are boolean.
> >> @@ -91,6 +103,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Active level of channel Y index input; irrelevant in
> >>  		non-synchronous load mode.
> >>  
> >> @@ -98,6 +112,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
> >>  KernelVersion:	4.10
> >>  Contact:	linux-iio at vger.kernel.org
> >>  Description:
> >> +		This interface is deprecated; please use the Counter subsystem.
> >> +
> >>  		Configure channel Y counter for non-synchronous or synchronous
> >>  		load mode. Synchronous load mode cannot be selected in
> >>  		non-quadrature clock mode.
> >> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> >> index d69e85a8bdc3..1152efad91a1 100644
> >> --- a/drivers/iio/Kconfig
> >> +++ b/drivers/iio/Kconfig
> >> @@ -74,7 +74,6 @@ source "drivers/iio/afe/Kconfig"
> >>  source "drivers/iio/amplifiers/Kconfig"
> >>  source "drivers/iio/chemical/Kconfig"
> >>  source "drivers/iio/common/Kconfig"
> >> -source "drivers/iio/counter/Kconfig"
> >>  source "drivers/iio/dac/Kconfig"
> >>  source "drivers/iio/dummy/Kconfig"
> >>  source "drivers/iio/frequency/Kconfig"
> >> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> >> index d8cba9c229c0..7bdd31f1b88f 100644
> >> --- a/drivers/iio/Makefile
> >> +++ b/drivers/iio/Makefile
> >> @@ -20,7 +20,6 @@ obj-y += amplifiers/
> >>  obj-y += buffer/
> >>  obj-y += chemical/
> >>  obj-y += common/
> >> -obj-y += counter/
> >>  obj-y += dac/
> >>  obj-y += dummy/
> >>  obj-y += gyro/
> >> diff --git a/drivers/iio/counter/Kconfig b/drivers/iio/counter/Kconfig
> >> deleted file mode 100644
> >> index 95a7a0df6cac..000000000000
> >> --- a/drivers/iio/counter/Kconfig
> >> +++ /dev/null
> >> @@ -1,8 +0,0 @@
> >> -#
> >> -# Counter devices
> >> -#
> >> -# When adding new entries keep the list in alphabetical order
> >> -
> >> -menu "Counters"
> >> -
> >> -endmenu
> >> diff --git a/drivers/iio/counter/Makefile b/drivers/iio/counter/Makefile
> >> deleted file mode 100644
> >> index 8fd3d954775a..000000000000
> >> --- a/drivers/iio/counter/Makefile
> >> +++ /dev/null
> >> @@ -1,5 +0,0 @@
> >> -#
> >> -# Makefile for IIO counter devices
> >> -#
> >> -
> >> -# When adding new entries keep the list in alphabetical order  
> >  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 07/14] ARM: spectre-v2: add Cortex A8 and A15 validation of the IBE bit
From: Russell King - ARM Linux @ 2018-05-22 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdWdfjmdnQVmX7PJsXV8PcHhCCwAeHgxXRSV3CjX4C_amg@mail.gmail.com>

On Tue, May 22, 2018 at 12:38:05PM +0200, Geert Uytterhoeven wrote:
> Hi Russell,
> 
> On Wed, May 16, 2018 at 1:01 PM, Russell King
> <rmk+kernel@armlinux.org.uk> wrote:
> > When the branch predictor hardening is enabled, firmware must have set
> > the IBE bit in the auxiliary control register.  If this bit has not
> > been set, the Spectre workarounds will not be functional.
> >
> > Add validation that this bit is set, and print a warning at alert level
> > if this is not the case.
> >
> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> 
> Thanks for your patch!
> 
> > --- /dev/null
> > +++ b/arch/arm/mm/proc-v7-bugs.c
> > @@ -0,0 +1,29 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +#include <linux/kernel.h>
> > +#include <linux/smp.h>
> > +
> > +static __maybe_unused void cpu_v7_check_auxcr_set(u32 mask, const char *msg)
> > +{
> > +       u32 aux_cr;
> > +
> > +       asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (aux_cr));
> > +
> > +       if ((aux_cr & mask) != mask)
> > +               pr_err("CPU%u: %s", smp_processor_id(), msg);
> 
> pr_alert(), to match the patch description.

It was alert, but I've lowered it because I don't think it warrants
alert status.  Maybe critical would be better?  Shrug, this stuff is
rather subjective.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* [PATCH] iommu/io-pgtable-arm: Make allocations NUMA-aware
From: Robin Murphy @ 2018-05-22 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180521184717.GA24025@arm.com>

On 21/05/18 19:47, Will Deacon wrote:
> On Mon, May 21, 2018 at 07:12:40PM +0100, Robin Murphy wrote:
>> We would generally expect pagetables to be read by the IOMMU more than
>> written by the CPU, so in NUMA systems it would be preferable to avoid
>> the IOMMU making cross-node pagetable walks if possible. We already have
>> a handle on the IOMMU device for the sake of coherency management, so
>> it's trivial to grab the appropriate NUMA node when allocating new
>> pagetable pages.
>>
>> Note that we drop the semantics of alloc_pages_exact(), but that's fine
>> since they have never been necessary: the only time we're allocating
>> more than one page is for stage 2 top-level concatenation, but since
>> that is based on the number of IPA bits, the size is always some exact
>> power of two anyway.
>>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>> ---
>>   drivers/iommu/io-pgtable-arm.c | 12 ++++++++----
>>   1 file changed, 8 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
>> index 39c2a056da21..e80ca386c5b4 100644
>> --- a/drivers/iommu/io-pgtable-arm.c
>> +++ b/drivers/iommu/io-pgtable-arm.c
>> @@ -231,12 +231,16 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
>>   				    struct io_pgtable_cfg *cfg)
>>   {
>>   	struct device *dev = cfg->iommu_dev;
>> +	int order = get_order(size);
>> +	struct page *p;
>>   	dma_addr_t dma;
>> -	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
>> +	void *pages;
>>   
>> -	if (!pages)
>> +	p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
>> +	if (!p)
>>   		return NULL;
>>   
>> +	pages = page_address(p);
> 
> Might be worth checking/masking out __GFP_HIGHMEM if we see it, since we
> could theoretically run into trouble if we got back a highmem mapping here
> and we're losing the check in __get_free_pages afaict.

True - the only callers are internal ones, and anyone trying to make 
inappropriate changes here should quickly discover why highmem doesn't 
work without significant surgery all over, but I don't see any harm in 
keeping an equivalent VM_BUG_ON as clear documentation.

> Other than than, looks good:
> 
> Acked-by: Will Deacon <will.deacon@arm.com>

Thanks!

Robin.

^ permalink raw reply

* [PATCH V7] ARM: dts: da850-evm: Enable LCD and Backlight
From: Sekhar Nori @ 2018-05-22 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2d52e1f8-d321-4465-fdfa-fd0d718c67cf@ti.com>

On Monday 21 May 2018 08:21 PM, Sekhar Nori wrote:
> On Saturday 19 May 2018 02:03 AM, Adam Ford wrote:
>> When using the board files the LCD works, but not with the DT.
>> This adds enables the original da850-evm to work with the same
>> LCD in device tree mode.
>>
>> The EVM has a gpio for the regulator and a PWM for dimming the
>> backlight.  The LCD and the vpif display pins are mutually
>> exclusive, so if using the LCD, do not load the vpif driver.
>>
>> Signed-off-by: Adam Ford <aford173@gmail.com>
> 
>> diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
>> index 0e82bb988fde..a76c2ddfd23e 100644
>> --- a/arch/arm/boot/dts/da850-evm.dts
>> +++ b/arch/arm/boot/dts/da850-evm.dts
>> @@ -27,6 +27,60 @@
>>  		spi0 = &spi1;
>>  	};
>>  
>> +	backlight: backlight-pwm {
>> +		pinctrl-names = "default";
>> +		pinctrl-0 = <&ecap2_pins>;
>> +		power-supply = <&backlight_lcd>;
>> +		compatible = "pwm-backlight";
>> +		pwms = <&ecap2 0 50000 0>;
> 
> It will be nice to add a comment here: "The PWM here corresponds to 
> production hardware. The schematic needs to be 1015171 (15 March 2010), 
> Rev A or newer."
> 
>> +		brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
>> +		default-brightness-level = <7>;
>> +	};
>> +
>> +	panel {
>> +		compatible = "ti,tilcdc,panel";
>> +		pinctrl-names = "default";
>> +		pinctrl-0 = <&lcd_pins>;
>> +		/*
>> +		 * The vpif and the LCD are mutually exclusive.
>> +		 * To enable VPIF, change the status below to 'disabled' then
>> +		 * then change the status of the vpif below to 'okay'
>> +		*/
> 
> This results in checkpatch warning:
>  
> [PATCH V7] ARM: dts: da850-evm: Enable LCD and Backlight.eml:153: WARNING: Block comments should align the * on each line
> [PATCH V7] ARM: dts: da850-evm: Enable LCD and Backlight.eml:239: WARNING: Block comments should align the * on each line
> 
>>  &vpif {
>>  	pinctrl-names = "default";
>>  	pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
>> -	status = "okay";
>> +	/*
>> +	 * The vpif and the LCD are mutually exclusive.
>> +	 * To enable VPIF, disable the ti,tilcdc,panel then
>> +	 * changed the status below to 'okay'
>> +	*/
>> +	status = "disabled";
> 
> Are you able to see VPIF is disabled after this? Trying your patch, I 
> still see VPIF probing[1]. Also, only VPIF display has a conflict with 
> LCD, correct (capture should be fine)?

To answer myself, I forgot that VPIF is bit special because it is
registered through pdata-quirks. As such the parent vpif node is used
only for pinmux setting. I do think the platform devices for capture and
display should not be registered if the vpif parent node is disabled in
DT. But thats a subject of another patch.

With that, I fixed up my comments above locally and added this in queue
for v4.19

Thanks,
Sekhar

^ permalink raw reply

* [PATCH RFC V2 0/6] hwmon: Add support for Raspberry Pi voltage sensor
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel

A common issue for the Raspberry Pi is an inadequate power supply. 
Noralf Tr?nnes started a discussion [1] about writing such undervoltage
conditions into the kernel log.

This series is a draft to upstream the resulting kernel patch and is not
intended for 4.18.

Changes in V2:
- simplified Kconfig dependency suggested by Robin Murphy
- replace dt-binding by probing from firmware driver
- add hwmon documentation
- minor improvements suggested by Guenter Roeck

[1] - https://github.com/raspberrypi/linux/issues/2367

Stefan Wahren (6):
  ARM: bcm2835: Add GET_THROTTLED firmware property
  hwmon: Add support for RPi voltage sensor
  firmware: raspberrypi: Register hwmon driver
  ARM: bcm2835_defconfig: Enable RPi voltage sensor
  ARM: multi_v7_defconfig: Enable RPi voltage sensor
  arm64: defconfig: Enable RPi voltage sensor

 Documentation/hwmon/raspberrypi-hwmon      |  22 ++++
 arch/arm/configs/bcm2835_defconfig         |   2 +-
 arch/arm/configs/multi_v7_defconfig        |   1 +
 arch/arm64/configs/defconfig               |   1 +
 drivers/firmware/raspberrypi.c             |  19 ++++
 drivers/hwmon/Kconfig                      |  10 ++
 drivers/hwmon/Makefile                     |   1 +
 drivers/hwmon/raspberrypi-hwmon.c          | 168 +++++++++++++++++++++++++++++
 include/soc/bcm2835/raspberrypi-firmware.h |   1 +
 9 files changed, 224 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/hwmon/raspberrypi-hwmon
 create mode 100644 drivers/hwmon/raspberrypi-hwmon.c

-- 
2.7.4

^ permalink raw reply

* [PATCH RFC V2 1/6] ARM: bcm2835: Add GET_THROTTLED firmware property
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

Recent Raspberry Pi firmware provides a mailbox property to detect
under-voltage conditions. Here is the current definition.

The u32 value returned by the firmware is divided into 2 parts:
  - lower 16-bits are the live value
  - upper 16-bits are the history or sticky value

  Bits:
  0: undervoltage
  1: arm frequency capped
  2: currently throttled
  16: undervoltage has occurred
  17: arm frequency capped has occurred
  18: throttling has occurred

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 include/soc/bcm2835/raspberrypi-firmware.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 8ee8991..c4a5c9e 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag {
 	RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
 	RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
 	RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
+	RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
 	RPI_FIRMWARE_SET_CLOCK_STATE =                        0x00038001,
 	RPI_FIRMWARE_SET_CLOCK_RATE =                         0x00038002,
 	RPI_FIRMWARE_SET_VOLTAGE =                            0x00038003,
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC V2 2/6] hwmon: Add support for RPi voltage sensor
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

Currently there is no easy way to detect undervoltage conditions on a
remote Raspberry Pi. This hwmon driver retrieves the state of the
undervoltage sensor via mailbox interface. The handling based on
Noralf's modifications to the downstream firmware driver. In case of
an undervoltage condition only an entry is written to the kernel log.

CC: "Noralf Tr?nnes" <noralf@tronnes.org>
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 Documentation/hwmon/raspberrypi-hwmon |  22 +++++
 drivers/hwmon/Kconfig                 |  10 ++
 drivers/hwmon/Makefile                |   1 +
 drivers/hwmon/raspberrypi-hwmon.c     | 168 ++++++++++++++++++++++++++++++++++
 4 files changed, 201 insertions(+)
 create mode 100644 Documentation/hwmon/raspberrypi-hwmon
 create mode 100644 drivers/hwmon/raspberrypi-hwmon.c

diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon
new file mode 100644
index 0000000..3c92e2c
--- /dev/null
+++ b/Documentation/hwmon/raspberrypi-hwmon
@@ -0,0 +1,22 @@
+Kernel driver raspberrypi-hwmon
+===============================
+
+Supported boards:
+  * Raspberry Pi A+ (via GPIO on SoC)
+  * Raspberry Pi B+ (via GPIO on SoC)
+  * Raspberry Pi 2 B (via GPIO on SoC)
+  * Raspberry Pi 3 B (via GPIO on port expander)
+  * Raspberry Pi 3 B+ (via PMIC)
+
+Author: Stefan Wahren <stefan.wahren@i2se.com>
+
+Description
+-----------
+
+This driver periodically polls a mailbox property of the VC4 firmware to detect
+undervoltage conditions.
+
+Sysfs entries
+-------------
+
+in0_lcrit_alarm		Undervoltage alarm
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 768aed5..9a5bdb0 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1298,6 +1298,16 @@ config SENSORS_PWM_FAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called pwm-fan.
 
+config SENSORS_RASPBERRYPI_HWMON
+	tristate "Raspberry Pi voltage monitor"
+	depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+	help
+	  If you say yes here you get support for voltage sensor on the
+	  Raspberry Pi.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called raspberrypi-hwmon.
+
 config SENSORS_SHT15
 	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
 	depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index e7d52a3..a929770 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
 obj-$(CONFIG_SENSORS_PWM_FAN)	+= pwm-fan.o
+obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON)	+= raspberrypi-hwmon.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
 obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
 obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
new file mode 100644
index 0000000..6233e84
--- /dev/null
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi voltage sensor driver
+ *
+ * Based on firmware/raspberrypi.c by Noralf Tr?nnes
+ *
+ * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define UNDERVOLTAGE_STICKY_BIT	BIT(16)
+
+struct rpi_hwmon_data {
+	struct device *hwmon_dev;
+	struct rpi_firmware *fw;
+	u32 last_throttled;
+	struct delayed_work get_values_poll_work;
+};
+
+static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
+{
+	u32 new_uv, old_uv, value;
+	int ret;
+
+	/* Request firmware to clear sticky bits */
+	value = 0xffff;
+
+	ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+				    &value, sizeof(value));
+	if (ret) {
+		dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
+			     ret);
+		return;
+	}
+
+	new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+	old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+	data->last_throttled = value;
+
+	if (new_uv == old_uv)
+		return;
+
+	if (new_uv)
+		dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
+	else
+		dev_info(data->hwmon_dev, "Voltage normalised\n");
+
+	sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
+}
+
+static void get_values_poll(struct work_struct *work)
+{
+	struct rpi_hwmon_data *data;
+
+	data = container_of(work, struct rpi_hwmon_data,
+			    get_values_poll_work.work);
+
+	rpi_firmware_get_throttled(data);
+
+	/*
+	 * We can't run faster than the sticky shift (100ms) since we get
+	 * flipping in the sticky bits that are cleared.
+	 */
+	schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+}
+
+static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
+		    u32 attr, int channel, long *val)
+{
+	struct rpi_hwmon_data *data = dev_get_drvdata(dev);
+
+	*val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+	return 0;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+			      u32 attr, int channel)
+{
+	return 0444;
+}
+
+static const u32 rpi_in_config[] = {
+	HWMON_I_LCRIT_ALARM,
+	0
+};
+
+static const struct hwmon_channel_info rpi_in = {
+	.type = hwmon_in,
+	.config = rpi_in_config,
+};
+
+static const struct hwmon_channel_info *rpi_info[] = {
+	&rpi_in,
+	NULL
+};
+
+static const struct hwmon_ops rpi_hwmon_ops = {
+	.is_visible = rpi_is_visible,
+	.read = rpi_read,
+};
+
+static const struct hwmon_chip_info rpi_chip_info = {
+	.ops = &rpi_hwmon_ops,
+	.info = rpi_info,
+};
+
+static int rpi_hwmon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rpi_hwmon_data *data;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->fw = platform_get_drvdata(to_platform_device(dev->parent));
+	if (!data->fw)
+		return -EPROBE_DEFER;
+
+	ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+				    &data->last_throttled,
+				    sizeof(data->last_throttled));
+	if (ret)
+		return -ENODEV;
+
+	data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
+							       data,
+							       &rpi_chip_info,
+							       NULL);
+
+	INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+	platform_set_drvdata(pdev, data);
+
+	if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
+		schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+
+	return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int rpi_hwmon_remove(struct platform_device *pdev)
+{
+	struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&data->get_values_poll_work);
+
+	return 0;
+}
+
+static struct platform_driver rpi_hwmon_driver = {
+	.probe = rpi_hwmon_probe,
+	.remove = rpi_hwmon_remove,
+	.driver = {
+		.name = "raspberrypi-hwmon",
+	},
+};
+module_platform_driver(rpi_hwmon_driver);
+
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC V2 3/6] firmware: raspberrypi: Register hwmon driver
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

Since the raspberrypi-hwmon driver is tied to the VC4 firmware instead of
particular hardware its registration should be in the firmware driver.

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 drivers/firmware/raspberrypi.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 6692888f..0602626 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -21,6 +21,8 @@
 #define MBOX_DATA28(msg)		((msg) & ~0xf)
 #define MBOX_CHAN_PROPERTY		8
 
+static struct platform_device *rpi_hwmon;
+
 struct rpi_firmware {
 	struct mbox_client cl;
 	struct mbox_chan *chan; /* The property channel. */
@@ -183,6 +185,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
 	}
 }
 
+static void
+rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+{
+	u32 packet;
+	int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
+					&packet, sizeof(packet));
+
+	if (ret)
+		return;
+
+	rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
+						  -1, NULL, 0);
+}
+
 static int rpi_firmware_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -209,6 +225,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, fw);
 
 	rpi_firmware_print_firmware_revision(fw);
+	rpi_register_hwmon_driver(dev, fw);
 
 	return 0;
 }
@@ -217,6 +234,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
 {
 	struct rpi_firmware *fw = platform_get_drvdata(pdev);
 
+	platform_device_unregister(rpi_hwmon);
+	rpi_hwmon = NULL;
 	mbox_free_channel(fw->chan);
 
 	return 0;
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC V2 4/6] ARM: bcm2835_defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

The patch enables the hwmon driver for the Raspberry Pi.

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 arch/arm/configs/bcm2835_defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index e4d188f..e9bc889 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -86,7 +86,7 @@ CONFIG_SPI=y
 CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_THERMAL=y
 CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC V2 5/6] ARM: multi_v7_defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

The patch enables the hwmon driver for the Raspberry Pi.

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 720461b..5c9dc00 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -477,6 +477,7 @@ CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM95245=y
 CONFIG_SENSORS_NTC_THERMISTOR=m
 CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_SENSORS_INA2XX=m
 CONFIG_CPU_THERMAL=y
 CONFIG_BCM2835_THERMAL=m
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC V2 6/6] arm64: defconfig: Enable RPi voltage sensor
From: Stefan Wahren @ 2018-05-22 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526988112-4021-1-git-send-email-stefan.wahren@i2se.com>

The patch enables the hwmon driver for the Raspberry Pi.

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index d25121b..5cdecef 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -352,6 +352,7 @@ CONFIG_BATTERY_BQ27XXX=y
 CONFIG_SENSORS_ARM_SCPI=y
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
 CONFIG_THERMAL_EMULATION=y
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/2] clk: imx6ul: add GPIO clock gates
From: Fabio Estevam @ 2018-05-22 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526959560-6014-1-git-send-email-Anson.Huang@nxp.com>

On Tue, May 22, 2018 at 12:25 AM, Anson Huang <Anson.Huang@nxp.com> wrote:
> i.MX6UL has GPIO clock gates in CCM CCGR, add
> them into clock tree for clock management.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>

Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>

^ permalink raw reply

* [PATCH 2/2] ARM: dts: imx6ul: add GPIO clocks
From: Fabio Estevam @ 2018-05-22 11:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526959560-6014-2-git-send-email-Anson.Huang@nxp.com>

On Tue, May 22, 2018 at 12:26 AM, Anson Huang <Anson.Huang@nxp.com> wrote:
> i.MX6UL has GPIO clock gates in CCM CCGR, add
> clock property for GPIO driver to make sure all
> GPIO banks work as expected.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>

Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>

^ permalink raw reply

* [PATCH] cpufreq: Add Kryo CPU scaling driver
From: Ilia Lin @ 2018-05-22 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526729701-8589-1-git-send-email-ilialin@codeaurora.org>

In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
the CPU frequency subset and voltage value of each OPP varies
based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
defines the voltage and frequency value based on the msm-id in SMEM
and speedbin blown in the efuse combination.
The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
to provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each OPP of
operating-points-v2 table when it is parsed by the OPP framework.

Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/Kconfig.arm          |  10 +++
 drivers/cpufreq/Makefile             |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   3 +
 drivers/cpufreq/qcom-cpufreq-kryo.c  | 163 +++++++++++++++++++++++++++++++++++
 4 files changed, 177 insertions(+)
 create mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index de55c7d..0bfd40e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,6 +124,16 @@ config ARM_OMAP2PLUS_CPUFREQ
 	depends on ARCH_OMAP2PLUS
 	default ARCH_OMAP2PLUS
 
+config ARM_QCOM_CPUFREQ_KRYO
+	bool "Qualcomm Kryo based CPUFreq"
+	depends on QCOM_QFPROM
+	depends on QCOM_SMEM
+	select PM_OPP
+	help
+	  This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
+
+	  If in doubt, say N.
+
 config ARM_S3C_CPUFREQ
 	bool
 	help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 8d24ade..fb4a2ec 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)	+= qcom-cpufreq-kryo.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)	+= s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)	+= s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)	+= s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3b585e4..77d6ab8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,9 @@
 
 	{ .compatible = "nvidia,tegra124", },
 
+	{ .compatible = "qcom,apq8096", },
+	{ .compatible = "qcom,msm8996", },
+
 	{ .compatible = "st,stih407", },
 	{ .compatible = "st,stih410", },
 
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
new file mode 100644
index 0000000..c5bb070
--- /dev/null
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/*
+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
+ * the CPU frequency subset and voltage value of each OPP varies
+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
+ * defines the voltage and frequency value based on the msm-id in SMEM
+ * and speedbin blown in the efuse combination.
+ * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * to provide the OPP framework with required information.
+ * This is used to determine the voltage and frequency value for each OPP of
+ * operating-points-v2 table when it is parsed by the OPP framework.
+ */
+
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
+
+#define MSM_ID_SMEM	137
+
+enum _msm_id {
+	MSM8996V3 = 0xF6ul,
+	APQ8096V3 = 0x123ul,
+	MSM8996SG = 0x131ul,
+	APQ8096SG = 0x138ul,
+};
+
+enum _msm8996_version {
+	MSM8996_V3,
+	MSM8996_SG,
+	NUM_OF_MSM8996_VERSIONS,
+};
+
+static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+{
+	size_t len;
+	u32 *msm_id;
+	enum _msm8996_version version;
+
+	msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
+	/* The first 4 bytes are format, next to them is the actual msm-id */
+	msm_id++;
+
+	switch ((enum _msm_id)*msm_id) {
+	case MSM8996V3:
+	case APQ8096V3:
+		version = MSM8996_V3;
+		break;
+	case MSM8996SG:
+	case APQ8096SG:
+		version = MSM8996_SG;
+		break;
+	default:
+		version = NUM_OF_MSM8996_VERSIONS;
+	}
+
+	return version;
+}
+
+static int __init qcom_cpufreq_kryo_driver_init(void)
+{
+	struct opp_table *opp_tables[NR_CPUS] = {0};
+	enum _msm8996_version msm8996_version;
+	struct nvmem_cell *speedbin_nvmem;
+	struct platform_device *pdev;
+	struct device_node *np;
+	struct device *cpu_dev;
+	unsigned cpu;
+	u8 *speedbin;
+	u32 versions;
+	size_t len;
+	int ret;
+
+	cpu_dev = get_cpu_device(0);
+	if (NULL == cpu_dev)
+		return -ENODEV;
+
+	msm8996_version = qcom_cpufreq_kryo_get_msm_id();
+	if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
+		dev_err(cpu_dev, "Not Snapdragon 820/821!");
+		return -ENODEV;
+	}
+
+	np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np))
+		return PTR_ERR(np);
+
+	if (!of_device_is_compatible(np, "operating-points-v2-kryo-cpu")) {
+		ret = -ENOENT;
+		goto free_np;
+	}
+
+	speedbin_nvmem = of_nvmem_cell_get(np, NULL);
+	if (IS_ERR(speedbin_nvmem)) {
+		ret = PTR_ERR(speedbin_nvmem);
+		dev_err(cpu_dev, "Could not get nvmem cell: %d\n", ret);
+		goto free_np;
+	}
+
+	speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+	nvmem_cell_put(speedbin_nvmem);
+
+	switch (msm8996_version) {
+	case MSM8996_V3:
+		versions = 1 << (unsigned int)(*speedbin);
+		break;
+	case MSM8996_SG:
+		versions = 1 << ((unsigned int)(*speedbin) + 4);
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	for_each_possible_cpu(cpu) {
+		cpu_dev = get_cpu_device(cpu);
+		if (NULL == cpu_dev) {
+			ret = -ENODEV;
+			goto free_opp;
+		}
+
+		opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev,
+							      &versions, 1);
+		ret = PTR_ERR(opp_tables[cpu]);
+		if (ret && ret != -EBUSY) {
+			dev_err(cpu_dev, "Failed to set supported hardware\n");
+			goto free_opp;
+		}
+	}
+
+	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+	if (!IS_ERR(pdev))
+		return 0;
+
+	ret = PTR_ERR(pdev);
+	dev_err(cpu_dev, "Failed to register platform device\n");
+
+free_opp:
+	for_each_possible_cpu(cpu) {
+		if (IS_ERR_OR_NULL(opp_tables[cpu]))
+			break;
+		dev_pm_opp_put_supported_hw(opp_tables[cpu]);
+	}
+free_np:
+	of_node_put(np);
+
+	return ret;
+}
+late_initcall(qcom_cpufreq_kryo_driver_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/2] arm64: dts: renesas: r8a77980: add GEther support
From: Geert Uytterhoeven @ 2018-05-22 11:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8910c197-cf1b-9ee9-9ddb-5d2f705a4b26@cogentembedded.com>

Hi Sergei,

On Fri, May 18, 2018 at 9:45 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Define the generic R8A77980 part of the GEther device node.
>
> Based on the original (and large) patch by Vladimir Barinov.
>
> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

Thanks for your patch!

With the below addressed:
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

> --- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980.dtsi
> +++ renesas/arch/arm64/boot/dts/renesas/r8a77980.dtsi
> @@ -417,6 +417,17 @@
>                         dma-channels = <16>;
>                 };
>
> +               gether: ethernet at e7400000 {
> +                       compatible = "renesas,gether-r8a77980";
> +                       reg = <0 0xe7400000 0 0x1000>;
> +                       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
> +                       clocks = <&cpg CPG_MOD 813>;
> +                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;

resets = <&cpg 813>;

> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +                       status = "disabled";

Any default phy-mode needed?

> +               };
> +
>                 mmc0: mmc at ee140000 {
>                         compatible = "renesas,sdhi-r8a77980",
>                                      "renesas,rcar-gen3-sdhi";


Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH v2] iommu/io-pgtable-arm: Make allocations NUMA-aware
From: Robin Murphy @ 2018-05-22 11:50 UTC (permalink / raw)
  To: linux-arm-kernel

We would generally expect pagetables to be read by the IOMMU more than
written by the CPU, so in NUMA systems it makes sense to locate them
close to the former and avoid cross-node pagetable walks if at all
possible. As it turns out, we already have a handle on the IOMMU device
for the sake of coherency management, so it's trivial to grab the
appropriate NUMA node when allocating new pagetable pages.

Note that we drop the semantics of alloc_pages_exact(), but that's fine
since they have never been necessary: the only time we're allocating
more than one page is for stage 2 top-level concatenation, but since
that is based on the number of IPA bits, the size is always some exact
power of two anyway.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Retain equivalent highmem check

 drivers/iommu/io-pgtable-arm.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 39c2a056da21..5194755bba29 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -231,12 +231,17 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
 				    struct io_pgtable_cfg *cfg)
 {
 	struct device *dev = cfg->iommu_dev;
+	int order = get_order(size);
+	struct page *p;
 	dma_addr_t dma;
-	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
+	void *pages;
 
-	if (!pages)
+	VM_BUG_ON((gfp & __GFP_HIGHMEM));
+	p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
+	if (!p)
 		return NULL;
 
+	pages = page_address(p);
 	if (!(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) {
 		dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, dma))
@@ -256,7 +261,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
 	dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
 	dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
 out_free:
-	free_pages_exact(pages, size);
+	__free_pages(p, order);
 	return NULL;
 }
 
@@ -266,7 +271,7 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
 	if (!(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA))
 		dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
 				 size, DMA_TO_DEVICE);
-	free_pages_exact(pages, size);
+	free_pages((unsigned long)pages, get_order(size));
 }
 
 static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep,
-- 
2.17.0.dirty

^ permalink raw reply related

* [PATCH 04/20] arm-nommu: use generic dma_noncoherent_ops
From: Christoph Hellwig @ 2018-05-22 11:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180511091114.GA16141@n2100.armlinux.org.uk>

On Fri, May 11, 2018 at 10:11:15AM +0100, Russell King - ARM Linux wrote:
> > +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
> > +		size_t size, enum dma_data_direction dir)
> 
> Please no.  There is a lot of history of these (__dma_page_cpu_to_dev etc)
> functions being abused by out of tree drivers, because they think they
> know better.  This is stopped by making them static and ensuring that
> drivers have no access to these functions.
> 
> Please do not re-expose these to the global kernel.
> 
> While it may make things easier for a cross-architecture point of view,
> it makes it a lot easier for people to abuse these private APIs.

The point of this series, which isn't fully archived yet, is to
consolidate the direct mapping dma code, that is all dma_map_ops
instances except for iommus.  It is in fact in many ways modelled
after the ARM code.  For that we need the architectures to supply
the cache maintainance routines.

However, even if they now appear in dma-noncoherent.h they are NOT
and will NOT be exported, so using them directly from drivers won't
easily be possible.

I'll drop the arm-nommu patch for now, but I will pester your with this
again once arm is the last architecture not sharing the common code.

> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
> According to speedtest.net: 8.21Mbps down 510kbps up
---end quoted text---

^ permalink raw reply

* [PATCH 1/9] ARM: shmobile: defconfig: Enable MTD command line partition parsing
From: Marek Vasut @ 2018-05-22 12:02 UTC (permalink / raw)
  To: linux-arm-kernel

In preparation for removing MTD partitioning from the DTs and moving
it over to kernel command line partition parsing, enable the support
for kernel command line MTD partition parsing.

The argument for not having MTD partitions in the DT is the same as
for not having hard drive partitions in DT, neither describes the
hardware itself, so it shouldn't be in the DT. Furthermore, kernel
command line MTD partition passing allows greater flexibility in
case someone decided to repartition the flash, which is well in the
realm of possibility with these systems.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc at vger.kernel.org
---
 arch/arm/configs/shmobile_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index b49887e86a3d..4d0d5a00a188 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -64,6 +64,7 @@ CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_SIMPLE_PM_BUS=y
 CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SPI_NOR=y
-- 
2.16.2

^ permalink raw reply related


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