Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 3/6] coresight: Support panic kdump functionality
From: Leo Yan @ 2018-01-10  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109184126.GA21932@xps15>

On Tue, Jan 09, 2018 at 11:41:26AM -0700, Mathieu Poirier wrote:
> On Thu, Dec 21, 2017 at 04:20:12PM +0800, Leo Yan wrote:
> > After kernel panic happens, coresight has many useful info can be used
> > for analysis.  For example, the trace info from ETB RAM can be used to
> > check the CPU execution flows before crash.  So we can save the tracing
> > data from sink devices, and rely on kdump to save DDR content and uses
> > "crash" tool to extract coresight dumping from vmcore file.
> > 
> > This patch is to add a simple framework to support panic dump
> > functionality; it registers panic notifier, and provide the general APIs
> > {coresight_kdump_add|coresight_kdump_del} as helper functions so any
> > coresight device can add itself into dump list or delete as needed.
> > 
> > This driver provides helper function coresight_kdump_update() to update
> > the dump buffer base address and buffer size.  This function can be used
> > by coresight driver, e.g. it can be used to save ETM meta data info at
> > runtime and these info can be prepared pre panic happening.
> > 
> > When kernel panic happens, the notifier iterates dump list and calls
> > callback function to dump device specific info.  The panic dump is
> > mainly used to dump trace data so we can get to know the execution flow
> > before the panic happens.
> > 
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/Kconfig                |   9 ++
> >  drivers/hwtracing/coresight/Makefile               |   1 +
> >  .../hwtracing/coresight/coresight-panic-kdump.c    | 154 +++++++++++++++++++++
> >  drivers/hwtracing/coresight/coresight-priv.h       |  13 ++
> >  include/linux/coresight.h                          |   7 +
> >  5 files changed, 184 insertions(+)
> >  create mode 100644 drivers/hwtracing/coresight/coresight-panic-kdump.c
> > 
> > diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> > index ef9cb3c..4812529 100644
> > --- a/drivers/hwtracing/coresight/Kconfig
> > +++ b/drivers/hwtracing/coresight/Kconfig
> > @@ -103,4 +103,13 @@ config CORESIGHT_CPU_DEBUG
> >  	  properly, please refer Documentation/trace/coresight-cpu-debug.txt
> >  	  for detailed description and the example for usage.
> >  
> > +config CORESIGHT_PANIC_KDUMP
> > +	bool "CoreSight Panic Kdump driver"
> > +	depends on ARM || ARM64
> 
> At this time only ETMv4 supports the feature, so it is only ARM64.

Thanks for reviewing, Mathieu.

Will change to only for ARM64.

> > +	help
> > +	  This driver provides panic kdump functionality for CoreSight
> > +	  devices.  When a kernel panic happen a device supplied callback function
> > +	  is used to save trace data to memory. From there we rely on kdump to extract
> > +	  the trace data from kernel dump file.
> > +
> >  endif
> > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> > index 61db9dd..946fe19 100644
> > --- a/drivers/hwtracing/coresight/Makefile
> > +++ b/drivers/hwtracing/coresight/Makefile
> > @@ -18,3 +18,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
> >  obj-$(CONFIG_CORESIGHT_DYNAMIC_REPLICATOR) += coresight-dynamic-replicator.o
> >  obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
> >  obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
> > +obj-$(CONFIG_CORESIGHT_PANIC_KDUMP) += coresight-panic-kdump.o
> > diff --git a/drivers/hwtracing/coresight/coresight-panic-kdump.c b/drivers/hwtracing/coresight/coresight-panic-kdump.c
> > new file mode 100644
> > index 0000000..c21d20b
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-panic-kdump.c
> > @@ -0,0 +1,154 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (c) 2017 Linaro Limited.
> > +#include <linux/coresight.h>
> > +#include <linux/coresight-pmu.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/device.h>
> > +#include <linux/init.h>
> > +#include <linux/list.h>
> > +#include <linux/mm.h>
> > +#include <linux/perf_event.h>
> > +#include <linux/slab.h>
> > +#include <linux/types.h>
> > +
> > +#include "coresight-priv.h"
> > +
> > +typedef void (*coresight_cb_t)(void *data);
> > +
> > +/**
> > + * struct coresight_kdump_node - Node information for dump
> > + * @cpu:	The cpu this node is affined to.
> > + * @csdev:	Handler for coresight device.
> > + * @buf:	Pointer for dump buffer.
> > + * @buf_size:	Length of dump buffer.
> > + * @list:	Hook to the list.
> > + */
> > +struct coresight_kdump_node {
> > +	int cpu;
> > +	struct coresight_device *csdev;
> > +	char *buf;
> > +	unsigned int buf_size;
> > +	struct list_head list;
> > +};
> > +
> > +static DEFINE_SPINLOCK(coresight_kdump_lock);
> > +static LIST_HEAD(coresight_kdump_list);
> > +static struct notifier_block coresight_kdump_nb;
> > +
> > +int coresight_kdump_update(struct coresight_device *csdev, char *buf,
> > +			   unsigned int buf_size)
> > +{
> > +	struct coresight_kdump_node *node = csdev->dump_node;
> > +
> > +	if (!node) {
> > +		dev_err(&csdev->dev, "Failed to update dump node.\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	node->buf = buf;
> > +	node->buf_size = buf_size;
> > +	return 0;
> > +}
> > +
> > +int coresight_kdump_add(struct coresight_device *csdev, int cpu)
> > +{
> > +	struct coresight_kdump_node *node;
> > +	unsigned long flags;
> > +
> > +	node = kzalloc(sizeof(*node), GFP_KERNEL);
> > +	if (!node)
> > +		return -ENOMEM;
> > +
> > +	csdev->dump_node = (void *)node;
> > +	node->cpu = cpu;
> > +	node->csdev = csdev;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +	list_add_tail(&node->list, &coresight_kdump_list);
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +	return 0;
> > +}
> > +
> > +void coresight_kdump_del(struct coresight_device *csdev)
> > +{
> > +	struct coresight_kdump_node *node, *next;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +	list_for_each_entry_safe(node, next, &coresight_kdump_list, list) {
> > +		if (node->csdev == csdev) {
> > +			list_del(&node->list);
> > +			kfree(node);
> > +			break;
> > +		}
> > +	}
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +}
> > +
> > +static coresight_cb_t
> > +coresight_kdump_get_cb(struct coresight_device *csdev)
> > +{
> > +	coresight_cb_t cb = NULL;
> > +
> > +	switch (csdev->type) {
> > +	case CORESIGHT_DEV_TYPE_SINK:
> > +	case CORESIGHT_DEV_TYPE_LINKSINK:
> > +		cb = sink_ops(csdev)->panic_cb;
> > +		break;
> > +	case CORESIGHT_DEV_TYPE_SOURCE:
> > +		cb = source_ops(csdev)->panic_cb;
> > +		break;
> > +	case CORESIGHT_DEV_TYPE_LINK:
> > +		cb = link_ops(csdev)->panic_cb;
> > +		break;
> 
> I don't see why we need a callback for link devices - didn't I raised
> that question before?

Yes, sorry I have not deleted for link devices completely. Will remove
it.

> And I've been thinking further about this.  The way we call the panic callbacks
> won't work.  When a panic is triggered there might be trace data in the CS network
> that hasn't made it to the sink yet and calling the panic callbacks for sinks
> will lead to a loss of data.
> 
> That is why, when accessing from both sysFS and perf, the current implementation
> takes great care to stop the tracers first and then deal with the sink.  To fix
> this I suggest to call the panic callbacks only for sources.  What happens there
> will depend on what interface is used (sysFS or perf) - look at what is
> currently done to get a better understanding.

Will look into this.

If I understand correctly, we need firstly stop tracers and save trace
data from sink, right? If so we need use single callback function to
disable path and dump data for sink, will study current case and check
what's the clean method for kdump.

> > +	default:
> > +		dev_info(&csdev->dev, "Unsupport panic dump\n");
> 
> I would not bother with the dev_info()...

Will remove it.

> > +		break;
> > +	}
> > +
> > +	return cb;
> > +}
> > +
> > +/**
> > + * coresight_kdump_notify - Invoke panic dump callbacks, this is
> > + * the main function to fulfill the panic dump.  It distinguishs
> > + * to two types: one is pre panic dump which the callback function
> > + * handler is NULL and coresight drivers can use function
> > + * coresight_kdump_update() to directly update dump buffer base
> > + * address and buffer size, for this case this function does nothing
> > + * and directly bail out; another case is for post panic dump so
> > + * invoke callback on alive CPU.
> 
> Now that pre and post processing are gone the description above doesn't match
> what the function is doing.

Yeah, will remove 'pre' and 'post' to avoid confusion.

> > + *
> > + * Returns: 0 on success.
> > + */
> > +static int coresight_kdump_notify(struct notifier_block *nb,
> > +				  unsigned long mode, void *_unused)
> > +{
> > +	struct coresight_kdump_node *node;
> > +	struct coresight_device *csdev;
> > +	coresight_cb_t cb;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +
> > +	list_for_each_entry(node, &coresight_kdump_list, list) {
> > +		csdev = node->csdev;
> > +		cb = coresight_kdump_get_cb(csdev);
> > +		if (cb)
> > +			cb(csdev);
> > +	}
> > +
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +	return 0;
> > +}
> > +
> > +static int __init coresight_kdump_init(void)
> > +{
> > +	int ret;
> > +
> > +	coresight_kdump_nb.notifier_call = coresight_kdump_notify;
> > +	ret = atomic_notifier_chain_register(&panic_notifier_list,
> > +					     &coresight_kdump_nb);
> > +	return ret;
> > +}
> > +late_initcall(coresight_kdump_init);
> > diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> > index f1d0e21d..937750e 100644
> > --- a/drivers/hwtracing/coresight/coresight-priv.h
> > +++ b/drivers/hwtracing/coresight/coresight-priv.h
> > @@ -151,4 +151,17 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
> >  static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
> >  #endif
> >  
> > +#ifdef CONFIG_CORESIGHT_PANIC_KDUMP
> > +extern int coresight_kdump_add(struct coresight_device *csdev, int cpu);
> > +extern void coresight_kdump_del(struct coresight_device *csdev);
> > +extern int coresight_kdump_update(struct coresight_device *csdev,
> > +				  char *buf, unsigned int buf_size);
> > +#else
> > +static inline int
> > +coresight_kdump_add(struct coresight_device *csdev, int cpu) { return 0; }
> > +static inline void coresight_kdump_del(struct coresight_device *csdev) {}
> > +static inline int coresight_kdump_update(struct coresight_device *csdev,
> > +	char *buf, unsigned int buf_size) { return 0; }
> 
> static inline int
> coresight_kdump_update(struct coresight_device *csdev, char *buf,
>                        unsigned int buf_size) { return 0; }

Will fix.

> > +#endif
> > +
> >  #endif
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index d950dad..43e40fa 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -171,6 +171,7 @@ struct coresight_device {
> >  	bool orphan;
> >  	bool enable;	/* true only if configured as part of a path */
> >  	bool activated;	/* true only if a sink is part of a path */
> > +	void *dump_node;
> 
> Please add a description for this entry.

Will do.

Thanks,
Leo Yan

> >  };
> >  
> >  #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
> > @@ -189,6 +190,7 @@ struct coresight_device {
> >   * @set_buffer:		initialises buffer mechanic before a trace session.
> >   * @reset_buffer:	finalises buffer mechanic after a trace session.
> >   * @update_buffer:	update buffer pointers after a trace session.
> > + * @panic_cb:		hook function for panic notifier.
> >   */
> >  struct coresight_ops_sink {
> >  	int (*enable)(struct coresight_device *csdev, u32 mode);
> > @@ -205,6 +207,7 @@ struct coresight_ops_sink {
> >  	void (*update_buffer)(struct coresight_device *csdev,
> >  			      struct perf_output_handle *handle,
> >  			      void *sink_config);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  /**
> > @@ -212,10 +215,12 @@ struct coresight_ops_sink {
> >   * Operations available for links.
> >   * @enable:	enables flow between iport and oport.
> >   * @disable:	disables flow between iport and oport.
> > + * @panic_cb:	hook function for panic notifier.
> >   */
> >  struct coresight_ops_link {
> >  	int (*enable)(struct coresight_device *csdev, int iport, int oport);
> >  	void (*disable)(struct coresight_device *csdev, int iport, int oport);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  /**
> > @@ -227,6 +232,7 @@ struct coresight_ops_link {
> >   *		to the HW.
> >   * @enable:	enables tracing for a source.
> >   * @disable:	disables tracing for a source.
> > + * @panic_cb:	hook function for panic notifier.
> >   */
> >  struct coresight_ops_source {
> >  	int (*cpu_id)(struct coresight_device *csdev);
> > @@ -235,6 +241,7 @@ struct coresight_ops_source {
> >  		      struct perf_event *event,  u32 mode);
> >  	void (*disable)(struct coresight_device *csdev,
> >  			struct perf_event *event);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  struct coresight_ops {
> > -- 
> > 2.7.4
> > 

^ permalink raw reply

* [PATCH v3 6/6] coresight: etm4x: Support panic kdump
From: Leo Yan @ 2018-01-10  5:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109202128.GB21932@xps15>

On Tue, Jan 09, 2018 at 01:21:28PM -0700, Mathieu Poirier wrote:
> On Thu, Dec 21, 2017 at 04:20:15PM +0800, Leo Yan wrote:
> > ETMv4 hardware information and configuration needs to be saved as
> > metadata; these metadata should be compatible with tool 'perf' and
> > can be used for tracing data analysis.  ETMv4 usually works as tracer
> > per CPU, we cannot wait to gather ETM info after the CPU has been panic
> > and cannot execute dump operations for itself; so should gather
> > metadata when the corresponding CPU is alive.
> > 
> > Since values in TRCIDR{0, 1, 2, 8} and TRCAUTHSTATUS are read-only and
> > won't change at the runtime.  Those registers value are filled when
> > tracers are instantiated.
> > 
> > The configuration and control registers TRCCONFIGR and TRCTRACEIDR are
> > dynamically configured, we record their value when enabling coresight
> > path.  When operating from sysFS tracer these two registers are recorded
> > in etm4_enable_sysfs() and add kdump node into list, and remove the
> > kdump node in etm4_disable_sysfs().  When operating from perf,
> > etm_setup_aux() adds all tracers to the dump list and etm4_enable_perf()
> > is used to record configuration registers and update dump buffer info,
> > this can avoid unnecessary list addition and deletion operations.
> > Removal of the tracers from the dump list is done in function
> > free_event_data().
> > 
> > Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/coresight-etm-perf.c | 12 +++++++++++-
> >  drivers/hwtracing/coresight/coresight-etm4x.c    | 23 +++++++++++++++++++++++
> >  drivers/hwtracing/coresight/coresight-etm4x.h    | 15 +++++++++++++++
> >  3 files changed, 49 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > index 8a0ad77..fec779b 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > @@ -137,6 +137,12 @@ static void free_event_data(struct work_struct *work)
> >  	}
> >  
> >  	for_each_cpu(cpu, mask) {
> > +		struct coresight_device *csdev;
> > +
> > +		csdev = per_cpu(csdev_src, cpu);
> > +		if (csdev)
> > +			coresight_kdump_del(csdev);
> > +
> >  		if (!(IS_ERR_OR_NULL(event_data->path[cpu])))
> >  			coresight_release_path(event_data->path[cpu]);
> >  	}
> > @@ -195,7 +201,7 @@ static void etm_free_aux(void *data)
> >  static void *etm_setup_aux(int event_cpu, void **pages,
> >  			   int nr_pages, bool overwrite)
> >  {
> > -	int cpu;
> > +	int cpu, ret;
> >  	cpumask_t *mask;
> >  	struct coresight_device *sink;
> >  	struct etm_event_data *event_data = NULL;
> > @@ -238,6 +244,10 @@ static void *etm_setup_aux(int event_cpu, void **pages,
> >  		event_data->path[cpu] = coresight_build_path(csdev, sink);
> >  		if (IS_ERR(event_data->path[cpu]))
> >  			goto err;
> > +
> > +		ret = coresight_kdump_add(csdev, cpu);
> 
> Aren't you missing the configuration for trcconfigr and trctraceidr?

Ah, should update these two configurations in function
etm4_enable_perf()?

> > +		if (ret)
> > +			goto err;
> >  	}
> >  
> >  	if (!sink_ops(sink)->alloc_buffer)
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> > index cf364a5..cbde398 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> > @@ -258,10 +258,19 @@ static int etm4_enable_perf(struct coresight_device *csdev,
> >  static int etm4_enable_sysfs(struct coresight_device *csdev)
> >  {
> >  	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> > +	struct etmv4_config *config = &drvdata->config;
> > +	struct etmv4_metadata *metadata = &drvdata->metadata;
> >  	int ret;
> >  
> >  	spin_lock(&drvdata->spinlock);
> >  
> > +	/* Update meta data and add into kdump list */
> > +	metadata->trcconfigr = config->cfg;
> > +	metadata->trctraceidr = drvdata->trcid;
> > +
> > +	coresight_kdump_add(csdev, drvdata->cpu);
> > +	coresight_kdump_update(csdev, (char *)metadata, sizeof(*metadata));
> > +
> >  	/*
> >  	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
> >  	 * ensures that register writes occur when cpu is powered.
> > @@ -384,6 +393,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
> >  	 */
> >  	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
> >  
> > +	/* Delete from kdump list */
> > +	coresight_kdump_del(csdev);
> > +
> >  	spin_unlock(&drvdata->spinlock);
> >  	cpus_read_unlock();
> >  
> > @@ -438,6 +450,7 @@ static void etm4_init_arch_data(void *info)
> >  	u32 etmidr4;
> >  	u32 etmidr5;
> >  	struct etmv4_drvdata *drvdata = info;
> > +	struct etmv4_metadata *metadata = &drvdata->metadata;
> >  
> >  	/* Make sure all registers are accessible */
> >  	etm4_os_unlock(drvdata);
> > @@ -590,6 +603,16 @@ static void etm4_init_arch_data(void *info)
> >  	drvdata->nrseqstate = BMVAL(etmidr5, 25, 27);
> >  	/* NUMCNTR, bits[30:28] number of counters available for tracing */
> >  	drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
> > +
> > +	/* Update metadata */
> > +	metadata->magic = ETM4_METADATA_MAGIC;
> > +	metadata->cpu = drvdata->cpu;
> > +	metadata->trcidr0 = readl_relaxed(drvdata->base + TRCIDR0);
> > +	metadata->trcidr1 = readl_relaxed(drvdata->base + TRCIDR1);
> > +	metadata->trcidr2 = readl_relaxed(drvdata->base + TRCIDR2);
> > +	metadata->trcidr8 = readl_relaxed(drvdata->base + TRCIDR8);
> > +	metadata->trcauthstatus = readl_relaxed(drvdata->base + TRCAUTHSTATUS);
> > +
> >  	CS_LOCK(drvdata->base);
> >  }
> >  
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> > index b3b5ea7..08dc8b7 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> > @@ -198,6 +198,20 @@
> >  #define ETM_EXLEVEL_NS_HYP		BIT(14)
> >  #define ETM_EXLEVEL_NS_NA		BIT(15)
> >  
> > +#define ETM4_METADATA_MAGIC		0x4040404040404040ULL
> 
> This is a duplicate of the magic value found in cs-etm.h but I'm not sure of
> what we'll do about that. It is probably time to come up
> with a shared file between the kernel and the perf tools, just like
> coresight-pmu.h.  You can have a stab at it or concentrate on my previous
> comments for now - it's entirely up to you.

I will do some try for this for changing to use one shared single
header, if I have no confidence for this I will go back to keep this
code for new version patch.

> > +
> > +struct etmv4_metadata {
> > +	u64 magic;
> > +	u64 cpu;
> > +	u64 trcconfigr;
> > +	u64 trctraceidr;
> > +	u64 trcidr0;
> > +	u64 trcidr1;
> > +	u64 trcidr2;
> > +	u64 trcidr8;
> > +	u64 trcauthstatus;
> > +};
> 
> Same here...  This is a duplicate of struct etmv4_drvdata.  Again not sure about
> the best way to handle this.  I'll think about it.

Sure, I might check with you when I spin patches for this.

Thanks,
Leo Yan

> > +
> >  /**
> >   * struct etmv4_config - configuration information related to an ETMv4
> >   * @mode:	Controls various modes supported by this ETM.
> > @@ -393,6 +407,7 @@ struct etmv4_drvdata {
> >  	bool				atbtrig;
> >  	bool				lpoverride;
> >  	struct etmv4_config		config;
> > +	struct etmv4_metadata		metadata;
> >  };
> >  
> >  /* Address comparator access types */
> > -- 
> > 2.7.4
> > 

^ permalink raw reply

* [PATCH v2 5/5] pinctrl: imx6ul: add IOMUXC SNVS pinctrl driver for i.MX 6ULL
From: A.s. Dong @ 2018-01-10  5:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYJcS3Ng=uR-iPgJ22ABfbiVENjWGsaWwShUfbg1hU4+g@mail.gmail.com>

Hi Linus,

> -----Original Message-----
> From: Linus Walleij [mailto:linus.walleij at linaro.org]
> Sent: Tuesday, January 09, 2018 10:08 PM
....
> 
> Stefan, would you consider making a patch adding you, Dong Aisheng and
> Shawn Guo as maintainers in MAINTAINERS for
> drivers/pinctrl/freescale/*
> Documentation/devicetree/bindings/pinctrl/fsl,*
> ?

I'm okay to take that MAINTAINER work.
Thanks for the nomination.

Regards
Dong Aisheng

^ permalink raw reply

* [PATCH 05/10] perf tools: Add support for decoding CoreSight trace data
From: Leo Yan @ 2018-01-10  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJ9a7VjEdu9gsTw9eLhLJnfjxewZHAr4k-DELMPk3zoG=ZPj6g@mail.gmail.com>

Hi Mike,

On Tue, Jan 09, 2018 at 12:09:58PM +0000, Mike Leach wrote:
> Hi Leo,
> 
> The OCSD_GEN_TRC_ELEM_ADDR_NACC element indicates that the decoder
> does not have an code image mapping for the address contained in the
> trace, at the location described by this element. the payload for the
> NACC element is the memory location it could not address.
> This means that it cannot correctly follow the instruction execution
> sequence described by the individual trace packets.
> 
> The dump option works because we do not need to follow the execution
> sequence to dump raw trace packets.
> 
> It is not clear to me if the perf script option as you specified is
> mapping the vmlinux image into the decoder.

I only can say that the 'perf script' has loaded symbol list by the
option '--kallsyms ./System.map'.  Here have one corner case is for
option '-k vmlinux', at my side I build 'perf' tool without linking
libelf, so perf cannot directly parse kernel symbol.  If the perf
tool is built with linking libelf, then we can directly load kernel
symbol mapping from vmlinux and don't need specifiy option
'--kallsyms ./System.map' anymore.

Could you point which perf code will pass vmlinux mapping to the
decoder? I don't know this before.  After some debugging I only found
perf relies on OpenCSD to return back OCSD_GEN_TRC_ELEM_INSTR_RANGE
and then perf will do symbol/sym_off analysis, otherwise it will skip
symbol analysis.

BTW, I use the same 'perf script' command with OpenCSD v0.7.5, it
can return back OCSD_GEN_TRC_ELEM_INSTR_RANGE but not
OCSD_GEN_TRC_ELEM_ADDR_NACC so it can print out kernel symbol, this
is for using the same perf.data and vmlinux files.

Thanks,
Leo Yan

> On 30 December 2017 at 00:33, Leo Yan <leo.yan@linaro.org> wrote:
> > Hi Mathieu, Mike,
> >
> > On Fri, Dec 15, 2017 at 09:44:54AM -0700, Mathieu Poirier wrote:
> >> Adding functionality to create a CoreSight trace decoder capable
> >> of decoding trace data pushed by a client application.
> >>
> >> Co-authored-by: Tor Jeremiassen <tor@ti.com>
> >> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >> ---
> >>  tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 119 ++++++++++++++++++++++++
> >>  1 file changed, 119 insertions(+)
> >>
> >> diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> index 6a4c86b1431f..57b020b0b36f 100644
> >> --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> @@ -200,6 +200,121 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
> >>       }
> >>  }
> >>
> >> +static ocsd_datapath_resp_t
> >> +cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
> >> +                           const ocsd_generic_trace_elem *elem,
> >> +                           const u8 trace_chan_id,
> >> +                           enum cs_etm_sample_type sample_type)
> >> +{
> >> +     u32 et = 0;
> >> +     struct int_node *inode = NULL;
> >> +
> >> +     if (decoder->packet_count >= MAX_BUFFER - 1)
> >> +             return OCSD_RESP_FATAL_SYS_ERR;
> >> +
> >> +     /* Search the RB tree for the cpu associated with this traceID */
> >> +     inode = intlist__find(traceid_list, trace_chan_id);
> >> +     if (!inode)
> >> +             return OCSD_RESP_FATAL_SYS_ERR;
> >> +
> >> +     et = decoder->tail;
> >> +     decoder->packet_buffer[et].sample_type = sample_type;
> >> +     decoder->packet_buffer[et].start_addr = elem->st_addr;
> >> +     decoder->packet_buffer[et].end_addr = elem->en_addr;
> >> +     decoder->packet_buffer[et].exc = false;
> >> +     decoder->packet_buffer[et].exc_ret = false;
> >> +     decoder->packet_buffer[et].cpu = *((int *)inode->priv);
> >> +
> >> +     /* Wrap around if need be */
> >> +     et = (et + 1) & (MAX_BUFFER - 1);
> >> +
> >> +     decoder->tail = et;
> >> +     decoder->packet_count++;
> >> +
> >> +     if (decoder->packet_count == MAX_BUFFER - 1)
> >> +             return OCSD_RESP_WAIT;
> >> +
> >> +     return OCSD_RESP_CONT;
> >> +}
> >> +
> >> +static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
> >> +                             const void *context,
> >> +                             const ocsd_trc_index_t indx __maybe_unused,
> >> +                             const u8 trace_chan_id __maybe_unused,
> >> +                             const ocsd_generic_trace_elem *elem)
> >> +{
> >> +     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
> >> +     struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
> >
> > After apply this patch set and build 'perf' tool with linking
> > OpenCSDv0.8.0 libs, I can everytime OpenCSD parses 'elem->elem_type'
> > is OCSD_GEN_TRC_ELEM_ADDR_NACC but not OCSD_GEN_TRC_ELEM_INSTR_RANGE.
> >
> > As result, the 'perf' tool can dump the raw data with '-D' option but
> > it cannot analyze the symbol and symbol offset with below command:
> >
> > ./perf script -v -a -F cpu,event,ip,sym,symoff -i ./perf.data -k vmlinux
> > --kallsyms ./System.map
> >
> > Have uploaded perf.data/vmlinux/System.map in the folder:
> > http://people.linaro.org/~leo.yan/binaries/perf_4.15_r4/
> >
> > Thanks,
> > Leo Yan
> >
> >> +     switch (elem->elem_type) {
> >> +     case OCSD_GEN_TRC_ELEM_UNKNOWN:
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_NO_SYNC:
> >> +             decoder->trace_on = false;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_TRACE_ON:
> >> +             decoder->trace_on = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
> >> +             resp = cs_etm_decoder__buffer_packet(decoder, elem,
> >> +                                                  trace_chan_id,
> >> +                                                  CS_ETM_RANGE);
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_EXCEPTION:
> >> +             decoder->packet_buffer[decoder->tail].exc = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
> >> +             decoder->packet_buffer[decoder->tail].exc_ret = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
> >> +     case OCSD_GEN_TRC_ELEM_EO_TRACE:
> >> +     case OCSD_GEN_TRC_ELEM_ADDR_NACC:
> >> +     case OCSD_GEN_TRC_ELEM_TIMESTAMP:
> >> +     case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
> >> +     case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
> >> +     case OCSD_GEN_TRC_ELEM_EVENT:
> >> +     case OCSD_GEN_TRC_ELEM_SWTRACE:
> >> +     case OCSD_GEN_TRC_ELEM_CUSTOM:
> >> +     default:
> >> +             break;
> >> +     }
> >> +
> >> +     return resp;
> >> +}
> >> +
> >> +static int cs_etm_decoder__create_etm_packet_decoder(
> >> +                                     struct cs_etm_trace_params *t_params,
> >> +                                     struct cs_etm_decoder *decoder)
> >> +{
> >> +     const char *decoder_name;
> >> +     ocsd_etmv4_cfg trace_config_etmv4;
> >> +     void *trace_config;
> >> +     u8 csid;
> >> +
> >> +     switch (t_params->protocol) {
> >> +     case CS_ETM_PROTO_ETMV4i:
> >> +             cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
> >> +             decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
> >> +             trace_config = &trace_config_etmv4;
> >> +             break;
> >> +     default:
> >> +             return -1;
> >> +     }
> >> +
> >> +     if (ocsd_dt_create_decoder(decoder->dcd_tree,
> >> +                                  decoder_name,
> >> +                                  OCSD_CREATE_FLG_FULL_DECODER,
> >> +                                  trace_config, &csid))
> >> +             return -1;
> >> +
> >> +     if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
> >> +                                    cs_etm_decoder__gen_trace_elem_printer,
> >> +                                    decoder))
> >> +             return -1;
> >> +
> >> +     return 0;
> >> +}
> >> +
> >>  static int
> >>  cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> >>                                  struct cs_etm_trace_params *t_params,
> >> @@ -208,6 +323,10 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> >>       if (d_params->operation == CS_ETM_OPERATION_PRINT)
> >>               return cs_etm_decoder__create_etm_packet_printer(t_params,
> >>                                                                decoder);
> >> +     else if (d_params->operation == CS_ETM_OPERATION_DECODE)
> >> +             return cs_etm_decoder__create_etm_packet_decoder(t_params,
> >> +                                                              decoder);
> >> +
> >>       return -1;
> >>  }
> >>
> >> --
> >> 2.7.4
> >>
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> 
> 
> -- 
> Mike Leach
> Principal Engineer, ARM Ltd.
> Blackburn Design Centre. UK

^ permalink raw reply

* [PATCH 3/3] pinctrl: qcom: Don't allow protected pins to be requested
From: Bjorn Andersson @ 2018-01-10  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110015848.11480-4-sboyd@codeaurora.org>

On Tue 09 Jan 17:58 PST 2018, Stephen Boyd wrote:

I like it, a few comment below though.

> +static int msm_gpio_init_irq_valid_mask(struct gpio_chip *chip,
> +					struct msm_pinctrl *pctrl)
> +{
> +	int ret;
> +	unsigned int len, i;
> +	unsigned int max_gpios = pctrl->soc->ngpios;
> +	struct device_node *np = pctrl->dev->of_node;
> +
> +	/* The number of GPIOs in the ACPI tables */
> +	ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0);
> +	if (ret > 0 && ret < max_gpios) {
> +		u16 *tmp;
> +
> +		len = ret;
> +		tmp = kmalloc_array(len, sizeof(tmp[0]), GFP_KERNEL);
> +		if (!tmp)
> +			return -ENOMEM;
> +
> +		ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp,
> +						     len);
> +		if (ret < 0) {
> +			dev_err(pctrl->dev, "could not read list of GPIOs\n");
> +			kfree(tmp);
> +			return ret;
> +		}
> +
> +		bitmap_zero(chip->irq_valid_mask, max_gpios);

The valid_mask is moving into the gpio_irq_chip, so this should be
chip->irq.valid_mask.

See dc7b0387ee89 ("gpio: Move irq_valid_mask into struct gpio_irq_chip")

> +		for (i = 0; i < len; i++)
> +			set_bit(tmp[i], chip->irq_valid_mask);
> +

You're leaking tmp here.

> +		return 0;
> +	}
> +
> +	/* If there's a DT ngpios-ranges property then add those ranges */
> +	ret = of_property_count_u32_elems(np,  "ngpios-ranges");
> +	if (ret > 0 && ret % 2 == 0 && ret / 2 < max_gpios) {
> +		u32 start;
> +		u32 count;
> +
> +		len = ret / 2;
> +		bitmap_zero(chip->irq_valid_mask, max_gpios);
> +
> +		for (i = 0; i < len; i++) {

If you take steps of 2, when looping from 0 to ret, your loop index will
have the value that you're passing as index into the read - without
duplicating it.

> +			of_property_read_u32_index(np, "ngpios-ranges",
> +						   i * 2, &start);
> +			of_property_read_u32_index(np, "ngpios-ranges",
> +						   i * 2 + 1, &count);
> +			bitmap_set(chip->irq_valid_mask, start, count);
> +		}
> +	}
> +
> +	return 0;
> +}
[..]
> @@ -824,6 +907,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
>  	chip->parent = pctrl->dev;
>  	chip->owner = THIS_MODULE;
>  	chip->of_node = pctrl->dev->of_node;
> +	chip->irq_need_valid_mask = msm_gpio_needs_irq_valid_mask(pctrl);

chip->irq.need_valid_mask

>  
>  	ret = gpiochip_add_data(&pctrl->chip, pctrl);
>  	if (ret) {
> @@ -831,6 +915,12 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
>  		return ret;
>  	}
>  
> +	ret = msm_gpio_init_irq_valid_mask(chip, pctrl);
> +	if (ret) {
> +		dev_err(pctrl->dev, "Failed to setup irq valid bits\n");

gpiochip_remove() here, to release resources allocated by
gpiochip_add_data.

> +		return ret;
> +	}
> +
>  	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
>  	if (ret) {
>  		dev_err(pctrl->dev, "Failed to add pin range\n");

Regards,
Bjorn

^ permalink raw reply

* [PATCH 1/3] gpiolib: Export gpiochip_irqchip_irq_valid() to drivers
From: Bjorn Andersson @ 2018-01-10  6:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110015848.11480-2-sboyd@codeaurora.org>

On Tue 09 Jan 17:58 PST 2018, Stephen Boyd wrote:

> Some pinctrl drivers can use the gpiochip irq valid information
> to figure out if certain gpios are exposed to the kernel for
> usage or not. Expose this API so we can use it in the
> pinmux_ops::request ops.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Regards,
Bjorn

> ---
>  drivers/gpio/gpiolib.c      | 5 +++--
>  include/linux/gpio/driver.h | 3 +++
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index b80936a25caa..c18b7b60ea1d 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -1503,14 +1503,15 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
>  	gpiochip->irq.valid_mask = NULL;
>  }
>  
> -static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> -				       unsigned int offset)
> +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> +				unsigned int offset)
>  {
>  	/* No mask means all valid */
>  	if (likely(!gpiochip->irq.valid_mask))
>  		return true;
>  	return test_bit(offset, gpiochip->irq.valid_mask);
>  }
> +EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid);
>  
>  /**
>   * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
> diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
> index 7258cd676df4..1ba9a331ec51 100644
> --- a/include/linux/gpio/driver.h
> +++ b/include/linux/gpio/driver.h
> @@ -436,6 +436,9 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
>  			     struct lock_class_key *lock_key,
>  			     struct lock_class_key *request_key);
>  
> +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> +				unsigned int offset);
> +
>  #ifdef CONFIG_LOCKDEP
>  
>  /*
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

^ permalink raw reply

* [PATCH v2] iommu/exynos: Don't unconditionally steal bus ops
From: Marek Szyprowski @ 2018-01-10  6:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <da24d31fc6f4be7b44ceef215f672c0ed3c37979.1515511941.git.robin.murphy@arm.com>

Hi Robin,

On 2018-01-09 16:34, Robin Murphy wrote:
> Removing the early device registration hook overlooked the fact that
> it only ran conditionally on a compatible device being present in the
> DT. With exynos_iommu_init() now running as an unconditional initcall,
> problems arise on non-Exynos systems when other IOMMU drivers find
> themselves unable to install their ops on the platform bus, or at worst
> the Exynos ops get called with someone else's domain and all hell breaks
> loose.
>
> The global ops/cache setup could probably all now be triggered from the
> first IOMMU probe, as with dma_dev assigment, but for the time being the
> simplest fix is to resurrect the logic from commit a7b67cd5d9af
> ("iommu/exynos: Play nice in multi-platform builds") to explicitly check
> the DT for the presence of an Exynos IOMMU before trying anything.
>
> Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code")
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>

> ---
>
> v2: Use the simpler explicit DT check.
>
>   drivers/iommu/exynos-iommu.c | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
> index 79c45650f8de..736d4552d96f 100644
> --- a/drivers/iommu/exynos-iommu.c
> +++ b/drivers/iommu/exynos-iommu.c
> @@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = {
>   
>   static int __init exynos_iommu_init(void)
>   {
> +	struct device_node *np;
>   	int ret;
>   
> +	np = of_find_matching_node(NULL, sysmmu_of_match);
> +	if (!np)
> +		return 0;
> +
> +	of_node_put(np);
> +
>   	lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
>   				LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
>   	if (!lv2table_kmem_cache) {

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply

* [PATCH 0/2] pinctrl: meson: use one uniform 'function' name
From: Jerome Brunet @ 2018-01-10  7:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a6a4ed23-696c-ae2d-9b6a-c2578372b1aa@amlogic.com>

On Wed, 2018-01-10 at 10:12 +0800, Yixun Lan wrote:
> 
> On 01/08/18 16:52, Jerome Brunet wrote:
> > On Mon, 2018-01-08 at 15:33 +0800, Yixun Lan wrote:
> > > These two patches are general improvement for meson pinctrl driver.
> > > It make the two pinctrl trees (ee/ao) to share one uniform 'function' name for
> > > one hardware block even its pin groups live inside two differet hardware domains,
> > > which for example EE vs AO domain here.
> > > 
> > > This idea is motivated by Martin's question at [1]
> > > 
> > > [1]
> > >  http://lkml.kernel.org/r/CAFBinCCuQ-NK747+GHDkhZty_UMMgzCYOYFcNTrRDJgU8OM=Gw at mail.gmail.com
> > > 
> > > 
> > > Yixun Lan (2):
> > >   pinctrl: meson: introduce a macro to have name/groups seperated
> > >   pinctrl: meson-axg: correct the pin expansion of UART_AO_B
> > > 
> > >  drivers/pinctrl/meson/pinctrl-meson-axg.c | 4 ++--
> > >  drivers/pinctrl/meson/pinctrl-meson.h     | 8 +++++---
> > >  2 files changed, 7 insertions(+), 5 deletions(-)
> > 
> > Hi Yixun,
> > 
> > Honestly, I don't like the idea. I think it adds an unnecessary complexity.
> > I don't see the point of FUNCTION_EX(uart_ao_b, _z) when you could simply write 
> > FUNCTION(uart_ao_b_z) ... especially when there is just a couple of function per
> > SoC available on different domains.
> > 
> > A pinctrl driver can already be challenging to understand at first, let's keep
> > it simple and avoid adding more macros.
> > 
> 
> Hi Jerome?
>   In my opinion, the idea of keeping one uniform 'function' in DT (thus
> introducing another macro) is worth considering. It would make the DT
> part much clean.

Ok this is your opinion. I don't share it. Keeping function names tidy is good,
I don't think we need another macro to do so.

>   And yes, it's a trade-off here, either we 1) do more in code to make
> DT clean or 2) do nothing in the code level to make DT live with it.

I don't see how adding a macro doing just string concatenation is going to make
anything more clean. It does not prevent one to write FUNCTION_EX(uart_ao_b,
_gpioz), resulting in uart_ao_b_gpioz, which is what is apparently considered
'not clean'

BTW, there no cleanness issue here, the name is just out of the 'usual scheme'
but there is no problem with. If you want to change this, and
s/uart_ao_b_gpioz/uart_ao_b_z/, now is the time to change it. 

> 
> Yixun
> --
> To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 0/2] phy: rockchip-emmc: fixes emmc-phy power on failed with rk3399 SoCs
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kishon,

Since the Shawn isn't available, I take over this series patches for now.

As the original bug had tracked on https://issuetracker.google.com/71561742.
In some cases, the mmc phy power on failed during booting up.
The log as below:
...
[   2.375333] rockchip_emmc_phy_power: caldone timeout.
[    2.377815] phy phy-ff770000.syscon:phy at f780.4: phy poweron failed --> -110
...
[    2.489295] mmc0: mmc_select_hs400es failed, error -110
[    2.489302] mmc0: error -110 whilst initialising MMC card
..

The actual emulate, the wait 5us for calpad busy trimming, that's no enough.
We need give the enough margin for it.

Verified on url =
        https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-4.4
This series patches can apply and bring up with kernel-next on rk3399 chromebook.

-Caesar


Changes in v2:
- print the return valut with regmap_read_poll_timeout failing.
- As Brian commented on https://patchwork.kernel.org/patch/10139891/,
  changed the note and added to print error value with
  regmap_read_poll_timeout API.

Shawn Lin (2):
  phy: rockchip-emmc: retry calpad busy trimming
  phy: rockchip-emmc: use regmap_read_poll_timeout to poll dllrdy

 drivers/phy/rockchip/phy-rockchip-emmc.c | 60 +++++++++++++++-----------------
 1 file changed, 28 insertions(+), 32 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 1/2] phy: rockchip-emmc: retry calpad busy trimming
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515569879-31808-1-git-send-email-wxt@rock-chips.com>

From: Shawn Lin <shawn.lin@rock-chips.com>

It turns out that 5us isn't enough for all cases, so let's
retry some more times to wait for caldone.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Tested-by: Ziyuan Xu <xzy.xu@rock-chips.com>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
---

Changes in v2:
- print the return valut with regmap_read_poll_timeout failing.

 drivers/phy/rockchip/phy-rockchip-emmc.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index f1b24f1..574838f 100644
--- a/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -76,6 +76,10 @@
 #define PHYCTRL_OTAPDLYSEL_MASK		0xf
 #define PHYCTRL_OTAPDLYSEL_SHIFT	0x7
 
+#define PHYCTRL_IS_CALDONE(x) \
+	((((x) >> PHYCTRL_CALDONE_SHIFT) & \
+	  PHYCTRL_CALDONE_MASK) == PHYCTRL_CALDONE_DONE)
+
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
 	struct regmap	*reg_base;
@@ -90,6 +94,7 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long rate;
 	unsigned long timeout;
+	int ret;
 
 	/*
 	 * Keep phyctrl_pdb and phyctrl_endll low to allow
@@ -160,17 +165,19 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 				   PHYCTRL_PDB_SHIFT));
 
 	/*
-	 * According to the user manual, it asks driver to
-	 * wait 5us for calpad busy trimming
+	 * According to the user manual, it asks driver to wait 5us for
+	 * calpad busy trimming. However it is documented that this value is
+	 * PVT(A.K.A process,voltage and temperature) relevant, so some
+	 * failure cases are found which indicates we should be more tolerant
+	 * to calpad busy trimming.
 	 */
-	udelay(5);
-	regmap_read(rk_phy->reg_base,
-		    rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-		    &caldone);
-	caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
-	if (caldone != PHYCTRL_CALDONE_DONE) {
-		pr_err("rockchip_emmc_phy_power: caldone timeout.\n");
-		return -ETIMEDOUT;
+	ret = regmap_read_poll_timeout(rk_phy->reg_base,
+				       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+				       caldone, PHYCTRL_IS_CALDONE(caldone),
+				       5, 50);
+	if (ret) {
+		pr_err("%s: caldone timeout, ret=%d\n", __func__, ret);
+		return ret;
 	}
 
 	/* Set the frequency of the DLL operation */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/2] phy: rockchip-emmc: use regmap_read_poll_timeout to poll dllrdy
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515569879-31808-1-git-send-email-wxt@rock-chips.com>

From: Shawn Lin <shawn.lin@rock-chips.com>

Just use the API instead of open-coding it, no functional change
intended.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>

---

Changes in v2:
- As Brian commented on https://patchwork.kernel.org/patch/10139891/,
  changed the note and added to print error value with
  regmap_read_poll_timeout API.

 drivers/phy/rockchip/phy-rockchip-emmc.c | 33 +++++++++++---------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index 574838f..343c623 100644
--- a/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -79,6 +79,9 @@
 #define PHYCTRL_IS_CALDONE(x) \
 	((((x) >> PHYCTRL_CALDONE_SHIFT) & \
 	  PHYCTRL_CALDONE_MASK) == PHYCTRL_CALDONE_DONE)
+#define PHYCTRL_IS_DLLRDY(x) \
+	((((x) >> PHYCTRL_DLLRDY_SHIFT) & \
+	  PHYCTRL_DLLRDY_MASK) == PHYCTRL_DLLRDY_DONE)
 
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
@@ -93,7 +96,6 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	unsigned int dllrdy;
 	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long rate;
-	unsigned long timeout;
 	int ret;
 
 	/*
@@ -217,28 +219,15 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	 * NOTE: There appear to be corner cases where the DLL seems to take
 	 * extra long to lock for reasons that aren't understood.  In some
 	 * extreme cases we've seen it take up to over 10ms (!).  We'll be
-	 * generous and give it 50ms.  We still busy wait here because:
-	 * - In most cases it should be super fast.
-	 * - This is not called lots during normal operation so it shouldn't
-	 *   be a power or performance problem to busy wait.  We expect it
-	 *   only at boot / resume.  In both cases, eMMC is probably on the
-	 *   critical path so busy waiting a little extra time should be OK.
+	 * generous and give it 50ms.
 	 */
-	timeout = jiffies + msecs_to_jiffies(50);
-	do {
-		udelay(1);
-
-		regmap_read(rk_phy->reg_base,
-			rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-			&dllrdy);
-		dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
-		if (dllrdy == PHYCTRL_DLLRDY_DONE)
-			break;
-	} while (!time_after(jiffies, timeout));
-
-	if (dllrdy != PHYCTRL_DLLRDY_DONE) {
-		pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n");
-		return -ETIMEDOUT;
+	ret = regmap_read_poll_timeout(rk_phy->reg_base,
+				       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+				       dllrdy, PHYCTRL_IS_DLLRDY(dllrdy),
+				       1, 50 * USEC_PER_MSEC);
+	if (ret) {
+		pr_err("%s: dllrdy timeout. ret=%d\n", __func__, ret);
+		return ret;
 	}
 
 	return 0;
-- 
2.7.4

^ permalink raw reply related

* consolidate direct dma mapping V3
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel

Almost every architecture supports a direct dma mapping implementation,
where no iommu is used and the device dma address is a 1:1 mapping to
the physical address or has a simple linear offset.  Currently the
code for this implementation is most duplicated over the architectures,
and the duplicated again in the swiotlb code, and then duplicated again
for special cases like the x86 memory encryption DMA ops.

This series takes the existing very simple dma-noop dma mapping
implementation, enhances it with all the x86 features and quirks, and
creates a common set of architecture hooks for it and the swiotlb code.

It then switches a number of architectures to this generic
direct map implemention.

Note that for now this only handles architectures that do cache coherent
DMA, but a similar consolidation for non-coherent architectures is in the
work for later merge windows.

A git tree is also available:

   git://git.infradead.org/users/hch/misc.git dma-direct.3

Gitweb:

   http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/dma-direct.3

Changes since V1:
 - fixed a few patch description typos
 - fixed a few printk formats
 - fixed an off by one in dma_coherent_ok
 - add a few Reviewed-by/Acked-by tags.
 - moved the swiotlb consolidation to a new series
 - dropped a few patches for now to not overwhelem the x86
   maintainers.  They will be resubmitted in the next merge window

^ permalink raw reply

* [PATCH 01/33] alpha: mark jensen as broken
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

CONFIG_ALPHA_JENSEN has failed to compile since commit 6aca0503
("alpha/dma: use common noop dma ops"), so mark it as broken.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/alpha/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index b31b974a03cb..e96adcbcab41 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -209,6 +209,7 @@ config ALPHA_EIGER
 
 config ALPHA_JENSEN
 	bool "Jensen"
+	depends on BROKEN
 	help
 	  DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
 	  of the first-generation Alpha systems. A number of these systems
-- 
2.14.2

^ permalink raw reply related

* [PATCH 02/33] hexagon: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/hexagon/include/asm/io.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index 66f5e9a61efc..9e8621d94ee9 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -330,8 +330,6 @@ static inline void outsl(unsigned long port, const void *buffer, int count)
 	}
 }
 
-#define flush_write_buffers() do { } while (0)
-
 #endif /* __KERNEL__ */
 
 #endif
-- 
2.14.2

^ permalink raw reply related

* [PATCH 03/33] m32r: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/m32r/include/asm/io.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h
index 1b653bb16f9a..a4272d8f0d9c 100644
--- a/arch/m32r/include/asm/io.h
+++ b/arch/m32r/include/asm/io.h
@@ -191,8 +191,6 @@ static inline void _writel(unsigned long l, unsigned long addr)
 
 #define mmiowb()
 
-#define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
-
 static inline void
 memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
-- 
2.14.2

^ permalink raw reply related

* [PATCH 04/33] powerpc: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/powerpc/include/asm/dma-mapping.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 5a6cbe11db6f..592c7f418aa0 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -107,9 +107,6 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
 		dev->archdata.dma_offset = off;
 }
 
-/* this will be removed soon */
-#define flush_write_buffers()
-
 #define HAVE_ARCH_DMA_SET_MASK 1
 extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
-- 
2.14.2

^ permalink raw reply related

* [PATCH 05/33] arc: remove CONFIG_ARC_PLAT_NEEDS_PHYS_TO_DMA
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

We always use the stub definitions, so remove the unused other code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/Kconfig                   |  3 ---
 arch/arc/include/asm/dma-mapping.h |  7 -------
 arch/arc/mm/dma.c                  | 14 +++++++-------
 3 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 9d5fd00d9e91..f3a80cf164cc 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -463,9 +463,6 @@ config ARCH_PHYS_ADDR_T_64BIT
 config ARCH_DMA_ADDR_T_64BIT
 	bool
 
-config ARC_PLAT_NEEDS_PHYS_TO_DMA
-	bool
-
 config ARC_KVADDR_SIZE
 	int "Kernel Virtual Address Space size (MB)"
 	range 0 512
diff --git a/arch/arc/include/asm/dma-mapping.h b/arch/arc/include/asm/dma-mapping.h
index 94285031c4fb..7a16824bfe98 100644
--- a/arch/arc/include/asm/dma-mapping.h
+++ b/arch/arc/include/asm/dma-mapping.h
@@ -11,13 +11,6 @@
 #ifndef ASM_ARC_DMA_MAPPING_H
 #define ASM_ARC_DMA_MAPPING_H
 
-#ifndef CONFIG_ARC_PLAT_NEEDS_PHYS_TO_DMA
-#define plat_dma_to_phys(dev, dma_handle) ((phys_addr_t)(dma_handle))
-#define plat_phys_to_dma(dev, paddr) ((dma_addr_t)(paddr))
-#else
-#include <plat/dma.h>
-#endif
-
 extern const struct dma_map_ops arc_dma_ops;
 
 static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index e9d93604ad0f..1dcc404b5aec 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -60,7 +60,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
 	/* This is linear addr (0x8000_0000 based) */
 	paddr = page_to_phys(page);
 
-	*dma_handle = plat_phys_to_dma(dev, paddr);
+	*dma_handle = paddr;
 
 	/* This is kernel Virtual address (0x7000_0000 based) */
 	if (need_kvaddr) {
@@ -92,7 +92,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
 static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
 		dma_addr_t dma_handle, unsigned long attrs)
 {
-	phys_addr_t paddr = plat_dma_to_phys(dev, dma_handle);
+	phys_addr_t paddr = dma_handle;
 	struct page *page = virt_to_page(paddr);
 	int is_non_coh = 1;
 
@@ -111,7 +111,7 @@ static int arc_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 {
 	unsigned long user_count = vma_pages(vma);
 	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	unsigned long pfn = __phys_to_pfn(plat_dma_to_phys(dev, dma_addr));
+	unsigned long pfn = __phys_to_pfn(dma_addr);
 	unsigned long off = vma->vm_pgoff;
 	int ret = -ENXIO;
 
@@ -175,7 +175,7 @@ static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page,
 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		_dma_cache_sync(paddr, size, dir);
 
-	return plat_phys_to_dma(dev, paddr);
+	return paddr;
 }
 
 /*
@@ -190,7 +190,7 @@ static void arc_dma_unmap_page(struct device *dev, dma_addr_t handle,
 			       size_t size, enum dma_data_direction dir,
 			       unsigned long attrs)
 {
-	phys_addr_t paddr = plat_dma_to_phys(dev, handle);
+	phys_addr_t paddr = handle;
 
 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		_dma_cache_sync(paddr, size, dir);
@@ -224,13 +224,13 @@ static void arc_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 static void arc_dma_sync_single_for_cpu(struct device *dev,
 		dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
 {
-	_dma_cache_sync(plat_dma_to_phys(dev, dma_handle), size, DMA_FROM_DEVICE);
+	_dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE);
 }
 
 static void arc_dma_sync_single_for_device(struct device *dev,
 		dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
 {
-	_dma_cache_sync(plat_dma_to_phys(dev, dma_handle), size, DMA_TO_DEVICE);
+	_dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
 }
 
 static void arc_dma_sync_sg_for_cpu(struct device *dev,
-- 
2.14.2

^ permalink raw reply related

* [PATCH 06/33] m32r: remove the unused dma_capable helper
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/m32r/include/asm/dma-mapping.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/m32r/include/asm/dma-mapping.h b/arch/m32r/include/asm/dma-mapping.h
index 336ffe60814b..8967fb659691 100644
--- a/arch/m32r/include/asm/dma-mapping.h
+++ b/arch/m32r/include/asm/dma-mapping.h
@@ -14,11 +14,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &dma_noop_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return false;
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 #endif /* _ASM_M32R_DMA_MAPPING_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 07/33] riscv: remove the unused dma_capable helper
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/riscv/include/asm/dma-mapping.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/riscv/include/asm/dma-mapping.h b/arch/riscv/include/asm/dma-mapping.h
index 3eec1000196d..73849e2cc761 100644
--- a/arch/riscv/include/asm/dma-mapping.h
+++ b/arch/riscv/include/asm/dma-mapping.h
@@ -27,12 +27,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &dma_noop_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return false;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 #endif	/* __ASM_RISCV_DMA_MAPPING_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 08/33] s390: remove the unused dma_capable helper
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/s390/include/asm/dma-mapping.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/s390/include/asm/dma-mapping.h b/arch/s390/include/asm/dma-mapping.h
index eaf490f9c5bc..2ec7240c1ada 100644
--- a/arch/s390/include/asm/dma-mapping.h
+++ b/arch/s390/include/asm/dma-mapping.h
@@ -16,11 +16,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &dma_noop_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return false;
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 #endif /* _ASM_S390_DMA_MAPPING_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 09/33] dma-mapping: take dma_pfn_offset into account in dma_max_pfn
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

This makes sure the generic version can be used with architectures /
devices that have a DMA offset in the direct mapping.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 include/linux/dma-mapping.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 81ed9b2d84dc..d84951865be7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -692,7 +692,7 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
 #ifndef dma_max_pfn
 static inline unsigned long dma_max_pfn(struct device *dev)
 {
-	return *dev->dma_mask >> PAGE_SHIFT;
+	return (*dev->dma_mask >> PAGE_SHIFT) + dev->dma_pfn_offset;
 }
 #endif
 
-- 
2.14.2

^ permalink raw reply related

* [PATCH 10/33] arm64: don't override dma_max_pfn
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

The generic version now takes dma_pfn_offset into account, so there is no
more need for an architecture override.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/arm64/include/asm/dma-mapping.h | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index 0df756b24863..eada887a93bf 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -76,14 +76,5 @@ static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
 
-/* Override for dma_max_pfn() */
-static inline unsigned long dma_max_pfn(struct device *dev)
-{
-	dma_addr_t dma_max = (dma_addr_t)*dev->dma_mask;
-
-	return (ulong)dma_to_phys(dev, dma_max) >> PAGE_SHIFT;
-}
-#define dma_max_pfn(dev) dma_max_pfn(dev)
-
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_DMA_MAPPING_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

phys_to_dma, dma_to_phys and dma_capable are helpers published by
architecture code for use of swiotlb and xen-swiotlb only.  Drivers are
not supposed to use these directly, but use the DMA API instead.

Move these to a new asm/dma-direct.h helper, included by a
linux/dma-direct.h wrapper that provides the default linear mapping
unless the architecture wants to override it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 MAINTAINERS                                        |  1 +
 arch/Kconfig                                       |  4 +++
 arch/arm/Kconfig                                   |  1 +
 arch/arm/include/asm/dma-direct.h                  | 36 ++++++++++++++++++++++
 arch/arm/include/asm/dma-mapping.h                 | 31 -------------------
 arch/arm64/include/asm/dma-mapping.h               | 22 -------------
 arch/arm64/mm/dma-mapping.c                        |  2 +-
 arch/ia64/include/asm/dma-mapping.h                | 18 -----------
 arch/mips/Kconfig                                  |  2 ++
 arch/mips/include/asm/dma-direct.h                 |  1 +
 arch/mips/include/asm/dma-mapping.h                |  8 -----
 .../include/asm/mach-cavium-octeon/dma-coherence.h |  8 +++++
 arch/mips/include/asm/mach-generic/dma-coherence.h | 12 --------
 .../include/asm/mach-loongson64/dma-coherence.h    |  8 +++++
 arch/powerpc/Kconfig                               |  1 +
 arch/powerpc/include/asm/dma-direct.h              | 29 +++++++++++++++++
 arch/powerpc/include/asm/dma-mapping.h             | 25 ---------------
 arch/tile/include/asm/dma-mapping.h                | 18 -----------
 arch/unicore32/include/asm/dma-mapping.h           | 18 -----------
 arch/x86/Kconfig                                   |  1 +
 arch/x86/include/asm/dma-direct.h                  | 30 ++++++++++++++++++
 arch/x86/include/asm/dma-mapping.h                 | 26 ----------------
 arch/x86/kernel/amd_gart_64.c                      |  1 +
 arch/x86/kernel/pci-dma.c                          |  2 +-
 arch/x86/kernel/pci-nommu.c                        |  2 +-
 arch/x86/kernel/pci-swiotlb.c                      |  2 +-
 arch/x86/mm/mem_encrypt.c                          |  2 +-
 arch/x86/pci/sta2x11-fixup.c                       |  1 +
 arch/xtensa/include/asm/dma-mapping.h              | 10 ------
 drivers/crypto/marvell/cesa.c                      |  1 +
 drivers/mtd/nand/qcom_nandc.c                      |  1 +
 drivers/xen/swiotlb-xen.c                          |  2 +-
 include/linux/dma-direct.h                         | 32 +++++++++++++++++++
 lib/swiotlb.c                                      |  2 +-
 34 files changed, 165 insertions(+), 195 deletions(-)
 create mode 100644 arch/arm/include/asm/dma-direct.h
 create mode 100644 arch/mips/include/asm/dma-direct.h
 create mode 100644 arch/powerpc/include/asm/dma-direct.h
 create mode 100644 arch/x86/include/asm/dma-direct.h
 create mode 100644 include/linux/dma-direct.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 95c3fa1f520f..d2cfdcce1db5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4338,6 +4338,7 @@ F:	lib/dma-noop.c
 F:	lib/dma-virt.c
 F:	drivers/base/dma-mapping.c
 F:	drivers/base/dma-coherent.c
+F:	include/linux/dma-direct.h
 F:	include/linux/dma-mapping.h
 
 DME1737 HARDWARE MONITOR DRIVER
diff --git a/arch/Kconfig b/arch/Kconfig
index 400b9e1b2f27..3edf118ad777 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -938,6 +938,10 @@ config STRICT_MODULE_RWX
 	  and non-text memory will be made non-executable. This provides
 	  protection against certain security exploits (e.g. writing to text)
 
+# select if the architecture provides an asm/dma-direct.h header
+config ARCH_HAS_PHYS_TO_DMA
+	bool
+
 config ARCH_HAS_REFCOUNT
 	bool
 	help
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 51c8df561077..00d889a37965 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -8,6 +8,7 @@ config ARM
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_SET_MEMORY
+	select ARCH_HAS_PHYS_TO_DMA
 	select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
 	select ARCH_HAS_STRICT_MODULE_RWX if MMU
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
diff --git a/arch/arm/include/asm/dma-direct.h b/arch/arm/include/asm/dma-direct.h
new file mode 100644
index 000000000000..5b0a8a421894
--- /dev/null
+++ b/arch/arm/include/asm/dma-direct.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASM_ARM_DMA_DIRECT_H
+#define ASM_ARM_DMA_DIRECT_H 1
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	unsigned int offset = paddr & ~PAGE_MASK;
+	return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+{
+	unsigned int offset = dev_addr & ~PAGE_MASK;
+	return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset;
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	u64 limit, mask;
+
+	if (!dev->dma_mask)
+		return 0;
+
+	mask = *dev->dma_mask;
+
+	limit = (mask + 1) & ~mask;
+	if (limit && size > limit)
+		return 0;
+
+	if ((addr | (addr + size - 1)) & ~mask)
+		return 0;
+
+	return 1;
+}
+
+#endif /* ASM_ARM_DMA_DIRECT_H */
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index daf837423a76..5fb1b7fbdfbe 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -109,37 +109,6 @@ static inline bool is_device_dma_coherent(struct device *dev)
 	return dev->archdata.dma_coherent;
 }
 
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	unsigned int offset = paddr & ~PAGE_MASK;
-	return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
-{
-	unsigned int offset = dev_addr & ~PAGE_MASK;
-	return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset;
-}
-
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	u64 limit, mask;
-
-	if (!dev->dma_mask)
-		return 0;
-
-	mask = *dev->dma_mask;
-
-	limit = (mask + 1) & ~mask;
-	if (limit && size > limit)
-		return 0;
-
-	if ((addr | (addr + size - 1)) & ~mask)
-		return 0;
-
-	return 1;
-}
-
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
 /**
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index eada887a93bf..400fa67d3b5a 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -50,28 +50,6 @@ static inline bool is_device_dma_coherent(struct device *dev)
 	return dev->archdata.dma_coherent;
 }
 
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	dma_addr_t dev_addr = (dma_addr_t)paddr;
-
-	return dev_addr - ((dma_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
-{
-	phys_addr_t paddr = (phys_addr_t)dev_addr;
-
-	return paddr + ((phys_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
-}
-
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return false;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index b45c5bcaeccb..f3a637b98487 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -24,7 +24,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/genalloc.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/dma-contiguous.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index c1bab526a046..eabee56d995c 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -27,22 +27,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return platform_dma_get_ops(NULL);
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return 0;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return paddr;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return daddr;
-}
-
 #endif /* _ASM_IA64_DMA_MAPPING_H */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 350a990fc719..4b0c26b2e9b7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -429,6 +429,7 @@ config MACH_LOONGSON32
 
 config MACH_LOONGSON64
 	bool "Loongson-2/3 family of machines"
+	select ARCH_HAS_PHYS_TO_DMA
 	select SYS_SUPPORTS_ZBOOT
 	help
 	  This enables the support of Loongson-2/3 family of machines.
@@ -877,6 +878,7 @@ config MIKROTIK_RB532
 config CAVIUM_OCTEON_SOC
 	bool "Cavium Networks Octeon SoC based boards"
 	select CEVT_R4K
+	select ARCH_HAS_PHYS_TO_DMA
 	select ARCH_PHYS_ADDR_T_64BIT
 	select DMA_COHERENT
 	select SYS_SUPPORTS_64BIT_KERNEL
diff --git a/arch/mips/include/asm/dma-direct.h b/arch/mips/include/asm/dma-direct.h
new file mode 100644
index 000000000000..f32f15530aba
--- /dev/null
+++ b/arch/mips/include/asm/dma-direct.h
@@ -0,0 +1 @@
+#include <asm/dma-coherence.h>
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 0d9418d264f9..676c14cfc580 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -17,14 +17,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return mips_dma_map_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return false;
-
-	return addr + size <= *dev->dma_mask;
-}
-
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
 #define arch_setup_dma_ops arch_setup_dma_ops
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 9110988b92a1..f00833acb626 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -61,6 +61,14 @@ static inline void plat_post_dma_flush(struct device *dev)
 {
 }
 
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return false;
+
+	return addr + size <= *dev->dma_mask;
+}
+
 dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
 phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
 
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 61addb1677e9..8ad7a40ca786 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -70,16 +70,4 @@ static inline void plat_post_dma_flush(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_SWIOTLB
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return paddr;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return daddr;
-}
-#endif
-
 #endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-loongson64/dma-coherence.h b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
index 1602a9e9e8c2..5cfda8f893e9 100644
--- a/arch/mips/include/asm/mach-loongson64/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
@@ -17,6 +17,14 @@
 
 struct device;
 
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return false;
+
+	return addr + size <= *dev->dma_mask;
+}
+
 extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
 extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
 static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c51e6ce42e7a..887285eb684a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -139,6 +139,7 @@ config PPC
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_GCOV_PROFILE_ALL
+	select ARCH_HAS_PHYS_TO_DMA
 	select ARCH_HAS_PMEM_API                if PPC64
 	select ARCH_HAS_SCALED_CPUTIME		if VIRT_CPU_ACCOUNTING_NATIVE
 	select ARCH_HAS_SG_CHAIN
diff --git a/arch/powerpc/include/asm/dma-direct.h b/arch/powerpc/include/asm/dma-direct.h
new file mode 100644
index 000000000000..a5b59c765426
--- /dev/null
+++ b/arch/powerpc/include/asm/dma-direct.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASM_POWERPC_DMA_DIRECT_H
+#define ASM_POWERPC_DMA_DIRECT_H 1
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+#ifdef CONFIG_SWIOTLB
+	struct dev_archdata *sd = &dev->archdata;
+
+	if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
+		return false;
+#endif
+
+	if (!dev->dma_mask)
+		return false;
+
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return paddr + get_dma_offset(dev);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return daddr - get_dma_offset(dev);
+}
+#endif /* ASM_POWERPC_DMA_DIRECT_H */
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 592c7f418aa0..f6ab51205a85 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -112,31 +112,6 @@ extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
 extern u64 __dma_get_required_mask(struct device *dev);
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-#ifdef CONFIG_SWIOTLB
-	struct dev_archdata *sd = &dev->archdata;
-
-	if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
-		return false;
-#endif
-
-	if (!dev->dma_mask)
-		return false;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return paddr + get_dma_offset(dev);
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return daddr - get_dma_offset(dev);
-}
-
 #define ARCH_HAS_DMA_MMAP_COHERENT
 
 #endif /* __KERNEL__ */
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index 97ad62878290..75b8aaa4e70b 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -44,26 +44,8 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
 	dev->archdata.dma_offset = off;
 }
 
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return paddr;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return daddr;
-}
-
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return 0;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 #define HAVE_ARCH_DMA_SET_MASK 1
 int dma_set_mask(struct device *dev, u64 mask);
 
diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
index ac608c2f6af6..5cb250bf2d8c 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -25,24 +25,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &swiotlb_dma_map_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (dev && dev->dma_mask)
-		return addr + size - 1 <= *dev->dma_mask;
-
-	return 1;
-}
-
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return paddr;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return daddr;
-}
-
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
 #endif /* __KERNEL__ */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d4fc98c50378..f6f4328103c0 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -54,6 +54,7 @@ config X86
 	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_HAS_KCOV			if X86_64
+	select ARCH_HAS_PHYS_TO_DMA
 	select ARCH_HAS_PMEM_API		if X86_64
 	# Causing hangs/crashes, see the commit that added this change for details.
 	select ARCH_HAS_REFCOUNT
diff --git a/arch/x86/include/asm/dma-direct.h b/arch/x86/include/asm/dma-direct.h
new file mode 100644
index 000000000000..1295bc622ebe
--- /dev/null
+++ b/arch/x86/include/asm/dma-direct.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASM_X86_DMA_DIRECT_H
+#define ASM_X86_DMA_DIRECT_H 1
+
+#include <linux/mem_encrypt.h>
+
+#ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */
+bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
+dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
+phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+#else
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return __sme_set(paddr);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return __sme_clr(daddr);
+}
+#endif /* CONFIG_X86_DMA_REMAP */
+#endif /* ASM_X86_DMA_DIRECT_H */
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 0350d99bb8fd..dfdc9357a349 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,7 +12,6 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
-#include <linux/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -42,31 +41,6 @@ extern void dma_generic_free_coherent(struct device *dev, size_t size,
 				      void *vaddr, dma_addr_t dma_addr,
 				      unsigned long attrs);
 
-#ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */
-extern bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
-extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
-extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
-#else
-
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return 0;
-
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return __sme_set(paddr);
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return __sme_clr(daddr);
-}
-#endif /* CONFIG_X86_DMA_REMAP */
-
 static inline unsigned long dma_alloc_coherent_mask(struct device *dev,
 						    gfp_t gfp)
 {
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index cc0e8bc0ea3f..ecd486cb06ab 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/gfp.h>
 #include <linux/atomic.h>
+#include <linux/dma-direct.h>
 #include <asm/mtrr.h>
 #include <asm/pgtable.h>
 #include <asm/proto.h>
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 599d7462eccc..8439e6de6156 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/dma-debug.h>
 #include <linux/dmar.h>
 #include <linux/export.h>
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index b0caae27e1b7..618285e475c6 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Fallback functions when the main IOMMU code is not compiled in. This
    code is roughly equivalent to i386. */
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/gfp.h>
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 53bd05ea90d8..9d3e35c33d94 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -6,7 +6,7 @@
 #include <linux/init.h>
 #include <linux/swiotlb.h>
 #include <linux/bootmem.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/mem_encrypt.h>
 
 #include <asm/iommu.h>
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 391b13402e40..09532c935da0 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -15,7 +15,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/swiotlb.h>
 #include <linux/mem_encrypt.h>
 
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
index 53d600217973..75577c1490c4 100644
--- a/arch/x86/pci/sta2x11-fixup.c
+++ b/arch/x86/pci/sta2x11-fixup.c
@@ -26,6 +26,7 @@
 #include <linux/pci_ids.h>
 #include <linux/export.h>
 #include <linux/list.h>
+#include <linux/dma-direct.h>
 #include <asm/iommu.h>
 
 #define STA2X11_SWIOTLB_SIZE (4*1024*1024)
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index 153bf2370988..44098800dad7 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -23,14 +23,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &xtensa_dma_map_ops;
 }
 
-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-	return (dma_addr_t)paddr;
-}
-
-static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
-{
-	return (phys_addr_t)daddr;
-}
-
 #endif	/* _XTENSA_DMA_MAPPING_H */
diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index 293832488cc9..3a0c40081ffb 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -24,6 +24,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/dma-direct.h> /* XXX: drivers shall never use this directly! */
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 2656c1ac5646..411cdfd12a85 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -23,6 +23,7 @@
 #include <linux/of_device.h>
 #include <linux/delay.h>
 #include <linux/dma/qcom_bam_dma.h>
+#include <linux/dma-direct.h> /* XXX: drivers shall never use this directly! */
 
 /* NANDc reg offsets */
 #define	NAND_FLASH_CMD			0x00
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 82fc54f8eb77..5bb72d3f8337 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -36,7 +36,7 @@
 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
 
 #include <linux/bootmem.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/export.h>
 #include <xen/swiotlb-xen.h>
 #include <xen/page.h>
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
new file mode 100644
index 000000000000..2cc1b6558944
--- /dev/null
+++ b/include/linux/dma-direct.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_DMA_DIRECT_H
+#define _LINUX_DMA_DIRECT_H 1
+
+#include <linux/dma-mapping.h>
+
+#ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA
+#include <asm/dma-direct.h>
+#else
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	dma_addr_t dev_addr = (dma_addr_t)paddr;
+
+	return dev_addr - ((dma_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+{
+	phys_addr_t paddr = (phys_addr_t)dev_addr;
+
+	return paddr + ((phys_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return false;
+
+	return addr + size - 1 <= *dev->dma_mask;
+}
+#endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+#endif /* _LINUX_DMA_DIRECT_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index cea19aaf303c..6583f3512386 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -18,7 +18,7 @@
  */
 
 #include <linux/cache.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
-- 
2.14.2

^ permalink raw reply related

* [PATCH 12/33] dma-mapping: move dma_mark_clean to dma-direct.h
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

And unlike the other helpers we don't require a <asm/dma-direct.h> as
this helper is a special case for ia64 only, and this keeps it as
simple as possible.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/arm/include/asm/dma-mapping.h       | 2 --
 arch/arm64/include/asm/dma-mapping.h     | 4 ----
 arch/ia64/Kconfig                        | 1 +
 arch/ia64/include/asm/dma.h              | 2 --
 arch/mips/include/asm/dma-mapping.h      | 2 --
 arch/powerpc/include/asm/swiotlb.h       | 2 --
 arch/tile/include/asm/dma-mapping.h      | 2 --
 arch/unicore32/include/asm/dma-mapping.h | 2 --
 arch/x86/include/asm/swiotlb.h           | 2 --
 include/linux/dma-direct.h               | 9 +++++++++
 10 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 5fb1b7fbdfbe..e5d9020c9ee1 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -109,8 +109,6 @@ static inline bool is_device_dma_coherent(struct device *dev)
 	return dev->archdata.dma_coherent;
 }
 
-static inline void dma_mark_clean(void *addr, size_t size) { }
-
 /**
  * arm_dma_alloc - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index 400fa67d3b5a..b7847eb8a7bb 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -50,9 +50,5 @@ static inline bool is_device_dma_coherent(struct device *dev)
 	return dev->archdata.dma_coherent;
 }
 
-static inline void dma_mark_clean(void *addr, size_t size)
-{
-}
-
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_DMA_MAPPING_H */
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 49583c5a5d44..4d18fca885ee 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -33,6 +33,7 @@ config IA64
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_VIRT_CPU_ACCOUNTING
+	select ARCH_HAS_DMA_MARK_CLEAN
 	select ARCH_HAS_SG_CHAIN
 	select VIRT_TO_BUS
 	select ARCH_DISCARD_MEMBLOCK
diff --git a/arch/ia64/include/asm/dma.h b/arch/ia64/include/asm/dma.h
index 186850eec934..23604d6a2cb2 100644
--- a/arch/ia64/include/asm/dma.h
+++ b/arch/ia64/include/asm/dma.h
@@ -20,6 +20,4 @@ extern unsigned long MAX_DMA_ADDRESS;
 
 #define free_dma(x)
 
-void dma_mark_clean(void *addr, size_t size);
-
 #endif /* _ASM_IA64_DMA_H */
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 676c14cfc580..886e75a383f2 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -17,8 +17,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return mips_dma_map_ops;
 }
 
-static inline void dma_mark_clean(void *addr, size_t size) {}
-
 #define arch_setup_dma_ops arch_setup_dma_ops
 static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base,
 				      u64 size, const struct iommu_ops *iommu,
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 01d45a5fd00b..9341ee804d19 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -15,8 +15,6 @@
 
 extern const struct dma_map_ops swiotlb_dma_ops;
 
-static inline void dma_mark_clean(void *addr, size_t size) {}
-
 extern unsigned int ppc_swiotlb_enable;
 int __init swiotlb_setup_bus_notifier(void);
 
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index 75b8aaa4e70b..d25fce101fc0 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -44,8 +44,6 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
 	dev->archdata.dma_offset = off;
 }
 
-static inline void dma_mark_clean(void *addr, size_t size) {}
-
 #define HAVE_ARCH_DMA_SET_MASK 1
 int dma_set_mask(struct device *dev, u64 mask);
 
diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
index 5cb250bf2d8c..f2bfec273aa7 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -25,7 +25,5 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return &swiotlb_dma_map_ops;
 }
 
-static inline void dma_mark_clean(void *addr, size_t size) {}
-
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index bdf9aed40403..1c6a6cb230ff 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -28,8 +28,6 @@ static inline void pci_swiotlb_late_init(void)
 }
 #endif
 
-static inline void dma_mark_clean(void *addr, size_t size) {}
-
 extern void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 					dma_addr_t *dma_handle, gfp_t flags,
 					unsigned long attrs);
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 2cc1b6558944..10e924b7cba7 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -29,4 +29,13 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 	return addr + size - 1 <= *dev->dma_mask;
 }
 #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+
+#ifdef CONFIG_ARCH_HAS_DMA_MARK_CLEAN
+void dma_mark_clean(void *addr, size_t size);
+#else
+static inline void dma_mark_clean(void *addr, size_t size)
+{
+}
+#endif /* CONFIG_ARCH_HAS_DMA_MARK_CLEAN */
+
 #endif /* _LINUX_DMA_DIRECT_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 13/33] hexagon: use the generic dma_capable helper
From: Christoph Hellwig @ 2018-01-10  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Richard Kuo <rkuo@codeaurora.org>
---
 arch/hexagon/include/asm/dma-mapping.h | 7 -------
 arch/hexagon/kernel/dma.c              | 1 +
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
index 5208de242e79..263f6acbfb0f 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -37,11 +37,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 	return dma_ops;
 }
 
-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
-{
-	if (!dev->dma_mask)
-		return 0;
-	return addr + size - 1 <= *dev->dma_mask;
-}
-
 #endif
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 546792d176a4..ad8347c29dcf 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
 #include <linux/bootmem.h>
 #include <linux/genalloc.h>
 #include <asm/dma-mapping.h>
-- 
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