* [PATCH] serial: omap: fix DeviceTree boot
From: Felipe Balbi @ 2012-09-07 18:10 UTC (permalink / raw)
To: Greg KH
Cc: linux-serial, Tony Lindgren, Linux OMAP Mailing List,
Linux ARM Kernel Mailing List, Felipe Balbi
In-Reply-To: <20120907175721.GD1303@atomide.com>
OMAP Architecture code, passes a few function
pointers for UART driver to use in order to
properly implement Power Management and Wakeup
capabilities.
The problem is that those function pointers,
which are passed (ab)using platform_data on
non-DT kernels, can't be passed down to drivers
through DT.
commit e5b57c0 (serial: omap: define helpers
for pdata function pointers) failed to take DT
kernels into consideration and caused a regression
to DT kernel boot.
Fix that by (re-)adding a check for valid pdata
pointer together with valid pdata->$FUNCTION
pointer.
Reported-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
Tony, does this solve the issue ?
drivers/tty/serial/omap-serial.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0a6e78e..743e8e1 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -143,7 +143,7 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (!pdata->get_context_loss_count)
+ if (!pdata || !pdata->get_context_loss_count)
return 0;
return pdata->get_context_loss_count(up->dev);
@@ -153,24 +153,30 @@ static void serial_omap_set_forceidle(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->set_forceidle)
- pdata->set_forceidle(up->dev);
+ if (!pdata || !pdata->set_forceidle)
+ return;
+
+ pdata->set_forceidle(up->dev);
}
static void serial_omap_set_noidle(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->set_noidle)
- pdata->set_noidle(up->dev);
+ if (!pdata || !pdata->set_noidle)
+ return;
+
+ pdata->set_noidle(up->dev);
}
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->enable_wakeup)
- pdata->enable_wakeup(up->dev, enable);
+ if (!pdata || !pdata->enable_wakeup)
+ return;
+
+ pdata->enable_wakeup(up->dev, enable);
}
/*
--
1.7.12.rc3
^ permalink raw reply related
* Re: [PATCH] serial: omap: fix DeviceTree boot
From: Tony Lindgren @ 2012-09-07 18:26 UTC (permalink / raw)
To: Felipe Balbi
Cc: Greg KH, linux-serial, Linux OMAP Mailing List,
Linux ARM Kernel Mailing List
In-Reply-To: <1347041433-11723-1-git-send-email-balbi@ti.com>
* Felipe Balbi <balbi@ti.com> [120907 11:15]:
> OMAP Architecture code, passes a few function
> pointers for UART driver to use in order to
> properly implement Power Management and Wakeup
> capabilities.
>
> The problem is that those function pointers,
> which are passed (ab)using platform_data on
> non-DT kernels, can't be passed down to drivers
> through DT.
>
> commit e5b57c0 (serial: omap: define helpers
> for pdata function pointers) failed to take DT
> kernels into consideration and caused a regression
> to DT kernel boot.
>
> Fix that by (re-)adding a check for valid pdata
> pointer together with valid pdata->$FUNCTION
> pointer.
>
> Reported-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> ---
>
> Tony, does this solve the issue ?
Yes thanks console works again now:
Tested-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply
* Re: [PATCH] serial: omap: Request pins using pinctrl framework
From: Tony Lindgren @ 2012-09-07 18:27 UTC (permalink / raw)
To: Greg KH; +Cc: linux-serial, linux-omap, linux-arm-kernel
In-Reply-To: <20120907175939.GE1303@atomide.com>
* Tony Lindgren <tony@atomide.com> [120907 11:00]:
> Request pins using pinctrl framework. Only show a warning
> on error as some boards set the pins in the bootloader
> even if CONFIG_PINCTRL is enabled.
>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
>
> ---
>
> Note that this has only so far been tested with the legacy
> non-devicetree boot as devicetree boot now has a regression
> issue with omap-serial.
Now also tested with devicetree case on top tty-next +
Felipe's "[PATCH] serial: omap: fix DeviceTree boot.
Tony
> --- a/drivers/tty/serial/omap-serial.c
> +++ b/drivers/tty/serial/omap-serial.c
> @@ -40,6 +40,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/of.h>
> #include <linux/gpio.h>
> +#include <linux/pinctrl/consumer.h>
>
> #include <plat/omap-serial.h>
>
> @@ -108,6 +109,7 @@ struct uart_omap_port {
> u32 latency;
> u32 calc_latency;
> struct work_struct qos_work;
> + struct pinctrl *pins;
> };
>
> #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
> @@ -1371,6 +1373,13 @@ static int __devinit serial_omap_probe(struct platform_device *pdev)
> goto err_port_line;
> }
>
> + up->pins = devm_pinctrl_get_select_default(&pdev->dev);
> + if (IS_ERR(up->pins)) {
> + dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
> + up->port.line, PTR_ERR(up->pins));
> + up->pins = NULL;
> + }
> +
> sprintf(up->name, "OMAP UART%d", up->port.line);
> up->port.mapbase = mem->start;
> up->port.membase = devm_ioremap(&pdev->dev, mem->start,
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" 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 v4 00/21] OMAP UART Patches
From: Kevin Hilman @ 2012-09-07 20:53 UTC (permalink / raw)
To: balbi
Cc: Greg KH, Tony Lindgren, Linux Kernel Mailing List,
Santosh Shilimkar, linux-serial, Sourav Poddar,
Linux OMAP Mailing List, Shubhrajyoti Datta,
Linux ARM Kernel Mailing List, alan
In-Reply-To: <20120907054932.GB3136@arwen.pp.htv.fi>
Felipe Balbi <balbi@ti.com> writes:
> Hi,
>
> On Thu, Sep 06, 2012 at 03:44:13PM -0700, Kevin Hilman wrote:
>> Felipe Balbi <balbi@ti.com> writes:
>>
>> > Hi guys,
>> >
>> > here's v4 of the omap uart patchset. No changes other than a rebase on top of
>> > Greg's tty-next branch and Tony's Acked-by being added to a couple patches
>> >
>> > Note: I'm resending the series with Vikram's Software Flow Control fix anyway
>> > as it can just be ignored if it's decided it needs to go into this merge
>> > window.
>>
>> Sorry to be late to the party... just getting back from some time off.
>>
>> I'm assuming that this was not tested with PM, so decided I better do it
>
> you assumed wrong. See the previous versions of the series and you'll
> see I mention all the basic pm testing I did.
My apologies for not reading the previous versions. I don't think it's
unusual that a reviewer should expect everything he to know about a
series (including how it was tested) is in the cover letter or in the
changelogs of the latest series. I don't expect to have to look through
all the previous versions for this kind of info. Since I wasn't around
to review/test the earlier versions, I just looked at the latest (v4)
and didn't see any mention of testing of any sort in the cover letter.
Looking back at the previous cover letters, I don't see any description
of the PM testing either. I only see it was tested on pandaboard.
Since mainline doesn't have full PM support for OMAP4, testing on panda
doesn't really test UART PM at all.
Could you please point me to the descriptions in earlier mails of how
you did PM testing, and on what platforms?
In addition, IMO, if this was only tested on Panda (as suggested by
earlier cover letters), it really should not have been merged until it
got some broader testing.
>> myself seeing that Greg is has already merge it. To test, I merged
>> Greg's tty-next branch with v3.6-rc4 and did some PM testing.
>>
>> The bad news is that it doesn't even compile (see reply to [PATCH v4
>> 20/21]).
>
> yeah, that was an automerge issue when rebasing on greg's tty-next
> branch, plus me assuming omap serial was already enabled on my .config
> and not checking the compile output. Sent a patch now.
As I reported in my reply to [PATCH v4 20/21], that patch also had
another problem where it introduced a new (but unused) field. Maybe
another rebase problem? I see the same problem in v3 and v4.
>> Also, there is a big WARNING on boot[1], which seems to be triggered by
>> a new check added for v3.6-rc3[2]. This appears to be introduced by
>> $SUBJECT series, because I don't see it on vanilla v3.6-rc4.
[...]
> This doesn't seem to be caused by $SUBJECT at all. See that we are
> calling uart_add_one_port() which will call tty_port_register_device()
> which, in turn, will call tty_port_link_device() and that will set
> driver->ports[index] correctly.
>
> Have you checked if this doesn't happen without my series before waving
> your blame hammer ? FWIW, that part of the code wasn't change by
> $SUBJECT at all.
Whoa. This was only test report. No need to get personal. All I said
is that it "seemed" to introduced by $SUBJECT series. Hardly waiving
"blame hammer."
And yes, I did check without your series. As I reported above, the
warning didn't exist with v3.6-rc4, and it did with yesterday's tty-next
branch. The WARNING pointed a finger at ttyO (omap-serial) so I assumed
it was in $SUBJECT series.
Testing with todays tty-next, the problem is gone. The patch
'tty_register_device_attr updated for tty-next'[1] seems to have made
the problem go away. So it's now clear that it wasn't introduced by
$SUBJECT series. My bad.
Yesterday, it wasn't that obvious, so I made an assumption in order to
report a problem uncovered in my testing in the hopes that it would be
helpful to you in fixing a potential problem. My assumption was wrong, I
was wrong. I'm wrong a lot, and I'm OK with that. The bug was
elsewhere, and is already fixed.
My apologies if it seemed like I was blaming you.
Kevin
[1]
Author: Tomas Hlavacek <tmshlvck@gmail.com> 2012-09-06 14:17:47
Committer: Greg Kroah-Hartman <gregkh@linuxfoundation.org> 2012-09-06 14:40:18
Parent: 6915c0e487c822e2436683e14302c0b8a6155cc7 (tty: uartclk value from serial_core exposed to sysfs)
Child: e36851d0fa94b0f7802b3cc80406dbd3ef4f2f16 (serial: omap: fix compile breakage)
Branch: tmp/uart-test-2
Follows: v3.6-rc3
Precedes:
tty_register_device_attr updated for tty-next
Added tty_device_create_release() and bound to dev->release in
tty_register_device_attr().
Added tty_port_register_device_attr() and used in uart_add_one_port()
instead of tty_register_device_attr().
Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply
* [PATCH] msm_serial: fix clock rate on DMA-based uarts
From: David Brown @ 2012-09-07 21:45 UTC (permalink / raw)
To: David Brown, Daniel Walker, Bryan Huntsman, Alan Cox
Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-serial
The driver explicitly requests a clock rate for the UART, but it is
off by a factor of four from the dividers that it programs into the
UART. Fix this by setting the rate to 1/4 of the current value.
Signed-off-by: David Brown <davidb@codeaurora.org>
---
drivers/tty/serial/msm_serial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 8131e2c..033e0bc 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -896,7 +896,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
return PTR_ERR(msm_port->clk);
if (msm_port->is_uartdm)
- clk_set_rate(msm_port->clk, 7372800);
+ clk_set_rate(msm_port->clk, 1843200);
port->uartclk = clk_get_rate(msm_port->clk);
printk(KERN_INFO "uartclk = %d\n", port->uartclk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* Fwd: Bug in USB FTDI SIO driver
From: peter.sheeren @ 2012-09-08 10:14 UTC (permalink / raw)
To: linux-serial; +Cc: peter.sheeren
[-- Attachment #1: Type: text/plain, Size: 138 bytes --]
Hello
At the suggestion of Greg's friendly e-mail bot I'm sending my report
to this e-mail address. I hope it's the right one.
Peter
[-- Attachment #2: Forwarded Message: Bug in USB FTDI SIO driver --]
[-- Type: message/rfc822, Size: 2759 bytes --]
From: peter.sheeren@axiris.be
To: jhovold@gmail.com, greg@kroah.com
Subject: Bug in USB FTDI SIO driver
Date: Sat, 08 Sep 2012 04:21:06 +0200
Message-ID: <20120908042106.60247e3thepx3q1e@webmail.axiris.be>
Hello
I didn't find an easy way to file a bug report so I extracted the
source file ftdi_sio.c from the latest Linux kernel and browsed for
the e-mail addresses hence this e-mail.
I've been struggling with an annoying plug-and-play issue involving an
FT232RL-based USB device on ARM machines with Linux lately (including
Raspberry Pi and BeagleBoard). In a nutshell the following is happening:
* I plug in the FT232RL-based USB device. /dev/ttyUSB0 is created.
* I run an application that communicate with the device via
/dev/ttyUSB0. The application sets a baudrate - this is important. The
application reads and writes data successfully.
* I unplug the USB device. /dev/ttyUSB0 remains in existence - this is
important too.
* I replug the USB device. /dev/ttyUSB0 is still there.
* I rerun the application. The application again connects with
/dev/ttyUSB0 but it fails to transfer data. So it seems.
I ran I number of tests with a small program on my ARM based systems
and I discovered that the culprit is setting the baudrate. It turns
out that, after replugging the USB device, setting the baudrate is not
relayed to the USB device.
Since this looks like a caching problem, I tracked down the
corresponding source code in ftdi_sio.c and I'm confident the
following text is the cause of the problem:
(line 1375)
if (((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) ||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(old_priv.custom_divisor != priv->custom_divisor))) {
change_speed(tty, port);
Function change_speed() is called only when the baudrate
(custom_divisor) has changed but after a USB replug this assumption is
wrong. Also note that /dev/ttyUSB0 remains in existence on the system
under test. If it were up to me, I'd always send the baudrate setting
over the USB bus nomatter whether the baudrate (supposedly) has
changed or not.
I found a workaround for this bug: my software sets a different
baudrate prior to the intended baudrate hence fooling the ftdi_sio.c
code but ofcourse it's a workaround.
I hope this report will help you improve your driver.
Best regards,
Peter S'heeren
http://www.axiris.be/
^ permalink raw reply
* Re: Fwd: Bug in USB FTDI SIO driver
From: Greg KH @ 2012-09-08 15:45 UTC (permalink / raw)
To: peter.sheeren; +Cc: linux-serial
In-Reply-To: <20120908121439.15264wgwo05hva8f@webmail.axiris.be>
On Sat, Sep 08, 2012 at 12:14:39PM +0200, peter.sheeren@axiris.be wrote:
> Hello
>
> At the suggestion of Greg's friendly e-mail bot I'm sending my
> report to this e-mail address. I hope it's the right one.
>
> Peter
>
> Date: Sat, 08 Sep 2012 04:21:06 +0200
> From: peter.sheeren@axiris.be
> To: jhovold@gmail.com, greg@kroah.com
> Subject: Bug in USB FTDI SIO driver
>
>
> Hello
>
> I didn't find an easy way to file a bug report so I extracted the
> source file ftdi_sio.c from the latest Linux kernel and browsed for
> the e-mail addresses hence this e-mail.
>
> I've been struggling with an annoying plug-and-play issue involving
> an FT232RL-based USB device on ARM machines with Linux lately
> (including Raspberry Pi and BeagleBoard). In a nutshell the
> following is happening:
> * I plug in the FT232RL-based USB device. /dev/ttyUSB0 is created.
> * I run an application that communicate with the device via
> /dev/ttyUSB0. The application sets a baudrate - this is important.
> The application reads and writes data successfully.
> * I unplug the USB device. /dev/ttyUSB0 remains in existence - this
> is important too.
Huh? The device node should go away, as the application was told that
the device went away, is the application somehow still keeping the
device node open? If so, that's the issue here.
> * I replug the USB device. /dev/ttyUSB0 is still there.
> * I rerun the application. The application again connects with
> /dev/ttyUSB0 but it fails to transfer data. So it seems.
That's because it is trying to still talk to the old device, not the new
one, which should have showed up on ttyUSB1.
What kernel version are you using here?
greg k-h
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: Alan Cox @ 2012-09-08 17:16 UTC (permalink / raw)
To: peter.sheeren; +Cc: linux-serial
In-Reply-To: <20120908121439.15264wgwo05hva8f@webmail.axiris.be>
On Sat, 08 Sep 2012 12:14:39 +0200
peter.sheeren@axiris.be wrote:
> if (((old_priv.flags & ASYNC_SPD_MASK) !=
> (priv->flags & ASYNC_SPD_MASK)) ||
> (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
> (old_priv.custom_divisor != priv->custom_divisor))) {
> change_speed(tty, port);
>
> Function change_speed() is called only when the baudrate
> (custom_divisor) has changed but after a USB replug this assumption is
> wrong. Also note that /dev/ttyUSB0 remains in existence on the system
> under test. If it were up to me, I'd always send the baudrate setting
> over the USB bus nomatter whether the baudrate (supposedly) has
> changed or not.
We don't do that because if you gratuitously send speed changes that have
no effect the hardware seems to reset its configuration and you lose
characters, something a lot of software doesn't expect.
If you think that if check is the problem can you replace it with an
unconditional call to change_speed(tty, port) and the re-test. That will
confirm if it is the cause.
If it is then we can think about fixing it somehow.
Alan
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: peter.sheeren @ 2012-09-08 17:20 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial
In-Reply-To: <20120908181634.7c6e5c73@pyramind.ukuu.org.uk>
Hello Alan
Thanks for the answer.
I'm seeing the issue on:
* Raspberry Pi with Debian6 (kernel 3.1.9+)
* Raspberry Pi with Raspbian (also kernel 3.1.9+)
* BeagleBoard xM rev. C with Ubuntu (kernel 3.1.4)
I did a much simpler test without test application, just plugging and
looking. The results are the same on all three systems:
0. Reboot and log in
1. lsmod -> no usbserial, no ftdi_sio
2. plug in the USB device (first time)
3. lsmod -> usbserial loaded, ftdi_sio loaded
4. plug out the USB device
5. lsmod -> usbserial loaded, ftdi_sio loaded
6. plug in the USB device
7. lsmod -> usbserial loaded, ftdi_sio loaded
The existence of /dev/ttyUSB0 depends on the system:
* RPi with Raspbian: /dev/ttyUSB0 never goes away after step 4.
* RPi with Debian6, BBXM: /dev/ttyUSB0 goes away after step 4 and
comes back after step 6.
The fact is that ftdi_sio and usbserial are never unloaded. That's
probably the cause of the baudrate problem.
Are there any commands I can run to provide you with more information?
Best regards,
Peter
Quoting Alan Cox <alan@lxorguk.ukuu.org.uk>:
> On Sat, 08 Sep 2012 12:14:39 +0200
> peter.sheeren@axiris.be wrote:
>
>> if (((old_priv.flags & ASYNC_SPD_MASK) !=
>> (priv->flags & ASYNC_SPD_MASK)) ||
>> (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
>> (old_priv.custom_divisor != priv->custom_divisor))) {
>> change_speed(tty, port);
>>
>> Function change_speed() is called only when the baudrate
>> (custom_divisor) has changed but after a USB replug this assumption is
>> wrong. Also note that /dev/ttyUSB0 remains in existence on the system
>> under test. If it were up to me, I'd always send the baudrate setting
>> over the USB bus nomatter whether the baudrate (supposedly) has
>> changed or not.
>
> We don't do that because if you gratuitously send speed changes that have
> no effect the hardware seems to reset its configuration and you lose
> characters, something a lot of software doesn't expect.
>
> If you think that if check is the problem can you replace it with an
> unconditional call to change_speed(tty, port) and the re-test. That will
> confirm if it is the cause.
>
> If it is then we can think about fixing it somehow.
>
> Alan
>
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: Alan Cox @ 2012-09-08 17:30 UTC (permalink / raw)
To: peter.sheeren; +Cc: linux-serial
In-Reply-To: <20120908192037.20412mlnvfniwkmd@webmail.axiris.be>
> The existence of /dev/ttyUSB0 depends on the system:
> * RPi with Raspbian: /dev/ttyUSB0 never goes away after step 4.
> * RPi with Debian6, BBXM: /dev/ttyUSB0 goes away after step 4 and
> comes back after step 6.
Thats dependant upon your user space and really nothing to do with this
> Are there any commands I can run to provide you with more information?
As I said...
> > If you think that if check is the problem can you replace it with an
> > unconditional call to change_speed(tty, port) and the re-test. That will
> > confirm if it is the cause.
Alan
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: peter.sheeren @ 2012-09-08 17:35 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial
In-Reply-To: <20120908183015.2ca02043@pyramind.ukuu.org.uk>
I'm sorry, I've no experience with compiling a driver for Linux.
Q: When I plug in the USB device without even using it, should
ftdi_sio and usbserial remain loaded after I unplug the USB device?
Quoting Alan Cox <alan@lxorguk.ukuu.org.uk>:
>> The existence of /dev/ttyUSB0 depends on the system:
>> * RPi with Raspbian: /dev/ttyUSB0 never goes away after step 4.
>> * RPi with Debian6, BBXM: /dev/ttyUSB0 goes away after step 4 and
>> comes back after step 6.
>
> Thats dependant upon your user space and really nothing to do with this
>
>> Are there any commands I can run to provide you with more information?
>
> As I said...
>
>> > If you think that if check is the problem can you replace it with an
>> > unconditional call to change_speed(tty, port) and the re-test. That will
>> > confirm if it is the cause.
>
> Alan
>
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: Alan Cox @ 2012-09-08 17:54 UTC (permalink / raw)
To: peter.sheeren; +Cc: linux-serial
In-Reply-To: <20120908193516.11911xl64w1z7lxw@webmail.axiris.be>
On Sat, 08 Sep 2012 19:35:16 +0200
peter.sheeren@axiris.be wrote:
>
> I'm sorry, I've no experience with compiling a driver for Linux.
>
> Q: When I plug in the USB device without even using it, should
> ftdi_sio and usbserial remain loaded after I unplug the USB device?
Thats up to your distribution.
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: Greg KH @ 2012-09-08 18:19 UTC (permalink / raw)
To: peter.sheeren; +Cc: Alan Cox, linux-serial
In-Reply-To: <20120908193516.11911xl64w1z7lxw@webmail.axiris.be>
On Sat, Sep 08, 2012 at 07:35:16PM +0200, peter.sheeren@axiris.be wrote:
>
> I'm sorry, I've no experience with compiling a driver for Linux.
>
> Q: When I plug in the USB device without even using it, should
> ftdi_sio and usbserial remain loaded after I unplug the USB device?
Yes, no one unloads modules after devices are removed, as you really
don't know if the driver is still needed or not.
But, this shouldn't be an issue for you, when you replug the device in,
it should be reset, with no internal, or kernel, state as to what it is
in. You have to always explicitly set the line settings up again,
otherwise you have no idea what it is running at.
greg k-h
^ permalink raw reply
* Re: [PATCH v4 00/21] OMAP UART Patches
From: Felipe Balbi @ 2012-09-08 19:04 UTC (permalink / raw)
To: Kevin Hilman
Cc: balbi, Greg KH, Tony Lindgren, Linux Kernel Mailing List,
Santosh Shilimkar, linux-serial, Sourav Poddar,
Linux OMAP Mailing List, Shubhrajyoti Datta,
Linux ARM Kernel Mailing List, alan
In-Reply-To: <87oblhmu6g.fsf@deeprootsystems.com>
[-- Attachment #1: Type: text/plain, Size: 5925 bytes --]
Hi,
On Fri, Sep 07, 2012 at 01:53:11PM -0700, Kevin Hilman wrote:
> Felipe Balbi <balbi@ti.com> writes:
>
> > Hi,
> >
> > On Thu, Sep 06, 2012 at 03:44:13PM -0700, Kevin Hilman wrote:
> >> Felipe Balbi <balbi@ti.com> writes:
> >>
> >> > Hi guys,
> >> >
> >> > here's v4 of the omap uart patchset. No changes other than a rebase on top of
> >> > Greg's tty-next branch and Tony's Acked-by being added to a couple patches
> >> >
> >> > Note: I'm resending the series with Vikram's Software Flow Control fix anyway
> >> > as it can just be ignored if it's decided it needs to go into this merge
> >> > window.
> >>
> >> Sorry to be late to the party... just getting back from some time off.
> >>
> >> I'm assuming that this was not tested with PM, so decided I better do it
> >
> > you assumed wrong. See the previous versions of the series and you'll
> > see I mention all the basic pm testing I did.
>
> My apologies for not reading the previous versions. I don't think it's
> unusual that a reviewer should expect everything he to know about a
> series (including how it was tested) is in the cover letter or in the
> changelogs of the latest series. I don't expect to have to look through
you've got a point there. My bad, should've kept series history on all
revisions.
> all the previous versions for this kind of info. Since I wasn't around
> to review/test the earlier versions, I just looked at the latest (v4)
> and didn't see any mention of testing of any sort in the cover letter.
Well, fair enough. Maybe I wasn't too verbose, but here's what I did on
panda:
. check that console still works
. check that IRQs increase as I type on console
. check that pm_runtime suspend callback is called after 1 second of
inactivity (with printk)
. check that device resumes properly when I type on console again
. enable UART wakeup (through sysfs) and 'echo mem > /sys/power/state'
then check that I can wakeup from suspend and check that all
powerdomains actually reached low power state
> Looking back at the previous cover letters, I don't see any description
> of the PM testing either. I only see it was tested on pandaboard.
Yeah, initially I wasn't testing PM because UART wakeup was known to be
broken, but then I decided to test and sent it as a reply to cover
letter v2, then I forgot to keep the history on v3 and v4. My bad.
> Since mainline doesn't have full PM support for OMAP4, testing on panda
> doesn't really test UART PM at all.
Fair enough. What's missing for omap4 panda ? I could reach suspend2ram
with echo mem > /sys/power/state and wakeup from it.
> Could you please point me to the descriptions in earlier mails of how
> you did PM testing, and on what platforms?
Though not on a cover letter, this is how I was testing from v2 and
onwards:
http://marc.info/?l=linux-omap&m=134555434407362&w=2
> In addition, IMO, if this was only tested on Panda (as suggested by
> earlier cover letters), it really should not have been merged until it
> got some broader testing.
Shubhro's got his Tested-by tag. I believe he tested on beagleboard and
omap4sdp. Shubhro, can you confirm which platforms you tested the UART
patches ? cheers
> >> myself seeing that Greg is has already merge it. To test, I merged
> >> Greg's tty-next branch with v3.6-rc4 and did some PM testing.
> >>
> >> The bad news is that it doesn't even compile (see reply to [PATCH v4
> >> 20/21]).
> >
> > yeah, that was an automerge issue when rebasing on greg's tty-next
> > branch, plus me assuming omap serial was already enabled on my .config
> > and not checking the compile output. Sent a patch now.
>
> As I reported in my reply to [PATCH v4 20/21], that patch also had
> another problem where it introduced a new (but unused) field. Maybe
> another rebase problem? I see the same problem in v3 and v4.
I'll check it out and make sure to delete any such unused fields. Thanks
> >> Also, there is a big WARNING on boot[1], which seems to be triggered by
> >> a new check added for v3.6-rc3[2]. This appears to be introduced by
> >> $SUBJECT series, because I don't see it on vanilla v3.6-rc4.
>
> [...]
>
> > This doesn't seem to be caused by $SUBJECT at all. See that we are
> > calling uart_add_one_port() which will call tty_port_register_device()
> > which, in turn, will call tty_port_link_device() and that will set
> > driver->ports[index] correctly.
> >
> > Have you checked if this doesn't happen without my series before waving
> > your blame hammer ? FWIW, that part of the code wasn't change by
> > $SUBJECT at all.
>
> Whoa. This was only test report. No need to get personal. All I said
> is that it "seemed" to introduced by $SUBJECT series. Hardly waiving
> "blame hammer."
fair enough.
> And yes, I did check without your series. As I reported above, the
What about v3.6-rc4 + the patch which added the warning ? :-)
> warning didn't exist with v3.6-rc4, and it did with yesterday's tty-next
> branch. The WARNING pointed a finger at ttyO (omap-serial) so I assumed
> it was in $SUBJECT series.
>
> Testing with todays tty-next, the problem is gone. The patch
> 'tty_register_device_attr updated for tty-next'[1] seems to have made
> the problem go away. So it's now clear that it wasn't introduced by
> $SUBJECT series. My bad.
Thankfully...
> Yesterday, it wasn't that obvious, so I made an assumption in order to
> report a problem uncovered in my testing in the hopes that it would be
> helpful to you in fixing a potential problem. My assumption was wrong, I
> was wrong. I'm wrong a lot, and I'm OK with that. The bug was
> elsewhere, and is already fixed.
>
> My apologies if it seemed like I was blaming you.
I'm the one who owes you an apology for misunderstanding your bug
report. I'm sorry.
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Bug in USB FTDI SIO driver
From: peter.sheeren @ 2012-09-08 22:09 UTC (permalink / raw)
To: Greg KH; +Cc: Alan Cox, linux-serial
In-Reply-To: <20120908181917.GA7038@kroah.com>
It's interesting to know the driver aren't unloaded. So I did a couple
of tests with rmmod:
Test 1:
1. Plug in the USB device
2. Run test application, baud rate is successfully set
3. Plug out the USB device, lsmod shows usbserial and ftdi_sio
4. rmmod ftdi_sio
5. Plug in the USB device
6. Run test application, baud rate not set in the USB device
Test 2:
1. Plug in the USB device
2. Run test application, baud rate is successfully set
3. Plug out the USB device, lsmod shows usbserial and ftdi_sio
4. rmmod ftdi_sio
5. rmmod usbserial
6. Plug in the USB device
7. Run test application, baud rate is successfully set
Thus if I remove both ftdi_sio and usbserial before I plug the USB
device back in, the problem is solved. Maybe usbserial is causing the
problem?
Quoting Greg KH <gregkh@linuxfoundation.org>:
> On Sat, Sep 08, 2012 at 07:35:16PM +0200, peter.sheeren@axiris.be wrote:
>>
>> I'm sorry, I've no experience with compiling a driver for Linux.
>>
>> Q: When I plug in the USB device without even using it, should
>> ftdi_sio and usbserial remain loaded after I unplug the USB device?
>
> Yes, no one unloads modules after devices are removed, as you really
> don't know if the driver is still needed or not.
>
> But, this shouldn't be an issue for you, when you replug the device in,
> it should be reset, with no internal, or kernel, state as to what it is
> in. You have to always explicitly set the line settings up again,
> otherwise you have no idea what it is running at.
>
> greg k-h
>
^ permalink raw reply
* [PATCH v5 0/14] KGDB/KDB FIQ (NMI) debugger
From: Anton Vorontsov @ 2012-09-10 4:08 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
Hi all,
There wasn't much feedback on v4, the only comment was from Brian
Swetland concerning async console (I explained how we deal with it).
It would be really great if the core functionality could make it into
v3.7. Which raises the question: if the patches are OK, who should take
them? They touch 3 subsystems: KGDB, TTY and ARM.
Taking the patches via -mm or TTY trees would be the easiest way as this
way we'll avoid having to deal with conflicts (see changelog*). But
merging via ARM or KDB will also work.
Russell, Jason, naively presuming that the ARM & KDB patches are OK,
would you be willing to ack ARM/KDB patches? Or, in case if it goes via
KDB or ARM tree, we'll need acks from Greg and Alan on tty patches...
Anyways, here goes the shiny v5:
- *I took two amba-pl1011 patches from Greg's tty tree. This is needed
to ease Stephen Rothwell's life in case if this goes into -next via
non-tty or non-mm tree.
The problem is that we now touch the same lines as tty tree, and
conflicts are not trivial. But by taking the two patches and rebasing
my work on top, we turn the conflicts into trivial ones.
- There were some concerns that '$3#33' might be not lengthy enough
(i.e., it's a bit shorter than '\nreboot\n'). Reading 2GB of
/dev/urandom couldn't find $3#33 sequence, but I made the magic phrase
configurable via kgdb_nmi.magic kernel command line option, just in
case.
These patches can be found in the following repo:
git://git.infradead.org/users/cbou/linux-nmi-kdb.git master
Boilerplate:
These patches introduce KGDB FIQ debugger support. The idea (and some
code, of course) comes from Google's FIQ debugger[2]. There are some
differences (mostly implementation details, feature-wise they're almost
equivalent, or can be made equivalent, if desired).
The FIQ debugger is a facility that can be used to debug situations when
the kernel stuck in uninterruptable sections, e.g. the kernel infinitely
loops or deadlocked in an interrupt or with interrupts disabled. On some
development boards there is even a special NMI button, which is very
useful for debugging weird kernel hangs.
And FIQ is basically an NMI, it has a higher priority than IRQs, and
upon IRQ exception FIQs are not disabled. It is still possible to
disable FIQs (as well as some "NMIs" on other architectures), but via
special means.
So, here FIQs and NMIs are synonyms, but in the code I use NMI term for
arch-independent code, and FIQs for ARM code.
A few years ago KDB wasn't yet ready for production, or even not
well-known, so originally Google implemented its own FIQ debugger that
included its own shell, ring-buffer, commands, dumping, backtracing
logic and whatnot. This is very much like PowerPC's xmon
(arch/powerpc/xmon), except that xmon was there for a decade, so it even
predates KDB.
Anyway, nowadays KGDB/KDB is the cross-platform debugger, and the only
feature that was missing is NMI handling. This is now fixed for ARM.
There are a few differences comparing to the original (Google's) FIQ
debugger:
- Doing stuff in FIQ context is dangerous, as there we are not allowed
to cause aborts or faults. In the original FIQ debugger there was a
"signal" software-induced interrupt, upon exit from FIQ it would fire,
and we would continue to execute "dangerous" commands from there.
In KGDB/KDB we don't use signal interrupts. We can do easier: set up a
breakpoint, continue, and you'll trap into KGDB again in a safe
context.
It works for most cases, but I can imagine cases when you can't set up
a breakpoint. For these cases we'd better introduce a KDB command
"exit_nmi", that will rise the SW IRQ, after which we're allowed to do
anything.
- KGDB/KDB FIQ debugger shell is synchronous. In Google's version you
could have a dedicated shell always running in the FIQ context, so
when you type something on a serial line, you won't actually cause any
debugging actions, FIQ would save the characters in its own buffer and
continue execution normally. But when you hit return key after the
command, then the command is executed.
In KGDB/KDB FIQ debugger it is different. Once you enter KGDB, the
kernel will stop until you instruct it to continue.
This might look as a drastic change, but it is not. There is actually
no difference whether you have sync or async shell, or at least I
couldn't find any use-case where this would matter at all. Anyways, it
is still possible to do async shell in KDB, just don't see any need
for this.
- Original FIQ debugger used a custom FIQ vector handling code, w/ a lot
of logic in it. In this approach I'm using the fact that FIQs are
basically IRQs, except that we there are a bit more registers banked,
and we can actually trap from the IRQ context.
But this all does not prevent us from using a simple jump-table based
approach as used in the generic ARM entry code. So, here I just reuse
the generic approach.
Note that I test the code on a modelled ARM machine (QEMU Versatile), so
there might be some issues on a real HW, but it works in QEMU tho. :-)
Assuming you have QEMU >= 1.1.0, you can easily play with the code using
ARM/versatile defconfig and command like this:
qemu-system-arm -nographic -machine versatilepb -kernel
linux/arch/arm/boot/zImage -append "console=ttyAMA0 kgdboc=ttyAMA0
kgdb_fiq.enable=1"
Thanks,
--
arch/arm/Kconfig | 19 ++
arch/arm/common/vic.c | 28 +++
arch/arm/include/asm/hardware/vic.h | 2 +
arch/arm/include/asm/kgdb.h | 8 +
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/entry-armv.S | 167 +-------------
arch/arm/kernel/entry-header.S | 170 +++++++++++++++
arch/arm/kernel/kgdb_fiq.c | 99 +++++++++
arch/arm/kernel/kgdb_fiq_entry.S | 87 ++++++++
arch/arm/mach-versatile/Makefile | 1 +
arch/arm/mach-versatile/kgdb_fiq.c | 31 +++
drivers/tty/serial/Kconfig | 19 ++
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/amba-pl010.c | 15 +-
drivers/tty/serial/amba-pl011.c | 106 +++++----
drivers/tty/serial/kgdb_nmi.c | 352 ++++++++++++++++++++++++++++++
drivers/tty/serial/kgdboc.c | 16 ++
drivers/tty/serial/serial_core.c | 30 +++
include/linux/kdb.h | 29 +--
include/linux/kgdb.h | 34 +++
include/linux/serial_core.h | 2 +
include/linux/tty_driver.h | 1 +
kernel/debug/debug_core.c | 36 ++-
kernel/debug/kdb/kdb_main.c | 29 +++
24 files changed, 1051 insertions(+), 232 deletions(-)
In v4:
- Implemented kgdb_nmi serial driver, it provides 'nmi_console' KDB
command. With the driver we can use our debugger port as a normal
console, except that we can always get back to the debugger using the
magic sequence. Note that I still somewhat reluctant to introduce
software-raised interrupts, as they're arch-specific and not always
possible. So today the driver uses a tasklet, it should be pretty
cheap: we're checking for the input on timer interrupts, but we don't
cause needless wakeups. The pro of this is that it works everywhere
(but arches still have an option to optimize things, of course);
- Two new patches added to propagate init_poll() callbacks from tty to
uart drivers. As a side-effect, a long-standing bug fixed in
amba-pl1011 driver;
- Dropped patch 'Get rid of .LCcralign local label';
- Some more fixes in SVC return path. Now it seems rock-solid;
In v3:
- Per Colin Cross suggestion, added a way to release a debug console for
normal use. This is done via 'disable_nmi' command (in the original
FIQ debugger it was 'console' command). For this I added a new
callback in the tty ops, and serial drivers have to provide a way to
clear its interrupts. The patch 'tty/serial/kgdboc: Add and wire up
clear_irqs callback' explains the concept in details.
- Made the debug entry prompt more shell-like;
- A new knocking mode '-1'. It disables the feature altogether, and thus
makes it possible to hook KDB entry to a dedicated button.
- The code was rebased on 'v3.5 + kdb kiosk'[1] patches;
In v2:
- Per Colin Cross' suggestion, we should not enter the debugger on any
received byte (this might be a problem when there's a noise on the
serial line). So there is now an additional patch that implements
"knocking" to the KDB (either via $3#33 command or return key, this is
configurable);
- Reworked {enable,select}_fiq/is_fiq callbacks, now multi-mach kernels
should not be a problem;
- For versatile machines there are run-time checks for proper UART port
(kernel will scream aloud if out of range port is specified);
- Added some __init annotations;
- Since not every architecture defines FIQ_START, we can't just blindly
select CONFIG_FIQ symbol. So ARCH_MIGHT_HAVE_FIQ introduced;
- Add !THUMB2_KERNEL dependency for KGDB_FIQ, we don't support Thumb2
kernels;
- New patch that is used to get rid of LCcralign label in alignment_trap
macro.
[1] https://lkml.org/lkml/2012/7/26/260
[2] Original Google's FIQ debugger, fiq_* files:
http://android.git.linaro.org/gitweb?p=kernel/common.git;a=tree;f=arch/arm/common;hb=refs/heads/android-3.4
And board support as an example of using it:
http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=commitdiff;h=461cb80c16e4e266ab6207a00767b59212148086
^ permalink raw reply
* [PATCH 02/14] drivers/tty/serial/amba-pl0{10,11}.c: use clk_prepare_enable and clk_disable_unprepare
From: Anton Vorontsov @ 2012-09-10 4:12 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
From: Julia Lawall <Julia.Lawall@lip6.fr>
Clk_prepare_enable and clk_disable_unprepare combine clk_prepare and
clk_enable, and clk_disable and clk_unprepare. The9 make the code more
concise, and ensure that clk_unprepare is called when clk_enable fails.
A simplified version of the semantic patch that introduces calls to these
functions is as follows: (http://coccinelle.lip6.fr/)
// <smpl>
@@
expression e;
@@
- clk_prepare(e);
- clk_enable(e);
+ clk_prepare_enable(e);
@@
expression e;
@@
- clk_disable(e);
- clk_unprepare(e);
+ clk_disable_unprepare(e);
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
The patch was taken from the TTY tree.
If this patch rejects because 'already applied', this means that your
tree is probably based on TTY tree or -next (e.g. -mm). In which case
you don't need this patch, just drop it.
If your tree is based on Linus' tree, you need this patch to not bring
horrible conflicts into -next.
drivers/tty/serial/amba-pl010.c | 15 ++++-----------
drivers/tty/serial/amba-pl011.c | 15 ++++-----------
2 files changed, 8 insertions(+), 22 deletions(-)
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 0d91a54..22317dd 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -312,16 +312,12 @@ static int pl010_startup(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port;
int retval;
- retval = clk_prepare(uap->clk);
- if (retval)
- goto out;
-
/*
* Try to enable the clock producer.
*/
- retval = clk_enable(uap->clk);
+ retval = clk_prepare_enable(uap->clk);
if (retval)
- goto clk_unprep;
+ goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
@@ -346,9 +342,7 @@ static int pl010_startup(struct uart_port *port)
return 0;
clk_dis:
- clk_disable(uap->clk);
- clk_unprep:
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
out:
return retval;
}
@@ -375,8 +369,7 @@ static void pl010_shutdown(struct uart_port *port)
/*
* Shut down the clock producer
*/
- clk_disable(uap->clk);
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
}
static void
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 92b1ac8..3322023 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1324,16 +1324,12 @@ static int pl011_startup(struct uart_port *port)
"could not set default pins\n");
}
- retval = clk_prepare(uap->clk);
- if (retval)
- goto out;
-
/*
* Try to enable the clock producer.
*/
- retval = clk_enable(uap->clk);
+ retval = clk_prepare_enable(uap->clk);
if (retval)
- goto clk_unprep;
+ goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
@@ -1411,9 +1407,7 @@ static int pl011_startup(struct uart_port *port)
return 0;
clk_dis:
- clk_disable(uap->clk);
- clk_unprep:
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
out:
return retval;
}
@@ -1473,8 +1467,7 @@ static void pl011_shutdown(struct uart_port *port)
/*
* Shut down the clock producer
*/
- clk_disable(uap->clk);
- clk_unprepare(uap->clk);
+ clk_disable_unprepare(uap->clk);
/* Optionally let pins go into sleep states */
if (!IS_ERR(uap->pins_sleep)) {
retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep);
--
1.7.11.5
^ permalink raw reply related
* [PATCH 05/14] kdb: Turn KGDB_KDB=n stubs into static inlines
From: Anton Vorontsov @ 2012-09-10 4:13 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
This makes the stubs actually usable, since e.g. 'foo = kdb_register();'
leads to build errors in !KGDB_KDB case. Plus, with static inlines we
do type checking.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
include/linux/kdb.h | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index 42d9e86..7f6fe6e 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -13,6 +13,14 @@
* Copyright (C) 2009 Jason Wessel <jason.wessel@windriver.com>
*/
+typedef enum {
+ KDB_REPEAT_NONE = 0, /* Do not repeat this command */
+ KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */
+ KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */
+} kdb_repeat_t;
+
+typedef int (*kdb_func_t)(int, const char **);
+
#ifdef CONFIG_KGDB_KDB
#include <linux/init.h>
#include <linux/sched.h>
@@ -32,14 +40,6 @@ extern atomic_t kdb_event;
#define KDB_MAXARGS 16 /* Maximum number of arguments to a function */
-typedef enum {
- KDB_REPEAT_NONE = 0, /* Do not repeat this command */
- KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */
- KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */
-} kdb_repeat_t;
-
-typedef int (*kdb_func_t)(int, const char **);
-
/* KDB return codes from a command or internal kdb function */
#define KDB_NOTFOUND (-1)
#define KDB_ARGCOUNT (-2)
@@ -149,11 +149,14 @@ extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
short, kdb_repeat_t);
extern int kdb_unregister(char *);
#else /* ! CONFIG_KGDB_KDB */
-#define kdb_printf(...)
-#define kdb_init(x)
-#define kdb_register(...)
-#define kdb_register_repeat(...)
-#define kdb_uregister(x)
+static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; }
+static inline void kdb_init(int level) {}
+static inline int kdb_register(char *cmd, kdb_func_t func, char *usage,
+ char *help, short minlen) { return 0; }
+static inline int kdb_register_repeat(char *cmd, kdb_func_t func, char *usage,
+ char *help, short minlen,
+ kdb_repeat_t repeat) { return 0; }
+static inline int kdb_unregister(char *cmd) { return 0; }
#endif /* CONFIG_KGDB_KDB */
enum {
KDB_NOT_INITIALIZED,
--
1.7.11.5
^ permalink raw reply related
* [PATCH 06/14] tty/serial/core: Introduce poll_init callback
From: Anton Vorontsov @ 2012-09-10 4:13 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
It was noticed that polling drivers (like KGDB) are not able to use
serial ports if the ports were not previously initialized via console.
I.e. when booting with console=ttyAMA0 kgdboc=ttyAMA0, everything works
fine, but with console=ttyFOO kgdboc=ttyAMA0, the kgdboc doesn't work.
This is because we don't initialize the hardware. Calling ->startup() is
not an option, because drivers request interrupts there, and drivers
fail to handle situations when tty isn't opened with interrupts enabled.
So, we have to implement a new callback (actually, tty_ops already have
a similar callback), which does everything needed to initialize just the
hardware.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
drivers/tty/serial/serial_core.c | 15 +++++++++++++++
include/linux/serial_core.h | 1 +
2 files changed, 16 insertions(+)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..cba8443 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2108,11 +2108,13 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
{
struct uart_driver *drv = driver->driver_state;
struct uart_state *state = drv->state + line;
+ struct tty_port *tport;
struct uart_port *port;
int baud = 9600;
int bits = 8;
int parity = 'n';
int flow = 'n';
+ int ret;
if (!state || !state->uart_port)
return -1;
@@ -2121,6 +2123,19 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
if (!(port->ops->poll_get_char && port->ops->poll_put_char))
return -1;
+ tport = &state->port;
+ if (!(tport->flags & ASYNC_INITIALIZED) && port->ops->poll_init) {
+ mutex_lock(&tport->mutex);
+ ret = port->ops->poll_init(port);
+ /*
+ * We don't set ASYNCB_INITIALIZED as we only initialized the
+ * hw, e.g. state->xmit is still uninitialized.
+ */
+ mutex_unlock(&tport->mutex);
+ if (ret)
+ return ret;
+ }
+
if (options) {
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(port, NULL, baud, parity, bits, flow);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 0253c20..3642710 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -274,6 +274,7 @@ struct uart_ops {
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
+ int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif
--
1.7.11.5
^ permalink raw reply related
* [PATCH 07/14] tty/serial/amba-pl011: Implement poll_init callback
From: Anton Vorontsov @ 2012-09-10 4:13 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
The callback is used to initialize the hardware, nothing else should be
done, i.e. we should not request interrupts (but we can and do unmask
some of them, as they might be useful for NMI entry).
As a side-effect, the patch also fixes a division by zero[1] when booting
with kgdboc options specified (e.g. kgdboc=ttyAMA0,115200n8). The issue
happens because serial core calls set_termios callback, but the driver
doesn't know clock frequency, and thus cannot calculate proper baud rate
values.
[1]
WARNING: at drivers/tty/serial/serial_core.c:400 uart_get_baud_rate+0xe8/0x14c()
Modules linked in:
[<c0018e50>] (unwind_backtrace+0x0/0xf0) from [<c0020ae8>] (warn_slowpath_common+0x4c/0x64)
[<c0020ae8>] (warn_slowpath_common+0x4c/0x64) from [<c0020b1c>] (warn_slowpath_null+0x1c/0x24)
[<c0020b1c>] (warn_slowpath_null+0x1c/0x24) from [<c0185ed8>] (uart_get_baud_rate+0xe8/0x14c)
[<c0185ed8>] (uart_get_baud_rate+0xe8/0x14c) from [<c0187078>] (pl011_set_termios+0x48/0x278)
[<c0187078>] (pl011_set_termios+0x48/0x278) from [<c01850b0>] (uart_set_options+0xe8/0x114)
[<c01850b0>] (uart_set_options+0xe8/0x114) from [<c0185de4>] (uart_poll_init+0xd4/0xe0)
[<c0185de4>] (uart_poll_init+0xd4/0xe0) from [<c016da8c>] (tty_find_polling_driver+0x100/0x17c)
[<c016da8c>] (tty_find_polling_driver+0x100/0x17c) from [<c0188538>] (configure_kgdboc+0xc8/0x1b8)
[<c0188538>] (configure_kgdboc+0xc8/0x1b8) from [<c00088a4>] (do_one_initcall+0x30/0x168)
[<c00088a4>] (do_one_initcall+0x30/0x168) from [<c033784c>] (do_basic_setup+0x94/0xc8)
[<c033784c>] (do_basic_setup+0x94/0xc8) from [<c03378e0>] (kernel_init+0x60/0xf4)
[<c03378e0>] (kernel_init+0x60/0xf4) from [<c00144a0>] (kernel_thread_exit+0x0/0x8)
---[ end trace 7d41c9186f342c40 ]---
Division by zero in kernel.
[<c0018e50>] (unwind_backtrace+0x0/0xf0) from [<c014546c>] (Ldiv0+0x8/0x10)
[<c014546c>] (Ldiv0+0x8/0x10) from [<c0187098>] (pl011_set_termios+0x68/0x278)
[<c0187098>] (pl011_set_termios+0x68/0x278) from [<c01850b0>] (uart_set_options+0xe8/0x114)
[<c01850b0>] (uart_set_options+0xe8/0x114) from [<c0185de4>] (uart_poll_init+0xd4/0xe0)
[<c0185de4>] (uart_poll_init+0xd4/0xe0) from [<c016da8c>] (tty_find_polling_driver+0x100/0x17c)
[<c016da8c>] (tty_find_polling_driver+0x100/0x17c) from [<c0188538>] (configure_kgdboc+0xc8/0x1b8)
[<c0188538>] (configure_kgdboc+0xc8/0x1b8) from [<c00088a4>] (do_one_initcall+0x30/0x168)
[<c00088a4>] (do_one_initcall+0x30/0x168) from [<c033784c>] (do_basic_setup+0x94/0xc8)
[<c033784c>] (do_basic_setup+0x94/0xc8) from [<c03378e0>] (kernel_init+0x60/0xf4)
[<c03378e0>] (kernel_init+0x60/0xf4) from [<c00144a0>] (kernel_thread_exit+0x0/0x8)
Division by zero in kernel.
[<c0018e50>] (unwind_backtrace+0x0/0xf0) from [<c014546c>] (Ldiv0+0x8/0x10)
[<c014546c>] (Ldiv0+0x8/0x10) from [<c0183a98>] (uart_update_timeout+0x4c/0x5c)
[<c0183a98>] (uart_update_timeout+0x4c/0x5c) from [<c01870f8>] (pl011_set_termios+0xc8/0x278)
[<c01870f8>] (pl011_set_termios+0xc8/0x278) from [<c01850b0>] (uart_set_options+0xe8/0x114)
[<c01850b0>] (uart_set_options+0xe8/0x114) from [<c0185de4>] (uart_poll_init+0xd4/0xe0)
[<c0185de4>] (uart_poll_init+0xd4/0xe0) from [<c016da8c>] (tty_find_polling_driver+0x100/0x17c)
[<c016da8c>] (tty_find_polling_driver+0x100/0x17c) from [<c0188538>] (configure_kgdboc+0xc8/0x1b8)
[<c0188538>] (configure_kgdboc+0xc8/0x1b8) from [<c00088a4>] (do_one_initcall+0x30/0x168)
[<c00088a4>] (do_one_initcall+0x30/0x168) from [<c033784c>] (do_basic_setup+0x94/0xc8)
[<c033784c>] (do_basic_setup+0x94/0xc8) from [<c03378e0>] (kernel_init+0x60/0xf4)
[<c03378e0>] (kernel_init+0x60/0xf4) from [<c00144a0>] (kernel_thread_exit+0x0/0x8)
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
drivers/tty/serial/amba-pl011.c | 44 ++++++++++++++++++++++++++++++-----------
1 file changed, 33 insertions(+), 11 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 3322023..88e2df2 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1310,10 +1310,9 @@ static void pl011_put_poll_char(struct uart_port *port,
#endif /* CONFIG_CONSOLE_POLL */
-static int pl011_startup(struct uart_port *port)
+static int pl011_hwinit(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int cr;
int retval;
/* Optionaly enable pins to be muxed in and configured */
@@ -1338,6 +1337,37 @@ static int pl011_startup(struct uart_port *port)
UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
/*
+ * Save interrupts enable mask, and enable RX interrupts in case if
+ * the interrupt is used for NMI entry.
+ */
+ uap->im = readw(uap->port.membase + UART011_IMSC);
+ writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
+
+ if (uap->port.dev->platform_data) {
+ struct amba_pl011_data *plat;
+
+ plat = uap->port.dev->platform_data;
+ if (plat->init)
+ plat->init();
+ }
+ return 0;
+ out:
+ return retval;
+}
+
+static int pl011_startup(struct uart_port *port)
+{
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
+ unsigned int cr;
+ int retval;
+
+ retval = pl011_hwinit(port);
+ if (retval)
+ goto clk_dis;
+
+ writew(uap->im, uap->port.membase + UART011_IMSC);
+
+ /*
* Allocate the IRQ
*/
retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
@@ -1396,19 +1426,10 @@ static int pl011_startup(struct uart_port *port)
writew(uap->im, uap->port.membase + UART011_IMSC);
spin_unlock_irq(&uap->port.lock);
- if (uap->port.dev->platform_data) {
- struct amba_pl011_data *plat;
-
- plat = uap->port.dev->platform_data;
- if (plat->init)
- plat->init();
- }
-
return 0;
clk_dis:
clk_disable_unprepare(uap->clk);
- out:
return retval;
}
@@ -1689,6 +1710,7 @@ static struct uart_ops amba_pl011_pops = {
.config_port = pl011_config_port,
.verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
+ .poll_init = pl011_hwinit,
.poll_get_char = pl011_get_poll_char,
.poll_put_char = pl011_put_poll_char,
#endif
--
1.7.11.5
^ permalink raw reply related
* [PATCH 08/14] tty/serial/kgdboc: Add and wire up clear_irqs callback
From: Anton Vorontsov @ 2012-09-10 4:13 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
This patch implements a new callback: clear_irqs. It is used for the
cases when KDB-entry (e.g. NMI) and KDB IO (e.g. serial port) shares the
same interrupt. To get the idea, let's take some real example (ARM
machine): we have a serial port which interrupt is routed to an NMI, and
the interrupt is used to enter KDB. Once there is some activity on the
serial port, the CPU receives NMI exception, and we fall into KDB shell.
So, it is our "debug console", and it is able to interrupt (and thus
debug) even IRQ handlers themselves.
When used that way, the interrupt never reaches serial driver's IRQ
handler routine, which means that serial driver will not silence the
interrupt. NMIs behaviour are quite arch-specific, and we can't assume
that we can use them as ordinary IRQs, e.g. on some arches (like ARM) we
can't handle data aborts, the behaviour is undefined then. So we can't
just handle execution to serial driver's IRQ handler from the NMI
context once we're done with KDB (plus this would defeat the debugger's
purpose: we want the NMI handler be as simple as possible, so it will
have less chances to hang).
So, given that have to deal with it somehow, we have two options:
1. Implement something that clears the interrupt; 2. Implement a whole
new concept of grabbing tty for exclusive KDB use, plus implement
mask/unmask callbacks, i.e.:
- Since consoles might use ttys w/o opending them, we would have to
make kdb respect CON_ENABLED flag (maybe a good idea to do it
anyway);
- Add 'bool exclusive' argument to tty_find_polling_driver(), if set
to 1, the function will refuse to return an already opened tty; and
will use the flag in tty_reopen() to not allow multiple users
(there are already checks for pty masters, which are "open once"
ttys);
- Once we got the tty exclusively, we would need to call some new
uart->mask_all_but_rx_interrupts call before we want to use the
port for NMI/KDB, and unmask_all_but_rx_interrupts after we're done
with it.
The second option is obviously more complex, needlessly so, and less
generic. So I went with the first one: we just consume all the
interrupts. The tty becomes silently unusable for the rest of the world
when we use it with KDB; but once we reroute the serial IRQ source back
from NMI to an ordinary IRQ (in KDB this can be done with 'disable_nmi'
command), it will behave as normal.
p.s. Since the callback is so far used only by polling users, we place
it under the appropriate #ifdef.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
drivers/tty/serial/kgdboc.c | 10 ++++++++++
drivers/tty/serial/serial_core.c | 15 +++++++++++++++
include/linux/kgdb.h | 1 +
include/linux/serial_core.h | 1 +
include/linux/tty_driver.h | 1 +
5 files changed, 28 insertions(+)
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
index 2b42a01..0aa08c8 100644
--- a/drivers/tty/serial/kgdboc.c
+++ b/drivers/tty/serial/kgdboc.c
@@ -227,6 +227,15 @@ static int kgdboc_get_char(void)
kgdb_tty_line);
}
+static void kgdboc_clear_irqs(void)
+{
+ if (!kgdb_tty_driver)
+ return;
+ if (kgdb_tty_driver->ops->clear_irqs)
+ kgdb_tty_driver->ops->clear_irqs(kgdb_tty_driver,
+ kgdb_tty_line);
+}
+
static void kgdboc_put_char(u8 chr)
{
if (!kgdb_tty_driver)
@@ -298,6 +307,7 @@ static struct kgdb_io kgdboc_io_ops = {
.name = "kgdboc",
.read_char = kgdboc_get_char,
.write_char = kgdboc_put_char,
+ .clear_irqs = kgdboc_clear_irqs,
.pre_exception = kgdboc_pre_exp_handler,
.post_exception = kgdboc_post_exp_handler,
};
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index cba8443..908d108 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2169,6 +2169,20 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
port = state->uart_port;
port->ops->poll_put_char(port, ch);
}
+
+static void uart_clear_irqs(struct tty_driver *driver, int line)
+{
+ struct uart_driver *drv = driver->driver_state;
+ struct uart_state *state = drv->state + line;
+ struct uart_port *port;
+
+ if (!state || !state->uart_port)
+ return;
+
+ port = state->uart_port;
+ if (port->ops->clear_irqs)
+ port->ops->clear_irqs(port);
+}
#endif
static const struct tty_operations uart_ops = {
@@ -2201,6 +2215,7 @@ static const struct tty_operations uart_ops = {
.poll_init = uart_poll_init,
.poll_get_char = uart_poll_get_char,
.poll_put_char = uart_poll_put_char,
+ .clear_irqs = uart_clear_irqs,
#endif
};
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 3b111a6..1fd1cf0 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -295,6 +295,7 @@ struct kgdb_io {
const char *name;
int (*read_char) (void);
void (*write_char) (u8);
+ void (*clear_irqs) (void);
void (*flush) (void);
int (*init) (void);
void (*pre_exception) (void);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 3642710..114b3f3 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -277,6 +277,7 @@ struct uart_ops {
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
+ void (*clear_irqs)(struct uart_port *);
#endif
};
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 6e6dbb7..94b14cd 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -287,6 +287,7 @@ struct tty_operations {
int (*poll_init)(struct tty_driver *driver, int line, char *options);
int (*poll_get_char)(struct tty_driver *driver, int line);
void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
+ void (*clear_irqs)(struct tty_driver *driver, int line);
#endif
const struct file_operations *proc_fops;
};
--
1.7.11.5
^ permalink raw reply related
* [PATCH 09/14] tty/serial/amba-pl011: Implement clear_irqs callback
From: Anton Vorontsov @ 2012-09-10 4:14 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
It's all pretty straightforward, except for TXIM interrupt. The interrupt
has meaning "ready to transmit", so it's almost always raised, and the
only way to silence it is to mask it. But that's OK, ops->start_tx will
unmask it.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
drivers/tty/serial/amba-pl011.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 88e2df2..7522d97 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1308,6 +1308,18 @@ static void pl011_put_poll_char(struct uart_port *port,
writew(ch, uap->port.membase + UART01x_DR);
}
+static void pl011_clear_irqs(struct uart_port *port)
+{
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
+ unsigned char __iomem *regs = uap->port.membase;
+
+ writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+ /*
+ * There is no way to clear TXIM, this is "ready to transmit IRQ", so
+ * we simply mask it. ops->start_tx will unmask it.
+ */
+ writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
+}
#endif /* CONFIG_CONSOLE_POLL */
static int pl011_hwinit(struct uart_port *port)
@@ -1713,6 +1725,7 @@ static struct uart_ops amba_pl011_pops = {
.poll_init = pl011_hwinit,
.poll_get_char = pl011_get_poll_char,
.poll_put_char = pl011_put_poll_char,
+ .clear_irqs = pl011_clear_irqs,
#endif
};
--
1.7.11.5
^ permalink raw reply related
* [PATCH 10/14] tty/serial: Add kgdb_nmi driver
From: Anton Vorontsov @ 2012-09-10 4:14 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
This special driver makes it possible to temporary use NMI debugger port
as a normal console by issuing 'nmi_console' command (assuming that the
port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always able
to go back to the debugger using KGDB escape sequence ($3#33). This is
because this console driver processes the input in NMI context, and thus
is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP it is still better to fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw
console.
Usually, to enter the debugger one have to type the magic sequence, so
initially the kernel will print the following prompt on the NMI debugger
console:
Type $3#33 to enter the debugger>
For convenience, there is a kgdb_fiq.knock kernel command line option,
when set to 0, this turns the special command to just a return key
press, so the kernel will be printing this:
Hit <return> to enter the debugger>
This is more convenient for long debugging sessions, although it makes
nmi_console feature somewhat useless.
And for the cases when NMI connected to a dedicated button, the knocking
can be disabled altogether by setting kgdb_fiq.knock to -1.
Suggested-by: Colin Cross <ccross@android.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
drivers/tty/serial/Kconfig | 19 +++
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/kgdb_nmi.c | 352 ++++++++++++++++++++++++++++++++++++++++++
drivers/tty/serial/kgdboc.c | 6 +
include/linux/kgdb.h | 10 ++
5 files changed, 388 insertions(+)
create mode 100644 drivers/tty/serial/kgdb_nmi.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 4720b4b..32d6d3f 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -141,6 +141,25 @@ config SERIAL_ATMEL_TTYAT
Say Y if you have an external 8250/16C550 UART. If unsure, say N.
+config SERIAL_KGDB_NMI
+ bool "Serial console over KGDB NMI debugger port"
+ depends on KGDB_SERIAL_CONSOLE
+ help
+ This special driver allows you to temporary use NMI debugger port
+ as a normal console (assuming that the port is attached to KGDB).
+
+ Unlike KDB's disable_nmi command, with this driver you are always
+ able to go back to the debugger using KGDB escape sequence ($3#33).
+ This is because this console driver processes the input in NMI
+ context, and thus is able to intercept the magic sequence.
+
+ Note that since the console interprets input and uses polling
+ communication methods, for things like PPP you still must fully
+ detach debugger port from the KGDB NMI (i.e. disable_nmi), and
+ use raw console.
+
+ If unsure, say N.
+
config SERIAL_KS8695
bool "Micrel KS8695 (Centaur) serial port support"
depends on ARCH_KS8695
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 7257c5d..7a61d52 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
+obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
new file mode 100644
index 0000000..697cf13
--- /dev/null
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -0,0 +1,352 @@
+/*
+ * KGDB NMI serial console
+ *
+ * Copyright 2010 Google, Inc.
+ * Arve Hjønnevåg <arve@android.com>
+ * Colin Cross <ccross@android.com>
+ * Copyright 2012 Linaro Ltd.
+ * Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/kfifo.h>
+#include <linux/kgdb.h>
+#include <linux/kdb.h>
+
+static int kgdb_nmi_knock = 1;
+module_param_named(knock, kgdb_nmi_knock, int, 0600);
+MODULE_PARM_DESC(knock, "if set to 1 (default), the special '$3#33' command "
+ "must be used to enter the debugger; when set to 0, "
+ "hitting return key is enough to enter the debugger; "
+ "when set to -1, the debugger is entered immediately "
+ "upon NMI");
+
+static char *kgdb_nmi_magic = "$3#33";
+module_param_named(magic, kgdb_nmi_magic, charp, 0600);
+MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
+
+static bool kgdb_nmi_tty_enabled;
+
+static void kgdb_nmi_console_write(struct console *co, const char *s, uint c)
+{
+ int i;
+
+ if (!kgdb_nmi_tty_enabled || atomic_read(&kgdb_active) >= 0)
+ return;
+
+ for (i = 0; i < c; i++)
+ dbg_io_ops->write_char(s[i]);
+}
+
+static struct tty_driver *kgdb_nmi_tty_driver;
+
+static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx)
+{
+ *idx = co->index;
+ return kgdb_nmi_tty_driver;
+}
+
+static struct console kgdb_nmi_console = {
+ .name = "ttyNMI",
+ .write = kgdb_nmi_console_write,
+ .device = kgdb_nmi_console_device,
+ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED,
+ .index = -1,
+};
+
+/*
+ * This is usually the maximum rate on debug ports. We make fifo large enough
+ * to make copy-pasting to the terminal usable.
+ */
+#define KGDB_NMI_BAUD 115200
+#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ)
+
+struct kgdb_nmi_tty_priv {
+ int opened;
+ struct tty_struct *tty;
+ struct tasklet_struct tlet;
+ STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo;
+};
+
+/*
+ * Our debugging console is polled in a tasklet, so we'll check for input
+ * every tick. In HZ-less mode, we should program the next tick. We have
+ * to use the lowlevel stuff as no locks should be grabbed.
+ */
+#ifdef CONFIG_HIGH_RES_TIMERS
+static void kgdb_tty_poke(void)
+{
+ tick_program_event(ktime_get(), 0);
+}
+#else
+static inline void kgdb_tty_poke(void) {}
+#endif
+
+static struct tty_struct *kgdb_nmi_tty;
+
+static void kgdb_tty_recv(int ch)
+{
+ struct kgdb_nmi_tty_priv *priv;
+ char c = ch;
+
+ if (!kgdb_nmi_tty || ch < 0)
+ return;
+
+ priv = kgdb_nmi_tty->driver_data;
+ kfifo_in(&priv->fifo, &c, 1);
+ kgdb_tty_poke();
+}
+
+static int kgdb_nmi_poll_one_knock(void)
+{
+ static int n;
+ int c = -1;
+ const char *magic = kgdb_nmi_magic;
+ size_t m = strlen(magic);
+ bool printch = 0;
+
+ c = dbg_io_ops->read_char();
+ if (c == NO_POLL_CHAR)
+ return c;
+
+ if (!kgdb_nmi_knock && (c == '\r' || c == '\n')) {
+ return 1;
+ } else if (c == magic[n]) {
+ n = (n + 1) % m;
+ if (!n)
+ return 1;
+ printch = 1;
+ } else {
+ n = 0;
+ }
+
+ if (kgdb_nmi_tty_enabled) {
+ kgdb_tty_recv(c);
+ return 0;
+ }
+
+ if (printch) {
+ kdb_printf("%c", c);
+ return 0;
+ }
+
+ kdb_printf("\r%s %s to enter the debugger> %*s",
+ kgdb_nmi_knock ? "Type" : "Hit",
+ kgdb_nmi_knock ? magic : "<return>", m, "");
+ while (m--)
+ kdb_printf("\b");
+ return 0;
+}
+
+/**
+ * kgdb_nmi_poll_knock - Check if it is time to enter the debugger
+ *
+ * "Serial ports are often noisy, especially when muxed over another port (we
+ * often use serial over the headset connector). Noise on the async command
+ * line just causes characters that are ignored, on a command line that blocked
+ * execution noise would be catastrophic." -- Colin Cross
+ *
+ * So, this function implements KGDB/KDB knocking on the serial line: we won't
+ * enter the debugger until we receive a known magic phrase (which is actually
+ * "$3#33", known as "escape to KDB" command. There is also a relaxed variant
+ * of knocking, i.e. just pressing the return key is enough to enter the
+ * debugger. And if knocking is disabled, the function always returns 1.
+ */
+bool kgdb_nmi_poll_knock(void)
+{
+ if (kgdb_nmi_knock < 0)
+ return 1;
+
+ dbg_io_ops->clear_irqs();
+
+ while (1) {
+ int ret;
+
+ ret = kgdb_nmi_poll_one_knock();
+ if (ret == NO_POLL_CHAR)
+ return 0;
+ else if (ret == 1)
+ break;
+ }
+ return 1;
+}
+
+static void kgdb_nmi_tty_receiver(unsigned long data)
+{
+ struct kgdb_nmi_tty_priv *priv = (void *)data;
+ char ch;
+
+ tasklet_schedule(&priv->tlet);
+
+ if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo)))
+ return;
+
+ while (kfifo_out(&priv->fifo, &ch, 1))
+ tty_insert_flip_char(priv->tty, ch, TTY_NORMAL);
+ tty_flip_buffer_push(priv->tty);
+}
+
+static DEFINE_MUTEX(kgdb_nmi_tty_mutex);
+
+static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
+{
+ struct kgdb_nmi_tty_priv *priv;
+ int ret = 0;
+
+ mutex_lock(&kgdb_nmi_tty_mutex);
+
+ priv = tty->driver_data;
+ if (priv)
+ goto out;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ kgdb_nmi_tty = tty;
+ priv->tty = tty;
+ INIT_KFIFO(priv->fifo);
+ tty->driver_data = priv;
+
+ /*
+ * The tasklet is cheap, it does not cause wakeups when reschedules
+ * itself, instead it waits for the next tick.
+ */
+ tasklet_init(&priv->tlet, kgdb_nmi_tty_receiver, (unsigned long)priv);
+ tasklet_schedule(&priv->tlet);
+out:
+ priv->opened++;
+err:
+ mutex_unlock(&kgdb_nmi_tty_mutex);
+ return ret;
+}
+
+static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
+{
+ struct kgdb_nmi_tty_priv *priv;
+
+ mutex_lock(&kgdb_nmi_tty_mutex);
+
+ priv = tty->driver_data;
+ if (--priv->opened)
+ goto out;
+
+ tasklet_kill(&priv->tlet);
+ kgdb_nmi_tty = NULL;
+ kfree(priv);
+out:
+ mutex_unlock(&kgdb_nmi_tty_mutex);
+}
+
+static int kgdb_nmi_tty_write_room(struct tty_struct *tty)
+{
+ /* Actually, we can handle any amount as we use polled writes. */
+ return 2048;
+}
+
+static int kgdb_nmi_tty_write(struct tty_struct *tty, const unchar *buf, int c)
+{
+ int i;
+
+ for (i = 0; i < c; i++)
+ dbg_io_ops->write_char(buf[i]);
+ return c;
+}
+
+static const struct tty_operations kgdb_nmi_tty_ops = {
+ .open = kgdb_nmi_tty_open,
+ .close = kgdb_nmi_tty_close,
+ .write_room = kgdb_nmi_tty_write_room,
+ .write = kgdb_nmi_tty_write,
+};
+
+static int kgdb_nmi_enable_console(int argc, const char *argv[])
+{
+ kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off"));
+ return 0;
+}
+
+int kgdb_register_nmi_console(void)
+{
+ int ret;
+
+ kgdb_nmi_tty_driver = alloc_tty_driver(1);
+ if (!kgdb_nmi_tty_driver) {
+ pr_err("%s: cannot allocate tty\n", __func__);
+ return -ENOMEM;
+ }
+ kgdb_nmi_tty_driver->driver_name = "ttyNMI";
+ kgdb_nmi_tty_driver->name = "ttyNMI";
+ kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+ kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV;
+ kgdb_nmi_tty_driver->init_termios = tty_std_termios;
+ tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
+ KGDB_NMI_BAUD, KGDB_NMI_BAUD);
+ tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops);
+
+ ret = tty_register_driver(kgdb_nmi_tty_driver);
+ if (ret) {
+ pr_err("%s: unable to register tty: %d\n", __func__, ret);
+ goto err_tty_reg;
+ }
+
+ ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]",
+ "switch to Linux NMI console", 0);
+ if (ret) {
+ pr_err("%s: unable to register kdb command: %d\n",
+ __func__, ret);
+ goto err_kdb_reg;
+ }
+
+ register_console(&kgdb_nmi_console);
+ kgdb_enable_nmi(1);
+
+ return 0;
+err_kdb_reg:
+ tty_unregister_driver(kgdb_nmi_tty_driver);
+err_tty_reg:
+ put_tty_driver(kgdb_nmi_tty_driver);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
+
+int kgdb_unregister_nmi_console(void)
+{
+ int ret;
+
+ kgdb_enable_nmi(0);
+
+ ret = tty_unregister_driver(kgdb_nmi_tty_driver);
+ if (ret)
+ return ret;
+ put_tty_driver(kgdb_nmi_tty_driver);
+
+ ret = unregister_console(&kgdb_nmi_console);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console);
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
index 0aa08c8..bb69803 100644
--- a/drivers/tty/serial/kgdboc.c
+++ b/drivers/tty/serial/kgdboc.c
@@ -145,6 +145,8 @@ __setup("kgdboc=", kgdboc_option_setup);
static void cleanup_kgdboc(void)
{
+ if (kgdb_unregister_nmi_console())
+ return;
kgdboc_unregister_kbd();
if (configured == 1)
kgdb_unregister_io_module(&kgdboc_io_ops);
@@ -198,6 +200,10 @@ do_register:
if (err)
goto noconfig;
+ err = kgdb_register_nmi_console();
+ if (err)
+ goto noconfig;
+
configured = 1;
return 0;
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 1fd1cf0..fb7c55c 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -245,6 +245,16 @@ extern void kgdb_arch_enable_nmi(bool on);
*/
extern int kgdb_enable_nmi(bool on);
+#ifdef CONFIG_SERIAL_KGDB_NMI
+extern int kgdb_register_nmi_console(void);
+extern int kgdb_unregister_nmi_console(void);
+extern bool kgdb_nmi_poll_knock(void);
+#else
+static inline int kgdb_register_nmi_console(void) { return 0; }
+static inline int kgdb_unregister_nmi_console(void) { return 0; }
+static inline bool kgdb_nmi_poll_knock(void) { return 1; }
+#endif
+
/**
* struct kgdb_arch - Describe architecture specific values.
* @gdb_bpt_instr: The instruction to trigger a breakpoint.
--
1.7.11.5
^ permalink raw reply related
* [PATCH 11/14] ARM: Move some macros from entry-armv to entry-header
From: Anton Vorontsov @ 2012-09-10 4:14 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
Just move the macros into header file as we would want to use them for
KGDB FIQ entry code.
The following macros were moved:
- svc_entry
- usr_entry
- kuser_cmpxchg_check
- vector_stub
To make kuser_cmpxchg_check actually work across different files, we
also have to make kuser_cmpxchg64_fixup global.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
arch/arm/kernel/entry-armv.S | 167 +---------------------------------------
| 170 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 171 insertions(+), 166 deletions(-)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0f82098..0f15368 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -136,57 +136,6 @@ common_invalid:
b bad_mode
ENDPROC(__und_invalid)
-/*
- * SVC mode handlers
- */
-
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
-#define SPFIX(code...) code
-#else
-#define SPFIX(code...)
-#endif
-
- .macro svc_entry, stack_hole=0
- UNWIND(.fnstart )
- UNWIND(.save {r0 - pc} )
- sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
-#ifdef CONFIG_THUMB2_KERNEL
- SPFIX( str r0, [sp] ) @ temporarily saved
- SPFIX( mov r0, sp )
- SPFIX( tst r0, #4 ) @ test original stack alignment
- SPFIX( ldr r0, [sp] ) @ restored
-#else
- SPFIX( tst sp, #4 )
-#endif
- SPFIX( subeq sp, sp, #4 )
- stmia sp, {r1 - r12}
-
- ldmia r0, {r3 - r5}
- add r7, sp, #S_SP - 4 @ here for interlock avoidance
- mov r6, #-1 @ "" "" "" ""
- add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
- SPFIX( addeq r2, r2, #4 )
- str r3, [sp, #-4]! @ save the "real" r0 copied
- @ from the exception stack
-
- mov r3, lr
-
- @
- @ We are now ready to fill in the remaining blanks on the stack:
- @
- @ r2 - sp_svc
- @ r3 - lr_svc
- @ r4 - lr_<exception>, already fixed up for correct return/restart
- @ r5 - spsr_<exception>
- @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
- @
- stmia r7, {r2 - r6}
-
-#ifdef CONFIG_TRACE_IRQFLAGS
- bl trace_hardirqs_off
-#endif
- .endm
-
.align 5
__dabt_svc:
svc_entry
@@ -348,71 +297,8 @@ ENDPROC(__pabt_svc)
/*
* User mode handlers
- *
- * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
*/
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
-#error "sizeof(struct pt_regs) must be a multiple of 8"
-#endif
-
- .macro usr_entry
- UNWIND(.fnstart )
- UNWIND(.cantunwind ) @ don't unwind the user space
- sub sp, sp, #S_FRAME_SIZE
- ARM( stmib sp, {r1 - r12} )
- THUMB( stmia sp, {r0 - r12} )
-
- ldmia r0, {r3 - r5}
- add r0, sp, #S_PC @ here for interlock avoidance
- mov r6, #-1 @ "" "" "" ""
-
- str r3, [sp] @ save the "real" r0 copied
- @ from the exception stack
-
- @
- @ We are now ready to fill in the remaining blanks on the stack:
- @
- @ r4 - lr_<exception>, already fixed up for correct return/restart
- @ r5 - spsr_<exception>
- @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
- @
- @ Also, separately save sp_usr and lr_usr
- @
- stmia r0, {r4 - r6}
- ARM( stmdb r0, {sp, lr}^ )
- THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
-
- @
- @ Enable the alignment trap while in kernel mode
- @
- alignment_trap r0
-
- @
- @ Clear FP to mark the first stack frame
- @
- zero_fp
-
-#ifdef CONFIG_IRQSOFF_TRACER
- bl trace_hardirqs_off
-#endif
- .endm
-
- .macro kuser_cmpxchg_check
-#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
-#ifndef CONFIG_MMU
-#warning "NPTL on non MMU needs fixing"
-#else
- @ Make sure our user space atomic helper is restarted
- @ if it was interrupted in a critical region. Here we
- @ perform a quick test inline since it should be false
- @ 99.9999% of the time. The rest is done out of line.
- cmp r4, #TASK_SIZE
- blhs kuser_cmpxchg64_fixup
-#endif
-#endif
- .endm
-
.align 5
__dabt_usr:
usr_entry
@@ -846,6 +732,7 @@ __kuser_cmpxchg64: @ 0xffff0f60
ldmfd sp!, {r4, r5, r6, pc}
.text
+ .global kuser_cmpxchg64_fixup
kuser_cmpxchg64_fixup:
@ Called from kuser_cmpxchg_fixup.
@ r4 = address of interrupted insn (must be preserved).
@@ -976,58 +863,6 @@ __kuser_helper_end:
THUMB( .thumb )
-/*
- * Vector stubs.
- *
- * This code is copied to 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's. Note that this code must not
- * exceed 0x300 bytes.
- *
- * Common stub entry macro:
- * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
- *
- * SP points to a minimal amount of processor-private memory, the address
- * of which is copied into r0 for the mode specific abort handler.
- */
- .macro vector_stub, name, mode, correction=0
- .align 5
-
-vector_\name:
- .if \correction
- sub lr, lr, #\correction
- .endif
-
- @
- @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
- @ (parent CPSR)
- @
- stmia sp, {r0, lr} @ save r0, lr
- mrs lr, spsr
- str lr, [sp, #8] @ save spsr
-
- @
- @ Prepare for SVC32 mode. IRQs remain disabled.
- @
- mrs r0, cpsr
- eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
- msr spsr_cxsf, r0
-
- @
- @ the branch table must immediately follow this code
- @
- and lr, lr, #0x0f
- THUMB( adr r0, 1f )
- THUMB( ldr lr, [r0, lr, lsl #2] )
- mov r0, sp
- ARM( ldr lr, [pc, lr, lsl #2] )
- movs pc, lr @ branch to handler in SVC mode
-ENDPROC(vector_\name)
-
- .align 2
- @ handler addresses follow this label
-1:
- .endm
-
.globl __stubs_start
__stubs_start:
/*
--git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..c3c09ac 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -73,6 +73,109 @@
msr cpsr_c, \rtemp @ switch back to the SVC mode
.endm
+/*
+ * Vector stubs.
+ *
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's. Note that this code must not
+ * exceed 0x300 bytes.
+ *
+ * Common stub entry macro:
+ * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
+ */
+ .macro vector_stub, name, mode, correction=0
+ .align 5
+
+vector_\name:
+ .if \correction
+ sub lr, lr, #\correction
+ .endif
+
+ @
+ @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
+ @ (parent CPSR)
+ @
+ stmia sp, {r0, lr} @ save r0, lr
+ mrs lr, spsr
+ str lr, [sp, #8] @ save spsr
+
+ @
+ @ Prepare for SVC32 mode. IRQs remain disabled.
+ @
+ mrs r0, cpsr
+ eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
+ msr spsr_cxsf, r0
+
+ @
+ @ the branch table must immediately follow this code
+ @
+ and lr, lr, #0x0f
+ THUMB( adr r0, 1f )
+ THUMB( ldr lr, [r0, lr, lsl #2] )
+ mov r0, sp
+ ARM( ldr lr, [pc, lr, lsl #2] )
+ movs pc, lr @ branch to handler in SVC mode
+ENDPROC(vector_\name)
+
+ .align 2
+ @ handler addresses follow this label
+1:
+ .endm
+
+/*
+ * SVC mode handlers
+ */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+#define SPFIX(code...) code
+#else
+#define SPFIX(code...)
+#endif
+
+ .macro svc_entry, stack_hole=0
+ UNWIND(.fnstart )
+ UNWIND(.save {r0 - pc} )
+ sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+#ifdef CONFIG_THUMB2_KERNEL
+ SPFIX( str r0, [sp] ) @ temporarily saved
+ SPFIX( mov r0, sp )
+ SPFIX( tst r0, #4 ) @ test original stack alignment
+ SPFIX( ldr r0, [sp] ) @ restored
+#else
+ SPFIX( tst sp, #4 )
+#endif
+ SPFIX( subeq sp, sp, #4 )
+ stmia sp, {r1 - r12}
+
+ ldmia r0, {r3 - r5}
+ add r7, sp, #S_SP - 4 @ here for interlock avoidance
+ mov r6, #-1 @ "" "" "" ""
+ add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+ SPFIX( addeq r2, r2, #4 )
+ str r3, [sp, #-4]! @ save the "real" r0 copied
+ @ from the exception stack
+
+ mov r3, lr
+
+ @
+ @ We are now ready to fill in the remaining blanks on the stack:
+ @
+ @ r2 - sp_svc
+ @ r3 - lr_svc
+ @ r4 - lr_<exception>, already fixed up for correct return/restart
+ @ r5 - spsr_<exception>
+ @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
+ @
+ stmia r7, {r2 - r6}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+ bl trace_hardirqs_off
+#endif
+ .endm
+
#ifndef CONFIG_THUMB2_KERNEL
.macro svc_exit, rpsr
msr spsr_cxsf, \rpsr
@@ -164,6 +267,73 @@
#endif /* !CONFIG_THUMB2_KERNEL */
/*
+ * User mode handlers
+ *
+ * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
+ */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#error "sizeof(struct pt_regs) must be a multiple of 8"
+#endif
+
+ .macro usr_entry
+ UNWIND(.fnstart )
+ UNWIND(.cantunwind ) @ don't unwind the user space
+ sub sp, sp, #S_FRAME_SIZE
+ ARM( stmib sp, {r1 - r12} )
+ THUMB( stmia sp, {r0 - r12} )
+
+ ldmia r0, {r3 - r5}
+ add r0, sp, #S_PC @ here for interlock avoidance
+ mov r6, #-1 @ "" "" "" ""
+
+ str r3, [sp] @ save the "real" r0 copied
+ @ from the exception stack
+
+ @
+ @ We are now ready to fill in the remaining blanks on the stack:
+ @
+ @ r4 - lr_<exception>, already fixed up for correct return/restart
+ @ r5 - spsr_<exception>
+ @ r6 - orig_r0 (see pt_regs definition in ptrace.h)
+ @
+ @ Also, separately save sp_usr and lr_usr
+ @
+ stmia r0, {r4 - r6}
+ ARM( stmdb r0, {sp, lr}^ )
+ THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
+
+ @
+ @ Enable the alignment trap while in kernel mode
+ @
+ alignment_trap r0
+
+ @
+ @ Clear FP to mark the first stack frame
+ @
+ zero_fp
+
+#ifdef CONFIG_IRQSOFF_TRACER
+ bl trace_hardirqs_off
+#endif
+ .endm
+
+ .macro kuser_cmpxchg_check
+#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#ifndef CONFIG_MMU
+#warning "NPTL on non MMU needs fixing"
+#else
+ @ Make sure our user space atomic helper is restarted
+ @ if it was interrupted in a critical region. Here we
+ @ perform a quick test inline since it should be false
+ @ 99.9999% of the time. The rest is done out of line.
+ cmp r4, #TASK_SIZE
+ blhs kuser_cmpxchg64_fixup
+#endif
+#endif
+ .endm
+
+/*
* These are the registers used in the syscall handler, and allow us to
* have in theory up to 7 arguments to a function - r0 to r6.
*
--
1.7.11.5
^ permalink raw reply related
* [PATCH 12/14] ARM: Add KGDB/KDB FIQ debugger generic code
From: Anton Vorontsov @ 2012-09-10 4:14 UTC (permalink / raw)
To: Andrew Morton, Russell King, Jason Wessel, Greg Kroah-Hartman,
Alan Cox
Cc: Arve Hjønnevåg, Colin Cross, Brian Swetland,
John Stultz, linux-kernel, linux-arm-kernel, linaro-kernel,
patches, kernel-team, kgdb-bugreport, linux-serial
In-Reply-To: <20120910040802.GA1261@lizard>
The FIQ debugger may be used to debug situations when the kernel stuck
in uninterruptable sections, e.g. the kernel infinitely loops or
deadlocked in an interrupt or with interrupts disabled.
By default KGDB FIQ is disabled in runtime, but can be enabled with
kgdb_fiq.enable=1 kernel command line option.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
arch/arm/Kconfig | 18 ++++++++
arch/arm/include/asm/kgdb.h | 8 ++++
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/kgdb_fiq.c | 99 ++++++++++++++++++++++++++++++++++++++++
arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++++++++++++++++
5 files changed, 213 insertions(+)
create mode 100644 arch/arm/kernel/kgdb_fiq.c
create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c5f9ae5..66f4f81 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -171,6 +171,24 @@ config GENERIC_ISA_DMA
config FIQ
bool
+config ARCH_MIGHT_HAVE_KGDB_FIQ
+ bool
+
+config KGDB_FIQ
+ bool "KGDB/KDB FIQ debugger"
+ depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL
+ select FIQ
+ help
+ The FIQ debugger may be used to debug situations when the
+ kernel stuck in uninterruptable sections, e.g. the kernel
+ infinitely loops or deadlocked in an interrupt or with
+ interrupts disabled.
+
+ By default KGDB FIQ is disabled in runtime, but can be
+ enabled with kgdb_fiq.enable=1 kernel command line option.
+
+ If unsure, say N.
+
config NEED_RET_TO_USER
bool
diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h
index 48066ce..807e547 100644
--- a/arch/arm/include/asm/kgdb.h
+++ b/arch/arm/include/asm/kgdb.h
@@ -11,6 +11,8 @@
#define __ARM_KGDB_H__
#include <linux/ptrace.h>
+#include <linux/linkage.h>
+#include <asm/exception.h>
/*
* GDB assumes that we're a user process being debugged, so
@@ -47,6 +49,12 @@ static inline void arch_kgdb_breakpoint(void)
extern void kgdb_handle_bus_error(void);
extern int kgdb_fault_expected;
+extern char kgdb_fiq_handler;
+extern char kgdb_fiq_handler_end;
+asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs);
+extern int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq,
+ void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on),
+ bool (*mach_is_kgdb_fiq)(unsigned int irq));
#endif /* !__ASSEMBLY__ */
/*
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7ad2d5c..5aa079b 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o
obj-$(CONFIG_ARM_UNWIND) += unwind.o
obj-$(CONFIG_HAVE_TCM) += tcm.o
obj-$(CONFIG_OF) += devtree.o
diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c
new file mode 100644
index 0000000..8443af1
--- /dev/null
+++ b/arch/arm/kernel/kgdb_fiq.c
@@ -0,0 +1,99 @@
+/*
+ * KGDB FIQ
+ *
+ * Copyright 2010 Google, Inc.
+ * Arve Hjønnevåg <arve@android.com>
+ * Colin Cross <ccross@android.com>
+ * Copyright 2012 Linaro Ltd.
+ * Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/hardirq.h>
+#include <linux/kdb.h>
+#include <linux/kgdb.h>
+#include <asm/fiq.h>
+#include <asm/exception.h>
+
+static int kgdb_fiq_enabled;
+module_param_named(enable, kgdb_fiq_enabled, int, 0600);
+MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB");
+
+static unsigned int kgdb_fiq;
+static bool (*is_kgdb_fiq)(unsigned int irq);
+
+asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs)
+{
+ if (!is_kgdb_fiq(kgdb_fiq))
+ return;
+ if (!kgdb_nmi_poll_knock())
+ return;
+
+ nmi_enter();
+ kgdb_handle_exception(1, 0, 0, regs);
+ nmi_exit();
+}
+
+static struct fiq_handler kgdb_fiq_desc = {
+ .name = "kgdb",
+};
+
+static long kgdb_fiq_setup_stack(void *info)
+{
+ struct pt_regs regs;
+
+ regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) +
+ THREAD_START_SP;
+ WARN_ON(!regs.ARM_sp);
+
+ set_fiq_regs(®s);
+ return 0;
+}
+
+static void (*kgdb_enable_fiq)(unsigned int irq, bool on);
+
+void kgdb_arch_enable_nmi(bool on)
+{
+ if (!kgdb_enable_fiq)
+ return;
+ kgdb_enable_fiq(kgdb_fiq, on);
+}
+
+int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq,
+ void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on),
+ bool (*mach_is_kgdb_fiq)(unsigned int irq))
+{
+ int err;
+ int cpu;
+
+ if (!kgdb_fiq_enabled)
+ return -ENODEV;
+ if (kgdb_fiq)
+ return -EBUSY;
+
+ kgdb_fiq = mach_kgdb_fiq;
+ kgdb_enable_fiq = mach_kgdb_enable_fiq;
+ is_kgdb_fiq = mach_is_kgdb_fiq;
+
+ err = claim_fiq(&kgdb_fiq_desc);
+ if (err) {
+ pr_warn("%s: unable to claim fiq", __func__);
+ return err;
+ }
+
+ for_each_possible_cpu(cpu)
+ work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL);
+
+ set_fiq_handler(&kgdb_fiq_handler,
+ &kgdb_fiq_handler_end - &kgdb_fiq_handler);
+
+ return 0;
+}
diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S
new file mode 100644
index 0000000..d6becca
--- /dev/null
+++ b/arch/arm/kernel/kgdb_fiq_entry.S
@@ -0,0 +1,87 @@
+/*
+ * KGDB FIQ entry
+ *
+ * Copyright 1996,1997,1998 Russell King.
+ * Copyright 2012 Linaro Ltd.
+ * Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/unwind.h>
+#include "entry-header.S"
+
+ .text
+
+@ This is needed for usr_entry/alignment_trap
+.LCcralign:
+ .long cr_alignment
+.LCdohandle:
+ .long kgdb_fiq_do_handle
+
+ .macro fiq_handler
+ ldr r1, =.LCdohandle
+ mov r0, sp
+ adr lr, BSYM(9997f)
+ ldr pc, [r1]
+9997:
+ .endm
+
+ .align 5
+__fiq_svc:
+ svc_entry
+ fiq_handler
+ mov r0, sp
+ ldmib r0, {r1 - r14}
+ msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT
+ add r8, r0, #S_PC
+ ldr r9, [r0, #S_PSR]
+ msr spsr_cxsf, r9
+ ldr r0, [r0, #S_R0]
+ ldmia r8, {pc}^
+
+ UNWIND(.fnend )
+ENDPROC(__fiq_svc)
+ .ltorg
+
+ .align 5
+__fiq_usr:
+ usr_entry
+ kuser_cmpxchg_check
+ fiq_handler
+ get_thread_info tsk
+ mov why, #0
+ b ret_to_user_from_irq
+ UNWIND(.fnend )
+ENDPROC(__fiq_usr)
+ .ltorg
+
+ .global kgdb_fiq_handler
+kgdb_fiq_handler:
+
+ vector_stub fiq, FIQ_MODE, 4
+
+ .long __fiq_usr @ 0 (USR_26 / USR_32)
+ .long __fiq_svc @ 1 (FIQ_26 / FIQ_32)
+ .long __fiq_svc @ 2 (IRQ_26 / IRQ_32)
+ .long __fiq_svc @ 3 (SVC_26 / SVC_32)
+ .long __fiq_svc @ 4
+ .long __fiq_svc @ 5
+ .long __fiq_svc @ 6
+ .long __fiq_svc @ 7
+ .long __fiq_svc @ 8
+ .long __fiq_svc @ 9
+ .long __fiq_svc @ a
+ .long __fiq_svc @ b
+ .long __fiq_svc @ c
+ .long __fiq_svc @ d
+ .long __fiq_svc @ e
+ .long __fiq_svc @ f
+
+ .global kgdb_fiq_handler_end
+kgdb_fiq_handler_end:
--
1.7.11.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox