All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 08/14] drm/i915/scheduler: Execute requests in order of priorities
From: Tvrtko Ursulin @ 2016-11-14 11:48 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
In-Reply-To: <20161114114113.GE32240@nuc-i3427.alporthouse.com>


On 14/11/2016 11:41, Chris Wilson wrote:
> On Mon, Nov 14, 2016 at 11:15:52AM +0000, Tvrtko Ursulin wrote:
>> On 14/11/2016 08:56, Chris Wilson wrote:
>>> +static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
>>> +{
>>> +	struct intel_engine_cs *engine = NULL;
>>> +	struct i915_dependency *dep, *p;
>>> +	struct i915_dependency stack;
>>> +	LIST_HEAD(dfs);
>>> +
>>> +	if (prio <= READ_ONCE(request->priotree.priority))
>>> +		return;
>>> +
>>> +	/* Need BKL in order to use the temporary link inside i915_dependency */
>>> +	lockdep_assert_held(&request->i915->drm.struct_mutex);
>>> +
>>> +	stack.signaler = &request->priotree;
>>> +	list_add(&stack.dfs_link, &dfs);
>>> +
>>> +	/* Recursively bump all dependent priorities to match the new request */
>>
>> Missed last time round that the comment needs updating.
>
> It still is a recursive design though, just flat. That one word was
> saving a paragraph :|
>
> I think the easiest way to describe what the code is doing here is to
> show the recursive version in the comment and then hope for inspiration
> in describing how that maps onto the search list.

I can see that angle yes. Maybe the just add a second sentence saying 
something like "To avoid having recursive code to do this recursive 
update we build a flat list of dependencies in a depth first search 
manner."?

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH V3 3/3] drm: Add new driver for MXSFB controller
From: Daniel Vetter @ 2016-11-14 11:47 UTC (permalink / raw)
  To: Marek Vasut; +Cc: Fabio Estevam, Daniel Vetter, Shawn Guo, dri-devel
In-Reply-To: <20161114101036.3505-3-marex@denx.de>

On Mon, Nov 14, 2016 at 11:10:36AM +0100, Marek Vasut wrote:
> Add new driver for the MXSFB controller found in i.MX23/28/6SX .
> The MXSFB controller is a simple framebuffer controller with one
> parallel LCD output. Unlike the MXSFB fbdev driver that is used
> on these systems now, this driver uses the DRM/KMS framework.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Lucas Stach <l.stach@pengutronix.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> --
> V2: - Use drm_simple_kms_helper to reduce amount of common code
>     - Add dedicated OF compatible for i.MX6SX
> V3: - Update to latest next/master

Imo looks all pretty. Please wrap up in a pull request as soon as you have
acks from dt and all that and then send a pull request to Dave.

Thanks, Daniel

> ---
>  MAINTAINERS                        |   6 +
>  drivers/gpu/drm/Kconfig            |   2 +
>  drivers/gpu/drm/Makefile           |   1 +
>  drivers/gpu/drm/mxsfb/Kconfig      |  18 ++
>  drivers/gpu/drm/mxsfb/Makefile     |   2 +
>  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 241 ++++++++++++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 444 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  54 +++++
>  drivers/gpu/drm/mxsfb/mxsfb_out.c  | 131 +++++++++++
>  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 114 ++++++++++
>  10 files changed, 1013 insertions(+)
>  create mode 100644 drivers/gpu/drm/mxsfb/Kconfig
>  create mode 100644 drivers/gpu/drm/mxsfb/Makefile
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_drv.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_drv.h
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c
>  create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_regs.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3f3f60b..f32b5df 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8339,6 +8339,12 @@ T:	git git://linuxtv.org/mkrufky/tuners.git
>  S:	Maintained
>  F:	drivers/media/tuners/mxl5007t.*
>  
> +MXSFB DRM DRIVER
> +M:	Marek Vasut <marex@denx.de>
> +S:	Supported
> +F:	drivers/gpu/drm/mxsfb/
> +F:	Documentation/devicetree/bindings/display/mxsfb-drm.txt
> +
>  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
>  M:	Hyong-Youb Kim <hykim@myri.com>
>  L:	netdev@vger.kernel.org
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 863cdca..fbcb984 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -239,6 +239,8 @@ source "drivers/gpu/drm/mediatek/Kconfig"
>  
>  source "drivers/gpu/drm/zte/Kconfig"
>  
> +source "drivers/gpu/drm/mxsfb/Kconfig"
> +
>  # Keep legacy drivers last
>  
>  menuconfig DRM_LEGACY
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index f217274..ac5e115 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -88,3 +88,4 @@ obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
>  obj-$(CONFIG_DRM_ARCPGU)+= arc/
>  obj-y			+= hisilicon/
>  obj-$(CONFIG_DRM_ZTE)	+= zte/
> +obj-$(CONFIG_DRM_MXSFB)	+= mxsfb/
> diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
> new file mode 100644
> index 0000000..0b6cb59
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/Kconfig
> @@ -0,0 +1,18 @@
> +config DRM_MXS
> +	bool
> +	help
> +	  Choose this option to select drivers for MXS FB devices
> +
> +config DRM_MXSFB
> +	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
> +	depends on DRM && OF
> +	depends on COMMON_CLK
> +	select DRM_MXS
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_FB_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	help
> +	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
> +	  LCD controller.
> +
> +	  If M is selected the module will be called mxsfb.
> diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
> new file mode 100644
> index 0000000..857f3a4
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/Makefile
> @@ -0,0 +1,2 @@
> +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
> +obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> new file mode 100644
> index 0000000..0818903
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> @@ -0,0 +1,241 @@
> +/*
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * This code is based on drivers/video/fbdev/mxsfb.c :
> + * Copyright (C) 2010 Juergen Beisert, Pengutronix
> + * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +#include <linux/clk.h>
> +#include <linux/iopoll.h>
> +#include <linux/of_graph.h>
> +#include <linux/platform_data/simplefb.h>
> +#include <video/videomode.h>
> +
> +#include "mxsfb_drv.h"
> +#include "mxsfb_regs.h"
> +
> +static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
> +{
> +	return (val & mxsfb->devdata->hs_wdth_mask) <<
> +		mxsfb->devdata->hs_wdth_shift;
> +}
> +
> +/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
> +static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
> +{
> +	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
> +	struct drm_device *drm = crtc->dev;
> +	const u32 format = crtc->primary->state->fb->pixel_format;
> +	u32 ctrl, ctrl1;
> +
> +	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
> +
> +	/*
> +	 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
> +	 * match the selected mode here. This differs from the original
> +	 * MXSFB driver, which had the option to configure the bus width
> +	 * to arbitrary value. This limitation should not pose an issue.
> +	 */
> +
> +	/* CTRL1 contains IRQ config and status bits, preserve those. */
> +	ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
> +	ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
> +
> +	switch (format) {
> +	case DRM_FORMAT_RGB565:
> +		dev_dbg(drm->dev, "Setting up RGB565 mode\n");
> +		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
> +		ctrl |= CTRL_SET_WORD_LENGTH(0);
> +		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
> +		break;
> +	case DRM_FORMAT_XRGB8888:
> +		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
> +		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
> +		ctrl |= CTRL_SET_WORD_LENGTH(3);
> +		/* Do not use packed pixels = one pixel per word instead. */
> +		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
> +		break;
> +	default:
> +		dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
> +		return -EINVAL;
> +	}
> +
> +	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
> +	writel(ctrl, mxsfb->base + LCDC_CTRL);
> +
> +	return 0;
> +}
> +
> +static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
> +{
> +	u32 reg;
> +
> +	if (mxsfb->clk_disp_axi)
> +		clk_prepare_enable(mxsfb->clk_disp_axi);
> +	clk_prepare_enable(mxsfb->clk);
> +	mxsfb_enable_axi_clk(mxsfb);
> +
> +	/* If it was disabled, re-enable the mode again */
> +	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
> +
> +	/* Enable the SYNC signals first, then the DMA engine */
> +	reg = readl(mxsfb->base + LCDC_VDCTRL4);
> +	reg |= VDCTRL4_SYNC_SIGNALS_ON;
> +	writel(reg, mxsfb->base + LCDC_VDCTRL4);
> +
> +	writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
> +}
> +
> +static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
> +{
> +	u32 reg;
> +
> +	/*
> +	 * Even if we disable the controller here, it will still continue
> +	 * until its FIFOs are running out of data
> +	 */
> +	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
> +
> +	readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
> +			   0, 1000);
> +
> +	reg = readl(mxsfb->base + LCDC_VDCTRL4);
> +	reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
> +	writel(reg, mxsfb->base + LCDC_VDCTRL4);
> +
> +	mxsfb_disable_axi_clk(mxsfb);
> +
> +	clk_disable_unprepare(mxsfb->clk);
> +	if (mxsfb->clk_disp_axi)
> +		clk_disable_unprepare(mxsfb->clk_disp_axi);
> +}
> +
> +static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
> +{
> +	struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
> +	const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
> +	u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
> +	int err;
> +
> +	/*
> +	 * It seems, you can't re-program the controller if it is still
> +	 * running. This may lead to shifted pictures (FIFO issue?), so
> +	 * first stop the controller and drain its FIFOs.
> +	 */
> +	mxsfb_enable_axi_clk(mxsfb);
> +
> +	/* Clear the FIFOs */
> +	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
> +
> +	err = mxsfb_set_pixel_fmt(mxsfb);
> +	if (err)
> +		return;
> +
> +	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
> +
> +	writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
> +	       TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
> +	       mxsfb->base + mxsfb->devdata->transfer_count);
> +
> +	vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
> +
> +	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* Always in DOTCLOCK mode */
> +		  VDCTRL0_VSYNC_PERIOD_UNIT |
> +		  VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
> +		  VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
> +	if (m->flags & DRM_MODE_FLAG_PHSYNC)
> +		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
> +	if (m->flags & DRM_MODE_FLAG_PVSYNC)
> +		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
> +	if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
> +		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
> +	if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
> +		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
> +
> +	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
> +
> +	/* Frame length in lines. */
> +	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
> +
> +	/* Line length in units of clocks or pixels. */
> +	hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
> +	writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
> +	       VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
> +	       mxsfb->base + LCDC_VDCTRL2);
> +
> +	writel(SET_HOR_WAIT_CNT(m->crtc_hblank_end - m->crtc_hsync_end) |
> +	       SET_VERT_WAIT_CNT(m->crtc_vblank_end - m->crtc_vsync_end),
> +	       mxsfb->base + LCDC_VDCTRL3);
> +
> +	writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
> +	       mxsfb->base + LCDC_VDCTRL4);
> +
> +	mxsfb_disable_axi_clk(mxsfb);
> +}
> +
> +void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
> +{
> +	mxsfb_crtc_mode_set_nofb(mxsfb);
> +	mxsfb_enable_controller(mxsfb);
> +}
> +
> +void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
> +{
> +	mxsfb_disable_controller(mxsfb);
> +}
> +
> +void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
> +			       struct drm_plane_state *state)
> +{
> +	struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
> +	struct drm_crtc *crtc = &pipe->crtc;
> +	struct drm_framebuffer *fb = pipe->plane.state->fb;
> +	struct drm_pending_vblank_event *event;
> +	struct drm_gem_cma_object *gem;
> +
> +	if (!crtc)
> +		return;
> +
> +	spin_lock_irq(&crtc->dev->event_lock);
> +	event = crtc->state->event;
> +	if (event) {
> +		crtc->state->event = NULL;
> +
> +		if (drm_crtc_vblank_get(crtc) == 0) {
> +			drm_crtc_arm_vblank_event(crtc, event);
> +		} else {
> +			drm_crtc_send_vblank_event(crtc, event);
> +		}
> +	}
> +	spin_unlock_irq(&crtc->dev->event_lock);
> +
> +	if (!fb)
> +		return;
> +
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	mxsfb_enable_axi_clk(mxsfb);
> +	writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
> +	mxsfb_disable_axi_clk(mxsfb);
> +}
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> new file mode 100644
> index 0000000..79a18bf
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -0,0 +1,444 @@
> +/*
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * This code is based on drivers/video/fbdev/mxsfb.c :
> + * Copyright (C) 2010 Juergen Beisert, Pengutronix
> + * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/spinlock.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/list.h>
> +#include <linux/of_device.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reservation.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_simple_kms_helper.h>
> +
> +#include "mxsfb_drv.h"
> +#include "mxsfb_regs.h"
> +
> +enum mxsfb_devtype {
> +	MXSFB_V3,
> +	MXSFB_V4,
> +};
> +
> +static const struct mxsfb_devdata mxsfb_devdata[] = {
> +	[MXSFB_V3] = {
> +		.transfer_count	= LCDC_V3_TRANSFER_COUNT,
> +		.cur_buf	= LCDC_V3_CUR_BUF,
> +		.next_buf	= LCDC_V3_NEXT_BUF,
> +		.debug0		= LCDC_V3_DEBUG0,
> +		.hs_wdth_mask	= 0xff,
> +		.hs_wdth_shift	= 24,
> +		.ipversion	= 3,
> +	},
> +	[MXSFB_V4] = {
> +		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
> +		.cur_buf	= LCDC_V4_CUR_BUF,
> +		.next_buf	= LCDC_V4_NEXT_BUF,
> +		.debug0		= LCDC_V4_DEBUG0,
> +		.hs_wdth_mask	= 0x3fff,
> +		.hs_wdth_shift	= 18,
> +		.ipversion	= 4,
> +	},
> +};
> +
> +static const uint32_t mxsfb_formats[] = {
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_RGB565
> +};
> +
> +static struct mxsfb_drm_private *
> +drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
> +{
> +	return container_of(pipe, struct mxsfb_drm_private, pipe);
> +}
> +
> +void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
> +{
> +	if (mxsfb->clk_axi)
> +		clk_prepare_enable(mxsfb->clk_axi);
> +}
> +
> +void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
> +{
> +	if (mxsfb->clk_axi)
> +		clk_disable_unprepare(mxsfb->clk_axi);
> +}
> +
> +static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
> +	.fb_create		= drm_fb_cma_create,
> +	.atomic_check		= drm_atomic_helper_check,
> +	.atomic_commit		= drm_atomic_helper_commit,
> +};
> +
> +static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
> +			      struct drm_crtc_state *crtc_state)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> +
> +	mxsfb_crtc_enable(mxsfb);
> +}
> +
> +static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> +
> +	mxsfb_crtc_disable(mxsfb);
> +}
> +
> +static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
> +			      struct drm_plane_state *plane_state)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
> +
> +	mxsfb_plane_atomic_update(mxsfb, plane_state);
> +}
> +
> +static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
> +				 struct drm_plane_state *plane_state)
> +{
> +	return drm_fb_cma_prepare_fb(&pipe->plane, plane_state);
> +}
> +
> +struct drm_simple_display_pipe_funcs mxsfb_funcs = {
> +	.enable		= mxsfb_pipe_enable,
> +	.disable	= mxsfb_pipe_disable,
> +	.update		= mxsfb_pipe_update,
> +	.prepare_fb	= mxsfb_pipe_prepare_fb,
> +};
> +
> +static int mxsfb_load(struct drm_device *drm, unsigned long flags)
> +{
> +	struct platform_device *pdev = to_platform_device(drm->dev);
> +	struct mxsfb_drm_private *mxsfb;
> +	struct resource *res;
> +	int ret;
> +
> +	mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
> +	if (!mxsfb)
> +		return -ENOMEM;
> +
> +	drm->dev_private = mxsfb;
> +	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mxsfb->base = devm_ioremap_resource(drm->dev, res);
> +	if (IS_ERR(mxsfb->base))
> +		return PTR_ERR(mxsfb->base);
> +
> +	mxsfb->clk = devm_clk_get(drm->dev, NULL);
> +	if (IS_ERR(mxsfb->clk))
> +		return PTR_ERR(mxsfb->clk);
> +
> +	mxsfb->clk_axi = devm_clk_get(drm->dev, "axi");
> +	if (IS_ERR(mxsfb->clk_axi))
> +		mxsfb->clk_axi = NULL;
> +
> +	mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
> +	if (IS_ERR(mxsfb->clk_disp_axi))
> +		mxsfb->clk_disp_axi = NULL;
> +
> +	ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
> +	if (ret)
> +		return ret;
> +
> +	pm_runtime_enable(drm->dev);
> +
> +	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "Failed to initialise vblank\n");
> +		goto err_vblank;
> +	}
> +
> +	/* Modeset init */
> +	drm_mode_config_init(drm);
> +
> +	ret = mxsfb_create_output(drm);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "Failed to create outputs\n");
> +		goto err_vblank;
> +	}
> +
> +	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
> +			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
> +			&mxsfb->connector);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "Cannot setup simple display pipe\n");
> +		goto err_vblank;
> +	}
> +
> +	ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
> +	if (ret) {
> +		dev_err(drm->dev, "Cannot connect panel\n");
> +		goto err_vblank;
> +	}
> +
> +	drm->mode_config.min_width	= MXSFB_MIN_XRES;
> +	drm->mode_config.min_height	= MXSFB_MIN_YRES;
> +	drm->mode_config.max_width	= MXSFB_MAX_XRES;
> +	drm->mode_config.max_height	= MXSFB_MAX_YRES;
> +	drm->mode_config.funcs		= &mxsfb_mode_config_funcs;
> +
> +	drm_mode_config_reset(drm);
> +
> +	pm_runtime_get_sync(drm->dev);
> +	ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
> +	pm_runtime_put_sync(drm->dev);
> +
> +	if (ret < 0) {
> +		dev_err(drm->dev, "Failed to install IRQ handler\n");
> +		goto err_irq;
> +	}
> +
> +	drm_kms_helper_poll_init(drm);
> +
> +	mxsfb->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
> +					  drm->mode_config.num_connector);
> +	if (IS_ERR(mxsfb->fbdev)) {
> +		mxsfb->fbdev = NULL;
> +		dev_err(drm->dev, "Failed to init FB CMA area\n");
> +		goto err_cma;
> +	}
> +
> +	platform_set_drvdata(pdev, drm);
> +
> +	drm_helper_hpd_irq_event(drm);
> +
> +	return 0;
> +
> +err_cma:
> +	drm_irq_uninstall(drm);
> +err_irq:
> +	drm_panel_detach(mxsfb->panel);
> +err_vblank:
> +	pm_runtime_disable(drm->dev);
> +
> +	return ret;
> +}
> +
> +static void mxsfb_unload(struct drm_device *drm)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +
> +	if (mxsfb->fbdev)
> +		drm_fbdev_cma_fini(mxsfb->fbdev);
> +
> +	drm_kms_helper_poll_fini(drm);
> +	drm_mode_config_cleanup(drm);
> +	drm_vblank_cleanup(drm);
> +
> +	pm_runtime_get_sync(drm->dev);
> +	drm_irq_uninstall(drm);
> +	pm_runtime_put_sync(drm->dev);
> +
> +	drm->dev_private = NULL;
> +
> +	pm_runtime_disable(drm->dev);
> +}
> +
> +static void mxsfb_lastclose(struct drm_device *drm)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +
> +	drm_fbdev_cma_restore_mode(mxsfb->fbdev);
> +}
> +
> +static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +
> +	/* Clear and enable VBLANK IRQ */
> +	mxsfb_enable_axi_clk(mxsfb);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
> +	mxsfb_disable_axi_clk(mxsfb);
> +
> +	return 0;
> +}
> +
> +static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +
> +	/* Disable and clear VBLANK IRQ */
> +	mxsfb_enable_axi_clk(mxsfb);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +	mxsfb_disable_axi_clk(mxsfb);
> +}
> +
> +static void mxsfb_irq_preinstall(struct drm_device *drm)
> +{
> +	mxsfb_disable_vblank(drm, 0);
> +}
> +
> +static irqreturn_t mxsfb_irq_handler(int irq, void *data)
> +{
> +	struct drm_device *drm = data;
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +	u32 reg;
> +
> +	mxsfb_enable_axi_clk(mxsfb);
> +
> +	reg = readl(mxsfb->base + LCDC_CTRL1);
> +
> +	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
> +		drm_crtc_handle_vblank(&mxsfb->pipe.crtc);
> +
> +	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
> +
> +	mxsfb_disable_axi_clk(mxsfb);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct file_operations fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= noop_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver mxsfb_driver = {
> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
> +				  DRIVER_PRIME | DRIVER_ATOMIC |
> +				  DRIVER_HAVE_IRQ,
> +	.lastclose		= mxsfb_lastclose,
> +	.irq_handler		= mxsfb_irq_handler,
> +	.irq_preinstall		= mxsfb_irq_preinstall,
> +	.irq_uninstall		= mxsfb_irq_preinstall,
> +	.get_vblank_counter	= drm_vblank_no_hw_counter,
> +	.enable_vblank		= mxsfb_enable_vblank,
> +	.disable_vblank		= mxsfb_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.fops	= &fops,
> +	.name	= "mxsfb-drm",
> +	.desc	= "MXSFB Controller DRM",
> +	.date	= "20160824",
> +	.major	= 1,
> +	.minor	= 0,
> +};
> +
> +static const struct platform_device_id mxsfb_devtype[] = {
> +	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
> +	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
> +	{ .name = "imx6sx-fb", .driver_data = MXSFB_V4, },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
> +
> +static const struct of_device_id mxsfb_dt_ids[] = {
> +	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
> +	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
> +	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
> +
> +static int mxsfb_probe(struct platform_device *pdev)
> +{
> +	struct drm_device *drm;
> +	const struct of_device_id *of_id =
> +			of_match_device(mxsfb_dt_ids, &pdev->dev);
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	if (of_id)
> +		pdev->id_entry = of_id->data;
> +
> +	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
> +	if (!drm)
> +		return -ENOMEM;
> +
> +	ret = mxsfb_load(drm, 0);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = drm_dev_register(drm, 0);
> +	if (ret)
> +		goto err_unload;
> +
> +	return 0;
> +
> +err_unload:
> +	mxsfb_unload(drm);
> +err_free:
> +	drm_dev_unref(drm);
> +
> +	return ret;
> +}
> +
> +static int mxsfb_remove(struct platform_device *pdev)
> +{
> +	struct drm_device *drm = platform_get_drvdata(pdev);
> +
> +	drm_dev_unregister(drm);
> +	mxsfb_unload(drm);
> +	drm_dev_unref(drm);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver mxsfb_platform_driver = {
> +	.probe		= mxsfb_probe,
> +	.remove		= mxsfb_remove,
> +	.id_table	= mxsfb_devtype,
> +	.driver	= {
> +		.name		= "mxsfb",
> +		.of_match_table	= mxsfb_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(mxsfb_platform_driver);
> +
> +MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
> +MODULE_DESCRIPTION("Freescale MXS DRM/KMS driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> new file mode 100644
> index 0000000..5d0883f
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller driver.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MXSFB_DRV_H__
> +#define __MXSFB_DRV_H__
> +
> +struct mxsfb_devdata {
> +	unsigned int	 transfer_count;
> +	unsigned int	 cur_buf;
> +	unsigned int	 next_buf;
> +	unsigned int	 debug0;
> +	unsigned int	 hs_wdth_mask;
> +	unsigned int	 hs_wdth_shift;
> +	unsigned int	 ipversion;
> +};
> +
> +struct mxsfb_drm_private {
> +	const struct mxsfb_devdata	*devdata;
> +
> +	void __iomem			*base;	/* registers */
> +	struct clk			*clk;
> +	struct clk			*clk_axi;
> +	struct clk			*clk_disp_axi;
> +
> +	struct drm_simple_display_pipe	pipe;
> +	struct drm_connector		connector;
> +	struct drm_panel		*panel;
> +	struct drm_fbdev_cma		*fbdev;
> +};
> +
> +int mxsfb_setup_crtc(struct drm_device *dev);
> +int mxsfb_create_output(struct drm_device *dev);
> +
> +void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
> +void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
> +
> +void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
> +void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
> +void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
> +			       struct drm_plane_state *state);
> +
> +#endif /* __MXSFB_DRV_H__ */
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> new file mode 100644
> index 0000000..fa8d173
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> @@ -0,0 +1,131 @@
> +/*
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/of_graph.h>
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "mxsfb_drv.h"
> +
> +static struct mxsfb_drm_private *
> +drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct mxsfb_drm_private, connector);
> +}
> +
> +static int mxsfb_panel_get_modes(struct drm_connector *connector)
> +{
> +	struct mxsfb_drm_private *mxsfb =
> +			drm_connector_to_mxsfb_drm_private(connector);
> +
> +	if (mxsfb->panel)
> +		return mxsfb->panel->funcs->get_modes(mxsfb->panel);
> +
> +	return 0;
> +}
> +
> +static const struct
> +drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
> +	.get_modes = mxsfb_panel_get_modes,
> +};
> +
> +static enum drm_connector_status
> +mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	struct mxsfb_drm_private *mxsfb =
> +			drm_connector_to_mxsfb_drm_private(connector);
> +
> +	if (mxsfb->panel)
> +		return connector_status_connected;
> +
> +	return connector_status_disconnected;
> +}
> +
> +static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
> +{
> +	struct mxsfb_drm_private *mxsfb =
> +			drm_connector_to_mxsfb_drm_private(connector);
> +
> +	if (mxsfb->panel)
> +		drm_panel_detach(mxsfb->panel);
> +
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
> +	.dpms			= drm_atomic_helper_connector_dpms,
> +	.detect			= mxsfb_panel_connector_detect,
> +	.fill_modes		= drm_helper_probe_single_connector_modes,
> +	.destroy		= mxsfb_panel_connector_destroy,
> +	.reset			= drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int mxsfb_attach_endpoint(struct drm_device *drm,
> +				 const struct of_endpoint *ep)
> +{
> +	struct mxsfb_drm_private *mxsfb = drm->dev_private;
> +	struct device_node *np;
> +	struct drm_panel *panel;
> +	int ret = -EPROBE_DEFER;
> +
> +	np = of_graph_get_remote_port_parent(ep->local_node);
> +	panel = of_drm_find_panel(np);
> +	of_node_put(np);
> +
> +	if (!panel)
> +		return -EPROBE_DEFER;
> +
> +	mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
> +	mxsfb->connector.polled = 0;
> +	drm_connector_helper_add(&mxsfb->connector,
> +			&mxsfb_panel_connector_helper_funcs);
> +	ret = drm_connector_init(drm, &mxsfb->connector,
> +				 &mxsfb_panel_connector_funcs,
> +				 DRM_MODE_CONNECTOR_Unknown);
> +	if (!ret)
> +		mxsfb->panel = panel;
> +
> +	return ret;
> +}
> +
> +int mxsfb_create_output(struct drm_device *drm)
> +{
> +	struct device_node *ep_np = NULL;
> +	struct of_endpoint ep;
> +	int ret;
> +
> +	for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
> +		ret = of_graph_parse_endpoint(ep_np, &ep);
> +		if (!ret)
> +			ret = mxsfb_attach_endpoint(drm, &ep);
> +
> +		if (ret) {
> +			of_node_put(ep_np);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> new file mode 100644
> index 0000000..31d62cd
> --- /dev/null
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
> @@ -0,0 +1,114 @@
> +/*
> + * Copyright (C) 2010 Juergen Beisert, Pengutronix
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller driver.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MXSFB_REGS_H__
> +#define __MXSFB_REGS_H__
> +
> +#define REG_SET	4
> +#define REG_CLR	8
> +
> +#define LCDC_CTRL			0x00
> +#define LCDC_CTRL1			0x10
> +#define LCDC_V3_TRANSFER_COUNT		0x20
> +#define LCDC_V4_TRANSFER_COUNT		0x30
> +#define LCDC_V4_CUR_BUF			0x40
> +#define LCDC_V4_NEXT_BUF		0x50
> +#define LCDC_V3_CUR_BUF			0x30
> +#define LCDC_V3_NEXT_BUF		0x40
> +#define LCDC_VDCTRL0			0x70
> +#define LCDC_VDCTRL1			0x80
> +#define LCDC_VDCTRL2			0x90
> +#define LCDC_VDCTRL3			0xa0
> +#define LCDC_VDCTRL4			0xb0
> +#define LCDC_V4_DEBUG0			0x1d0
> +#define LCDC_V3_DEBUG0			0x1f0
> +
> +#define CTRL_SFTRST			(1 << 31)
> +#define CTRL_CLKGATE			(1 << 30)
> +#define CTRL_BYPASS_COUNT		(1 << 19)
> +#define CTRL_VSYNC_MODE			(1 << 18)
> +#define CTRL_DOTCLK_MODE		(1 << 17)
> +#define CTRL_DATA_SELECT		(1 << 16)
> +#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
> +#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
> +#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
> +#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
> +#define CTRL_MASTER			(1 << 5)
> +#define CTRL_DF16			(1 << 3)
> +#define CTRL_DF18			(1 << 2)
> +#define CTRL_DF24			(1 << 1)
> +#define CTRL_RUN			(1 << 0)
> +
> +#define CTRL1_FIFO_CLEAR		(1 << 21)
> +#define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
> +#define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
> +#define CTRL1_CUR_FRAME_DONE_IRQ_EN	(1 << 13)
> +#define CTRL1_CUR_FRAME_DONE_IRQ	(1 << 9)
> +
> +#define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
> +#define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
> +#define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
> +#define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
> +
> +#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
> +#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
> +#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
> +#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
> +#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
> +#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
> +#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
> +#define VDCTRL0_HALF_LINE		(1 << 19)
> +#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
> +#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
> +#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
> +
> +#define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
> +#define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
> +
> +#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
> +#define VDCTRL3_VSYNC_ONLY		(1 << 28)
> +#define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
> +#define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
> +#define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
> +#define GET_VERT_WAIT_CNT(x)		((x) & 0xffff)
> +
> +#define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
> +#define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
> +#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
> +#define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
> +
> +#define DEBUG0_HSYNC			(1 < 26)
> +#define DEBUG0_VSYNC			(1 < 25)
> +
> +#define MXSFB_MIN_XRES			120
> +#define MXSFB_MIN_YRES			120
> +#define MXSFB_MAX_XRES			0xffff
> +#define MXSFB_MAX_YRES			0xffff
> +
> +#define RED 0
> +#define GREEN 1
> +#define BLUE 2
> +#define TRANSP 3
> +
> +#define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
> +#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
> +#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
> +#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
> +
> +#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
> +#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negative edge sampling */
> +
> +#endif /* __MXSFB_REGS_H__ */
> -- 
> 2.10.2
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH V4 1/2] iio: adc: spmi-vadc: Update function for generic voltage conversion
From: Phani A, Rama Krishna @ 2016-11-14 11:47 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	cdevired-sgV2jX0FEOL9JmXXK+q4OQ, smohanad-sgV2jX0FEOL9JmXXK+q4OQ,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ, sivaa-sgV2jX0FEOL9JmXXK+q4OQ,
	knaack.h-Mmb7MZpHnFY, lars-Qo5EllUWu/uELgA04lAiVw,
	pmeerw-jW+XmwGofnusTnJN9+BGXg, Julia.Lawall-L2FTfq7BK8M
In-Reply-To: <38428ee7-5d1b-2b36-99a9-988e0e7d29b5-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Hi Jonathan,

On 12-Nov-16 8:43 PM, Jonathan Cameron wrote:
> On 08/11/16 11:58, Rama Krishna Phani A wrote:
>> Several channels are supported in ADC of PMIC which can be used to
>> measure voltage, temperature, current etc. Hardware provides
>> readings for all channels in adc code. That adc code needs to be
>> converted to voltage. Logic for conversion of adc code to voltage
>> is common for all ADC channels(voltage, temperature, current etc).
>> Implement separate function for generic conversion logic.
>>
>> Signed-off-by: Rama Krishna Phani A <rphani-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Looks good to me. Kind of the best we can do with minimal
> ABI changes.
>
> I had applied this but have now backed out to wait for patch 2.
>> ---
>>  drivers/iio/adc/qcom-spmi-vadc.c | 52 +++++++++++++++++++++-------------------
>>  1 file changed, 28 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
>> index c2babe5..93c0639 100644
>> --- a/drivers/iio/adc/qcom-spmi-vadc.c
>> +++ b/drivers/iio/adc/qcom-spmi-vadc.c
>> @@ -1,5 +1,5 @@
>>  /*
>> - * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License version 2 and
>> @@ -468,27 +468,38 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>>  	return ret;
>>  }
>>
>> -static s32 vadc_calibrate(struct vadc_priv *vadc,
>> -			  const struct vadc_channel_prop *prop, u16 adc_code)
>> +static void vadc_scale_calib(struct vadc_priv *vadc, u16 adc_code,
>> +			     const struct vadc_channel_prop *prop,
>> +			     s64 *scale_voltage)
>>  {
>> -	const struct vadc_prescale_ratio *prescale;
>> -	s64 voltage;
>> +	*scale_voltage = (adc_code -
>> +		vadc->graph[prop->calibration].gnd);
>> +	*scale_voltage *= vadc->graph[prop->calibration].dx;
>> +	*scale_voltage = div64_s64(*scale_voltage,
>> +		vadc->graph[prop->calibration].dy);
>> +	if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> +		*scale_voltage +=
>> +		vadc->graph[prop->calibration].dx;
>>
>> -	voltage = adc_code - vadc->graph[prop->calibration].gnd;
>> -	voltage *= vadc->graph[prop->calibration].dx;
>> -	voltage = div64_s64(voltage, vadc->graph[prop->calibration].dy);
>> +	if (*scale_voltage < 0)
>> +		*scale_voltage = 0;
>> +}
>>
>> -	if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> -		voltage += vadc->graph[prop->calibration].dx;
>> +static int vadc_scale_volt(struct vadc_priv *vadc,
>> +			   const struct vadc_channel_prop *prop, u16 adc_code,
>> +			   int *result_uv)
>> +{
>> +	const struct vadc_prescale_ratio *prescale;
>> +	s64 voltage = 0, result = 0;
>>
>> -	if (voltage < 0)
>> -		voltage = 0;
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>>
>>  	prescale = &vadc_prescale_ratios[prop->prescale];
>> -
>>  	voltage = voltage * prescale->den;
>> +	result = div64_s64(voltage, prescale->num);
>> +	*result_uv = result;
>>
>> -	return div64_s64(voltage, prescale->num);
>> +	return 0;
>>  }
>>
>>  static int vadc_decimation_from_dt(u32 value)
>> @@ -552,11 +563,8 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>>  		if (ret)
>>  			break;
>>
>> -		*val = vadc_calibrate(vadc, prop, adc_code);
>> +		vadc_scale_volt(vadc, prop, adc_code, val);
>>
>> -		/* 2mV/K, return milli Celsius */
>> -		*val /= 2;
>> -		*val -= KELVINMIL_CELSIUSMIL;
>>  		return IIO_VAL_INT;
>>  	case IIO_CHAN_INFO_RAW:
>>  		prop = &vadc->chan_props[chan->address];
>> @@ -564,12 +572,8 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>>  		if (ret)
>>  			break;
>>
>> -		*val = vadc_calibrate(vadc, prop, adc_code);
>> +		*val = (int)adc_code;
>>  		return IIO_VAL_INT;
>> -	case IIO_CHAN_INFO_SCALE:
>> -		*val = 0;
>> -		*val2 = 1000;
>> -		return IIO_VAL_INT_PLUS_MICRO;
>>  	default:
>>  		ret = -EINVAL;
>>  		break;
>> @@ -617,7 +621,7 @@ struct vadc_channels {
>>
>>  #define VADC_CHAN_VOLT(_dname, _pre)					\
>>  	VADC_CHAN(_dname, IIO_VOLTAGE,					\
>> -		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),	\
>> +		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
>>  		  _pre)							\
> This is still odd, but I guess justifiable from the point of view
> of maintaining backwards compatibility.  The scale was simply wrong
> so not much we can do about that other than drop it!
ok., Will retain "IIO_CHAN_INFO_SCALE" to maintain backward 
compatibility and include support for "IIO_CHAN_INFO_PROCESSED" as well 
in the next patch.
>>
>>  /*
>>
>
Thanks,
Ramakrishna

^ permalink raw reply

* Re: [Intel-gfx] [PATCH 0/4] Compact userptr object backing store allocation
From: Tvrtko Ursulin @ 2016-11-14 11:45 UTC (permalink / raw)
  To: Tvrtko Ursulin, Intel-gfx, Andrew Morton; +Cc: linux-kernel
In-Reply-To: <1478854220-3255-1-git-send-email-tvrtko.ursulin@linux.intel.com>


Hi Andrew,

On 11/11/2016 08:50, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>
> Userptr backing store with SWIOTBL active is currently allocated in the same
> inefficient manner, with one sg entry per object page, as what the commit
> 871dfbd67d4e ("drm/i915: Allow compaction upto SWIOTLB max segment size") fixed
> for regular GEM objects.
>
> We can fix that by adding new a __sg_alloc_table_from_pages core function which
> allows us to control the maximum desired coalesced segment size.
>
> Other than that the series starts with two simple fixes to
> sg_alloc_table_from_pages which deal with incorrect data type usage and a
> theoretical overflow condition. Fixing the latter enables easy addition of the
> above mentioned __sg_alloc_table_from_pages.
>
> Tvrtko Ursulin (4):
>   lib/scatterlist: Fix offset type in sg_alloc_table_from_pages
>   lib/scatterlist: Avoid potential scatterlist entry overflow
>   lib/scatterlist: Introduce and export __sg_alloc_table_from_pages
>   drm/i915: Use __sg_alloc_table_from_pages for userptr allocations
>
>  drivers/gpu/drm/i915/i915_drv.h                |  9 +++
>  drivers/gpu/drm/i915/i915_gem.c                | 15 +----
>  drivers/gpu/drm/i915/i915_gem_userptr.c        | 28 ++-------
>  drivers/media/v4l2-core/videobuf2-dma-contig.c |  4 +-
>  drivers/rapidio/devices/rio_mport_cdev.c       |  4 +-
>  include/linux/scatterlist.h                    | 11 ++--
>  lib/scatterlist.c                              | 78 ++++++++++++++++++++------
>  7 files changed, 87 insertions(+), 62 deletions(-)

I have three patches to lib/scatterlist.c in this series which has all 
been reviewed and tested.

We would like to merge them via the DRM tree if there are no objections?

Kind regards,

Tvrtko

^ permalink raw reply

* Re: [PATCH 0/4] Compact userptr object backing store allocation
From: Tvrtko Ursulin @ 2016-11-14 11:45 UTC (permalink / raw)
  To: Tvrtko Ursulin, Intel-gfx, Andrew Morton; +Cc: linux-kernel
In-Reply-To: <1478854220-3255-1-git-send-email-tvrtko.ursulin@linux.intel.com>


Hi Andrew,

On 11/11/2016 08:50, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>
> Userptr backing store with SWIOTBL active is currently allocated in the same
> inefficient manner, with one sg entry per object page, as what the commit
> 871dfbd67d4e ("drm/i915: Allow compaction upto SWIOTLB max segment size") fixed
> for regular GEM objects.
>
> We can fix that by adding new a __sg_alloc_table_from_pages core function which
> allows us to control the maximum desired coalesced segment size.
>
> Other than that the series starts with two simple fixes to
> sg_alloc_table_from_pages which deal with incorrect data type usage and a
> theoretical overflow condition. Fixing the latter enables easy addition of the
> above mentioned __sg_alloc_table_from_pages.
>
> Tvrtko Ursulin (4):
>   lib/scatterlist: Fix offset type in sg_alloc_table_from_pages
>   lib/scatterlist: Avoid potential scatterlist entry overflow
>   lib/scatterlist: Introduce and export __sg_alloc_table_from_pages
>   drm/i915: Use __sg_alloc_table_from_pages for userptr allocations
>
>  drivers/gpu/drm/i915/i915_drv.h                |  9 +++
>  drivers/gpu/drm/i915/i915_gem.c                | 15 +----
>  drivers/gpu/drm/i915/i915_gem_userptr.c        | 28 ++-------
>  drivers/media/v4l2-core/videobuf2-dma-contig.c |  4 +-
>  drivers/rapidio/devices/rio_mport_cdev.c       |  4 +-
>  include/linux/scatterlist.h                    | 11 ++--
>  lib/scatterlist.c                              | 78 ++++++++++++++++++++------
>  7 files changed, 87 insertions(+), 62 deletions(-)

I have three patches to lib/scatterlist.c in this series which has all 
been reviewed and tested.

We would like to merge them via the DRM tree if there are no objections?

Kind regards,

Tvrtko


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH v2 05/12] mm: thp: add core routines for thp/pmd migration
From: Kirill A. Shutemov @ 2016-11-14 11:45 UTC (permalink / raw)
  To: Naoya Horiguchi
  Cc: linux-mm, Kirill A. Shutemov, Hugh Dickins, Andrew Morton,
	Dave Hansen, Andrea Arcangeli, Mel Gorman, Michal Hocko,
	Vlastimil Babka, Pavel Emelyanov, Zi Yan, Balbir Singh,
	linux-kernel, Naoya Horiguchi
In-Reply-To: <1478561517-4317-6-git-send-email-n-horiguchi@ah.jp.nec.com>

On Tue, Nov 08, 2016 at 08:31:50AM +0900, Naoya Horiguchi wrote:
> This patch prepares thp migration's core code. These code will be open when
> unmap_and_move() stops unconditionally splitting thp and get_new_page() starts
> to allocate destination thps.
> 
> Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
> ---
> ChangeLog v1 -> v2:
> - support pte-mapped thp, doubly-mapped thp
> ---
>  arch/x86/include/asm/pgtable_64.h |   2 +
>  include/linux/swapops.h           |  61 +++++++++++++++
>  mm/huge_memory.c                  | 154 ++++++++++++++++++++++++++++++++++++++
>  mm/migrate.c                      |  44 ++++++++++-
>  mm/pgtable-generic.c              |   3 +-
>  5 files changed, 262 insertions(+), 2 deletions(-)
> 
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/arch/x86/include/asm/pgtable_64.h v4.9-rc2-mmotm-2016-10-27-18-27_patched/arch/x86/include/asm/pgtable_64.h
> index 1cc82ec..3a1b48e 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/arch/x86/include/asm/pgtable_64.h
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/arch/x86/include/asm/pgtable_64.h
> @@ -167,7 +167,9 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
>  					 ((type) << (SWP_TYPE_FIRST_BIT)) \
>  					 | ((offset) << SWP_OFFSET_FIRST_BIT) })
>  #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val((pte)) })
> +#define __pmd_to_swp_entry(pte)		((swp_entry_t) { pmd_val((pmd)) })
>  #define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
> +#define __swp_entry_to_pmd(x)		((pmd_t) { .pmd = (x).val })
>  
>  extern int kern_addr_valid(unsigned long addr);
>  extern void cleanup_highmap(void);
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/include/linux/swapops.h v4.9-rc2-mmotm-2016-10-27-18-27_patched/include/linux/swapops.h
> index 5c3a5f3..b6b22a2 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/include/linux/swapops.h
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/include/linux/swapops.h
> @@ -163,6 +163,67 @@ static inline int is_write_migration_entry(swp_entry_t entry)
>  
>  #endif
>  
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +extern void set_pmd_migration_entry(struct page *page,
> +		struct vm_area_struct *vma, unsigned long address);
> +
> +extern int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old);
> +
> +extern void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd);
> +
> +static inline swp_entry_t pmd_to_swp_entry(pmd_t pmd)
> +{
> +	swp_entry_t arch_entry;
> +
> +	arch_entry = __pmd_to_swp_entry(pmd);
> +	return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry));
> +}
> +
> +static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)
> +{
> +	swp_entry_t arch_entry;
> +
> +	arch_entry = __swp_entry(swp_type(entry), swp_offset(entry));
> +	return __swp_entry_to_pmd(arch_entry);
> +}
> +
> +static inline int is_pmd_migration_entry(pmd_t pmd)
> +{
> +	return !pmd_present(pmd) && is_migration_entry(pmd_to_swp_entry(pmd));
> +}
> +#else
> +static inline void set_pmd_migration_entry(struct page *page,
> +			struct vm_area_struct *vma, unsigned long address)
> +{

VM_BUG()? Or BUILD_BUG()?

> +}
> +
> +static inline int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old)
> +{
> +	return 0;

Ditto.

> +}
> +
> +static inline void pmd_migration_entry_wait(struct mm_struct *m, pmd_t *p) { }
> +
> +static inline swp_entry_t pmd_to_swp_entry(pmd_t pmd)
> +{
> +	return swp_entry(0, 0);

Ditto.

> +}
> +
> +static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)
> +{
> +	pmd_t pmd = {};

Ditto.

> +	return pmd;
> +}
> +
> +static inline int is_pmd_migration_entry(pmd_t pmd)
> +{
> +	return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_MEMORY_FAILURE
>  
>  extern atomic_long_t num_poisoned_pages __read_mostly;
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/huge_memory.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/huge_memory.c
> index 0509d17..b3022b3 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/huge_memory.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/huge_memory.c
> @@ -2310,3 +2310,157 @@ static int __init split_huge_pages_debugfs(void)
>  }
>  late_initcall(split_huge_pages_debugfs);
>  #endif
> +
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +void set_pmd_migration_entry(struct page *page, struct vm_area_struct *vma,
> +				unsigned long addr)
> +{
> +	struct mm_struct *mm = vma->vm_mm;
> +	pgd_t *pgd;
> +	pud_t *pud;
> +	pmd_t *pmd;
> +	pmd_t pmdval;
> +	swp_entry_t entry;
> +	spinlock_t *ptl;
> +
> +	pgd = pgd_offset(mm, addr);
> +	if (!pgd_present(*pgd))
> +		return;
> +	pud = pud_offset(pgd, addr);
> +	if (!pud_present(*pud))
> +		return;
> +	pmd = pmd_offset(pud, addr);
> +	pmdval = *pmd;
> +	barrier();
> +	if (!pmd_present(pmdval))
> +		return;
> +
> +	mmu_notifier_invalidate_range_start(mm, addr, addr + HPAGE_PMD_SIZE);
> +	if (pmd_trans_huge(pmdval)) {
> +		pmd_t pmdswp;
> +
> +		ptl = pmd_lock(mm, pmd);
> +		if (!pmd_present(*pmd))
> +			goto unlock_pmd;
> +		if (unlikely(!pmd_trans_huge(*pmd)))
> +			goto unlock_pmd;

Just check *pmd == pmdval?

> +		if (pmd_page(*pmd) != page)
> +			goto unlock_pmd;
> +
> +		pmdval = pmdp_huge_get_and_clear(mm, addr, pmd);
> +		if (pmd_dirty(pmdval))
> +			set_page_dirty(page);
> +		entry = make_migration_entry(page, pmd_write(pmdval));
> +		pmdswp = swp_entry_to_pmd(entry);
> +		pmdswp = pmd_mkhuge(pmdswp);
> +		set_pmd_at(mm, addr, pmd, pmdswp);
> +		page_remove_rmap(page, true);
> +		put_page(page);
> +unlock_pmd:
> +		spin_unlock(ptl);
> +	} else { /* pte-mapped thp */
> +		pte_t *pte;
> +		pte_t pteval;
> +		struct page *tmp = compound_head(page);
> +		unsigned long address = addr & HPAGE_PMD_MASK;
> +		pte_t swp_pte;
> +		int i;
> +
> +		pte = pte_offset_map(pmd, address);
> +		ptl = pte_lockptr(mm, pmd);
> +		spin_lock(ptl);

pte_offset_map_lock() ?

> +		for (i = 0; i < HPAGE_PMD_NR; i++, pte++, tmp++) {
> +			if (!(pte_present(*pte) &&
> +			      page_to_pfn(tmp) == pte_pfn(*pte)))

			if (!pte_present(*pte) || pte_page(*pte) != tmp) ?

> +				continue;
> +			pteval = ptep_clear_flush(vma, address, pte);
> +			if (pte_dirty(pteval))
> +				set_page_dirty(tmp);
> +			entry = make_migration_entry(tmp, pte_write(pteval));
> +			swp_pte = swp_entry_to_pte(entry);
> +			set_pte_at(mm, address, pte, swp_pte);
> +			page_remove_rmap(tmp, false);
> +			put_page(tmp);
> +		}
> +		pte_unmap_unlock(pte, ptl);
> +	}
> +	mmu_notifier_invalidate_range_end(mm, addr, addr + HPAGE_PMD_SIZE);
> +	return;
> +}
> +
> +int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old)
> +{
> +	struct mm_struct *mm = vma->vm_mm;
> +	spinlock_t *ptl;
> +	pmd_t pmde;
> +	swp_entry_t entry;
> +
> +	pmde = *pmd;
> +	barrier();
> +
> +	if (!pmd_present(pmde)) {
> +		if (is_migration_entry(pmd_to_swp_entry(pmde))) {

		if (!is_migration_entry(pmd_to_swp_entry(pmde)))
			return SWAP_AGAIN;

And one level less indentation below.

> +			unsigned long mmun_start = addr & HPAGE_PMD_MASK;
> +			unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
> +
> +			ptl = pmd_lock(mm, pmd);
> +			entry = pmd_to_swp_entry(*pmd);
> +			if (migration_entry_to_page(entry) != old)
> +				goto unlock_ptl;
> +			get_page(new);
> +			pmde = pmd_mkold(mk_huge_pmd(new, vma->vm_page_prot));
> +			if (is_write_migration_entry(entry))
> +				pmde = maybe_pmd_mkwrite(pmde, vma);
> +			flush_cache_range(vma, mmun_start, mmun_end);
> +			page_add_anon_rmap(new, vma, mmun_start, true);
> +			pmdp_huge_clear_flush_notify(vma, mmun_start, pmd);
> +			set_pmd_at(mm, mmun_start, pmd, pmde);
> +			flush_tlb_range(vma, mmun_start, mmun_end);
> +			if (vma->vm_flags & VM_LOCKED)
> +				mlock_vma_page(new);
> +			update_mmu_cache_pmd(vma, addr, pmd);
> +unlock_ptl:
> +			spin_unlock(ptl);

			return SWAP_AGAIN;

And one level less indentation below.

> +		}
> +	} else { /* pte-mapped thp */
> +		pte_t *ptep;
> +		pte_t pte;
> +		int i;
> +		struct page *tmpnew = compound_head(new);
> +		struct page *tmpold = compound_head((struct page *)old);
> +		unsigned long address = addr & HPAGE_PMD_MASK;
> +
> +		ptep = pte_offset_map(pmd, addr);
> +		ptl = pte_lockptr(mm, pmd);
> +		spin_lock(ptl);

pte_offset_map_lock() ?

> +
> +		for (i = 0; i < HPAGE_PMD_NR;
> +		     i++, ptep++, tmpnew++, tmpold++, address += PAGE_SIZE) {
> +			pte = *ptep;
> +			if (!is_swap_pte(pte))
> +				continue;
> +			entry = pte_to_swp_entry(pte);
> +			if (!is_migration_entry(entry) ||
> +			    migration_entry_to_page(entry) != tmpold)
> +				continue;
> +			get_page(tmpnew);
> +			pte = pte_mkold(mk_pte(tmpnew,
> +					       READ_ONCE(vma->vm_page_prot)));

READ_ONCE()? Do we get here under mmap_sem, right?

> +			if (pte_swp_soft_dirty(*ptep))
> +				pte = pte_mksoft_dirty(pte);
> +			if (is_write_migration_entry(entry))
> +				pte = maybe_mkwrite(pte, vma);
> +			flush_dcache_page(tmpnew);
> +			set_pte_at(mm, address, ptep, pte);
> +			if (PageAnon(new))
> +				page_add_anon_rmap(tmpnew, vma, address, false);
> +			else
> +				page_add_file_rmap(tmpnew, false);
> +			update_mmu_cache(vma, address, ptep);
> +		}
> +		pte_unmap_unlock(ptep, ptl);
> +	}
> +	return SWAP_AGAIN;
> +}
> +#endif
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/migrate.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/migrate.c
> index 66ce6b4..54f2eb6 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/migrate.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/migrate.c
> @@ -198,6 +198,8 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
>  {
>  	struct mm_struct *mm = vma->vm_mm;
>  	swp_entry_t entry;
> +	pgd_t *pgd;
> +	pud_t *pud;
>   	pmd_t *pmd;
>  	pte_t *ptep, pte;
>   	spinlock_t *ptl;
> @@ -208,10 +210,29 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
>  			goto out;
>  		ptl = huge_pte_lockptr(hstate_vma(vma), mm, ptep);
>  	} else {
> -		pmd = mm_find_pmd(mm, addr);
> +		pmd_t pmde;
> +
> +		pgd = pgd_offset(mm, addr);
> +		if (!pgd_present(*pgd))
> +			goto out;
> +		pud = pud_offset(pgd, addr);
> +		if (!pud_present(*pud))
> +			goto out;
> +		pmd = pmd_offset(pud, addr);
>  		if (!pmd)
>  			goto out;
>  
> +		if (PageTransCompound(new)) {
> +			remove_migration_pmd(new, pmd, vma, addr, old);
> +			goto out;
> +		}
> +
> +		pmde = *pmd;
> +		barrier();
> +
> +		if (!pmd_present(pmde) || pmd_trans_huge(pmde))
> +			goto out;
> +
>  		ptep = pte_offset_map(pmd, addr);
>  
>  		/*
> @@ -344,6 +365,27 @@ void migration_entry_wait_huge(struct vm_area_struct *vma,
>  	__migration_entry_wait(mm, pte, ptl);
>  }
>  
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)
> +{
> +	spinlock_t *ptl;
> +	struct page *page;
> +
> +	ptl = pmd_lock(mm, pmd);
> +	if (!is_pmd_migration_entry(*pmd))
> +		goto unlock;
> +	page = migration_entry_to_page(pmd_to_swp_entry(*pmd));
> +	if (!get_page_unless_zero(page))
> +		goto unlock;
> +	spin_unlock(ptl);
> +	wait_on_page_locked(page);
> +	put_page(page);
> +	return;
> +unlock:
> +	spin_unlock(ptl);
> +}
> +#endif
> +
>  #ifdef CONFIG_BLOCK
>  /* Returns true if all buffers are successfully locked */
>  static bool buffer_migrate_lock_buffers(struct buffer_head *head,
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/pgtable-generic.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/pgtable-generic.c
> index 71c5f91..6012343 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/pgtable-generic.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/pgtable-generic.c
> @@ -118,7 +118,8 @@ pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address,
>  {
>  	pmd_t pmd;
>  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
> -	VM_BUG_ON(!pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp));
> +	VM_BUG_ON(pmd_present(*pmdp) && !pmd_trans_huge(*pmdp) &&
> +		  !pmd_devmap(*pmdp));
>  	pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
>  	flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
>  	return pmd;
> -- 
> 2.7.0
> 

-- 
 Kirill A. Shutemov

^ permalink raw reply

* Re: [PATCH v2 05/12] mm: thp: add core routines for thp/pmd migration
From: Kirill A. Shutemov @ 2016-11-14 11:45 UTC (permalink / raw)
  To: Naoya Horiguchi
  Cc: linux-mm, Kirill A. Shutemov, Hugh Dickins, Andrew Morton,
	Dave Hansen, Andrea Arcangeli, Mel Gorman, Michal Hocko,
	Vlastimil Babka, Pavel Emelyanov, Zi Yan, Balbir Singh,
	linux-kernel, Naoya Horiguchi
In-Reply-To: <1478561517-4317-6-git-send-email-n-horiguchi@ah.jp.nec.com>

On Tue, Nov 08, 2016 at 08:31:50AM +0900, Naoya Horiguchi wrote:
> This patch prepares thp migration's core code. These code will be open when
> unmap_and_move() stops unconditionally splitting thp and get_new_page() starts
> to allocate destination thps.
> 
> Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
> ---
> ChangeLog v1 -> v2:
> - support pte-mapped thp, doubly-mapped thp
> ---
>  arch/x86/include/asm/pgtable_64.h |   2 +
>  include/linux/swapops.h           |  61 +++++++++++++++
>  mm/huge_memory.c                  | 154 ++++++++++++++++++++++++++++++++++++++
>  mm/migrate.c                      |  44 ++++++++++-
>  mm/pgtable-generic.c              |   3 +-
>  5 files changed, 262 insertions(+), 2 deletions(-)
> 
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/arch/x86/include/asm/pgtable_64.h v4.9-rc2-mmotm-2016-10-27-18-27_patched/arch/x86/include/asm/pgtable_64.h
> index 1cc82ec..3a1b48e 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/arch/x86/include/asm/pgtable_64.h
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/arch/x86/include/asm/pgtable_64.h
> @@ -167,7 +167,9 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
>  					 ((type) << (SWP_TYPE_FIRST_BIT)) \
>  					 | ((offset) << SWP_OFFSET_FIRST_BIT) })
>  #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val((pte)) })
> +#define __pmd_to_swp_entry(pte)		((swp_entry_t) { pmd_val((pmd)) })
>  #define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
> +#define __swp_entry_to_pmd(x)		((pmd_t) { .pmd = (x).val })
>  
>  extern int kern_addr_valid(unsigned long addr);
>  extern void cleanup_highmap(void);
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/include/linux/swapops.h v4.9-rc2-mmotm-2016-10-27-18-27_patched/include/linux/swapops.h
> index 5c3a5f3..b6b22a2 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/include/linux/swapops.h
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/include/linux/swapops.h
> @@ -163,6 +163,67 @@ static inline int is_write_migration_entry(swp_entry_t entry)
>  
>  #endif
>  
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +extern void set_pmd_migration_entry(struct page *page,
> +		struct vm_area_struct *vma, unsigned long address);
> +
> +extern int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old);
> +
> +extern void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd);
> +
> +static inline swp_entry_t pmd_to_swp_entry(pmd_t pmd)
> +{
> +	swp_entry_t arch_entry;
> +
> +	arch_entry = __pmd_to_swp_entry(pmd);
> +	return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry));
> +}
> +
> +static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)
> +{
> +	swp_entry_t arch_entry;
> +
> +	arch_entry = __swp_entry(swp_type(entry), swp_offset(entry));
> +	return __swp_entry_to_pmd(arch_entry);
> +}
> +
> +static inline int is_pmd_migration_entry(pmd_t pmd)
> +{
> +	return !pmd_present(pmd) && is_migration_entry(pmd_to_swp_entry(pmd));
> +}
> +#else
> +static inline void set_pmd_migration_entry(struct page *page,
> +			struct vm_area_struct *vma, unsigned long address)
> +{

VM_BUG()? Or BUILD_BUG()?

> +}
> +
> +static inline int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old)
> +{
> +	return 0;

Ditto.

> +}
> +
> +static inline void pmd_migration_entry_wait(struct mm_struct *m, pmd_t *p) { }
> +
> +static inline swp_entry_t pmd_to_swp_entry(pmd_t pmd)
> +{
> +	return swp_entry(0, 0);

Ditto.

> +}
> +
> +static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)
> +{
> +	pmd_t pmd = {};

Ditto.

> +	return pmd;
> +}
> +
> +static inline int is_pmd_migration_entry(pmd_t pmd)
> +{
> +	return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_MEMORY_FAILURE
>  
>  extern atomic_long_t num_poisoned_pages __read_mostly;
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/huge_memory.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/huge_memory.c
> index 0509d17..b3022b3 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/huge_memory.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/huge_memory.c
> @@ -2310,3 +2310,157 @@ static int __init split_huge_pages_debugfs(void)
>  }
>  late_initcall(split_huge_pages_debugfs);
>  #endif
> +
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +void set_pmd_migration_entry(struct page *page, struct vm_area_struct *vma,
> +				unsigned long addr)
> +{
> +	struct mm_struct *mm = vma->vm_mm;
> +	pgd_t *pgd;
> +	pud_t *pud;
> +	pmd_t *pmd;
> +	pmd_t pmdval;
> +	swp_entry_t entry;
> +	spinlock_t *ptl;
> +
> +	pgd = pgd_offset(mm, addr);
> +	if (!pgd_present(*pgd))
> +		return;
> +	pud = pud_offset(pgd, addr);
> +	if (!pud_present(*pud))
> +		return;
> +	pmd = pmd_offset(pud, addr);
> +	pmdval = *pmd;
> +	barrier();
> +	if (!pmd_present(pmdval))
> +		return;
> +
> +	mmu_notifier_invalidate_range_start(mm, addr, addr + HPAGE_PMD_SIZE);
> +	if (pmd_trans_huge(pmdval)) {
> +		pmd_t pmdswp;
> +
> +		ptl = pmd_lock(mm, pmd);
> +		if (!pmd_present(*pmd))
> +			goto unlock_pmd;
> +		if (unlikely(!pmd_trans_huge(*pmd)))
> +			goto unlock_pmd;

Just check *pmd == pmdval?

> +		if (pmd_page(*pmd) != page)
> +			goto unlock_pmd;
> +
> +		pmdval = pmdp_huge_get_and_clear(mm, addr, pmd);
> +		if (pmd_dirty(pmdval))
> +			set_page_dirty(page);
> +		entry = make_migration_entry(page, pmd_write(pmdval));
> +		pmdswp = swp_entry_to_pmd(entry);
> +		pmdswp = pmd_mkhuge(pmdswp);
> +		set_pmd_at(mm, addr, pmd, pmdswp);
> +		page_remove_rmap(page, true);
> +		put_page(page);
> +unlock_pmd:
> +		spin_unlock(ptl);
> +	} else { /* pte-mapped thp */
> +		pte_t *pte;
> +		pte_t pteval;
> +		struct page *tmp = compound_head(page);
> +		unsigned long address = addr & HPAGE_PMD_MASK;
> +		pte_t swp_pte;
> +		int i;
> +
> +		pte = pte_offset_map(pmd, address);
> +		ptl = pte_lockptr(mm, pmd);
> +		spin_lock(ptl);

pte_offset_map_lock() ?

> +		for (i = 0; i < HPAGE_PMD_NR; i++, pte++, tmp++) {
> +			if (!(pte_present(*pte) &&
> +			      page_to_pfn(tmp) == pte_pfn(*pte)))

			if (!pte_present(*pte) || pte_page(*pte) != tmp) ?

> +				continue;
> +			pteval = ptep_clear_flush(vma, address, pte);
> +			if (pte_dirty(pteval))
> +				set_page_dirty(tmp);
> +			entry = make_migration_entry(tmp, pte_write(pteval));
> +			swp_pte = swp_entry_to_pte(entry);
> +			set_pte_at(mm, address, pte, swp_pte);
> +			page_remove_rmap(tmp, false);
> +			put_page(tmp);
> +		}
> +		pte_unmap_unlock(pte, ptl);
> +	}
> +	mmu_notifier_invalidate_range_end(mm, addr, addr + HPAGE_PMD_SIZE);
> +	return;
> +}
> +
> +int remove_migration_pmd(struct page *new, pmd_t *pmd,
> +		struct vm_area_struct *vma, unsigned long addr, void *old)
> +{
> +	struct mm_struct *mm = vma->vm_mm;
> +	spinlock_t *ptl;
> +	pmd_t pmde;
> +	swp_entry_t entry;
> +
> +	pmde = *pmd;
> +	barrier();
> +
> +	if (!pmd_present(pmde)) {
> +		if (is_migration_entry(pmd_to_swp_entry(pmde))) {

		if (!is_migration_entry(pmd_to_swp_entry(pmde)))
			return SWAP_AGAIN;

And one level less indentation below.

> +			unsigned long mmun_start = addr & HPAGE_PMD_MASK;
> +			unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
> +
> +			ptl = pmd_lock(mm, pmd);
> +			entry = pmd_to_swp_entry(*pmd);
> +			if (migration_entry_to_page(entry) != old)
> +				goto unlock_ptl;
> +			get_page(new);
> +			pmde = pmd_mkold(mk_huge_pmd(new, vma->vm_page_prot));
> +			if (is_write_migration_entry(entry))
> +				pmde = maybe_pmd_mkwrite(pmde, vma);
> +			flush_cache_range(vma, mmun_start, mmun_end);
> +			page_add_anon_rmap(new, vma, mmun_start, true);
> +			pmdp_huge_clear_flush_notify(vma, mmun_start, pmd);
> +			set_pmd_at(mm, mmun_start, pmd, pmde);
> +			flush_tlb_range(vma, mmun_start, mmun_end);
> +			if (vma->vm_flags & VM_LOCKED)
> +				mlock_vma_page(new);
> +			update_mmu_cache_pmd(vma, addr, pmd);
> +unlock_ptl:
> +			spin_unlock(ptl);

			return SWAP_AGAIN;

And one level less indentation below.

> +		}
> +	} else { /* pte-mapped thp */
> +		pte_t *ptep;
> +		pte_t pte;
> +		int i;
> +		struct page *tmpnew = compound_head(new);
> +		struct page *tmpold = compound_head((struct page *)old);
> +		unsigned long address = addr & HPAGE_PMD_MASK;
> +
> +		ptep = pte_offset_map(pmd, addr);
> +		ptl = pte_lockptr(mm, pmd);
> +		spin_lock(ptl);

pte_offset_map_lock() ?

> +
> +		for (i = 0; i < HPAGE_PMD_NR;
> +		     i++, ptep++, tmpnew++, tmpold++, address += PAGE_SIZE) {
> +			pte = *ptep;
> +			if (!is_swap_pte(pte))
> +				continue;
> +			entry = pte_to_swp_entry(pte);
> +			if (!is_migration_entry(entry) ||
> +			    migration_entry_to_page(entry) != tmpold)
> +				continue;
> +			get_page(tmpnew);
> +			pte = pte_mkold(mk_pte(tmpnew,
> +					       READ_ONCE(vma->vm_page_prot)));

READ_ONCE()? Do we get here under mmap_sem, right?

> +			if (pte_swp_soft_dirty(*ptep))
> +				pte = pte_mksoft_dirty(pte);
> +			if (is_write_migration_entry(entry))
> +				pte = maybe_mkwrite(pte, vma);
> +			flush_dcache_page(tmpnew);
> +			set_pte_at(mm, address, ptep, pte);
> +			if (PageAnon(new))
> +				page_add_anon_rmap(tmpnew, vma, address, false);
> +			else
> +				page_add_file_rmap(tmpnew, false);
> +			update_mmu_cache(vma, address, ptep);
> +		}
> +		pte_unmap_unlock(ptep, ptl);
> +	}
> +	return SWAP_AGAIN;
> +}
> +#endif
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/migrate.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/migrate.c
> index 66ce6b4..54f2eb6 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/migrate.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/migrate.c
> @@ -198,6 +198,8 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
>  {
>  	struct mm_struct *mm = vma->vm_mm;
>  	swp_entry_t entry;
> +	pgd_t *pgd;
> +	pud_t *pud;
>   	pmd_t *pmd;
>  	pte_t *ptep, pte;
>   	spinlock_t *ptl;
> @@ -208,10 +210,29 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
>  			goto out;
>  		ptl = huge_pte_lockptr(hstate_vma(vma), mm, ptep);
>  	} else {
> -		pmd = mm_find_pmd(mm, addr);
> +		pmd_t pmde;
> +
> +		pgd = pgd_offset(mm, addr);
> +		if (!pgd_present(*pgd))
> +			goto out;
> +		pud = pud_offset(pgd, addr);
> +		if (!pud_present(*pud))
> +			goto out;
> +		pmd = pmd_offset(pud, addr);
>  		if (!pmd)
>  			goto out;
>  
> +		if (PageTransCompound(new)) {
> +			remove_migration_pmd(new, pmd, vma, addr, old);
> +			goto out;
> +		}
> +
> +		pmde = *pmd;
> +		barrier();
> +
> +		if (!pmd_present(pmde) || pmd_trans_huge(pmde))
> +			goto out;
> +
>  		ptep = pte_offset_map(pmd, addr);
>  
>  		/*
> @@ -344,6 +365,27 @@ void migration_entry_wait_huge(struct vm_area_struct *vma,
>  	__migration_entry_wait(mm, pte, ptl);
>  }
>  
> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
> +void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)
> +{
> +	spinlock_t *ptl;
> +	struct page *page;
> +
> +	ptl = pmd_lock(mm, pmd);
> +	if (!is_pmd_migration_entry(*pmd))
> +		goto unlock;
> +	page = migration_entry_to_page(pmd_to_swp_entry(*pmd));
> +	if (!get_page_unless_zero(page))
> +		goto unlock;
> +	spin_unlock(ptl);
> +	wait_on_page_locked(page);
> +	put_page(page);
> +	return;
> +unlock:
> +	spin_unlock(ptl);
> +}
> +#endif
> +
>  #ifdef CONFIG_BLOCK
>  /* Returns true if all buffers are successfully locked */
>  static bool buffer_migrate_lock_buffers(struct buffer_head *head,
> diff --git v4.9-rc2-mmotm-2016-10-27-18-27/mm/pgtable-generic.c v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/pgtable-generic.c
> index 71c5f91..6012343 100644
> --- v4.9-rc2-mmotm-2016-10-27-18-27/mm/pgtable-generic.c
> +++ v4.9-rc2-mmotm-2016-10-27-18-27_patched/mm/pgtable-generic.c
> @@ -118,7 +118,8 @@ pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address,
>  {
>  	pmd_t pmd;
>  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
> -	VM_BUG_ON(!pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp));
> +	VM_BUG_ON(pmd_present(*pmdp) && !pmd_trans_huge(*pmdp) &&
> +		  !pmd_devmap(*pmdp));
>  	pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
>  	flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
>  	return pmd;
> -- 
> 2.7.0
> 

-- 
 Kirill A. Shutemov

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [GIT PULL] fbdev fixes for 4.9
From: Tomi Valkeinen @ 2016-11-14 11:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fbdev, linux-kernel@vger.kernel.org


[-- Attachment #1.1: Type: text/plain, Size: 1029 bytes --]

Hi Linus,

Please pull two fbdev fixes for 4.9.

 Tomi

The following changes since commit a909d3e636995ba7c349e2ca5dbb528154d4ac30:

  Linux 4.9-rc3 (2016-10-29 13:52:02 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git tags/fbdev-fixes-4.9

for you to fetch changes up to 1746aff3dba0f7530688e405e7802eeca928665f:

  Fix loading of module radeonfb on PowerMac (2016-11-14 13:27:54 +0200)

----------------------------------------------------------------
fbdev fixes for 4.9

* Fix CLCD regression on Vexpress
* Fix loading of radeonfb on PowerMac

----------------------------------------------------------------
Linus Walleij (1):
      video: ARM CLCD: fix Vexpress regression

Mathieu Malaterre (1):
      Fix loading of module radeonfb on PowerMac

 drivers/video/fbdev/amba-clcd-versatile.c |  4 ++--
 drivers/video/fbdev/aty/radeon_base.c     | 22 ++++++++++++++++++++--
 2 files changed, 22 insertions(+), 4 deletions(-)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH V4 2/2] drm/imx: Switch to drm_fb_cma_prepare_fb() helper
From: Daniel Vetter @ 2016-11-14 11:44 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Marek Vasut, Daniel Vetter, dri-devel
In-Reply-To: <1479119567.5657.1.camel@pengutronix.de>

On Mon, Nov 14, 2016 at 11:32:47AM +0100, Lucas Stach wrote:
> Am Montag, den 14.11.2016, 11:07 +0100 schrieb Marek Vasut:
> > Remove the common code from the driver and use the
> > drm_fb_cma_prepare_fb() helper instead.
> > Moveover, call the helper from prepare_fb() plane hook .
> > 
> > Signed-off-by: Marek Vasut <marex@denx.de>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Lucas Stach <l.stach@pengutronix.de>
> 
> Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

Both patches applied to drm-misc, thanks.
-Daniel

> 
> > ---
> > V2: - Rename the function to drm_fb_cma_extract_and_attach_fence()
> >     - Add missing newline
> > V3: - Call drm_fb_cma_prepare_fb directly
> > V4: - Update to latest next/master (b60de3e)
> > ---
> >  drivers/gpu/drm/imx/imx-drm-core.c | 32 +-------------------------------
> >  drivers/gpu/drm/imx/ipuv3-plane.c  |  1 +
> >  2 files changed, 2 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
> > index a16e8b7..3340429 100644
> > --- a/drivers/gpu/drm/imx/imx-drm-core.c
> > +++ b/drivers/gpu/drm/imx/imx-drm-core.c
> > @@ -18,7 +18,6 @@
> >  #include <linux/dma-buf.h>
> >  #include <linux/module.h>
> >  #include <linux/platform_device.h>
> > -#include <linux/reservation.h>
> >  #include <drm/drmP.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> > @@ -151,40 +150,11 @@ static int imx_drm_atomic_check(struct drm_device *dev,
> >  	return ret;
> >  }
> >  
> > -static int imx_drm_atomic_commit(struct drm_device *dev,
> > -				 struct drm_atomic_state *state,
> > -				 bool nonblock)
> > -{
> > -	struct drm_plane_state *plane_state;
> > -	struct drm_plane *plane;
> > -	struct dma_buf *dma_buf;
> > -	struct dma_fence *fence;
> > -	int i;
> > -
> > -	/*
> > -	 * If the plane fb has an dma-buf attached, fish out the exclusive
> > -	 * fence for the atomic helper to wait on.
> > -	 */
> > -	for_each_plane_in_state(state, plane, plane_state, i) {
> > -		if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
> > -			dma_buf = drm_fb_cma_get_gem_obj(plane_state->fb,
> > -							 0)->base.dma_buf;
> > -			if (!dma_buf)
> > -				continue;
> > -			fence = reservation_object_get_excl_rcu(dma_buf->resv);
> > -
> > -			drm_atomic_set_fence_for_plane(plane_state, fence);
> > -		}
> > -	}
> > -
> > -	return drm_atomic_helper_commit(dev, state, nonblock);
> > -}
> > -
> >  static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
> >  	.fb_create = drm_fb_cma_create,
> >  	.output_poll_changed = imx_drm_output_poll_changed,
> >  	.atomic_check = imx_drm_atomic_check,
> > -	.atomic_commit = imx_drm_atomic_commit,
> > +	.atomic_commit = drm_atomic_helper_commit,
> >  };
> >  
> >  static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
> > diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
> > index 6a97e396..e74a0ad 100644
> > --- a/drivers/gpu/drm/imx/ipuv3-plane.c
> > +++ b/drivers/gpu/drm/imx/ipuv3-plane.c
> > @@ -468,6 +468,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
> >  }
> >  
> >  static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
> > +	.prepare_fb = drm_fb_cma_prepare_fb,
> >  	.atomic_check = ipu_plane_atomic_check,
> >  	.atomic_disable = ipu_plane_atomic_disable,
> >  	.atomic_update = ipu_plane_atomic_update,
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH v10 01/11] remoteproc: st_slim_rproc: add a slimcore rproc driver
From: Peter Griffin @ 2016-11-14 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161114051854.GW3000@localhost>

Hi Vinod,

On Mon, 14 Nov 2016, Vinod Koul wrote:

> On Mon, Nov 07, 2016 at 01:57:35PM +0000, Peter Griffin wrote:
> > > 
> > > As you now make changes to the entire remoteproc Kconfig file, rather
> > > than simply add a Kconfig symbol we can't bring this in via Vinod's tree
> > > without providing Linus with a messy merge conflict.
> > > 
> > > So the remoteproc parts now has to go through my tree.
> > 
> > OK, I think the best approach is for Vinod to create an immutable
> > branch with the entire fdma series on, and then both of you merge that branch into
> > your respective trees.
> 
> my topic/st_fdma is immutable branch. You cna merge it, if you need a signed
> tag, please do let me know

OK.

> 
> > 
> > That way there won't be any conflicts and you can both accept further changes
> > for v4.9 release. Trying to take half the series via rproc, and half via dma trees won't work
> > because they have dependencies on each other.
> > 
> > I will send a v11 series in a moment which includes the feedback in this email
> > and also include the additional fixes which Vinod has applied since the driver
> > has been in linux-next.
> 
> WHY.. Stuff is already merged twice!

When the feedback is "there is an unrelated change in this patch", the only way
you can fix that is by having a new version of the patch.

>Please send updated on top of already
> merged code!

You have dropped the remoteproc parts which were updated in v11, so
it is no longer merged. Bjorn can now pick the v11 versions if he chooses which
incporporates his feedback.

>This is how kernel developement is done...

regards,

Peter.

^ permalink raw reply

* Re: [PATCH v10 01/11] remoteproc: st_slim_rproc: add a slimcore rproc driver
From: Peter Griffin @ 2016-11-14 11:42 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Bjorn Andersson, linux-arm-kernel, linux-kernel, kernel, ohad,
	patrice.chotard, lee.jones, dmaengine, devicetree,
	linux-remoteproc
In-Reply-To: <20161114051854.GW3000@localhost>

Hi Vinod,

On Mon, 14 Nov 2016, Vinod Koul wrote:

> On Mon, Nov 07, 2016 at 01:57:35PM +0000, Peter Griffin wrote:
> > > 
> > > As you now make changes to the entire remoteproc Kconfig file, rather
> > > than simply add a Kconfig symbol we can't bring this in via Vinod's tree
> > > without providing Linus with a messy merge conflict.
> > > 
> > > So the remoteproc parts now has to go through my tree.
> > 
> > OK, I think the best approach is for Vinod to create an immutable
> > branch with the entire fdma series on, and then both of you merge that branch into
> > your respective trees.
> 
> my topic/st_fdma is immutable branch. You cna merge it, if you need a signed
> tag, please do let me know

OK.

> 
> > 
> > That way there won't be any conflicts and you can both accept further changes
> > for v4.9 release. Trying to take half the series via rproc, and half via dma trees won't work
> > because they have dependencies on each other.
> > 
> > I will send a v11 series in a moment which includes the feedback in this email
> > and also include the additional fixes which Vinod has applied since the driver
> > has been in linux-next.
> 
> WHY.. Stuff is already merged twice!

When the feedback is "there is an unrelated change in this patch", the only way
you can fix that is by having a new version of the patch.

>Please send updated on top of already
> merged code!

You have dropped the remoteproc parts which were updated in v11, so
it is no longer merged. Bjorn can now pick the v11 versions if he chooses which
incporporates his feedback.

>This is how kernel developement is done...

regards,

Peter.

^ permalink raw reply

* Re: [PATCH v3 08/14] drm/i915/scheduler: Execute requests in order of priorities
From: Chris Wilson @ 2016-11-14 11:41 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx
In-Reply-To: <ea5d13f8-eb3c-bd87-3eeb-15f28c8e6776@linux.intel.com>

On Mon, Nov 14, 2016 at 11:15:52AM +0000, Tvrtko Ursulin wrote:
> On 14/11/2016 08:56, Chris Wilson wrote:
> >+static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
> >+{
> >+	struct intel_engine_cs *engine = NULL;
> >+	struct i915_dependency *dep, *p;
> >+	struct i915_dependency stack;
> >+	LIST_HEAD(dfs);
> >+
> >+	if (prio <= READ_ONCE(request->priotree.priority))
> >+		return;
> >+
> >+	/* Need BKL in order to use the temporary link inside i915_dependency */
> >+	lockdep_assert_held(&request->i915->drm.struct_mutex);
> >+
> >+	stack.signaler = &request->priotree;
> >+	list_add(&stack.dfs_link, &dfs);
> >+
> >+	/* Recursively bump all dependent priorities to match the new request */
> 
> Missed last time round that the comment needs updating.

It still is a recursive design though, just flat. That one word was
saving a paragraph :|

I think the easiest way to describe what the code is doing here is to
show the recursive version in the comment and then hope for inspiration
in describing how that maps onto the search list.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* [PATCH] drm/nouveau: Use drm_crtc_vblank_off/on
From: Daniel Vetter @ 2016-11-14 11:41 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Ben Skeggs, Daniel Vetter
In-Reply-To: <20161114090255.31595-2-daniel.vetter@ffwll.ch>

With atomic nv50+ is already converted over to them, but the old
display code is still using it. Found in a 2 year old patch I have
lying around to un-export these old helpers!

v2: Drop the hand-rolled versions from resume/suspend code. Now that
crtc callbacks do this, we don't need a special case for s/r anymore.

v3: Remove unused variables.

Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/nouveau/dispnv04/crtc.c   |  4 ++--
 drivers/gpu/drm/nouveau/nouveau_display.c | 11 +----------
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 0cb7a18cde26..59d1d1c5de5f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -702,7 +702,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc)
 	if (nv_two_heads(dev))
 		NVSetOwner(dev, nv_crtc->index);
 
-	drm_vblank_pre_modeset(dev, nv_crtc->index);
+	drm_crtc_vblank_off(crtc);
 	funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
 	NVBlankScreen(dev, nv_crtc->index, true);
@@ -734,7 +734,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
 #endif
 
 	funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-	drm_vblank_post_modeset(dev, nv_crtc->index);
+	drm_crtc_vblank_on(crtc);
 }
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 75c90a8da18a..76c342bf047b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -380,15 +380,10 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
 	struct nouveau_display *disp = nouveau_display(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct drm_connector *connector;
-	int head;
 
 	if (!suspend)
 		drm_crtc_force_disable_all(dev);
 
-	/* Make sure that drm and hw vblank irqs get properly disabled. */
-	for (head = 0; head < dev->mode_config.num_crtc; head++)
-		drm_vblank_off(dev, head);
-
 	/* disable flip completion events */
 	nvif_notify_put(&drm->flip);
 
@@ -723,7 +718,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 	struct nouveau_display *disp = nouveau_display(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct drm_crtc *crtc;
-	int ret, head;
+	int ret;
 
 	if (dev->mode_config.funcs->atomic_commit) {
 		nouveau_display_init(dev);
@@ -777,10 +772,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 
 	drm_helper_resume_force_mode(dev);
 
-	/* Make sure that drm and hw vblank irqs get resumed if needed. */
-	for (head = 0; head < dev->mode_config.num_crtc; head++)
-		drm_vblank_on(dev, head);
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
-- 
2.10.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* Re: Getting ATH10K to work with Linksys WUSB6100M
From: Michal Kazior @ 2016-11-14 11:40 UTC (permalink / raw)
  To: Johan Lindström; +Cc: ath10k@lists.infradead.org
In-Reply-To: <0DA73A6D-68F0-4999-8F63-62B4D594796B@gmail.com>

On 11 November 2016 at 00:56, Johan Lindström
<johan.von.lindstrom@gmail.com> wrote:
> This device is running  QCA9377 chipset with the usb.id 13b1:0042
>
> Any ideas on how to add this device to the working devices? Does ath10k even work with USB devices?
>
> See info: http://askubuntu.com/questions/799104/linksys-wusb6100m

USB transport is not implemented in ath10k. Adding it will require a
slight HTC/HTT rework and implementing the transport code itself. I'm
pretty sure qcacld[1] can used as reference.

[1]: https://github.com/sktjdgns1189/qcacld-2.0/tree/master/CORE/SERVICES/HIF/USB


Michał

_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k

^ permalink raw reply

* 答复: 答复: 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI
From: Liu, Monk @ 2016-11-14 11:39 UTC (permalink / raw)
  To: Christian König,
	amd-gfx-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org
In-Reply-To: <ddae0dc9-7b1a-6092-b11a-f66e760afe19-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>

I have no strong opinion, I checked windows kmd and they separate vgt-flush and cntx-ctrl as well, 
Fine with your suggestion 

BR Monk

-----邮件原件-----
发件人: Christian König [mailto:deathsimple@vodafone.de] 
发送时间: Monday, November 14, 2016 7:33 PM
收件人: Liu, Monk; amd-gfx@freedesktop.org
主题: Re: 答复: 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI

The callbacks are use case driven, so it doesn't matter what packets they use. I would really prefer not to add to many of them.

Maybe rename the emit_cntxcntl callback to just emit_context_preamble or something like this to make it more clear what that is good for.

Regards,
Christian.

Am 14.11.2016 um 11:01 schrieb Liu, Monk:
> Although the effect is equal, but cntxcntl uses CONTEXT_CONTROL only, 
> while vgt-flush uses EVENT_WRITE on vgt_flush and vs_partial_flush only, And vgt flush only operate on tessellation category registers, I'd prefer it not mixed with CONTEXT_CONTROL package ...
> I think Put them together seems not grace ...
>
> BR Monk
>
> -----邮件原件-----
> 发件人: Christian König [mailto:deathsimple@vodafone.de]
> 发送时间: Monday, November 14, 2016 5:46 PM
> 收件人: Liu, Monk; amd-gfx@freedesktop.org
> 主题: Re: 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI
>
> Am 14.11.2016 um 04:17 schrieb Liu, Monk:
>> Anyone review this patch ?
> Looks good in general, but is there any reason not to put it into the existing emit_cntxcntl callback?
>
> Regards,
> Christian.
>
>> This patch could fix tessellation bug when shadowing enabled, we 
>> should always insert vgt_flush when there is a context switch
>>
>> BR Monk
>>
>> -----邮件原件-----
>> 发件人: Monk Liu [mailto:Monk.Liu@amd.com]
>> 发送时间: Friday, November 11, 2016 6:32 PM
>> 收件人: amd-gfx@freedesktop.org
>> 抄送: Liu, Monk
>> 主题: [PATCH] drm/amdgpu:impl vgt_flush for VI
>>
>> when hardware shadowing enabled, tesselation will trigger vm fault, the root cause is because VGT_FLUSH not introduced in kmd. this could fix tesselation crash issue.
>>
>> Change-Id: I77d87d93ce6580e559e734fb41d97ee8c59d245b
>> Signed-off-by: Monk Liu <Monk.Liu@amd.com>
>> ---
>>    drivers/gpu/drm/amd/amdgpu/amdgpu.h      |  1 +
>>    drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c   |  5 ++++-
>>    drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h |  1 +
>>    drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c    | 13 +++++++++++++
>>    4 files changed, 19 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> index 15015bc..f46e96b 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> @@ -1630,6 +1630,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring
>> *ring)  #define amdgpu_ring_emit_fence(r, addr, seq, flags) 
>> (r)->funcs->emit_fence((r), (addr), (seq), (flags))  #define 
>> amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) 
>> (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab),
>> (as))  #define amdgpu_ring_emit_hdp_flush(r)
>> (r)->funcs->emit_hdp_flush((r))
>> +#define amdgpu_ring_emit_vgt_flush(r) 
>> +(r)->funcs->emit_vgt_flush((r))
>>    #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
>>    #define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
>>    #define amdgpu_ring_emit_cntxcntl(r, d) 
>> (r)->funcs->emit_cntxcntl((r), (d)) diff --git 
>> a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> index acf48de..c039890 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> @@ -175,11 +175,14 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
>>    	if (ring->funcs->emit_hdp_flush)
>>    		amdgpu_ring_emit_hdp_flush(ring);
>>    
>> +	need_ctx_switch = ring->current_ctx != fence_ctx;
>> +	if (ring->funcs->emit_vgt_flush && need_ctx_switch)
>> +		 amdgpu_ring_emit_vgt_flush(ring);
>> +
>>    	/* always set cond_exec_polling to CONTINUE */
>>    	*ring->cond_exe_cpu_addr = 1;
>>    
>>    	skip_preamble = ring->current_ctx == fence_ctx;
>> -	need_ctx_switch = ring->current_ctx != fence_ctx;
>>    	if (job && ring->funcs->emit_cntxcntl) {
>>    		if (need_ctx_switch)
>>    			status |= AMDGPU_HAVE_CTX_SWITCH; diff --git 
>> a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> index 92bc89b..c3a7329 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> @@ -116,6 +116,7 @@ struct amdgpu_ring_funcs {
>>    	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
>>    			      uint64_t pd_addr);
>>    	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
>> +	void (*emit_vgt_flush)(struct amdgpu_ring *ring);
>>    	void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
>>    	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
>>    				uint32_t gds_base, uint32_t gds_size, diff --git 
>> a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> index 9017803..1d407d76 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> @@ -6187,6 +6187,18 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
>>    	amdgpu_ring_write(ring, 0x20); /* poll interval */  }
>>    
>> +static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring) {
>> +	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
>> +	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
>> +		EVENT_INDEX(4));
>> +
>> +	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
>> +	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
>> +		EVENT_INDEX(0));
>> +}
>> +
>> +
>>    static void gfx_v8_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)  {
>>    	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); @@ -6590,6 +6602,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
>>    	.pad_ib = amdgpu_ring_generic_pad_ib,
>>    	.emit_switch_buffer = gfx_v8_ring_emit_sb,
>>    	.emit_cntxcntl = gfx_v8_ring_emit_cntxcntl,
>> +	.emit_vgt_flush = gfx_v8_0_ring_emit_vgt_flush,
>>    };
>>    
>>    static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute 
>> = {
>> --
>> 1.9.1
>>
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply

* Re: [PATCH] broadcom/brcm80211/brcmfmac/cfg80211 driver, bad regulatory domain frequency value
From: Gianfranco Costamagna @ 2016-11-14 11:34 UTC (permalink / raw)
  To: Arend Van Spriel, brcm80211-dev-list@broadcom.com,
	linux-wireless@vger.kernel.org
  Cc: nsmaldone@tierratelematics.com, Marco.Arlone@roj.com
In-Reply-To: <0812c8f2-f0ce-c62c-5f09-fa46dafd630f@broadcom.com>

Hi Arend,


>Finally response. As it turns out the range was explcitly changed

>enabling channels 12 and 13 to be used where applicable. They forgot to
>update the comment.


so, the struct in net/wireless/reg.c is actually used in that case?

static const struct ieee80211_regdomain world_regdom = {

do you plan to update the comment?

thanks!

Gianfranco

^ permalink raw reply

* Re: [PATCH V4 2/2] iio: adc: spmi-vadc: Changes to support different scaling
From: Phani A, Rama Krishna @ 2016-11-14 11:38 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio
  Cc: linux-arm-msm, cdevired, smohanad, mgautam, sivaa, knaack.h, lars,
	pmeerw, Julia.Lawall
In-Reply-To: <bc8b56e3-e1bf-3e92-bdca-cf7b0a13dca1@kernel.org>

Hi Jonathan,

On 12-Nov-16 8:32 PM, Jonathan Cameron wrote:
> On 08/11/16 11:58, Rama Krishna Phani A wrote:
>> Several ADC channels are supported in PMIC which can be used to
>> measure voltage, temperature, current etc. Different scaling can be
>> applied on the obtained voltage to report in physical units. Scaling
>> functionality can be different per channel. Add scaling support per
>> channel. Every channel present in adc has an unique conversion formula
>> for obtained voltage. Add support to report in Raw as well as in
>> processed format. Scaling is applied when processed read is requested
>> and is not applied when a Raw read is requested.
>>
>> Signed-off-by: Rama Krishna Phani A <rphani@codeaurora.org>
>
> This looks good except for one thing.  If we can't provide a scale,
> we shouldn't try to provide processed output so it shouldn't be in the
> info_mask.  Shouldn't take a huge amount of work to tidy this up.
>
> I'm backing out patch 1 for now though as if this takes a while we
> could end up with an intermediate interface actually getting to users
> which would be even worse than changing once as we are!
>
> Thanks,
>
> Jonathan
Sure ., will include scale support as well in the "info_mask".
>> ---
>>  drivers/iio/adc/qcom-spmi-vadc.c | 436 +++++++++++++++++++++++++++++----------
>>  1 file changed, 326 insertions(+), 110 deletions(-)
>>
>> diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
>> index 93c0639..d36ba49 100644
>> --- a/drivers/iio/adc/qcom-spmi-vadc.c
>> +++ b/drivers/iio/adc/qcom-spmi-vadc.c
>> @@ -84,7 +84,7 @@
>>  #define VADC_MAX_ADC_CODE			0xa800
>>
>>  #define VADC_ABSOLUTE_RANGE_UV			625000
>> -#define VADC_RATIOMETRIC_RANGE_UV		1800000
>> +#define VADC_RATIOMETRIC_RANGE			1800
>>
>>  #define VADC_DEF_PRESCALING			0 /* 1:1 */
>>  #define VADC_DEF_DECIMATION			0 /* 512 */
>> @@ -100,9 +100,23 @@
>>
>>  #define KELVINMIL_CELSIUSMIL			273150
>>
>> +#define PMI_CHG_SCALE_1				-138890
>> +#define PMI_CHG_SCALE_2				391750000000
>> +
>>  #define VADC_CHAN_MIN			VADC_USBIN
>>  #define VADC_CHAN_MAX			VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM
>>
>> +/**
>> + * struct vadc_map_pt - Map the graph representation for ADC channel
>> + * @x: Represent the ADC digitized code.
>> + * @y: Represent the physical data which can be temperature, voltage,
>> + *     resistance.
>> + */
>> +struct vadc_map_pt {
>> +	s32 x;
>> +	s32 y;
>> +};
>> +
>>  /*
>>   * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels.
>>   * VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for
>> @@ -148,6 +162,9 @@ struct vadc_prescale_ratio {
>>   *	start of conversion.
>>   * @avg_samples: ability to provide single result from the ADC
>>   *	that is an average of multiple measurements.
>> + * @scale_fn: Represents the scaling function to convert voltage
>> + *	physical units desired by the client for the channel.
>> + *	Referenced from enum vadc_scale_fn_type.
>>   */
>>  struct vadc_channel_prop {
>>  	unsigned int channel;
>> @@ -156,6 +173,7 @@ struct vadc_channel_prop {
>>  	unsigned int prescale;
>>  	unsigned int hw_settle_time;
>>  	unsigned int avg_samples;
>> +	unsigned int scale_fn;
>>  };
>>
>>  /**
>> @@ -186,6 +204,37 @@ struct vadc_priv {
>>  	struct mutex		 lock;
>>  };
>>
>> +/**
>> + * struct vadc_scale_fn - Scaling function prototype
>> + * @scale: Function pointer to one of the scaling functions
>> + *	which takes the adc properties, channel properties,
>> + *	and returns the physical result.
>> + */
>> +struct vadc_scale_fn {
>> +	int (*scale)(struct vadc_priv *, const struct vadc_channel_prop *,
>> +		     u16, int *);
>> +};
>> +
>> +/**
>> + * enum vadc_scale_fn_type - Scaling function to convert ADC code to
>> + *				physical scaled units for the channel.
>> + * SCALE_DEFAULT: Default scaling to convert raw adc code to voltage (uV).
>> + * SCALE_THERM_100K_PULLUP: Returns temperature in millidegC.
>> + *				 Uses a mapping table with 100K pullup.
>> + * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
>> + * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
>> + * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
>> + * SCALE_NONE: Do not use this scaling type.
>> + */
>> +enum vadc_scale_fn_type {
>> +	SCALE_DEFAULT = 0,
>> +	SCALE_THERM_100K_PULLUP,
>> +	SCALE_PMIC_THERM,
>> +	SCALE_XOTHERM,
>> +	SCALE_PMI_CHG_TEMP,
>> +	SCALE_NONE,
>> +};
>> +
>>  static const struct vadc_prescale_ratio vadc_prescale_ratios[] = {
>>  	{.num =  1, .den =  1},
>>  	{.num =  1, .den =  3},
>> @@ -197,6 +246,44 @@ struct vadc_priv {
>>  	{.num =  1, .den = 10}
>>  };
>>
>> +/* Voltage to temperature */
>> +static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
>> +	{1758,	-40},
>> +	{1742,	-35},
>> +	{1719,	-30},
>> +	{1691,	-25},
>> +	{1654,	-20},
>> +	{1608,	-15},
>> +	{1551,	-10},
>> +	{1483,	-5},
>> +	{1404,	0},
>> +	{1315,	5},
>> +	{1218,	10},
>> +	{1114,	15},
>> +	{1007,	20},
>> +	{900,	25},
>> +	{795,	30},
>> +	{696,	35},
>> +	{605,	40},
>> +	{522,	45},
>> +	{448,	50},
>> +	{383,	55},
>> +	{327,	60},
>> +	{278,	65},
>> +	{237,	70},
>> +	{202,	75},
>> +	{172,	80},
>> +	{146,	85},
>> +	{125,	90},
>> +	{107,	95},
>> +	{92,	100},
>> +	{79,	105},
>> +	{68,	110},
>> +	{59,	115},
>> +	{51,	120},
>> +	{44,	125}
>> +};
>> +
>>  static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data)
>>  {
>>  	return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1);
>> @@ -418,7 +505,7 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>>  	u16 read_1, read_2;
>>  	int ret;
>>
>> -	vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE_UV;
>> +	vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE;
>>  	vadc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV;
>>
>>  	prop = vadc_get_channel(vadc, VADC_REF_1250MV);
>> @@ -468,6 +555,51 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>>  	return ret;
>>  }
>>
>> +static int vadc_map_voltage_temp(const struct vadc_map_pt *pts,
>> +				 u32 tablesize, s32 input, s64 *output)
>> +{
>> +	bool descending = 1;
>> +	u32 i = 0;
>> +
>> +	if (!pts)
>> +		return -EINVAL;
>> +
>> +	/* Check if table is descending or ascending */
>> +	if (tablesize > 1) {
>> +		if (pts[0].x < pts[1].x)
>> +			descending = 0;
>> +	}
>> +
>> +	while (i < tablesize) {
>> +		if ((descending) && (pts[i].x < input)) {
>> +			/* table entry is less than measured*/
>> +			 /* value and table is descending, stop */
>> +			break;
>> +		} else if ((!descending) &&
>> +				(pts[i].x > input)) {
>> +			/* table entry is greater than measured*/
>> +			/*value and table is ascending, stop */
>> +			break;
>> +		}
>> +		i++;
>> +	}
>> +
>> +	if (i == 0) {
>> +		*output = pts[0].y;
>> +	} else if (i == tablesize) {
>> +		*output = pts[tablesize - 1].y;
>> +	} else {
>> +		/* result is between search_index and search_index-1 */
>> +		/* interpolate linearly */
>> +		*output = (((s32)((pts[i].y - pts[i - 1].y) *
>> +			(input - pts[i - 1].x)) /
>> +			(pts[i].x - pts[i - 1].x)) +
>> +			pts[i - 1].y);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  static void vadc_scale_calib(struct vadc_priv *vadc, u16 adc_code,
>>  			     const struct vadc_channel_prop *prop,
>>  			     s64 *scale_voltage)
>> @@ -502,6 +634,77 @@ static int vadc_scale_volt(struct vadc_priv *vadc,
>>  	return 0;
>>  }
>>
>> +static int vadc_scale_therm(struct vadc_priv *vadc,
>> +			    const struct vadc_channel_prop *prop, u16 adc_code,
>> +			    int *result_mdec)
>> +{
>> +	s64 voltage = 0, result = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> +		voltage /= 1000;
>> +
>> +	vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
>> +			      ARRAY_SIZE(adcmap_100k_104ef_104fb),
>> +			      voltage, &result);
>> +	result *= 1000;
>> +	*result_mdec = result;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale_die_temp(struct vadc_priv *vadc,
>> +			       const struct vadc_channel_prop *prop,
>> +			       u16 adc_code, int *result_mdec)
>> +{
>> +	const struct vadc_prescale_ratio *prescale;
>> +	s64 voltage = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	if (voltage > 0) {
>> +		prescale = &vadc_prescale_ratios[prop->prescale];
>> +		voltage = voltage * prescale->den;
>> +		voltage /= (prescale->num * 2);
>> +	} else {
>> +		voltage = 0;
>> +	}
>> +
>> +	voltage -= KELVINMIL_CELSIUSMIL;
>> +	*result_mdec = voltage;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale_chg_temp(struct vadc_priv *vadc,
>> +			       const struct vadc_channel_prop *prop,
>> +			       u16 adc_code, int *result_mdec)
>> +{
>> +	const struct vadc_prescale_ratio *prescale;
>> +	s64 voltage = 0, result = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	prescale = &vadc_prescale_ratios[prop->prescale];
>> +	voltage = voltage * prescale->den;
>> +	voltage = div64_s64(voltage, prescale->num);
>> +	voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
>> +	voltage = (voltage + PMI_CHG_SCALE_2);
>> +	result =  div64_s64(voltage, 1000000);
>> +	*result_mdec = result;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale(struct vadc_priv *vadc,
>> +		      const struct vadc_channel_prop *prop, u16 adc_code,
>> +		      int *scale)
>> +{
>> +	dev_err(vadc->dev, "Need a scale function\n");
>> +	return 0;
>> +}
>> +
>>  static int vadc_decimation_from_dt(u32 value)
>>  {
>>  	if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
>> @@ -547,6 +750,15 @@ static int vadc_avg_samples_from_dt(u32 value)
>>  	return __ffs64(value);
>>  }
>>
>> +static struct vadc_scale_fn scale_fn[] = {
>> +	[SCALE_DEFAULT] = {vadc_scale_volt},
>> +	[SCALE_THERM_100K_PULLUP] = {vadc_scale_therm},
>> +	[SCALE_PMIC_THERM] = {vadc_scale_die_temp},
>> +	[SCALE_XOTHERM] = {vadc_scale_therm},
>> +	[SCALE_PMI_CHG_TEMP] = {vadc_scale_chg_temp},
>> +	[SCALE_NONE] = {vadc_scale},
>> +};
>> +
>>  static int vadc_read_raw(struct iio_dev *indio_dev,
>>  			 struct iio_chan_spec const *chan, int *val, int *val2,
>>  			 long mask)
>> @@ -563,7 +775,7 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>>  		if (ret)
>>  			break;
>>
>> -		vadc_scale_volt(vadc, prop, adc_code, val);
>> +		scale_fn[prop->scale_fn].scale(vadc, prop, adc_code, val);
>>
>>  		return IIO_VAL_INT;
>>  	case IIO_CHAN_INFO_RAW:
>> @@ -606,23 +818,27 @@ struct vadc_channels {
>>  	unsigned int prescale_index;
>>  	enum iio_chan_type type;
>>  	long info_mask;
>> +	unsigned int scale_fn;
>>  };
>>
>> -#define VADC_CHAN(_dname, _type, _mask, _pre)				\
>> +#define VADC_CHAN(_dname, _type, _mask, _pre, _scale)			\
>>  	[VADC_##_dname] = {						\
>>  		.datasheet_name = __stringify(_dname),			\
>>  		.prescale_index = _pre,					\
>>  		.type = _type,						\
>> -		.info_mask = _mask					\
>> +		.info_mask = _mask,					\
>> +		.scale_fn = _scale					\
>>  	},								\
>>
>> -#define VADC_CHAN_TEMP(_dname, _pre)					\
>> -	VADC_CHAN(_dname, IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED), _pre)	\
>> +#define VADC_CHAN_TEMP(_dname, _pre, _scale)				\
>> +	VADC_CHAN(_dname, IIO_TEMP,					\
>> +		BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),	\
>> +		_pre, _scale)						\
>>
>> -#define VADC_CHAN_VOLT(_dname, _pre)					\
>> +#define VADC_CHAN_VOLT(_dname, _pre, _scale)				\
>>  	VADC_CHAN(_dname, IIO_VOLTAGE,					\
>>  		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
>> -		  _pre)							\
>> +		  _pre, _scale)						\
>>
So here., Need to include support for "IIO_CHAN_INFO_SCALE" for 
"VADC_CHAN_VOLT" to provide backward compatibility and same support for 
"VADC_CHAN_TEMP" as well. Please correct me otherwise.

>>  /*
>>   * The array represents all possible ADC channels found in the supported PMICs.
>> @@ -630,106 +846,106 @@ struct vadc_channels {
>>   * gaps in the array should be treated as reserved channels.
>>   */
>>  static const struct vadc_channels vadc_chans[] = {
>> -	VADC_CHAN_VOLT(USBIN, 4)
>> -	VADC_CHAN_VOLT(DCIN, 4)
>> -	VADC_CHAN_VOLT(VCHG_SNS, 3)
>> -	VADC_CHAN_VOLT(SPARE1_03, 1)
>> -	VADC_CHAN_VOLT(USB_ID_MV, 1)
>> -	VADC_CHAN_VOLT(VCOIN, 1)
>> -	VADC_CHAN_VOLT(VBAT_SNS, 1)
>> -	VADC_CHAN_VOLT(VSYS, 1)
>> -	VADC_CHAN_TEMP(DIE_TEMP, 0)
>> -	VADC_CHAN_VOLT(REF_625MV, 0)
>> -	VADC_CHAN_VOLT(REF_1250MV, 0)
>> -	VADC_CHAN_VOLT(CHG_TEMP, 0)
>> -	VADC_CHAN_VOLT(SPARE1, 0)
>> -	VADC_CHAN_VOLT(SPARE2, 0)
>> -	VADC_CHAN_VOLT(GND_REF, 0)
>> -	VADC_CHAN_VOLT(VDD_VADC, 0)
>> -
>> -	VADC_CHAN_VOLT(P_MUX1_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX2_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX3_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX4_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX5_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX6_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX7_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX8_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX9_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX10_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX11_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX12_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX13_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX14_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX15_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX16_1_1, 0)
>> -
>> -	VADC_CHAN_VOLT(P_MUX1_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX2_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX3_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX4_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX5_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX6_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX7_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX8_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX9_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX10_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX11_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX12_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX13_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX14_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX15_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX16_1_3, 1)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_USB_ID, 0)
>> -	VADC_CHAN_VOLT(AMUX_PU1, 0)
>> -	VADC_CHAN_VOLT(AMUX_PU2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU1_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU1_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU1_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU1_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU1_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU1_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU1_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU1_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU1_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU1_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU2_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU2_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU2_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU2_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU2_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU2_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU2_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU2_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU2_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU2_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU1_PU2_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU1_PU2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU1_PU2_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU1_PU2_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU1_PU2_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU1_PU2_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU1_PU2_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU1_PU2_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0)
>> +	VADC_CHAN_VOLT(USBIN, 4, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(DCIN, 4, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VCHG_SNS, 3, SCALE_NONE)
>> +	VADC_CHAN_VOLT(SPARE1_03, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(USB_ID_MV, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(VCOIN, 1, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VBAT_SNS, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(VSYS, 1, SCALE_DEFAULT)
>> +	VADC_CHAN_TEMP(DIE_TEMP, 0, SCALE_PMIC_THERM)
>> +	VADC_CHAN_VOLT(REF_625MV, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(REF_1250MV, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(CHG_TEMP, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(SPARE1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(SPARE2, 0, SCALE_PMI_CHG_TEMP)
>> +	VADC_CHAN_VOLT(GND_REF, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VDD_VADC, 0, SCALE_DEFAULT)
>> +
>> +	VADC_CHAN_VOLT(P_MUX1_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX2_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX3_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX4_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX5_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX6_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX7_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX8_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX9_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX10_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX11_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX12_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX13_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX14_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX15_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX16_1_1, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_VOLT(P_MUX1_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX2_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX3_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX4_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX5_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX6_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX7_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX8_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX9_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX10_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX11_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX12_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX13_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX14_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX15_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX16_1_3, 1, SCALE_NONE)
>> +
>> +	VADC_CHAN_VOLT(LR_MUX1_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX3_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX4_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX5_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX6_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX8_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX9_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(AMUX_PU1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(AMUX_PU2, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX3_BUF_XO_THERM, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU1_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU1_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU1_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU1_AMUX_THM1, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU1_AMUX_THM2, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU1_AMUX_THM3, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU1_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU1_AMUX_THM4, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU1_AMUX_THM5, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU1_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU1_XO_THERM, 0, SCALE_XOTHERM)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU2_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU2_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU2_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU2_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU2_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU2_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU2_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU2_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU2_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU2_XO_THERM, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU1_PU2_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU1_PU2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU1_PU2_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU1_PU2_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU1_PU2_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU1_PU2_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU1_PU2_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU1_PU2_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0, SCALE_NONE)
>>  };
>>
>>  static int vadc_get_dt_channel_data(struct device *dev,
>> @@ -847,7 +1063,7 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node)
>>  			of_node_put(child);
>>  			return ret;
>>  		}
>> -
> If I was being really fussy... This white space is as valid as it was before this
> addition so shouldn't really have been removed ;)
Sure., Will retain this new line in the next patch.
>> +		prop.scale_fn = vadc_chans[prop.channel].scale_fn;
>>  		vadc->chan_props[index] = prop;
>>
>>  		vadc_chan = &vadc_chans[prop.channel];
>>
>

Thanks,
Ramakrishna

^ permalink raw reply

* Re: [PATCH V4 2/2] iio: adc: spmi-vadc: Changes to support different scaling
From: Phani A, Rama Krishna @ 2016-11-14 11:38 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	cdevired-sgV2jX0FEOL9JmXXK+q4OQ, smohanad-sgV2jX0FEOL9JmXXK+q4OQ,
	mgautam-sgV2jX0FEOL9JmXXK+q4OQ, sivaa-sgV2jX0FEOL9JmXXK+q4OQ,
	knaack.h-Mmb7MZpHnFY, lars-Qo5EllUWu/uELgA04lAiVw,
	pmeerw-jW+XmwGofnusTnJN9+BGXg, Julia.Lawall-L2FTfq7BK8M
In-Reply-To: <bc8b56e3-e1bf-3e92-bdca-cf7b0a13dca1-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Hi Jonathan,

On 12-Nov-16 8:32 PM, Jonathan Cameron wrote:
> On 08/11/16 11:58, Rama Krishna Phani A wrote:
>> Several ADC channels are supported in PMIC which can be used to
>> measure voltage, temperature, current etc. Different scaling can be
>> applied on the obtained voltage to report in physical units. Scaling
>> functionality can be different per channel. Add scaling support per
>> channel. Every channel present in adc has an unique conversion formula
>> for obtained voltage. Add support to report in Raw as well as in
>> processed format. Scaling is applied when processed read is requested
>> and is not applied when a Raw read is requested.
>>
>> Signed-off-by: Rama Krishna Phani A <rphani-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>
> This looks good except for one thing.  If we can't provide a scale,
> we shouldn't try to provide processed output so it shouldn't be in the
> info_mask.  Shouldn't take a huge amount of work to tidy this up.
>
> I'm backing out patch 1 for now though as if this takes a while we
> could end up with an intermediate interface actually getting to users
> which would be even worse than changing once as we are!
>
> Thanks,
>
> Jonathan
Sure ., will include scale support as well in the "info_mask".
>> ---
>>  drivers/iio/adc/qcom-spmi-vadc.c | 436 +++++++++++++++++++++++++++++----------
>>  1 file changed, 326 insertions(+), 110 deletions(-)
>>
>> diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
>> index 93c0639..d36ba49 100644
>> --- a/drivers/iio/adc/qcom-spmi-vadc.c
>> +++ b/drivers/iio/adc/qcom-spmi-vadc.c
>> @@ -84,7 +84,7 @@
>>  #define VADC_MAX_ADC_CODE			0xa800
>>
>>  #define VADC_ABSOLUTE_RANGE_UV			625000
>> -#define VADC_RATIOMETRIC_RANGE_UV		1800000
>> +#define VADC_RATIOMETRIC_RANGE			1800
>>
>>  #define VADC_DEF_PRESCALING			0 /* 1:1 */
>>  #define VADC_DEF_DECIMATION			0 /* 512 */
>> @@ -100,9 +100,23 @@
>>
>>  #define KELVINMIL_CELSIUSMIL			273150
>>
>> +#define PMI_CHG_SCALE_1				-138890
>> +#define PMI_CHG_SCALE_2				391750000000
>> +
>>  #define VADC_CHAN_MIN			VADC_USBIN
>>  #define VADC_CHAN_MAX			VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM
>>
>> +/**
>> + * struct vadc_map_pt - Map the graph representation for ADC channel
>> + * @x: Represent the ADC digitized code.
>> + * @y: Represent the physical data which can be temperature, voltage,
>> + *     resistance.
>> + */
>> +struct vadc_map_pt {
>> +	s32 x;
>> +	s32 y;
>> +};
>> +
>>  /*
>>   * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels.
>>   * VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for
>> @@ -148,6 +162,9 @@ struct vadc_prescale_ratio {
>>   *	start of conversion.
>>   * @avg_samples: ability to provide single result from the ADC
>>   *	that is an average of multiple measurements.
>> + * @scale_fn: Represents the scaling function to convert voltage
>> + *	physical units desired by the client for the channel.
>> + *	Referenced from enum vadc_scale_fn_type.
>>   */
>>  struct vadc_channel_prop {
>>  	unsigned int channel;
>> @@ -156,6 +173,7 @@ struct vadc_channel_prop {
>>  	unsigned int prescale;
>>  	unsigned int hw_settle_time;
>>  	unsigned int avg_samples;
>> +	unsigned int scale_fn;
>>  };
>>
>>  /**
>> @@ -186,6 +204,37 @@ struct vadc_priv {
>>  	struct mutex		 lock;
>>  };
>>
>> +/**
>> + * struct vadc_scale_fn - Scaling function prototype
>> + * @scale: Function pointer to one of the scaling functions
>> + *	which takes the adc properties, channel properties,
>> + *	and returns the physical result.
>> + */
>> +struct vadc_scale_fn {
>> +	int (*scale)(struct vadc_priv *, const struct vadc_channel_prop *,
>> +		     u16, int *);
>> +};
>> +
>> +/**
>> + * enum vadc_scale_fn_type - Scaling function to convert ADC code to
>> + *				physical scaled units for the channel.
>> + * SCALE_DEFAULT: Default scaling to convert raw adc code to voltage (uV).
>> + * SCALE_THERM_100K_PULLUP: Returns temperature in millidegC.
>> + *				 Uses a mapping table with 100K pullup.
>> + * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
>> + * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
>> + * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
>> + * SCALE_NONE: Do not use this scaling type.
>> + */
>> +enum vadc_scale_fn_type {
>> +	SCALE_DEFAULT = 0,
>> +	SCALE_THERM_100K_PULLUP,
>> +	SCALE_PMIC_THERM,
>> +	SCALE_XOTHERM,
>> +	SCALE_PMI_CHG_TEMP,
>> +	SCALE_NONE,
>> +};
>> +
>>  static const struct vadc_prescale_ratio vadc_prescale_ratios[] = {
>>  	{.num =  1, .den =  1},
>>  	{.num =  1, .den =  3},
>> @@ -197,6 +246,44 @@ struct vadc_priv {
>>  	{.num =  1, .den = 10}
>>  };
>>
>> +/* Voltage to temperature */
>> +static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
>> +	{1758,	-40},
>> +	{1742,	-35},
>> +	{1719,	-30},
>> +	{1691,	-25},
>> +	{1654,	-20},
>> +	{1608,	-15},
>> +	{1551,	-10},
>> +	{1483,	-5},
>> +	{1404,	0},
>> +	{1315,	5},
>> +	{1218,	10},
>> +	{1114,	15},
>> +	{1007,	20},
>> +	{900,	25},
>> +	{795,	30},
>> +	{696,	35},
>> +	{605,	40},
>> +	{522,	45},
>> +	{448,	50},
>> +	{383,	55},
>> +	{327,	60},
>> +	{278,	65},
>> +	{237,	70},
>> +	{202,	75},
>> +	{172,	80},
>> +	{146,	85},
>> +	{125,	90},
>> +	{107,	95},
>> +	{92,	100},
>> +	{79,	105},
>> +	{68,	110},
>> +	{59,	115},
>> +	{51,	120},
>> +	{44,	125}
>> +};
>> +
>>  static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data)
>>  {
>>  	return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1);
>> @@ -418,7 +505,7 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>>  	u16 read_1, read_2;
>>  	int ret;
>>
>> -	vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE_UV;
>> +	vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE;
>>  	vadc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV;
>>
>>  	prop = vadc_get_channel(vadc, VADC_REF_1250MV);
>> @@ -468,6 +555,51 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>>  	return ret;
>>  }
>>
>> +static int vadc_map_voltage_temp(const struct vadc_map_pt *pts,
>> +				 u32 tablesize, s32 input, s64 *output)
>> +{
>> +	bool descending = 1;
>> +	u32 i = 0;
>> +
>> +	if (!pts)
>> +		return -EINVAL;
>> +
>> +	/* Check if table is descending or ascending */
>> +	if (tablesize > 1) {
>> +		if (pts[0].x < pts[1].x)
>> +			descending = 0;
>> +	}
>> +
>> +	while (i < tablesize) {
>> +		if ((descending) && (pts[i].x < input)) {
>> +			/* table entry is less than measured*/
>> +			 /* value and table is descending, stop */
>> +			break;
>> +		} else if ((!descending) &&
>> +				(pts[i].x > input)) {
>> +			/* table entry is greater than measured*/
>> +			/*value and table is ascending, stop */
>> +			break;
>> +		}
>> +		i++;
>> +	}
>> +
>> +	if (i == 0) {
>> +		*output = pts[0].y;
>> +	} else if (i == tablesize) {
>> +		*output = pts[tablesize - 1].y;
>> +	} else {
>> +		/* result is between search_index and search_index-1 */
>> +		/* interpolate linearly */
>> +		*output = (((s32)((pts[i].y - pts[i - 1].y) *
>> +			(input - pts[i - 1].x)) /
>> +			(pts[i].x - pts[i - 1].x)) +
>> +			pts[i - 1].y);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  static void vadc_scale_calib(struct vadc_priv *vadc, u16 adc_code,
>>  			     const struct vadc_channel_prop *prop,
>>  			     s64 *scale_voltage)
>> @@ -502,6 +634,77 @@ static int vadc_scale_volt(struct vadc_priv *vadc,
>>  	return 0;
>>  }
>>
>> +static int vadc_scale_therm(struct vadc_priv *vadc,
>> +			    const struct vadc_channel_prop *prop, u16 adc_code,
>> +			    int *result_mdec)
>> +{
>> +	s64 voltage = 0, result = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> +		voltage /= 1000;
>> +
>> +	vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
>> +			      ARRAY_SIZE(adcmap_100k_104ef_104fb),
>> +			      voltage, &result);
>> +	result *= 1000;
>> +	*result_mdec = result;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale_die_temp(struct vadc_priv *vadc,
>> +			       const struct vadc_channel_prop *prop,
>> +			       u16 adc_code, int *result_mdec)
>> +{
>> +	const struct vadc_prescale_ratio *prescale;
>> +	s64 voltage = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	if (voltage > 0) {
>> +		prescale = &vadc_prescale_ratios[prop->prescale];
>> +		voltage = voltage * prescale->den;
>> +		voltage /= (prescale->num * 2);
>> +	} else {
>> +		voltage = 0;
>> +	}
>> +
>> +	voltage -= KELVINMIL_CELSIUSMIL;
>> +	*result_mdec = voltage;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale_chg_temp(struct vadc_priv *vadc,
>> +			       const struct vadc_channel_prop *prop,
>> +			       u16 adc_code, int *result_mdec)
>> +{
>> +	const struct vadc_prescale_ratio *prescale;
>> +	s64 voltage = 0, result = 0;
>> +
>> +	vadc_scale_calib(vadc, adc_code, prop, &voltage);
>> +
>> +	prescale = &vadc_prescale_ratios[prop->prescale];
>> +	voltage = voltage * prescale->den;
>> +	voltage = div64_s64(voltage, prescale->num);
>> +	voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
>> +	voltage = (voltage + PMI_CHG_SCALE_2);
>> +	result =  div64_s64(voltage, 1000000);
>> +	*result_mdec = result;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vadc_scale(struct vadc_priv *vadc,
>> +		      const struct vadc_channel_prop *prop, u16 adc_code,
>> +		      int *scale)
>> +{
>> +	dev_err(vadc->dev, "Need a scale function\n");
>> +	return 0;
>> +}
>> +
>>  static int vadc_decimation_from_dt(u32 value)
>>  {
>>  	if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
>> @@ -547,6 +750,15 @@ static int vadc_avg_samples_from_dt(u32 value)
>>  	return __ffs64(value);
>>  }
>>
>> +static struct vadc_scale_fn scale_fn[] = {
>> +	[SCALE_DEFAULT] = {vadc_scale_volt},
>> +	[SCALE_THERM_100K_PULLUP] = {vadc_scale_therm},
>> +	[SCALE_PMIC_THERM] = {vadc_scale_die_temp},
>> +	[SCALE_XOTHERM] = {vadc_scale_therm},
>> +	[SCALE_PMI_CHG_TEMP] = {vadc_scale_chg_temp},
>> +	[SCALE_NONE] = {vadc_scale},
>> +};
>> +
>>  static int vadc_read_raw(struct iio_dev *indio_dev,
>>  			 struct iio_chan_spec const *chan, int *val, int *val2,
>>  			 long mask)
>> @@ -563,7 +775,7 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>>  		if (ret)
>>  			break;
>>
>> -		vadc_scale_volt(vadc, prop, adc_code, val);
>> +		scale_fn[prop->scale_fn].scale(vadc, prop, adc_code, val);
>>
>>  		return IIO_VAL_INT;
>>  	case IIO_CHAN_INFO_RAW:
>> @@ -606,23 +818,27 @@ struct vadc_channels {
>>  	unsigned int prescale_index;
>>  	enum iio_chan_type type;
>>  	long info_mask;
>> +	unsigned int scale_fn;
>>  };
>>
>> -#define VADC_CHAN(_dname, _type, _mask, _pre)				\
>> +#define VADC_CHAN(_dname, _type, _mask, _pre, _scale)			\
>>  	[VADC_##_dname] = {						\
>>  		.datasheet_name = __stringify(_dname),			\
>>  		.prescale_index = _pre,					\
>>  		.type = _type,						\
>> -		.info_mask = _mask					\
>> +		.info_mask = _mask,					\
>> +		.scale_fn = _scale					\
>>  	},								\
>>
>> -#define VADC_CHAN_TEMP(_dname, _pre)					\
>> -	VADC_CHAN(_dname, IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED), _pre)	\
>> +#define VADC_CHAN_TEMP(_dname, _pre, _scale)				\
>> +	VADC_CHAN(_dname, IIO_TEMP,					\
>> +		BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),	\
>> +		_pre, _scale)						\
>>
>> -#define VADC_CHAN_VOLT(_dname, _pre)					\
>> +#define VADC_CHAN_VOLT(_dname, _pre, _scale)				\
>>  	VADC_CHAN(_dname, IIO_VOLTAGE,					\
>>  		  BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
>> -		  _pre)							\
>> +		  _pre, _scale)						\
>>
So here., Need to include support for "IIO_CHAN_INFO_SCALE" for 
"VADC_CHAN_VOLT" to provide backward compatibility and same support for 
"VADC_CHAN_TEMP" as well. Please correct me otherwise.

>>  /*
>>   * The array represents all possible ADC channels found in the supported PMICs.
>> @@ -630,106 +846,106 @@ struct vadc_channels {
>>   * gaps in the array should be treated as reserved channels.
>>   */
>>  static const struct vadc_channels vadc_chans[] = {
>> -	VADC_CHAN_VOLT(USBIN, 4)
>> -	VADC_CHAN_VOLT(DCIN, 4)
>> -	VADC_CHAN_VOLT(VCHG_SNS, 3)
>> -	VADC_CHAN_VOLT(SPARE1_03, 1)
>> -	VADC_CHAN_VOLT(USB_ID_MV, 1)
>> -	VADC_CHAN_VOLT(VCOIN, 1)
>> -	VADC_CHAN_VOLT(VBAT_SNS, 1)
>> -	VADC_CHAN_VOLT(VSYS, 1)
>> -	VADC_CHAN_TEMP(DIE_TEMP, 0)
>> -	VADC_CHAN_VOLT(REF_625MV, 0)
>> -	VADC_CHAN_VOLT(REF_1250MV, 0)
>> -	VADC_CHAN_VOLT(CHG_TEMP, 0)
>> -	VADC_CHAN_VOLT(SPARE1, 0)
>> -	VADC_CHAN_VOLT(SPARE2, 0)
>> -	VADC_CHAN_VOLT(GND_REF, 0)
>> -	VADC_CHAN_VOLT(VDD_VADC, 0)
>> -
>> -	VADC_CHAN_VOLT(P_MUX1_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX2_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX3_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX4_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX5_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX6_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX7_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX8_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX9_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX10_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX11_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX12_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX13_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX14_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX15_1_1, 0)
>> -	VADC_CHAN_VOLT(P_MUX16_1_1, 0)
>> -
>> -	VADC_CHAN_VOLT(P_MUX1_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX2_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX3_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX4_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX5_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX6_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX7_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX8_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX9_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX10_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX11_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX12_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX13_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX14_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX15_1_3, 1)
>> -	VADC_CHAN_VOLT(P_MUX16_1_3, 1)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_USB_ID, 0)
>> -	VADC_CHAN_VOLT(AMUX_PU1, 0)
>> -	VADC_CHAN_VOLT(AMUX_PU2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU1_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU1_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU1_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU1_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU1_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU1_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU1_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU1_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU1_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU1_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU2_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU2_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU2_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU2_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU2_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU2_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU2_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU2_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU2_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU2_XO_THERM, 0)
>> -
>> -	VADC_CHAN_VOLT(LR_MUX1_PU1_PU2_BAT_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX2_PU1_PU2_BAT_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_PU1_PU2_XO_THERM, 0)
>> -	VADC_CHAN_VOLT(LR_MUX4_PU1_PU2_AMUX_THM1, 0)
>> -	VADC_CHAN_VOLT(LR_MUX5_PU1_PU2_AMUX_THM2, 0)
>> -	VADC_CHAN_VOLT(LR_MUX6_PU1_PU2_AMUX_THM3, 0)
>> -	VADC_CHAN_VOLT(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX8_PU1_PU2_AMUX_THM4, 0)
>> -	VADC_CHAN_VOLT(LR_MUX9_PU1_PU2_AMUX_THM5, 0)
>> -	VADC_CHAN_VOLT(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0)
>> -	VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0)
>> +	VADC_CHAN_VOLT(USBIN, 4, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(DCIN, 4, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VCHG_SNS, 3, SCALE_NONE)
>> +	VADC_CHAN_VOLT(SPARE1_03, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(USB_ID_MV, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(VCOIN, 1, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VBAT_SNS, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(VSYS, 1, SCALE_DEFAULT)
>> +	VADC_CHAN_TEMP(DIE_TEMP, 0, SCALE_PMIC_THERM)
>> +	VADC_CHAN_VOLT(REF_625MV, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(REF_1250MV, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(CHG_TEMP, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(SPARE1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(SPARE2, 0, SCALE_PMI_CHG_TEMP)
>> +	VADC_CHAN_VOLT(GND_REF, 0, SCALE_DEFAULT)
>> +	VADC_CHAN_VOLT(VDD_VADC, 0, SCALE_DEFAULT)
>> +
>> +	VADC_CHAN_VOLT(P_MUX1_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX2_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX3_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX4_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX5_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX6_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX7_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX8_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX9_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX10_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX11_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX12_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX13_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX14_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX15_1_1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX16_1_1, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_VOLT(P_MUX1_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX2_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX3_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX4_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX5_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX6_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX7_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX8_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX9_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX10_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX11_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX12_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX13_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX14_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX15_1_3, 1, SCALE_NONE)
>> +	VADC_CHAN_VOLT(P_MUX16_1_3, 1, SCALE_NONE)
>> +
>> +	VADC_CHAN_VOLT(LR_MUX1_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX3_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX4_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX5_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX6_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX8_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX9_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(AMUX_PU1, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(AMUX_PU2, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX3_BUF_XO_THERM, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU1_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU1_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU1_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU1_AMUX_THM1, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU1_AMUX_THM2, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU1_AMUX_THM3, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU1_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU1_AMUX_THM4, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU1_AMUX_THM5, 0, SCALE_THERM_100K_PULLUP)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU1_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU1_XO_THERM, 0, SCALE_XOTHERM)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU2_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU2_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU2_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU2_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU2_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU2_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU2_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU2_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU2_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU2_XO_THERM, 0, SCALE_NONE)
>> +
>> +	VADC_CHAN_TEMP(LR_MUX1_PU1_PU2_BAT_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX2_PU1_PU2_BAT_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_PU1_PU2_XO_THERM, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX4_PU1_PU2_AMUX_THM1, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX5_PU1_PU2_AMUX_THM2, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX6_PU1_PU2_AMUX_THM3, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX8_PU1_PU2_AMUX_THM4, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX9_PU1_PU2_AMUX_THM5, 0, SCALE_NONE)
>> +	VADC_CHAN_VOLT(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0, SCALE_NONE)
>> +	VADC_CHAN_TEMP(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0, SCALE_NONE)
>>  };
>>
>>  static int vadc_get_dt_channel_data(struct device *dev,
>> @@ -847,7 +1063,7 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node)
>>  			of_node_put(child);
>>  			return ret;
>>  		}
>> -
> If I was being really fussy... This white space is as valid as it was before this
> addition so shouldn't really have been removed ;)
Sure., Will retain this new line in the next patch.
>> +		prop.scale_fn = vadc_chans[prop.channel].scale_fn;
>>  		vadc->chan_props[index] = prop;
>>
>>  		vadc_chan = &vadc_chans[prop.channel];
>>
>

Thanks,
Ramakrishna

^ permalink raw reply

* Re: [PATCH for-4.8 2/2] x86/traps: Don't call hvm_hypervisor_cpuid_leaf() for PV guests
From: Jan Beulich @ 2016-11-14 11:38 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Wei Liu, Xen-devel
In-Reply-To: <1479121286-6390-2-git-send-email-andrew.cooper3@citrix.com>

>>> On 14.11.16 at 12:01, <andrew.cooper3@citrix.com> wrote:
> Luckily, hvm_hypervisor_cpuid_leaf() and vmx_hypervisor_cpuid_leaf() are safe
> to execute in the context of a PV guest, but HVM-specific feature flags
> shouldn't be visible to PV guests.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
albeit ...

> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -928,6 +928,11 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>          break;
>  
>      case 4:
> +        if ( !has_hvm_container_domain(currd) )
> +        {
> +            *eax = *ebx = *ecx = *edx = 0;
> +            break;
> +        }
>          hvm_hypervisor_cpuid_leaf(sub_idx, eax, ebx, ecx, edx);
>          break;

... this being the last leaf, wouldn't we better limit the number of
leaves (reported in leaf 0) to 3 for PV?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply

* Re: [PATCH] Fixup packets with incorrect ethertype sent by ZTE MF821D
From: Bjørn Mork @ 2016-11-14 11:37 UTC (permalink / raw)
  To: Jussi Peltola; +Cc: netdev
In-Reply-To: <20161114002218.GW2745@pokute.pelzi.net>

Jussi Peltola <plz@plz.fi> writes:

> So here's another stab. The comments and the current implementation are
> not in sync: any non-multicast address starting with a null octet gets
> rewritten, while the comment specifically mentions 00:a0:c6:00:00:00. It
> is certainly not elegant but re-writing all unicast destinations with
> our address does come to mind instead of special cases.

The known bug is related to 00:a0:c6:00:00:00 only.  But the workaround
catches anything starting with 00 for simplicity.  It's a deliberate
trade-off.  Could probably be clearer from the comments, yes.

> This patch fails to handle the invalid destinations in either way so I
> will send another one if you think it's worthwhile to go on. And it
> seems I forgot htons but I need this device for work now so a better
> patch must wait :)
>
> commit 35d3a46b7f1ece70e24386acbdd16af4507cb5f3
> Author: Jussi Peltola <plz@plz.fi>
> Date:   Mon Nov 14 01:45:32 2016 +0200
>
>     Attempt to fix up packets with a broken ethernet header
>     
>     Signed-off-by: Jussi Peltola <plz@plz.fi>
>
> diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> index 3ff76c6..7308d6b 100644
> --- a/drivers/net/usb/qmi_wwan.c
> +++ b/drivers/net/usb/qmi_wwan.c
> @@ -153,25 +153,57 @@ static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
>  
>  static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
>  
> -/* Make up an ethernet header if the packet doesn't have one.
> +/* Check if the ethernet header has an unknown ethertype, and return a
> + * guess of the correct one based on the L3 header, or zero if the type was
> + * known or detection failed.
> + */
> +static __be16 detect_bogus_header(struct sk_buff *skb) {
> +       struct ethhdr *eth_hdr = (struct ethhdr*) skb->data;
> +
> +       switch (eth_hdr->h_proto) {
> +       case ETH_P_IP:
> +       case ETH_P_IPV6:
> +       case ETH_P_ARP:
> +               return 0;
> +       default:
> +               switch (skb->data[14] & 0xf0) {
> +               case 0x40:
> +                       return htons(ETH_P_IP);
> +               case 0x60:
> +                       return htons(ETH_P_IPV6);
> +               default:
> +                       /* pass on undetectable packets */
> +                       return 0;
> +               }
> +       }
> +       /*NOTREACHED*/
> +       return 0;
> +}
> +
> +/* Make up an ethernet header if the packet doesn't have a correct one.
>   *
>   * A firmware bug common among several devices cause them to send raw
>   * IP packets under some circumstances.  There is no way for the
>   * driver/host to know when this will happen.  And even when the bug
>   * hits, some packets will still arrive with an intact header.
>   *
> - * The supported devices are only capably of sending IPv4, IPv6 and
> + * The supported devices are only capable of sending IPv4, IPv6 and
>   * ARP packets on a point-to-point link. Any packet with an ethernet
>   * header will have either our address or a broadcast/multicast
> - * address as destination.  ARP packets will always have a header.
> + * address as destination. ARP packets will always have a header.
>   *
>   * This means that this function will reliably add the appropriate
> - * header iff necessary, provided our hardware address does not start
> + * header if necessary, provided our hardware address does not start
>   * with 4 or 6.
>   *
>   * Another common firmware bug results in all packets being addressed
>   * to 00:a0:c6:00:00:00 despite the host address being different.
> - * This function will also fixup such packets.
> + *
> + * Some devices will send packets with garbage source/destination MACs and
> + * ethertypes.
> + *
> + * This function will try to fix up all such packets.
> + *
>   */
>  static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>  {
> @@ -179,8 +211,8 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>         bool rawip = info->flags & QMI_WWAN_FLAG_RAWIP;
>         __be16 proto;
>  
> -       /* This check is no longer done by usbnet */
> -       if (skb->len < dev->net->hard_header_len)
> +       /* Shorter is definitely invalid and breaks subsequent tests */
> +       if (skb->len < 15)
>                 return 0;
>  
>         switch (skb->data[0] & 0xf0) {


Makes sense, but could we please use some reasonable macro or something
instead of an arbitrary magic number?  Anything shorter than an IP
header will be bogus, for example.



> @@ -190,17 +222,17 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>         case 0x60:
>                 proto = htons(ETH_P_IPV6);
>                 break;
> -       case 0x00:
> +       default:
>                 if (rawip)
>                         return 0;
>                 if (is_multicast_ether_addr(skb->data))
>                         return 1;
> -               /* possibly bogus destination - rewrite just in case */
> -               skb_reset_mac_header(skb);
> -               goto fix_dest;
> -       default:
> -               if (rawip)
> -                       return 0;
> +               proto = detect_bogus_header(skb);
> +               if (proto) {
> +                       /* remove terminally broken header */
> +                       skb_pull(skb, ETH_HLEN);
> +                       break;
> +               }
>                 /* pass along other packets without modifications */
>                 return 1;
>         }


Am I missing somehting, or is this removing the bogus destination
address fixup?  In any case, I don't have any device with that bug
available or the time to go and test it.  So I want you to either leave
that part of the code alone, or verify the workaround on a device with
the "00:a0:c6:00:00:00" bug.


> @@ -208,17 +240,17 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>                 skb->dev = dev->net; /* normally set by eth_type_trans */
>                 skb->protocol = proto;
>                 return 1;
> +       } else {


Completely unnecessary "else". We return from the other branch.

In any case, this change is not related to the rest of the patch and is
just making review more confusing.  And why would you add more indenting
levels than strictly necessary?


But please: Try to make the device work with raw-ip first. Qualcomm
never managed to fix their fake ethernet mode, and have given up on it.
Newer devices don't have that mode at all.  The device you have does
still have the mode.  But as is pretty obvious from the observed
behaviour: It's completely untested and not really working.  If you look
at the Windows driver, I'm pretty sure you'll find that the only reason
it works is because they use raw-ip mode.

FWIW, I regret having chosen the fake ethernet mode as the default for
qmi_wwan.  I did not anticipate the number of firmware issues Qualcomm
could manage to create simply adding a made-up ethernet header.  And I
did not anticipate them finally dropping it on the floor, forcing us to
support raw-ip mode anyway.

But with raw-ip support, there is absolutely no reason to play around
with fixing up the ethernet header bugs anymore.  If you have an older
device where it sort of works, then by all means use it.  But otherwise:
Use raw-ip mode.  I don't think I would have wanted any of the existing
header fixups either if the driver had supported raw-ip when they were
proposed.


Bjørn

^ permalink raw reply

* [Bug 98578] AMDGPU white glitches in some games
From: bugzilla-daemon @ 2016-11-14 11:37 UTC (permalink / raw)
  To: dri-devel
In-Reply-To: <bug-98578-502@http.bugs.freedesktop.org/>


[-- Attachment #1.1: Type: text/plain, Size: 650 bytes --]

https://bugs.freedesktop.org/show_bug.cgi?id=98578

--- Comment #8 from Nicolai Hähnle <nhaehnle@gmail.com> ---
This took a while to track down. There is a shader (source @9633678, linked
into program 1127) which relies on -inf * +F == -inf. LLVM transforms the
shader in such a way that the result becomes a NaN instead (visible at a single
pixel @ 953,0 in the final frame of the trimmed trace at @14722003), which then
propagates to an ugly white square in post-processing. The LLVM transform is
simply incorrect and fixed by https://reviews.llvm.org/D26602.

-- 
You are receiving this mail because:
You are the assignee for the bug.

[-- Attachment #1.2: Type: text/html, Size: 1463 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI(v2)
From: Liu, Monk @ 2016-11-14 11:37 UTC (permalink / raw)
  To: Liu, Monk, amd-gfx-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org
In-Reply-To: <1479094665-5938-1-git-send-email-Monk.Liu-5C7GfCeVMHo@public.gmane.org>

If no one review it I'm going to push it later

-----邮件原件-----
发件人: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] 代表 Monk Liu
发送时间: Monday, November 14, 2016 11:38 AM
收件人: amd-gfx@freedesktop.org
抄送: Liu, Monk
主题: [PATCH] drm/amdgpu:impl vgt_flush for VI(v2)

when shadowing enabled, tesselation app will trigger vm fault because below three tesselation registers:

VGT_TF_RING_SIZE__CI__VI,
VGT_HS_OFFCHIP_PARAM__CI__VI,
VGT_TF_MEMORY_BASE__CI__VI,

need to be programed after vgt-flush.

Tesselation picture vm fault disappeared after vgt-flush introduced.

v2:implement vgt-flush for CI & SI.

Change-Id: I77d87d93ce6580e559e734fb41d97ee8c59d245b
Signed-off-by: Monk Liu <Monk.Liu@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h      |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c   |  5 ++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h |  1 +
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c    |  8 ++++++++
 drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c    | 13 +++++++++++++
 drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c    | 13 +++++++++++++
 6 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 15015bc..f46e96b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1630,6 +1630,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)  #define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags))  #define amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab), (as))  #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r))
+#define amdgpu_ring_emit_vgt_flush(r) (r)->funcs->emit_vgt_flush((r))
 #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
 #define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
 #define amdgpu_ring_emit_cntxcntl(r, d) (r)->funcs->emit_cntxcntl((r), (d)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index acf48de..c039890 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -175,11 +175,14 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
 	if (ring->funcs->emit_hdp_flush)
 		amdgpu_ring_emit_hdp_flush(ring);
 
+	need_ctx_switch = ring->current_ctx != fence_ctx;
+	if (ring->funcs->emit_vgt_flush && need_ctx_switch)
+		 amdgpu_ring_emit_vgt_flush(ring);
+
 	/* always set cond_exec_polling to CONTINUE */
 	*ring->cond_exe_cpu_addr = 1;
 
 	skip_preamble = ring->current_ctx == fence_ctx;
-	need_ctx_switch = ring->current_ctx != fence_ctx;
 	if (job && ring->funcs->emit_cntxcntl) {
 		if (need_ctx_switch)
 			status |= AMDGPU_HAVE_CTX_SWITCH;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 92bc89b..c3a7329 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -116,6 +116,7 @@ struct amdgpu_ring_funcs {
 	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
 			      uint64_t pd_addr);
 	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
+	void (*emit_vgt_flush)(struct amdgpu_ring *ring);
 	void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
 	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
 				uint32_t gds_base, uint32_t gds_size, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 9423501..77f906e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -1463,6 +1463,13 @@ static void gfx_v6_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 	amdgpu_ring_write(ring, 0x1);
 }
 
+static void gfx_v6_0_ring_emit_vgt_flush(struct amdgpu_ring *ring) {
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
 /**
  * gfx_v6_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
  *
@@ -3272,6 +3279,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 	.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
 	.emit_vm_flush = gfx_v6_0_ring_emit_vm_flush,
 	.emit_hdp_flush = gfx_v6_0_ring_emit_hdp_flush,
+	.emit_vgt_flush = gfx_v6_0_ring_emit_vgt_flush,
 	.emit_hdp_invalidate = gfx_v6_0_ring_emit_hdp_invalidate,
 	.test_ring = gfx_v6_0_ring_test_ring,
 	.test_ib = gfx_v6_0_ring_test_ib,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index bd9a6c8..01e5ad4 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -2105,6 +2105,18 @@ static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 	amdgpu_ring_write(ring, 0x20); /* poll interval */  }
 
+static void gfx_v7_0_ring_emit_vgt_flush(struct amdgpu_ring *ring) {
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+		EVENT_INDEX(4));
+
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
+
 /**
  * gfx_v7_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
  *
@@ -5155,6 +5167,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
 	.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
 	.emit_gds_switch = gfx_v7_0_ring_emit_gds_switch,
 	.emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush,
+	.emit_vgt_flush = gfx_v7_0_ring_emit_vgt_flush,
 	.emit_hdp_invalidate = gfx_v7_0_ring_emit_hdp_invalidate,
 	.test_ring = gfx_v7_0_ring_test_ring,
 	.test_ib = gfx_v7_0_ring_test_ib,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 9017803..1d407d76 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -6187,6 +6187,18 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 	amdgpu_ring_write(ring, 0x20); /* poll interval */  }
 
+static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring) {
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+		EVENT_INDEX(4));
+
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
+
 static void gfx_v8_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)  {
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); @@ -6590,6 +6602,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.emit_switch_buffer = gfx_v8_ring_emit_sb,
 	.emit_cntxcntl = gfx_v8_ring_emit_cntxcntl,
+	.emit_vgt_flush = gfx_v8_0_ring_emit_vgt_flush,
 };
 
 static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
--
1.9.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related

* Re: [PATCH] broadcom/brcm80211/brcmfmac/cfg80211 driver, bad regulatory domain frequency value
From: Arend Van Spriel @ 2016-11-14 11:36 UTC (permalink / raw)
  To: Gianfranco Costamagna, brcm80211-dev-list@broadcom.com,
	linux-wireless@vger.kernel.org
  Cc: nsmaldone@tierratelematics.com, Marco.Arlone@roj.com
In-Reply-To: <233918815.6357602.1479123253455@mail.yahoo.com>

On 14-11-2016 12:34, Gianfranco Costamagna wrote:
> Hi Arend,
> 
> 
>> Finally response. As it turns out the range was explcitly changed
> 
>> enabling channels 12 and 13 to be used where applicable. They forgot to
>> update the comment.
> 
> 
> so, the struct in net/wireless/reg.c is actually used in that case?
> 
> static const struct ieee80211_regdomain world_regdom = {
> 
> do you plan to update the comment?

Well, not before you pointed it out ;-). You are welcome to send a patch
fixing it. Otherwise, I will take care of it.

Regards,
Arend

^ permalink raw reply

* Re: [PATCH v4 7/8] v4l: Add signal lock status to source change events
From: Hans Verkuil @ 2016-11-14 11:36 UTC (permalink / raw)
  To: Steve Longerbeam, lars
  Cc: mchehab, linux-media, linux-kernel, Steve Longerbeam,
	Mauro Carvalho Chehab
In-Reply-To: <1470247430-11168-8-git-send-email-steve_longerbeam@mentor.com>

On 08/03/2016 08:03 PM, Steve Longerbeam wrote:
> Add a signal lock status change to the source changes bitmask.
> This indicates there was a signal lock or unlock event detected
> at the input of a video decoder.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> 
> ---
> 
> v4:
> - converted to rst from DocBook
> 
> v3: no changes
> v2: no changes
> ---
>  Documentation/media/uapi/v4l/vidioc-dqevent.rst | 9 +++++++++
>  Documentation/media/videodev2.h.rst.exceptions  | 1 +
>  include/uapi/linux/videodev2.h                  | 1 +
>  3 files changed, 11 insertions(+)
> 
> diff --git a/Documentation/media/uapi/v4l/vidioc-dqevent.rst b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
> index 73c0d5b..7d8a053 100644
> --- a/Documentation/media/uapi/v4l/vidioc-dqevent.rst
> +++ b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
> @@ -564,6 +564,15 @@ call.
>  	  an input. This can come from an input connector or from a video
>  	  decoder.
>  
> +    -  .. row 2
> +
> +       -  ``V4L2_EVENT_SRC_CH_LOCK_STATUS``
> +
> +       -  0x0002
> +
> +       -  This event gets triggered when there is a signal lock or
> +	  unlock detected at the input of a video decoder.
> +
>  
>  Return Value
>  ============
> diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
> index 9bb9a6c..f412cc8 100644
> --- a/Documentation/media/videodev2.h.rst.exceptions
> +++ b/Documentation/media/videodev2.h.rst.exceptions
> @@ -453,6 +453,7 @@ replace define V4L2_EVENT_CTRL_CH_FLAGS ctrl-changes-flags
>  replace define V4L2_EVENT_CTRL_CH_RANGE ctrl-changes-flags
>  
>  replace define V4L2_EVENT_SRC_CH_RESOLUTION src-changes-flags
> +replace define V4L2_EVENT_SRC_CH_LOCK_STATUS src-changes-flags
>  
>  replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ v4l2-event-motion-det
>  
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 724f43e..08a153f 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -2078,6 +2078,7 @@ struct v4l2_event_frame_sync {
>  };
>  
>  #define V4L2_EVENT_SRC_CH_RESOLUTION		(1 << 0)
> +#define V4L2_EVENT_SRC_CH_LOCK_STATUS		(1 << 1)
>  
>  struct v4l2_event_src_change {
>  	__u32 changes;
> 

Quoting from an old (July) conversation about this:

>> > I'm not entirely sure I like this. Typically losing lock means that this event
>> > is triggered with the V4L2_EVENT_SRC_CH_RESOLUTION flag set, and userspace has
>> > to check the new timings etc., which will fail if there is no lock anymore.
>> >
>> > This information is also available through ENUMINPUT.
>> >
>> > I would need to know more about why you think this is needed, because I don't
>> > see what this adds.
> 
> Hi Hans,
> 
> At least on the ADV718x, a source resolution change (from an 
> autodetected video
> standard change) and a signal lock status change are distinct events. 
> For example
> there can be a temporary loss of input signal lock without a change in 
> detected
> input video standard/resolution.

OK, but what can the application do with that event? If the glitch didn't
affect the video, then it is pointless.

If the lock is lost, then normally you loose video as well. If not, then
applications are not interested in the event.

So I am not convinced...

Regards,

	Hans

^ permalink raw reply

* Re: [PATCH for-4.8 1/2] x86/vmx: Correct the long mode check in vmx_cpuid_intercept()
From: Jan Beulich @ 2016-11-14 11:35 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Kevin Tian, Wei Liu, Jun Nakajima, Xen-devel
In-Reply-To: <1479121286-6390-1-git-send-email-andrew.cooper3@citrix.com>

>>> On 14.11.16 at 12:01, <andrew.cooper3@citrix.com> wrote:
> %cs.L may be set in a legacy mode segment, or clear in a compatibility mode
> segment; it is not the correct way to check for long mode being active.
> 
> Both of these situations result in incorrect visibility of the SYSCALL feature
> in CPUID, and by extension, incorrect behaviour in hvm_efer_valid().
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.