Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Re: Hardcoded instruction causes certain features to fail on ARM platfrom due to endianness
From: Dave Martin @ 2012-10-16 12:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKw8HL154a=K9O7CzPFZ-EqtT+BxYU-uRHodtutdRfYmNpWVww@mail.gmail.com>

On Mon, Oct 15, 2012 at 11:33:08PM +0800, Fei Yang wrote:
> 2012/10/15 Mikael Pettersson <mikpe@it.uu.se>:
> > Yangfei (Felix) writes:
> >  > Hi all,
> >  >
> >  >     I found that hardcoded instruction in inline asm can cause certains certain features fail to work on ARM platform due to endianness.
> >  >     As an example, consider the following code snippet of platform_do_lowpower function from arch/arm/mach-realview/hotplug.c:
> >  >                 / *
> >  >                  * here's the WFI
> >  >                  */
> >  >                 asm(".word      0xe320f003\n"
> >  >                     :
> >  >                     :
> >  >                     : "memory", "cc");
> >  >
> >  >     The instruction generated from this inline asm will not work on big-endian ARM platform, such as ARM BE-8 format. Instead, an exception will be generated.
> >  >
> >  >     Here the code should be:
> >  >                 / *
> >  >                  * here's the WFI
> >  >                  */
> >  >                 asm("WFI\n"
> >  >                     :
> >  >                     :
> >  >                     : "memory", "cc");
> >  >
> >  >     Seems the kernel doesn't support ARM BE-8 well. I don't know why this problem happens.
> >  >     Can anyone tell me who owns this part? I can prepare a patch then.
> >  >     Thanks.
> >
> > Questions regarding the ARM kernel should go to the linux-arm-kernel mailing list
> > (see the MAINTAINERS file), with an optional cc: to the regular LKML.
> >
> > BE-8 is, if I recall correctly, ARMv7's broken format where code and data have
> > different endianess.  GAS supports an ".inst" directive which is like ".word"
> > except the data is assumed to be code.  This matters for disassembly, and may
> > also be required for BE-8.
> >
> > That is, just s/.word/.inst/g above and report back if that works or not.
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> >
> >
> 
> Hi Mikael,
> 
> Thanks for the reply. I modified the code as suggested and rebuilt the
> kernel, cpu-hotplug feature now works on big-endian(BE-8) ARM
> platform.
> Since the ARM core can be configured by system software to work in
> big-endian mode, it's necessary to fix this problem. And here is a
> small patch :
> 
> diff -urN linux-3.6.2/arch/arm/mach-exynos/hotplug.c
> linux/arch/arm/mach-exynos/hotplug.c
> --- linux-3.6.2/arch/arm/mach-exynos/hotplug.c	2012-10-13
> 04:50:59.000000000 +0800
> +++ linux/arch/arm/mach-exynos/hotplug.c	2012-10-15 23:05:44.000000000 +0800
> @@ -72,7 +72,7 @@
>  		/*
>  		 * here's the WFI
>  		 */
> -		asm(".word	0xe320f003\n"
> +		asm(".inst	0xe320f003\n"

The cleanest fix would simply be to build these files with appropriate
modified CFLAGS (-march=armv6k or -march=armv7-a), and use the proper
"wfi" mnemonic.

Failing that, you could use the facilities in <asm/opcodes.h> to
declare a wrapper macro for injecting this opcode (see
<asm/opcodes-virt.h> for an example).  However, putting custom
opcodes into the assembler should only be done if it's really
necessary.  Nowadays, I think we can consider tools which don't
understand the WFI mnemonic to be obsolete, at least for platforms
which only build for v7 and above.

The relevant board maintainers would need to sign off on such a
change, so we don't end up breaking their builds.

If any of these boards needs to build for v6K, the custom opcode might
be worth it -- some people might just possibly be relying on older tools
for such platforms.

Cheers
---Dave

>  		    :
>  		    :
>  		    : "memory", "cc");
> diff -urN linux-3.6.2/arch/arm/mach-realview/hotplug.c
> linux/arch/arm/mach-realview/hotplug.c
> --- linux-3.6.2/arch/arm/mach-realview/hotplug.c	2012-10-13
> 04:50:59.000000000 +0800
> +++ linux/arch/arm/mach-realview/hotplug.c	2012-10-15 23:05:00.000000000 +0800
> @@ -66,7 +66,7 @@
>  		/*
>  		 * here's the WFI
>  		 */
> -		asm(".word	0xe320f003\n"
> +		asm(".inst	0xe320f003\n"
>  		    :
>  		    :
>  		    : "memory", "cc");
> diff -urN linux-3.6.2/arch/arm/mach-shmobile/hotplug.c
> linux/arch/arm/mach-shmobile/hotplug.c
> --- linux-3.6.2/arch/arm/mach-shmobile/hotplug.c	2012-10-13
> 04:50:59.000000000 +0800
> +++ linux/arch/arm/mach-shmobile/hotplug.c	2012-10-15 23:05:25.000000000 +0800
> @@ -53,7 +53,7 @@
>  		/*
>  		 * here's the WFI
>  		 */
> -		asm(".word	0xe320f003\n"
> +		asm(".inst	0xe320f003\n"
>  		    :
>  		    :
>  		    : "memory", "cc");
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 2/2] ARM: unwind: enable dumping stacks for SMP && ARM_UNWIND
From: Dave Martin @ 2012-10-16 12:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016105504.GD21164@n2100.arm.linux.org.uk>

On Tue, Oct 16, 2012 at 11:55:04AM +0100, Russell King - ARM Linux wrote:
> On Tue, Oct 16, 2012 at 11:12:01AM +0100, Dave Martin wrote:
> > On Mon, Oct 15, 2012 at 07:15:31PM -0700, Colin Cross wrote:
> > > About half the callers to unwind_frame end up limiting the number of
> > > frames they will follow before giving up, so I wasn't sure if I should
> > > put an arbitrary limit in unwind_frame or just make sure all callers
> > > are bounded.  Your idea of limiting same sp frames instead of total
> > > frames sounds better.  I can send a new patch that adds a new field to
> > > struct stackframe (which will need to be initialized everywhere, the
> > > struct is usually on the stack) and limits the recursion.  Any
> > > suggestion on the recursion limit?  I would never expect to see a real
> > > situation with more than a few, but on the other hand parsing the
> > > frames should be pretty fast so a high number (100?) shouldn't cause
> > > any user visible effect.
> > 
> > Talking to some tools guys about this, it sounds like there really
> > shouldn't be any stackless frame except for the leaf frame.  If there are
> > stackless functions they will probably not be visible in the frame chain
> > at all.  So it might make sense to have a pretty small limit.  Maybe it
> > could even be 1.  Cartainly a small number.
> > 
> > We should also add a check for whether the current and frame and previous
> > frame appear identical and abort if that's the case, if we don't do that
> > already.
> 
> The case that actually worries me is not the "end up looping for ever"
> case, but the effects of having the stack change while the unwinder is
> reading from it - for example:
> 
>                 /* pop R4-R15 according to mask */
>                 load_sp = mask & (1 << (13 - 4));
>                 while (mask) {
>                         if (mask & 1)
>                                 ctrl->vrs[reg] = *vsp++;
>                         mask >>= 1;
>                         reg++;
>                 }
> 
> Remember that for a running thread, the stack will be changing all the
> time while another CPU tries to read it to do the unwind, and also
> remember that the bottom of stack isn't really known.  All you have is
> the snapshot of the registers when the thread was last stopped by the
> scheduler, and that state probably isn't valid.

So long as the unwinder enforces continuous progress towards a fixed
limit, sooner or later the supposed bottom of the stack will be reached,
or the unwinder will encounter something which is recognised as garbage
and stop.

This the best we can hope for if trying to print a backtrace for a
thread without stopping it...  which admittedly seems quite a dodgy
thing to attempt.

Colin, what are the scenarios when we want to backtrace a thread while
it is actually running?

> So what you're asking is for the unwinder to produce a backtrace from
> a kernel stack which is possibly changing beneath it from an unknown
> current state.
> 
> This doesn't sound like a particularly bright thing to be doing...

Nonetheless, the changes are relevant to normal stack dumping too, since
when we take a fault the sp or stack may be corrupted, even if the
thread in question is stopped.  Being more robust against infinte loops
etc., still seems like a good idea ?

Cheers
---Dave

^ permalink raw reply

* [PATCH] mmc: mmci: Fixup and cleanup code for DMA handling
From: Ulf Hansson @ 2012-10-16 11:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZPbrvfk0QNB7x8YZ+DVibPJMTLsLDSf310CcBEeOTuww@mail.gmail.com>

On 16 October 2012 10:17, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Oct 16, 2012 at 9:16 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
>> This code has not been tested on a "legacy" ARM PL180 but only for
>> ux500 boards. Even if it should affect DMA handling we should test
>> this properly. Would be great if you were able to help out, I guess
>> you still have available hardware for these tests?
>
> I can test the Integrator/CP and Realview in IRQ/PIO mode and
> the U300 in DMA mode.

Great!

>
> I need some help to provoke errorpath in DMA mode though,
> so any hints are welcome...

One good option could be to stress test card insert/removal sequences,
while at the same time doing read/write requests.

>
> Yours,
> Linus Walleij

Kind regards
Ulf Hansson

^ permalink raw reply

* [PATCH 00/11] Minimum set of omap serial patches to fix merge window breakage
From: Russell King - ARM Linux @ 2012-10-16 11:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

On Tue, Oct 16, 2012 at 11:14:58AM +0100, Russell King - ARM Linux wrote:
> During the merge window, a series of patches from various people went in,
> allegedly fixing various problems with the OMAP serial driver.
> 
> Unfortunately, there was not a full understanding of the issues I brought
> up here back in April, and so the "fixes", while being individually
> correct, result in a worse situation with the driver than before.
> 
> Specifically, this patch:
> 
> commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6
> Author: Vikram Pandita <vikram.pandita@ti.com>
> Date:   Thu Sep 6 15:45:37 2012 +0300
> 
>     serial: omap: fix software flow control
> 
>     Software flow control register bits were not defined correctly.
> 
>     Also clarify the IXON and IXOFF logic to reflect what userspace wants.
> 
> does what it says on the tin - it fixes the register definitions so that
> we do end up enabling the right two software flow control bits.
> 
> The down side is that there are other bugs in this area which have been
> exposed.  For example:
> 
> 1. the XON/XOFF registers aren't written to; their address is, but we will
>    not be writing to the right registers because their access rules are not
>    respected by the driver.  These are by default zero.
> 
>    This means that with hardware assisted software flow control enabled,
>    the port will now transmit an 0x00 byte for XON and XOFF events.
> 
> 2. the driver set_termios function is not called for changes in software
>    flow control settings if not accompanied by some other change.
> 
> 3. the there isn't actually a way for the hardware assisted flow control
>    to be used other than by increasing interrupt latency to cause the
>    receiver hardware FIFO to fill.  This will cause 0x00 bytes to be
>    transmitted.
> 
> There are two options to resolve this.  The first one is to revert this
> patch to bring the driver back down to the pre-merge window state.  The
> other is to apply this series of patches, which frankly I don't think
> is -rc material, even with the above regressions.
> 
> Given that the above regressions were caused by a lack of due care and
> correct process (I had declared to TI that I had investigated these
> issues back in April), I believe that the right answer is to revert at
> least commit 957ee7270d, which should re-hide these other bugs in the
> driver.

Note: these patches are not as well validated as my previous set; I
haven't even build-tested just this set, but only my full set.  YMMV.

^ permalink raw reply

* [PATCH] slab : allow SLAB_RED_ZONE and SLAB_STORE_USER to work on arm
From: Matthieu CASTET @ 2012-10-16 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: Matthieu CASTET <castet.matthieu@free.fr>

on cortexA8 (omap3) ralign is 64 and __alignof__(unsigned long long) is 8.
So we always disable debug.

This patch is based on 5c5e3b33b7cb959a401f823707bee006caadd76e, but fix
case were align < sizeof(unsigned long long).

Signed-off-by: Matthieu Castet <matthieu.castet@parrot.com>
CC: Russell King <rmk@arm.linux.org.uk>
CC: Pekka Enberg <penberg@cs.helsinki.fi>
---
 mm/slab.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index c685475..8427901 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2462,9 +2462,6 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 	if (ralign < align) {
 		ralign = align;
 	}
-	/* disable debug if necessary */
-	if (ralign > __alignof__(unsigned long long))
-		flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 	/*
 	 * 4) Store it.
 	 */
@@ -2491,8 +2488,9 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 	 */
 	if (flags & SLAB_RED_ZONE) {
 		/* add space for red zone words */
-		cachep->obj_offset += sizeof(unsigned long long);
-		size += 2 * sizeof(unsigned long long);
+		int offset = max(align, sizeof(unsigned long long));
+		cachep->obj_offset += offset;
+		size += offset + sizeof(unsigned long long);
 	}
 	if (flags & SLAB_STORE_USER) {
 		/* user store requires one word storage behind the end of
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 10/11] SERIAL: omap: fix MCR TCRTLR bit handling
From: Russell King - ARM Linux @ 2012-10-16 11:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1TO4tW-0000Wl-SY@rmk-PC.arm.linux.org.uk>

On Tue, Oct 16, 2012 at 12:01:06PM +0100, Russell King wrote:
> The MCR TCRTLR bit can only be changed when ECB is set in the EFR.
> Unfortunately, several places were trying to alter this bit while ECB
> was clear:
> 
> - serial_omap_configure_xonxoff() was attempting to clear the bit after
>   explicitly clearing the ECB bit.
> - serial_omap_set_termios() was trying the same trick after setting the
>   SCR, and when trying to change the TCR register when hardware flow
>   control was enabled.
> 
> Fix this by ensuring that we always have ECB set whenever the TCRTLR bit
> is changed.
> 
> Moreover, we start out by reading the EFR and MCR registers, which may
> have indeterminent bit settings for the ECB and TCRTLR bits.  Ensure
> that these bits always start off in a known state.

Note - this patch unfortunately exposes some of the bugs in their full
glory as we now write to the correct registers and actually end up
programming the hardware correctly.

I've reduced the window as far as possible by putting this one next to
patch 11 which fixes it, but no amount of reordering can hide some kind
of breakage along the way.

> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/tty/serial/omap-serial.c |   32 ++++++++++++++++++--------------
>  1 files changed, 18 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
> index 537829f..7cc151c 100644
> --- a/drivers/tty/serial/omap-serial.c
> +++ b/drivers/tty/serial/omap-serial.c
> @@ -706,9 +706,10 @@ serial_omap_configure_xonxoff
>  	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
>  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
>  	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
> -	serial_out(up, UART_EFR, up->efr);
>  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
>  	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
> +	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> +	serial_out(up, UART_EFR, up->efr);
>  	serial_out(up, UART_LCR, up->lcr);
>  }
>  
> @@ -729,7 +730,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>  {
>  	struct uart_omap_port *up = to_uart_omap_port(port);
>  	unsigned char cval = 0;
> -	unsigned char efr = 0;
>  	unsigned long flags = 0;
>  	unsigned int baud, quot;
>  
> @@ -839,12 +839,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>  
>  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
>  
> -	up->efr = serial_in(up, UART_EFR);
> +	up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB;
>  	up->efr &= ~UART_EFR_SCD;
>  	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
>  
>  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
> -	up->mcr = serial_in(up, UART_MCR);
> +	up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR;
>  	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
>  	/* FIFO ENABLE, DMA MODE */
>  
> @@ -863,9 +863,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>  
>  	serial_out(up, UART_OMAP_SCR, up->scr);
>  
> -	serial_out(up, UART_EFR, up->efr);
> +	/* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
>  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
>  	serial_out(up, UART_MCR, up->mcr);
> +	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> +	serial_out(up, UART_EFR, up->efr);
> +	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
>  
>  	/* Protocol, Baud Rate, and Interrupt Settings */
>  
> @@ -904,20 +907,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
>  	/* Hardware Flow Control Configuration */
>  
>  	if (termios->c_cflag & CRTSCTS) {
> -		efr |= (UART_EFR_CTS | UART_EFR_RTS);
> -		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
> -
> -		up->mcr = serial_in(up, UART_MCR);
> -		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
> -
> +		/* Enable access to TCR/TLR */
>  		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> -		up->efr = serial_in(up, UART_EFR);
>  		serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
> +		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
> +		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
>  
>  		serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
> -		serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
> -		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
> +
> +		/* Enable AUTORTS and AUTOCTS */
> +		up->efr |= UART_EFR_CTS | UART_EFR_RTS;
> +
> +		/* Disable access to TCR/TLR */
>  		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
> +		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> +		serial_out(up, UART_EFR, up->efr);
>  		serial_out(up, UART_LCR, cval);
>  	} else {
>  		/* Disable AUTORTS and AUTOCTS */
> -- 
> 1.7.4.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [Linaro-mm-sig] [RFC 0/2] DMA-mapping & IOMMU - physically contiguous allocations
From: Inki Dae @ 2012-10-16 11:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016103109.GA21164@n2100.arm.linux.org.uk>

Hi Russell,

2012/10/16 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Tue, Oct 16, 2012 at 07:12:49PM +0900, Inki Dae wrote:
>> Hi Hiroshi,
>>
>> I'm not sure I understand what you mean but we had already tried this
>> way and for this, you can refer to below link,
>>                http://www.mail-archive.com/dri-devel at lists.freedesktop.org/msg22555.html
>>
>> but this way had been pointed out by drm guys because the pages could
>> be used through gem object after that pages had been freed by free()
>> anyway their pointing was reasonable and I'm trying another way, this
>> is the way that the pages to user space has same life time with dma
>> operation. in other word, if dma completed access to that pages then
>> also that pages will be freed. actually drm-based via driver of
>> mainline kernel is using same way
>
> I don't know about Hiroshi, but the above "sentence" - and I mean the 7
> line sentence - is very difficult to understand and wears readers out.
>

Sorry for this. Please see below comments.

> If your GPU hardware has a MMU, then the problem of dealing with userspace
> pages is very easy.  Do it the same way that the i915 driver and the rest
> of DRM does.  Use shmem backed memory.
>
> I'm doing that for the Dove DRM driver and it works a real treat, and as
> the pages are backed by page cache pages, you can use all the normal
> page refcounting on them to prevent them being freed until your DMA has
> completed.  All my X pixmaps are shmem backed drm objects, except for
> the scanout buffers which are dumb drm objects (because they must be
> contiguous.)
>
> In fact, get_user_pages() will take the reference for you before you pass
> them over to dma_map_sg().  On completion of DMA, you just need to use
> dma_unmap_sg() and release each page.
>

It's exactly same as ours. Besides, I know get_user_pages() takes 2
reference counts if the user process has never accessed user region
allocated by malloc(). Then, if the user calls free(), the page
reference count becomes 1 and becomes 0 with put_page() call. And the
reverse holds as well. This means how the pages backed are used by dma
and freed. dma_map_sg() just does cache operation properly and maps
these pages with iommu table. There may be my missing point.

Thanks,
Inki Dae

> If you don't want to use get_user_pages() (which other drivers don't) then
> you need to following the i915 example and get each page out of shmem
> individually.
>
> (My situation on the Dove hardware is a little different, because the
> kernel DRM driver isn't involved with the GPU - it merely provides the
> memory for pixmaps.  The GPU software stack, being a chunk of closed
> source userspace library with open source kernel driver, means that
> things are more complicated; the kernel side GPU driver uses
> get_user_pages() to pin them prior to building the GPU's MMU table.)
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo at kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email at kvack.org </a>

^ permalink raw reply

* [PATCH v3 2/2] i2c: change id to let i2c-at91 work
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-16 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507D361C.6020403@atmel.com>

On 18:25 Tue 16 Oct     , Bo Shen wrote:
> Hi J,
> 
> On 10/16/2012 16:39, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >On 11:13 Tue 16 Oct     , Bo Shen wrote:
> >>Hi J,
> >>
> >>On 10/15/2012 23:02, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >>>On 17:30 Mon 15 Oct     , Bo Shen wrote:
> >>>>The i2c core driver will turn the platform device ID to busnum
> >>>>When using platfrom device ID as -1, it means dynamically assigned
> >>>>the busnum. When writing code, we need to make sure the busnum,
> >>>>and call i2c_register_board_info(int busnum, ...) to register device
> >>>>if using -1, we do not know the value of busnum
> >>>>	
> >>>>In order to solve this issue, set the platform device ID as a fix number
> >>>>Here using 0 to match the busnum used in i2c_regsiter_board_info()
> >>>>
> >>>>Signed-off-by: Bo Shen <voice.shen@atmel.com>
> >>>>---
> >>>
> >>>can you check when this append for the first time to schedule a patch for stable too
> >>
> >>OK. I will resend it and add linux stable into the cc list.
> >no this not how it work
> >
> >I ask you to check which patch add the regression and then when this is
> >applied in the kernel we will request greg to apply it too to the stable
> 
> The code is using id = -1 appear 4 years ago. And after dig, I don't
> find which patch cause this the regression.
so use git bisect to find the commit responsible

Best Regards,
J.

^ permalink raw reply

* [PATCH 11/11] SERIAL: omap: fix hardware assisted flow control
From: Russell King @ 2012-10-16 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

When the UART device has hardware flow control enabled, it ignores the
MCR RTS bit in the MCR register, and keeps RTS asserted as long as we
continue to read characters from the UART receiver FIFO.  This means
that when the TTY buffers become full, the UART doesn't tell the remote
end to stop sending, which causes the TTY layer to start dropping
characters.

A similar problem exists with software flow control.  We need the FIFO
register to fill when software flow control is enabled to provoke the
UART to send the XOFF character.

Fix this by implementing the throttle/unthrottle callbacks, and use
these to disable receiver interrupts.  This in turn means that the UART
FIFO will fill, which will then cause the UART's hardware to deassert
the RTS signal and/or send the XOFF character, stopping the remote end.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7cc151c..aabc94d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -303,6 +303,34 @@ static void serial_omap_start_tx(struct uart_port *port)
 	pm_runtime_put_autosuspend(up->dev);
 }
 
+static void serial_omap_throttle(struct uart_port *port)
+{
+	struct uart_omap_port *up = to_uart_omap_port(port);
+	unsigned long flags;
+
+	pm_runtime_get_sync(up->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+}
+
+static void serial_omap_unthrottle(struct uart_port *port)
+{
+	struct uart_omap_port *up = to_uart_omap_port(port);
+	unsigned long flags;
+
+	pm_runtime_get_sync(up->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->ier |= UART_IER_RLSI | UART_IER_RDI;
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+}
+
 static unsigned int check_modem_status(struct uart_omap_port *up)
 {
 	unsigned int status;
@@ -1000,6 +1028,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags)
 	dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
 							up->port.line);
 	up->port.type = PORT_OMAP;
+	up->port.flags |= UPF_SOFT_FLOW | UPF_HARD_FLOW;
 }
 
 static int
@@ -1203,6 +1232,8 @@ static struct uart_ops serial_omap_pops = {
 	.get_mctrl	= serial_omap_get_mctrl,
 	.stop_tx	= serial_omap_stop_tx,
 	.start_tx	= serial_omap_start_tx,
+	.throttle	= serial_omap_throttle,
+	.unthrottle	= serial_omap_unthrottle,
 	.stop_rx	= serial_omap_stop_rx,
 	.enable_ms	= serial_omap_enable_ms,
 	.break_ctl	= serial_omap_break_ctl,
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 10/11] SERIAL: omap: fix MCR TCRTLR bit handling
From: Russell King @ 2012-10-16 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

The MCR TCRTLR bit can only be changed when ECB is set in the EFR.
Unfortunately, several places were trying to alter this bit while ECB
was clear:

- serial_omap_configure_xonxoff() was attempting to clear the bit after
  explicitly clearing the ECB bit.
- serial_omap_set_termios() was trying the same trick after setting the
  SCR, and when trying to change the TCR register when hardware flow
  control was enabled.

Fix this by ensuring that we always have ECB set whenever the TCRTLR bit
is changed.

Moreover, we start out by reading the EFR and MCR registers, which may
have indeterminent bit settings for the ECB and TCRTLR bits.  Ensure
that these bits always start off in a known state.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |   32 ++++++++++++++++++--------------
 1 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 537829f..7cc151c 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -706,9 +706,10 @@ serial_omap_configure_xonxoff
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-	serial_out(up, UART_EFR, up->efr);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, up->efr);
 	serial_out(up, UART_LCR, up->lcr);
 }
 
@@ -729,7 +730,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
 	unsigned char cval = 0;
-	unsigned char efr = 0;
 	unsigned long flags = 0;
 	unsigned int baud, quot;
 
@@ -839,12 +839,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
-	up->efr = serial_in(up, UART_EFR);
+	up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB;
 	up->efr &= ~UART_EFR_SCD;
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-	up->mcr = serial_in(up, UART_MCR);
+	up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR;
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	/* FIFO ENABLE, DMA MODE */
 
@@ -863,9 +863,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	serial_out(up, UART_OMAP_SCR, up->scr);
 
-	serial_out(up, UART_EFR, up->efr);
+	/* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, up->efr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	/* Protocol, Baud Rate, and Interrupt Settings */
 
@@ -904,20 +907,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	/* Hardware Flow Control Configuration */
 
 	if (termios->c_cflag & CRTSCTS) {
-		efr |= (UART_EFR_CTS | UART_EFR_RTS);
-		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
-		up->mcr = serial_in(up, UART_MCR);
-		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
-
+		/* Enable access to TCR/TLR */
 		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-		up->efr = serial_in(up, UART_EFR);
 		serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 
 		serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-		serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
-		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+
+		/* Enable AUTORTS and AUTOCTS */
+		up->efr |= UART_EFR_CTS | UART_EFR_RTS;
+
+		/* Disable access to TCR/TLR */
 		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+		serial_out(up, UART_EFR, up->efr);
 		serial_out(up, UART_LCR, cval);
 	} else {
 		/* Disable AUTORTS and AUTOCTS */
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 09/11] SERIAL: omap: fix set_mctrl() breakage
From: Russell King @ 2012-10-16 11:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

c538d20c7f (and maybe previous commits) broke set_mctrl() by making
it only capable of setting bits in the MCR register.  This prevents
software controlled flow control and modem control line manipulation
via TIOCMSET/TIOCMBIC from working correctly.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index c8a0425..537829f 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -504,7 +504,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
 static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
-	unsigned char mcr = 0;
+	unsigned char mcr = 0, old_mcr;
 
 	dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
 	if (mctrl & TIOCM_RTS)
@@ -519,8 +519,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 		mcr |= UART_MCR_LOOP;
 
 	pm_runtime_get_sync(up->dev);
-	up->mcr = serial_in(up, UART_MCR);
-	up->mcr |= mcr;
+	old_mcr = serial_in(up, UART_MCR);
+	old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
+		     UART_MCR_DTR | UART_MCR_RTS);
+	up->mcr = old_mcr | mcr;
 	serial_out(up, UART_MCR, up->mcr);
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 08/11] SERIAL: omap: no need to re-read EFR
From: Russell King @ 2012-10-16 11:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

There's no need to re-read EFR after we've recently written it; the
register is a configuration register which doesn't change its value
without us writing to it.  The last value which was written to this
register was up->efr.

Removing this re-reading avoids the possibility that we end up with
up->efr having unintended bits set, which should only be temporarily
set when accessing the enhanced features.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 71db4e6..c8a0425 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -873,8 +873,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
-	up->efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, 0);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 07/11] SERIAL: omap: remove setting of EFR SCD bit
From: Russell King @ 2012-10-16 11:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

The SCD (special character detect) bit enables comparisons with XOFF2,
which we do not program.  As the XOFF2 character remains unprogrammed,
there's little point enabling this feature along with its associated
interrupt.  Remove this, and ensure that the SCD bit is cleared.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7c313c2..71db4e6 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -704,13 +704,8 @@ serial_omap_configure_xonxoff
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-	/* Enable special char function UARTi.EFR_REG[5] and
-	 * load the new software flow control mode IXON or IXOFF
-	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
-	 */
-	serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
+	serial_out(up, UART_EFR, up->efr);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
 	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, up->lcr);
 }
@@ -843,6 +838,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	up->efr = serial_in(up, UART_EFR);
+	up->efr &= ~UART_EFR_SCD;
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 06/11] SERIAL: omap: allow hardware assisted IXANY mode to be disabled
From: Russell King @ 2012-10-16 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

Nothing was clearing the UART_MCR_XONANY bit, so once the ixany
mode gets set, there's no possibility to disable it.  Clear this
bit when IXANY mode is cleared.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index c55af63..7c313c2 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -698,6 +698,8 @@ serial_omap_configure_xonxoff
 	 */
 	if (termios->c_iflag & IXANY)
 		up->mcr |= UART_MCR_XONANY;
+	else
+		up->mcr &= ~UART_MCR_XONANY;
 
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-- 
1.7.4.4

^ permalink raw reply related

* [RESEND] [PATCH 3.6.0- 3/6] ARM/pxa: use module_platform_driver macro
From: Igor Grinberg @ 2012-10-16 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350025880-30551-1-git-send-email-srinivas.kandagatla@st.com>

On 10/12/12 09:11, Srinivas KANDAGATLA wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> 
> This patch removes some code duplication by using
> module_platform_driver.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>

Acked-by: Igor Grinberg <grinberg@compulab.co.il>

> ---
>  arch/arm/mach-pxa/pxa3xx-ulpi.c |   13 +------------
>  1 files changed, 1 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
> index 7dbe3cc..e329cce 100644
> --- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
> +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
> @@ -384,18 +384,7 @@ static struct platform_driver pxa3xx_u2d_ulpi_driver = {
>          .probe          = pxa3xx_u2d_probe,
>          .remove         = pxa3xx_u2d_remove,
>  };
> -
> -static int pxa3xx_u2d_ulpi_init(void)
> -{
> -	return platform_driver_register(&pxa3xx_u2d_ulpi_driver);
> -}
> -module_init(pxa3xx_u2d_ulpi_init);
> -
> -static void __exit pxa3xx_u2d_ulpi_exit(void)
> -{
> -	platform_driver_unregister(&pxa3xx_u2d_ulpi_driver);
> -}
> -module_exit(pxa3xx_u2d_ulpi_exit);
> +module_platform_driver(pxa3xx_u2d_ulpi_driver);
>  
>  MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
>  MODULE_AUTHOR("Igor Grinberg");

-- 
Regards,
Igor.

^ permalink raw reply

* [PATCH 05/11] SERIAL: omap: allow hardware assisted rts/cts modes to be disabled
From: Russell King @ 2012-10-16 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

There is nothing which clears the auto RTS/CTS bits, so once hardware
flow control gets enabled, there's no possibility to disable it.
So, clear these bits when CRTSCTS is cleared.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/omap-serial.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6ede6fd..c55af63 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -921,6 +921,13 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
 		serial_out(up, UART_LCR, cval);
+	} else {
+		/* Disable AUTORTS and AUTOCTS */
+		up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
+
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+		serial_out(up, UART_EFR, up->efr);
+		serial_out(up, UART_LCR, cval);
 	}
 
 	serial_omap_set_mctrl(&up->port, up->port.mctrl);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 04/11] SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control
From: Russell King @ 2012-10-16 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

Add two callbacks for hardware assisted flow control; we need to know
when the tty layers want us to stop and restart due to their buffer
levels.

Call a driver specific throttle/unthrottle function if and only if the
driver indicates that it is using an enabled hardware assisted flow
control method, otherwise fall back to the non-hardware assisted
methods.

Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/serial_core.c |   31 +++++++++++++++++++++++++++----
 include/linux/serial_core.h      |    2 ++
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 9d8796e..098bb99 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -610,27 +610,50 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
 static void uart_throttle(struct tty_struct *tty)
 {
 	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->uart_port;
+	uint32_t mask = 0;
 
 	if (I_IXOFF(tty))
+		mask |= UPF_SOFT_FLOW;
+	if (tty->termios.c_cflag & CRTSCTS)
+		mask |= UPF_HARD_FLOW;
+
+	if (port->flags & mask) {
+		port->ops->throttle(port);
+		mask &= ~port->flags;
+	}
+
+	if (mask & UPF_SOFT_FLOW)
 		uart_send_xchar(tty, STOP_CHAR(tty));
 
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_clear_mctrl(state->uart_port, TIOCM_RTS);
+	if (mask & UPF_HARD_FLOW)
+		uart_clear_mctrl(port, TIOCM_RTS);
 }
 
 static void uart_unthrottle(struct tty_struct *tty)
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port = state->uart_port;
+	uint32_t mask = 0;
 
-	if (I_IXOFF(tty)) {
+	if (I_IXOFF(tty))
+		mask |= UPF_SOFT_FLOW;
+	if (tty->termios.c_cflag & CRTSCTS)
+		mask |= UPF_HARD_FLOW;
+
+	if (port->flags & mask) {
+		port->ops->unthrottle(port);
+		mask &= ~port->flags;
+	}
+
+	if (mask & UPF_SOFT_FLOW) {
 		if (port->x_char)
 			port->x_char = 0;
 		else
 			uart_send_xchar(tty, START_CHAR(tty));
 	}
 
-	if (tty->termios.c_cflag & CRTSCTS)
+	if (mask & UPF_HARD_FLOW)
 		uart_set_mctrl(port, TIOCM_RTS);
 }
 
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e2cda5d..c6690a2 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -46,6 +46,8 @@ struct uart_ops {
 	unsigned int	(*get_mctrl)(struct uart_port *);
 	void		(*stop_tx)(struct uart_port *);
 	void		(*start_tx)(struct uart_port *);
+	void		(*throttle)(struct uart_port *);
+	void		(*unthrottle)(struct uart_port *);
 	void		(*send_xchar)(struct uart_port *, char ch);
 	void		(*stop_rx)(struct uart_port *);
 	void		(*enable_ms)(struct uart_port *);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 03/11] SERIAL: core: add hardware assisted h/w flow control support
From: Russell King @ 2012-10-16 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

Ports which are handling h/w flow control in hardware must not have
their RTS state altered depending on the tty's hardware-stopped state.
Avoid this additional logic when setting the termios state.

Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/serial_core.c |    7 +++++++
 include/linux/serial_core.h      |    2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index bd10bbd..9d8796e 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1255,6 +1255,13 @@ static void uart_set_termios(struct tty_struct *tty,
 		uart_set_mctrl(uport, mask);
 	}
 
+	/*
+	 * If the port is doing h/w assisted flow control, do nothing.
+	 * We assume that tty->hw_stopped has never been set.
+	 */
+	if (uport->flags & UPF_HARD_FLOW)
+		return;
+
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
 		spin_lock_irqsave(&uport->lock, flags);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 0005138..e2cda5d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -163,6 +163,8 @@ struct uart_port {
 #define UPF_BUGGY_UART		((__force upf_t) (1 << 14))
 #define UPF_NO_TXEN_TEST	((__force upf_t) (1 << 15))
 #define UPF_MAGIC_MULTIPLIER	((__force upf_t) (1 << 16))
+/* Port has hardware-assisted h/w flow control (iow, auto-RTS *not* auto-CTS) */
+#define UPF_HARD_FLOW		((__force upf_t) (1 << 21))
 /* Port has hardware-assisted s/w flow control */
 #define UPF_SOFT_FLOW		((__force upf_t) (1 << 22))
 #define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 02/11] SERIAL: core: add hardware assisted s/w flow control support
From: Russell King @ 2012-10-16 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

Ports which are capable of handling s/w flow control in hardware to
know when the s/w flow control termios settings are changed.  Add a
flag to allow the low level serial drivers to indicate that they
support this, and these changes should be propagated to them.

Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/serial_core.c |   16 ++++++++++++++--
 include/linux/serial_core.h      |    2 ++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index bc2065d..bd10bbd 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1213,7 +1213,19 @@ static void uart_set_termios(struct tty_struct *tty,
 	struct uart_port *uport = state->uart_port;
 	unsigned long flags;
 	unsigned int cflag = tty->termios.c_cflag;
+	unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
+	bool sw_changed = false;
 
+	/*
+	 * Drivers doing software flow control also need to know
+	 * about changes to these input settings.
+	 */
+	if (uport->flags & UPF_SOFT_FLOW) {
+		iflag_mask |= IXANY|IXON|IXOFF;
+		sw_changed =
+		   tty->termios.c_cc[VSTART] != old_termios->c_cc[VSTART] ||
+		   tty->termios.c_cc[VSTOP] != old_termios->c_cc[VSTOP];
+	}
 
 	/*
 	 * These are the bits that are used to setup various
@@ -1221,11 +1233,11 @@ static void uart_set_termios(struct tty_struct *tty,
 	 * bits in c_cflag; c_[io]speed will always be set
 	 * appropriately by set_termios() in tty_ioctl.c
 	 */
-#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 	if ((cflag ^ old_termios->c_cflag) == 0 &&
 	    tty->termios.c_ospeed == old_termios->c_ospeed &&
 	    tty->termios.c_ispeed == old_termios->c_ispeed &&
-	    RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
+	    ((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
+	    !sw_changed) {
 		return;
 	}
 
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 3c43022..0005138 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -163,6 +163,8 @@ struct uart_port {
 #define UPF_BUGGY_UART		((__force upf_t) (1 << 14))
 #define UPF_NO_TXEN_TEST	((__force upf_t) (1 << 15))
 #define UPF_MAGIC_MULTIPLIER	((__force upf_t) (1 << 16))
+/* Port has hardware-assisted s/w flow control */
+#define UPF_SOFT_FLOW		((__force upf_t) (1 << 22))
 #define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
 #define UPF_EXAR_EFR		((__force upf_t) (1 << 25))
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 01/11] SERIAL: core: use local variable uport in uart_set_termios()
From: Russell King @ 2012-10-16 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101458.GZ21164@n2100.arm.linux.org.uk>

This is to make the following change more clear.

Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/serial_core.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0fcfd98..bc2065d 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1210,6 +1210,7 @@ static void uart_set_termios(struct tty_struct *tty,
 						struct ktermios *old_termios)
 {
 	struct uart_state *state = tty->driver_data;
+	struct uart_port *uport = state->uart_port;
 	unsigned long flags;
 	unsigned int cflag = tty->termios.c_cflag;
 
@@ -1232,31 +1233,31 @@ static void uart_set_termios(struct tty_struct *tty,
 
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
+		uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
 	/* Handle transition away from B0 status */
 	else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
 		unsigned int mask = TIOCM_DTR;
 		if (!(cflag & CRTSCTS) ||
 		    !test_bit(TTY_THROTTLED, &tty->flags))
 			mask |= TIOCM_RTS;
-		uart_set_mctrl(state->uart_port, mask);
+		uart_set_mctrl(uport, mask);
 	}
 
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->uart_port->lock, flags);
+		spin_lock_irqsave(&uport->lock, flags);
 		tty->hw_stopped = 0;
 		__uart_start(tty);
-		spin_unlock_irqrestore(&state->uart_port->lock, flags);
+		spin_unlock_irqrestore(&uport->lock, flags);
 	}
 	/* Handle turning on CRTSCTS */
 	else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->uart_port->lock, flags);
-		if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
+		spin_lock_irqsave(&uport->lock, flags);
+		if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) {
 			tty->hw_stopped = 1;
-			state->uart_port->ops->stop_tx(state->uart_port);
+			uport->ops->stop_tx(uport);
 		}
-		spin_unlock_irqrestore(&state->uart_port->lock, flags);
+		spin_unlock_irqrestore(&uport->lock, flags);
 	}
 }
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 2/2] ARM: unwind: enable dumping stacks for SMP && ARM_UNWIND
From: Russell King - ARM Linux @ 2012-10-16 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016101201.GA26075@linaro.org>

On Tue, Oct 16, 2012 at 11:12:01AM +0100, Dave Martin wrote:
> On Mon, Oct 15, 2012 at 07:15:31PM -0700, Colin Cross wrote:
> > About half the callers to unwind_frame end up limiting the number of
> > frames they will follow before giving up, so I wasn't sure if I should
> > put an arbitrary limit in unwind_frame or just make sure all callers
> > are bounded.  Your idea of limiting same sp frames instead of total
> > frames sounds better.  I can send a new patch that adds a new field to
> > struct stackframe (which will need to be initialized everywhere, the
> > struct is usually on the stack) and limits the recursion.  Any
> > suggestion on the recursion limit?  I would never expect to see a real
> > situation with more than a few, but on the other hand parsing the
> > frames should be pretty fast so a high number (100?) shouldn't cause
> > any user visible effect.
> 
> Talking to some tools guys about this, it sounds like there really
> shouldn't be any stackless frame except for the leaf frame.  If there are
> stackless functions they will probably not be visible in the frame chain
> at all.  So it might make sense to have a pretty small limit.  Maybe it
> could even be 1.  Cartainly a small number.
> 
> We should also add a check for whether the current and frame and previous
> frame appear identical and abort if that's the case, if we don't do that
> already.

The case that actually worries me is not the "end up looping for ever"
case, but the effects of having the stack change while the unwinder is
reading from it - for example:

                /* pop R4-R15 according to mask */
                load_sp = mask & (1 << (13 - 4));
                while (mask) {
                        if (mask & 1)
                                ctrl->vrs[reg] = *vsp++;
                        mask >>= 1;
                        reg++;
                }

Remember that for a running thread, the stack will be changing all the
time while another CPU tries to read it to do the unwind, and also
remember that the bottom of stack isn't really known.  All you have is
the snapshot of the registers when the thread was last stopped by the
scheduler, and that state probably isn't valid.

So what you're asking is for the unwinder to produce a backtrace from
a kernel stack which is possibly changing beneath it from an unknown
current state.

This doesn't sound like a particularly bright thing to be doing...

^ permalink raw reply

* [Linaro-mm-sig] [RFC 0/2] DMA-mapping & IOMMU - physically contiguous allocations
From: Russell King - ARM Linux @ 2012-10-16 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016.132755.661591248175727826.hdoyu@nvidia.com>

On Tue, Oct 16, 2012 at 12:27:55PM +0200, Hiroshi Doyu wrote:
> Hi Russell,
> 
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote @ Tue, 16 Oct 2012 10:59:28 +0200:
> 
> > On Tue, Oct 16, 2012 at 09:04:34AM +0300, Hiroshi Doyu wrote:
> > > In addition to those contiguous/discontiguous page allocation, is
> > > there any way to _import_ anonymous pages allocated by a process to be
> > > used in dma-mapping API later?
> > > 
> > > I'm considering the following scenario, an user process allocates a
> > > buffer by malloc() in advance, and then it asks some driver to convert
> > > that buffer into IOMMU'able/DMA'able ones later. In this case, pages
> > > are discouguous and even they may not be yet allocated at
> > > malloc()/mmap().
> > 
> > That situation is covered.  It's the streaming API you're wanting for that.
> > dma_map_sg() - but you may need additional cache handling via
> > flush_dcache_page() to ensure that your code is safe for all CPU cache
> > architectures.
> >
> > Remember that pages allocated into userspace will be cacheable, so a cache
> > flush is required before they can be DMA'd.  Hence the streaming
> > API.
> 
> Is the syscall "cacheflush()" supposed to be the knob for that?
> 
> Or is there any other ones to have more precise control, "clean",
> "invalidate" and "flush", from userland in generic way?

No other syscalls are required - this sequence will do everything you
need to perform DMA on pages mapped into userspace:

	get_user_pages()
	convert array of struct page * to scatterlist
	dma_map_sg()
	perform DMA
	dma_unmap_sg()
	for each page in sg()
		page_cache_release(page);

If you get the list of pages some other way (eg, via shmem_read_mapping_page_gfp)
then additional maintanence may be required (though that may be a bug in
shmem - remember this stuff hasn't been well tested on ARM before.)

^ permalink raw reply

* [Linaro-mm-sig] [RFC 0/2] DMA-mapping & IOMMU - physically contiguous allocations
From: Russell King - ARM Linux @ 2012-10-16 10:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAQKjZNQFfxpr-7dFb4cgNB2Gkrxxrswds_fSrYgssxXaqRF7g@mail.gmail.com>

On Tue, Oct 16, 2012 at 07:12:49PM +0900, Inki Dae wrote:
> Hi Hiroshi,
> 
> I'm not sure I understand what you mean but we had already tried this
> way and for this, you can refer to below link,
>                http://www.mail-archive.com/dri-devel at lists.freedesktop.org/msg22555.html
> 
> but this way had been pointed out by drm guys because the pages could
> be used through gem object after that pages had been freed by free()
> anyway their pointing was reasonable and I'm trying another way, this
> is the way that the pages to user space has same life time with dma
> operation. in other word, if dma completed access to that pages then
> also that pages will be freed. actually drm-based via driver of
> mainline kernel is using same way

I don't know about Hiroshi, but the above "sentence" - and I mean the 7
line sentence - is very difficult to understand and wears readers out.

If your GPU hardware has a MMU, then the problem of dealing with userspace
pages is very easy.  Do it the same way that the i915 driver and the rest
of DRM does.  Use shmem backed memory.

I'm doing that for the Dove DRM driver and it works a real treat, and as
the pages are backed by page cache pages, you can use all the normal
page refcounting on them to prevent them being freed until your DMA has
completed.  All my X pixmaps are shmem backed drm objects, except for
the scanout buffers which are dumb drm objects (because they must be
contiguous.)

In fact, get_user_pages() will take the reference for you before you pass
them over to dma_map_sg().  On completion of DMA, you just need to use
dma_unmap_sg() and release each page.

If you don't want to use get_user_pages() (which other drivers don't) then
you need to following the i915 example and get each page out of shmem
individually.

(My situation on the Dove hardware is a little different, because the
kernel DRM driver isn't involved with the GPU - it merely provides the
memory for pixmaps.  The GPU software stack, being a chunk of closed
source userspace library with open source kernel driver, means that
things are more complicated; the kernel side GPU driver uses
get_user_pages() to pin them prior to building the GPU's MMU table.)

^ permalink raw reply

* [Linaro-mm-sig] [RFC 0/2] DMA-mapping & IOMMU - physically contiguous allocations
From: Hiroshi Doyu @ 2012-10-16 10:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016085928.GV21164@n2100.arm.linux.org.uk>

Hi Russell,

Russell King - ARM Linux <linux@arm.linux.org.uk> wrote @ Tue, 16 Oct 2012 10:59:28 +0200:

> On Tue, Oct 16, 2012 at 09:04:34AM +0300, Hiroshi Doyu wrote:
> > In addition to those contiguous/discontiguous page allocation, is
> > there any way to _import_ anonymous pages allocated by a process to be
> > used in dma-mapping API later?
> > 
> > I'm considering the following scenario, an user process allocates a
> > buffer by malloc() in advance, and then it asks some driver to convert
> > that buffer into IOMMU'able/DMA'able ones later. In this case, pages
> > are discouguous and even they may not be yet allocated at
> > malloc()/mmap().
> 
> That situation is covered.  It's the streaming API you're wanting for that.
> dma_map_sg() - but you may need additional cache handling via
> flush_dcache_page() to ensure that your code is safe for all CPU cache
> architectures.
>
> Remember that pages allocated into userspace will be cacheable, so a cache
> flush is required before they can be DMA'd.  Hence the streaming
> API.

Is the syscall "cacheflush()" supposed to be the knob for that?

Or is there any other ones to have more precise control, "clean",
"invalidate" and "flush", from userland in generic way?

^ permalink raw reply

* [PATCH v3 2/2] i2c: change id to let i2c-at91 work
From: Bo Shen @ 2012-10-16 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016083954.GB12801@game.jcrosoft.org>

Hi J,

On 10/16/2012 16:39, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 11:13 Tue 16 Oct     , Bo Shen wrote:
>> Hi J,
>>
>> On 10/15/2012 23:02, Jean-Christophe PLAGNIOL-VILLARD wrote:
>>> On 17:30 Mon 15 Oct     , Bo Shen wrote:
>>>> The i2c core driver will turn the platform device ID to busnum
>>>> When using platfrom device ID as -1, it means dynamically assigned
>>>> the busnum. When writing code, we need to make sure the busnum,
>>>> and call i2c_register_board_info(int busnum, ...) to register device
>>>> if using -1, we do not know the value of busnum
>>>> 	
>>>> In order to solve this issue, set the platform device ID as a fix number
>>>> Here using 0 to match the busnum used in i2c_regsiter_board_info()
>>>>
>>>> Signed-off-by: Bo Shen <voice.shen@atmel.com>
>>>> ---
>>>
>>> can you check when this append for the first time to schedule a patch for stable too
>>
>> OK. I will resend it and add linux stable into the cc list.
> no this not how it work
>
> I ask you to check which patch add the regression and then when this is
> applied in the kernel we will request greg to apply it too to the stable

The code is using id = -1 appear 4 years ago. And after dig, I don't 
find which patch cause this the regression.

Sorry for that.

> But before do that you MUST foudn the commit responsible
>
> Best Regards,
> J.
>

^ 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