Linux Serial subsystem development
 help / color / mirror / Atom feed
* Re: [PATCH 2/3] RFC: Solved unnecessary schedule latency in the TTY layer (2/3)
From: Ivo Sieben @ 2012-05-07  7:45 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial, Alan Cox, RT
In-Reply-To: <20120503162529.GB3063@kroah.com>

Hi,

2012/5/3 Greg KH <gregkh@linuxfoundation.org>:
>
> Why, what does this cause to have happen?  What's the difference here
> that causes any speedups or latency fixes?
>

This patch solves the following scenario:
- A low priority process starts to send data to serial port A
- In order to do this, the low priority process calls the
tty_ldisc_ref_wait() function to retrieve a reference to its line
discipline.
- In the tty_ldisc_ref_wait() function, the global ldisc spinlock is locked.
- While the spin lock is still locked, a context switch takes place
and a second process on high real-time priority starts reading data
from another serial port B (this is a possible scenario on a
PREEMPT_RT system where a "normal" spin lock behaves like a mutex and
no interrupts are actually disabled, although the "irqsave" postfix in
the spinlock function name suggests otherwise)
- The second project also calls the tty_ldisc_ref_wait() function, and
therefor gets blocked on the global ldisc spin lock.
- As a result priority inversion takes place, and the second process
is scheduled out, the first process is scheduled in on high priority.
After the first process has released the spin lock, the second process
is scheduled again.

The above scenario is not wrong, it works fine... but the scheduling &
mutex handling requires a lot of extra processing time what makes that
a normal read operation of about 50us sometimes can last up to 230us.
By using raw spin locks this situation is prevented. I think it is
legitimate to use raw spin locks because the critical sections in
ldisc are small.

Regards,
Ivo Sieben
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH RESEND 0/5] Adopt pinctrl support for a few outstanding imx drivers
From: Shawn Guo @ 2012-05-07  7:34 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: linux-arm-kernel, Arnd Bergmann, netdev, Sascha Hauer,
	Wolfram Sang, linux-can, Grant Likely, Marc Kleine-Budde,
	linux-i2c, linux-serial, Greg Kroah-Hartman, Olof Johansson,
	spi-devel-general, Dong Aisheng, David S. Miller
In-Reply-To: <20120507065001.GA23607@shlinux2.ap.freescale.net>

On Mon, May 07, 2012 at 02:50:02PM +0800, Dong Aisheng wrote:
> Shouldn't we add the pinctrl states in dts file at the same time
> with this patch series or using another separate patch to add them
> before this series to avoid breaking the exist mx6q platforms?
> 
Ah, I just noticed that your patch "ARM: imx: enable pinctrl dummy
states" did not cover imx6q.  I think we should do the same for imx6q,
so that we can separate dts update from the driver change.  When all
imx6q boards' dts files get updated to have pins defined for the
devices, we can then remove dummy state for imx6q.  Doing so will ease
the pinctrl migration for those imx6q boards.

Will update your patch on my branch to have dummy state enabled for
imx6q.

> >   net: fec: adopt pinctrl support
> >   can: flexcan: adopt pinctrl support
> This two also depends on another patch you sent.
> [PATCH RESEND 1/9] ARM: mxs: enable pinctrl dummy states
> http://www.spinics.net/lists/arm-kernel/msg173341.html
> 
> Maybe you can put this two in the mxs convert series to avoid breaking
> mxs platforms.
> [PATCH 0/9] Enable pinctrl support for mach-mxs
> http://www.spinics.net/lists/arm-kernel/msg173312.html
> 
Right.  I'm going to merge these two series into one since there are
device drives shared between imx and mxs.

-- 
Regards,
Shawn

^ permalink raw reply

* Re: [alsa-devel] [PATCH RESEND 0/9] Enable pinctrl support for mach-mxs
From: Dong Aisheng @ 2012-05-07  7:14 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, linux-fbdev, Chris Ball, Arnd Bergmann,
	Florian Tobias Schandinat, Artem Bityutskiy, Mark Brown,
	linux-mmc, alsa-devel, Wolfram Sang, linux-mtd, linux-i2c,
	linux-serial, Greg Kroah-Hartman, Olof Johansson
In-Reply-To: <1336353374-28939-1-git-send-email-shawn.guo@linaro.org>

On Mon, May 07, 2012 at 09:16:05AM +0800, Shawn Guo wrote:
> [Resend to have subsystem lists Cc-ed]
> 
> With pinctrl-mxs driver (DT only) applied on pinctrl tree, the mxs
> device tree conversion can start basing on that support.  This series
> adopts pinctrl support for mxs device drivers with a dummy pinctrl
> state provided for non-DT boot, so that the pinctrl call in the device
> drivers will be bypassed for non-DT probe while it starts working for
> DT probe.
> 
> To ease the merge process, I would like to ask Arnd and Olof to pull
> pinctrl tree as a dependency in arm-soc and have this series go through
> arm-soc.
> 
As IMX, basically i'd prefer to add pinctrl states in dts file at the
same time within the patch or using a separate patch to add them before
this series to avoid breaking the exist platforms.

However i noted that for mxs, most drivers here are still not dt capable,
so it may be ok to not add their pinctrl state at this time.

But for the patch "serial: amba-pl011: adopt pinctrl support" since it is
dt capable, so with this patch applied, the mx28 dt boot will fail.
Maybe we should at least add pinctrl states for amba-pl011 first.

> Regards,
> Shawn
> 
> Shawn Guo (9):
>   ARM: mxs: enable pinctrl dummy states
>   serial: amba-pl011: adopt pinctrl support
BTW, will this one break other platforms using this driver?

>   serial: mxs-auart: adopt pinctrl support
>   mmc: mxs-mmc: adopt pinctrl support
>   mtd: nand: gpmi: adopt pinctrl support
>   i2c: mxs: adopt pinctrl support
>   ASoC: mxs-saif: adopt pinctrl support
>   video: mxsfb: adopt pinctrl support
>   ARM: mxs: enable pinctrl support
> 
>  arch/arm/Kconfig                        |    1 +
>  arch/arm/mach-mxs/Kconfig               |    2 ++
>  arch/arm/mach-mxs/include/mach/common.h |    2 ++
>  arch/arm/mach-mxs/mach-apx4devkit.c     |    2 ++
>  arch/arm/mach-mxs/mach-m28evk.c         |    2 ++
>  arch/arm/mach-mxs/mach-mx23evk.c        |    2 ++
>  arch/arm/mach-mxs/mach-mx28evk.c        |    2 ++
>  arch/arm/mach-mxs/mach-stmp378x_devb.c  |    2 ++
>  arch/arm/mach-mxs/mach-tx28.c           |    2 ++
>  arch/arm/mach-mxs/mm.c                  |   11 +++++++++++
>  drivers/i2c/busses/i2c-mxs.c            |    6 ++++++
>  drivers/mmc/host/mxs-mmc.c              |    8 ++++++++
>  drivers/mtd/nand/gpmi-nand/gpmi-nand.c  |    9 +++++++++
>  drivers/tty/serial/amba-pl011.c         |    8 ++++++++
>  drivers/tty/serial/mxs-auart.c          |    8 ++++++++
>  drivers/video/mxsfb.c                   |    9 +++++++++
>  sound/soc/mxs/mxs-saif.c                |    8 ++++++++
>  17 files changed, 84 insertions(+), 0 deletions(-)
> 
> -- 
> 1.7.5.4
> 

Regards
Dong Aisheng


^ permalink raw reply

* Re: [PATCH RESEND 0/5] Adopt pinctrl support for a few outstanding imx drivers
From: Dong Aisheng @ 2012-05-07  6:50 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, Arnd Bergmann, netdev, Sascha Hauer,
	Wolfram Sang, linux-can, Grant Likely, Marc Kleine-Budde,
	linux-i2c, linux-serial, Greg Kroah-Hartman, Olof Johansson,
	spi-devel-general, Dong Aisheng, David S. Miller
In-Reply-To: <1336352040-28447-1-git-send-email-shawn.guo@linaro.org>

On Mon, May 07, 2012 at 08:53:55AM +0800, Shawn Guo wrote:
> With patch 5b3aa5f (pinctrl: add pinctrl_provide_dummies interface for
> platforms to use) applied on pinctrl tree, and patch "ARM: imx: enable
> pinctrl dummy states" [1] being there, we are ready to adopt pinctrl
> API for imx drivers.  So let's start from a few outstanding ones.
> 
> I would expect to ask Arnd and Olof to pull pinctrl tree into arm-soc
> as a dependency and then have series [1] and this patch set go through
> arm-soc tree to ease the merge process.
> 
Shouldn't we add the pinctrl states in dts file at the same time
with this patch series or using another separate patch to add them
before this series to avoid breaking the exist mx6q platforms?

> Resend to have subsystem lists Cc-ed.
> 
> Regards,
> Shawn
> 
> [1] http://thread.gmane.org/gmane.linux.kernel.mmc/14180
> 
> Shawn Guo (5):
>   tty: serial: imx: adopt pinctrl support
...

>   net: fec: adopt pinctrl support
>   can: flexcan: adopt pinctrl support
This two also depends on another patch you sent.
[PATCH RESEND 1/9] ARM: mxs: enable pinctrl dummy states
http://www.spinics.net/lists/arm-kernel/msg173341.html

Maybe you can put this two in the mxs convert series to avoid breaking
mxs platforms.
[PATCH 0/9] Enable pinctrl support for mach-mxs
http://www.spinics.net/lists/arm-kernel/msg173312.html

Regards
Dong Aisheng

>   i2c: imx: adopt pinctrl support
>   spi/imx: adopt pinctrl support
> 
>  drivers/i2c/busses/i2c-imx.c         |    8 ++++++++
>  drivers/net/can/flexcan.c            |    6 ++++++
>  drivers/net/ethernet/freescale/fec.c |    9 +++++++++
>  drivers/spi/spi-imx.c                |    8 ++++++++
>  drivers/tty/serial/imx.c             |    8 ++++++++
>  5 files changed, 39 insertions(+), 0 deletions(-)
> 
> -- 
> 1.7.5.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply

* [PATCH RESEND 3/9] serial: mxs-auart: adopt pinctrl support
From: Shawn Guo @ 2012-05-07  1:16 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Arnd Bergmann, Olof Johansson, Shawn Guo, linux-serial,
	Greg Kroah-Hartman
In-Reply-To: <1336353374-28939-1-git-send-email-shawn.guo@linaro.org>

Cc: linux-serial@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/tty/serial/mxs-auart.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 55fd362..7081600 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -32,6 +32,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/cacheflush.h>
 
@@ -678,6 +679,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 	u32 version;
 	int ret = 0;
 	struct resource *r;
+	struct pinctrl *pinctrl;
 
 	s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
 	if (!s) {
@@ -685,6 +687,12 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 		goto out;
 	}
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto out_free;
+	}
+
 	s->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(s->clk)) {
 		ret = PTR_ERR(s->clk);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH RESEND 2/9] serial: amba-pl011: adopt pinctrl support
From: Shawn Guo @ 2012-05-07  1:16 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Arnd Bergmann, Olof Johansson, Shawn Guo, linux-serial,
	Greg Kroah-Hartman
In-Reply-To: <1336353374-28939-1-git-send-email-shawn.guo@linaro.org>

Cc: linux-serial@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 3d569cd..062ef8c 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -52,6 +52,7 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/io.h>
 #include <asm/sizes.h>
@@ -1916,6 +1917,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
 	struct vendor_data *vendor = id->data;
+	struct pinctrl *pinctrl;
 	void __iomem *base;
 	int i, ret;
 
@@ -1940,6 +1942,12 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		goto free;
 	}
 
+	pinctrl = devm_pinctrl_get_select_default(&dev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto unmap;
+	}
+
 	uap->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(uap->clk)) {
 		ret = PTR_ERR(uap->clk);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH RESEND 0/9] Enable pinctrl support for mach-mxs
From: Shawn Guo @ 2012-05-07  1:16 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Arnd Bergmann, Olof Johansson, Shawn Guo, linux-fbdev,
	Florian Tobias Schandinat, alsa-devel, Mark Brown, linux-i2c,
	Wolfram Sang, linux-mtd, Artem Bityutskiy, linux-mmc, Chris Ball,
	linux-serial, Greg Kroah-Hartman

[Resend to have subsystem lists Cc-ed]

With pinctrl-mxs driver (DT only) applied on pinctrl tree, the mxs
device tree conversion can start basing on that support.  This series
adopts pinctrl support for mxs device drivers with a dummy pinctrl
state provided for non-DT boot, so that the pinctrl call in the device
drivers will be bypassed for non-DT probe while it starts working for
DT probe.

To ease the merge process, I would like to ask Arnd and Olof to pull
pinctrl tree as a dependency in arm-soc and have this series go through
arm-soc.

Regards,
Shawn

Shawn Guo (9):
  ARM: mxs: enable pinctrl dummy states
  serial: amba-pl011: adopt pinctrl support
  serial: mxs-auart: adopt pinctrl support
  mmc: mxs-mmc: adopt pinctrl support
  mtd: nand: gpmi: adopt pinctrl support
  i2c: mxs: adopt pinctrl support
  ASoC: mxs-saif: adopt pinctrl support
  video: mxsfb: adopt pinctrl support
  ARM: mxs: enable pinctrl support

 arch/arm/Kconfig                        |    1 +
 arch/arm/mach-mxs/Kconfig               |    2 ++
 arch/arm/mach-mxs/include/mach/common.h |    2 ++
 arch/arm/mach-mxs/mach-apx4devkit.c     |    2 ++
 arch/arm/mach-mxs/mach-m28evk.c         |    2 ++
 arch/arm/mach-mxs/mach-mx23evk.c        |    2 ++
 arch/arm/mach-mxs/mach-mx28evk.c        |    2 ++
 arch/arm/mach-mxs/mach-stmp378x_devb.c  |    2 ++
 arch/arm/mach-mxs/mach-tx28.c           |    2 ++
 arch/arm/mach-mxs/mm.c                  |   11 +++++++++++
 drivers/i2c/busses/i2c-mxs.c            |    6 ++++++
 drivers/mmc/host/mxs-mmc.c              |    8 ++++++++
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c  |    9 +++++++++
 drivers/tty/serial/amba-pl011.c         |    8 ++++++++
 drivers/tty/serial/mxs-auart.c          |    8 ++++++++
 drivers/video/mxsfb.c                   |    9 +++++++++
 sound/soc/mxs/mxs-saif.c                |    8 ++++++++
 17 files changed, 84 insertions(+), 0 deletions(-)

-- 
1.7.5.4


^ permalink raw reply

* [PATCH RESEND 1/5] tty: serial: imx: adopt pinctrl support
From: Shawn Guo @ 2012-05-07  0:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Arnd Bergmann, Olof Johansson, Sascha Hauer, Dong Aisheng,
	Shawn Guo, linux-serial, Greg Kroah-Hartman
In-Reply-To: <1336352040-28447-1-git-send-email-shawn.guo@linaro.org>

Cc: linux-serial@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/tty/serial/imx.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e7fecee..ec20673 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -47,6 +47,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -1464,6 +1465,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 	void __iomem *base;
 	int ret = 0;
 	struct resource *res;
+	struct pinctrl *pinctrl;
 
 	sport = kzalloc(sizeof(*sport), GFP_KERNEL);
 	if (!sport)
@@ -1503,6 +1505,12 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto unmap;
+	}
+
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH RESEND 0/5] Adopt pinctrl support for a few outstanding imx drivers
From: Shawn Guo @ 2012-05-07  0:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Arnd Bergmann, Olof Johansson, Sascha Hauer, Dong Aisheng,
	Shawn Guo, spi-devel-general, Grant Likely, linux-i2c,
	Wolfram Sang, linux-can, Marc Kleine-Budde, netdev,
	David S. Miller, linux-serial, Greg Kroah-Hartman

With patch 5b3aa5f (pinctrl: add pinctrl_provide_dummies interface for
platforms to use) applied on pinctrl tree, and patch "ARM: imx: enable
pinctrl dummy states" [1] being there, we are ready to adopt pinctrl
API for imx drivers.  So let's start from a few outstanding ones.

I would expect to ask Arnd and Olof to pull pinctrl tree into arm-soc
as a dependency and then have series [1] and this patch set go through
arm-soc tree to ease the merge process.

Resend to have subsystem lists Cc-ed.

Regards,
Shawn

[1] http://thread.gmane.org/gmane.linux.kernel.mmc/14180

Shawn Guo (5):
  tty: serial: imx: adopt pinctrl support
  net: fec: adopt pinctrl support
  can: flexcan: adopt pinctrl support
  i2c: imx: adopt pinctrl support
  spi/imx: adopt pinctrl support

 drivers/i2c/busses/i2c-imx.c         |    8 ++++++++
 drivers/net/can/flexcan.c            |    6 ++++++
 drivers/net/ethernet/freescale/fec.c |    9 +++++++++
 drivers/spi/spi-imx.c                |    8 ++++++++
 drivers/tty/serial/imx.c             |    8 ++++++++
 5 files changed, 39 insertions(+), 0 deletions(-)

-- 
1.7.5.4


^ permalink raw reply

* Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Greg KH @ 2012-05-05 14:57 UTC (permalink / raw)
  To: Alan Cox
  Cc: Preston Fick, linux-usb, linux-kernel, linux-serial, preston.fick,
	linux-arm-kernel@lists.arm.linux.org.uk
In-Reply-To: <20120505120137.11a45c86@pyramind.ukuu.org.uk>

On Sat, May 05, 2012 at 12:01:37PM +0100, Alan Cox wrote:
> > Will the new ldisc mess with the tty stuff to prevent "normal" serial
> > data and line settings from being handled properly?  If not, that all
> > looks very good to me, thanks for working this out.
> 
> It'll have no effect on that. What it will do is provide a way for things
> like ISO7816 ldiscs to use the extra pins (as they can call from the
> ldisc into the gpio layer) and to know the mapping of the extra control
> wires, which varies by device.

Ok, that sounds good to me.

^ permalink raw reply

* Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Alan Cox @ 2012-05-05 11:01 UTC (permalink / raw)
  To: Greg KH
  Cc: Preston Fick, linux-usb, linux-kernel, linux-serial, preston.fick,
	linux-arm-kernel@lists.arm.linux.org.uk
In-Reply-To: <20120505003208.GA30718@kroah.com>

> Will the new ldisc mess with the tty stuff to prevent "normal" serial
> data and line settings from being handled properly?  If not, that all
> looks very good to me, thanks for working this out.

It'll have no effect on that. What it will do is provide a way for things
like ISO7816 ldiscs to use the extra pins (as they can call from the
ldisc into the gpio layer) and to know the mapping of the extra control
wires, which varies by device.

Alan

^ permalink raw reply

* Re: Deterministic behavior for TTY serial
From: Greg KH @ 2012-05-05  0:32 UTC (permalink / raw)
  To: Ivo Sieben; +Cc: linux-serial, Alan Cox, RT
In-Reply-To: <CAMSQXEEnvpBoq7m5hMTtYObj4FsMAtUbpEaiftZ1CDmF56LZAQ@mail.gmail.com>

On Thu, May 03, 2012 at 05:28:47PM +0200, Ivo Sieben wrote:
> Hi,
> 
> >
> > The PREEMPT_RT uses mutexes for "normal" spin locks that do not
> > disable interrupts...
> > I'll try to use raw spinlocks in this code section and for the tty flip buffer
> > See if that can solve my problem.
> >
> > If you have other ideas... let me know!
> >
> > Regards,
> > Ivo
> 
> I've changed some small things to the tty layer (see my other 3 RFC
> patches I've send).
> Performance increased with my loopback stress test:
> - Old situation: average read call last for 50us, with peaks up to 230 us
> - New situation: average read call still 50us, peak up to 60 us
> - Write was stable in both situations: average of 90 us, peak up to 100 us
> 
> Only the very first read & write took extra time (128 us for read, 143
> for write)
> I'm still investigating that...
> 
> Feedback is very appreciated.

Why are raw spinlocks "faster" here?  I like the end-result of what you
have accomplished, but I had some questions on your patches, care to
answer them?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Greg KH @ 2012-05-05  0:32 UTC (permalink / raw)
  To: Alan Cox
  Cc: Preston Fick, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	preston.fick-S6d6foEdJf7QT0dZR+AlfA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW@public.gmane.org
In-Reply-To: <20120503213456.77c55c51-38n7/U1jhRXW96NNrWNlrekiAK3p4hvP@public.gmane.org>

On Thu, May 03, 2012 at 09:34:56PM +0100, Alan Cox wrote:
> 
> Ok this is my suggestion based on GregKH comments and a couple of others
> plus some other driver and ldisc stuff that is pending
> 
> - register the gpio lines with the gpio layer dynamically
> - put them in the right place in the device tree (I'll let Greg advise on
>   the best way to do that bit), plus make them visible via the ioctls for
>   convenience and as they will be needed anyway in kernel

Hang them off of the USB-serial device?

> That provides the user space API
> 
> After that I'll add the hooks to the core tty layer code which allow an
> ldisc to adjust the gpio lines.
> 
> For that we'll need
> 
> struct tty_gpio {
> 	u32 base;
> 	u16 num;
> 	u16 reserved;
> #define NR_TTY_GPIOMAP 8
> 	u16 map[NR_TTY_GPIOMAP];
> 	u32 reserved2[4];
> };
> 
> and
> 
> tty->gpiomap
> 
> which will be NULL for most users.
> 
> 
> Plus
> 
> struct tty_gpio d;
> ioctl(tty, TIOCGPIO, &d)
> 
> and
> 
> ioctl(tty, TIOCSGPIO, &d)
> 
> where the only bits that can be updated will be the map.
> 
> 
> 
> So the normal use case from user space would be
> 
> struct tty_gpio d;
> int fd = open("/dev/ttyUSB0", O_RDWR);
> ioctl(tty, TIOCSGPIO, &d);
> 
> stuff using the gpio driver interfaces
> 
> close(fd);
> 
> 
> And setting up for a kernel ldisc something like
> 
> 
> /* Set a GPIO to LDISC signal mapping for ISO7816 */
> ioctl(tty, TIOCGPIO, &d);
> d.map[TTY_GPIO_ISO7816_RESET] = d.base;
> d.map]TTY_GPIO_ISO7816_VCC] = d.base + 1;
> ioctl(tty, TIOCSGPIO, &d);
> 
> /* Switch to the ldisc */
> ld = N_ISO7816;
> ioctl(tty, TCSETD, &ld);
> 
> 
> and we can then abstract all the wiring details away to keep the ldisc
> portable.
> 
> 
> Thoughts ?

Will the new ldisc mess with the tty stuff to prevent "normal" serial
data and line settings from being handled properly?  If not, that all
looks very good to me, thanks for working this out.

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 3/3] tty_lock: Localise the lock
From: Greg KH @ 2012-05-04 23:55 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, linux-serial
In-Reply-To: <20120504235412.GA5694@kroah.com>

On Fri, May 04, 2012 at 04:54:12PM -0700, Greg KH wrote:
> On Thu, May 03, 2012 at 10:24:08PM +0100, Alan Cox wrote:
> > From: Alan Cox <alan@linux.intel.com>
> > 
> > In each remaining case the tty_lock is associated with a specific tty. This
> > means we can now lock on a per tty basis. We do need tty_lock_pair() for
> > the pty case. Uglier but still a step in the right direction.
> > 
> > Signed-off-by: Alan Cox <alan@linux.intel.com>
> > Acked-by: Arnd Bergmann <arnd@arndb.de>
> > ---
> > 
> >  drivers/tty/amiserial.c   |   12 ++++----
> >  drivers/tty/cyclades.c    |    2 +
> >  drivers/tty/n_r3964.c     |   11 ++++---
> >  drivers/tty/pty.c         |   23 +++++++++------
> >  drivers/tty/synclink.c    |    4 +--
> >  drivers/tty/synclink_gt.c |    4 +--
> >  drivers/tty/synclinkmp.c  |    4 +--
> >  drivers/tty/tty_io.c      |   67 +++++++++++++++++++++++++++------------------
> >  drivers/tty/tty_ldisc.c   |   30 ++++++++++----------
> >  drivers/tty/tty_mutex.c   |   60 ++++++++++++++++++++++++++++++----------
> >  drivers/tty/tty_port.c    |    6 ++--
> >  include/linux/tty.h       |   23 +++++++++------
> >  12 files changed, 149 insertions(+), 97 deletions(-)
> 
> You forgot the call in net/bluetooth/rfcomm/tty.c, I'll go fix that
> up...

And drivers/tty/serial/crisv10.c and
drivers/staging/serial/68360serial.c...

^ permalink raw reply

* Re: [PATCH 3/3] tty_lock: Localise the lock
From: Greg KH @ 2012-05-04 23:54 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, linux-serial
In-Reply-To: <20120503212219.568.15653.stgit@bob.linux.org.uk>

On Thu, May 03, 2012 at 10:24:08PM +0100, Alan Cox wrote:
> From: Alan Cox <alan@linux.intel.com>
> 
> In each remaining case the tty_lock is associated with a specific tty. This
> means we can now lock on a per tty basis. We do need tty_lock_pair() for
> the pty case. Uglier but still a step in the right direction.
> 
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> ---
> 
>  drivers/tty/amiserial.c   |   12 ++++----
>  drivers/tty/cyclades.c    |    2 +
>  drivers/tty/n_r3964.c     |   11 ++++---
>  drivers/tty/pty.c         |   23 +++++++++------
>  drivers/tty/synclink.c    |    4 +--
>  drivers/tty/synclink_gt.c |    4 +--
>  drivers/tty/synclinkmp.c  |    4 +--
>  drivers/tty/tty_io.c      |   67 +++++++++++++++++++++++++++------------------
>  drivers/tty/tty_ldisc.c   |   30 ++++++++++----------
>  drivers/tty/tty_mutex.c   |   60 ++++++++++++++++++++++++++++++----------
>  drivers/tty/tty_port.c    |    6 ++--
>  include/linux/tty.h       |   23 +++++++++------
>  12 files changed, 149 insertions(+), 97 deletions(-)

You forgot the call in net/bluetooth/rfcomm/tty.c, I'll go fix that
up...

^ permalink raw reply

* Re: [PATCH 3/3] tty_lock: Localise the lock
From: Arnd Bergmann @ 2012-05-04 20:48 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, linux-serial
In-Reply-To: <20120503212219.568.15653.stgit@bob.linux.org.uk>

On Thursday 03 May 2012, Alan Cox wrote:
> 
> From: Alan Cox <alan@linux.intel.com>
> 
> In each remaining case the tty_lock is associated with a specific tty. This
> means we can now lock on a per tty basis. We do need tty_lock_pair() for
> the pty case. Uglier but still a step in the right direction.
> 
> Signed-off-by: Alan Cox <alan@linux.intel.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

^ permalink raw reply

* [PATCH 1/1] serial_core: Update buffer overrun statistics.
From: Corbin Atkinson @ 2012-05-04 17:35 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Alan Cox; +Cc: linux-serial, Corbin Atkinson

Currently, serial drivers don't report buffer overruns. When a buffer overrun
occurs, tty_insert_flip_char returns 0, and no attempt is made to insert that
same character again (i.e. it is lost). This patch reports buffer overruns via
the buf_overrun field in the port's icount structure.

Signed-off-by: Corbin Atkinson <corbin.atkinson@ni.com>
---
 drivers/tty/serial/serial_core.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 9c4c05b..59fb3ba 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2526,14 +2526,16 @@ void uart_insert_char(struct uart_port *port, unsigned int status,
 	struct tty_struct *tty = port->state->port.tty;
 
 	if ((status & port->ignore_status_mask & ~overrun) == 0)
-		tty_insert_flip_char(tty, ch, flag);
+		if (tty_insert_flip_char(tty, ch, flag) == 0)
+			++port->icount.buf_overrun;
 
 	/*
 	 * Overrun is special.  Since it's reported immediately,
 	 * it doesn't affect the current character.
 	 */
 	if (status & ~port->ignore_status_mask & overrun)
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0)
+			++port->icount.buf_overrun;
 }
 EXPORT_SYMBOL_GPL(uart_insert_char);
 
-- 
1.7.5.4


^ permalink raw reply related

* Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Alan Cox @ 2012-05-04 16:33 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Preston Fick, gregkh, linux-usb, linux-kernel, linux-serial,
	preston.fick
In-Reply-To: <1436626.86ImxHLlqB@ws-stein>

On Fri, 04 May 2012 18:26:58 +0200
Alexander Stein <a.stein@systec-electronic.com> wrote:

> Am Montag, 30. April 2012, 15:27:17 schrieb Preston Fick:
> > This fix contains several changes that allow toggling of GPIO on CP210x
> > devices that support it. Changes include:
> > * Added in part number support, necessary to see if the connected device
> > supports the GPIO functionality
> > * Added two IOCTLs and ioctl function to allow GET/SET of GPIO
> > * Added in new #defines for partnum support, new USB requests
> > * Changed "Config request types" section to contain more correct definitions
> > for request recipient
> > 
> > Signed-off-by: Preston Fick <preston.fick@silabs.com>
> 
> Do you actually need to create new ioctls? You also could support gpiolib and 
> create a gpiochip for that.

See my follow up posting, and comment on that proposal.

^ permalink raw reply

* Re: [PATCH 00/06] serial8250: DLL/DLM rework, Emma Mobile UART driver
From: Arnd Bergmann @ 2012-05-04 16:28 UTC (permalink / raw)
  To: Magnus Damm
  Cc: linux-serial, horms, linux-sh, gregkh, swarren, linux-kernel, rjw,
	paul.gortmaker, lethal, olof, dan.j.williams, alan
In-Reply-To: <20120502124642.30480.41373.sendpatchset@w520>

On Wednesday 02 May 2012, Magnus Damm wrote:
> Note that there is no DT support included at this point,
> but it boils down to a 10 line change. The boot loader on
> my board does not do DT so I'd like to use kexec for DT
> development (as usual), but to use kexec I first need to
> get a non-DT kernel working. Which is basically this. =)

As a follow-up on this, based on my comments to your emma platform
code, I think it would be easy enough to just use the appended
dtb support that we have, which allows you to boot a DT-enabled
kernel with a legacy boot loader.

	Arnd

^ permalink raw reply

* Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Alexander Stein @ 2012-05-04 16:26 UTC (permalink / raw)
  To: Preston Fick; +Cc: gregkh, linux-usb, linux-kernel, linux-serial, preston.fick
In-Reply-To: <1335817637-2862-1-git-send-email-preston.fick@silabs.com>

Am Montag, 30. April 2012, 15:27:17 schrieb Preston Fick:
> This fix contains several changes that allow toggling of GPIO on CP210x
> devices that support it. Changes include:
> * Added in part number support, necessary to see if the connected device
> supports the GPIO functionality
> * Added two IOCTLs and ioctl function to allow GET/SET of GPIO
> * Added in new #defines for partnum support, new USB requests
> * Changed "Config request types" section to contain more correct definitions
> for request recipient
> 
> Signed-off-by: Preston Fick <preston.fick@silabs.com>

Do you actually need to create new ioctls? You also could support gpiolib and 
create a gpiochip for that.

just my 2 cents,
Alexander


^ permalink raw reply

* RE: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)
From: Preston Fick @ 2012-05-04 15:27 UTC (permalink / raw)
  To: Alan Cox, Preston Fick
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org,
	linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW@public.gmane.org
In-Reply-To: <20120503213456.77c55c51-38n7/U1jhRXW96NNrWNlrekiAK3p4hvP@public.gmane.org>

Hi Alan -

Thanks for this detailed explanation - I'll continue to look deeper into this, a lot of this is new to me. If Greg is in agreement here, then I will work on this as a solution to our GPIO support and submit a series of patches for this when it's ready and tested.

Kind Regards -
Preston

-----Original Message-----
From: Alan Cox [mailto:alan-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org] 
Sent: Thursday, May 03, 2012 3:35 PM
To: Preston Fick
Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Preston Fick; linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW@public.gmane.org
Subject: Re: [PATCH] usb: cp210x: Added support for GPIO (CP2103/4/5)


Ok this is my suggestion based on GregKH comments and a couple of others
plus some other driver and ldisc stuff that is pending

- register the gpio lines with the gpio layer dynamically
- put them in the right place in the device tree (I'll let Greg advise on
  the best way to do that bit), plus make them visible via the ioctls for
  convenience and as they will be needed anyway in kernel

That provides the user space API

After that I'll add the hooks to the core tty layer code which allow an
ldisc to adjust the gpio lines.

For that we'll need

struct tty_gpio {
	u32 base;
	u16 num;
	u16 reserved;
#define NR_TTY_GPIOMAP 8
	u16 map[NR_TTY_GPIOMAP];
	u32 reserved2[4];
};

and

tty->gpiomap

which will be NULL for most users.


Plus

struct tty_gpio d;
ioctl(tty, TIOCGPIO, &d)

and

ioctl(tty, TIOCSGPIO, &d)

where the only bits that can be updated will be the map.



So the normal use case from user space would be

struct tty_gpio d;
int fd = open("/dev/ttyUSB0", O_RDWR);
ioctl(tty, TIOCSGPIO, &d);

stuff using the gpio driver interfaces

close(fd);


And setting up for a kernel ldisc something like


/* Set a GPIO to LDISC signal mapping for ISO7816 */
ioctl(tty, TIOCGPIO, &d);
d.map[TTY_GPIO_ISO7816_RESET] = d.base;
d.map]TTY_GPIO_ISO7816_VCC] = d.base + 1;
ioctl(tty, TIOCSGPIO, &d);

/* Switch to the ldisc */
ld = N_ISO7816;
ioctl(tty, TCSETD, &ld);


and we can then abstract all the wiring details away to keep the ldisc
portable.


Thoughts ?

Alan
This message (including any attachments) is intended only for the use of the individual or entity to which it is addressed and may contain information that is non-public, proprietary, privileged, confidential, and exempt from disclosure under applicable law or may constitute as attorney work product.  If you are not the intended recipient, you are hereby notified that any use, dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, notify us immediately by telephone and (i) destroy this message if a facsimile or (ii) delete this message immediately if this is an electronic communication.  

Thank you.


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 10/14] SERIAL: MIPS: lantiq: implement OF support
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Alan Cox, linux-serial
In-Reply-To: <1336133919-26525-1-git-send-email-blogic@openwrt.org>

Add devicetree and handling for our new clkdev clocks. The patch is rather
straightforward. .of_match_table is set and the 3 irqs are now loaded from the
devicetree.

This series converts the lantiq target to clkdev amongst other things. The
driver needs to handle two clocks now. The fpi bus clock used to derive the
divider and the clock gate needed on some socs to make the secondary port work.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Alan Cox <alan@linux.intel.com>
Cc: linux-serial@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 drivers/tty/serial/lantiq.c |   83 ++++++++++++++++++++++++++----------------
 1 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 96c1cac..b5044fa 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -31,16 +31,19 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
-#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 
 #include <lantiq_soc.h>
 
 #define PORT_LTQ_ASC		111
 #define MAXPORTS		2
 #define UART_DUMMY_UER_RX	1
-#define DRVNAME			"ltq_asc"
+#define DRVNAME			"lantiq,asc"
 #ifdef __BIG_ENDIAN
 #define LTQ_ASC_TBUF		(0x0020 + 3)
 #define LTQ_ASC_RBUF		(0x0024 + 3)
@@ -114,6 +117,9 @@ static DEFINE_SPINLOCK(ltq_asc_lock);
 
 struct ltq_uart_port {
 	struct uart_port	port;
+	/* clock used to derive divider */
+	struct clk		*fpiclk;
+	/* clock gating of the ASC core */
 	struct clk		*clk;
 	unsigned int		tx_irq;
 	unsigned int		rx_irq;
@@ -316,7 +322,9 @@ lqasc_startup(struct uart_port *port)
 	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 	int retval;
 
-	port->uartclk = clk_get_rate(ltq_port->clk);
+	if (ltq_port->clk)
+		clk_enable(ltq_port->clk);
+	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
 	ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
 		port->membase + LTQ_ASC_CLC);
@@ -382,6 +390,8 @@ lqasc_shutdown(struct uart_port *port)
 		port->membase + LTQ_ASC_RXFCON);
 	ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
 		port->membase + LTQ_ASC_TXFCON);
+	if (ltq_port->clk)
+		clk_disable(ltq_port->clk);
 }
 
 static void
@@ -630,7 +640,7 @@ lqasc_console_setup(struct console *co, char *options)
 
 	port = &ltq_port->port;
 
-	port->uartclk = clk_get_rate(ltq_port->clk);
+	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -668,37 +678,32 @@ static struct uart_driver lqasc_reg = {
 static int __init
 lqasc_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct ltq_uart_port *ltq_port;
 	struct uart_port *port;
-	struct resource *mmres, *irqres;
-	int tx_irq, rx_irq, err_irq;
-	struct clk *clk;
+	struct resource *mmres, irqres[3];
+	int line = 0;
 	int ret;
 
 	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
+	ret = of_irq_to_resource_table(node, irqres, 3);
+	if (!mmres || (ret != 3)) {
+		dev_err(&pdev->dev,
+			"failed to get memory/irq for serial port\n");
 		return -ENODEV;
+	}
 
-	if (pdev->id >= MAXPORTS)
-		return -EBUSY;
+	/* check if this is the console port */
+	if (mmres->start != LTQ_ASC1_BASE_ADDR)
+		line = 1;
 
-	if (lqasc_port[pdev->id] != NULL)
+	if (lqasc_port[line]) {
+		dev_err(&pdev->dev, "port %d already allocated\n", line);
 		return -EBUSY;
-
-	clk = clk_get(&pdev->dev, "fpi");
-	if (IS_ERR(clk)) {
-		pr_err("failed to get fpi clk\n");
-		return -ENOENT;
 	}
 
-	tx_irq = platform_get_irq_byname(pdev, "tx");
-	rx_irq = platform_get_irq_byname(pdev, "rx");
-	err_irq = platform_get_irq_byname(pdev, "err");
-	if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0))
-		return -ENODEV;
-
-	ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
+	ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port),
+			GFP_KERNEL);
 	if (!ltq_port)
 		return -ENOMEM;
 
@@ -709,19 +714,26 @@ lqasc_probe(struct platform_device *pdev)
 	port->ops	= &lqasc_pops;
 	port->fifosize	= 16;
 	port->type	= PORT_LTQ_ASC,
-	port->line	= pdev->id;
+	port->line	= line;
 	port->dev	= &pdev->dev;
-
-	port->irq	= tx_irq; /* unused, just to be backward-compatibe */
+	/* unused, just to be backward-compatible */
+	port->irq	= irqres[0].start;
 	port->mapbase	= mmres->start;
 
-	ltq_port->clk	= clk;
+	ltq_port->fpiclk = clk_get_fpi();
+	if (IS_ERR(ltq_port->fpiclk)) {
+		pr_err("failed to get fpi clk\n");
+		return -ENOENT;
+	}
 
-	ltq_port->tx_irq = tx_irq;
-	ltq_port->rx_irq = rx_irq;
-	ltq_port->err_irq = err_irq;
+	/* not all asc ports have clock gates, lets ignore the return code */
+	ltq_port->clk = clk_get(&pdev->dev, NULL);
 
-	lqasc_port[pdev->id] = ltq_port;
+	ltq_port->tx_irq = irqres[0].start;
+	ltq_port->rx_irq = irqres[1].start;
+	ltq_port->err_irq = irqres[2].start;
+
+	lqasc_port[line] = ltq_port;
 	platform_set_drvdata(pdev, ltq_port);
 
 	ret = uart_add_one_port(&lqasc_reg, port);
@@ -729,10 +741,17 @@ lqasc_probe(struct platform_device *pdev)
 	return ret;
 }
 
+static const struct of_device_id ltq_asc_match[] = {
+	{ .compatible = DRVNAME },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_asc_match);
+
 static struct platform_driver lqasc_driver = {
 	.driver		= {
 		.name	= DRVNAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = ltq_asc_match,
 	},
 };
 
-- 
1.7.9.1


^ permalink raw reply related

* Urgent Letter
From: Microsoft  Notification @ 2012-05-04 11:08 UTC (permalink / raw)
  To: Recipients

We wish to inform you that you have won (One Million British Pound Sterlings) in the Microsoft Online Monthly Lottery held this month of April with Ticket Number (EKT/LTUK/3410) and the Lucky Numbers (BTUK5890BD) (01) For claim of Prize,please forward to us 1.Name: 2.Address 3.Age: 4.Sex: 5.Phone: 6.Country:7:Ticket Number and Lucky Number Contact: Mrs.Rita Hall. claims_dept25@kimo.com

Congratulations once again.
Yours faithfully,
Mrs.Rita Hall.
On-line Coordinator

^ permalink raw reply

* Using quad uart st16c554 on at91rm9200 linux 2.6.30 board
From: Dmitriy Alekseev @ 2012-05-04  8:34 UTC (permalink / raw)
  To: linux-serial@vger.kernel.org

Hello, Developers.



Trying to add support of st16c554 quad uart in at91rm9200 based board.
First, doing menuconfig...
From /drivers/serial/Konfig:
config SERIAL_8250_EXAR_ST16C554
tristate "Support Exar ST16C554/554D Quad UART"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
ISA required, but isn't avaiable for at91 system type:
Symbol: ISA [=n]                                                        
  Type  : boolean                                                        
     Selected by: ARCH_EBSA110 [=n] && <choice> || ARCH_SA1100 [=n] && ... no AT91


Nevertheless, this message http://www.spinics.net/lists/arm-kernel/msg55077.html gives hope that it is possible.
But how? 
If this device is not supporting, suggest me please, what better to use instead.

Thanks.
Best regards,
Dmitriy Alekseev
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 3/3] tty_lock: Localise the lock
From: Alan Cox @ 2012-05-03 21:24 UTC (permalink / raw)
  To: linux-kernel, linux-serial
In-Reply-To: <20120503212151.568.91854.stgit@bob.linux.org.uk>

From: Alan Cox <alan@linux.intel.com>

In each remaining case the tty_lock is associated with a specific tty. This
means we can now lock on a per tty basis. We do need tty_lock_pair() for
the pty case. Uglier but still a step in the right direction.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/tty/amiserial.c   |   12 ++++----
 drivers/tty/cyclades.c    |    2 +
 drivers/tty/n_r3964.c     |   11 ++++---
 drivers/tty/pty.c         |   23 +++++++++------
 drivers/tty/synclink.c    |    4 +--
 drivers/tty/synclink_gt.c |    4 +--
 drivers/tty/synclinkmp.c  |    4 +--
 drivers/tty/tty_io.c      |   67 +++++++++++++++++++++++++++------------------
 drivers/tty/tty_ldisc.c   |   30 ++++++++++----------
 drivers/tty/tty_mutex.c   |   60 ++++++++++++++++++++++++++++++----------
 drivers/tty/tty_port.c    |    6 ++--
 include/linux/tty.h       |   23 +++++++++------
 12 files changed, 149 insertions(+), 97 deletions(-)


diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 6cc4358..b88a65c 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
 	if (!retinfo)
 		return -EFAULT;
 	memset(&tmp, 0, sizeof(tmp));
-	tty_lock();
+	tty_lock(tty);
 	tmp.line = tty->index;
 	tmp.port = state->port;
 	tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
 	tmp.close_delay = state->tport.close_delay;
 	tmp.closing_wait = state->tport.closing_wait;
 	tmp.custom_divisor = state->custom_divisor;
-	tty_unlock();
+	tty_unlock(tty);
 	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
 		return -EFAULT;
 	return 0;
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
 	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
 		return -EFAULT;
 
-	tty_lock();
+	tty_lock(tty);
 	change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
 		new_serial.custom_divisor != state->custom_divisor;
 	if (new_serial.irq || new_serial.port != state->port ||
 			new_serial.xmit_fifo_size != state->xmit_fifo_size) {
-		tty_unlock();
+		tty_unlock(tty);
 		return -EINVAL;
 	}
   
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
 	}
 
 	if (new_serial.baud_base < 9600) {
-		tty_unlock();
+		tty_unlock(tty);
 		return -EINVAL;
 	}
 
@@ -1116,7 +1116,7 @@ check_and_exit:
 		}
 	} else
 		retval = startup(tty, state);
-	tty_unlock();
+	tty_unlock(tty);
 	return retval;
 }
 
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index e61cabd..6984e1a 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 	 * If the port is the middle of closing, bail out now
 	 */
 	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(info->port.close_wait,
+		wait_event_interruptible_tty(tty, info->port.close_wait,
 				!(info->port.flags & ASYNC_CLOSING));
 		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
 	}
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c314..656ad93 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 
 	TRACE_L("read()");
 
-	tty_lock();
+	/* FIXME: should use a private lock */
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 				goto unlock;
 			}
 			/* block until there is a message: */
-			wait_event_interruptible_tty(pInfo->read_wait,
+			wait_event_interruptible_tty(tty, pInfo->read_wait,
 					(pMsg = remove_msg(pInfo, pClient)));
 		}
 
@@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 	}
 	ret = -EPERM;
 unlock:
-	tty_unlock();
+	tty_unlock(tty);
 	return ret;
 }
 
@@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	pHeader->locks = 0;
 	pHeader->owner = NULL;
 
-	tty_lock();
+	tty_lock(tty);
 
 	pClient = findClient(pInfo, task_pid(current));
 	if (pClient) {
@@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 	add_tx_queue(pInfo, pHeader);
 	trigger_transmit(pInfo);
 
-	tty_unlock();
+	tty_unlock(tty);
 
 	return 0;
 }
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5505ffc..d6fa842 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 	wake_up_interruptible(&tty->read_wait);
 	wake_up_interruptible(&tty->write_wait);
 	tty->packet = 0;
+	/* Review - krefs on tty_link ?? */
 	if (!tty->link)
 		return;
 	tty->link->packet = 0;
@@ -62,9 +63,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 		        mutex_unlock(&devpts_mutex);
 		}
 #endif
-		tty_unlock();
 		tty_vhangup(tty->link);
-		tty_lock();
 	}
 }
 
@@ -622,26 +621,29 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 		return retval;
 
 	/* find a device that is not in use. */
-	tty_lock();
+	mutex_lock(&devpts_mutex);
 	index = devpts_new_index(inode);
-	tty_unlock();
 	if (index < 0) {
 		retval = index;
 		goto err_file;
 	}
 
+	mutex_unlock(&devpts_mutex);
+
 	mutex_lock(&tty_mutex);
 	mutex_lock(&devpts_mutex);
 	tty = tty_init_dev(ptm_driver, index);
-	mutex_unlock(&devpts_mutex);
-	tty_lock();
-	mutex_unlock(&tty_mutex);
 
 	if (IS_ERR(tty)) {
 		retval = PTR_ERR(tty);
 		goto out;
 	}
 
+	/* The tty returned here is locked so we can safely
+	   drop the mutex */
+	mutex_unlock(&devpts_mutex);
+	mutex_unlock(&tty_mutex);
+
 	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
 	tty_add_file(tty, filp);
@@ -654,16 +656,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 	if (retval)
 		goto err_release;
 
-	tty_unlock();
+	tty_unlock(tty);
 	return 0;
 err_release:
-	tty_unlock();
+	tty_unlock(tty);
 	tty_release(inode, filp);
 	return retval;
 out:
+	mutex_unlock(&tty_mutex);
 	devpts_kill_index(inode, index);
-	tty_unlock();
 err_file:
+        mutex_unlock(&devpts_mutex);
 	tty_free_file(filp);
 	return retval;
 }
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index d063b7d..bc1ae4a 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			printk("%s(%d):block_til_ready blocking on %s count=%d\n",
 				 __FILE__,__LINE__, tty->driver->name, port->count );
 				 
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 	
 	set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index fcde827..df4f0dc 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3337,9 +3337,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 		}
 
 		DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 
 	set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index a040a46..845502f 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -3358,9 +3358,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 			printk("%s(%d):%s block_til_ready() count=%d\n",
 				 __FILE__,__LINE__, tty->driver->name, port->count );
 
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 
 	set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..9e930c0 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)
 		put_device(tty->dev);
 	kfree(tty->write_buf);
 	tty_buffer_free_all(tty);
+	tty->magic = 0xDEADDEAD;
 	kfree(tty);
 }
 
@@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)
 	}
 	spin_unlock(&redirect_lock);
 
-	tty_lock();
+	tty_lock(tty);
 
 	/* some functions below drop BTM, so we need this bit */
 	set_bit(TTY_HUPPING, &tty->flags);
@@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)
 	clear_bit(TTY_HUPPING, &tty->flags);
 	tty_ldisc_enable(tty);
 
-	tty_unlock();
+	tty_unlock(tty);
 
 	if (f)
 		fput(f);
@@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)
 {
 	if (tty) {
 		mutex_lock(&tty->atomic_write_lock);
-		tty_lock();
+		tty_lock(tty);
 		if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
-			tty_unlock();
+			tty_unlock(tty);
 			tty->ops->write(tty, msg, strlen(msg));
 		} else
-			tty_unlock();
+			tty_unlock(tty);
 		tty_write_unlock(tty);
 	}
 	return;
@@ -1403,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
 	}
 	initialize_tty_struct(tty, driver, idx);
 
+	tty_lock(tty);
 	retval = tty_driver_install_tty(driver, tty);
 	if (retval < 0)
 		goto err_deinit_tty;
@@ -1415,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
 	retval = tty_ldisc_setup(tty, tty->link);
 	if (retval)
 		goto err_release_tty;
+	/* Return the tty locked so that it cannot vanish under the caller */
 	return tty;
 
 err_deinit_tty:
+	tty_unlock(tty);
 	deinitialize_tty_struct(tty);
 	free_tty_struct(tty);
 err_module_put:
@@ -1426,6 +1430,7 @@ err_module_put:
 
 	/* call the tty release_tty routine to clean out this slot */
 err_release_tty:
+	tty_unlock(tty);
 	printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
 				 "clearing slot %d\n", idx);
 	release_tty(tty, idx);
@@ -1628,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp)
 	if (tty_paranoia_check(tty, inode, __func__))
 		return 0;
 
-	tty_lock();
+	tty_lock(tty);
 	check_tty_count(tty, __func__);
 
 	__tty_fasync(-1, filp, 0);
@@ -1637,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp)
 	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 		      tty->driver->subtype == PTY_TYPE_MASTER);
 	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
+	/* Review: parallel close */
 	o_tty = tty->link;
 
 	if (tty_release_checks(tty, o_tty, idx)) {
-		tty_unlock();
+		tty_unlock(tty);
 		return 0;
 	}
 
@@ -1652,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp)
 	if (tty->ops->close)
 		tty->ops->close(tty, filp);
 
-	tty_unlock();
+	tty_unlock(tty);
 	/*
 	 * Sanity check: if tty->count is going to zero, there shouldn't be
 	 * any waiters on tty->read_wait or tty->write_wait.  We test the
@@ -1675,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp)
 		   opens on /dev/tty */
 
 		mutex_lock(&tty_mutex);
-		tty_lock();
+		tty_lock_pair(tty, o_tty);
 		tty_closing = tty->count <= 1;
 		o_tty_closing = o_tty &&
 			(o_tty->count <= (pty_master ? 1 : 0));
@@ -1706,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp)
 
 		printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
 				__func__, tty_name(tty, buf));
-		tty_unlock();
+		tty_unlock_pair(tty, o_tty);
 		mutex_unlock(&tty_mutex);
 		schedule();
 	}
@@ -1769,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp)
 
 	/* check whether both sides are closing ... */
 	if (!tty_closing || (o_tty && !o_tty_closing)) {
-		tty_unlock();
+		tty_unlock_pair(tty, o_tty);
 		return 0;
 	}
 
@@ -1782,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp)
 	tty_ldisc_release(tty, o_tty);
 	/*
 	 * The release_tty function takes care of the details of clearing
-	 * the slots and preserving the termios structure.
+	 * the slots and preserving the termios structure. The tty_unlock_pair
+	 * should be safe as we keep a kref while the tty is locked (so the
+	 * unlock never unlocks a freed tty).
 	 */
 	release_tty(tty, idx);
+	tty_unlock_pair(tty, o_tty);
 
 	/* Make this pty number available for reallocation */
 	if (devpts)
 		devpts_kill_index(inode, idx);
-	tty_unlock();
 	return 0;
 }
 
@@ -1893,6 +1901,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
  *	Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
  *		 tty->count should protect the rest.
  *		 ->siglock protects ->signal/->sighand
+ *
+ *	Note: the tty_unlock/lock cases without a ref are only safe due to
+ *	tty_mutex
  */
 
 static int tty_open(struct inode *inode, struct file *filp)
@@ -1916,8 +1927,7 @@ retry_open:
 	retval = 0;
 
 	mutex_lock(&tty_mutex);
-	tty_lock();
-
+	/* This is protected by the tty_mutex */
 	tty = tty_open_current_tty(device, filp);
 	if (IS_ERR(tty)) {
 		retval = PTR_ERR(tty);
@@ -1938,17 +1948,19 @@ retry_open:
 	}
 
 	if (tty) {
+		tty_lock(tty);
 		retval = tty_reopen(tty);
-		if (retval)
+		if (retval < 0) {
+			tty_unlock(tty);
 			tty = ERR_PTR(retval);
-	} else
+		}
+	} else	/* Returns with the tty_lock held for now */
 		tty = tty_init_dev(driver, index);
 
 	mutex_unlock(&tty_mutex);
 	if (driver)
 		tty_driver_kref_put(driver);
 	if (IS_ERR(tty)) {
-		tty_unlock();
 		retval = PTR_ERR(tty);
 		goto err_file;
 	}
@@ -1977,7 +1989,7 @@ retry_open:
 		printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
 				retval, tty->name);
 #endif
-		tty_unlock(); /* need to call tty_release without BTM */
+		tty_unlock(tty); /* need to call tty_release without BTM */
 		tty_release(inode, filp);
 		if (retval != -ERESTARTSYS)
 			return retval;
@@ -1989,17 +2001,15 @@ retry_open:
 		/*
 		 * Need to reset f_op in case a hangup happened.
 		 */
-		tty_lock();
 		if (filp->f_op == &hung_up_tty_fops)
 			filp->f_op = &tty_fops;
-		tty_unlock();
 		goto retry_open;
 	}
-	tty_unlock();
+	tty_unlock(tty);
 
 
 	mutex_lock(&tty_mutex);
-	tty_lock();
+	tty_lock(tty);
 	spin_lock_irq(&current->sighand->siglock);
 	if (!noctty &&
 	    current->signal->leader &&
@@ -2007,11 +2017,10 @@ retry_open:
 	    tty->session == NULL)
 		__proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
-	tty_unlock();
+	tty_unlock(tty);
 	mutex_unlock(&tty_mutex);
 	return 0;
 err_unlock:
-	tty_unlock();
 	mutex_unlock(&tty_mutex);
 	/* after locks to avoid deadlock */
 	if (!IS_ERR_OR_NULL(driver))
@@ -2094,10 +2103,13 @@ out:
 
 static int tty_fasync(int fd, struct file *filp, int on)
 {
+	struct tty_struct *tty = file_tty(filp);
 	int retval;
-	tty_lock();
+
+	tty_lock(tty);
 	retval = __tty_fasync(fd, filp, on);
-	tty_unlock();
+	tty_unlock(tty);
+
 	return retval;
 }
 
@@ -2934,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty,
 	tty->pgrp = NULL;
 	tty->overrun_time = jiffies;
 	tty_buffer_init(tty);
+	mutex_init(&tty->legacy_mutex);
 	mutex_init(&tty->termios_mutex);
 	mutex_init(&tty->ldisc_mutex);
 	init_waitqueue_head(&tty->write_wait);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 24b95db..fa65cde 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	if (IS_ERR(new_ldisc))
 		return PTR_ERR(new_ldisc);
 
-	tty_lock();
+	tty_lock(tty);
 	/*
 	 *	We need to look at the tty locking here for pty/tty pairs
 	 *	when both sides try to change in parallel.
@@ -581,12 +581,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	 */
 
 	if (tty->ldisc->ops->num == ldisc) {
-		tty_unlock();
+		tty_unlock(tty);
 		tty_ldisc_put(new_ldisc);
 		return 0;
 	}
 
-	tty_unlock();
+	tty_unlock(tty);
 	/*
 	 *	Problem: What do we do if this blocks ?
 	 *	We could deadlock here
@@ -594,7 +594,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 	tty_wait_until_sent(tty, 0);
 
-	tty_lock();
+	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
 
 	/*
@@ -604,10 +604,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 	while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
 		mutex_unlock(&tty->ldisc_mutex);
-		tty_unlock();
+		tty_unlock(tty);
 		wait_event(tty_ldisc_wait,
 			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
-		tty_lock();
+		tty_lock(tty);
 		mutex_lock(&tty->ldisc_mutex);
 	}
 
@@ -622,7 +622,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 	o_ldisc = tty->ldisc;
 
-	tty_unlock();
+	tty_unlock(tty);
 	/*
 	 *	Make sure we don't change while someone holds a
 	 *	reference to the line discipline. The TTY_LDISC bit
@@ -649,7 +649,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 	retval = tty_ldisc_wait_idle(tty, 5 * HZ);
 
-	tty_lock();
+	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
 
 	/* handle wait idle failure locked */
@@ -664,7 +664,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 		clear_bit(TTY_LDISC_CHANGING, &tty->flags);
 		mutex_unlock(&tty->ldisc_mutex);
 		tty_ldisc_put(new_ldisc);
-		tty_unlock();
+		tty_unlock(tty);
 		return -EIO;
 	}
 
@@ -707,7 +707,7 @@ enable:
 	if (o_work)
 		schedule_work(&o_tty->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
-	tty_unlock();
+	tty_unlock(tty);
 	return retval;
 }
 
@@ -815,11 +815,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 	 * need to wait for another function taking the BTM
 	 */
 	clear_bit(TTY_LDISC, &tty->flags);
-	tty_unlock();
+	tty_unlock(tty);
 	cancel_work_sync(&tty->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
 retry:
-	tty_lock();
+	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
 
 	/* At this point we have a closed ldisc and we want to
@@ -830,7 +830,7 @@ retry:
 		if (atomic_read(&tty->ldisc->users) != 1) {
 			char cur_n[TASK_COMM_LEN], tty_n[64];
 			long timeout = 3 * HZ;
-			tty_unlock();
+			tty_unlock(tty);
 
 			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
 				timeout = MAX_SCHEDULE_TIMEOUT;
@@ -911,10 +911,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 	 * race with the set_ldisc code path.
 	 */
 
-	tty_unlock();
+	tty_unlock(tty);
 	tty_ldisc_halt(tty);
 	tty_ldisc_flush_works(tty);
-	tty_lock();
+	tty_lock(tty);
 
 	mutex_lock(&tty->ldisc_mutex);
 	/*
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c..69adc80 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,29 +4,59 @@
 #include <linux/semaphore.h>
 #include <linux/sched.h>
 
-/*
- * The 'big tty mutex'
- *
- * This mutex is taken and released by tty_lock() and tty_unlock(),
- * replacing the older big kernel lock.
- * It can no longer be taken recursively, and does not get
- * released implicitly while sleeping.
- *
- * Don't use in new code.
- */
-static DEFINE_MUTEX(big_tty_mutex);
+/* Legacy tty mutex glue */
 
 /*
  * Getting the big tty mutex.
  */
-void __lockfunc tty_lock(void)
+
+void __lockfunc tty_lock(struct tty_struct *tty)
 {
-	mutex_lock(&big_tty_mutex);
+	if (tty->magic != TTY_MAGIC) {
+		printk(KERN_ERR "L Bad %p\n", tty);
+		WARN_ON(1);
+		return;
+	}
+	tty_kref_get(tty);
+	mutex_lock(&tty->legacy_mutex);
 }
 EXPORT_SYMBOL(tty_lock);
 
-void __lockfunc tty_unlock(void)
+void __lockfunc tty_unlock(struct tty_struct *tty)
 {
-	mutex_unlock(&big_tty_mutex);
+	if (tty->magic != TTY_MAGIC) {
+		printk(KERN_ERR "U Bad %p\n", tty);
+		WARN_ON(1);
+		return;
+	}
+	mutex_unlock(&tty->legacy_mutex);
+	tty_kref_put(tty);
 }
 EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Getting the big tty mutex for a pair of ttys with lock ordering
+ * On a non pty/tty pair tty2 can be NULL which is just fine.
+ */
+void __lockfunc tty_lock_pair(struct tty_struct *tty,
+					struct tty_struct *tty2)
+{
+	if (tty < tty2) {
+		tty_lock(tty);
+		tty_lock(tty2);
+	} else {
+		if (tty2 && tty2 != tty)
+			tty_lock(tty2);
+		tty_lock(tty);
+	}
+}
+EXPORT_SYMBOL(tty_lock_pair);
+
+void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+						struct tty_struct *tty2)
+{
+	tty_unlock(tty);
+	if (tty2 && tty2 != tty)
+		tty_unlock(tty2);
+}
+EXPORT_SYMBOL(tty_unlock_pair);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index d24807a..64f0975 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -237,7 +237,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 
 	/* block if port is in the process of being closed */
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-		wait_event_interruptible_tty(port->close_wait,
+		wait_event_interruptible_tty(tty, port->close_wait,
 				!(port->flags & ASYNC_CLOSING));
 		if (port->flags & ASYNC_HUP_NOTIFY)
 			return -EAGAIN;
@@ -303,9 +303,9 @@ int tty_port_block_til_ready(struct tty_port *port,
 			retval = -ERESTARTSYS;
 			break;
 		}
-		tty_unlock();
+		tty_unlock(tty);
 		schedule();
-		tty_lock();
+		tty_lock(tty);
 	}
 	finish_wait(&port->open_wait, &wait);
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..4990ef2 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -268,6 +268,7 @@ struct tty_struct {
 	struct mutex ldisc_mutex;
 	struct tty_ldisc *ldisc;
 
+	struct mutex legacy_mutex;
 	struct mutex termios_mutex;
 	spinlock_t ctrl_lock;
 	/* Termios values are protected by the termios mutex */
@@ -605,8 +606,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
 
 /* tty_mutex.c */
 /* functions for preparation of BKL removal */
-extern void __lockfunc tty_lock(void) __acquires(tty_lock);
-extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern void __lockfunc tty_unlock(struct tty_struct *tty);
+extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
+				struct tty_struct *tty2);
+extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+				struct tty_struct *tty2);
 
 /*
  * this shall be called only from where BTM is held (like close)
@@ -621,9 +626,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);
 static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
 		long timeout)
 {
-	tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
+	tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
 	tty_wait_until_sent(tty, timeout);
-	tty_lock();
+	tty_lock(tty);
 }
 
 /*
@@ -638,16 +643,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
  *
  * Do not use in new code.
  */
-#define wait_event_interruptible_tty(wq, condition)			\
+#define wait_event_interruptible_tty(tty, wq, condition)		\
 ({									\
 	int __ret = 0;							\
 	if (!(condition)) {						\
-		__wait_event_interruptible_tty(wq, condition, __ret);	\
+		__wait_event_interruptible_tty(tty, wq, condition, __ret);	\
 	}								\
 	__ret;								\
 })
 
-#define __wait_event_interruptible_tty(wq, condition, ret)		\
+#define __wait_event_interruptible_tty(tty, wq, condition, ret)		\
 do {									\
 	DEFINE_WAIT(__wait);						\
 									\
@@ -656,9 +661,9 @@ do {									\
 		if (condition)						\
 			break;						\
 		if (!signal_pending(current)) {				\
-			tty_unlock();					\
+			tty_unlock(tty);					\
 			schedule();					\
-			tty_lock();					\
+			tty_lock(tty);					\
 			continue;					\
 		}							\
 		ret = -ERESTARTSYS;					\


^ permalink raw reply related


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