Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 7/7] arm64: defconfig: update config for Rockchip PCIe
From: Shawn Lin @ 2018-05-09  1:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525828278-69800-1-git-send-email-shawn.lin@rock-chips.com>

Now Rockchip PCIe drivers could support both of RC mode and EP
mode, so we need rename the config name. This patch updates
defconfig to reflect the fact that we want to build Rockchip PCIe
controller as RC mode, into a module as before.

Cc: linux-arm-kernel at lists.infradead.org
Cc: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None

 arch/arm64/configs/defconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1d3b406..8fd8bae 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -78,7 +78,8 @@ CONFIG_PCIE_ARMADA_8K=y
 CONFIG_PCI_AARDVARK=y
 CONFIG_PCI_TEGRA=y
 CONFIG_PCIE_RCAR=y
-CONFIG_PCIE_ROCKCHIP=m
+CONFIG_PCIE_ROCKCHIP=y
+CONFIG_PCIE_ROCKCHIP_HOST=m
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCI_XGENE=y
 CONFIG_PCI_HOST_THUNDER_PEM=y
-- 
1.9.1

^ permalink raw reply related

* Incoming sms problem on Motorola Droid 4
From: Tony Lindgren @ 2018-05-09  1:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508215102.GA5253@amd>

* Pavel Machek <pavel@ucw.cz> [180508 21:53]:
> Hi!
> 
> I have problems with incoming SMS. ofono tries to use +CNMI=1,2,2,1,0
> 
> > AT+CNMI=?
> < +CNMI: (0,1,2),(0,1,2,3),(0,2),(0,1,2),(0,1)
> < OK
> ofonod[3070]: drivers/atmodem/sms.c:build_cnmi_string()
> ofonod[3070]: drivers/atmodem/sms.c:construct_ack_pdu()
> > AT+CNMI=1,2,2,1,0
> < OK
> ofonod[3070]: src/network.c:__ofono_netreg_add_status_watch() 0x5bbbf0
> 
> ... unfortunately, with that configuration no messages are comming to
> ofono and the other phone sees them as "delievery failed".
> 
> I had some luck with unicsy_demo using AT+CNMI=1,2 with text mode (not
> PDU) messages. That works well enough for me.
> 
> Unfortunately, if I force ofono to pass "AT+CNMI=1,2", it does not
> work well, either.
> 
> Any ideas how to debug this / what to try?

Well you can try to see what Android is doing for SMS with:

# echo 0x7fffffff > /sys/module/ts27010mux/parameters/debug_level
# dmesg | grep ts27010 | grep AT

To send SMS, looks like Android RIL first does:

2 AT+CMGS=327 where 327 seems to be the size of the whatever
encoded message. Then the next packet to dlci 2 contains the
encoded message that is of size 327.

When receiving, mdm6600 sends these on dlci 1:
~+WAKEUP
~+WAKEUP
~+WAKEUP

Then mdm6600 sends this on dlci 9:
~+CMT=372

And that's probably the incoming SMS size. But I don't see
anything for what actually reads the incoming SMS.

Regards,

Tony

^ permalink raw reply

* [PATCH 1/2] perf cs-etm: Support unknown_thread in cs_etm_auxtrace
From: Leo Yan @ 2018-05-09  0:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANLsYky4QatoCv_4k1r8eb4Rjugx9g2YZLG1dtHKJy9AsHtCSg@mail.gmail.com>

On Tue, May 08, 2018 at 11:01:30AM -0600, Mathieu Poirier wrote:
> On 3 May 2018 at 09:18, Leo Yan <leo.yan@linaro.org> wrote:
> > CoreSight doesn't allocate thread structure for unknown_thread in etm
> > auxtrace, so unknown_thread is NULL pointer.  If the perf data doesn't
> > contain valid tid and then cs_etm__mem_access() uses unknown_thread
> > instead as thread handler, this results in segmentation fault when
> > thread__find_addr_map() accesses thread handler.
> >
> > This commit creates new thread data which is used by unknown_thread, so
> > CoreSight tracing can roll back to use unknown_thread if perf data
> > doesn't include valid thread info.  This commit also releases thread
> > data for initialization failure case and for normal auxtrace free flow.
> >
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> >  tools/perf/util/cs-etm.c | 25 +++++++++++++++++++++++--
> >  1 file changed, 23 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> > index 6533b1a..417302c 100644
> > --- a/tools/perf/util/cs-etm.c
> > +++ b/tools/perf/util/cs-etm.c
> > @@ -239,6 +239,7 @@ static void cs_etm__free(struct perf_session *session)
> >         for (i = 0; i < aux->num_cpu; i++)
> >                 zfree(&aux->metadata[i]);
> >
> > +       thread__zput(aux->unknown_thread);
> >         zfree(&aux->metadata);
> >         zfree(&aux);
> >  }
> > @@ -266,6 +267,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
> >         if (!thread) {
> >                 if (cpumode != PERF_RECORD_MISC_KERNEL)
> >                         return -EINVAL;
> > +
> 
> Extra line, please remove.
> 
> With this change:
> 
> Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org>

Thanks for reviewing, Mathieu.  Will spin new patches and send out.

[...]

Thanks,
Leo Yan

^ permalink raw reply

* [PATCH] drivers/perf: arm-ccn: stop spamming dmesg in event_init
From: Kim Phillips @ 2018-05-08 23:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180504104117.8086-1-mark.rutland@arm.com>

On Fri,  4 May 2018 11:41:17 +0100
Mark Rutland <mark.rutland@arm.com> wrote:

[adding Pawel, arm-ccn driver author]

> The ARM CCN PMU driver uses dev_warn() to complain about parameters in
> the user-provided perf_event_attr. This means that under normal
> operation (e.g. a single invocation of the perf tool), dmesg may be
> spammed with multiple messages.

Nothing new there:  perf does that all the time: E.g., a single, basic
x86 invocation causes all this:

[77360.630571] perf: interrupt took too long (2549 > 2500), lowering kernel.perf_event_max_sample_rate to 78250
[77360.630800] perf: interrupt took too long (3492 > 3186), lowering kernel.perf_event_max_sample_rate to 57250
[77360.631045] perf: interrupt took too long (4379 > 4365), lowering kernel.perf_event_max_sample_rate to 45500
[77360.631437] perf: interrupt took too long (5845 > 5473), lowering kernel.perf_event_max_sample_rate to 34000
[77360.631967] perf: interrupt took too long (7736 > 7306), lowering kernel.perf_event_max_sample_rate to 25750
[77360.632520] perf: interrupt took too long (9921 > 9670), lowering kernel.perf_event_max_sample_rate to 20000
[77360.633344] perf: interrupt took too long (12778 > 12401), lowering kernel.perf_event_max_sample_rate to 15500
[77360.634294] perf: interrupt took too long (16030 > 15972), lowering kernel.perf_event_max_sample_rate to 12250
[77360.635587] perf: interrupt took too long (20105 > 20037), lowering kernel.perf_event_max_sample_rate to 9750
[77360.637301] perf: interrupt took too long (25319 > 25131), lowering kernel.perf_event_max_sample_rate to 7750

> Tools may issue multiple syscalls to probe for feature support, and

Why isn't it helpful?  A user can see the tool is trying different
options, and as they are tried, to see which ones are they can do
something about.  Arm-ccn has plenty of h/w specific errors, and users
need to know things like node specific details.

> multiple applications (from multiple users) can attempt to open events
> simultaneously, so this is not very helpful, 

Does running perf on the same PMU h/w against other users even work?
Is it even practical, if they get it to?  In any case, for Arm-ccn,
since it's system-wide PMU h/w, this use-case is completely unrealistic.

> even if a user happens to have access to dmesg.

Again, unrealistic:  If they have access to run arm-ccn, kptrs are
unrestricted, so they have way more access than to just dmesg.

> Worse, this can push important information out of
> the dmesg ring buffer,

Like what, specifically?  People about to run perf do so on a stable
system, for measurement of performance accuracy reasons.   Anyway,
there are logging daemons to help with that, and arm-ccn doesn't emit
*that* many messages such as to even come close to filling the buffer.

> and can significantly slow down syscall fuzzers,
> vastly increasing the time it takes to find critical bugs.

Facilitating first user experience  - esp. for Arm perf - trumps fuzzer
runner convenience any day, in my book.  Fuzzer runners can patch their
kernels prior to running the fuzzers.

> Demote the dev_warn() instances to dev_dbg(), as is the case for all
> other PMU drivers under drivers/perf/. Users who wish to debug PMU event
> initialisation can enable dynamic debug to receive these messages.

After having already debugged things to the point where they find the
problem is the driver's event_init() function?  Then they find they
have to recompile their kernels yet again, with DYNAMIC_DEBUG set?

No, please, this is a definite usability regression for Arm-ccn users.

In fact, are you sure it shouldn't be the other way around?:
{kernel,PMU driver} developers that wish to run fuzzers should disable
warnings using /proc/sys/kernel/printk, or boot with a different
loglevel on the boot command line.  I think our users would appreciate
that more than this patch.

Thanks,

Kim

^ permalink raw reply

* [PATCH v2 27/27] coresight: etm-perf: Add support for ETR backend
From: Mathieu Poirier @ 2018-05-08 22:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525165857-11096-28-git-send-email-suzuki.poulose@arm.com>

On Tue, May 01, 2018 at 10:10:57AM +0100, Suzuki K Poulose wrote:
> Add necessary support for using ETR as a sink in ETM perf tracing.
> We try make the best use of the available modes of buffers to
> try and avoid software double buffering.
> 
> We can use the perf ring buffer for ETR directly if all of the
> conditions below are met :
>  1) ETR is DMA coherent
>  2) perf is used in snapshot mode. In full tracing mode, we cannot
>     guarantee that the ETR will stop before it overwrites the data
>     at the beginning of the trace buffer leading to loss of trace
>     data. (The buffer which is being consumed by the perf is still
>     hidden from the ETR).
>  3) ETR supports save-restore with a scatter-gather mechanism
>     which can use a given set of pages we use the perf ring buffer
>     directly. If we have an in-built TMC ETR Scatter Gather unit,
>     we make use of a circular SG list to restart from a given head.
>     However, we need to align the starting offset to 4K in this case.
>     With CATU and ETR Save restore feature, we don't have to necessarily
>     align the head of the buffer.
> 
> If the ETR doesn't support either of this, we fallback to software
> double buffering.
> 
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> 
> Note: The conditions above need some rethink.
> 
> For (1) : We always sync the buffer for CPU, before we update the
> pointers. So, we should be safe here and should be able to remove
> this condition.
> 
> (2) is a bit more of problem, as the ETR (without SFIFO_2 mode)
> doesn't stop writing out the trace buffer, eventhough we exclude
> the part of the ring buffer currently consumed by perf, leading
> to loss of data. Also, since we don't have an interrupt (without
> SFIFO_2), we can't wake up the userspace reliably to consume
> the data.
> 
> One possible option is to use an hrtimer to wake up the userspace
> early enough, using a low wakeup mark. But that doesn't necessarily
> guarantee that the ETR will not wrap around overwriting the data,
> as we can't modify the ETR pointers, unless we disable it, which
> could again potentially cause data loss in Circular Buffer mode.
> We may still be able to detect if there was a data loss by checking
> how far the userspace has consumed the data.

I thought about timers before but as you point out it comes with a wealth of
problems.  Not having a buffer overflow interrupt is just a HW limitation we
need to live with until something better comes along.

> ---
>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 387 +++++++++++++++++++++++-
>  drivers/hwtracing/coresight/coresight-tmc.h     |   2 +
>  2 files changed, 386 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 8159e84..3e9ba02 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -31,6 +31,32 @@ struct etr_flat_buf {
>  };
>  
>  /*
> + * etr_perf_buffer - Perf buffer used for ETR
> + * @etr_buf		- Actual buffer used by the ETR
> + * @snaphost		- Perf session mode
> + * @head		- handle->head at the beginning of the session.
> + * @nr_pages		- Number of pages in the ring buffer.
> + * @pages		- Pages in the ring buffer.
> + * @flags		- Capabilities of the hardware buffer used in the
> + *			  session. If flags == 0, we use software double
> + *			  buffering.
> + */
> +struct etr_perf_buffer {
> +	struct etr_buf		*etr_buf;
> +	bool			snapshot;
> +	unsigned long		head;
> +	int			nr_pages;
> +	void			**pages;
> +	u32			flags;
> +};
> +
> +/* Convert the perf index to an offset within the ETR buffer */
> +#define PERF_IDX2OFF(idx, buf)	((idx) % ((buf)->nr_pages << PAGE_SHIFT))
> +
> +/* Lower limit for ETR hardware buffer in double buffering mode */
> +#define TMC_ETR_PERF_MIN_BUF_SIZE	SZ_1M
> +
> +/*
>   * The TMC ETR SG has a page size of 4K. The SG table contains pointers
>   * to 4KB buffers. However, the OS may use a PAGE_SIZE different from
>   * 4K (i.e, 16KB or 64KB). This implies that a single OS page could
> @@ -1164,7 +1190,7 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata)
>  		tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset);
>  }
>  
> -static int __maybe_unused
> +static int
>  tmc_restore_etr_buf(struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
>  		    unsigned long r_offset, unsigned long w_offset,
>  		    unsigned long size, u32 status)
> @@ -1415,10 +1441,361 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
>  	return ret;
>  }
>  
> +/*
> + * tmc_etr_setup_perf_buf: Allocate ETR buffer for use by perf. We try to
> + * use perf ring buffer pages for the ETR when we can. In the worst case
> + * we fallback to software double buffering. The size of the hardware buffer
> + * in this case is dependent on the size configured via sysfs, if we can't
> + * match the perf ring buffer size. We scale down the size by half until
> + * it reaches a limit of 1M, beyond which we give up.
> + */
> +static struct etr_perf_buffer *
> +tmc_etr_setup_perf_buf(struct tmc_drvdata *drvdata, int node, int nr_pages,
> +		       void **pages, bool snapshot)
> +{
> +	int i;
> +	struct etr_buf *etr_buf;
> +	struct etr_perf_buffer *etr_perf;
> +	unsigned long size;
> +	unsigned long buf_flags[] = {
> +					ETR_BUF_F_RESTORE_FULL,
> +					ETR_BUF_F_RESTORE_MINIMAL,
> +					0,
> +				    };
> +
> +	etr_perf = kzalloc_node(sizeof(*etr_perf), GFP_KERNEL, node);
> +	if (!etr_perf)
> +		return ERR_PTR(-ENOMEM);
> +
> +	size = nr_pages << PAGE_SHIFT;
> +	/*
> +	 * TODO: We need to refine the following rule.
> +	 *
> +	 * We can use the perf ring buffer for ETR only if it is coherent
> +	 * and used in snapshot mode.
> +	 *
> +	 * The ETR (without SFIFO_2 mode) cannot stop writing when a
> +	 * certain limit is reached, nor can it interrupt driver.
> +	 * We can protect the data which is being consumed by the
> +	 * userspace, by hiding it from the ETR's tables. So, we could
> +	 * potentially loose the trace data only for the current session
> +	 * session if the ETR wraps around.
> +	 */
> +	if (tmc_etr_has_cap(drvdata, TMC_ETR_COHERENT) && snapshot) {
> +		for (i = 0; buf_flags[i]; i++) {
> +			etr_buf = tmc_alloc_etr_buf(drvdata, size,
> +						 buf_flags[i], node, pages)

Indentation

> +			if (!IS_ERR(etr_buf)) {
> +				etr_perf->flags = buf_flags[i];
> +				goto done;
> +			}
> +		}
> +	}
> +
> +	/*
> +	 * We have to now fallback to software double buffering.
> +	 * The tricky decision is choosing a size for the hardware buffer.
> +	 * We could start with drvdata->size (configurable via sysfs) and
> +	 * scale it down until we can allocate the data.
> +	 */
> +	etr_buf = tmc_alloc_etr_buf(drvdata, size, 0, node, NULL);

The above comment doesn't match the code.  We start with a buffer size equal to
what was requested and then fall back to drvdata->size if something goes wrong.

I don't see why drvdata->size gets involved at all.  I would simply try to
reduce @size until we get a successful allocation.

> +	if (!IS_ERR(etr_buf))
> +		goto done;
> +	size = drvdata->size;
> +	do {
> +		etr_buf = tmc_alloc_etr_buf(drvdata, size, 0, node, NULL);
> +		if (!IS_ERR(etr_buf))
> +			goto done;
> +		size /= 2;
> +	} while (size >= TMC_ETR_PERF_MIN_BUF_SIZE);
> +
> +	kfree(etr_perf);
> +	return ERR_PTR(-ENOMEM);
> +
> +done:
> +	etr_perf->etr_buf = etr_buf;
> +	return etr_perf;
> +}
> +
> +
> +static void *tmc_etr_alloc_perf_buffer(struct coresight_device *csdev,
> +					int cpu, void **pages, int nr_pages,
> +					bool snapshot)
> +{
> +	struct etr_perf_buffer *etr_perf;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	if (cpu == -1)
> +		cpu = smp_processor_id();
> +
> +	etr_perf = tmc_etr_setup_perf_buf(drvdata, cpu_to_node(cpu),
> +					     nr_pages, pages, snapshot);
> +	if (IS_ERR(etr_perf)) {
> +		dev_dbg(drvdata->dev, "Unable to allocate ETR buffer\n");
> +		return NULL;
> +	}
> +
> +	etr_perf->snapshot = snapshot;
> +	etr_perf->nr_pages = nr_pages;
> +	etr_perf->pages = pages;
> +
> +	return etr_perf;
> +}
> +
> +static void tmc_etr_free_perf_buffer(void *config)
> +{
> +	struct etr_perf_buffer *etr_perf = config;
> +
> +	if (etr_perf->etr_buf)
> +		tmc_free_etr_buf(etr_perf->etr_buf);
> +	kfree(etr_perf);
> +}
> +
> +/*
> + * Pad the etr buffer with barrier packets to align the head to 4K aligned
> + * offset. This is required for ETR SG backed buffers, so that we can rotate
> + * the buffer easily and avoid a software double buffering.
> + */
> +static long tmc_etr_pad_perf_buffer(struct etr_perf_buffer *etr_perf, long head)
> +{
> +	long new_head;
> +	struct etr_buf *etr_buf = etr_perf->etr_buf;
> +
> +	head = PERF_IDX2OFF(head, etr_perf);
> +	new_head = ALIGN(head, SZ_4K);
> +	if (head == new_head)
> +		return head;
> +	/*
> +	 * If the padding is not aligned to barrier packet size
> +	 * we can't do much.
> +	 */
> +	if ((new_head - head) % CORESIGHT_BARRIER_PKT_SIZE)
> +		return -EINVAL;
> +	return tmc_etr_buf_insert_barrier_packets(etr_buf, head,
> +						  new_head - head);
> +}
> +
> +static int tmc_etr_set_perf_buffer(struct coresight_device *csdev,
> +				   struct perf_output_handle *handle,
> +				   void *config)
> +{
> +	int rc;
> +	unsigned long flags;
> +	long head, new_head;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +	struct etr_perf_buffer *etr_perf = config;
> +	struct etr_buf *etr_buf = etr_perf->etr_buf;
> +
> +	etr_perf->head = handle->head;
> +	head = PERF_IDX2OFF(etr_perf->head, etr_perf);
> +	switch (etr_perf->flags) {
> +	case ETR_BUF_F_RESTORE_MINIMAL:
> +		new_head = tmc_etr_pad_perf_buffer(etr_perf, head);
> +		if (new_head < 0)
> +			return new_head;
> +		if (head != new_head) {
> +			rc = perf_aux_output_skip(handle, new_head - head);
> +			if (rc)
> +				return rc;
> +			etr_perf->head = handle->head;
> +			head = new_head;
> +		}
> +		/* Fall through */
> +	case ETR_BUF_F_RESTORE_FULL:
> +		rc = tmc_restore_etr_buf(drvdata, etr_buf,
> +					 head, head, handle->size, 0);
> +		break;
> +	case 0:
> +		/* Nothing to do here. */
> +		rc = 0;
> +		break;
> +	default:
> +		dev_warn(drvdata->dev, "Unexpected flags in etr_perf buffer\n");
> +		WARN_ON(1);
> +		rc = -EINVAL;
> +	}
> +
> +	/*
> +	 * This sink is going to be used in perf mode. No other session can
> +	 * grab it from us. So set the perf mode specific data here. This will
> +	 * be released just before we disable the sink from update_buffer call
> +	 * back.
> +	 */
> +	if (!rc) {
> +		spin_lock_irqsave(&drvdata->spinlock, flags);
> +		if (WARN_ON(drvdata->perf_data))
> +			rc = -EBUSY;
> +		else
> +			drvdata->perf_data = etr_perf;
> +		spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +	}
> +	return rc;
> +}
> +
> +/*
> + * tmc_etr_sync_perf_buffer: Copy the actual trace data from the hardware
> + * buffer to the perf ring buffer.
> + */
> +static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf)
> +{
> +	struct etr_buf *etr_buf = etr_perf->etr_buf;
> +	long bytes, to_copy;
> +	unsigned long head = etr_perf->head;
> +	unsigned long pg_idx, pg_offset, src_offset;
> +	char **dst_pages, *src_buf;
> +
> +	head = PERF_IDX2OFF(etr_perf->head, etr_perf);
> +	pg_idx = head >> PAGE_SHIFT;
> +	pg_offset = head & (PAGE_SIZE - 1);
> +	dst_pages = (char **)etr_perf->pages;
> +	src_offset = etr_buf->offset;
> +	to_copy = etr_buf->len;
> +
> +	while (to_copy > 0) {
> +		/*
> +		 * We can copy minimum of :
> +		 *  1) what is available in the source buffer,
> +		 *  2) what is available in the source buffer, before it
> +		 *     wraps around.
> +		 *  3) what is available in the destination page.
> +		 * in one iteration.
> +		 */
> +		bytes = tmc_etr_buf_get_data(etr_buf, src_offset, to_copy,
> +					     &src_buf);
> +		if (WARN_ON_ONCE(bytes <= 0))
> +			break;
> +		if (PAGE_SIZE - pg_offset <  bytes)
> +			bytes = PAGE_SIZE - pg_offset;
> +
> +		memcpy(dst_pages[pg_idx] + pg_offset, src_buf, bytes);
> +		to_copy -= bytes;
> +		/* Move destination pointers */
> +		pg_offset += bytes;
> +		if (pg_offset == PAGE_SIZE) {
> +			pg_offset = 0;
> +			if (++pg_idx == etr_perf->nr_pages)
> +				pg_idx = 0;
> +		}
> +
> +		/* Move source pointers */
> +		src_offset += bytes;
> +		if (src_offset >= etr_buf->size)
> +			src_offset -= etr_buf->size;
> +	}
> +}
> +
> +/*
> + * XXX: What is the expected behavior here in the following cases ?
> + *  1) Full trace mode, without double buffering : What should be the size
> + *     reported back when the buffer is full and has wrapped around. Ideally,
> + *     we should report for the lost trace to make sure the "head" in the ring
> + *     buffer comes back to the position as in the trace buffer, rather than
> + *     returning "total size" of the buffer.

I agree with the above strategy as there isn't much else to do.  But do we
actually have a DMA coherent ETR SG or CATU?  From the documentation available
to me I don't see it for ERT SG and I don't have the one for CATU.  My hope
would be to get an IP with an overflow interrupt _before_ one that is DMA
coherent.


> + * 2) In snapshot mode, should we always return "full buffer size" ?

Snapshot mode is currently broken, something I intend to fix shortly.  Until
then and to follow what is done for other IPs I think it is best to return the
full size.

> + */
> +static unsigned long
> +tmc_etr_update_perf_buffer(struct coresight_device *csdev,
> +			   struct perf_output_handle *handle,
> +			   void *config)
> +{
> +	bool double_buffer, lost = false;
> +	unsigned long flags, offset, size = 0;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +	struct etr_perf_buffer *etr_perf = config;
> +	struct etr_buf *etr_buf = etr_perf->etr_buf;
> +
> +	double_buffer = (etr_perf->flags == 0);
> +
> +	spin_lock_irqsave(&drvdata->spinlock, flags);
> +	if (WARN_ON(drvdata->perf_data != etr_perf)) {
> +		lost = true;
> +		spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +		goto out;
> +	}
> +
> +	CS_UNLOCK(drvdata->base);
> +
> +	tmc_flush_and_stop(drvdata);
> +
> +	tmc_sync_etr_buf(drvdata);
> +	CS_UNLOCK(drvdata->base);
> +	/* Reset perf specific data */
> +	drvdata->perf_data = NULL;
> +	spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +
> +	offset = etr_buf->offset + etr_buf->len;
> +	if (offset > etr_buf->size)
> +		offset -= etr_buf->size;
> +
> +	if (double_buffer) {
> +		/*
> +		 * If we use software double buffering, update the ring buffer.
> +		 * And the size is what we have in the hardware buffer.
> +		 */
> +		size = etr_buf->len;
> +		tmc_etr_sync_perf_buffer(etr_perf);
> +	} else {
> +		/*
> +		 * If the hardware uses perf ring buffer the size of the data
> +		 * we have is from the old-head to the current head of the
> +		 * buffer. This also means in non-snapshot mode, we have lost
> +		 * one-full-buffer-size worth data, if the buffer wraps around.
> +		 */
> +		unsigned long old_head;
> +
> +		old_head = PERF_IDX2OFF(etr_perf->head, etr_perf);
> +		size = (offset - old_head + etr_buf->size) % etr_buf->size;
> +	}
> +
> +	/*
> +	 * Update handle->head in snapshot mode. Also update the size to the
> +	 * hardware buffer size if there was an overflow.
> +	 */
> +	if (etr_perf->snapshot) {
> +		if (double_buffer)
> +			handle->head += size;
> +		else
> +			handle->head = offset;
> +		if (etr_buf->full)
> +			size = etr_buf->size;
> +	}
> +
> +	lost |= etr_buf->full;
> +out:
> +	if (lost)
> +		perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
> +	return size;
> +}
> +
>  static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
>  {
> -	/* We don't support perf mode yet ! */
> -	return -EINVAL;
> +	int rc = 0;
> +	unsigned long flags;
> +	struct etr_perf_buffer *etr_perf;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	spin_lock_irqsave(&drvdata->spinlock, flags);
> +	/*
> +	 * There can be only one writer per sink in perf mode. If the sink
> +	 * is already open in SYSFS mode, we can't use it.
> +	 */
> +	if (drvdata->mode != CS_MODE_DISABLED) {
> +		rc = -EBUSY;
> +		goto unlock_out;
> +	}
> +
> +	etr_perf = drvdata->perf_data;
> +	if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) {
> +		rc = -EINVAL;
> +		goto unlock_out;
> +	}
> +
> +	drvdata->mode = CS_MODE_PERF;
> +	tmc_etr_enable_hw(drvdata, etr_perf->etr_buf);
> +
> +unlock_out:
> +	spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +	return rc;
>  }
>  
>  static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
> @@ -1459,6 +1836,10 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev)
>  static const struct coresight_ops_sink tmc_etr_sink_ops = {
>  	.enable		= tmc_enable_etr_sink,
>  	.disable	= tmc_disable_etr_sink,
> +	.alloc_buffer	= tmc_etr_alloc_perf_buffer,
> +	.update_buffer	= tmc_etr_update_perf_buffer,
> +	.set_buffer	= tmc_etr_set_perf_buffer,
> +	.free_buffer	= tmc_etr_free_perf_buffer,
>  };
>  
>  const struct coresight_ops tmc_etr_cs_ops = {
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index 185dc12..aa42f5d 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -197,6 +197,7 @@ struct etr_buf {
>   * @trigger_cntr: amount of words to store after a trigger.
>   * @etr_caps:	Bitmask of capabilities of the TMC ETR, inferred from the
>   *		device configuration register (DEVID)
> + * @perf_data:	PERF buffer for ETR.
>   * @sysfs_data:	SYSFS buffer for ETR.
>   */
>  struct tmc_drvdata {
> @@ -218,6 +219,7 @@ struct tmc_drvdata {
>  	u32			trigger_cntr;
>  	u32			etr_caps;
>  	struct etr_buf		*sysfs_buf;
> +	void			*perf_data;
>  };
>  
>  struct etr_buf_operations {
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v2 23/27] coresight: tmc-etr: Handle driver mode specific ETR buffers
From: Suzuki K Poulose @ 2018-05-08 21:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508171800.GA3389@xps15>

On 05/08/2018 06:18 PM, Mathieu Poirier wrote:
> On Tue, May 01, 2018 at 10:10:53AM +0100, Suzuki K Poulose wrote:
>> Since the ETR could be driven either by SYSFS or by perf, it
>> becomes complicated how we deal with the buffers used for each
>> of these modes. The ETR driver cannot simply free the current
>> attached buffer without knowing the provider (i.e, sysfs vs perf).
>>
>> To solve this issue, we provide:
>> 1) the driver-mode specific etr buffer to be retained in the drvdata
>> 2) the etr_buf for a session should be passed on when enabling the
>>     hardware, which will be stored in drvdata->etr_buf. This will be
>>     replaced (not free'd) as soon as the hardware is disabled, after
>>     necessary sync operation.
>>
>> The advantages of this are :
>>
>> 1) The common code path doesn't need to worry about how to dispose
>>     an existing buffer, if it is about to start a new session with a
>>     different buffer, possibly in a different mode.
>> 2) The driver mode can control its buffers and can get access to the
>>     saved session even when the hardware is operating in a different
>>     mode. (e.g, we can still access a trace buffer from a sysfs mode
>>     even if the etr is now used in perf mode, without disrupting the
>>     current session.)
>>
>> Towards this, we introduce a sysfs specific data which will hold the
>> etr_buf used for sysfs mode of operation, controlled solely by the
>> sysfs mode handling code.
> 
> Thinking further on this... I toyed with the idea of doing the same thing when
> working on the original driver and decided against it.  Do we really have a case
> where users would want to use sysFS and perf alternatively?  To me this looks
> overdesigned.
> 
> If we are going to go that way we need to enact the same behavior for ETB10 and
> ETF...  And take it out of this set as it is already substantial enough.

The difference between ETB10/ETF and ETR is the usage of the buffer. The 
former uses an internal buffer and we always have to copy it out to an
external buffer for consumption. Now this external buffer is actually 
separate for each mode, i.e sysfs and perf. Also the data is copied
out right after we disable the HW. This ensures that the interleaved
mode doesn't corrupt each others data.

However, the ETR doesn't have an internal buffer and uses the System 
RAM. That brings in the problem of one mode using the "buffer" as
described by the drvdata. So, eventually either mode could write to
the buffer allocated by the other mode before it is consumed by the
end user (via syfs read or perf). That brings in the challenge of
managing the buffer safely, switching back and forth the buffer
(with the right size and pages) for each mode without any interferences.
That also implies, one mode must be able to free the left-over buffer
from the previous mode safely (which could be potentially linked to
other data structures maintained by the mode). And that makes it more 
complex. e.g, we must leave the sysfs trace data for collection and
meanwhile the perf could grab the ETR for its usage. The perf mode
might not know the mode of the existing buffer and thus wouldn't know
how to free it properly.

This is why we need buffers per mode which can be managed by
each mode. i.e, both allocated, used and more importantly free'd
appropriately.

Cheers
Suzuki

^ permalink raw reply

* Incoming sms problem on Motorola Droid 4
From: Pavel Machek @ 2018-05-08 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

I have problems with incoming SMS. ofono tries to use +CNMI=1,2,2,1,0

> AT+CNMI=?
< +CNMI: (0,1,2),(0,1,2,3),(0,2),(0,1,2),(0,1)
< OK
ofonod[3070]: drivers/atmodem/sms.c:build_cnmi_string()
ofonod[3070]: drivers/atmodem/sms.c:construct_ack_pdu()
> AT+CNMI=1,2,2,1,0
< OK
ofonod[3070]: src/network.c:__ofono_netreg_add_status_watch() 0x5bbbf0

... unfortunately, with that configuration no messages are comming to
ofono and the other phone sees them as "delievery failed".

I had some luck with unicsy_demo using AT+CNMI=1,2 with text mode (not
PDU) messages. That works well enough for me.

Unfortunately, if I force ofono to pass "AT+CNMI=1,2", it does not
work well, either.

Any ideas how to debug this / what to try?

Thanks,

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180508/3f90d2c4/attachment.sig>

^ permalink raw reply

* [GIT PULL 2/2] ARM: Keystone DTS update for v4.18
From: Santosh Shilimkar @ 2018-05-08 21:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525815697-6338-1-git-send-email-santosh.shilimkar@oracle.com>

The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:

  Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git tags/keystone_dts_for_4.18

for you to fetch changes up to 84cfd2c4f3b159b308976ccd0501985524fd6ee1:

  ARM: dts: k2g-evm: Add DCAN dt nodes (2018-05-04 23:11:49 -0700)

----------------------------------------------------------------
ARM: DTS: Add DCAN support for Keystone K2G

----------------------------------------------------------------
Faiz Abbas (1):
      ARM: dts: k2g-evm: Add DCAN dt nodes

 arch/arm/boot/dts/keystone-k2g-evm.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

^ permalink raw reply

* [GIT PULL 1/2] ARM: SOC driver update v4.18
From: Santosh Shilimkar @ 2018-05-08 21:41 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:

  Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git tags/soc_drivers_for_4.18

for you to fetch changes up to 1e0a601437a6111ecf384df010812c53cada6497:

  firmware: ti_sci: Switch to SPDX Licensing (2018-05-04 23:10:23 -0700)

----------------------------------------------------------------
ARM: SOC driver update for 4.18

 - AEMIF driver update to support board files and remove
   need of mach-davinci aemif code
 - Use percpu counters for qmss datapath stats
 - License update for TI SCI

----------------------------------------------------------------
Bartosz Golaszewski (2):
      memory: aemif: don't rely on kbuild for driver's name
      memory: aemif: add support for board files

Lokesh Vutla (1):
      firmware: ti_sci: Switch to SPDX Licensing

Vasyl Gomonovych (1):
      soc: ti: knav_qmss: Use percpu instead atomic for stats counter

 drivers/firmware/ti_sci.c              | 10 +-----
 drivers/firmware/ti_sci.h              | 30 +----------------
 drivers/memory/ti-aemif.c              | 60 ++++++++++++++++++++++------------
 drivers/soc/ti/knav_qmss.h             | 14 ++++----
 drivers/soc/ti/knav_qmss_queue.c       | 60 ++++++++++++++++++++++------------
 include/linux/platform_data/ti-aemif.h | 25 ++++++++++++++
 include/linux/soc/ti/ti_sci_protocol.h | 10 +-----
 7 files changed, 115 insertions(+), 94 deletions(-)

^ permalink raw reply

* [PATCH v6 3/6] kernel/reboot.c: export pm_power_off_prepare
From: Rafael J. Wysocki @ 2018-05-08 21:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180505070147.epsrglnypm72jr5u@pengutronix.de>

On 5/5/2018 9:01 AM, Oleksij Rempel wrote:
> Moving Rafael from Cc to To.
>
> Hi Rafael,
>
> can you please help here?
> I need your ACK or NACK for this patch.

Sorry for the delay, I'll have a closer look at it in the next couple of 
days.

Thanks,
Rafael


> On Fri, May 04, 2018 at 01:49:56PM -0700, Andrew Morton wrote:
>> On Fri, 4 May 2018 20:50:52 +0200 Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>>
>>> Hallo Andrew,
>>> I need your ACK or NACK for this patch.
>>>
>>> This function is used to configure external PMIC to interpret
>>> signal which will be triggered by pm_power_off as power off.
>>> Since same signal can be used for stand by, I linked PMIC configuration
>>> with pm_power_off_prepare to avoid possible conflicts.
>>>
>>> ...
>>>
>>>> --- a/kernel/reboot.c
>>>> +++ b/kernel/reboot.c
>>>> @@ -49,6 +49,7 @@ int reboot_force;
>>>>    */
>>>>   
>>>>   void (*pm_power_off_prepare)(void);
>>>> +EXPORT_SYMBOL(pm_power_off_prepare);
>>>>   
>> OK by me, but it's more of a Rafael thing.
>>

^ permalink raw reply

* [PATCH] Kirin-PCIe: Add kirin pcie msi feature.
From: Dmitry Shmidt @ 2018-05-08 21:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525763028-107417-1-git-send-email-chenyao11@huawei.com>

On Tue, May 8, 2018 at 12:03 AM, Yao Chen <chenyao11@huawei.com> wrote:
> This patch adds kirin pcie msi feature.
>
> Signed-off-by: Yao Chen <chenyao11@huawei.com>
> ---
>  arch/arm64/boot/dts/hisilicon/hi3660.dtsi |  2 ++
>  drivers/pci/dwc/pcie-kirin.c              | 38 +++++++++++++++++++++++++++++++
>  2 files changed, 40 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index ec3eb8e..4ef684f 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -872,6 +872,8 @@
>                                   0x0 0x02000000>;
>                         num-lanes = <1>;
>                         #interrupt-cells = <1>;
> +                       interrupts = <0 283 4>;
> +                       interrupts-names = "msi";

Possible typo? Should be interrupt-names = "msi";

>                         interrupt-map-mask = <0xf800 0 0 7>;
>                         interrupt-map = <0x0 0 0 1
>                                          &gic GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
> diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/dwc/pcie-kirin.c
> index d2970a0..2319c9c 100644
> --- a/drivers/pci/dwc/pcie-kirin.c
> +++ b/drivers/pci/dwc/pcie-kirin.c
> @@ -426,9 +426,28 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)
>         return 0;
>  }
>
> +static irqreturn_t kirin_pcie_msi_irq_handler(int irq, void *arg)
> +{
> +       struct pcie_port *pp = arg;
> +
> +       return dw_handle_msi_irq(pp);
> +}
> +
> +static void kirin_pcie_msi_init(struct pcie_port *pp)
> +{
> +       dw_pcie_msi_init(pp);
> +}
> +
> +static void kirin_pcie_enable_interrupts(struct pcie_port *pp)
> +{
> +       if (IS_ENABLED(CONFIG_PCI_MSI))
> +               kirin_pcie_msi_init(pp);
> +}
> +
>  static int kirin_pcie_host_init(struct pcie_port *pp)
>  {
>         kirin_pcie_establish_link(pp);
> +       kirin_pcie_enable_interrupts(pp);
>
>         return 0;
>  }
> @@ -448,6 +467,25 @@ static int kirin_pcie_host_init(struct pcie_port *pp)
>  static int __init kirin_add_pcie_port(struct dw_pcie *pci,
>                                       struct platform_device *pdev)
>  {
> +       int ret;
> +
> +       if (IS_ENABLED(CONFIG_PCI_MSI)) {
> +               pci->pp.msi_irq = platform_get_irq(pdev, 0);
> +               if (!pci->pp.msi_irq) {
> +                       dev_err(&pdev->dev, "failed to get msi irq\n");
> +                       return -ENODEV;
> +               }
> +               ret = devm_request_irq(&pdev->dev, pci->pp.msi_irq,
> +                                      kirin_pcie_msi_irq_handler,
> +                                      IRQF_SHARED | IRQF_NO_THREAD,
> +                                      "kirin_pcie_msi", &pci->pp);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "failed to request msi irq\n");
> +                       return ret;
> +               }
> +       }
> +
> +       pci->pp.root_bus_nr = -1;
>         pci->pp.ops = &kirin_pcie_host_ops;
>
>         return dw_pcie_host_init(&pci->pp);
> --
> 1.9.1
>

^ permalink raw reply

* [PATCH] arm: dts: atmel: graph_child_address warning fixes
From: Boris Brezillon @ 2018-05-08 21:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508135930.5768-1-robh@kernel.org>

On Tue,  8 May 2018 08:59:25 -0500
Rob Herring <robh@kernel.org> wrote:

> Addresses for graph ports and endpoints are not necessary when
> there's only a single child. Fix the following warnings removing
> unnecessary addresses on OF graph nodes:
> 
> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller: graph node has single child node 'port at 0', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller/port at 0: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /ahb/apb/isi at f0034000/port: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /panel/port at 0: graph node has single child node 'endpoint at 0', #address-cells/#size-cells are not necessary
> 
> Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts | 15 ++++-----------
>  arch/arm/boot/dts/at91sam9g45.dtsi          |  2 --
>  arch/arm/boot/dts/at91sam9n12.dtsi          |  8 +-------
>  arch/arm/boot/dts/at91sam9n12ek.dts         | 14 ++++----------
>  arch/arm/boot/dts/at91sam9x5_lcd.dtsi       |  7 +------
>  arch/arm/boot/dts/at91sam9x5dm.dtsi         | 13 ++++---------
>  arch/arm/boot/dts/sama5d3.dtsi              |  2 --
>  arch/arm/boot/dts/sama5d3_lcd.dtsi          |  8 +-------
>  arch/arm/boot/dts/sama5d4.dtsi              |  8 +-------

For the hlcdc changes

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

I'll update the DT bindinds doc accordingly.

Thanks,

Boris

>  9 files changed, 16 insertions(+), 61 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> index fe05aaa7ac87..72c3b077fb46 100644
> --- a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> +++ b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> @@ -49,9 +49,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -144,16 +143,10 @@
>  		/* Actually Ampire 800480R2 */
>  		compatible = "foxlink,fl500wvr00-a0t", "simple-panel";
>  		backlight = <&backlight>;
> -		#address-cells = <1>;
> -		#size-cells = <0>;
>  		status = "okay";
>  
> -		port at 0 {
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
> index 1ee25a475be8..36729e3f2899 100644
> --- a/arch/arm/boot/dts/at91sam9g45.dtsi
> +++ b/arch/arm/boot/dts/at91sam9g45.dtsi
> @@ -1114,8 +1114,6 @@
>  				clock-names = "isi_clk";
>  				status = "disabled";
>  				port {
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  				};
>  			};
>  
> diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
> index 37cb81f457b5..a071fccb729b 100644
> --- a/arch/arm/boot/dts/at91sam9n12.dtsi
> +++ b/arch/arm/boot/dts/at91sam9n12.dtsi
> @@ -475,13 +475,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
> index c43095c5cb5c..eb0c1e11fa4d 100644
> --- a/arch/arm/boot/dts/at91sam9n12ek.dts
> +++ b/arch/arm/boot/dts/at91sam9n12ek.dts
> @@ -134,9 +134,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -246,13 +245,8 @@
>  		#size-cells = <0>;
>  		status = "okay";
>  
> -		port at 0 {
> -			reg = <0>;
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> index 1629db9dd563..e243dff67a67 100644
> --- a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> +++ b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> @@ -23,13 +23,8 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/at91sam9x5dm.dtsi
> index 34c089fe0bc0..5aea8fd09ad6 100644
> --- a/arch/arm/boot/dts/at91sam9x5dm.dtsi
> +++ b/arch/arm/boot/dts/at91sam9x5dm.dtsi
> @@ -29,9 +29,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -80,12 +79,8 @@
>  		#size-cells = <0>;
>  		status = "disabled";
>  
> -		port at 0 {
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
> index eae5e1ee9cd8..2c51042e1f6b 100644
> --- a/arch/arm/boot/dts/sama5d3.dtsi
> +++ b/arch/arm/boot/dts/sama5d3.dtsi
> @@ -239,8 +239,6 @@
>  				clock-names = "isi_clk";
>  				status = "disabled";
>  				port {
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  				};
>  			};
>  
> diff --git a/arch/arm/boot/dts/sama5d3_lcd.dtsi b/arch/arm/boot/dts/sama5d3_lcd.dtsi
> index be7cfefc6c31..2d042d7ec531 100644
> --- a/arch/arm/boot/dts/sama5d3_lcd.dtsi
> +++ b/arch/arm/boot/dts/sama5d3_lcd.dtsi
> @@ -23,13 +23,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi
> index 0cf9beddd556..90d7b64915ec 100644
> --- a/arch/arm/boot/dts/sama5d4.dtsi
> +++ b/arch/arm/boot/dts/sama5d4.dtsi
> @@ -333,13 +333,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  

^ permalink raw reply

* [PATCH] arm: dts: atmel: graph_child_address warning fixes
From: Boris Brezillon @ 2018-05-08 21:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqLckD9FAS=mOH_gr7PL5xipF2qsGvBi0mRKXPnXn6bEMQ@mail.gmail.com>

On Tue, 8 May 2018 15:41:51 -0500
Rob Herring <robh@kernel.org> wrote:

> On Tue, May 8, 2018 at 3:18 PM, Boris Brezillon
> <boris.brezillon@bootlin.com> wrote:
> > On Tue,  8 May 2018 08:59:25 -0500
> > Rob Herring <robh@kernel.org> wrote:
> >  
> >> Addresses for graph ports and endpoints are not necessary when
> >> there's only a single child. Fix the following warnings removing
> >> unnecessary addresses on OF graph nodes:
> >>
> >> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller: graph node has single child node 'port at 0', #address-cells/#size-cells are not necessary
> >> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller/port at 0: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> >> Warning (graph_child_address): /ahb/apb/isi at f0034000/port: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> >> Warning (graph_child_address): /panel/port at 0: graph node has single child node 'endpoint at 0', #address-cells/#size-cells are not necessary  
> >
> > Unfortunately that's not going to work, because the driver calls
> > drm_of_find_panel_or_bridge() with a positive port and endpoint,
> > not -1. While we could switch port arg from 0 to -1, that's not that
> > simple for the endpoint arg, because we don't know in advance how many
> > devices will be connected to the RGB/DPI port.  
> 
> 0 and -1 are treated the same way in the graph code.

Oh, you're right, I didn't check the of_graph_parse_endpoint() code.

> 
> Ports should be separate data streams. Can the hlcdc have more than 1
> data stream (I think I checked that)?

Yes, there's only one port.

> If not, then more than 1 port
> will never be needed. Likewise, a panel is pretty much never going to
> have 2 ports (or endpoints).

True.

> The hlcdc could have more than 1 endpoint
> if you have multiple connections, but that's not what's defined. If
> you have an 'endpoint' node, then having #address-cells/#size-cells is
> wrong without a reg prop and unit-address.

The reg and unit-address were present in the endpoint nodes (maybe not
in all dts though). AFAICT, the problem is more that the port only has a
single child, and dtc complains that such nodes should not have a reg
prop.

^ permalink raw reply

* [PATCH] arm: dts: atmel: graph_child_address warning fixes
From: Boris Brezillon @ 2018-05-08 20:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508221819.6b70d5c7@bbrezillon>

On Tue, 8 May 2018 22:18:19 +0200
Boris Brezillon <boris.brezillon@bootlin.com> wrote:

> On Tue,  8 May 2018 08:59:25 -0500
> Rob Herring <robh@kernel.org> wrote:
> 
> > Addresses for graph ports and endpoints are not necessary when
> > there's only a single child. Fix the following warnings removing
> > unnecessary addresses on OF graph nodes:
> > 
> > Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller: graph node has single child node 'port at 0', #address-cells/#size-cells are not necessary
> > Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller/port at 0: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> > Warning (graph_child_address): /ahb/apb/isi at f0034000/port: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> > Warning (graph_child_address): /panel/port at 0: graph node has single child node 'endpoint at 0', #address-cells/#size-cells are not necessary  
> 
> Unfortunately that's not going to work, because the driver calls
> drm_of_find_panel_or_bridge() with a positive port and endpoint,
> not -1. While we could switch port arg from 0 to -1, that's not that
> simple for the endpoint arg, because we don't know in advance how many
> devices will be connected to the RGB/DPI port.
> 
> [1]https://elixir.bootlin.com/linux/v4.17-rc3/source/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c#L41
> 

I can prepare patches containing the following changes, but I need to
test them first.

To be honest, I still don't see the problem with the "single child having
a reg" case. Sure, it's not required, but it's also not an invalid
representation. Also note that, depending on the board, we'll have to
define addresses in endpoints if there's more than one endpoint, which
IMO makes things even harder to follow, because in some cases endpoints
will be numbered and in the others they won't.

--->8---
diff --git a/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt b/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt
index 82f2acb3d374..bc01c431d624 100644
--- a/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt
+++ b/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt
@@ -7,13 +7,12 @@ Required properties:
  - compatible: value should be "atmel,hlcdc-display-controller"
  - pinctrl-names: the pin control state names. Should contain "default".
  - pinctrl-0: should contain the default pinctrl states.
- - #address-cells: should be set to 1.
- - #size-cells: should be set to 0.
 
 Required children nodes:
- Children nodes are encoding available output ports and their connections
- to external devices using the OF graph reprensentation (see ../graph.txt).
- At least one port node is required.
+ The port node represent the RGB/DPI output and can contain 0 to N endpoints
+ which encode connections to devices present on the RGB/DPI bus.
+ These connections are represented using the OF graph representation (see
+ ../graph.txt).
 
 Example:
 
@@ -28,16 +27,9 @@ Example:
                        compatible = "atmel,hlcdc-display-controller";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
 
-                       port at 0 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               reg = <0>;
-
-                               hlcdc_panel_output: endpoint at 0 {
-                                       reg = <0>;
+                       port {
+                               hlcdc_panel_output: endpoint {
                                        remote-endpoint = <&panel_input>;
                                };
                        };
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 8db51fb131db..0dc8f124a95e 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -38,7 +38,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
        struct drm_bridge *bridge;
        int ret;
 
-       ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint,
+       ret = drm_of_find_panel_or_bridge(dev->dev->of_node, -1, endpoint,
                                          &panel, &bridge);
        if (ret)
                return ret;
@@ -86,5 +86,10 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
        if (ret == -ENODEV && endpoint)
                return 0;
 
-       return ret;
+       /*
+        * If there's only one endpoint, the reg field will not be specified
+        * and no specific ID will be attached to this endpoint. Try with
+        * endpoint = -1 to handle this case.
+        */
+       return atmel_hlcdc_attach_endpoint(dev, -1);
 }

^ permalink raw reply related

* [PATCH] mtd: nxp-spifi: decrement flash_np refcnt on error paths
From: Alexey Khoroshilov @ 2018-05-08 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

nxp_spifi_probe() increments refcnt of SPI flash device node by
of_get_next_available_child() and then it passes the node
to mtd device in nxp_spifi_setup_flash().
But if a failure happens before mtd_device_register() succeed,
the refcnt is left undecremented.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
 drivers/mtd/spi-nor/nxp-spifi.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c
index 15374216d4d9..8919e31f2ab8 100644
--- a/drivers/mtd/spi-nor/nxp-spifi.c
+++ b/drivers/mtd/spi-nor/nxp-spifi.c
@@ -294,7 +294,8 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
 			break;
 		default:
 			dev_err(spifi->dev, "unsupported rx-bus-width\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto err_node_put;
 		}
 	}
 
@@ -328,7 +329,8 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
 		break;
 	default:
 		dev_err(spifi->dev, "only mode 0 and 3 supported\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_node_put;
 	}
 
 	writel(ctrl, spifi->io_base + SPIFI_CTRL);
@@ -356,22 +358,26 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
 	ret = spi_nor_scan(&spifi->nor, NULL, &hwcaps);
 	if (ret) {
 		dev_err(spifi->dev, "device scan failed\n");
-		return ret;
+		goto err_node_put;
 	}
 
 	ret = nxp_spifi_setup_memory_cmd(spifi);
 	if (ret) {
 		dev_err(spifi->dev, "memory command setup failed\n");
-		return ret;
+		goto err_node_put;
 	}
 
 	ret = mtd_device_register(&spifi->nor.mtd, NULL, 0);
 	if (ret) {
 		dev_err(spifi->dev, "mtd device parse failed\n");
-		return ret;
+		goto err_node_put;
 	}
 
 	return 0;
+
+err_node_put:
+	of_node_put(np);
+	return ret;
 }
 
 static int nxp_spifi_probe(struct platform_device *pdev)
-- 
2.7.4

^ permalink raw reply related

* [PATCH] arm: dts: atmel: graph_child_address warning fixes
From: Rob Herring @ 2018-05-08 20:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508221819.6b70d5c7@bbrezillon>

On Tue, May 8, 2018 at 3:18 PM, Boris Brezillon
<boris.brezillon@bootlin.com> wrote:
> On Tue,  8 May 2018 08:59:25 -0500
> Rob Herring <robh@kernel.org> wrote:
>
>> Addresses for graph ports and endpoints are not necessary when
>> there's only a single child. Fix the following warnings removing
>> unnecessary addresses on OF graph nodes:
>>
>> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller: graph node has single child node 'port at 0', #address-cells/#size-cells are not necessary
>> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller/port at 0: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
>> Warning (graph_child_address): /ahb/apb/isi at f0034000/port: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
>> Warning (graph_child_address): /panel/port at 0: graph node has single child node 'endpoint at 0', #address-cells/#size-cells are not necessary
>
> Unfortunately that's not going to work, because the driver calls
> drm_of_find_panel_or_bridge() with a positive port and endpoint,
> not -1. While we could switch port arg from 0 to -1, that's not that
> simple for the endpoint arg, because we don't know in advance how many
> devices will be connected to the RGB/DPI port.

0 and -1 are treated the same way in the graph code.

Ports should be separate data streams. Can the hlcdc have more than 1
data stream (I think I checked that)? If not, then more than 1 port
will never be needed. Likewise, a panel is pretty much never going to
have 2 ports (or endpoints). The hlcdc could have more than 1 endpoint
if you have multiple connections, but that's not what's defined. If
you have an 'endpoint' node, then having #address-cells/#size-cells is
wrong without a reg prop and unit-address.

Rob

^ permalink raw reply

* [PATCH 3/4] coresight: allow to build as modules
From: Kim Phillips @ 2018-05-08 20:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f299d0be-f1a6-46ca-3d8a-13d7d89a007d@infradead.org>

On Tue, 8 May 2018 12:31:08 -0700
Randy Dunlap <rdunlap@infradead.org> wrote:

> Hi,

Hi,

> On 05/08/2018 12:06 PM, Kim Phillips wrote:
> 
> >  if CORESIGHT
> >  config CORESIGHT_LINKS_AND_SINKS
> > -	bool "CoreSight Link and Sink drivers"
> > +	tristate "CoreSight Link and Sink drivers"
> > +	depends on CORESIGHT
> 
> The "if CORESIGHT" line serves as a "depends on CORESIGHT" for the entire "if"
> block, so please don't repeat the "depends on" here.

Thanks, removed.

> >  config CORESIGHT_CPU_DEBUG
> >  	tristate "CoreSight CPU Debug driver"
> > -	depends on ARM || ARM64
> > -	depends on DEBUG_FS
> > +	depends on CORESIGHT && DEBUG_FS
> 
> "depends on CORESIGHT" is not needed if this is still inside the
> if CORESIGHT/endif block.  (I think it is but I can't tell from just looking
> at the patch itself.)

Thanks, it is, removed.

> 
> >  	help
> >  	  This driver provides support for coresight debugging module. This
> >  	  is primarily used to dump sample-based profiling registers when
> > @@ -103,4 +127,7 @@ config CORESIGHT_CPU_DEBUG
> >  	  properly, please refer Documentation/trace/coresight-cpu-debug.txt
> >  	  for detailed description and the example for usage.
> >  
> > +	  To compile this code as a module, choose M here: the
> > +	  module will be called coresight-cpu-debug.
> > +
> >  endif
> 
> > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
> > index 3ffc9feb2d64..8c49c7b82d84 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h
> > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
> > @@ -54,7 +54,7 @@ struct etm_filters {
> >  };
> >  
> >  
> > -#ifdef CONFIG_CORESIGHT
> > +#if IS_ENABLED(CONFIG_CORESIGHT)
> 
> Have you found (observed) that this change (above) is necessary (and others
> like it below)?  I thought that they would be equivalent.
> 
> From include/linux/kconfig.h:
> /*
>  * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
>  * 0 otherwise.
>  */
> #define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
> 
> 
> 
> > diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> > index f1d0e21d8cab..335bca44b42d 100644
> > --- a/drivers/hwtracing/coresight/coresight-priv.h
> > +++ b/drivers/hwtracing/coresight/coresight-priv.h
> 
> > @@ -143,7 +149,7 @@ struct list_head *coresight_build_path(struct coresight_device *csdev,
> >  				       struct coresight_device *sink);
> >  void coresight_release_path(struct list_head *path);
> >  
> > -#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
> > +#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
> 
> ditto.
> 
> >  extern int etm_readl_cp14(u32 off, unsigned int *val);
> >  extern int etm_writel_cp14(u32 off, u32 val);
> >  #else
> 
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index d950dad5056a..5863eb1a7335 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -243,7 +243,7 @@ struct coresight_ops {
> >  	const struct coresight_ops_source *source_ops;
> >  };
> >  
> > -#ifdef CONFIG_CORESIGHT
> > +#if IS_ENABLED(CONFIG_CORESIGHT)
> 
> ditto.

If I revert all three IS_ENABLED back to plain #ifdefs, and rebuild with
CONFIG_CORESIGHT*=m, I get:

  CC [M]  drivers/hwtracing/coresight/coresight.o
  CC [M]  drivers/hwtracing/coresight/of_coresight.o
../drivers/hwtracing/coresight/coresight.c:586:5: error: redefinition of ?coresight_enable?
 int coresight_enable(struct coresight_device *csdev)
     ^~~~~~~~~~~~~~~~
In file included from ../drivers/hwtracing/coresight/coresight.c:23:0:
../include/linux/coresight.h:259:1: note: previous definition of ?coresight_enable? was here
 coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
 ^~~~~~~~~~~~~~~~
../drivers/hwtracing/coresight/coresight.c:670:6: error: redefinition of ?coresight_disable?
 void coresight_disable(struct coresight_device *csdev)
      ^~~~~~~~~~~~~~~~~
In file included from ../drivers/hwtracing/coresight/coresight.c:23:0:
../include/linux/coresight.h:260:20: note: previous definition of ?coresight_disable? was here
 static inline void coresight_disable(struct coresight_device *csdev) {}
                    ^~~~~~~~~~~~~~~~~
../drivers/hwtracing/coresight/coresight.c:945:5: error: redefinition of ?coresight_timeout?
 int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
     ^~~~~~~~~~~~~~~~~
In file included from ../drivers/hwtracing/coresight/coresight.c:23:0:
../include/linux/coresight.h:261:19: note: previous definition of ?coresight_timeout? was here
 static inline int coresight_timeout(void __iomem *addr, u32 offset,
                   ^~~~~~~~~~~~~~~~~
../drivers/hwtracing/coresight/coresight.c:991:26: error: redefinition of ?coresight_register?
 struct coresight_device *coresight_register(struct coresight_desc *desc)
                          ^~~~~~~~~~~~~~~~~~
In file included from ../drivers/hwtracing/coresight/coresight.c:23:0:
../include/linux/coresight.h:256:1: note: previous definition of ?coresight_register? was here
 coresight_register(struct coresight_desc *desc) { return NULL; }
 ^~~~~~~~~~~~~~~~~~
../drivers/hwtracing/coresight/coresight.c:1081:6: error: redefinition of ?coresight_unregister?
 void coresight_unregister(struct coresight_device *csdev)
      ^~~~~~~~~~~~~~~~~~~~
In file included from ../drivers/hwtracing/coresight/coresight.c:23:0:
../include/linux/coresight.h:257:20: note: previous definition of ?coresight_unregister? was here
 static inline void coresight_unregister(struct coresight_device *csdev) {}
                    ^~~~~~~~~~~~~~~~~~~~
../scripts/Makefile.build:312: recipe for target 'drivers/hwtracing/coresight/coresight.o' failed
make[3]: *** [drivers/hwtracing/coresight/coresight.o] Error 1

Building CORESIGHT=y builds ok, so, building it as a module causes the
latter stubs to be compiled:

#ifdef CONFIG_CORESIGHT
extern struct coresight_device *
coresight_register(struct coresight_desc *desc);
extern void coresight_unregister(struct coresight_device *csdev);
extern int coresight_enable(struct coresight_device *csdev);
extern void coresight_disable(struct coresight_device *csdev);
extern int coresight_timeout(void __iomem *addr, u32 offset,
                             int position, int value);
#else
static inline struct coresight_device *
coresight_register(struct coresight_desc *desc) { return NULL; }
static inline void coresight_unregister(struct coresight_device *csdev) {}
static inline int
coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
static inline void coresight_disable(struct coresight_device *csdev) {}
static inline int coresight_timeout(void __iomem *addr, u32 offset,
                                     int position, int value) { return 1; }
#endif

Adding kconfig.h to coresight.h's #include list doesn't help.  So we
need the IS_ENABLED for its __or(..., IS_MODULE()) case.

That being said, I don't know of any outside kernel-build dependencies
coresight.h might have.

Kim

^ permalink raw reply

* [PATCH v6 2/2] drivers: soc: Add LLCC driver
From: Rishabh Bhatnagar @ 2018-05-08 20:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525810921-15878-1-git-send-email-rishabhb@codeaurora.org>

LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into multiple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice they get and activate or deactivate the slice as needed. LLCC driver
provides API for the clients to perform these operations.

Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <rishabhb@codeaurora.org>
---
 drivers/soc/qcom/Kconfig           |  17 ++
 drivers/soc/qcom/Makefile          |   2 +
 drivers/soc/qcom/llcc-sdm845.c     | 106 ++++++++++++
 drivers/soc/qcom/llcc-slice.c      | 335 +++++++++++++++++++++++++++++++++++++
 include/linux/soc/qcom/llcc-qcom.h | 162 ++++++++++++++++++
 5 files changed, 622 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e050eb8..0b550f9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -21,6 +21,23 @@ config QCOM_GSBI
           functions for connecting the underlying serial UART, SPI, and I2C
           devices to the output pins.

+config QCOM_LLCC
+	tristate "Qualcomm Technologies, Inc. LLCC driver"
+	depends on ARCH_QCOM
+	help
+	  Qualcomm Technologies, Inc. platform specific
+	  Last Level Cache Controller(LLCC) driver. This provides interfaces
+	  to clients that use the LLCC. Say yes here to enable LLCC slice
+	  driver.
+
+config QCOM_SDM845_LLCC
+	tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+	depends on QCOM_LLCC
+	help
+	  Say yes here to enable the LLCC driver for SDM845. This provides
+	  data required to configure LLCC so that clients can start using the
+	  LLCC slices.
+
 config QCOM_MDT_LOADER
 	tristate
 	select QCOM_SCM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index dcebf28..e16d6a2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 0000000..e5e792c
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT(System Cache Table) entry contains of the following members:
+ * usecase_id: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Boolean indicating if the slice has a fixed capacity
+ * bonus_ways: Bonus ways are additional ways to be used for any slice,
+ *		if client ends up using more than reserved cache ways. Bonus
+ *		ways are allocated only if they are not reserved for some
+ *		other client.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot
+ *		be used by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ *             slice: normal or TCM(Tightly Coupled Memory)
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *                    configured to 1 only bonus and reserved ways are probed.
+ *                    When configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maintained active vote
+ *               then the ways assigned to this client are not flushed on power
+ *               collapse.
+ * activate_on_init: Activate the slice immediately after the SCT is programmed
+ */
+#define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+	{					\
+		.usecase_id = uid,		\
+		.slice_id = sid,		\
+		.max_cap = mc,			\
+		.priority = p,			\
+		.fixed_size = fs,		\
+		.bonus_ways = bway,		\
+		.res_ways = rway,		\
+		.cache_mode = cmod,		\
+		.probe_target_ways = ptw,	\
+		.dis_cap_alloc = dca,		\
+		.retain_on_pc = rp,		\
+		.activate_on_init = a,		\
+	}
+
+static struct llcc_slice_config sdm845_data[] =  {
+	SCT_ENTRY(1,  1,  2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 1),
+	SCT_ENTRY(2,  2,  512,  2, 1, 0x0,   0x0f0, 0, 0, 1, 1, 0),
+	SCT_ENTRY(3,  3,  512,  2, 1, 0x0,   0x0f0, 0, 0, 1, 1, 0),
+	SCT_ENTRY(4,  4,  563,  2, 1, 0x0,   0x00e, 2, 0, 1, 1, 0),
+	SCT_ENTRY(5,  5,  2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(6,  6,  2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(7,  7,  1024, 2, 0, 0xfc,  0xf00, 0, 0, 1, 1, 0),
+	SCT_ENTRY(8,  8,  2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(10, 10, 2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(11, 11, 512,  1, 1, 0xc,   0x0,   0, 0, 1, 1, 0),
+	SCT_ENTRY(12, 12, 2304, 1, 0, 0xff0, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(13, 13, 256,  2, 0, 0x0,   0x1,   0, 0, 1, 0, 1),
+	SCT_ENTRY(15, 15, 2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(16, 16, 2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(17, 17, 2816, 1, 0, 0xffc, 0x2,   0, 0, 1, 1, 0),
+	SCT_ENTRY(20, 20, 1024, 2, 1, 0x0,   0xf00, 0, 0, 1, 1, 0),
+	SCT_ENTRY(21, 21, 1024, 0, 1, 0x1e,  0x0,   0, 0, 1, 1, 0),
+	SCT_ENTRY(22, 22, 1024, 1, 1, 0xffc, 0x2,   0, 0, 1, 1, 0),
+};
+
+static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
+{
+	return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data));
+}
+
+static const struct of_device_id sdm845_qcom_llcc_of_match[] = {
+	{ .compatible = "qcom,sdm845-llcc", },
+	{ },
+};
+
+static struct platform_driver sdm845_qcom_llcc_driver = {
+	.driver = {
+		.name = "sdm845-llcc",
+		.owner = THIS_MODULE,
+		.of_match_table = sdm845_qcom_llcc_of_match,
+	},
+	.probe = sdm845_qcom_llcc_probe,
+};
+
+static int __init sdm845_init_qcom_llcc_init(void)
+{
+	return platform_driver_register(&sdm845_qcom_llcc_driver);
+}
+module_init(sdm845_init_qcom_llcc_init);
+
+static void __exit sdm845_exit_qcom_llcc_exit(void)
+{
+	platform_driver_unregister(&sdm845_qcom_llcc_driver);
+}
+module_exit(sdm845_exit_qcom_llcc_exit);
+
+MODULE_DESCRIPTION("QCOM sdm845 LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
new file mode 100644
index 0000000..209df55
--- /dev/null
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+#define ACTIVATE                      0x1
+#define DEACTIVATE                    0x2
+#define ACT_CTRL_OPCODE_ACTIVATE      0x1
+#define ACT_CTRL_OPCODE_DEACTIVATE    0x2
+#define ACT_CTRL_ACT_TRIG             0x1
+#define ACT_CTRL_OPCODE_SHIFT         0x1
+#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x2
+#define ATTR1_FIXED_SIZE_SHIFT        0x3
+#define ATTR1_PRIORITY_SHIFT          0x4
+#define ATTR1_MAX_CAP_SHIFT           0x10
+#define ATTR0_RES_WAYS_MASK           0x00000fff
+#define ATTR0_BONUS_WAYS_MASK         0x0fff0000
+#define ATTR0_BONUS_WAYS_SHIFT        0x10
+#define LLCC_STATUS_READ_DELAY 100
+
+#define CACHE_LINE_SIZE_SHIFT 6
+
+#define LLCC_COMMON_STATUS0		0x0003000c
+#define LLCC_LB_CNT_MASK		0xf0000000
+#define LLCC_LB_CNT_SHIFT		28
+
+#define MAX_CAP_TO_BYTES(n) (n * 1024)
+#define LLCC_TRP_ACT_CTRLn(n) (n * 0x1000)
+#define LLCC_TRP_STATUSn(n)   (4 + n * 0x1000)
+#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + 0x8 * n)
+#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + 0x8 * n)
+
+#define BANK_OFFSET_STRIDE	0x80000
+
+static struct llcc_drv_data *drv_data;
+
+static const struct regmap_config llcc_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.fast_io = true,
+};
+
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @uid: usecase_id for the client
+ *
+ * A pointer to llcc slice descriptor will be returned on success and
+ * and error pointer is returned on failure
+ */
+struct llcc_slice_desc *llcc_slice_getd(u32 uid)
+{
+	const struct llcc_slice_config *cfg;
+	struct llcc_slice_desc *desc;
+	u32 sz, count = 0;
+
+	cfg = drv_data->cfg;
+	sz = drv_data->cfg_size;
+
+	while (cfg && count < sz) {
+		if (cfg->usecase_id == uid)
+			break;
+		cfg++;
+		count++;
+	}
+	if (cfg == NULL || count == sz)
+		return ERR_PTR(-ENODEV);
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->slice_id = cfg->slice_id;
+	desc->slice_size = cfg->max_cap;
+
+	return desc;
+}
+EXPORT_SYMBOL_GPL(llcc_slice_getd);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+	kfree(desc);
+}
+EXPORT_SYMBOL_GPL(llcc_slice_putd);
+
+static int llcc_update_act_ctrl(u32 sid,
+				u32 act_ctrl_reg_val, u32 status)
+{
+	u32 act_ctrl_reg;
+	u32 status_reg;
+	u32 slice_status;
+	int ret = 0;
+
+	act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid);
+	status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid);
+
+	/* Set the ACTIVE trigger */
+	act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
+	ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
+	if (ret)
+		return ret;
+
+	/* Clear the ACTIVE trigger */
+	act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
+	ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
+	if (ret)
+		return ret;
+
+	ret = regmap_read_poll_timeout(drv_data->regmap, status_reg,
+	slice_status, !(slice_status & status), 0, LLCC_STATUS_READ_DELAY);
+	return ret;
+}
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value of zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	int ret;
+	u32 act_ctrl_val;
+
+	mutex_lock(&drv_data->lock);
+	if (test_bit(desc->slice_id, drv_data->bitmap)) {
+		mutex_unlock(&drv_data->lock);
+		return 0;
+	}
+
+	act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+
+	ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
+				  DEACTIVATE);
+	if (ret)
+		return ret;
+
+	__set_bit(desc->slice_id, drv_data->bitmap);
+	mutex_unlock(&drv_data->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(llcc_slice_activate);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value of zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	u32 act_ctrl_val;
+	int ret;
+
+	mutex_lock(&drv_data->lock);
+	if (!test_bit(desc->slice_id, drv_data->bitmap)) {
+		mutex_unlock(&drv_data->lock);
+		return 0;
+	}
+	act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+
+	ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
+				  ACTIVATE);
+	if (ret)
+		return ret;
+
+	__clear_bit(desc->slice_id, drv_data->bitmap);
+	mutex_unlock(&drv_data->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(llcc_slice_deactivate);
+
+/**
+ * llcc_get_slice_id - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	return desc->slice_id;
+}
+EXPORT_SYMBOL_GPL(llcc_get_slice_id);
+
+/**
+ * llcc_get_slice_size - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	return desc->slice_size;
+}
+EXPORT_SYMBOL_GPL(llcc_get_slice_size);
+
+static int qcom_llcc_cfg_program(struct platform_device *pdev)
+{
+	int i;
+	u32 attr1_cfg;
+	u32 attr0_cfg;
+	u32 attr1_val;
+	u32 attr0_val;
+	u32 max_cap_cacheline;
+	u32 sz;
+	int ret = 0;
+	const struct llcc_slice_config *llcc_table;
+	struct llcc_slice_desc desc;
+	u32 bcast_off = drv_data->bcast_off;
+
+	sz = drv_data->cfg_size;
+	llcc_table = drv_data->cfg;
+
+	for (i = 0; i < sz; i++) {
+		attr1_cfg = bcast_off +
+				LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
+		attr0_cfg = bcast_off +
+				LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
+
+		attr1_val = llcc_table[i].cache_mode;
+		attr1_val |= llcc_table[i].probe_target_ways <<
+				ATTR1_PROBE_TARGET_WAYS_SHIFT;
+		attr1_val |= llcc_table[i].fixed_size <<
+				ATTR1_FIXED_SIZE_SHIFT;
+		attr1_val |= llcc_table[i].priority << ATTR1_PRIORITY_SHIFT;
+
+		max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap);
+
+		/* LLCC instances can vary for each target.
+		 * The SW writes to broadcast register which gets propagated
+		 * to each llcc instace (llcc0,.. llccN).
+		 * Since the size of the memory is divided equally amongst the
+		 * llcc instances, we need to configure the max cap accordingly.
+		 */
+		max_cap_cacheline = max_cap_cacheline / drv_data->num_banks;
+		max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
+		attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
+
+		attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
+		attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
+
+		ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val);
+		if (ret)
+			return ret;
+		ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val);
+		if (ret)
+			return ret;
+		if (llcc_table[i].activate_on_init) {
+			desc.slice_id = llcc_table[i].slice_id;
+			ret = llcc_slice_activate(&desc);
+		}
+	}
+	return ret;
+}
+
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *llcc_cfg, u32 sz)
+{
+
+	u32 num_banks = 0;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem *base;
+	int ret = 0;
+	int i;
+
+	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	drv_data->regmap = devm_regmap_init_mmio(dev, base,
+					&llcc_regmap_config);
+	if (IS_ERR(drv_data->regmap))
+		return PTR_ERR(drv_data->regmap);
+
+	ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
+						&num_banks);
+	if (ret)
+		return ret;
+
+	num_banks &= LLCC_LB_CNT_MASK;
+	num_banks >>= LLCC_LB_CNT_SHIFT;
+	drv_data->num_banks = num_banks;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "max-slices",
+				  &drv_data->max_slices);
+	if (ret)
+		return ret;
+
+	drv_data->offsets = devm_kzalloc(dev, num_banks * sizeof(u32),
+							GFP_KERNEL);
+	if (!drv_data->offsets)
+		return -ENOMEM;
+
+	for (i = 0; i < num_banks; i++)
+		drv_data->offsets[i] = (i * BANK_OFFSET_STRIDE);
+
+	drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE;
+
+	drv_data->bitmap = devm_kcalloc(dev,
+	BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
+						GFP_KERNEL);
+	if (!drv_data->bitmap)
+		return -ENOMEM;
+
+	bitmap_zero(drv_data->bitmap, drv_data->max_slices);
+	drv_data->cfg = llcc_cfg;
+	drv_data->cfg_size = sz;
+	mutex_init(&drv_data->lock);
+	platform_set_drvdata(pdev, drv_data);
+
+	return qcom_llcc_cfg_program(pdev);
+}
+EXPORT_SYMBOL_GPL(qcom_llcc_probe);
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
new file mode 100644
index 0000000..e7ffd7a
--- /dev/null
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/platform_device.h>
+#ifndef __LLCC_QCOM__
+#define __LLCC_QCOM__
+/**
+ * llcc_slice_desc - Cache slice descriptor
+ * @slice_id: llcc slice id
+ * @slice_size: Size allocated for the llcc slice
+ */
+struct llcc_slice_desc {
+	u32 slice_id;
+	size_t slice_size;
+};
+
+/**
+ * llcc_slice_config - Data associated with the llcc slice
+ * @name: name of the use case associated with the llcc slice
+ * @usecase_id: usecase id for which the llcc slice is used
+ * @slice_id: llcc slice id assigned to each slice
+ * @max_cap: maximum capacity of the llcc slice
+ * @priority: priority of the llcc slice
+ * @fixed_size: whether the llcc slice can grow beyond its size
+ * @bonus_ways: bonus ways associated with llcc slice
+ * @res_ways: reserved ways associated with llcc slice
+ * @cache_mode: mode of the llcc slice
+ * @probe_target_ways: Probe only reserved and bonus ways on a cache miss
+ * @dis_cap_alloc: Disable capacity based allocation
+ * @retain_on_pc: Retain through power collapse
+ * @activate_on_init: activate the slice on init
+ */
+struct llcc_slice_config {
+	const char *name;
+	u32 usecase_id;
+	u32 slice_id;
+	u32 max_cap;
+	u32 priority;
+	bool fixed_size;
+	u32 bonus_ways;
+	u32 res_ways;
+	u32 cache_mode;
+	u32 probe_target_ways;
+	bool dis_cap_alloc;
+	bool retain_on_pc;
+	bool activate_on_init;
+};
+
+/**
+ * llcc_drv_data - Data associated with the llcc driver
+ * @regmap: regmap associated with the llcc device
+ * @cfg: pointer to the data structure for slice configuration
+ * @lock: mutex associated with each slice
+ * @cfg_size: size of the config data table
+ * @max_slices: max slices as read from device tree
+ * @bcast_off: Offset of the broadcast bank
+ * @num_banks: Number of llcc banks
+ * @bitmap: Bit map to track the active slice ids
+ * @offsets: Pointer to the bank offsets array
+ */
+struct llcc_drv_data {
+	struct regmap *regmap;
+	const struct llcc_slice_config *cfg;
+	struct mutex lock;
+	u32 cfg_size;
+	u32 max_slices;
+	u32 bcast_off;
+	u32 num_banks;
+	unsigned long *bitmap;
+	u32 *offsets;
+};
+
+#if IS_ENABLED(CONFIG_QCOM_LLCC)
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @uid: usecase_id of the client
+ */
+struct llcc_slice_desc *llcc_slice_getd(u32 uid);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_id - get slice id
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_size - llcc slice size
+ * @desc: Pointer to llcc slice descriptor
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc);
+
+/**
+ * qcom_llcc_probe - program the sct table
+ * @pdev: platform device pointer
+ * @table: soc sct table
+ * @sz: Size of the config table
+ */
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz);
+#else
+static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid)
+{
+	return NULL;
+}
+
+static inline void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+
+};
+
+static inline int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	return 0;
+}
+static inline int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+static inline int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz)
+{
+	return -ENODEV;
+}
+
+static inline int qcom_llcc_remove(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related

* [PATCH v6 1/2] dt-bindings: Documentation for qcom, llcc
From: Rishabh Bhatnagar @ 2018-05-08 20:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525810921-15878-1-git-send-email-rishabhb@codeaurora.org>

Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <rishabhb@codeaurora.org>
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 0000000..a586a17
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,32 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+	Usage: required
+	Value Type: <prop-encoded-array>
+	Definition: Start address and the range of the LLCC registers.
+
+- max-slices:
+	usage: required
+	Value Type: <u32>
+	Definition: Number of cache slices supported by hardware
+
+Example:
+
+	llcc: qcom,llcc at 1100000 {
+		compatible = "qcom,sdm845-llcc";
+		reg = <0x1100000 0x250000>;
+		max-slices = <32>;
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related

* [PATCH v6 0/2] SDM845 System Cache Driver
From: Rishabh Bhatnagar @ 2018-05-08 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

This series implements system cache or LLCC(Last Level Cache Controller)
driver for SDM845 SOC. The purpose of the driver is to partition the
system cache and program the settings such as priortiy, lines to probe
while doing a look up in the system cache, low power related settings etc.
The partitions are called cache slices. Each cache slice is associated
with size and SCID(System Cache ID). The driver also provides API for
clients to query the cache slice details,activate and deactivate them.

The driver can be broadly classified into:
* SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

* API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Changes since v5:
* Remove client information from DT and make driver data global.
* Check return value of llcc_update_act_ctrl function
* Change error returned from -EFAULT to -EINVAL

Changes since v4:
* Remove null pointer checks as per comments.
* Remove extra blank lines.

Changes since v3:
* Use the regmap_read_poll_timeout function
* Check for regmap read/write errors.
* Remove memory barrier after regmap write
* Derive memory bank offsets using stride macro variable
* Remove debug statements from code
* Remove the qcom_llcc_remove function
* Use if IS_ENABLED in place of ifdef for built-in module
* Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Remove unnecessary free functions
* Change the variable names as per review comments

Changes since v2:
* Corrected the Makefile to fix compilation.

Changes since v1:
* Added Makefile and Kconfig.

Changes since v0:
* Removed the syscon and simple-mfd approach
* Updated the device tree nodes to mention LLCC as a single HW block
* Moved llcc bank offsets from device tree and handled the offset
  in the driver.

ckadabi at codeaurora.org (2):
  dt-bindings: Documentation for qcom, llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt      |  32 ++
 drivers/soc/qcom/Kconfig                           |  17 ++
 drivers/soc/qcom/Makefile                          |   2 +
 drivers/soc/qcom/llcc-sdm845.c                     | 106 +++++++
 drivers/soc/qcom/llcc-slice.c                      | 335 +++++++++++++++++++++
 include/linux/soc/qcom/llcc-qcom.h                 | 162 ++++++++++
 6 files changed, 654 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH] arm: dts: atmel: graph_child_address warning fixes
From: Boris Brezillon @ 2018-05-08 20:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508135930.5768-1-robh@kernel.org>

On Tue,  8 May 2018 08:59:25 -0500
Rob Herring <robh@kernel.org> wrote:

> Addresses for graph ports and endpoints are not necessary when
> there's only a single child. Fix the following warnings removing
> unnecessary addresses on OF graph nodes:
> 
> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller: graph node has single child node 'port at 0', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /ahb/apb/hlcdc at f0030000/hlcdc-display-controller/port at 0: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /ahb/apb/isi at f0034000/port: graph node has single child node 'endpoint', #address-cells/#size-cells are not necessary
> Warning (graph_child_address): /panel/port at 0: graph node has single child node 'endpoint at 0', #address-cells/#size-cells are not necessary

Unfortunately that's not going to work, because the driver calls
drm_of_find_panel_or_bridge() with a positive port and endpoint,
not -1. While we could switch port arg from 0 to -1, that's not that
simple for the endpoint arg, because we don't know in advance how many
devices will be connected to the RGB/DPI port.

[1]https://elixir.bootlin.com/linux/v4.17-rc3/source/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c#L41

> 
> Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts | 15 ++++-----------
>  arch/arm/boot/dts/at91sam9g45.dtsi          |  2 --
>  arch/arm/boot/dts/at91sam9n12.dtsi          |  8 +-------
>  arch/arm/boot/dts/at91sam9n12ek.dts         | 14 ++++----------
>  arch/arm/boot/dts/at91sam9x5_lcd.dtsi       |  7 +------
>  arch/arm/boot/dts/at91sam9x5dm.dtsi         | 13 ++++---------
>  arch/arm/boot/dts/sama5d3.dtsi              |  2 --
>  arch/arm/boot/dts/sama5d3_lcd.dtsi          |  8 +-------
>  arch/arm/boot/dts/sama5d4.dtsi              |  8 +-------
>  9 files changed, 16 insertions(+), 61 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> index fe05aaa7ac87..72c3b077fb46 100644
> --- a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> +++ b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
> @@ -49,9 +49,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -144,16 +143,10 @@
>  		/* Actually Ampire 800480R2 */
>  		compatible = "foxlink,fl500wvr00-a0t", "simple-panel";
>  		backlight = <&backlight>;
> -		#address-cells = <1>;
> -		#size-cells = <0>;
>  		status = "okay";
>  
> -		port at 0 {
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
> index 1ee25a475be8..36729e3f2899 100644
> --- a/arch/arm/boot/dts/at91sam9g45.dtsi
> +++ b/arch/arm/boot/dts/at91sam9g45.dtsi
> @@ -1114,8 +1114,6 @@
>  				clock-names = "isi_clk";
>  				status = "disabled";
>  				port {
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  				};
>  			};
>  
> diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
> index 37cb81f457b5..a071fccb729b 100644
> --- a/arch/arm/boot/dts/at91sam9n12.dtsi
> +++ b/arch/arm/boot/dts/at91sam9n12.dtsi
> @@ -475,13 +475,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
> index c43095c5cb5c..eb0c1e11fa4d 100644
> --- a/arch/arm/boot/dts/at91sam9n12ek.dts
> +++ b/arch/arm/boot/dts/at91sam9n12ek.dts
> @@ -134,9 +134,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -246,13 +245,8 @@
>  		#size-cells = <0>;
>  		status = "okay";
>  
> -		port at 0 {
> -			reg = <0>;
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> index 1629db9dd563..e243dff67a67 100644
> --- a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> +++ b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi
> @@ -23,13 +23,8 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/at91sam9x5dm.dtsi
> index 34c089fe0bc0..5aea8fd09ad6 100644
> --- a/arch/arm/boot/dts/at91sam9x5dm.dtsi
> +++ b/arch/arm/boot/dts/at91sam9x5dm.dtsi
> @@ -29,9 +29,8 @@
>  					pinctrl-names = "default";
>  					pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
>  
> -					port at 0 {
> -						hlcdc_panel_output: endpoint at 0 {
> -							reg = <0>;
> +					port {
> +						hlcdc_panel_output: endpoint {
>  							remote-endpoint = <&panel_input>;
>  						};
>  					};
> @@ -80,12 +79,8 @@
>  		#size-cells = <0>;
>  		status = "disabled";
>  
> -		port at 0 {
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			panel_input: endpoint at 0 {
> -				reg = <0>;
> +		port {
> +			panel_input: endpoint {
>  				remote-endpoint = <&hlcdc_panel_output>;
>  			};
>  		};
> diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
> index eae5e1ee9cd8..2c51042e1f6b 100644
> --- a/arch/arm/boot/dts/sama5d3.dtsi
> +++ b/arch/arm/boot/dts/sama5d3.dtsi
> @@ -239,8 +239,6 @@
>  				clock-names = "isi_clk";
>  				status = "disabled";
>  				port {
> -					#address-cells = <1>;
> -					#size-cells = <0>;
>  				};
>  			};
>  
> diff --git a/arch/arm/boot/dts/sama5d3_lcd.dtsi b/arch/arm/boot/dts/sama5d3_lcd.dtsi
> index be7cfefc6c31..2d042d7ec531 100644
> --- a/arch/arm/boot/dts/sama5d3_lcd.dtsi
> +++ b/arch/arm/boot/dts/sama5d3_lcd.dtsi
> @@ -23,13 +23,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  
> diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi
> index 0cf9beddd556..90d7b64915ec 100644
> --- a/arch/arm/boot/dts/sama5d4.dtsi
> +++ b/arch/arm/boot/dts/sama5d4.dtsi
> @@ -333,13 +333,7 @@
>  
>  				hlcdc-display-controller {
>  					compatible = "atmel,hlcdc-display-controller";
> -					#address-cells = <1>;
> -					#size-cells = <0>;
> -
> -					port at 0 {
> -						#address-cells = <1>;
> -						#size-cells = <0>;
> -						reg = <0>;
> +					port {
>  					};
>  				};
>  

^ permalink raw reply

* [PATCH v3 1/3] leds: triggers: provide led_trigger_register_format()
From: Uwe Kleine-König @ 2018-05-08 20:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ea34ce99-d446-03d2-b38d-d40a22480337@gmail.com>

Hello Jacek,

On Tue, May 08, 2018 at 09:33:14PM +0200, Jacek Anaszewski wrote:
> Thank you for the patch. It looks fine, but please split
> the drivers/net/can/led.c related changes into a separate one.

I renamed led_trigger_rename_static() to led_trigger_rename() (and
changed the parameters). The can change just adapts the only user of
led_trigger_rename_static() to use the new one.

It's not impossible to separate this patches, but I wonder if it's worth
the effort.

The first patch would be like the patch under discussion, just without
the can bits and introducing something like:

	/*
	 * compat stuff to be removed once the only caller is converted
	 */
	static inline led_trigger_rename_static(const char *name, struct led_trigger *trig)
	{
		(void)led_trigger_rename(trig, "%s", name);
	}

Then the second patch would just be the 6-line can hunk. And a third
patch would remove the compat function. (Maybe I'd choose to squash the
two can patches together then, but this doesn't reduce the overhead
considerably.) The only upside I can see here is that it increases my
patch count, but it's otherwise not worth the effort for such an easy
change. Further more as there is a strict dependency on these three
patches this either delays the cleanup or (IMHO more likely) the can
change would go in via the led tree anyhow.  (Mark already acked patch 2
of this series and in private confirmed that the agrees to let this
change go in via the led tree, too.)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* [arm-platforms:irq/level-msi 5/13] kernel//irq/msi.c:88:26: error: 'IRQCHIP_SUPPORTS_LEVEL_MSI' undeclared; did you mean 'IRQCHIP_STATE_LINE_LEVEL'?
From: kbuild test robot @ 2018-05-08 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/level-msi
head:   0861f66578097d276094bf0c83e25c7ac0a28d2a
commit: f91d97462a9a4b2034e09826c1b758ece59646f8 [5/13] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
config: x86_64-randconfig-s5-05090145 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        git checkout f91d97462a9a4b2034e09826c1b758ece59646f8
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the arm-platforms/irq/level-msi HEAD 0861f66578097d276094bf0c83e25c7ac0a28d2a builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   In file included from arch/x86/include/asm/bug.h:83:0,
                    from include/linux/bug.h:5,
                    from include/linux/cpumask.h:13,
                    from arch/x86/include/asm/cpumask.h:5,
                    from arch/x86/include/asm/msr.h:11,
                    from arch/x86/include/asm/processor.h:21,
                    from include/linux/mutex.h:19,
                    from include/linux/kernfs.h:13,
                    from include/linux/sysfs.h:16,
                    from include/linux/kobject.h:20,
                    from include/linux/device.h:16,
                    from kernel//irq/msi.c:12:
   kernel//irq/msi.c: In function 'msi_check_level':
>> kernel//irq/msi.c:88:26: error: 'IRQCHIP_SUPPORTS_LEVEL_MSI' undeclared (first use in this function); did you mean 'IRQCHIP_STATE_LINE_LEVEL'?
        (info->chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)) &&
                             ^
   include/asm-generic/bug.h:112:25: note: in definition of macro 'WARN_ON'
     int __ret_warn_on = !!(condition);    \
                            ^~~~~~~~~
   kernel//irq/msi.c:88:26: note: each undeclared identifier is reported only once for each function it appears in
        (info->chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)) &&
                             ^
   include/asm-generic/bug.h:112:25: note: in definition of macro 'WARN_ON'
     int __ret_warn_on = !!(condition);    \
                            ^~~~~~~~~

vim +88 kernel//irq/msi.c

  > 12	#include <linux/device.h>
    13	#include <linux/irq.h>
    14	#include <linux/irqdomain.h>
    15	#include <linux/msi.h>
    16	#include <linux/slab.h>
    17	
    18	#include "internals.h"
    19	
    20	/**
    21	 * alloc_msi_entry - Allocate an initialize msi_entry
    22	 * @dev:	Pointer to the device for which this is allocated
    23	 * @nvec:	The number of vectors used in this entry
    24	 * @affinity:	Optional pointer to an affinity mask array size of @nvec
    25	 *
    26	 * If @affinity is not NULL then a an affinity array[@nvec] is allocated
    27	 * and the affinity masks from @affinity are copied.
    28	 */
    29	struct msi_desc *
    30	alloc_msi_entry(struct device *dev, int nvec, const struct cpumask *affinity)
    31	{
    32		struct msi_desc *desc;
    33	
    34		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
    35		if (!desc)
    36			return NULL;
    37	
    38		INIT_LIST_HEAD(&desc->list);
    39		desc->dev = dev;
    40		desc->nvec_used = nvec;
    41		if (affinity) {
    42			desc->affinity = kmemdup(affinity,
    43				nvec * sizeof(*desc->affinity), GFP_KERNEL);
    44			if (!desc->affinity) {
    45				kfree(desc);
    46				return NULL;
    47			}
    48		}
    49	
    50		return desc;
    51	}
    52	
    53	void free_msi_entry(struct msi_desc *entry)
    54	{
    55		kfree(entry->affinity);
    56		kfree(entry);
    57	}
    58	
    59	void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
    60	{
    61		*msg = entry->msg;
    62	}
    63	
    64	void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
    65	{
    66		struct msi_desc *entry = irq_get_msi_desc(irq);
    67	
    68		__get_cached_msi_msg(entry, msg);
    69	}
    70	EXPORT_SYMBOL_GPL(get_cached_msi_msg);
    71	
    72	#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
    73	static inline void irq_chip_write_msi_msg(struct irq_data *data,
    74						  struct msi_msg *msg)
    75	{
    76		data->chip->irq_write_msi_msg(data, msg);
    77	}
    78	
    79	static void msi_check_level(struct irq_domain *domain, struct msi_msg *msg)
    80	{
    81		struct msi_domain_info *info = domain->host_data;
    82	
    83		/*
    84		 * If the MSI provider has messed with the second message and
    85		 * not advertized that it is level-capable, signal the breakage.
    86		 */
    87		WARN_ON(!((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
  > 88			  (info->chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)) &&
    89			(msg[1].address_lo || msg[1].address_hi || msg[1].data));
    90	}
    91	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 34162 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180509/4170f43a/attachment-0001.gz>

^ permalink raw reply

* [RESEND PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability
From: Doug Anderson @ 2018-05-08 19:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508015623.GA61455@rodete-desktop-imager.corp.google.com>

Hi,

On Mon, May 7, 2018 at 6:56 PM, Brian Norris <briannorris@chromium.org> wrote:
> On Tue, May 08, 2018 at 09:36:24AM +0800, Jeffy Chen wrote:
>> On 05/08/2018 06:15 AM, Brian Norris wrote:
>> > On the other hand...this also implies there may be a race condition
>> > there, where we might lose an interrupt if there is an edge between the
>> > re-configuration of the polarity in rockchip_irq_demux() and the
>> > clearing/handling of the interrupt (handle_edge_irq() ->
>> > chip->irq_ack()). If we have an edge between there, then we might ack
>> > it, but leave the polarity such that we aren't ready for the next
>> > (inverted) edge.
>>
>> if let me guess, the unexpected irq we saw is the hardware trying to avoid
>> losing irq? for example, we set a EDGE_RISING, and the hardware saw the gpio
>> is already high, then though it might lost an irq, so fake one for safe?
>
> I won't pretend to know what the IC designers were doing, but I don't
> think that would resolve the problem I'm talking about. The sequence is
> something like:
> 1. EDGE_BOTH IRQ occurs (e.g., low to high)
> 2. reconfigure polarity in rockchip_irq_demux() (polarity=low)
> 3. continue to handle_edge_irq()
> 4. another HW edge occurs (e.g., high to low)
> 5. handle_edge_irq() (from 3) acks (clears) IRQ (before a subsequent
>    rockchip_irq_demux() gets a chance to run and flip the polarity)
> ...
>
> Now the polarity is still low, but the next trigger should be a
> low-to-high edge.
>
>> i'll try to confirm it with IC guys.

One note is that in the case Brian points at (where we need to
simulate EDGE_BOTH by swapping edges) we purposely ignored the TRM and
we needed to do that to avoid losing interrupts.  For details, see
commit 53b1bfc76df2 ("pinctrl: rockchip: Avoid losing interrupts when
supporting both edges").  We did this because:

1. We believed that the IP block in Rockchip SoCs has nearly the same
logic as "gpio-dwapb.c" and that's what "gpio-dwapb.c" did.

2. We were actually losing real interrupts and this was the only way
we could figure out how to fix it.

When I tested that back in the day I was fairly convinced that we
weren't losing any interrupts in the EDGE_BOTH case after my fix, but
I certainly could have messed up.


For the EDGE_BOTH case it was important not to lose an interrupt
because, as you guys are talking about, we could end up configured the
wrong way.  I think in your case where you're just picking one
polarity losing an interrupt shouldn't matter since it's undefined
exactly if an edge happens while you're in the middle of executing
rockchip_irq_set_type().  Is that right?


-Doug

^ permalink raw reply

* [PATCH v2 26/27] coresight: perf: Remove reset_buffer call back for sinks
From: Mathieu Poirier @ 2018-05-08 19:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525165857-11096-27-git-send-email-suzuki.poulose@arm.com>

On Tue, May 01, 2018 at 10:10:56AM +0100, Suzuki K Poulose wrote:
> Right now we issue an update_buffer() and reset_buffer() call backs
> in succession when we stop tracing an event. The update_buffer is
> supposed to check the status of the buffer and make sure the ring buffer
> is updated with the trace data. And we store information about the
> size of the data collected only to be consumed by the reset_buffer
> callback which always follows the update_buffer. This was originally
> designed for handling future IPs which could trigger a buffer overflow
> interrupt. This patch gets rid of the reset_buffer callback altogether
> and performs the actions in update_buffer, making it return the size
> collected. We can always add the support for handling the overflow
> interrupt case later.
> 
> This removes some not-so pretty hack (storing the new head in the
> size field for snapshot mode) and cleans it up a little bit.

IPs with an overflow interrupts will be arriving shortly, so it is not like the
future is uncertain - they are coming.  Right now the logic is there - I don't
see a real need to consolidate things only to split it again in the near future.

I agree the part about overloading buf->data_size with the head of the ring
buffer when operating in snapshot mode isn't pretty (though well documented).
If anything that can be improve, i.e add a buf->head and things will be clear.
Once again this could be part of another patchset.

> 
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  drivers/hwtracing/coresight/coresight-etb10.c    | 56 +++++------------------
>  drivers/hwtracing/coresight/coresight-etm-perf.c |  9 +---
>  drivers/hwtracing/coresight/coresight-tmc-etf.c  | 58 +++++-------------------
>  include/linux/coresight.h                        |  5 +-
>  4 files changed, 26 insertions(+), 102 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index d9c2f87..b13712a 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -322,37 +322,7 @@ static int etb_set_buffer(struct coresight_device *csdev,
>  	return ret;
>  }
>  
> -static unsigned long etb_reset_buffer(struct coresight_device *csdev,
> -				      struct perf_output_handle *handle,
> -				      void *sink_config)
> -{
> -	unsigned long size = 0;
> -	struct cs_buffers *buf = sink_config;
> -
> -	if (buf) {
> -		/*
> -		 * In snapshot mode ->data_size holds the new address of the
> -		 * ring buffer's head.  The size itself is the whole address
> -		 * range since we want the latest information.
> -		 */
> -		if (buf->snapshot)
> -			handle->head = local_xchg(&buf->data_size,
> -						  buf->nr_pages << PAGE_SHIFT);
> -
> -		/*
> -		 * Tell the tracer PMU how much we got in this run and if
> -		 * something went wrong along the way.  Nobody else can use
> -		 * this cs_buffers instance until we are done.  As such
> -		 * resetting parameters here and squaring off with the ring
> -		 * buffer API in the tracer PMU is fine.
> -		 */
> -		size = local_xchg(&buf->data_size, 0);
> -	}
> -
> -	return size;
> -}
> -
> -static void etb_update_buffer(struct coresight_device *csdev,
> +static unsigned long etb_update_buffer(struct coresight_device *csdev,
>  			      struct perf_output_handle *handle,
>  			      void *sink_config)
>  {
> @@ -361,13 +331,13 @@ static void etb_update_buffer(struct coresight_device *csdev,
>  	u8 *buf_ptr;
>  	const u32 *barrier;
>  	u32 read_ptr, write_ptr, capacity;
> -	u32 status, read_data, to_read;
> -	unsigned long offset;
> +	u32 status, read_data;
> +	unsigned long offset, to_read;
>  	struct cs_buffers *buf = sink_config;
>  	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>  
>  	if (!buf)
> -		return;
> +		return 0;
>  
>  	capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
>  
> @@ -472,18 +442,17 @@ static void etb_update_buffer(struct coresight_device *csdev,
>  	writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
>  
>  	/*
> -	 * In snapshot mode all we have to do is communicate to
> -	 * perf_aux_output_end() the address of the current head.  In full
> -	 * trace mode the same function expects a size to move rb->aux_head
> -	 * forward.
> +	 * In snapshot mode we have to update the handle->head to point
> +	 * to the new location.
>  	 */
> -	if (buf->snapshot)
> -		local_set(&buf->data_size, (cur * PAGE_SIZE) + offset);
> -	else
> -		local_add(to_read, &buf->data_size);
> -
> +	if (buf->snapshot) {
> +		handle->head = (cur * PAGE_SIZE) + offset;
> +		to_read = buf->nr_pages << PAGE_SHIFT;
> +	}
>  	etb_enable_hw(drvdata);
>  	CS_LOCK(drvdata->base);
> +
> +	return to_read;
>  }
>  
>  static const struct coresight_ops_sink etb_sink_ops = {
> @@ -492,7 +461,6 @@ static const struct coresight_ops_sink etb_sink_ops = {
>  	.alloc_buffer	= etb_alloc_buffer,
>  	.free_buffer	= etb_free_buffer,
>  	.set_buffer	= etb_set_buffer,
> -	.reset_buffer	= etb_reset_buffer,
>  	.update_buffer	= etb_update_buffer,
>  };
>  
> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> index 4e5ed65..5096def 100644
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> @@ -342,15 +342,8 @@ static void etm_event_stop(struct perf_event *event, int mode)
>  		if (!sink_ops(sink)->update_buffer)
>  			return;
>  
> -		sink_ops(sink)->update_buffer(sink, handle,
> +		size = sink_ops(sink)->update_buffer(sink, handle,
>  					      event_data->snk_config);
> -
> -		if (!sink_ops(sink)->reset_buffer)
> -			return;
> -
> -		size = sink_ops(sink)->reset_buffer(sink, handle,
> -						    event_data->snk_config);
> -
>  		perf_aux_output_end(handle, size);
>  	}
>  
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 0a32734..75ef5c4 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -360,36 +360,7 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
>  	return ret;
>  }
>  
> -static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
> -					  struct perf_output_handle *handle,
> -					  void *sink_config)
> -{
> -	long size = 0;
> -	struct cs_buffers *buf = sink_config;
> -
> -	if (buf) {
> -		/*
> -		 * In snapshot mode ->data_size holds the new address of the
> -		 * ring buffer's head.  The size itself is the whole address
> -		 * range since we want the latest information.
> -		 */
> -		if (buf->snapshot)
> -			handle->head = local_xchg(&buf->data_size,
> -						  buf->nr_pages << PAGE_SHIFT);
> -		/*
> -		 * Tell the tracer PMU how much we got in this run and if
> -		 * something went wrong along the way.  Nobody else can use
> -		 * this cs_buffers instance until we are done.  As such
> -		 * resetting parameters here and squaring off with the ring
> -		 * buffer API in the tracer PMU is fine.
> -		 */
> -		size = local_xchg(&buf->data_size, 0);
> -	}
> -
> -	return size;
> -}
> -
> -static void tmc_update_etf_buffer(struct coresight_device *csdev,
> +static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
>  				  struct perf_output_handle *handle,
>  				  void *sink_config)
>  {
> @@ -398,17 +369,17 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
>  	const u32 *barrier;
>  	u32 *buf_ptr;
>  	u64 read_ptr, write_ptr;
> -	u32 status, to_read;
> -	unsigned long offset;
> +	u32 status;
> +	unsigned long offset, to_read;
>  	struct cs_buffers *buf = sink_config;
>  	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>  
>  	if (!buf)
> -		return;
> +		return 0;
>  
>  	/* This shouldn't happen */
>  	if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))
> -		return;
> +		return 0;
>  
>  	CS_UNLOCK(drvdata->base);
>  
> @@ -497,18 +468,14 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
>  		}
>  	}
>  
> -	/*
> -	 * In snapshot mode all we have to do is communicate to
> -	 * perf_aux_output_end() the address of the current head.  In full
> -	 * trace mode the same function expects a size to move rb->aux_head
> -	 * forward.
> -	 */
> -	if (buf->snapshot)
> -		local_set(&buf->data_size, (cur * PAGE_SIZE) + offset);
> -	else
> -		local_add(to_read, &buf->data_size);
> -
> +	/* In snapshot mode we have to update the head */
> +	if (buf->snapshot) {
> +		handle->head = (cur * PAGE_SIZE) + offset;
> +		to_read = buf->nr_pages << PAGE_SHIFT;
> +	}
>  	CS_LOCK(drvdata->base);
> +
> +	return to_read;
>  }
>  
>  static const struct coresight_ops_sink tmc_etf_sink_ops = {
> @@ -517,7 +484,6 @@ static const struct coresight_ops_sink tmc_etf_sink_ops = {
>  	.alloc_buffer	= tmc_alloc_etf_buffer,
>  	.free_buffer	= tmc_free_etf_buffer,
>  	.set_buffer	= tmc_set_etf_buffer,
> -	.reset_buffer	= tmc_reset_etf_buffer,
>  	.update_buffer	= tmc_update_etf_buffer,
>  };
>  
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index c0e1568..41b3729 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -212,10 +212,7 @@ struct coresight_ops_sink {
>  	int (*set_buffer)(struct coresight_device *csdev,
>  			  struct perf_output_handle *handle,
>  			  void *sink_config);
> -	unsigned long (*reset_buffer)(struct coresight_device *csdev,
> -				      struct perf_output_handle *handle,
> -				      void *sink_config);
> -	void (*update_buffer)(struct coresight_device *csdev,
> +	unsigned long (*update_buffer)(struct coresight_device *csdev,
>  			      struct perf_output_handle *handle,
>  			      void *sink_config);
>  };
> -- 
> 2.7.4
> 

^ permalink raw reply


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