Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6] atmel_flexcom: Support resuming after a chip reset
From: Alexandre Belloni @ 2017-12-18 20:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171212162119.32138-1-romain.izard.pro@gmail.com>

On 12/12/2017 at 17:21:19 +0100, Romain Izard wrote:
> The controller used by a flexcom module is configured at boot, and left
> alone after this. In the suspend mode called "backup with self-refresh"
> available on SAMA5D2, the chip will resume with most of its registers
> reset. In this case, we need to restore the state of the flexcom driver
> on resume.
> 
> Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>

Seems good to me

Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

> ---
> Changes in v5:
> * extract from the patch series, and send as a standalone patch
> 
> Changes in v6:
> * Reword the patch title and description
> * Rename the internal structure to ddata
> 
>  drivers/mfd/atmel-flexcom.c | 63 ++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 48 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
> index 064bde9cff5a..f684a93a3340 100644
> --- a/drivers/mfd/atmel-flexcom.c
> +++ b/drivers/mfd/atmel-flexcom.c
> @@ -39,34 +39,43 @@
>  #define FLEX_MR_OPMODE(opmode)	(((opmode) << FLEX_MR_OPMODE_OFFSET) &	\
>  				 FLEX_MR_OPMODE_MASK)
>  
> +struct atmel_flexcom {
> +	void __iomem *base;
> +	u32 opmode;
> +	struct clk *clk;
> +};
>  
>  static int atmel_flexcom_probe(struct platform_device *pdev)
>  {
>  	struct device_node *np = pdev->dev.of_node;
> -	struct clk *clk;
>  	struct resource *res;
> -	void __iomem *base;
> -	u32 opmode;
> +	struct atmel_flexcom *ddata;
>  	int err;
>  
> -	err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode);
> +	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
> +	if (!ddata)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, ddata);
> +
> +	err = of_property_read_u32(np, "atmel,flexcom-mode", &ddata->opmode);
>  	if (err)
>  		return err;
>  
> -	if (opmode < ATMEL_FLEXCOM_MODE_USART ||
> -	    opmode > ATMEL_FLEXCOM_MODE_TWI)
> +	if (ddata->opmode < ATMEL_FLEXCOM_MODE_USART ||
> +	    ddata->opmode > ATMEL_FLEXCOM_MODE_TWI)
>  		return -EINVAL;
>  
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(base))
> -		return PTR_ERR(base);
> +	ddata->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(ddata->base))
> +		return PTR_ERR(ddata->base);
>  
> -	clk = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(clk))
> -		return PTR_ERR(clk);
> +	ddata->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(ddata->clk))
> +		return PTR_ERR(ddata->clk);
>  
> -	err = clk_prepare_enable(clk);
> +	err = clk_prepare_enable(ddata->clk);
>  	if (err)
>  		return err;
>  
> @@ -76,9 +85,9 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
>  	 * inaccessible and are read as zero. Also the external I/O lines of the
>  	 * Flexcom are muxed to reach the selected device.
>  	 */
> -	writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR);
> +	writel(FLEX_MR_OPMODE(ddata->opmode), ddata->base + FLEX_MR);
>  
> -	clk_disable_unprepare(clk);
> +	clk_disable_unprepare(ddata->clk);
>  
>  	return devm_of_platform_populate(&pdev->dev);
>  }
> @@ -89,10 +98,34 @@ static const struct of_device_id atmel_flexcom_of_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int atmel_flexcom_resume(struct device *dev)
> +{
> +	struct atmel_flexcom *ddata = dev_get_drvdata(dev);
> +	int err;
> +	u32 val;
> +
> +	err = clk_prepare_enable(ddata->clk);
> +	if (err)
> +		return err;
> +
> +	val = FLEX_MR_OPMODE(ddata->opmode),
> +	writel(val, ddata->base + FLEX_MR);
> +
> +	clk_disable_unprepare(ddata->clk);
> +
> +	return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(atmel_flexcom_pm_ops, NULL,
> +			 atmel_flexcom_resume);
> +
>  static struct platform_driver atmel_flexcom_driver = {
>  	.probe	= atmel_flexcom_probe,
>  	.driver	= {
>  		.name		= "atmel_flexcom",
> +		.pm		= &atmel_flexcom_pm_ops,
>  		.of_match_table	= atmel_flexcom_of_match,
>  	},
>  };
> -- 
> 2.14.1
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 3/8] media: v4l2-async: simplify v4l2_async_subdev structure
From: Benoit Parrot @ 2017-12-18 20:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <014b64d13c8b9d516afc3319a9de1a97b2a845de.1513625884.git.mchehab@s-opensource.com>

For am437x/am437x-vpfe.c & ti-vpe/cal.c

Acked-by: Benoit Parrot <bparrot@ti.com>

Mauro Carvalho Chehab <mchehab@s-opensource.com> wrote on Mon [2017-Dec-18 17:53:57 -0200]:
> The V4L2_ASYNC_MATCH_FWNODE match criteria requires just one
> struct to be filled (struct fwnode_handle). The V4L2_ASYNC_MATCH_DEVNAME
> match criteria requires just a device name.
> 
> So, it doesn't make sense to enclose those into structs,
> as the criteria can go directly into the union.
> 
> That makes easier to document it, as we don't need to document
> weird senseless structs.
> 
> At drivers, this makes even clearer about the match criteria.
> 
> Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> ---
>  drivers/media/platform/am437x/am437x-vpfe.c    |  6 +++---
>  drivers/media/platform/atmel/atmel-isc.c       |  2 +-
>  drivers/media/platform/atmel/atmel-isi.c       |  2 +-
>  drivers/media/platform/davinci/vpif_capture.c  |  4 ++--
>  drivers/media/platform/exynos4-is/media-dev.c  |  4 ++--
>  drivers/media/platform/pxa_camera.c            |  2 +-
>  drivers/media/platform/qcom/camss-8x16/camss.c |  2 +-
>  drivers/media/platform/rcar-vin/rcar-core.c    |  2 +-
>  drivers/media/platform/rcar_drif.c             |  4 ++--
>  drivers/media/platform/soc_camera/soc_camera.c |  2 +-
>  drivers/media/platform/stm32/stm32-dcmi.c      |  2 +-
>  drivers/media/platform/ti-vpe/cal.c            |  2 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c    |  2 +-
>  drivers/media/v4l2-core/v4l2-async.c           | 16 ++++++++--------
>  drivers/media/v4l2-core/v4l2-fwnode.c          | 10 +++++-----
>  drivers/staging/media/imx/imx-media-dev.c      |  4 ++--
>  include/media/v4l2-async.h                     |  8 ++------
>  17 files changed, 35 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
> index 0997c640191d..601ae6487617 100644
> --- a/drivers/media/platform/am437x/am437x-vpfe.c
> +++ b/drivers/media/platform/am437x/am437x-vpfe.c
> @@ -2304,8 +2304,8 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
>  	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
>  
>  	for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
> -		if (vpfe->cfg->asd[i]->match.fwnode.fwnode ==
> -		    asd[i].match.fwnode.fwnode) {
> +		if (vpfe->cfg->asd[i]->match.fwnode ==
> +		    asd[i].match.fwnode) {
>  			sdinfo = &vpfe->cfg->sub_devs[i];
>  			vpfe->sd[i] = subdev;
>  			vpfe->sd[i]->grp_id = sdinfo->grp_id;
> @@ -2510,7 +2510,7 @@ vpfe_get_pdata(struct platform_device *pdev)
>  		}
>  
>  		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		pdata->asd[i]->match.fwnode.fwnode = of_fwnode_handle(rem);
> +		pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
>  		of_node_put(rem);
>  	}
>  
> diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c
> index 0c2635647f69..34676409ca08 100644
> --- a/drivers/media/platform/atmel/atmel-isc.c
> +++ b/drivers/media/platform/atmel/atmel-isc.c
> @@ -2088,7 +2088,7 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
>  			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
>  
>  		subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		subdev_entity->asd->match.fwnode.fwnode =
> +		subdev_entity->asd->match.fwnode =
>  			of_fwnode_handle(rem);
>  		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
>  	}
> diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
> index e900995143a3..9958918e2449 100644
> --- a/drivers/media/platform/atmel/atmel-isi.c
> +++ b/drivers/media/platform/atmel/atmel-isi.c
> @@ -1128,7 +1128,7 @@ static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node)
>  		/* Remote node to connect */
>  		isi->entity.node = remote;
>  		isi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		isi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
> +		isi->entity.asd.match.fwnode = of_fwnode_handle(remote);
>  		return 0;
>  	}
>  }
> diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
> index e45916f69def..e1c273c8b9a6 100644
> --- a/drivers/media/platform/davinci/vpif_capture.c
> +++ b/drivers/media/platform/davinci/vpif_capture.c
> @@ -1390,7 +1390,7 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier,
>  
>  	for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) {
>  		struct v4l2_async_subdev *_asd = vpif_obj.config->asd[i];
> -		const struct fwnode_handle *fwnode = _asd->match.fwnode.fwnode;
> +		const struct fwnode_handle *fwnode = _asd->match.fwnode;
>  
>  		if (fwnode == subdev->fwnode) {
>  			vpif_obj.sd[i] = subdev;
> @@ -1595,7 +1595,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
>  		}
>  
>  		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		pdata->asd[i]->match.fwnode.fwnode = of_fwnode_handle(rem);
> +		pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
>  		of_node_put(rem);
>  	}
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index 0ef583cfc424..78b48a1fa26c 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -456,7 +456,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
>  	}
>  
>  	fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	fmd->sensor[index].asd.match.fwnode.fwnode = of_fwnode_handle(rem);
> +	fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
>  	fmd->async_subdevs[index] = &fmd->sensor[index].asd;
>  
>  	fmd->num_sensors++;
> @@ -1364,7 +1364,7 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
>  
>  	/* Find platform data for this sensor subdev */
>  	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
> -		if (fmd->sensor[i].asd.match.fwnode.fwnode ==
> +		if (fmd->sensor[i].asd.match.fwnode ==
>  		    of_fwnode_handle(subdev->dev->of_node))
>  			si = &fmd->sensor[i];
>  
> diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
> index 305cf1cac210..f028084f0775 100644
> --- a/drivers/media/platform/pxa_camera.c
> +++ b/drivers/media/platform/pxa_camera.c
> @@ -2335,7 +2335,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
>  	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
>  	remote = of_graph_get_remote_port(np);
>  	if (remote) {
> -		asd->match.fwnode.fwnode = of_fwnode_handle(remote);
> +		asd->match.fwnode = of_fwnode_handle(remote);
>  		of_node_put(remote);
>  	} else {
>  		dev_notice(dev, "no remote for %pOF\n", np);
> diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c
> index 390a42c17b66..05f06c98aa64 100644
> --- a/drivers/media/platform/qcom/camss-8x16/camss.c
> +++ b/drivers/media/platform/qcom/camss-8x16/camss.c
> @@ -341,7 +341,7 @@ static int camss_of_parse_ports(struct device *dev,
>  		}
>  
>  		csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		csd->asd.match.fwnode.fwnode = of_fwnode_handle(remote);
> +		csd->asd.match.fwnode = of_fwnode_handle(remote);
>  	}
>  
>  	return notifier->num_subdevs;
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
> index 108d776f3265..f1fc7978d6d1 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -187,7 +187,7 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
>  		return -ENODEV;
>  
>  	vin_dbg(vin, "Found digital subdevice %pOF\n",
> -		to_of_node(vin->digital->asd.match.fwnode.fwnode));
> +		to_of_node(vin->digital->asd.match.fwnode));
>  
>  	vin->notifier.ops = &rvin_digital_notify_ops;
>  	ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
> diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
> index 63c94f4028a7..b2e080ef5391 100644
> --- a/drivers/media/platform/rcar_drif.c
> +++ b/drivers/media/platform/rcar_drif.c
> @@ -1107,7 +1107,7 @@ static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier,
>  	struct rcar_drif_sdr *sdr =
>  		container_of(notifier, struct rcar_drif_sdr, notifier);
>  
> -	if (sdr->ep.asd.match.fwnode.fwnode !=
> +	if (sdr->ep.asd.match.fwnode !=
>  	    of_fwnode_handle(subdev->dev->of_node)) {
>  		rdrif_err(sdr, "subdev %s cannot bind\n", subdev->name);
>  		return -EINVAL;
> @@ -1235,7 +1235,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
>  		return -EINVAL;
>  	}
>  
> -	sdr->ep.asd.match.fwnode.fwnode = fwnode;
> +	sdr->ep.asd.match.fwnode = fwnode;
>  	sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
>  	notifier->num_subdevs++;
>  
> diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
> index 916ff68b73d4..d13e2c5fb06f 100644
> --- a/drivers/media/platform/soc_camera/soc_camera.c
> +++ b/drivers/media/platform/soc_camera/soc_camera.c
> @@ -1517,7 +1517,7 @@ static int soc_of_bind(struct soc_camera_host *ici,
>  	if (!info)
>  		return -ENOMEM;
>  
> -	info->sasd.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
> +	info->sasd.asd.match.fwnode = of_fwnode_handle(remote);
>  	info->sasd.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
>  	info->subdev = &info->sasd.asd;
>  
> diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
> index ac4c450a6c7d..9460b3080dca 100644
> --- a/drivers/media/platform/stm32/stm32-dcmi.c
> +++ b/drivers/media/platform/stm32/stm32-dcmi.c
> @@ -1520,7 +1520,7 @@ static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
>  		/* Remote node to connect */
>  		dcmi->entity.node = remote;
>  		dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		dcmi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
> +		dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
>  		return 0;
>  	}
>  }
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 719ed1d79957..d1febe5baa6d 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -1702,7 +1702,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
>  		goto cleanup_exit;
>  	}
>  	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	asd->match.fwnode.fwnode = of_fwnode_handle(sensor_node);
> +	asd->match.fwnode = of_fwnode_handle(sensor_node);
>  
>  	remote_ep = of_graph_get_remote_endpoint(ep_node);
>  	if (!remote_ep) {
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index f4c3e48ed2c0..6bb28cd49dae 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -387,7 +387,7 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
>  
>  		entity->node = remote;
>  		entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		entity->asd.match.fwnode.fwnode = of_fwnode_handle(remote);
> +		entity->asd.match.fwnode = of_fwnode_handle(remote);
>  		list_add_tail(&entity->list, &xdev->entities);
>  		xdev->num_subdevs++;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index e5acfab470a5..2b08d03b251d 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -68,12 +68,12 @@ static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
>  static bool match_devname(struct v4l2_subdev *sd,
>  			  struct v4l2_async_subdev *asd)
>  {
> -	return !strcmp(asd->match.device_name.name, dev_name(sd->dev));
> +	return !strcmp(asd->match.device_name, dev_name(sd->dev));
>  }
>  
>  static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
>  {
> -	return sd->fwnode == asd->match.fwnode.fwnode;
> +	return sd->fwnode == asd->match.fwnode;
>  }
>  
>  static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
> @@ -319,7 +319,7 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
>  		if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
>  			continue;
>  
> -		if (asd->match.fwnode.fwnode == fwnode)
> +		if (asd->match.fwnode == fwnode)
>  			return true;
>  	}
>  
> @@ -330,7 +330,7 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
>  		if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
>  			continue;
>  
> -		if (sd->asd->match.fwnode.fwnode == fwnode)
> +		if (sd->asd->match.fwnode == fwnode)
>  			return true;
>  	}
>  
> @@ -355,8 +355,8 @@ static bool v4l2_async_notifier_fwnode_has_async_subdev(
>  		struct v4l2_async_subdev *other_asd = notifier->subdevs[j];
>  
>  		if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE &&
> -		    asd->match.fwnode.fwnode ==
> -		    other_asd->match.fwnode.fwnode)
> +		    asd->match.fwnode ==
> +		    other_asd->match.fwnode)
>  			return true;
>  	}
>  
> @@ -395,7 +395,7 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>  			break;
>  		case V4L2_ASYNC_MATCH_FWNODE:
>  			if (v4l2_async_notifier_fwnode_has_async_subdev(
> -				    notifier, asd->match.fwnode.fwnode, i)) {
> +				    notifier, asd->match.fwnode, i)) {
>  				dev_err(dev,
>  					"fwnode has already been registered or in notifier's subdev list\n");
>  				ret = -EEXIST;
> @@ -510,7 +510,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
>  
>  		switch (asd->match_type) {
>  		case V4L2_ASYNC_MATCH_FWNODE:
> -			fwnode_handle_put(asd->match.fwnode.fwnode);
> +			fwnode_handle_put(asd->match.fwnode);
>  			break;
>  		default:
>  			WARN_ON_ONCE(true);
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> index fb72c7ac04d4..d630640642ee 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -359,9 +359,9 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
>  		return -ENOMEM;
>  
>  	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	asd->match.fwnode.fwnode =
> +	asd->match.fwnode =
>  		fwnode_graph_get_remote_port_parent(endpoint);
> -	if (!asd->match.fwnode.fwnode) {
> +	if (!asd->match.fwnode) {
>  		dev_warn(dev, "bad remote port parent\n");
>  		ret = -EINVAL;
>  		goto out_err;
> @@ -393,7 +393,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
>  	return 0;
>  
>  out_err:
> -	fwnode_handle_put(asd->match.fwnode.fwnode);
> +	fwnode_handle_put(asd->match.fwnode);
>  	kfree(asd);
>  
>  	return ret == -ENOTCONN ? 0 : ret;
> @@ -566,7 +566,7 @@ static int v4l2_fwnode_reference_parse(
>  		}
>  
>  		notifier->subdevs[notifier->num_subdevs] = asd;
> -		asd->match.fwnode.fwnode = args.fwnode;
> +		asd->match.fwnode = args.fwnode;
>  		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
>  		notifier->num_subdevs++;
>  	}
> @@ -853,7 +853,7 @@ static int v4l2_fwnode_reference_parse_int_props(
>  		}
>  
>  		notifier->subdevs[notifier->num_subdevs] = asd;
> -		asd->match.fwnode.fwnode = fwnode;
> +		asd->match.fwnode = fwnode;
>  		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
>  		notifier->num_subdevs++;
>  	}
> diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
> index 2800700482d6..f7ed5f506fa9 100644
> --- a/drivers/staging/media/imx/imx-media-dev.c
> +++ b/drivers/staging/media/imx/imx-media-dev.c
> @@ -48,7 +48,7 @@ find_async_subdev(struct imx_media_dev *imxmd,
>  		asd = &imxasd->asd;
>  		switch (asd->match_type) {
>  		case V4L2_ASYNC_MATCH_FWNODE:
> -			if (fwnode && asd->match.fwnode.fwnode == fwnode)
> +			if (fwnode && asd->match.fwnode == fwnode)
>  				return asd;
>  			break;
>  		case V4L2_ASYNC_MATCH_DEVNAME:
> @@ -104,7 +104,7 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
>  
>  	if (fwnode) {
>  		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		asd->match.fwnode.fwnode = fwnode;
> +		asd->match.fwnode = fwnode;
>  	} else {
>  		asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
>  		asd->match.device_name.name = devname;
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 6152434cbe82..a010af5134b2 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -58,12 +58,8 @@ enum v4l2_async_match_type {
>  struct v4l2_async_subdev {
>  	enum v4l2_async_match_type match_type;
>  	union {
> -		struct {
> -			struct fwnode_handle *fwnode;
> -		} fwnode;
> -		struct {
> -			const char *name;
> -		} device_name;
> +		struct fwnode_handle *fwnode;
> +		const char *device_name;
>  		struct {
>  			int adapter_id;
>  			unsigned short address;
> -- 
> 2.14.3
> 

^ permalink raw reply

* [PATCH 3/8] media: v4l2-async: simplify v4l2_async_subdev structure
From: Mauro Carvalho Chehab @ 2017-12-18 19:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1513625884.git.mchehab@s-opensource.com>

The V4L2_ASYNC_MATCH_FWNODE match criteria requires just one
struct to be filled (struct fwnode_handle). The V4L2_ASYNC_MATCH_DEVNAME
match criteria requires just a device name.

So, it doesn't make sense to enclose those into structs,
as the criteria can go directly into the union.

That makes easier to document it, as we don't need to document
weird senseless structs.

At drivers, this makes even clearer about the match criteria.

Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
---
 drivers/media/platform/am437x/am437x-vpfe.c    |  6 +++---
 drivers/media/platform/atmel/atmel-isc.c       |  2 +-
 drivers/media/platform/atmel/atmel-isi.c       |  2 +-
 drivers/media/platform/davinci/vpif_capture.c  |  4 ++--
 drivers/media/platform/exynos4-is/media-dev.c  |  4 ++--
 drivers/media/platform/pxa_camera.c            |  2 +-
 drivers/media/platform/qcom/camss-8x16/camss.c |  2 +-
 drivers/media/platform/rcar-vin/rcar-core.c    |  2 +-
 drivers/media/platform/rcar_drif.c             |  4 ++--
 drivers/media/platform/soc_camera/soc_camera.c |  2 +-
 drivers/media/platform/stm32/stm32-dcmi.c      |  2 +-
 drivers/media/platform/ti-vpe/cal.c            |  2 +-
 drivers/media/platform/xilinx/xilinx-vipp.c    |  2 +-
 drivers/media/v4l2-core/v4l2-async.c           | 16 ++++++++--------
 drivers/media/v4l2-core/v4l2-fwnode.c          | 10 +++++-----
 drivers/staging/media/imx/imx-media-dev.c      |  4 ++--
 include/media/v4l2-async.h                     |  8 ++------
 17 files changed, 35 insertions(+), 39 deletions(-)

diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index 0997c640191d..601ae6487617 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -2304,8 +2304,8 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
 	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
 
 	for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
-		if (vpfe->cfg->asd[i]->match.fwnode.fwnode ==
-		    asd[i].match.fwnode.fwnode) {
+		if (vpfe->cfg->asd[i]->match.fwnode ==
+		    asd[i].match.fwnode) {
 			sdinfo = &vpfe->cfg->sub_devs[i];
 			vpfe->sd[i] = subdev;
 			vpfe->sd[i]->grp_id = sdinfo->grp_id;
@@ -2510,7 +2510,7 @@ vpfe_get_pdata(struct platform_device *pdev)
 		}
 
 		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		pdata->asd[i]->match.fwnode.fwnode = of_fwnode_handle(rem);
+		pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
 		of_node_put(rem);
 	}
 
diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c
index 0c2635647f69..34676409ca08 100644
--- a/drivers/media/platform/atmel/atmel-isc.c
+++ b/drivers/media/platform/atmel/atmel-isc.c
@@ -2088,7 +2088,7 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
 
 		subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		subdev_entity->asd->match.fwnode.fwnode =
+		subdev_entity->asd->match.fwnode =
 			of_fwnode_handle(rem);
 		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
 	}
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index e900995143a3..9958918e2449 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -1128,7 +1128,7 @@ static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node)
 		/* Remote node to connect */
 		isi->entity.node = remote;
 		isi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-		isi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
+		isi->entity.asd.match.fwnode = of_fwnode_handle(remote);
 		return 0;
 	}
 }
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index e45916f69def..e1c273c8b9a6 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1390,7 +1390,7 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier,
 
 	for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) {
 		struct v4l2_async_subdev *_asd = vpif_obj.config->asd[i];
-		const struct fwnode_handle *fwnode = _asd->match.fwnode.fwnode;
+		const struct fwnode_handle *fwnode = _asd->match.fwnode;
 
 		if (fwnode == subdev->fwnode) {
 			vpif_obj.sd[i] = subdev;
@@ -1595,7 +1595,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
 		}
 
 		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		pdata->asd[i]->match.fwnode.fwnode = of_fwnode_handle(rem);
+		pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
 		of_node_put(rem);
 	}
 
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 0ef583cfc424..78b48a1fa26c 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -456,7 +456,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
 	}
 
 	fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	fmd->sensor[index].asd.match.fwnode.fwnode = of_fwnode_handle(rem);
+	fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
 	fmd->async_subdevs[index] = &fmd->sensor[index].asd;
 
 	fmd->num_sensors++;
@@ -1364,7 +1364,7 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
 
 	/* Find platform data for this sensor subdev */
 	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
-		if (fmd->sensor[i].asd.match.fwnode.fwnode ==
+		if (fmd->sensor[i].asd.match.fwnode ==
 		    of_fwnode_handle(subdev->dev->of_node))
 			si = &fmd->sensor[i];
 
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index 305cf1cac210..f028084f0775 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -2335,7 +2335,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 	remote = of_graph_get_remote_port(np);
 	if (remote) {
-		asd->match.fwnode.fwnode = of_fwnode_handle(remote);
+		asd->match.fwnode = of_fwnode_handle(remote);
 		of_node_put(remote);
 	} else {
 		dev_notice(dev, "no remote for %pOF\n", np);
diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c
index 390a42c17b66..05f06c98aa64 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss.c
@@ -341,7 +341,7 @@ static int camss_of_parse_ports(struct device *dev,
 		}
 
 		csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-		csd->asd.match.fwnode.fwnode = of_fwnode_handle(remote);
+		csd->asd.match.fwnode = of_fwnode_handle(remote);
 	}
 
 	return notifier->num_subdevs;
diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 108d776f3265..f1fc7978d6d1 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -187,7 +187,7 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 		return -ENODEV;
 
 	vin_dbg(vin, "Found digital subdevice %pOF\n",
-		to_of_node(vin->digital->asd.match.fwnode.fwnode));
+		to_of_node(vin->digital->asd.match.fwnode));
 
 	vin->notifier.ops = &rvin_digital_notify_ops;
 	ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
index 63c94f4028a7..b2e080ef5391 100644
--- a/drivers/media/platform/rcar_drif.c
+++ b/drivers/media/platform/rcar_drif.c
@@ -1107,7 +1107,7 @@ static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier,
 	struct rcar_drif_sdr *sdr =
 		container_of(notifier, struct rcar_drif_sdr, notifier);
 
-	if (sdr->ep.asd.match.fwnode.fwnode !=
+	if (sdr->ep.asd.match.fwnode !=
 	    of_fwnode_handle(subdev->dev->of_node)) {
 		rdrif_err(sdr, "subdev %s cannot bind\n", subdev->name);
 		return -EINVAL;
@@ -1235,7 +1235,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
 		return -EINVAL;
 	}
 
-	sdr->ep.asd.match.fwnode.fwnode = fwnode;
+	sdr->ep.asd.match.fwnode = fwnode;
 	sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
 	notifier->num_subdevs++;
 
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 916ff68b73d4..d13e2c5fb06f 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -1517,7 +1517,7 @@ static int soc_of_bind(struct soc_camera_host *ici,
 	if (!info)
 		return -ENOMEM;
 
-	info->sasd.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
+	info->sasd.asd.match.fwnode = of_fwnode_handle(remote);
 	info->sasd.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
 	info->subdev = &info->sasd.asd;
 
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index ac4c450a6c7d..9460b3080dca 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -1520,7 +1520,7 @@ static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
 		/* Remote node to connect */
 		dcmi->entity.node = remote;
 		dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-		dcmi->entity.asd.match.fwnode.fwnode = of_fwnode_handle(remote);
+		dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
 		return 0;
 	}
 }
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 719ed1d79957..d1febe5baa6d 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1702,7 +1702,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 		goto cleanup_exit;
 	}
 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode.fwnode = of_fwnode_handle(sensor_node);
+	asd->match.fwnode = of_fwnode_handle(sensor_node);
 
 	remote_ep = of_graph_get_remote_endpoint(ep_node);
 	if (!remote_ep) {
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index f4c3e48ed2c0..6bb28cd49dae 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -387,7 +387,7 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
 
 		entity->node = remote;
 		entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-		entity->asd.match.fwnode.fwnode = of_fwnode_handle(remote);
+		entity->asd.match.fwnode = of_fwnode_handle(remote);
 		list_add_tail(&entity->list, &xdev->entities);
 		xdev->num_subdevs++;
 	}
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index e5acfab470a5..2b08d03b251d 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -68,12 +68,12 @@ static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
 static bool match_devname(struct v4l2_subdev *sd,
 			  struct v4l2_async_subdev *asd)
 {
-	return !strcmp(asd->match.device_name.name, dev_name(sd->dev));
+	return !strcmp(asd->match.device_name, dev_name(sd->dev));
 }
 
 static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
 {
-	return sd->fwnode == asd->match.fwnode.fwnode;
+	return sd->fwnode == asd->match.fwnode;
 }
 
 static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
@@ -319,7 +319,7 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
 		if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
 			continue;
 
-		if (asd->match.fwnode.fwnode == fwnode)
+		if (asd->match.fwnode == fwnode)
 			return true;
 	}
 
@@ -330,7 +330,7 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
 		if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
 			continue;
 
-		if (sd->asd->match.fwnode.fwnode == fwnode)
+		if (sd->asd->match.fwnode == fwnode)
 			return true;
 	}
 
@@ -355,8 +355,8 @@ static bool v4l2_async_notifier_fwnode_has_async_subdev(
 		struct v4l2_async_subdev *other_asd = notifier->subdevs[j];
 
 		if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE &&
-		    asd->match.fwnode.fwnode ==
-		    other_asd->match.fwnode.fwnode)
+		    asd->match.fwnode ==
+		    other_asd->match.fwnode)
 			return true;
 	}
 
@@ -395,7 +395,7 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 			break;
 		case V4L2_ASYNC_MATCH_FWNODE:
 			if (v4l2_async_notifier_fwnode_has_async_subdev(
-				    notifier, asd->match.fwnode.fwnode, i)) {
+				    notifier, asd->match.fwnode, i)) {
 				dev_err(dev,
 					"fwnode has already been registered or in notifier's subdev list\n");
 				ret = -EEXIST;
@@ -510,7 +510,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 
 		switch (asd->match_type) {
 		case V4L2_ASYNC_MATCH_FWNODE:
-			fwnode_handle_put(asd->match.fwnode.fwnode);
+			fwnode_handle_put(asd->match.fwnode);
 			break;
 		default:
 			WARN_ON_ONCE(true);
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index fb72c7ac04d4..d630640642ee 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -359,9 +359,9 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 		return -ENOMEM;
 
 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode.fwnode =
+	asd->match.fwnode =
 		fwnode_graph_get_remote_port_parent(endpoint);
-	if (!asd->match.fwnode.fwnode) {
+	if (!asd->match.fwnode) {
 		dev_warn(dev, "bad remote port parent\n");
 		ret = -EINVAL;
 		goto out_err;
@@ -393,7 +393,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 	return 0;
 
 out_err:
-	fwnode_handle_put(asd->match.fwnode.fwnode);
+	fwnode_handle_put(asd->match.fwnode);
 	kfree(asd);
 
 	return ret == -ENOTCONN ? 0 : ret;
@@ -566,7 +566,7 @@ static int v4l2_fwnode_reference_parse(
 		}
 
 		notifier->subdevs[notifier->num_subdevs] = asd;
-		asd->match.fwnode.fwnode = args.fwnode;
+		asd->match.fwnode = args.fwnode;
 		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 		notifier->num_subdevs++;
 	}
@@ -853,7 +853,7 @@ static int v4l2_fwnode_reference_parse_int_props(
 		}
 
 		notifier->subdevs[notifier->num_subdevs] = asd;
-		asd->match.fwnode.fwnode = fwnode;
+		asd->match.fwnode = fwnode;
 		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 		notifier->num_subdevs++;
 	}
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index 2800700482d6..f7ed5f506fa9 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -48,7 +48,7 @@ find_async_subdev(struct imx_media_dev *imxmd,
 		asd = &imxasd->asd;
 		switch (asd->match_type) {
 		case V4L2_ASYNC_MATCH_FWNODE:
-			if (fwnode && asd->match.fwnode.fwnode == fwnode)
+			if (fwnode && asd->match.fwnode == fwnode)
 				return asd;
 			break;
 		case V4L2_ASYNC_MATCH_DEVNAME:
@@ -104,7 +104,7 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
 
 	if (fwnode) {
 		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		asd->match.fwnode.fwnode = fwnode;
+		asd->match.fwnode = fwnode;
 	} else {
 		asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
 		asd->match.device_name.name = devname;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 6152434cbe82..a010af5134b2 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -58,12 +58,8 @@ enum v4l2_async_match_type {
 struct v4l2_async_subdev {
 	enum v4l2_async_match_type match_type;
 	union {
-		struct {
-			struct fwnode_handle *fwnode;
-		} fwnode;
-		struct {
-			const char *name;
-		} device_name;
+		struct fwnode_handle *fwnode;
+		const char *device_name;
 		struct {
 			int adapter_id;
 			unsigned short address;
-- 
2.14.3

^ permalink raw reply related

* [PATCH 1/3] dt-bindings: chosen: Add clocksource and clockevent selection
From: Boris Brezillon @ 2017-12-18 19:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171215113242.skmh5nzr7wqdmvnw@lakrids.cambridge.arm.com>

On Fri, 15 Dec 2017 11:32:42 +0000
Mark Rutland <mark.rutland@arm.com> wrote:

> Hi,
> 
> On Wed, Dec 13, 2017 at 07:53:11PM +0100, Alexandre Belloni wrote:
> > The clocksource and clockevent timer are probed early in the boot process.
> > At that time it is difficult for linux to know whether a particular timer
> > can be used as the clocksource or the clockevent or by another driver,
> > especially when they are all identical or have similar features.  
> 
> I think that to solve this problem, we need to stop treating
> clocksources and clockevent devices as completely separate device types,
> and instead treat them as particular cases of a more general clock
> device.
> 
> That way, a driver can register a single device, with flags saying
> whether it is:
> 
> * a clocksource only
> * a clockevent device only
> * both a clocksource and clockevent device
> * both, but mutually exclusive at runtime
> 
> ... and thus drivers don't have to make an impossible decision up-front
> as to how the device should be used.
> 
> As more devices get registered, the core timekeeping code can improve on
> its choices and re-assign devices.

I'm coming back to the Atmel TCB use case. Say you have 2 'timers' one
has been assigned 2 channels (a channel is what I call TC in my
previous explanation) and the other one only one channel. Both timers
are capable of acting as a clockevent or a clocksource device (not
both at the same time). Now, the question is, how do you decide which
one is assigned the clocksource role and which one is assigned the
clkevent role. Do you plan to pass the expected clocksource/clkevent
properties (precision, max value, wraparound period, ...) through the
device tree so that the framework can decide which timer is best suited
for a specific feature?

> 
> That doesn't solve the case where a clock device may use resources we
> want for something else, but I think we can solve that separately.
> 
> Thanks,
> Mark.
> 
> > Until now, multiple strategies have been used to solve that:
> >  - use Kconfig option as MXC_USE_EPIT or ATMEL_TCB_CLKSRC_BLOCK
> >  - use a kernel parameter as the "clocksource" early_param in mach-omap2
> >  - registering the first seen timer as a clockevent and the second one as
> >  a clocksource as in rk_timer_init or dw_apb_timer_init
> > 
> > Add a linux,clocksource and a linux,clockevent node in chosen with a timer
> > property pointing to the timer to use. Other properties, like the targeted
> > precision may be added later.
> > 
> > Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> > ---
> >  Documentation/devicetree/bindings/chosen.txt | 20 ++++++++++++++++++++
> >  1 file changed, 20 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
> > index e3b13ea7d2ae..c7ee3ecb5276 100644
> > --- a/Documentation/devicetree/bindings/chosen.txt
> > +++ b/Documentation/devicetree/bindings/chosen.txt
> > @@ -120,3 +120,23 @@ e.g.
> >  While this property does not represent a real hardware, the address
> >  and the size are expressed in #address-cells and #size-cells,
> >  respectively, of the root node.
> > +
> > +linux,clocksource and linux,clockevent
> > +--------------------------------------
> > +
> > +Those nodes have a timer property. This property is a phandle to the timer to be
> > +chosen as the clocksource or clockevent. This is only useful when the platform
> > +has multiple identical timers and it is not possible to let linux make the
> > +correct choice.
> > +
> > +/ {
> > +	chosen {
> > +		linux,clocksource {
> > +			timer = <&timer0>;
> > +		};
> > +
> > +		linux,clockevent {
> > +			timer = <&timer1>;
> > +		};
> > +	};
> > +};
> > -- 
> > 2.15.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe devicetree" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html  
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v2 3/4] dt-bindings: opp: Introduce ti-opp-supply bindings
From: Dave Gerlach @ 2017-12-18 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJZ5v0iRg0Sncqt4s3M5+E0h=HJiEDQ4vnB3=6mFhECCv_Lnng@mail.gmail.com>

Rafael,
On 12/16/2017 04:52 AM, Rafael J. Wysocki wrote:
> On Fri, Dec 15, 2017 at 3:29 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
>> On Fri, Dec 15, 2017 at 5:25 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
>>> Document the devicetree bindings that describe Texas Instruments
>>> opp-supply which allow a platform to describe multiple regulators and
>>> additional information, such as registers containing data needed to
>>> program aforementioned regulators.
>>>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>
>> I need an ACK from Rob on this one.
> 
> Actually, how this (and the next patch) is related to the [1-2/4]?
> 

The main goal of this series is to add support for scaling the multiple
regulators needed for the CPU on these TI platforms. The OPP core supports
multiple regulators but only to the point that it can associate a list of
regulators to a device. It still by default only scales the normal vdd regulator
when doing a rate transition. Because of this, we must define our own method of
doing rate transitions to take the references to our regulators held in the OPP
core and scale them in the proper sequence depending on what the platform needs.

So to describe the purpose of each patch and their relation to each other:

Patch 1: We must be able to defer the ti-cpufreq driver now that we look for
regulators during probe as they likely won't be ready when we probe.

Patch 2: Tell the OPP core about regulators needed for TI CPUFreq operation
using the OPP core. This doesn't actually do anything besides place them in a
list at this point because the OPP core can't know how TI platforms needs them
scaled in relation to each other. Placing the regulator definition in ti-cpufreq
driver ensures they are registered with opp core before cpufreq-dt probes (which
is triggered at the end of ti-cpufreq probe) and actually makes the opp core get
the regulators.

Patch 3: Binding doc for patch 4 driver.

Patch 4: TI OPP supply driver which understands how to actually make use of the
two regulators that the OPP core now has a reference to. This overrides the
standard opp_set_rate function to let us scale frequency and voltage as needed
for TI platforms.

Regards,
Dave

^ permalink raw reply

* [PATCH v2 13/17] media: v4l2-async: simplify v4l2_async_subdev structure
From: Mauro Carvalho Chehab @ 2017-12-18 19:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170929220524.gsx3tmirdni2mhpx@valkosipuli.retiisi.org.uk>

Em Sat, 30 Sep 2017 01:05:24 +0300
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> (Removing the non-list recipients.)
> 
> On Fri, Sep 29, 2017 at 06:27:13AM -0300, Mauro Carvalho Chehab wrote:
> > Em Thu, 28 Sep 2017 15:09:21 +0300
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > On Wed, Sep 27, 2017 at 06:46:56PM -0300, Mauro Carvalho Chehab wrote:  
> > > > The V4L2_ASYNC_MATCH_FWNODE match criteria requires just one
> > > > struct to be filled (struct fwnode_handle). The V4L2_ASYNC_MATCH_DEVNAME
> > > > match criteria requires just a device name.
> > > > 
> > > > So, it doesn't make sense to enclose those into structs,
> > > > as the criteria can go directly into the union.
> > > > 
> > > > That makes easier to document it, as we don't need to document
> > > > weird senseless structs.    
> > > 
> > > The idea is that in the union, there's a struct which is specific to the
> > > match_type field. I wouldn't call it senseless.  
> > 
> > Why a struct for each specific match_type is **needed**? It it is not
> > needed, then it is senseless per definition :-) 
> > 
> > In the specific case of fwnode, there's already a named struct
> > for fwnode_handle. The only thing is that it is declared outside
> > enum v4l2_async_match_type. So, I don't see any reason to do things
> > like:
> > 
> > 		struct {
> > 			struct fwnode_handle *fwnode;
> > 		} fwnode;
> > 
> > If you're in doubt about that, think on how would you document
> > both fwnode structs. Both fwnode structs specify the match
> > criteria if %V4L2_ASYNC_MATCH_FWNODE.
> > 
> > The same applies to this:
> > 
> > 		struct {
> > 			const char *name;
> > 		} device_name;
> > 
> > Both device_name and name specifies the match criteria if
> > %V4L2_ASYNC_MATCH_DEVNAME.
> >   
> > > 
> > > In the two cases there's just a single field in the containing struct. You
> > > could remove the struct in that case as you do in this patch, and just use
> > > the field. But I think the result is less clean and so I wouldn't make this
> > > change.  
> > 
> > It is actually cleaner without the stucts.
> > 
> > Without the useless struct, if one wants to match a firmware node, it
> > should be doing:
> > 
> >  		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
> > 		pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);  
> 
> This code should be and will be moved out of drivers. See:
> 
> <URL:http://www.spinics.net/lists/linux-media/msg122688.html>
> 
> So there are going to be quite a bit fewer instances of it, and none should
> remain in drivers. I frankly don't have a strong opinion on this; there are
> arguments for and against. I just don't see a reason to change it.

There are still a few occurrences on drivers. Just rebased it.
I'll post it in a few, inside a new patch series.

Simplifying the name of the match rules makes easier to understand
what's going on.


Thanks,
Mauro

^ permalink raw reply

* [PATCH net-next v3 0/7] net: phy: meson-gxl: clean-up and improvements
From: David Miller @ 2017-12-18 18:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218094446.31912-1-jbrunet@baylibre.com>

From: Jerome Brunet <jbrunet@baylibre.com>
Date: Mon, 18 Dec 2017 10:44:39 +0100

> This patchset adds defines for the control registers and helpers to access
> the banked registers. The goal being to make it easier to understand what
> the driver actually does.
> Then CONFIG_A6 settings is removed since this statement was without effect
> Finally interrupt support is added, speeding things up a little
> 
> This series has been tested on the libretech-cc and khadas VIM
> 
> Changes since v2 [0]:
> Drop LPA corruption fix which has been merged through net. Apart from this,
> series remains the same.
> 
> [0]: https://lkml.kernel.org/r/20171207142715.32578-1-jbrunet at baylibre.com

Series applied, thanks.

^ permalink raw reply

* [PATCH v2 4/4] ARM: dts: r8a7745: Add TPU support
From: Fabrizio Castro @ 2017-12-18 18:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620411-17478-1-git-send-email-fabrizio.castro@bp.renesas.com>

Add TPU support to SoC DT.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
---
v1->v2:
* No change

 arch/arm/boot/dts/r8a7745.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi
index e68e20f..be316ca 100644
--- a/arch/arm/boot/dts/r8a7745.dtsi
+++ b/arch/arm/boot/dts/r8a7745.dtsi
@@ -1045,6 +1045,16 @@
 			status = "disabled";
 		};
 
+		tpu: pwm at e60f0000 {
+			compatible = "renesas,tpu-r8a7745", "renesas,tpu";
+			reg = <0 0xe60f0000 0 0x148>;
+			clocks = <&cpg CPG_MOD 304>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 304>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		sdhi0: sd at ee100000 {
 			compatible = "renesas,sdhi-r8a7745",
 				     "renesas,rcar-gen2-sdhi";
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/4] ARM: dts: r8a7745: Add PWM SoC support
From: Fabrizio Castro @ 2017-12-18 18:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620411-17478-1-git-send-email-fabrizio.castro@bp.renesas.com>

Add the definitions for pwm[0123456] to the SoC .dtsi.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
---
v1->v2:
* No change

 arch/arm/boot/dts/r8a7745.dtsi | 77 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi
index 0b67ee5..e68e20f 100644
--- a/arch/arm/boot/dts/r8a7745.dtsi
+++ b/arch/arm/boot/dts/r8a7745.dtsi
@@ -968,6 +968,83 @@
 			status = "disabled";
 		};
 
+		pwm0: pwm at e6e30000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e30000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm1: pwm at e6e31000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e31000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm2: pwm at e6e32000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e32000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm3: pwm at e6e33000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e33000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm4: pwm at e6e34000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e34000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm5: pwm at e6e35000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e35000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm6: pwm at e6e36000 {
+			compatible = "renesas,pwm-r8a7745",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e36000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
 		sdhi0: sd at ee100000 {
 			compatible = "renesas,sdhi-r8a7745",
 				     "renesas,rcar-gen2-sdhi";
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 0/4] Add PWM and TPU support to r8a7745
From: Fabrizio Castro @ 2017-12-18 18:06 UTC (permalink / raw)
  To: linux-arm-kernel

Dear All,

this series includes all that is required to add PWM and TPU SoC specific
support for the r8a7745.

Thanks,

Fabrizio Castro (4):
  pinctrl: sh-pfc: r8a7794: Add PWM[0123456] support
  ARM: dts: r8a7745: Add PWM SoC support
  pinctrl: sh-pfc: r8a7794: Add tpu groups and function
  ARM: dts: r8a7745: Add TPU support

 arch/arm/boot/dts/r8a7745.dtsi       |  87 ++++++++++++
 drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 266 +++++++++++++++++++++++++++++++++++
 2 files changed, 353 insertions(+)

-- 
2.7.4

^ permalink raw reply

* [PATCH 4/4] coresight: etb10: remove duplicate includes
From: Mathieu Poirier @ 2017-12-18 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620345-1366-1-git-send-email-mathieu.poirier@linaro.org>

From: Pravin Shedge <pravin.shedge4linux@gmail.com>

These duplicate includes have been found with scripts/checkincludes.pl but
they have been removed manually to avoid removing false positives.

Signed-off-by: Pravin Shedge <pravin.shedge4linux@gmail.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index e03e58933141..580cd381adf3 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -33,7 +33,6 @@
 #include <linux/mm.h>
 #include <linux/perf_event.h>
 
-#include <asm/local.h>
 
 #include "coresight-priv.h"
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/4] coresight: Fix disabling of CoreSight TPIU
From: Mathieu Poirier @ 2017-12-18 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620345-1366-1-git-send-email-mathieu.poirier@linaro.org>

From: Robert Walker <robert.walker@arm.com>

The CoreSight TPIU should be disabled when tracing to other sinks to allow
them to operate at full bandwidth.

This patch fixes tpiu_disable_hw() to correctly disable the TPIU by
configuring the TPIU to stop on flush, initiating a manual flush, waiting
for the flush to complete and then waits for the TPIU to indicate it has
stopped.

Signed-off-by: Robert Walker <robert.walker@arm.com>
Tested-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 drivers/hwtracing/coresight/coresight-tpiu.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 76ea1b8d4db5..805f7c2210fe 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -46,8 +46,11 @@
 #define TPIU_ITATBCTR0		0xef8
 
 /** register definition **/
+/* FFSR - 0x300 */
+#define FFSR_FT_STOPPED		BIT(1)
 /* FFCR - 0x304 */
 #define FFCR_FON_MAN		BIT(6)
+#define FFCR_STOP_FI		BIT(12)
 
 /**
  * @base:	memory mapped base address for this component.
@@ -85,10 +88,14 @@ static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
 {
 	CS_UNLOCK(drvdata->base);
 
-	/* Clear formatter controle reg. */
-	writel_relaxed(0x0, drvdata->base + TPIU_FFCR);
+	/* Clear formatter and stop on flush */
+	writel_relaxed(FFCR_STOP_FI, drvdata->base + TPIU_FFCR);
 	/* Generate manual flush */
-	writel_relaxed(FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
+	writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
+	/* Wait for flush to complete */
+	coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN, 0);
+	/* Wait for formatter to stop */
+	coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED, 1);
 
 	CS_LOCK(drvdata->base);
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/4] coresight: Use PTR_ERR_OR_ZERO()
From: Mathieu Poirier @ 2017-12-18 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620345-1366-1-git-send-email-mathieu.poirier@linaro.org>

From: Vasyl Gomonovych <gomonovych@gmail.com>

Fix ptr_ret.cocci warnings:
drivers/hwtracing/coresight/coresight-tpiu.c:163:1-3: WARNING: PTR_ERR_OR_ZERO can be used
drivers/hwtracing/coresight/coresight-funnel.c:217:1-3: WARNING: PTR_ERR_OR_ZERO can be used
drivers/hwtracing/coresight/coresight-dynamic-replicator.c:166:1-3: WARNING: PTR_ERR_OR_ZERO can be used

Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR

Generated by: scripts/coccinelle/api/ptr_ret.cocci

Signed-off-by: Vasyl Gomonovych <gomonovych@gmail.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 drivers/hwtracing/coresight/coresight-dynamic-replicator.c | 4 +---
 drivers/hwtracing/coresight/coresight-funnel.c             | 4 +---
 drivers/hwtracing/coresight/coresight-tpiu.c               | 4 +---
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c
index 8f4357e2626c..043da86b0fe9 100644
--- a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c
@@ -163,10 +163,8 @@ static int replicator_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.dev = &adev->dev;
 	desc.groups = replicator_groups;
 	drvdata->csdev = coresight_register(&desc);
-	if (IS_ERR(drvdata->csdev))
-		return PTR_ERR(drvdata->csdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(drvdata->csdev);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index fd3c396717f6..9f8ac0bef853 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -214,10 +214,8 @@ static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.dev = dev;
 	desc.groups = coresight_funnel_groups;
 	drvdata->csdev = coresight_register(&desc);
-	if (IS_ERR(drvdata->csdev))
-		return PTR_ERR(drvdata->csdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(drvdata->csdev);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index bef49a3a5ca7..76ea1b8d4db5 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -160,10 +160,8 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.pdata = pdata;
 	desc.dev = dev;
 	drvdata->csdev = coresight_register(&desc);
-	if (IS_ERR(drvdata->csdev))
-		return PTR_ERR(drvdata->csdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(drvdata->csdev);
 }
 
 #ifdef CONFIG_PM
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/4] coresight: Deduplicate bus_find_device() by name matching
From: Mathieu Poirier @ 2017-12-18 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513620345-1366-1-git-send-email-mathieu.poirier@linaro.org>

From: Lukas Wunner <lukas@wunner.de>

No need to reinvent the wheel, we have bus_find_device_by_name().

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 drivers/hwtracing/coresight/coresight.c | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index b8091bef21dc..389c4baeca9d 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -843,32 +843,17 @@ static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
 }
 
 
-static int coresight_name_match(struct device *dev, void *data)
-{
-	char *to_match;
-	struct coresight_device *i_csdev;
-
-	to_match = data;
-	i_csdev = to_coresight_device(dev);
-
-	if (to_match && !strcmp(to_match, dev_name(&i_csdev->dev)))
-		return 1;
-
-	return 0;
-}
-
 static void coresight_fixup_device_conns(struct coresight_device *csdev)
 {
 	int i;
-	struct device *dev = NULL;
-	struct coresight_connection *conn;
 
 	for (i = 0; i < csdev->nr_outport; i++) {
-		conn = &csdev->conns[i];
-		dev = bus_find_device(&coresight_bustype, NULL,
-				      (void *)conn->child_name,
-				      coresight_name_match);
+		struct coresight_connection *conn = &csdev->conns[i];
+		struct device *dev = NULL;
 
+		if (conn->child_name)
+			dev = bus_find_device_by_name(&coresight_bustype, NULL,
+						      conn->child_name);
 		if (dev) {
 			conn->child_dev = to_coresight_device(dev);
 			/* and put reference from 'bus_find_device()' */
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/4] coresight: next v4.15-rc4
From: Mathieu Poirier @ 2017-12-18 18:05 UTC (permalink / raw)
  To: linux-arm-kernel

Good day,

Please see if you can add those to your tally for the 4.16 cycle.

Thanks,
Mathieu

Lukas Wunner (1):
  coresight: Deduplicate bus_find_device() by name matching

Pravin Shedge (1):
  coresight: etb10: remove duplicate includes

Robert Walker (1):
  coresight: Fix disabling of CoreSight TPIU

Vasyl Gomonovych (1):
  coresight: Use PTR_ERR_OR_ZERO()

 .../coresight/coresight-dynamic-replicator.c       |  4 +---
 drivers/hwtracing/coresight/coresight-etb10.c      |  1 -
 drivers/hwtracing/coresight/coresight-funnel.c     |  4 +---
 drivers/hwtracing/coresight/coresight-tpiu.c       | 17 +++++++++------
 drivers/hwtracing/coresight/coresight.c            | 25 +++++-----------------
 5 files changed, 18 insertions(+), 33 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 6/6] ARM: dts: r8a7743: Add TPU support
From: Fabrizio Castro @ 2017-12-18 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513619528-12060-1-git-send-email-fabrizio.castro@bp.renesas.com>

Add TPU support to SoC DT.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
---
v1->v2
* No change

 arch/arm/boot/dts/r8a7743.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi
index d73617a..11defe7c 100644
--- a/arch/arm/boot/dts/r8a7743.dtsi
+++ b/arch/arm/boot/dts/r8a7743.dtsi
@@ -1159,6 +1159,16 @@
 			status = "disabled";
 		};
 
+		tpu: pwm at e60f0000 {
+			compatible = "renesas,tpu-r8a7743", "renesas,tpu";
+			reg = <0 0xe60f0000 0 0x148>;
+			clocks = <&cpg CPG_MOD 304>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 304>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		sdhi0: sd at ee100000 {
 			compatible = "renesas,sdhi-r8a7743",
 				     "renesas,rcar-gen2-sdhi";
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 3/6] ARM: dts: r8a7743: Add PWM SoC support
From: Fabrizio Castro @ 2017-12-18 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513619528-12060-1-git-send-email-fabrizio.castro@bp.renesas.com>

Add the definitions for pwm[0123456] to the SoC .dtsi.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
---
v1->v2
* No change

 arch/arm/boot/dts/r8a7743.dtsi | 77 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi
index c65d8f4..d73617a 100644
--- a/arch/arm/boot/dts/r8a7743.dtsi
+++ b/arch/arm/boot/dts/r8a7743.dtsi
@@ -1082,6 +1082,83 @@
 			status = "disabled";
 		};
 
+		pwm0: pwm at e6e30000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e30000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm1: pwm at e6e31000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e31000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm2: pwm at e6e32000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e32000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm3: pwm at e6e33000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e33000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm4: pwm at e6e34000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e34000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm5: pwm at e6e35000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e35000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		pwm6: pwm at e6e36000 {
+			compatible = "renesas,pwm-r8a7743",
+				     "renesas,pwm-rcar";
+			reg = <0 0xe6e36000 0 0x8>;
+			clocks = <&cpg CPG_MOD 523>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			resets = <&cpg 523>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
 		sdhi0: sd at ee100000 {
 			compatible = "renesas,sdhi-r8a7743",
 				     "renesas,rcar-gen2-sdhi";
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 1/6] ARM: shmobile: defconfig: Enable PWM
From: Fabrizio Castro @ 2017-12-18 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513619528-12060-1-git-send-email-fabrizio.castro@bp.renesas.com>

RZ/G1 and R-Car platforms have PWM timers. This patch enables PWM support
by default.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
---
v1->v2
* No change

 arch/arm/configs/shmobile_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index d60dbe1..578434c 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -208,6 +208,7 @@ CONFIG_STAGING_BOARD=y
 CONFIG_IIO=y
 CONFIG_AK8975=y
 CONFIG_PWM=y
+CONFIG_PWM_RCAR=y
 CONFIG_PWM_RENESAS_TPU=y
 CONFIG_GENERIC_PHY=y
 CONFIG_PHY_RCAR_GEN2=y
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 0/6] Add PWM and TPU support to r8a7743
From: Fabrizio Castro @ 2017-12-18 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

Dear All,

this series includes all that is required to add PWM and TPU SoC specific
support for the r8a7743.

Thanks,

Fabrizio Castro (6):
  ARM: shmobile: defconfig: Enable PWM
  dt-bindings: pwm: rcar: Document r8a774[35] PWM bindings
  ARM: dts: r8a7743: Add PWM SoC support
  dt-bindings: pwm: renesas-tpu: Document r8a774[35] support
  pinctrl: sh-pfc: r8a7791: Add tpu groups and function
  ARM: dts: r8a7743: Add TPU support

 .../devicetree/bindings/pwm/renesas,pwm-rcar.txt   | 10 ++-
 .../devicetree/bindings/pwm/renesas,tpu-pwm.txt    |  4 +-
 arch/arm/boot/dts/r8a7743.dtsi                     | 87 ++++++++++++++++++++++
 arch/arm/configs/shmobile_defconfig                |  1 +
 drivers/pinctrl/sh-pfc/pfc-r8a7791.c               | 42 ++++++++++-
 5 files changed, 138 insertions(+), 6 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v3 19/19] arm64: Update the KVM memory map documentation
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

Update the documentation to reflect the new tricks we play on the
EL2 mappings...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/arm64/memory.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index 671bc0639262..ea64e20037f6 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -86,9 +86,11 @@ Translation table lookup with 64KB pages:
  +-------------------------------------------------> [63] TTBR0/1
 
 
-When using KVM without the Virtualization Host Extensions, the hypervisor
-maps kernel pages in EL2 at a fixed offset from the kernel VA. See the
-kern_hyp_va macro for more details.
+When using KVM without the Virtualization Host Extensions, the
+hypervisor maps kernel pages in EL2 at a fixed offset (modulo a random
+offset) from the linear mapping. See the kern_hyp_va macro and
+kvm_update_va_mask function for more details. MMIO devices such as
+GICv2 gets mapped next to the HYP idmap page.
 
 When using KVM with the Virtualization Host Extensions, no additional
 mappings are created, since the host kernel runs directly in EL2.
-- 
2.14.2

^ permalink raw reply related

* [PATCH v3 18/19] arm64: KVM: Introduce EL2 VA randomisation
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

The main idea behind randomising the EL2 VA is that we usually have
a few spare bits between the most significant bit of the VA mask
and the most significant bit of the linear mapping.

Those bits could be a bunch of zeroes, and could be useful
to move things around a bit. Of course, the more memory you have,
the less randomisation you get...

Alternatively, these bits could be the result of KASLR, in which
case they are already random. But it would be nice to have a
*different* randomization, just to make the job of a potential
attacker a bit more difficult.

Inserting these random bits is a bit involved. We don't have a spare
register (short of rewriting all the kern_hyp_va call sites), and
the immediate we want to insert is too random to be used with the
ORR instruction. The best option I could come up with is the following
sequence:

	and x0, x0, #va_mask
	ror x0, x0, #first_random_bit
	add x0, x0, #(random & 0xfff)
	add x0, x0, #(random >> 12), lsl #12
	ror x0, x0, #(63 - first_random_bit)

making it a fairly long sequence, but one that a decent CPU should
be able to execute without breaking a sweat. It is of course NOPed
out on VHE. The last 4 instructions can also be turned into NOPs
if it appears that there is no free bits to use.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_mmu.h | 10 +++++-
 arch/arm64/kvm/haslr.c           | 75 +++++++++++++++++++++++++++++++++++++---
 virt/kvm/arm/mmu.c               |  2 +-
 3 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 85aaaca5bf4f..ac237948d770 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -85,6 +85,10 @@
 .macro kern_hyp_va	reg
 alternative_cb kvm_update_va_mask
 	and     \reg, \reg, #1
+	ror	\reg, \reg, #1
+	add	\reg, \reg, #0
+	add	\reg, \reg, #0
+	ror	\reg, \reg, #63
 alternative_cb_end
 .endm
 
@@ -100,7 +104,11 @@ u32 kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn);
 
 static inline unsigned long __kern_hyp_va(unsigned long v)
 {
-	asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n",
+	asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
+				    "ror %0, %0, #1\n"
+				    "add %0, %0, #0\n"
+				    "add %0, %0, #0\n"
+				    "ror %0, %0, #63\n",
 				    kvm_update_va_mask)
 		     : "+r" (v));
 	return v;
diff --git a/arch/arm64/kvm/haslr.c b/arch/arm64/kvm/haslr.c
index 2c865d1c1344..3691a5471d95 100644
--- a/arch/arm64/kvm/haslr.c
+++ b/arch/arm64/kvm/haslr.c
@@ -16,19 +16,23 @@
  */
 
 #include <linux/kvm_host.h>
+#include <linux/random.h>
+#include <linux/memblock.h>
 #include <asm/alternative.h>
 #include <asm/debug-monitors.h>
 #include <asm/insn.h>
 #include <asm/kvm_mmu.h>
 
+static u8 tag_lsb;
+static u64 tag_val;
 static u64 va_mask;
 
 u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 {
 	u32 rd, rn, insn;
 
-	/* We only expect a 1 instruction sequence */
-	BUG_ON((alt->orig_len / sizeof(insn)) != 1);
+	/* We only expect a 5 instruction sequence */
+	BUG_ON((alt->orig_len / sizeof(insn)) != 5);
 
 	/* VHE doesn't need any address translation, let's NOP everything */
 	if (has_vhe())
@@ -42,8 +46,32 @@ u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 		region  = idmap_addr & BIT(VA_BITS - 1);
 		region ^= BIT(VA_BITS - 1);
 
-		va_mask  = BIT(VA_BITS - 1) - 1;
-		va_mask |= region;
+		tag_lsb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^
+				(u64)(high_memory - 1));
+
+		if (tag_lsb == (VA_BITS - 1)) {
+			/*
+			 * No space in the address, let's compute the
+			 * mask so that it covers (VA_BITS - 1) bits,
+			 * and the region bit. The tag is set to zero.
+			 */
+			tag_lsb = tag_val = 0;
+			va_mask  = BIT(VA_BITS - 1) - 1;
+			va_mask |= region;
+		} else {
+			/*
+			 * We do have some free bits. Let's have the
+			 * mask to cover the low bits of the VA, and
+			 * the tag to contain the random stuff plus
+			 * the region bit.
+			 */
+			u64 mask = GENMASK_ULL(VA_BITS - 2, tag_lsb);
+
+			va_mask = BIT(tag_lsb) - 1;
+			tag_val  = get_random_long() & mask;
+			tag_val |= region;
+			tag_val >>= tag_lsb;
+		}
 	}
 
 	rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, oinsn);
@@ -60,6 +88,45 @@ u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 							  AARCH64_INSN_VARIANT_64BIT,
 							  rn, rd, va_mask);
 		break;
+
+	case 1:
+		if (!tag_lsb)
+			return aarch64_insn_gen_nop();
+
+		/* ROR is a variant of EXTR with Rm = Rn */
+		insn = aarch64_insn_gen_extr(AARCH64_INSN_VARIANT_64BIT,
+					     rn, rn, rd,
+					     tag_lsb);
+		break;
+
+	case 2:
+		if (!tag_lsb)
+			return aarch64_insn_gen_nop();
+
+		insn = aarch64_insn_gen_add_sub_imm(rd, rn,
+						    tag_val & (SZ_4K - 1),
+						    AARCH64_INSN_VARIANT_64BIT,
+						    AARCH64_INSN_ADSB_ADD);
+		break;
+
+	case 3:
+		if (!tag_lsb)
+			return aarch64_insn_gen_nop();
+
+		insn = aarch64_insn_gen_add_sub_imm(rd, rn,
+						    tag_val & GENMASK(23, 12),
+						    AARCH64_INSN_VARIANT_64BIT,
+						    AARCH64_INSN_ADSB_ADD);
+		break;
+
+	case 4:
+		if (!tag_lsb)
+			return aarch64_insn_gen_nop();
+
+		/* ROR is a variant of EXTR with Rm = Rn */
+		insn = aarch64_insn_gen_extr(AARCH64_INSN_VARIANT_64BIT,
+					     rn, rn, rd, 64 - tag_lsb);
+		break;
 	}
 
 	BUG_ON(insn == AARCH64_BREAK_FAULT);
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 0597c9846f1a..6633f5f07200 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1797,7 +1797,7 @@ int kvm_mmu_init(void)
 		  kern_hyp_va((unsigned long)high_memory - 1));
 
 	if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) &&
-	    hyp_idmap_start <  kern_hyp_va(~0UL) &&
+	    hyp_idmap_start <  kern_hyp_va((unsigned long)high_memory - 1) &&
 	    hyp_idmap_start != (unsigned long)__hyp_idmap_text_start) {
 		/*
 		 * The idmap page is intersecting with the VA space,
-- 
2.14.2

^ permalink raw reply related

* [PATCH v3 17/19] arm64: KVM: Dynamically compute the HYP VA mask
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

As we're moving towards a much more dynamic way to compute our
HYP VA, let's express the mask in a slightly different way.

Instead of comparing the idmap position to the "low" VA mask,
we directly compute the mask by taking into account the idmap's
(VA_BIT-1) bit.

No functionnal change.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/haslr.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/haslr.c b/arch/arm64/kvm/haslr.c
index 94475ea9847b..2c865d1c1344 100644
--- a/arch/arm64/kvm/haslr.c
+++ b/arch/arm64/kvm/haslr.c
@@ -21,28 +21,11 @@
 #include <asm/insn.h>
 #include <asm/kvm_mmu.h>
 
-#define HYP_PAGE_OFFSET_HIGH_MASK	((UL(1) << VA_BITS) - 1)
-#define HYP_PAGE_OFFSET_LOW_MASK	((UL(1) << (VA_BITS - 1)) - 1)
-
-static unsigned long get_hyp_va_mask(void)
-{
-	phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
-	unsigned long mask = HYP_PAGE_OFFSET_HIGH_MASK;
-
-	/*
-	 * Activate the lower HYP offset only if the idmap doesn't
-	 * clash with it,
-	 */
-	if (idmap_addr > HYP_PAGE_OFFSET_LOW_MASK)
-		mask = HYP_PAGE_OFFSET_HIGH_MASK;
-
-	return mask;
-}
+static u64 va_mask;
 
 u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 {
 	u32 rd, rn, insn;
-	u64 imm;
 
 	/* We only expect a 1 instruction sequence */
 	BUG_ON((alt->orig_len / sizeof(insn)) != 1);
@@ -51,6 +34,18 @@ u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 	if (has_vhe())
 		return aarch64_insn_gen_nop();
 
+	if (!va_mask) {
+		phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
+		u64 region;
+
+		/* Where is my RAM region? */
+		region  = idmap_addr & BIT(VA_BITS - 1);
+		region ^= BIT(VA_BITS - 1);
+
+		va_mask  = BIT(VA_BITS - 1) - 1;
+		va_mask |= region;
+	}
+
 	rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, oinsn);
 	rn = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, oinsn);
 
@@ -61,10 +56,9 @@ u32 __init kvm_update_va_mask(struct alt_instr *alt, int index, u32 oinsn)
 		break;
 
 	case 0:
-		imm = get_hyp_va_mask();
 		insn = aarch64_insn_gen_logical_immediate(AARCH64_INSN_LOGIC_AND,
 							  AARCH64_INSN_VARIANT_64BIT,
-							  rn, rd, imm);
+							  rn, rd, va_mask);
 		break;
 	}
 
-- 
2.14.2

^ permalink raw reply related

* [PATCH v3 16/19] arm64: insn: Allow ADD/SUB (immediate) with LSL #12
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

The encoder for ADD/SUB (immediate) can only cope with 12bit
immediates, while there is an encoding for a 12bit immediate shifted
by 12 bits to the left.

Let's fix this small oversight by allowing the LSL_12 bit to be set.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kernel/insn.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 59669d7d4383..20655537cdd1 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -35,6 +35,7 @@
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
+#define AARCH64_INSN_LSL_12	BIT(22)
 
 static int aarch64_insn_encoding_class[] = {
 	AARCH64_INSN_CLS_UNKNOWN,
@@ -903,9 +904,18 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
 		return AARCH64_BREAK_FAULT;
 	}
 
+	/* We can't encode more than a 24bit value (12bit + 12bit shift) */
+	if (imm & ~(BIT(24) - 1))
+		goto out;
+
+	/* If we have something in the top 12 bits... */
 	if (imm & ~(SZ_4K - 1)) {
-		pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
-		return AARCH64_BREAK_FAULT;
+		/* ... and in the low 12 bits -> error */
+		if (imm & (SZ_4K - 1))
+			goto out;
+
+		imm >>= 12;
+		insn |= AARCH64_INSN_LSL_12;
 	}
 
 	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
@@ -913,6 +923,10 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
 	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
 
 	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
+
+out:
+	pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
+	return AARCH64_BREAK_FAULT;
 }
 
 u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
-- 
2.14.2

^ permalink raw reply related

* [PATCH v3 15/19] arm64; insn: Add encoder for the EXTR instruction
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

Add an encoder for the EXTR instruction, which also implements the ROR
variant (where Rn == Rm).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/insn.h |  6 ++++++
 arch/arm64/kernel/insn.c      | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 815b35bc53ed..f62c56b1793f 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -319,6 +319,7 @@ __AARCH64_INSN_FUNCS(and_imm,	0x7F800000, 0x12000000)
 __AARCH64_INSN_FUNCS(orr_imm,	0x7F800000, 0x32000000)
 __AARCH64_INSN_FUNCS(eor_imm,	0x7F800000, 0x52000000)
 __AARCH64_INSN_FUNCS(ands_imm,	0x7F800000, 0x72000000)
+__AARCH64_INSN_FUNCS(extr,	0x7FA00000, 0x13800000)
 __AARCH64_INSN_FUNCS(b,		0xFC000000, 0x14000000)
 __AARCH64_INSN_FUNCS(bl,	0xFC000000, 0x94000000)
 __AARCH64_INSN_FUNCS(cbz,	0x7F000000, 0x34000000)
@@ -433,6 +434,11 @@ u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type,
 				       enum aarch64_insn_register Rn,
 				       enum aarch64_insn_register Rd,
 				       u64 imm);
+u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
+			  enum aarch64_insn_register Rm,
+			  enum aarch64_insn_register Rn,
+			  enum aarch64_insn_register Rd,
+			  u8 lsb);
 u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
 			      enum aarch64_insn_prfm_type type,
 			      enum aarch64_insn_prfm_target target,
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 72cb1721c63f..59669d7d4383 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -1621,3 +1621,35 @@ u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type,
 	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
 	return aarch64_encode_immediate(imm, variant, insn);
 }
+
+u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
+			  enum aarch64_insn_register Rm,
+			  enum aarch64_insn_register Rn,
+			  enum aarch64_insn_register Rd,
+			  u8 lsb)
+{
+	u32 insn;
+
+	insn = aarch64_insn_get_extr_value();
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if (lsb > 31)
+			return AARCH64_BREAK_FAULT;
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		if (lsb > 63)
+			return AARCH64_BREAK_FAULT;
+		insn |= AARCH64_INSN_SF_BIT;
+		insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_N, insn, 1);
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, lsb);
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, Rd);
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
+}
-- 
2.14.2

^ permalink raw reply related

* [PATCH v3 14/19] KVM: arm/arm64: Move HYP IO VAs to the "idmap" range
From: Marc Zyngier @ 2017-12-18 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171218173926.16911-1-marc.zyngier@arm.com>

We so far mapped our HYP IO (which is essencially the GICv2 control
registers) using the same method as for memory. It recently appeared
that is a bit unsafe:

we compute the HYP VA using the kern_hyp_va helper, but that helper
is only designed to deal with kernel VAs coming from the linear map,
and not from the vmalloc region... This could in turn cause some bad
aliasing between the two, amplified by the new VA randomisation.

A solution is to come up with our very own basic VA allocator for
MMIO. Since half of the HYP address space only contains a single
page (the idmap), we have plenty to borrow from. Let's use the idmap
as a base, and allocate downwards from it. GICv2 now lives on the
other side of the great VA barrier.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/mmu.c | 40 ++++++++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 6192d45d1e1a..0597c9846f1a 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -43,6 +43,9 @@ static unsigned long hyp_idmap_start;
 static unsigned long hyp_idmap_end;
 static phys_addr_t hyp_idmap_vector;
 
+static DEFINE_MUTEX(io_map_lock);
+static unsigned long io_map_base;
+
 #define S2_PGD_SIZE	(PTRS_PER_S2_PGD * sizeof(pgd_t))
 #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
 
@@ -502,27 +505,31 @@ static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size)
  *
  * Assumes hyp_pgd is a page table used strictly in Hyp-mode and
  * therefore contains either mappings in the kernel memory area (above
- * PAGE_OFFSET), or device mappings in the vmalloc range (from
- * VMALLOC_START to VMALLOC_END).
+ * PAGE_OFFSET), or device mappings in the idmap range.
  *
- * boot_hyp_pgd should only map two pages for the init code.
+ * boot_hyp_pgd should only map the idmap range, and is only used in
+ * the extended idmap case.
  */
 void free_hyp_pgds(void)
 {
+	pgd_t *id_pgd;
+
 	mutex_lock(&kvm_hyp_pgd_mutex);
 
+	id_pgd = boot_hyp_pgd ? boot_hyp_pgd : hyp_pgd;
+
+	if (id_pgd)
+		unmap_hyp_range(id_pgd, io_map_base,
+				hyp_idmap_start + PAGE_SIZE - io_map_base);
+
 	if (boot_hyp_pgd) {
-		unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
 		free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
 		boot_hyp_pgd = NULL;
 	}
 
 	if (hyp_pgd) {
-		unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
 		unmap_hyp_range(hyp_pgd, kern_hyp_va(PAGE_OFFSET),
 				(uintptr_t)high_memory - PAGE_OFFSET);
-		unmap_hyp_range(hyp_pgd, kern_hyp_va(VMALLOC_START),
-				VMALLOC_END - VMALLOC_START);
 
 		free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
 		hyp_pgd = NULL;
@@ -721,7 +728,8 @@ int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
 			   void __iomem **kaddr,
 			   void __iomem **haddr)
 {
-	unsigned long start, end;
+	pgd_t *pgd = hyp_pgd;
+	unsigned long base;
 	int ret;
 
 	*kaddr = ioremap(phys_addr, size);
@@ -733,19 +741,26 @@ int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
 		return 0;
 	}
 
+	mutex_lock(&io_map_lock);
+
+	base = io_map_base - size;
+	base &= ~(size - 1);
+
+	if (__kvm_cpu_uses_extended_idmap())
+		pgd = boot_hyp_pgd;
 
-	start = kern_hyp_va((unsigned long)*kaddr);
-	end = kern_hyp_va((unsigned long)*kaddr + size);
-	ret = __create_hyp_mappings(hyp_pgd, start, end,
+	ret = __create_hyp_mappings(pgd, base, base + size,
 				     __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
 
 	if (ret) {
 		iounmap(*kaddr);
 		*kaddr = NULL;
 	} else {
-		*haddr = (void __iomem *)start;
+		*haddr = (void __iomem *)base;
+		io_map_base = base;
 	}
 
+	mutex_unlock(&io_map_lock);
 	return ret;
 }
 
@@ -1826,6 +1841,7 @@ int kvm_mmu_init(void)
 			goto out;
 	}
 
+	io_map_base = hyp_idmap_start;
 	return 0;
 out:
 	free_hyp_pgds();
-- 
2.14.2

^ permalink raw reply related


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